예제 #1
0
        //バイトイメージの取得
        public byte[] GetBytes()
        {
            var buffer = _dnsHeader.GetBytes();

            for (var i = 0; i < 4; i++)
            {
                var a = _ar[i];
                foreach (var o in a)
                {
                    var dataName = (new Compress(buffer, DnsUtil.Str2DnsName(o.Name))).GetData();
                    var data     = o.Data;
                    var dnsType  = o.DnsType;

                    if (i != 0)
                    {
                        //QDでは、data部分は存在しない
                        if (dnsType == DnsType.Ns || dnsType == DnsType.Cname || dnsType == DnsType.Ptr)
                        {
                            data = (new Compress(buffer, o.Data)).GetData(); //圧縮
                        }
                        else if (dnsType == DnsType.Mx)
                        {
                            var preference = Conv.GetUShort(o.Data, 0);
                            var mlServer   = new byte[o.Data.Length - 2];
                            //System.arraycopy(o.Data, 2, mlServer, 0, o.Data.Length - 2);
                            Buffer.BlockCopy(o.Data, 2, mlServer, 0, o.Data.Length - 2);

                            mlServer = (new Compress(buffer, mlServer)).GetData(); //圧縮
                            data     = Bytes.Create(Conv.GetBytes(preference), mlServer);
                        }
                    }
                    //PacketRrは、QD(i==0)の時、data.Length=0となり、内部でisQueryがセットされる
                    var packetRr = new PacketRr(data.Length);
                    try{
                        packetRr.Cls     = 1;
                        packetRr.DnsType = dnsType;
                        packetRr.Ttl     = o.Ttl; //PacketRr.isQueryがセットされているとき、処理なし
                        packetRr.Data    = data;  //PacketRr.isQueryがセットされているとき、処理なし
                    } catch (IOException e) {
                        //設計上の問題
                        Util.RuntimeException(e.Message);
                    }
                    //PacketRr.isQueryがセットされているとき、getBytes()は4バイト(TTL,DLEN,DATAなし)になっている
                    buffer = Bytes.Create(buffer, dataName, packetRr.GetBytes());
                }
            }
            return(buffer);
        }
예제 #2
0
파일: RrSoa.cs 프로젝트: schifflee/bjd5
 public RrSoa(string name, uint ttl, string n1, string n2, uint serial, uint refresh, uint retry, uint expire, uint minimum) : base(name, DnsType.Soa, ttl, Bytes.Create(DnsUtil.Str2DnsName(n1), DnsUtil.Str2DnsName(n2), Conv.GetBytes(serial), Conv.GetBytes(refresh), Conv.GetBytes(retry), Conv.GetBytes(expire), Conv.GetBytes(minimum)))
 {
 }
