Пример #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
 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
        //リソース定義(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));
                }
            }
        }
Пример #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
        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")));
            }
        }