public void パケット生成_MX() { //setUp //exercise //パケットの生成 const ushort id = (ushort) 0xf00f; const bool qr = true; //応答 const bool rd = false; //再帰要求(有効) const bool aa = true; //権限(あり) const bool ra = true; var sut = new PacketDns(id, qr, aa, rd, ra); sut.AddRr(RrKind.QD, new RrQuery("google.com.", DnsType.Mx)); sut.AddRr(RrKind.AN, new RrMx("google.com.", 0xa7d, 10, "smtp.google.com.")); sut.AddRr(RrKind.NS, new RrNs("google.com.", 0xa7d, "ns3.google.com.")); //生成したパケットのバイト配列で、再度パケットクラスを生成する byte[] b = sut.GetBytes(); var p = new PacketDns(b); //verify Assert.That(p.GetAa(), Is.EqualTo(true)); Assert.That(p.GetId(), Is.EqualTo((ushort) 0xf00f)); Assert.That(p.GetDnsType(), Is.EqualTo(DnsType.Mx)); Assert.That(p.GetCount(RrKind.QD), Is.EqualTo(1)); Assert.That(p.GetCount(RrKind.AN), Is.EqualTo(1)); Assert.That(p.GetCount(RrKind.NS), Is.EqualTo(1)); Assert.That(p.GetCount(RrKind.AR), Is.EqualTo(0)); Assert.That(p.GetRcode(), Is.EqualTo((short) 0)); //DEBUG //OneRr r = p.GetRr(RrKind.AN, 0); Assert.That(p.GetRr(RrKind.AN, 0).ToString(), Is.EqualTo(new RrMx("google.com.", 0xa7d, 10, "smtp.google.com.").ToString())); Assert.That(p.GetRr(RrKind.NS, 0).ToString(), Is.EqualTo(new RrNs("google.com.", 0xa7d, "ns3.google.com.").ToString())); // Assert.That(p.GetRr(RrKind.NS, 1).ToString(), Is.EqualTo(new RrNs("google.com.", 0xa7d, "ns1.google.com.").ToString())); // Assert.That(p.GetRr(RrKind.NS, 2).ToString(), Is.EqualTo(new RrNs("google.com.", 0xa7d, "ns4.google.com.").ToString())); // Assert.That(p.GetRr(RrKind.NS, 3).ToString(), Is.EqualTo(new RrNs("google.com.", 0xa7d, "ns2.google.com.").ToString())); // // Assert.That(p.GetRr(RrKind.AR, 0).ToString(), Is.EqualTo(new RrA("ns1.google.com.", 0xb5e, new Ip("216.239.32.10")).ToString())); // Assert.That(p.GetRr(RrKind.AR, 1).ToString(), Is.EqualTo(new RrA("ns2.google.com.", 0xbde, new Ip("216.239.34.10")).ToString())); // Assert.That(p.GetRr(RrKind.AR, 2).ToString(), Is.EqualTo(new RrA("ns3.google.com.", 0xaf5, new Ip("216.239.36.10")).ToString())); // Assert.That(p.GetRr(RrKind.AR, 3).ToString(), Is.EqualTo(new RrA("ns4.google.com.", 0xab3, new Ip("216.239.38.10")).ToString())); }
public void パケット生成_A_NS() { //setUp //exercise //パケットの生成 const ushort id = 0x0005; const bool qr = true; //応答 const bool rd = true; //再帰要求(有効) const bool aa = false; //権限(なし) const bool ra = true; var sut = new PacketDns(id, qr, aa, rd, ra); sut.AddRr(RrKind.QD, new RrQuery("www.google.com.", DnsType.Aaaa)); sut.AddRr(RrKind.NS, new RrNs("google.com.", 0xa7d, "ns3.google.com.")); sut.AddRr(RrKind.NS, new RrNs("google.com.", 0xa7d, "ns1.google.com.")); sut.AddRr(RrKind.NS, new RrNs("google.com.", 0xa7d, "ns4.google.com.")); sut.AddRr(RrKind.NS, new RrNs("google.com.", 0xa7d, "ns2.google.com.")); sut.AddRr(RrKind.AR, new RrA("ns1.google.com.", 0xb5e, new Ip("216.239.32.10"))); sut.AddRr(RrKind.AR, new RrA("ns2.google.com.", 0xbde, new Ip("216.239.34.10"))); sut.AddRr(RrKind.AR, new RrA("ns3.google.com.", 0xaf5, new Ip("216.239.36.10"))); sut.AddRr(RrKind.AR, new RrA("ns4.google.com.", 0xab3, new Ip("216.239.38.10"))); //生成したパケットのバイト配列で、再度パケットクラスを生成する var p = new PacketDns(sut.GetBytes()); //verify Assert.That(p.GetAa(), Is.EqualTo(false)); Assert.That(p.GetId(), Is.EqualTo((short) 0x0005)); Assert.That(p.GetDnsType(), Is.EqualTo(DnsType.Aaaa)); Assert.That(p.GetCount(RrKind.QD), Is.EqualTo(1)); Assert.That(p.GetCount(RrKind.AN), Is.EqualTo(0)); Assert.That(p.GetCount(RrKind.NS), Is.EqualTo(4)); Assert.That(p.GetCount(RrKind.AR), Is.EqualTo(4)); Assert.That(p.GetRcode(), Is.EqualTo((short) 0)); Assert.That(p.GetRr(RrKind.NS, 0).ToString(), Is.EqualTo(new RrNs("google.com.", 0xa7d, "ns3.google.com.").ToString())); Assert.That(p.GetRr(RrKind.NS, 1).ToString(), Is.EqualTo(new RrNs("google.com.", 0xa7d, "ns1.google.com.").ToString())); Assert.That(p.GetRr(RrKind.NS, 2).ToString(), Is.EqualTo(new RrNs("google.com.", 0xa7d, "ns4.google.com.").ToString())); Assert.That(p.GetRr(RrKind.NS, 3).ToString(), Is.EqualTo(new RrNs("google.com.", 0xa7d, "ns2.google.com.").ToString())); Assert.That(p.GetRr(RrKind.AR, 0).ToString(), Is.EqualTo(new RrA("ns1.google.com.", 0xb5e, new Ip("216.239.32.10")).ToString())); Assert.That(p.GetRr(RrKind.AR, 1).ToString(), Is.EqualTo(new RrA("ns2.google.com.", 0xbde, new Ip("216.239.34.10")).ToString())); Assert.That(p.GetRr(RrKind.AR, 2).ToString(), Is.EqualTo(new RrA("ns3.google.com.", 0xaf5, new Ip("216.239.36.10")).ToString())); Assert.That(p.GetRr(RrKind.AR, 3).ToString(), Is.EqualTo(new RrA("ns4.google.com.", 0xab3, new Ip("216.239.38.10")).ToString())); }
public void パケット解釈_str2() { //exercise var sut = new PacketDns(TestUtil.HexStream2Bytes(Str2)); //verify Assert.That(sut.GetId(), Is.EqualTo((short) 0x0004)); Assert.That(sut.GetCount(RrKind.QD), Is.EqualTo(1)); Assert.That(sut.GetCount(RrKind.AN), Is.EqualTo(1)); Assert.That(sut.GetCount(RrKind.NS), Is.EqualTo(2)); Assert.That(sut.GetCount(RrKind.AR), Is.EqualTo(2)); Assert.That(sut.GetRcode(), Is.EqualTo((short) 0)); Assert.That(sut.GetAa(), Is.EqualTo(false)); Assert.That(sut.GetRd(), Is.EqualTo(true)); Assert.That(sut.GetDnsType(), Is.EqualTo(DnsType.Soa)); Assert.That(sut.GetRequestName(), Is.EqualTo("nifty.com.")); Assert.That(sut.GetRr(RrKind.QD, 0).ToString(), Is.EqualTo((new RrQuery("nifty.com.", DnsType.Soa)).ToString())); Assert.That(sut.GetRr(RrKind.AN, 0).ToString(), Is.EqualTo((new RrSoa("nifty.com.", 0x616, "ons0.nifty.ad.jp", "hostmaster.nifty.ad.jp", 0x0bfe4128, 0xe10, 0x384, 0x36ee80, 0x384)).ToString())); Assert.That(sut.GetRr(RrKind.NS, 0).ToString(), Is.EqualTo((new RrNs("nifty.com.", 0x6d2, "ons0.nifty.ad.jp.")).ToString())); Assert.That(sut.GetRr(RrKind.NS, 1).ToString(), Is.EqualTo((new RrNs("nifty.com.", 0x6d2, "ons1.nifty.ad.jp.")).ToString())); Assert.That(sut.GetRr(RrKind.AR, 0).ToString(), Is.EqualTo((new RrA("ons0.nifty.ad.jp.", 0x712, new Ip("202.248.37.77"))).ToString())); Assert.That(sut.GetRr(RrKind.AR, 1).ToString(), Is.EqualTo((new RrA("ons1.nifty.ad.jp.", 0x6da, new Ip("202.248.20.156"))).ToString())); }
public void パケット解釈_str0() { //exercise var sut = new PacketDns(TestUtil.HexStream2Bytes(Str0)); //verify Assert.That(sut.GetId(), Is.EqualTo((short) 0x0003)); Assert.That(sut.GetCount(RrKind.QD), Is.EqualTo(1)); Assert.That(sut.GetCount(RrKind.AN), Is.EqualTo(0)); Assert.That(sut.GetCount(RrKind.NS), Is.EqualTo(4)); Assert.That(sut.GetCount(RrKind.AR), Is.EqualTo(4)); Assert.That(sut.GetRcode(), Is.EqualTo((short) 0)); Assert.That(sut.GetAa(), Is.EqualTo(false)); Assert.That(sut.GetRd(), Is.EqualTo(true)); Assert.That(sut.GetDnsType(), Is.EqualTo(DnsType.Aaaa)); Assert.That(sut.GetRequestName(), Is.EqualTo("www.google.com.")); Assert.That(sut.GetRr(RrKind.QD, 0).ToString(), Is.EqualTo((new RrQuery("www.google.com.", DnsType.Aaaa)).ToString())); Assert.That(sut.GetRr(RrKind.NS, 0).ToString(), Is.EqualTo((new RrNs("google.com.", 83400, "ns4.google.com.")).ToString())); Assert.That(sut.GetRr(RrKind.NS, 1).ToString(), Is.EqualTo((new RrNs("google.com.", 83400, "ns2.google.com.")).ToString())); Assert.That(sut.GetRr(RrKind.NS, 2).ToString(), Is.EqualTo((new RrNs("google.com.", 83400, "ns3.google.com.")).ToString())); Assert.That(sut.GetRr(RrKind.NS, 3).ToString(), Is.EqualTo((new RrNs("google.com.", 83400, "ns1.google.com.")).ToString())); Assert.That(sut.GetRr(RrKind.AR, 0).ToString(), Is.EqualTo((new RrA("ns1.google.com.", 83465, new Ip("216.239.32.10"))).ToString())); Assert.That(sut.GetRr(RrKind.AR, 1).ToString(), Is.EqualTo((new RrA("ns2.google.com.", 83563, new Ip("216.239.34.10"))).ToString())); Assert.That(sut.GetRr(RrKind.AR, 2).ToString(), Is.EqualTo((new RrA("ns3.google.com.", 83465, new Ip("216.239.36.10"))).ToString())); Assert.That(sut.GetRr(RrKind.AR, 3).ToString(), Is.EqualTo((new RrA("ns4.google.com.", 83465, new Ip("216.239.38.10"))).ToString())); }
public void パケット解釈_str1() { //exercise var sut = new PacketDns(TestUtil.HexStream2Bytes(Str1)); //verify Assert.That(sut.GetId(), Is.EqualTo((short) 0x0002)); Assert.That(sut.GetCount(RrKind.QD), Is.EqualTo(1)); Assert.That(sut.GetCount(RrKind.AN), Is.EqualTo(5)); Assert.That(sut.GetCount(RrKind.NS), Is.EqualTo(4)); Assert.That(sut.GetCount(RrKind.AR), Is.EqualTo(7)); Assert.That(sut.GetRcode(), Is.EqualTo((short) 0)); Assert.That(sut.GetAa(), Is.EqualTo(false)); Assert.That(sut.GetRd(), Is.EqualTo(true)); Assert.That(sut.GetDnsType(), Is.EqualTo(DnsType.Mx)); Assert.That(sut.GetRequestName(), Is.EqualTo("gmail.com.")); Assert.That(sut.GetRr(RrKind.QD, 0).ToString(), Is.EqualTo((new RrQuery("gmail.com.", DnsType.Mx)).ToString())); Assert.That(sut.GetRr(RrKind.AN, 0).ToString(), Is.EqualTo((new RrMx("gmail.com.", 3427, 10, "alt1.gmail-smtp-in.l.google.com.")).ToString())); Assert.That(sut.GetRr(RrKind.AN, 1).ToString(), Is.EqualTo((new RrMx("gmail.com.", 3427, 20, "alt2.gmail-smtp-in.l.google.com.")).ToString())); Assert.That(sut.GetRr(RrKind.AN, 2).ToString(), Is.EqualTo((new RrMx("gmail.com.", 3427, 30, "alt3.gmail-smtp-in.l.google.com.")).ToString())); Assert.That(sut.GetRr(RrKind.AN, 3).ToString(), Is.EqualTo((new RrMx("gmail.com.", 3427, 40, "alt4.gmail-smtp-in.l.google.com.")).ToString())); Assert.That(sut.GetRr(RrKind.AN, 4).ToString(), Is.EqualTo((new RrMx("gmail.com.", 3427, 5, "gmail-smtp-in.l.google.com.")).ToString())); Assert.That(sut.GetRr(RrKind.NS, 0).ToString(), Is.EqualTo((new RrNs("gmail.com.", 54413, "ns4.google.com.")).ToString())); Assert.That(sut.GetRr(RrKind.NS, 1).ToString(), Is.EqualTo((new RrNs("gmail.com.", 54413, "ns2.google.com.")).ToString())); Assert.That(sut.GetRr(RrKind.NS, 2).ToString(), Is.EqualTo((new RrNs("gmail.com.", 54413, "ns1.google.com.")).ToString())); Assert.That(sut.GetRr(RrKind.NS, 3).ToString(), Is.EqualTo((new RrNs("gmail.com.", 54413, "ns3.google.com.")).ToString())); Assert.That(sut.GetRr(RrKind.AR, 0).ToString(), Is.EqualTo((new RrA("gmail-smtp-in.l.google.com.", 295, new Ip("74.125.25.27"))).ToString())); Assert.That(sut.GetRr(RrKind.AR, 1).ToString(), Is.EqualTo((new RrA("alt2.gmail-smtp-in.l.google.com.", 60, new Ip("74.125.140.27"))).ToString())); Assert.That(sut.GetRr(RrKind.AR, 2).ToString(), Is.EqualTo((new RrA("alt4.gmail-smtp-in.l.google.com.", 149, new Ip("74.125.131.27"))).ToString())); Assert.That(sut.GetRr(RrKind.AR, 3).ToString(), Is.EqualTo((new RrA("ns1.google.com.", 54584, new Ip("216.239.32.10"))).ToString())); Assert.That(sut.GetRr(RrKind.AR, 4).ToString(), Is.EqualTo((new RrA("ns2.google.com.", 54578, new Ip("216.239.34.10"))).ToString())); Assert.That(sut.GetRr(RrKind.AR, 5).ToString(), Is.EqualTo((new RrA("ns3.google.com.", 54641, new Ip("216.239.36.10"))).ToString())); Assert.That(sut.GetRr(RrKind.AR, 6).ToString(), Is.EqualTo((new RrA("ns4.google.com.", 54520, new Ip("216.239.38.10"))).ToString())); }
// 共通メソッド // リクエスト送信して、サーバから返ったデータをDNSパケットとしてデコードする // レスポンスが無い場合は、1秒でタイムアウトしてnullを返す // rd = 再帰要求 private PacketDns lookup(DnsType dnsType, string name,bool rd=false) { //乱数で識別子生成 var id = (ushort) (new Random()).Next(100); //送信パケット生成 var sp = new PacketDns(id, false, false, rd, false); //質問フィールド追加 sp.AddRr(RrKind.QD, new RrQuery(name, dnsType)); //クライアントソケット生成、及び送信 var cl = new SockUdp(new Kernel(), new Ip(IpKind.V4Localhost), 53, null, sp.GetBytes()); //受信 //byte[] recvBuf = cl.Recv(1000); var recvBuf = cl.Recv(3); if (recvBuf.Length == 0){ //受信データが無い場合 return null; } //System.out.println(string.Format("lookup(%s,\"%s\") recv().Length=%d", dnsType, name, recvBuf.Length)); //デコード var p = new PacketDns(recvBuf); //System.out.println(print(p)); return p; }
// 共通メソッド //リソースレコードのToString() private string Print(PacketDns p, RrKind rrKind, int n) { var o = p.GetRr(rrKind, n); if (rrKind == RrKind.QD){ return o.ToString(); } return Print(o); }
//addrは通常オーダで指定されている //private PacketDns Lookup(Ip ip, string requestName, DNS_TYPE dnsType,RemoteInfo remoteInfo) { private PacketDns Lookup(Ip ip, string requestName, DnsType dnsType, Ip remoteAddr) { //Ip ip = new Ip(addr); Logger.Set(LogKind.Detail, null, 17, string.Format("{0} Server={1} Type={2}", requestName, ip, dnsType)); //"Lookup" //受信タイムアウト const int timeout = 3; // var random = new Random(Environment.TickCount); // var id = (ushort) random.Next(0xFFFF);//識別子をランダムに決定する var random = new Random(); var id = (ushort) random.Next(0xFFFF); const bool qr = false; //要求 const bool aa = false; //権威なし var rd = (bool) Conf.Get("useRD"); //再帰要求を使用するかどうか const bool ra = false; //再帰無効 //リクエストパケットの生成 var sp = new PacketDns(id, qr, aa, rd, ra); AppendRr(sp, RrKind.QD, new RrQuery(requestName, dnsType)); //QR(質問)フィールド追加 const int port = 53; //SockUdp sockUdp = new UdpObj(Kernel, getLogger(), ip, port); byte[] sendBuf = sp.GetBytes(); var sockUdp = new SockUdp(_kernel, ip, port, null, sendBuf); //送信 //この辺のロジックを動作確認する必要がある byte[] recvBuf = sockUdp.Recv(timeout); if (recvBuf != null && 12 <= recvBuf.Length) { //受信 try { var rp = new PacketDns(recvBuf); var str = string.Format("{0} count[{1},{2},{3},{4}] rcode={5} AA={6}", requestName, rp.GetCount(RrKind.QD), rp.GetCount(RrKind.AN), rp.GetCount(RrKind.NS), rp.GetCount(RrKind.AR), rp.GetRcode(), rp.GetAa()); Logger.Set(LogKind.Detail, sockUdp, 18, str); //"Lookup" //質問フィールの以外のリソースデータをキャッシュする //for (int rr = 1; rr < 4; rr++) { foreach (RrKind rr in Enum.GetValues(typeof (RrKind))) { if (rr == RrKind.QD) { continue; //質問フィールの以外のリソースデータをキャッシュする } var m = rp.GetCount(rr); for (var n = 0; n < m; n++) { var oneRr = rp.GetRr(rr, n); _rootCache.Add(oneRr); Logger.Set(LogKind.Detail, sockUdp, 24, string.Format("{0} _rootCache.Count={1}", oneRr, _rootCache.Count)); //_rootCache.Add } } return rp; } catch (IOException) { //ここでのエラーログも必要? return null; } } Logger.Set(LogKind.Error, sockUdp, 5, string.Format("addr={0} requestName={1} dnsType={2}", remoteAddr, requestName, dnsType)); //Lookup() パケット受信でタイムアウトが発生しました。 return null; }
//共通メソッド //リソースレコードの数を表示する private static string Print(PacketDns p) { return string.Format("QD={0} AN={1} NS={2} AR={3}", p.GetCount(RrKind.QD), p.GetCount(RrKind.AN), p.GetCount(RrKind.NS), p.GetCount(RrKind.AR)); }
//レスポンス情報追加をまとめて記述 private void AppendRr(PacketDns packetDns, RrKind rrKind, OneRr oneRr) { Logger.Set(LogKind.Detail, null, 23, string.Format("[{0}] {1}", rrKind, oneRr)); //"Append RR" packetDns.AddRr(rrKind, oneRr); }
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(); }
//addrは通常オーダで指定されている //private PacketDns Lookup(Ip ip, string requestName, DNS_TYPE dnsType,RemoteInfo remoteInfo) { private PacketDns Lookup(Ip ip, string requestName, DnsType dnsType, Ip remoteAddr) { //Ip ip = new Ip(addr); Logger.Set(LogKind.Detail, null, 17, string.Format("{0} Server={1} Type={2}", requestName, ip, dnsType)); //"Lookup" //受信タイムアウト const int timeout = 3; // var random = new Random(Environment.TickCount); // var id = (ushort) random.Next(0xFFFF);//識別子をランダムに決定する var random = new Random(); var id = (ushort)random.Next(0xFFFF); const bool qr = false; //要求 const bool aa = false; //権威なし var rd = (bool)Conf.Get("useRD"); //再帰要求を使用するかどうか const bool ra = false; //再帰無効 //リクエストパケットの生成 var sp = new PacketDns(id, qr, aa, rd, ra); AppendRr(sp, RrKind.QD, new RrQuery(requestName, dnsType)); //QR(質問)フィールド追加 const int port = 53; //SockUdp sockUdp = new UdpObj(Kernel, getLogger(), ip, port); byte[] sendBuf = sp.GetBytes(); var sockUdp = new SockUdp(_kernel, ip, port, null, sendBuf); //送信 //この辺のロジックを動作確認する必要がある byte[] recvBuf = sockUdp.Recv(timeout); if (recvBuf != null && 12 <= recvBuf.Length) { //受信 try { var rp = new PacketDns(recvBuf); var str = string.Format("{0} count[{1},{2},{3},{4}] rcode={5} AA={6}", requestName, rp.GetCount(RrKind.QD), rp.GetCount(RrKind.AN), rp.GetCount(RrKind.NS), rp.GetCount(RrKind.AR), rp.GetRcode(), rp.GetAa()); Logger.Set(LogKind.Detail, sockUdp, 18, str); //"Lookup" //質問フィールの以外のリソースデータをキャッシュする //for (int rr = 1; rr < 4; rr++) { foreach (RrKind rr in Enum.GetValues(typeof(RrKind))) { if (rr == RrKind.QD) { continue; //質問フィールの以外のリソースデータをキャッシュする } var m = rp.GetCount(rr); for (var n = 0; n < m; n++) { var oneRr = rp.GetRr(rr, n); _rootCache.Add(oneRr); Logger.Set(LogKind.Detail, sockUdp, 24, string.Format("{0} _rootCache.Count={1}", oneRr, _rootCache.Count)); //_rootCache.Add } } return(rp); } catch (IOException) { //ここでのエラーログも必要? return(null); } } Logger.Set(LogKind.Error, sockUdp, 5, string.Format("addr={0} requestName={1} dnsType={2}", remoteAddr, requestName, dnsType)); //Lookup() パケット受信でタイムアウトが発生しました。 return(null); }
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(); }