예제 #3
0
파일: Server.cs 프로젝트: schifflee/bjd5
        protected override void OnSubThread(SockObj sockObj)
        {
            var sockUdp = (SockUdp)sockObj;
            //セッションごとの情報
            //Session session = new Session((SockTcp) sockObj);

            PacketDns rp; //受信パケット

            try {
                //パケットの読込(受信パケットrp)
                var buf = sockUdp.RecvBuf;
                if (buf.Length < 12)
                {
                    return;
                }
                rp = new PacketDns(sockUdp.RecvBuf);
            }
            catch (IOException) {
                //データ解釈に失敗した場合は、処理なし
                Logger.Set(LogKind.Secure, sockUdp, 4, ""); //不正パケットの可能性あり
                return;
            }
            //リクエストのドメイン名を取得する
            var domainName = InitRequestDomain(rp.GetRequestName(), rp.GetDnsType());

            //リクエスト解釈完了
            Logger.Set(LogKind.Normal, sockUdp, 8,
                       string.Format("{0} {1} domain={2}", rp.GetDnsType(), rp.GetRequestName(), domainName)); //Query

            var        aa = false;                                                                             // ドメインオーソリティ(管理ドメインかそうでないか)
            const bool ra = true;                                                                              //再帰可能

            var targetCache = _rootCache;                                                                      //デフォルトはルートキャッシュ

            if (rp.GetDnsType() == DnsType.Ptr)
            {
                if (rp.GetRequestName().ToUpper() == "1.0.0.127.IN-ADDR.ARPA." ||
                    rp.GetRequestName().ToUpper() ==
                    "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA." ||
                    rp.GetRequestName().ToUpper() == "LOCALHOST.")
                {
                    //キャッシュはデフォルトであるルートキャッシュが使用される
                    aa = true;
                    Logger.Set(LogKind.Detail, sockUdp, 9, ""); //"request to a domain under auto (localhost)"
                }
                else
                {
                    foreach (var cache in _cacheList)
                    {
                        if (cache.Find(rp.GetRequestName(), DnsType.Ptr))
                        {
                            targetCache = cache;
                            aa          = true;
                            Logger.Set(LogKind.Detail, sockUdp, 10,
                                       string.Format("Resource={0}", targetCache.GetDomainName()));
                            //"request to a domain under management"
                            break;
                        }
                    }
                }
            }
            else
            {
                //A
                if (rp.GetRequestName().ToUpper() == "LOCALHOST.")
                {
                    //キャッシュはデフォルトであるルートキャッシュが使用される
                    aa = true;
                    Logger.Set(LogKind.Detail, sockUdp, 11, ""); //"request to a domain under auto (localhost)"
                }
                else
                {
                    foreach (var cache in _cacheList)
                    {
                        if (cache.GetDomainName().ToUpper() == domainName.ToUpper())
                        {
                            //大文字で比較される
                            targetCache = cache;
                            aa          = true;
                            Logger.Set(LogKind.Detail, sockUdp, 12, string.Format("Resource={0}", domainName));
                            //"request to a domain under management"
                            break;
                        }
                    }
                }
            }

            //管理するドメインでなく、かつ 再帰要求が無い場合は、処理を終わる
            if (!(aa) && !(rp.GetRd()))
            {
                return;
            }

            //aa ドメインオーソリティ
            //rs 再帰可能
            //rd 再起要求あり

            // (A)「ヘッダ」作成
            const bool qr = true; //応答

            //********************************************************
            //パケットの生成(送信パケットsp)
            //********************************************************
            //Ver6.1.0
again:
            var sp = new PacketDns(rp.GetId(), qr, aa, rp.GetRd(), ra);

            // (B)「質問セクション」の追加
            AppendRr(sp, RrKind.QD, new RrQuery(rp.GetRequestName(), rp.GetDnsType())); //質問フィールドの追加
            if (!aa)
            {
                //ドメインオーソリティ(権威サーバ)で無い場合
                //ルートキャッシュにターゲットのデータが蓄積されるまで、再帰的に検索する
                try {
                    SearchLoop(rp.GetRequestName(), rp.GetDnsType(), sockUdp.RemoteIp);
                }
                catch (IOException) {
                    // ここはどうやって扱えばいいか???
                    //e.printStackTrace();
                }
            }

            // (B)「回答セクション」作成
            var ansList = targetCache.GetList(rp.GetRequestName(), rp.GetDnsType());

            //Ver6.1.0 (リソースに無い場合は、再帰検索に入る)
            if (ansList.Count == 0 && aa && !targetCache.Authority)
            {
                targetCache = _rootCache; //ルートキャッシュに戻す
                aa          = false;
                goto again;
            }

            //Ver5.9.4 Aレコードを検索してCNAMEしか帰らない場合の処理
//            if (ansList.Count == 0 && rp.GetDnsType() == DnsType.A){
//                foreach (RrCname o in targetCache.GetList(rp.GetRequestName(), DnsType.Cname)) {
//                    ansList.Add(o);
//                    var list = targetCache.GetList(o.CName, DnsType.A);
//                    foreach (var l in list){
//                        ansList.Add(l);
//                    }
//                }
//            }

            Logger.Set(LogKind.Detail, sockUdp, 13,
                       string.Format("{0} ansList.Count={1}", rp.GetDnsType(), ansList.Count)); //"Create Response (AN)"
            if (0 < ansList.Count)
            {
                //検索でヒットした場合
                foreach (var oneRr in ansList)
                {
                    AppendRr(sp, RrKind.AN,
                             DnsUtil.CreateRr(rp.GetRequestName(), rp.GetDnsType(), oneRr.Ttl, oneRr.Data));

                    if (rp.GetDnsType() == DnsType.Mx || rp.GetDnsType() == DnsType.Cname ||
                        rp.GetDnsType() == DnsType.Ns)
                    {
                        var targetName = "";
                        if (rp.GetDnsType() == DnsType.Mx)
                        {
                            targetName = ((RrMx)oneRr).MailExchangeHost;
                        }
                        else if (rp.GetDnsType() == DnsType.Ns)
                        {
                            targetName = ((RrNs)oneRr).NsName;
                        }
                        else if (rp.GetDnsType() == DnsType.Cname)
                        {
                            targetName = ((RrCname)oneRr).CName;
                        }
                        else
                        {
                            Util.RuntimeException("not implement [Server.onSubThread()]");
                        }

                        //追加情報が必要な場合 (Aレコード)をパケットに追加する
                        var rr = targetCache.GetList(targetName, DnsType.A);
                        foreach (OneRr r in rr)
                        {
                            AppendRr(sp, RrKind.AR, new RrA(targetName, r.Ttl, r.Data));
                        }

                        //追加情報が必要な場合 (AAAAレコード)をパケットに追加する
                        rr = targetCache.GetList(targetName, DnsType.Aaaa);
                        foreach (var r in rr)
                        {
                            AppendRr(sp, RrKind.AR, new RrAaaa(targetName, r.Ttl, r.Data));
                        }
                    }
                }
            }
            else
            {
                //検索でヒットしない場合
                if (rp.GetDnsType() == DnsType.A)
                {
                    // CNAMEに定義されていないかどうかを確認する
                    //Ver5.9.4 再帰的にCNAMEを検索する
                    //var cnameList = targetCache.GetList(rp.GetRequestName(), DnsType.Cname);

                    var cnameList = new List <OneRr>();
                    cnameList = GetAllCname(targetCache, rp.GetRequestName(), cnameList);

                    foreach (var o in cnameList)
                    {
                        Logger.Set(LogKind.Detail, sockUdp, 16, o.ToString()); //"Append RR"
                        AppendRr(sp, RrKind.AN, o);

                        var cname = ((RrCname)o).CName;
                        var aList = targetCache.GetList(cname, DnsType.A);
                        foreach (var a in aList)
                        {
//                            Logger.Set(LogKind.Detail, sockUdp, 16, o.ToString()); //"Append RR"
//                            AppendRr(sp, RrKind.AN, o);
                            Logger.Set(LogKind.Detail, sockUdp, 16, a.ToString()); //"Append RR"
                            AppendRr(sp, RrKind.AN, a);
                        }
                    }
                }
            }

            if (rp.GetDnsType() == DnsType.A || rp.GetDnsType() == DnsType.Aaaa || rp.GetDnsType() == DnsType.Soa ||
                rp.GetDnsType() == DnsType.Cname)
            {
                // (C)「権威セクション」「追加情報セクション」作成
                var nsList = targetCache.GetList(domainName, DnsType.Ns);
                Logger.Set(LogKind.Detail, sockUdp, 22, string.Format("{0} nsList.Count={1}", DnsType.Ns, nsList.Count));
                // Create Response (AR)
                foreach (var o in nsList)
                {
                    var ns = (RrNs)o;

                    AppendRr(sp, RrKind.NS, new RrNs(ns.Name, ns.Ttl, ns.Data));

                    if (domainName.ToUpper() != "LOCALHOST.")
                    {
                        //localhost検索の場合は、追加情報はない
                        //「追加情報」
                        var addList = targetCache.GetList(ns.NsName, DnsType.A);
                        foreach (OneRr rr in addList)
                        {
                            AppendRr(sp, RrKind.AR, new RrA(ns.NsName, rr.Ttl, rr.Data));
                        }
                        addList = targetCache.GetList(ns.NsName, DnsType.Aaaa);
                        foreach (OneRr rr in addList)
                        {
                            AppendRr(sp, RrKind.AR, new RrAaaa(ns.NsName, rr.Ttl, rr.Data));
                        }
                    }
                }
            }

            sockUdp.Send(sp.GetBytes()); //送信
            //sockUdp.Close();UDPソケット(sockUdp)はクローンなのでクローズしても、処理されない※Close()を呼び出しても問題はない
            sockUdp.Close();
        }
예제 #4
0
 public RrMx(string name, uint ttl, ushort preference, string mailExchangerHost) : base(name, DnsType.Mx, ttl, Bytes.Create(Conv.GetBytes(preference), DnsUtil.Str2DnsName(mailExchangerHost)))
 {
 }
예제 #5
0
        //リソース定義(Dat)で初期化する場合
        public DnsCache(Logger logger, OneOption oneOption, Dat dat, string dName)
        {
            const uint ttl = 0;  //有効期限なし
            var        ns  = ""; //SOA追加時に使用するため、NSレコードを見つけたときにサーバ名を保存しておく

            //オプションを読み込んで、ローカルデータを初期化する
            //this.oneOption = oneOption;
            _soaExpire = (uint)(int)oneOption.GetValue("soaExpire");

            DomainName = dName;

            foreach (var o in dat)
            {
                if (o.Enable)
                {
                    var type  = Convert.ToInt32(o.StrList[0]);
                    var name  = o.StrList[1];
                    var alias = o.StrList[2];
                    var ip    = new Ip(o.StrList[3]);
                    var n     = Convert.ToInt32(o.StrList[4]);

                    var dnsType = DnsType.A;
                    if (type == 1)
                    {
                        dnsType = DnsType.Ns;
                    }
                    else if (type == 2)
                    {
                        dnsType = DnsType.Mx;
                    }
                    else if (type == 3)
                    {
                        dnsType = DnsType.Cname;
                    }
                    else if (type == 4)
                    {
                        dnsType = DnsType.Aaaa;
                    }
                    var priority = (ushort)n;
                    //uint addr = ip.AddrV4;        //class Ip -> uint;

                    //最後に.がついていない場合、ドメイン名を追加する
                    if (name.LastIndexOf('.') != name.Length - 1)
                    {
                        name = name + "." + DomainName;
                    }
                    if (alias.LastIndexOf('.') != alias.Length - 1)
                    {
                        alias = alias + "." + DomainName;
                    }

                    //CNAME以外は、PTRレコードを自動的に生成する
                    if (dnsType != DnsType.Cname)
                    {
                        //PTR名を作成 [例] 192.168.0.1 -> 1.0.168.192.in-addr.arpa;
                        if (ip.InetKind == InetKind.V4)   //IPv4
                        {
                            string ptrName = string.Format("{0}.{1}.{2}.{3}.in-addr.arpa.", ip.IpV4[3], ip.IpV4[2], ip.IpV4[1], ip.IpV4[0]);
                            Add(new OneRR(ptrName, DnsType.Ptr, ttl, DnsUtil.Str2DnsName(name)));
                        }
                        else     //IPv6
                        {
                            var sb = new StringBuilder();
                            foreach (var a in ip.IpV6)
                            {
                                sb.Append(string.Format("{0:x4}", a));
                            }
                            string ipStr = sb.ToString();
                            if (ipStr.Length == 32)
                            {
                                sb = new StringBuilder();
                                for (int e = 31; e >= 0; e--)
                                {
                                    sb.Append(ipStr[e]);
                                    sb.Append('.');
                                }
                                Add(new OneRR(sb + "ip6.arpa.", DnsType.Ptr, ttl, DnsUtil.Str2DnsName(name)));
                            }
                        }
                    }

                    //データベースへの追加
                    if (dnsType == DnsType.A)
                    {
                        if (ip.InetKind == InetKind.V4)
                        {
                            //ネットワークバイト配列の取得
                            Add(new OneRR(name, DnsType.A, ttl, ip.NetBytes()));
                        }
                        else
                        {
                            logger.Set(LogKind.Error, null, 19, string.Format("address {0}", ip));
                        }
                    }
                    else if (dnsType == DnsType.Aaaa)
                    {
                        if (ip.InetKind == InetKind.V6)
                        {
                            Add(new OneRR(name, DnsType.Aaaa, ttl, ip.NetBytes()));
                        }
                        else
                        {
                            logger.Set(LogKind.Error, null, 20, string.Format("address {0}", ip));
                        }
                    }
                    else if (dnsType == DnsType.Ns)
                    {
                        ns = name;//SOA追加時に使用するため、ネームサーバの名前を保存する

                        // A or AAAAレコードも追加
                        Add(new OneRR(name, (ip.InetKind == InetKind.V4) ? DnsType.A : DnsType.Aaaa, ttl, ip.NetBytes()));

                        Add(new OneRR(DomainName, DnsType.Ns, ttl, DnsUtil.Str2DnsName(name)));
                    }
                    else if (dnsType == DnsType.Mx)
                    {
                        // A or AAAAレコードも追加
                        Add(new OneRR(name, DnsType.A, ttl, ip.NetBytes()));

                        //プライオリィ
                        byte[] dataName = DnsUtil.Str2DnsName(name);//DNS名前形式に変換
                        byte[] data     = Bytes.Create(Util.htons(priority), dataName);
                        Add(new OneRR(DomainName, DnsType.Mx, ttl, data));
                    }
                    else if (dnsType == DnsType.Cname)
                    {
                        Add(new OneRR(alias, DnsType.Cname, ttl, DnsUtil.Str2DnsName(name)));
                    }
                }

                //SOAレコードの追加
                if (ns != "")   //NSサーバ名が必須
                {
                    var soaMail = (string)oneOption.GetValue("soaMail");
                    soaMail.Replace('@', '.'); //@を.に置き換える
                    soaMail = soaMail + ".";   //最後に.を追加する
                    var soaSerial  = (uint)(int)oneOption.GetValue("soaSerial");
                    var soaRefresh = (uint)(int)oneOption.GetValue("soaRefresh");
                    var soaRetry   = (uint)(int)oneOption.GetValue("soaRetry");
                    var soaExpire  = (uint)(int)oneOption.GetValue("soaExpire");
                    var soaMinimum = (uint)(int)oneOption.GetValue("soaMinimum");

                    byte[] data = Bytes.Create(
                        DnsUtil.Str2DnsName(ns),
                        DnsUtil.Str2DnsName(soaMail),
                        Util.htonl(soaSerial),
                        Util.htonl(soaRefresh),
                        Util.htonl(soaRetry),
                        Util.htonl(soaExpire),
                        Util.htonl(soaMinimum));

                    Add(new OneRR(DomainName, DnsType.Soa, ttl, data));
                }
            }
        }
예제 #6
0
        readonly uint _soaExpire;//終了時間(オプションで指定された有効時間)

        //named.caで初期化する場合
        //public DnsCache(Logger logger, OneOption oneOption, string fileName) {
        public DnsCache(OneOption oneOption, string fileName)
        {
            uint ttl = 0;//rootCacheは有効期限なし

            //オプションを読み込んで、ローカルデータを初期化する
            //this.oneOption = oneOption;
            _soaExpire = (uint)(int)oneOption.GetValue("soaExpire");

            DomainName = ".";
            //this.defaultExpire = defaultExpire;
            if (File.Exists(fileName))
            {
                using (var sr = new StreamReader(fileName, Encoding.GetEncoding("Shift_JIS"))) {
                    var tmpName = "";//全行のNAMEを保持する NAMEは前行と同じ場合省略が可能

                    while (true)
                    {
                        var name = "";
                        //string Class = "IN";
                        var dnsType = DnsType.Unknown;

                        var str = sr.ReadLine();
                        if (str == null)
                        {
                            break;
                        }
                        //;以降はコメントとして削除する
                        var i = str.IndexOf(';');
                        if (i != -1)
                        {
                            str = str.Substring(0, i);
                        }

                        //空の行は処理しない
                        if (str.Length == 0)
                        {
                            continue;
                        }

                        //空白・タブを削除して、パラメータをtmp2へ取得する
                        var tmp  = str.Split(new[] { ' ', '\t' });
                        var tmp2 = tmp.Where(s => s != "").ToList();

                        //************************************************
                        //タイプだけは省略することができないので、それを基準にサーチする
                        //************************************************
                        var typeCol = 0;
                        for (; typeCol < tmp2.Count; typeCol++)
                        {
                            foreach (DnsType t in Enum.GetValues(typeof(DnsType)))
                            {
                                if (tmp2[typeCol] != t.ToString().ToUpper())
                                {
                                    continue;
                                }
                                dnsType = t;
                                break;
                            }
                            if (dnsType != DnsType.Unknown)
                            {
                                break;
                            }
                        }
                        if (dnsType == DnsType.Unknown)
                        {
                            goto err;//タイプが見つからない場合は、無効行とする
                        }
                        //タイプの次がDATAとなる
                        if (typeCol + 1 >= tmp2.Count)
                        {
                            goto err; //タイプの次にカラム(DATA)が存在しない
                        }
                        string dataStr = tmp2[typeCol + 1];

                        //************************************************
                        //クラス(IN)が含まれているかどうかをサーチする
                        //************************************************
                        var classCol = 0;
                        for (; classCol < tmp2.Count; classCol++)
                        {
                            if (tmp2[classCol] != "IN")
                            {
                                continue;
                            }
                            goto find;
                        }
                        classCol = -1;
find:
                        //クラスが含まれた場合、そのカラムはclassColに保存されている
                        //含まれていない場合 classCol=-1

                        if (typeCol == 1)
                        {
                            if (classCol == -1)   //INが無い場合
                            //0番目はNAME若しくはTTLとなる
                            {
                                if (str.Substring(0, 1) == " " || str.Substring(0, 1) == "\t")
                                {
                                    //名前は省略されているので
                                    ttl = Convert.ToUInt32(tmp2[0]);
                                    ttl = Util.htonl(ttl);
                                }
                                else
                                {
                                    name = tmp2[0];
                                }
                            }
                            else     //INが有る場合
                            {
                                if (classCol != 0)
                                {
                                    goto err;//位置がおかしい
                                }
                                //0番目はINであるので、名前もTTLも省略されている
                            }
                        }
                        else if (typeCol == 2)
                        {
                            if (classCol == -1)   //INが無い場合
                            //0番目はNAME、1番目はTTLとなる
                            {
                                name = tmp2[0];
                                ttl  = Convert.ToUInt32(tmp2[1]);
                                ttl  = Util.htonl(ttl);
                            }
                            else     //INが有る場合
                            {
                                if (classCol != 1)
                                {
                                    goto err;//位置がおかしい
                                }
                                //0番目はNAME若しくはTTLとなる
                                if (str.Substring(0, 1) == " " || str.Substring(0, 1) == "\t")
                                {
                                    //名前は省略されているので
                                    ttl = Convert.ToUInt32(tmp2[0]);
                                    ttl = Util.htonl(ttl);
                                }
                                else
                                {
                                    name = tmp2[0];
                                }
                            }
                        }
                        else if (typeCol == 3)
                        {
                            if (classCol == -1)   //INが無い場合
                            //カラム不足
                            {
                                goto err;
                            }
                            //INが有る場合
                            if (classCol != 2)
                            {
                                goto err;//位置がおかしい
                            }
                            //0番目はNAME、1番目はTTLとなる
                            name = tmp2[0];
                            ttl  = Convert.ToUInt32(tmp2[1]);
                            ttl  = Util.htonl(ttl);
                        }

                        //*********************************************
                        //nameの補完
                        //*********************************************
                        if (name == "@")   //@の場合
                        {
                            name = DomainName;
                        }
                        else if (name.LastIndexOf('.') != name.Length - 1)     //最後に.がついていない場合、ドメイン名を追加する
                        {
                            name = name + "." + DomainName + ".";
                        }
                        else if (name == "")
                        {
                            name = tmpName; //前行と同じ
                        }
                        tmpName = name;     //前行分として記憶する

                        //*********************************************
                        //string sataStr を変換してデータベースに追加
                        //*********************************************
                        if (dnsType == DnsType.A)
                        {
                            var ipV4 = new Ip(dataStr);
                            Add(new OneRR(name, dnsType, ttl, ipV4.NetBytes()));
                        }
                        else if (dnsType == DnsType.Ns)
                        {
                            Add(new OneRR(name, dnsType, ttl, DnsUtil.Str2DnsName(dataStr)));
                        }
                        else if (dnsType == DnsType.Aaaa)
                        {
                            var ipV6 = new Ip(dataStr);
                            Add(new OneRR(name, dnsType, ttl, ipV6.NetBytes()));
                        }
                        else
                        {
                            Msg.Show(MsgKind.Error, "name.caには、タイプA,AAAA及びNS以外は使用できません。");
                            goto err;
                        }
                        continue;
err:                    //行に矛盾が有る
                        Msg.Show(MsgKind.Error, string.Format("ServerDnsCache() レコード読み込みエラー 矛盾があります。[ {0} {1} ]", fileName, str));
                    }
                    sr.Close();
                }
            }
            //locaohostレコードの追加
            {
                var ip = new Ip("127.0.0.1");
                Add(new OneRR("localhost.", DnsType.A, ttl, ip.NetBytes()));
                Add(new OneRR("1.0.0.127.in-addr.arpa.", DnsType.Ptr, ttl, DnsUtil.Str2DnsName("localhost")));

                ip = new Ip("::1");
                Add(new OneRR("localhost.", DnsType.Aaaa, ttl, ip.NetBytes()));
                Add(new OneRR("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA.", DnsType.Ptr, ttl, DnsUtil.Str2DnsName("localhost")));
            }
        }