+++ /dev/null
-//
-// Mono.Dns.DnsClass
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-namespace Mono.Dns {
- enum DnsClass : ushort {
- Internet = 1,
- IN = 1,
- CSNET = 2,
- CS = 2,
- CHAOS = 3,
- CH = 3,
- Hesiod = 4,
- HS = 4,
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.DnsHeader
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Mono.Dns {
- class DnsHeader {
- public const int DnsHeaderLength = 12;
- ArraySegment<byte> bytes;
-
- public DnsHeader (byte [] bytes)
- : this (bytes, 0)
- {
- }
-
- public DnsHeader (byte [] bytes, int offset)
- : this (new ArraySegment<byte> (bytes, offset, DnsHeaderLength))
- {
- }
-
- public DnsHeader (ArraySegment<byte> segment)
- {
- if (segment.Count != DnsHeaderLength)
- throw new ArgumentException ("Count must be 12", "segment");
-
- bytes = segment;
- }
-
- public void Clear ()
- {
- for (int i = 0; i < DnsHeaderLength; i++)
- bytes.Array [i + bytes.Offset] = 0;
- }
-
- public ushort ID {
- get {
- return (ushort)(bytes.Array [bytes.Offset] * 256 + bytes.Array [bytes.Offset + 1]);
- }
- set {
- bytes.Array [bytes.Offset] = (byte) ((value & 0x0ff00) >> 8);
- bytes.Array [bytes.Offset + 1] = (byte) (value & 0x0ff);
- }
- }
-
- public bool IsQuery {
- get { return ((bytes.Array [2 + bytes.Offset] & 0x80) != 0); }
- set {
- if (!value) {
- bytes.Array [2 + bytes.Offset] |= 0x80;
- } else {
- bytes.Array [2 + bytes.Offset] &= 0x7f;
- }
- }
- }
-
- public DnsOpCode OpCode {
- get { return (DnsOpCode) ((bytes.Array [2 + bytes.Offset] & 0x78) >> 3); }
- set {
- if (!Enum.IsDefined (typeof (DnsOpCode), value))
- throw new ArgumentOutOfRangeException ("value", "Invalid DnsOpCode value");
-
- int v = (int) value;
- v <<= 3;
- int prev = (bytes.Array [2 + bytes.Offset] & 0x87);
- v |= prev;
- bytes.Array [2 + bytes.Offset] = (byte) v;
- }
- }
-
- public bool AuthoritativeAnswer {
- get { return (bytes.Array [2 + bytes.Offset] & 4) != 0; }
- set {
- if(value) {
- bytes.Array [2 + bytes.Offset] |= 4;
- } else {
- bytes.Array [2 + bytes.Offset] &= 0xFB;
- }
- }
- }
-
- public bool Truncation {
- get { return (bytes.Array [2 + bytes.Offset] & 2) != 0; }
- set {
- if(value) {
- bytes.Array [2 + bytes.Offset] |= 2;
- } else {
- bytes.Array [2 + bytes.Offset] &= 0xFD;
- }
- }
- }
-
- public bool RecursionDesired {
- get { return (bytes.Array [2 + bytes.Offset] & 1) != 0; }
- set {
- if(value) {
- bytes.Array [2 + bytes.Offset] |= 1;
- } else {
- bytes.Array [2 + bytes.Offset] &= 0xFE;
- }
- }
- }
-
- public bool RecursionAvailable {
- get { return (bytes.Array [3 + bytes.Offset] & 0x80) != 0; }
- set {
- if(value) {
- bytes.Array [3 + bytes.Offset] |= 0x80;
- } else {
- bytes.Array [3 + bytes.Offset] &= 0x7F;
- }
- }
- }
-
- // TODO: Add AuthenticData and Checking Disabled (bit 10 and 11 of Z)
- public int ZReserved {
- get { return (bytes.Array [3 + bytes.Offset] & 0x70) >> 4; }
- set {
- if(value < 0 || value > 7) {
- throw new ArgumentOutOfRangeException("value", "Must be between 0 and 7");
- }
- bytes.Array [3 + bytes.Offset] &= 0x8F;
- bytes.Array [3 + bytes.Offset] |= (byte) ((value << 4) & 0x70);
- }
- }
-
- public DnsRCode RCode {
- get { return (DnsRCode) (bytes.Array [3 + bytes.Offset] & 0x0f); }
- set {
- int v = (int)value;
- //Info: Values > 15 are encoded in other records (OPT, TSIG, TKEY)
- if (v < 0 || v > 15)
- throw new ArgumentOutOfRangeException("value", "Must be between 0 and 15");
-
- bytes.Array [3 + bytes.Offset] &= 0x0f;
- bytes.Array [3 + bytes.Offset] |= (byte) v;
- }
- }
-
- static ushort GetUInt16 (byte [] bytes, int offset)
- {
- return (ushort)(bytes [offset] * 256 + bytes [offset + 1]);
- }
-
- static void SetUInt16 (byte [] bytes, int offset, ushort val)
- {
- bytes [offset] = (byte) ((val & 0x0ff00) >> 8);
- bytes [offset + 1] = (byte) (val & 0x0ff);
- }
-
- public ushort QuestionCount {
- get { return GetUInt16 (bytes.Array, 4); }
- set { SetUInt16 (bytes.Array, 4, value); }
- }
-
- public ushort AnswerCount {
- get { return GetUInt16 (bytes.Array, 6); }
- set { SetUInt16 (bytes.Array, 6, value); }
- }
-
- public ushort AuthorityCount {
- get { return GetUInt16 (bytes.Array, 8); }
- set { SetUInt16 (bytes.Array, 8, value); }
- }
-
- public ushort AdditionalCount {
- get { return GetUInt16 (bytes.Array, 10); }
- set { SetUInt16 (bytes.Array, 10, value); }
- }
-
- public override string ToString ()
- {
- StringBuilder sb = new StringBuilder();
- sb.AppendFormat ("ID: {0} QR: {1} Opcode: {2} AA: {3} TC: {4} RD: {5} RA: {6} \r\nRCode: {7} ",
- ID, IsQuery, OpCode, AuthoritativeAnswer, Truncation, RecursionDesired,
- RecursionAvailable, RCode);
- sb.AppendFormat ("Q: {0} A: {1} NS: {2} AR: {3}\r\n", QuestionCount, AnswerCount, AuthorityCount, AdditionalCount);
- return sb.ToString();
- }
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.DnsOpCode
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-namespace Mono.Dns {
- enum DnsOpCode : byte {
- Query = 0,
- [Obsolete] IQuery = 1,
- Status = 2,
- Notify = 4,
- Update = 5,
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.DnsPacket
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.IO;
-
-namespace Mono.Dns {
- abstract class DnsPacket {
- protected byte [] packet;
- protected int position;
- protected DnsHeader header;
-
- protected DnsPacket ()
- {
- // Caller has to initialize packet, position and header
- }
-
- protected DnsPacket (int length)
- : this (new byte [length], length)
- {
- }
-
- protected DnsPacket (byte [] buffer, int length)
- {
- if (buffer == null)
- throw new ArgumentNullException("buffer");
- if (length <= 0)
- throw new ArgumentOutOfRangeException("length", "Must be greater than zero.");
-
- packet = buffer;
- position = length;
- header = new DnsHeader(new ArraySegment<byte>(packet, 0, 12));
- }
-
- public byte [] Packet {
- get { return packet; }
- }
-
- public int Length {
- get { return position; }
- }
-
- public DnsHeader Header {
- get { return header; }
- }
-
- protected void WriteUInt16 (ushort v)
- {
- packet [position++] = (byte) ((v & 0x0ff00) >> 8);
- packet [position++] = (byte) (v & 0x0ff);
- }
-
- protected void WriteStringBytes (string str, int offset, int count)
- {
- for (int i = offset, c = 0; c < count; c++, i++)
- packet [position++] = (byte) str [i]; // Don't care about encoding.
- }
-
- protected void WriteLabel (string str, int offset, int count)
- {
- packet [position++] = (byte) count;
- WriteStringBytes (str, offset, count);
- }
-
- protected void WriteDnsName (string name)
- {
- if (!DnsUtil.IsValidDnsName (name))
- throw new ArgumentException ("Invalid DNS name");
-
- if (!String.IsNullOrEmpty (name)) {
- int len = name.Length;
- int label_start = 0;
- int label_len = 0;
- for (int i = 0; i < len; i++) {
- char c = name [i];
- if (c != '.') {
- label_len++;
- } else {
- if (i == 0)
- break; // "."
- WriteLabel (name, label_start, label_len);
- label_start += label_len + 1; // Skip the dot
- label_len = 0;
- }
- }
- if (label_len > 0)
- WriteLabel (name, label_start, label_len);
- }
-
- packet [position++] = 0;
- }
-
- protected internal string ReadName (ref int offset)
- {
- return DnsUtil.ReadName (packet, ref offset);
- }
-
- protected internal static string ReadName (byte [] buffer, ref int offset)
- {
- return DnsUtil.ReadName (buffer, ref offset);
- }
-
- protected internal ushort ReadUInt16 (ref int offset)
- {
- return (ushort)((packet[offset++] << 8) + packet[offset++]);
- }
-
- protected internal int ReadInt32 (ref int offset)
- {
- return (packet [offset++] << 24) + (packet [offset++] << 16) + (packet [offset++] << 8) + packet [offset++];
- }
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.DnsQClass
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-namespace Mono.Dns {
- enum DnsQClass : ushort {
- Internet = 1,
- IN = 1,
- CSNET = 2,
- CS = 2,
- CHAOS = 3,
- CH = 3,
- Hesiod = 4,
- HS = 4,
- None = 254,
- Any = 255
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.DnsQType
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-namespace Mono.Dns {
- enum DnsQType : ushort {
- A = 1,
- NS = 2,
- [Obsolete] MD = 3,
- [Obsolete] MF = 4,
- CNAME = 5,
- SOA = 6,
- [Obsolete] MB = 7,
- [Obsolete] MG = 8,
- [Obsolete] MR = 9,
- [Obsolete] NULL = 10,
- [Obsolete] WKS = 11,
- PTR = 12,
- [Obsolete] HINFO = 13,
- [Obsolete] MINFO = 14,
- MX = 15,
- TXT = 16,
- [Obsolete] RP = 17,
- AFSDB = 18,
- [Obsolete] X25 = 19,
- [Obsolete] ISDN = 20,
- [Obsolete] RT = 21,
- [Obsolete] NSAP = 22,
- [Obsolete] NSAPPTR = 23,
- SIG = 24,
- KEY = 25,
- [Obsolete] PX = 26,
- [Obsolete] GPOS = 27,
- AAAA = 28,
- LOC = 29,
- [Obsolete] NXT = 30,
- [Obsolete] EID = 31,
- [Obsolete] NIMLOC = 32,
- SRV = 33,
- [Obsolete] ATMA = 34,
- NAPTR = 35,
- KX = 36,
- CERT = 37,
- [Obsolete] A6 = 38,
- DNAME = 39,
- [Obsolete] SINK = 40,
- OPT = 41,
- [Obsolete] APL = 42,
- DS = 43,
- SSHFP = 44,
- IPSECKEY = 45,
- RRSIG = 46,
- NSEC = 47,
- DNSKEY = 48,
- DHCID = 49,
- NSEC3 = 50,
- NSEC3PARAM = 51,
- HIP = 55,
- NINFO = 56,
- RKEY = 57,
- TALINK = 58,
- SPF = 99,
- [Obsolete] UINFO = 100,
- [Obsolete] UID = 101,
- [Obsolete] GID = 102,
- [Obsolete] UNSPEC = 103,
- TKEY = 249,
- TSIG = 250,
- IXFR = 251,
- AXFR = 252,
- [Obsolete] MAILB = 253,
- [Obsolete] MAILA = 254,
- ALL = 255,
- URI = 256,
- TA = 32768,
- DLV = 32769,
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.DnsQuery
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-
-namespace Mono.Dns {
- class DnsQuery : DnsPacket {
- public DnsQuery (string name, DnsQType qtype, DnsQClass qclass)
- {
- if (String.IsNullOrEmpty (name))
- throw new ArgumentNullException ("name");
-
- int length = DnsUtil.GetEncodedLength (name);
- if (length == -1)
- throw new ArgumentException ("Invalid DNS name", "name");
-
- length += 12 + 2 + 2; // Header + qtype + qclass
- packet = new byte [length];
- header = new DnsHeader (packet, 0);
- position = 12;
- WriteDnsName (name);
- WriteUInt16 ((ushort) qtype);
- WriteUInt16 ((ushort) qclass);
- Header.QuestionCount = 1;
- Header.IsQuery = true;
- Header.RecursionDesired = true;
- }
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.DnsQuestion
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Mono.Dns {
- class DnsQuestion {
- string name;
- DnsQType type;
- DnsQClass _class;
-
- internal DnsQuestion ()
- {
- }
-
- internal int Init (DnsPacket packet, int offset)
- {
- name = packet.ReadName (ref offset);
- type = (DnsQType) packet.ReadUInt16 (ref offset);
- _class = (DnsQClass) packet.ReadUInt16 (ref offset);
- return offset;
- }
-
- public string Name {
- get { return name; }
- }
-
- public DnsQType Type {
- get { return type; }
- }
-
- public DnsQClass Class {
- get { return _class; }
- }
-
- public override string ToString() {
- return String.Format("Name: {0} Type: {1} Class: {2}", Name, Type, Class);
- }
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.DnsRCode
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-namespace Mono.Dns {
- enum DnsRCode : ushort {
- NoError = 0,
- FormErr = 1,
- ServFail = 2,
- NXDomain = 3,
- NotImp = 4,
- Refused = 5,
- YXDomain = 6,
- YXRRSet = 7,
- NXRRSet = 8,
- NotAuth = 9,
- NotZone = 10,
- BadVers = 16,
- BadSig = 16,
- BadKey = 17,
- BadTime = 18,
- BadMode = 19,
- BadName = 20,
- BadAlg = 21,
- BadTrunc = 22,
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.DnsResourceRecord
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-
-namespace Mono.Dns {
- class DnsResourceRecord {
- string name;
- DnsType type;
- DnsClass klass;
- int ttl;
- ushort rdlength;
- ArraySegment<byte> m_rdata;
-
- internal DnsResourceRecord() {
- }
-
- internal void CopyFrom(DnsResourceRecord rr) {
- name = rr.name;
- type = rr.type;
- klass = rr.klass;
- ttl = rr.ttl;
- rdlength = rr.rdlength;
- m_rdata = rr.m_rdata;
- }
-
- static internal DnsResourceRecord CreateFromBuffer(DnsPacket packet, int size, ref int offset) {
- string pname = packet.ReadName(ref offset);
- DnsType ptype = (DnsType)packet.ReadUInt16(ref offset);
- DnsClass pclass = (DnsClass)packet.ReadUInt16(ref offset);
- int pttl = packet.ReadInt32(ref offset);
- ushort prdlength = packet.ReadUInt16(ref offset);
- DnsResourceRecord rr = new DnsResourceRecord();
- rr.name = pname;
- rr.type = ptype;
- rr.klass = pclass;
- rr.ttl = pttl;
- rr.rdlength = prdlength;
- rr.m_rdata = new ArraySegment<byte>(packet.Packet, offset, prdlength);
- offset += prdlength;
-
- switch(pclass) {
- case DnsClass.IN:
- switch(ptype) {
- case DnsType.A:
- rr = new DnsResourceRecordA(rr);
- break;
- case DnsType.AAAA:
- rr = new DnsResourceRecordAAAA(rr);
- break;
- case DnsType.CNAME:
- rr = new DnsResourceRecordCName(rr);
- break;
- case DnsType.PTR:
- rr = new DnsResourceRecordPTR(rr);
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- return rr;
- }
-
- public string Name {
- get { return name; }
- }
-
- public DnsType Type {
- get { return type; }
- }
-
- public DnsClass Class {
- get { return klass; }
- }
-
- public int Ttl {
- get { return ttl; }
- }
-
- public ArraySegment<byte> Data {
- get { return m_rdata; }
- }
-
- public override string ToString() {
- return String.Format("Name: {0}, Type: {1}, Class: {2}, Ttl: {3}, Data length: {4}", name, type, klass, ttl, Data.Count);
- }
- }
-}
+++ /dev/null
-//
-// Mono.Dns.DnsResourceRecordA
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-using System.Collections.Generic;
-using System.Net;
-using System.Text;
-
-namespace Mono.Dns {
- class DnsResourceRecordA : DnsResourceRecordIPAddress {
- internal DnsResourceRecordA (DnsResourceRecord rr)
- : base (rr, 4)
- {
- }
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.DnsResourceRecordAAAA
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-using System.Collections.Generic;
-using System.Net;
-using System.Text;
-
-namespace Mono.Dns {
- class DnsResourceRecordAAAA : DnsResourceRecordIPAddress {
- internal DnsResourceRecordAAAA (DnsResourceRecord rr)
- : base (rr, 16)
- {
- }
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.DnsResourceRecordCName
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Mono.Dns {
- class DnsResourceRecordCName : DnsResourceRecord {
- string cname;
-
- internal DnsResourceRecordCName (DnsResourceRecord rr)
- {
- CopyFrom (rr);
- int offset = rr.Data.Offset;
- cname = DnsPacket.ReadName (rr.Data.Array, ref offset);
- }
-
- public string CName {
- get { return cname; }
- }
-
- public override string ToString ()
- {
- return base.ToString () + " CNAME: " + cname.ToString ();
- }
- }
-}
+++ /dev/null
-//
-// Mono.Dns.DnsResourceRecordIPAddress
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-using System.Collections.Generic;
-using System.Net;
-using System.Text;
-
-namespace Mono.Dns {
- abstract class DnsResourceRecordIPAddress : DnsResourceRecord {
- IPAddress address;
-
- internal DnsResourceRecordIPAddress (DnsResourceRecord rr, int address_size)
- {
- CopyFrom (rr);
- ArraySegment<byte> segment = rr.Data;
- byte [] bytes = new byte [address_size];
- Buffer.BlockCopy (segment.Array, segment.Offset, bytes, 0, address_size);
- address = new IPAddress (bytes);
- }
-
- public override string ToString ()
- {
- return base.ToString() + " Address: " + address;
- }
-
- public IPAddress Address {
- get { return address; }
- }
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.DnsResourceRecordPTR
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Mono.Dns {
- class DnsResourceRecordPTR : DnsResourceRecord {
- string dname;
-
- internal DnsResourceRecordPTR (DnsResourceRecord rr)
- {
- CopyFrom (rr);
- int offset = rr.Data.Offset;
- dname = DnsPacket.ReadName (rr.Data.Array, ref offset);
- }
-
- public string DName {
- get { return dname; }
- }
-
- public override string ToString() {
- return base.ToString () + " DNAME: " + dname.ToString ();
- }
- }
-}
+++ /dev/null
-//
-// Mono.Dns.DnsResponse
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.IO;
-using System.Text;
-
-namespace Mono.Dns {
- class DnsResponse : DnsPacket {
- static readonly ReadOnlyCollection<DnsResourceRecord> EmptyRR = new ReadOnlyCollection<DnsResourceRecord> (new DnsResourceRecord [0]);
- static readonly ReadOnlyCollection<DnsQuestion> EmptyQS = new ReadOnlyCollection<DnsQuestion> (new DnsQuestion [0]);
-
- ReadOnlyCollection<DnsQuestion> question;
- ReadOnlyCollection<DnsResourceRecord> answer;
- ReadOnlyCollection<DnsResourceRecord> authority;
- ReadOnlyCollection<DnsResourceRecord> additional;
- int offset = DnsHeader.DnsHeaderLength;
-
- public DnsResponse (byte [] buffer, int length)
- : base (buffer, length)
- {
- }
-
- public void Reset ()
- {
- question = null;
- answer = null;
- authority = null;
- additional = null;
- for (int i = 0; i < packet.Length; i++)
- packet [i] = 0;
- }
-
- ReadOnlyCollection<DnsResourceRecord> GetRRs (int count)
- {
- if (count <= 0)
- return EmptyRR;
-
- List<DnsResourceRecord> records = new List<DnsResourceRecord>(count);
- for (int i = 0; i < count; i++)
- records.Add (DnsResourceRecord.CreateFromBuffer (this, position, ref offset));
- return records.AsReadOnly ();
- }
-
- ReadOnlyCollection<DnsQuestion> GetQuestions (int count)
- {
- if (count <= 0)
- return EmptyQS;
-
- List<DnsQuestion> records = new List<DnsQuestion> (count);
- for(int i = 0; i < count; i++) {
- DnsQuestion record = new DnsQuestion ();
- offset = record.Init (this, offset);
- records.Add (record);
- }
- return records.AsReadOnly ();
- }
-
- public ReadOnlyCollection<DnsQuestion> GetQuestions ()
- {
- if (question == null)
- question = GetQuestions (Header.QuestionCount);
- return question;
- }
-
- public ReadOnlyCollection<DnsResourceRecord> GetAnswers ()
- {
- if (answer == null) {
- GetQuestions ();
- answer = GetRRs (Header.AnswerCount);
- }
- return answer;
- }
-
- public ReadOnlyCollection<DnsResourceRecord> GetAuthority ()
- {
- if (authority == null) {
- GetQuestions ();
- GetAnswers ();
- authority = GetRRs (Header.AuthorityCount);
- }
- return authority;
- }
-
- public ReadOnlyCollection<DnsResourceRecord> GetAdditional ()
- {
- if (additional == null) {
- GetQuestions ();
- GetAnswers ();
- GetAuthority ();
- additional = GetRRs (Header.AdditionalCount);
- }
- return additional;
- }
-
- public override string ToString ()
- {
- StringBuilder sb = new StringBuilder();
- sb.Append(Header);
- sb.Append("Question:\r\n");
- foreach(DnsQuestion q in GetQuestions()) {
- sb.AppendFormat("\t{0}\r\n", q);
- }
- sb.Append("Answer(s):\r\n");
- foreach(DnsResourceRecord q in GetAnswers()) {
- sb.AppendFormat("\t{0}\r\n", q);
- }
- sb.Append("Authority:\r\n");
- foreach(DnsResourceRecord q in GetAuthority()) {
- sb.AppendFormat("\t{0}\r\n", q);
- }
- sb.Append("Additional:\r\n");
- foreach(DnsResourceRecord q in GetAdditional()) {
- sb.AppendFormat("\t{0}\r\n", q);
- }
- return sb.ToString();
- }
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.DnsType
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-namespace Mono.Dns {
- enum DnsType : ushort {
- A = 1,
- NS = 2,
- [Obsolete] MD = 3,
- [Obsolete] MF = 4,
- CNAME = 5,
- SOA = 6,
- [Obsolete] MB = 7,
- [Obsolete] MG = 8,
- [Obsolete] MR = 9,
- [Obsolete] NULL = 10,
- [Obsolete] WKS = 11,
- PTR = 12,
- [Obsolete] HINFO = 13,
- [Obsolete] MINFO = 14,
- MX = 15,
- TXT = 16,
- [Obsolete] RP = 17,
- AFSDB = 18,
- [Obsolete] X25 = 19,
- [Obsolete] ISDN = 20,
- [Obsolete] RT = 21,
- [Obsolete] NSAP = 22,
- [Obsolete] NSAPPTR = 23,
- SIG = 24,
- KEY = 25,
- [Obsolete] PX = 26,
- [Obsolete] GPOS = 27,
- AAAA = 28,
- LOC = 29,
- [Obsolete] NXT = 30,
- [Obsolete] EID = 31,
- [Obsolete] NIMLOC = 32,
- SRV = 33,
- [Obsolete] ATMA = 34,
- NAPTR = 35,
- KX = 36,
- CERT = 37,
- [Obsolete] A6 = 38,
- DNAME = 39,
- [Obsolete] SINK = 40,
- OPT = 41,
- [Obsolete] APL = 42,
- DS = 43,
- SSHFP = 44,
- IPSECKEY = 45,
- RRSIG = 46,
- NSEC = 47,
- DNSKEY = 48,
- DHCID = 49,
- NSEC3 = 50,
- NSEC3PARAM = 51,
- HIP = 55,
- NINFO = 56,
- RKEY = 57,
- TALINK = 58,
- SPF = 99,
- [Obsolete] UINFO = 100,
- [Obsolete] UID = 101,
- [Obsolete] GID = 102,
- [Obsolete] UNSPEC = 103,
- TKEY = 249,
- TSIG = 250,
- IXFR = 251,
- AXFR = 252,
- [Obsolete] MAILB = 253,
- [Obsolete] MAILA = 254,
- URI = 256,
- TA = 32768,
- DLV = 32769,
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.DnsUtil
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Mono.Dns {
- static class DnsUtil {
- // RFC 2181 - Section 11
- public static bool IsValidDnsName (string name)
- {
- if (name == null)
- return false;
-
- int len = name.Length;
- if (len > 255)
- return false;
- int part_length = 0;
- for (int i = 0; i < len; i++) {
- char c = name [i];
- if (c == '.') {
- if (i == 0 && len > 1)
- return false; // Can't begin with a dot unless it's "."
- if (i > 0 && part_length == 0)
- return false; // No ".." allowed
- part_length = 0;
- continue;
- }
- part_length++;
- if (part_length > 63)
- return false;
- }
- return true;
- }
-
- public static int GetEncodedLength (string name)
- {
- if (!IsValidDnsName (name))
- return -1;
-
- if (name == String.Empty)
- return 1;
-
- int len = name.Length;
- if (name [len - 1] == '.')
- return len + 1; // (length + label + ... + \0)
- return len + 2; // need 1 more for the second to last label length
- }
-
- public static int GetNameLength (byte [] buffer)
- {
- return GetNameLength (buffer, 0);
- }
-
- public static int GetNameLength (byte [] buffer, int offset)
- {
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
- if (offset < 0 || offset >= buffer.Length)
- throw new ArgumentOutOfRangeException ("offset");
-
- int i = 0;
- int len = 0;
- while (len < 256) {
- i = buffer [offset++];
- if (i == 0)
- return len > 0 ? --len : 0;
- int ptr = i & 0x0C0;
- if (ptr == 0x0C0) {
- i = ((ptr & 0x3F) << 8) + buffer[offset++];
- offset = i;
- continue;
- } else if (ptr >= 0x40) {
- return -2; // Invalid ptr
- }
- len += i + 1;
- offset += i;
- }
- return -1; // Invalid length
- }
-
- public static string ReadName (byte [] buffer, ref int offset)
- {
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
- if (offset < 0 || offset >= buffer.Length)
- throw new ArgumentOutOfRangeException ("offset");
-
- StringBuilder sb = new StringBuilder (32);
- int i = 0;
- bool no_ptr = true;
- int off = offset;
- while (sb.Length < 256) {
- i = buffer [off++];
- if (no_ptr) offset++;
- if (i == 0) {
- if (sb.Length > 0)
- sb.Length--;
- return sb.ToString ();
- }
- int ptr = i & 0x0C0;
- if (ptr == 0x0C0) {
- i = ((ptr & 0x3F) << 8) + buffer [off];
- if (no_ptr) offset++;
- no_ptr = false;
- off = i;
- continue;
- } else if (i >= 0x40) {
- return null; // Invalid ptr
- }
-
- for (int k = 0; k < i; k++)
- sb.Append ((char) buffer [off + k]);
- sb.Append ('.');
- off += i;
- if (no_ptr) offset += i;
- }
- return null; // never reached
- }
-
- }
-}
-
+++ /dev/null
-SOURCES= \
- DnsClass.cs \
- DnsHeader.cs \
- DnsPacket.cs \
- DnsQClass.cs \
- DnsQType.cs \
- DnsQuery.cs \
- DnsQuestion.cs \
- DnsResourceRecordA.cs \
- DnsResourceRecordCName.cs \
- DnsResourceRecordPTR.cs \
- DnsResourceRecord.cs \
- DnsResponse.cs \
- DnsType.cs \
- ResolverAsyncOperation.cs \
- Resolver.cs \
- ResolverError.cs \
- SimpleResolverEventArgs.cs
-
-EXES = resolver.exe \
- plainolddns.exe
-
-all: $(EXES)
-
-resolver.exe: $(SOURCES)
- @gmcs -out:$@ -debug $(SOURCES)
-
-plainolddns.exe: plainolddns.cs
- @gmcs -out:$@ -debug $^
-clean:
- rm -f resolver.exe* plainolddns.exe* *.mdb
+++ /dev/null
-//
-// Mono.Dns.ResolverAsyncOperation
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-namespace Mono.Dns {
- enum ResolverAsyncOperation {
- None,
- GetHostEntry,
- GetHostAddresses,
- }
-}
-
+++ /dev/null
-// Mono.Dns.ResolverError
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-namespace Mono.Dns {
- enum ResolverError {
- NoError, // From DNS server
- FormatError, //
- ServerFailure, //
- NameError, //
- NotImplemented, //
- Refused, //
- // Resolver specific
- ResponseHeaderError,
- ResponseFormatError,
- Timeout,
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.SimpleResolver
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Diagnostics;
-using System.Net;
-using System.Net.Sockets;
-using System.Net.NetworkInformation;
-using System.Text;
-using System.Threading;
-
-namespace Mono.Dns {
- sealed class SimpleResolver : IDisposable {
- static string [] EmptyStrings = new string [0];
- static IPAddress [] EmptyAddresses = new IPAddress [0];
- IPEndPoint [] endpoints;
- Socket client;
- Dictionary<int, SimpleResolverEventArgs> queries;
- AsyncCallback receive_cb;
- TimerCallback timeout_cb;
- bool disposed;
-#if REUSE_RESPONSES
- Stack<DnsResponse> responses_avail = new Stack<DnsResponse> ();
-#endif
-
- public SimpleResolver ()
- {
- queries = new Dictionary<int, SimpleResolverEventArgs> ();
- receive_cb = new AsyncCallback (OnReceive);
- timeout_cb = new TimerCallback (OnTimeout);
- InitFromSystem ();
- InitSocket ();
- }
-
- void IDisposable.Dispose ()
- {
- if (!disposed) {
- disposed = true;
- if (client != null) {
- client.Close ();
- client = null;
- }
- }
- }
-
- public void Close ()
- {
- ((IDisposable) this).Dispose ();
- }
-
- void GetLocalHost (SimpleResolverEventArgs args)
- {
- //FIXME
- IPHostEntry entry = new IPHostEntry ();
- entry.HostName = "localhost";
- entry.AddressList = new IPAddress [] { IPAddress.Loopback };
- entry.Aliases = EmptyStrings;
- args.ResolverError = 0;
- args.HostEntry = entry;
- return;
-
-/*
- List<IPEndPoint> eps = new List<IPEndPoint> ();
- foreach (NetworkInterface iface in NetworkInterface.GetAllNetworkInterfaces ()) {
- if (NetworkInterfaceType.Loopback == iface.NetworkInterfaceType)
- continue;
-
- foreach (IPAddress addr in iface.GetIPProperties ().DnsAddresses) {
- if (AddressFamily.InterNetworkV6 == addr.AddressFamily)
- continue;
- IPEndPoint ep = new IPEndPoint (addr, 53);
- if (eps.Contains (ep))
- continue;
-
- eps.Add (ep);
- }
- }
- endpoints = eps.ToArray ();
-*/
- }
-
- // Type A query
- // Might fill in Aliases
- // -IPAddress -> return the same IPAddress
- // -"" -> Local host ip addresses (filter out IPv6 if needed)
- public bool GetHostAddressesAsync (SimpleResolverEventArgs args)
- {
- if (args == null)
- throw new ArgumentNullException ("args");
-
- if (args.HostName == null)
- throw new ArgumentNullException ("args.HostName is null");
-
- if (args.HostName.Length > 255)
- throw new ArgumentException ("args.HostName is too long");
-
- args.Reset (ResolverAsyncOperation.GetHostAddresses);
- string host = args.HostName;
- if (host == "") {
- GetLocalHost (args);
- return false;
- }
- IPAddress addr;
- if (IPAddress.TryParse (host, out addr)) {
- IPHostEntry entry = new IPHostEntry ();
- entry.HostName = host;
- entry.Aliases = EmptyStrings;
- entry.AddressList = new IPAddress [1] { addr };
- args.HostEntry = entry;
- return false;
- }
-
- SendAQuery (args, true);
- return true;
- }
-
- // For names -> type A Query
- // For IP addresses -> PTR + A -> will at least return itself
- // Careful: for IP addresses with PTR, the hostname might yield different IP addresses!
- public bool GetHostEntryAsync (SimpleResolverEventArgs args)
- {
- if (args == null)
- throw new ArgumentNullException ("args");
-
- if (args.HostName == null)
- throw new ArgumentNullException ("args.HostName is null");
-
- if (args.HostName.Length > 255)
- throw new ArgumentException ("args.HostName is too long");
-
- args.Reset (ResolverAsyncOperation.GetHostEntry);
- string host = args.HostName;
- if (host == "") {
- GetLocalHost (args);
- return false;
- }
-
- IPAddress addr;
- if (IPAddress.TryParse (host, out addr)) {
- IPHostEntry entry = new IPHostEntry ();
- entry.HostName = host;
- entry.Aliases = EmptyStrings;
- entry.AddressList = new IPAddress [1] { addr };
- args.HostEntry = entry;
- args.PTRAddress = addr;
- SendPTRQuery (args, true);
- return true;
- }
-
- // 3. For IP addresses:
- // 3.1 Parsing IP succeeds
- // 3.2 Reverse lookup of the IP fills in HostName -> fails? HostName = IP
- // 3.3 The hostname resulting from this is used to query DNS again to get the IP addresses
- //
- // Exclude IPv6 addresses if not supported by the system
- // .Aliases is always empty
- // Length > 255
- SendAQuery (args, true);
- return true;
- }
-
- bool AddQuery (DnsQuery query, SimpleResolverEventArgs args)
- {
- lock (queries) {
- if (queries.ContainsKey (query.Header.ID))
- return false;
- queries [query.Header.ID] = args;
- }
- return true;
- }
-
- static DnsQuery GetQuery (string host, DnsQType q, DnsQClass c)
- {
- return new DnsQuery (host, q, c);
- }
-
- void SendAQuery (SimpleResolverEventArgs args, bool add_it)
- {
- SendAQuery (args, args.HostName, add_it);
- }
-
- void SendAQuery (SimpleResolverEventArgs args, string host, bool add_it)
- {
- DnsQuery query = GetQuery (host, DnsQType.A, DnsQClass.IN);
- SendQuery (args, query, add_it);
- }
-
- static string GetPTRName (IPAddress address)
- {
- // TODO: IPv6 PTR query?
- byte [] bytes = address.GetAddressBytes ();
- // "XXX.XXX.XXX.XXX.in-addr.arpa".Length
- StringBuilder sb = new StringBuilder (28);
- for (int i = bytes.Length - 1; i >= 0; i--) {
- sb.AppendFormat ("{0}.", bytes [i]);
- }
- sb.Append ("in-addr.arpa");
- return sb.ToString ();
- }
-
- void SendPTRQuery (SimpleResolverEventArgs args, bool add_it)
- {
- DnsQuery query = GetQuery (GetPTRName (args.PTRAddress), DnsQType.PTR, DnsQClass.IN);
- SendQuery (args, query, add_it);
- }
-
- void SendQuery (SimpleResolverEventArgs args, DnsQuery query, bool add_it)
- {
- // TODO: not sure about reusing IDs when add_it == false
- int count = 0;
- if (add_it) {
- do {
- query.Header.ID = (ushort)new Random().Next(1, 65534);
- if (count > 500)
- throw new InvalidOperationException ("Too many pending queries (or really bad luck)");
- } while (AddQuery (query, args) == false);
- args.QueryID = query.Header.ID;
- } else {
- query.Header.ID = args.QueryID;
- }
- if (args.Timer == null)
- args.Timer = new Timer (timeout_cb, args, 5000, Timeout.Infinite);
- else
- args.Timer.Change (5000, Timeout.Infinite);
- client.BeginSend (query.Packet, 0, query.Length, SocketFlags.None, null, null);
- }
-
- byte [] GetFreshBuffer ()
- {
-#if !REUSE_RESPONSES
- return new byte [512];
-#else
-
- DnsResponse response = null;
- lock (responses_avail) {
- if (responses_avail.Count > 0) {
- response = responses_avail.Pop ();
- }
- }
- if (response == null) {
- response = new DnsResponse ();
- } else {
- response.Reset ();
- }
- return response;
-#endif
- }
-
- void FreeBuffer (byte [] buffer)
- {
-#if REUSE_RESPONSES
- // TODO: set some limit here. Configurable?
- lock (responses_avail) {
- responses_avail.Push (response);
- }
-#endif
- }
-
- void InitSocket ()
- {
- client = new Socket (AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
- client.Blocking = true;
- client.Bind (new IPEndPoint (IPAddress.Any, 0));
- client.Connect (endpoints [0]);
- BeginReceive ();
- }
-
- void BeginReceive ()
- {
- byte [] buffer = GetFreshBuffer ();
- client.BeginReceive (buffer, 0, buffer.Length, SocketFlags.None, receive_cb, buffer);
- }
-
- void OnTimeout (object obj)
- {
- SimpleResolverEventArgs args = (SimpleResolverEventArgs) obj;
- SimpleResolverEventArgs args2;
- lock (queries) {
- if (!queries.TryGetValue (args.QueryID, out args2)) {
- return; // Already processed.
- }
- if (args != args2)
- throw new Exception ("Should not happen: args != args2");
- args.Retries++;
- if (args.Retries > 1) {
- // Error timeout
- args.ResolverError = ResolverError.Timeout;
- args.OnCompleted (this);
- } else {
- SendAQuery (args, false);
- }
- }
- }
-
- void OnReceive (IAsyncResult ares)
- {
- if (disposed)
- return;
-
- int nread = 0;
- EndPoint remote_ep = client.RemoteEndPoint;
- try {
- nread = client.EndReceive (ares);
- } catch (Exception e) {
- Console.Error.WriteLine (e);
- }
-
- BeginReceive ();
-
- byte [] buffer = (byte []) ares.AsyncState;
- if (nread > 12) {
- DnsResponse response = new DnsResponse (buffer, nread);
- int id = response.Header.ID;
- SimpleResolverEventArgs args = null;
- lock (queries) {
- if (queries.TryGetValue (id, out args)) {
- queries.Remove (id);
- }
- }
-
- if (args != null) {
- Timer t = args.Timer;
- if (t != null)
- t.Change (Timeout.Infinite, Timeout.Infinite);
-
- try {
- ProcessResponse (args, response, remote_ep);
- } catch (Exception e) {
- args.ResolverError = (ResolverError) (-1);
- args.ErrorMessage = e.Message;
- }
-
- IPHostEntry entry = args.HostEntry;
- if (args.ResolverError != 0 && args.PTRAddress != null && entry != null && entry.HostName != null) {
- args.PTRAddress = null;
- SendAQuery (args, entry.HostName, true);
- args.Timer.Change (5000, Timeout.Infinite);
- } else {
- args.OnCompleted (this);
- }
- }
- }
- FreeBuffer (buffer);
- }
-
- void ProcessResponse (SimpleResolverEventArgs args, DnsResponse response, EndPoint server_ep)
- {
- DnsRCode status = response.Header.RCode;
- if (status != 0) {
- if (args.PTRAddress != null) {
- // PTR query failed -> no error, we have the IP
- return;
- }
- args.ResolverError = (ResolverError) status;
- return;
- }
-
- // TODO: verify IP of the server is in our list and the same one that got the query
- IPEndPoint ep = (IPEndPoint) server_ep;
- if (ep.Port != 53) {
- args.ResolverError = ResolverError.ResponseHeaderError;
- args.ErrorMessage = "Port";
- return;
- }
-
- DnsHeader header = response.Header;
- if (!header.IsQuery) {
- args.ResolverError = ResolverError.ResponseHeaderError;
- args.ErrorMessage = "IsQuery";
- return;
- }
-
- // TODO: handle Truncation. Retry with bigger buffer?
-
- if (header.QuestionCount > 1) {
- args.ResolverError = ResolverError.ResponseHeaderError;
- args.ErrorMessage = "QuestionCount";
- return;
- }
- ReadOnlyCollection<DnsQuestion> q = response.GetQuestions ();
- if (q.Count != 1) {
- args.ResolverError = ResolverError.ResponseHeaderError;
- args.ErrorMessage = "QuestionCount 2";
- return;
- }
- DnsQuestion question = q [0];
- /* The answer might have dot at the end, etc...
- if (String.Compare (question.Name, args.HostName) != 0) {
- args.ResolverError = ResolverError.ResponseHeaderError;
- args.ErrorMessage = "HostName - " + question.Name + " != " + args.HostName;
- return;
- }
- */
-
- DnsQType t = question.Type;
- if (t != DnsQType.A && t != DnsQType.AAAA && t != DnsQType.PTR) {
- args.ResolverError = ResolverError.ResponseHeaderError;
- args.ErrorMessage = "QType " + question.Type;
- return;
- }
-
- if (question.Class != DnsQClass.IN) {
- args.ResolverError = ResolverError.ResponseHeaderError;
- args.ErrorMessage = "QClass " + question.Class;
- return;
- }
-
- ReadOnlyCollection<DnsResourceRecord> records = response.GetAnswers ();
- if (records.Count == 0) {
- if (args.PTRAddress != null) {
- // PTR query failed -> no error
- return;
- }
- args.ResolverError = ResolverError.NameError; // is this ok?
- args.ErrorMessage = "NoAnswers";
- return;
- }
-
- List<string> aliases = null;
- List<IPAddress> addresses = null;
- foreach (DnsResourceRecord r in records) {
- if (r.Class != DnsClass.IN)
- continue;
- if (r.Type == DnsType.A || r.Type == DnsType.AAAA) {
- if (addresses == null)
- addresses = new List<IPAddress> ();
- addresses.Add (((DnsResourceRecordIPAddress) r).Address);
- } else if (r.Type == DnsType.CNAME) {
- if (aliases == null)
- aliases = new List<string> ();
- aliases.Add (((DnsResourceRecordCName) r).CName);
- } else if (r.Type == DnsType.PTR) {
- args.HostEntry.HostName = ((DnsResourceRecordPTR) r).DName;
- args.HostEntry.Aliases = aliases == null ? EmptyStrings : aliases.ToArray ();
- args.HostEntry.AddressList = EmptyAddresses;
- return;
- }
- }
-
- IPHostEntry entry = args.HostEntry ?? new IPHostEntry ();
- if (entry.HostName == null && aliases != null && aliases.Count > 0) {
- entry.HostName = aliases [0];
- aliases.RemoveAt (0);
- }
- entry.Aliases = aliases == null ? EmptyStrings : aliases.ToArray ();
- entry.AddressList = addresses == null ? EmptyAddresses : addresses.ToArray ();
- args.HostEntry = entry;
- if ((question.Type == DnsQType.A || question.Type == DnsQType.AAAA) && entry.AddressList == EmptyAddresses) {
- args.ResolverError = ResolverError.NameError;
- args.ErrorMessage = "No addresses in response";
- } else if (question.Type == DnsQType.PTR && entry.HostName == null) {
- args.ResolverError = ResolverError.NameError;
- args.ErrorMessage = "No PTR in response";
- }
-
- }
-
- void InitFromSystem ()
- {
- List<IPEndPoint> eps = new List<IPEndPoint> ();
- foreach (NetworkInterface iface in NetworkInterface.GetAllNetworkInterfaces ()) {
- if (NetworkInterfaceType.Loopback == iface.NetworkInterfaceType)
- continue;
-
- foreach (IPAddress addr in iface.GetIPProperties ().DnsAddresses) {
- if (AddressFamily.InterNetworkV6 == addr.AddressFamily)
- continue;
- IPEndPoint ep = new IPEndPoint (addr, 53);
- if (eps.Contains (ep))
- continue;
-
- eps.Add (ep);
- }
- }
- endpoints = eps.ToArray ();
- }
- }
-}
-
+++ /dev/null
-//
-// Mono.Dns.SimpleResolverEventArgs
-//
-// Authors:
-// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
-//
-// Copyright 2011 Gonzalo Paniagua Javier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System;
-using System.Net;
-using System.Threading;
-
-namespace Mono.Dns {
- class SimpleResolverEventArgs : EventArgs {
- public event EventHandler<SimpleResolverEventArgs> Completed;
-
- public SimpleResolverEventArgs ()
- {
- }
-
- public ResolverError ResolverError { get; set; }
- public string ErrorMessage { get; set; }
- public ResolverAsyncOperation LastOperation;
- public string HostName { get; set; }
- public IPHostEntry HostEntry { get; internal set; }
- public object UserToken { get; set; }
- internal ushort QueryID;
- internal ushort Retries;
- internal Timer Timer;
- internal IPAddress PTRAddress;
-
- internal void Reset (ResolverAsyncOperation op)
- {
- ResolverError = 0;
- ErrorMessage = null;
- HostEntry = null;
- LastOperation = op;
- QueryID = 0;
- Retries = 0;
- PTRAddress = null;
- }
-
- protected internal void OnCompleted (object sender)
- {
- var handler = Completed;
- if (handler != null)
- handler (sender, this);
- }
- }
-}
-
--- /dev/null
+//
+// Mono.Net.Dns.DnsClass
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+namespace Mono.Net.Dns {
+ enum DnsClass : ushort {
+ Internet = 1,
+ IN = 1,
+ CSNET = 2,
+ CS = 2,
+ CHAOS = 3,
+ CH = 3,
+ Hesiod = 4,
+ HS = 4,
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.DnsHeader
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Mono.Net.Dns {
+ class DnsHeader {
+ public const int DnsHeaderLength = 12;
+ ArraySegment<byte> bytes;
+
+ public DnsHeader (byte [] bytes)
+ : this (bytes, 0)
+ {
+ }
+
+ public DnsHeader (byte [] bytes, int offset)
+ : this (new ArraySegment<byte> (bytes, offset, DnsHeaderLength))
+ {
+ }
+
+ public DnsHeader (ArraySegment<byte> segment)
+ {
+ if (segment.Count != DnsHeaderLength)
+ throw new ArgumentException ("Count must be 12", "segment");
+
+ bytes = segment;
+ }
+
+ public void Clear ()
+ {
+ for (int i = 0; i < DnsHeaderLength; i++)
+ bytes.Array [i + bytes.Offset] = 0;
+ }
+
+ public ushort ID {
+ get {
+ return (ushort)(bytes.Array [bytes.Offset] * 256 + bytes.Array [bytes.Offset + 1]);
+ }
+ set {
+ bytes.Array [bytes.Offset] = (byte) ((value & 0x0ff00) >> 8);
+ bytes.Array [bytes.Offset + 1] = (byte) (value & 0x0ff);
+ }
+ }
+
+ public bool IsQuery {
+ get { return ((bytes.Array [2 + bytes.Offset] & 0x80) != 0); }
+ set {
+ if (!value) {
+ bytes.Array [2 + bytes.Offset] |= 0x80;
+ } else {
+ bytes.Array [2 + bytes.Offset] &= 0x7f;
+ }
+ }
+ }
+
+ public DnsOpCode OpCode {
+ get { return (DnsOpCode) ((bytes.Array [2 + bytes.Offset] & 0x78) >> 3); }
+ set {
+ if (!Enum.IsDefined (typeof (DnsOpCode), value))
+ throw new ArgumentOutOfRangeException ("value", "Invalid DnsOpCode value");
+
+ int v = (int) value;
+ v <<= 3;
+ int prev = (bytes.Array [2 + bytes.Offset] & 0x87);
+ v |= prev;
+ bytes.Array [2 + bytes.Offset] = (byte) v;
+ }
+ }
+
+ public bool AuthoritativeAnswer {
+ get { return (bytes.Array [2 + bytes.Offset] & 4) != 0; }
+ set {
+ if(value) {
+ bytes.Array [2 + bytes.Offset] |= 4;
+ } else {
+ bytes.Array [2 + bytes.Offset] &= 0xFB;
+ }
+ }
+ }
+
+ public bool Truncation {
+ get { return (bytes.Array [2 + bytes.Offset] & 2) != 0; }
+ set {
+ if(value) {
+ bytes.Array [2 + bytes.Offset] |= 2;
+ } else {
+ bytes.Array [2 + bytes.Offset] &= 0xFD;
+ }
+ }
+ }
+
+ public bool RecursionDesired {
+ get { return (bytes.Array [2 + bytes.Offset] & 1) != 0; }
+ set {
+ if(value) {
+ bytes.Array [2 + bytes.Offset] |= 1;
+ } else {
+ bytes.Array [2 + bytes.Offset] &= 0xFE;
+ }
+ }
+ }
+
+ public bool RecursionAvailable {
+ get { return (bytes.Array [3 + bytes.Offset] & 0x80) != 0; }
+ set {
+ if(value) {
+ bytes.Array [3 + bytes.Offset] |= 0x80;
+ } else {
+ bytes.Array [3 + bytes.Offset] &= 0x7F;
+ }
+ }
+ }
+
+ // TODO: Add AuthenticData and Checking Disabled (bit 10 and 11 of Z)
+ public int ZReserved {
+ get { return (bytes.Array [3 + bytes.Offset] & 0x70) >> 4; }
+ set {
+ if(value < 0 || value > 7) {
+ throw new ArgumentOutOfRangeException("value", "Must be between 0 and 7");
+ }
+ bytes.Array [3 + bytes.Offset] &= 0x8F;
+ bytes.Array [3 + bytes.Offset] |= (byte) ((value << 4) & 0x70);
+ }
+ }
+
+ public DnsRCode RCode {
+ get { return (DnsRCode) (bytes.Array [3 + bytes.Offset] & 0x0f); }
+ set {
+ int v = (int)value;
+ //Info: Values > 15 are encoded in other records (OPT, TSIG, TKEY)
+ if (v < 0 || v > 15)
+ throw new ArgumentOutOfRangeException("value", "Must be between 0 and 15");
+
+ bytes.Array [3 + bytes.Offset] &= 0x0f;
+ bytes.Array [3 + bytes.Offset] |= (byte) v;
+ }
+ }
+
+ static ushort GetUInt16 (byte [] bytes, int offset)
+ {
+ return (ushort)(bytes [offset] * 256 + bytes [offset + 1]);
+ }
+
+ static void SetUInt16 (byte [] bytes, int offset, ushort val)
+ {
+ bytes [offset] = (byte) ((val & 0x0ff00) >> 8);
+ bytes [offset + 1] = (byte) (val & 0x0ff);
+ }
+
+ public ushort QuestionCount {
+ get { return GetUInt16 (bytes.Array, 4); }
+ set { SetUInt16 (bytes.Array, 4, value); }
+ }
+
+ public ushort AnswerCount {
+ get { return GetUInt16 (bytes.Array, 6); }
+ set { SetUInt16 (bytes.Array, 6, value); }
+ }
+
+ public ushort AuthorityCount {
+ get { return GetUInt16 (bytes.Array, 8); }
+ set { SetUInt16 (bytes.Array, 8, value); }
+ }
+
+ public ushort AdditionalCount {
+ get { return GetUInt16 (bytes.Array, 10); }
+ set { SetUInt16 (bytes.Array, 10, value); }
+ }
+
+ public override string ToString ()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.AppendFormat ("ID: {0} QR: {1} Opcode: {2} AA: {3} TC: {4} RD: {5} RA: {6} \r\nRCode: {7} ",
+ ID, IsQuery, OpCode, AuthoritativeAnswer, Truncation, RecursionDesired,
+ RecursionAvailable, RCode);
+ sb.AppendFormat ("Q: {0} A: {1} NS: {2} AR: {3}\r\n", QuestionCount, AnswerCount, AuthorityCount, AdditionalCount);
+ return sb.ToString();
+ }
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.DnsOpCode
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+namespace Mono.Net.Dns {
+ enum DnsOpCode : byte {
+ Query = 0,
+ [Obsolete] IQuery = 1,
+ Status = 2,
+ Notify = 4,
+ Update = 5,
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.DnsPacket
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+
+namespace Mono.Net.Dns {
+ abstract class DnsPacket {
+ protected byte [] packet;
+ protected int position;
+ protected DnsHeader header;
+
+ protected DnsPacket ()
+ {
+ // Caller has to initialize packet, position and header
+ }
+
+ protected DnsPacket (int length)
+ : this (new byte [length], length)
+ {
+ }
+
+ protected DnsPacket (byte [] buffer, int length)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException("buffer");
+ if (length <= 0)
+ throw new ArgumentOutOfRangeException("length", "Must be greater than zero.");
+
+ packet = buffer;
+ position = length;
+ header = new DnsHeader(new ArraySegment<byte>(packet, 0, 12));
+ }
+
+ public byte [] Packet {
+ get { return packet; }
+ }
+
+ public int Length {
+ get { return position; }
+ }
+
+ public DnsHeader Header {
+ get { return header; }
+ }
+
+ protected void WriteUInt16 (ushort v)
+ {
+ packet [position++] = (byte) ((v & 0x0ff00) >> 8);
+ packet [position++] = (byte) (v & 0x0ff);
+ }
+
+ protected void WriteStringBytes (string str, int offset, int count)
+ {
+ for (int i = offset, c = 0; c < count; c++, i++)
+ packet [position++] = (byte) str [i]; // Don't care about encoding.
+ }
+
+ protected void WriteLabel (string str, int offset, int count)
+ {
+ packet [position++] = (byte) count;
+ WriteStringBytes (str, offset, count);
+ }
+
+ protected void WriteDnsName (string name)
+ {
+ if (!DnsUtil.IsValidDnsName (name))
+ throw new ArgumentException ("Invalid DNS name");
+
+ if (!String.IsNullOrEmpty (name)) {
+ int len = name.Length;
+ int label_start = 0;
+ int label_len = 0;
+ for (int i = 0; i < len; i++) {
+ char c = name [i];
+ if (c != '.') {
+ label_len++;
+ } else {
+ if (i == 0)
+ break; // "."
+ WriteLabel (name, label_start, label_len);
+ label_start += label_len + 1; // Skip the dot
+ label_len = 0;
+ }
+ }
+ if (label_len > 0)
+ WriteLabel (name, label_start, label_len);
+ }
+
+ packet [position++] = 0;
+ }
+
+ protected internal string ReadName (ref int offset)
+ {
+ return DnsUtil.ReadName (packet, ref offset);
+ }
+
+ protected internal static string ReadName (byte [] buffer, ref int offset)
+ {
+ return DnsUtil.ReadName (buffer, ref offset);
+ }
+
+ protected internal ushort ReadUInt16 (ref int offset)
+ {
+ return (ushort)((packet[offset++] << 8) + packet[offset++]);
+ }
+
+ protected internal int ReadInt32 (ref int offset)
+ {
+ return (packet [offset++] << 24) + (packet [offset++] << 16) + (packet [offset++] << 8) + packet [offset++];
+ }
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.DnsQClass
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+namespace Mono.Net.Dns {
+ enum DnsQClass : ushort {
+ Internet = 1,
+ IN = 1,
+ CSNET = 2,
+ CS = 2,
+ CHAOS = 3,
+ CH = 3,
+ Hesiod = 4,
+ HS = 4,
+ None = 254,
+ Any = 255
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.DnsQType
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+namespace Mono.Net.Dns {
+ enum DnsQType : ushort {
+ A = 1,
+ NS = 2,
+ [Obsolete] MD = 3,
+ [Obsolete] MF = 4,
+ CNAME = 5,
+ SOA = 6,
+ [Obsolete] MB = 7,
+ [Obsolete] MG = 8,
+ [Obsolete] MR = 9,
+ [Obsolete] NULL = 10,
+ [Obsolete] WKS = 11,
+ PTR = 12,
+ [Obsolete] HINFO = 13,
+ [Obsolete] MINFO = 14,
+ MX = 15,
+ TXT = 16,
+ [Obsolete] RP = 17,
+ AFSDB = 18,
+ [Obsolete] X25 = 19,
+ [Obsolete] ISDN = 20,
+ [Obsolete] RT = 21,
+ [Obsolete] NSAP = 22,
+ [Obsolete] NSAPPTR = 23,
+ SIG = 24,
+ KEY = 25,
+ [Obsolete] PX = 26,
+ [Obsolete] GPOS = 27,
+ AAAA = 28,
+ LOC = 29,
+ [Obsolete] NXT = 30,
+ [Obsolete] EID = 31,
+ [Obsolete] NIMLOC = 32,
+ SRV = 33,
+ [Obsolete] ATMA = 34,
+ NAPTR = 35,
+ KX = 36,
+ CERT = 37,
+ [Obsolete] A6 = 38,
+ DNAME = 39,
+ [Obsolete] SINK = 40,
+ OPT = 41,
+ [Obsolete] APL = 42,
+ DS = 43,
+ SSHFP = 44,
+ IPSECKEY = 45,
+ RRSIG = 46,
+ NSEC = 47,
+ DNSKEY = 48,
+ DHCID = 49,
+ NSEC3 = 50,
+ NSEC3PARAM = 51,
+ HIP = 55,
+ NINFO = 56,
+ RKEY = 57,
+ TALINK = 58,
+ SPF = 99,
+ [Obsolete] UINFO = 100,
+ [Obsolete] UID = 101,
+ [Obsolete] GID = 102,
+ [Obsolete] UNSPEC = 103,
+ TKEY = 249,
+ TSIG = 250,
+ IXFR = 251,
+ AXFR = 252,
+ [Obsolete] MAILB = 253,
+ [Obsolete] MAILA = 254,
+ ALL = 255,
+ URI = 256,
+ TA = 32768,
+ DLV = 32769,
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.DnsQuery
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Mono.Net.Dns {
+ class DnsQuery : DnsPacket {
+ public DnsQuery (string name, DnsQType qtype, DnsQClass qclass)
+ {
+ if (String.IsNullOrEmpty (name))
+ throw new ArgumentNullException ("name");
+
+ int length = DnsUtil.GetEncodedLength (name);
+ if (length == -1)
+ throw new ArgumentException ("Invalid DNS name", "name");
+
+ length += 12 + 2 + 2; // Header + qtype + qclass
+ packet = new byte [length];
+ header = new DnsHeader (packet, 0);
+ position = 12;
+ WriteDnsName (name);
+ WriteUInt16 ((ushort) qtype);
+ WriteUInt16 ((ushort) qclass);
+ Header.QuestionCount = 1;
+ Header.IsQuery = true;
+ Header.RecursionDesired = true;
+ }
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.DnsQuestion
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Mono.Net.Dns {
+ class DnsQuestion {
+ string name;
+ DnsQType type;
+ DnsQClass _class;
+
+ internal DnsQuestion ()
+ {
+ }
+
+ internal int Init (DnsPacket packet, int offset)
+ {
+ name = packet.ReadName (ref offset);
+ type = (DnsQType) packet.ReadUInt16 (ref offset);
+ _class = (DnsQClass) packet.ReadUInt16 (ref offset);
+ return offset;
+ }
+
+ public string Name {
+ get { return name; }
+ }
+
+ public DnsQType Type {
+ get { return type; }
+ }
+
+ public DnsQClass Class {
+ get { return _class; }
+ }
+
+ public override string ToString() {
+ return String.Format("Name: {0} Type: {1} Class: {2}", Name, Type, Class);
+ }
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.DnsRCode
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+namespace Mono.Net.Dns {
+ enum DnsRCode : ushort {
+ NoError = 0,
+ FormErr = 1,
+ ServFail = 2,
+ NXDomain = 3,
+ NotImp = 4,
+ Refused = 5,
+ YXDomain = 6,
+ YXRRSet = 7,
+ NXRRSet = 8,
+ NotAuth = 9,
+ NotZone = 10,
+ BadVers = 16,
+ BadSig = 16,
+ BadKey = 17,
+ BadTime = 18,
+ BadMode = 19,
+ BadName = 20,
+ BadAlg = 21,
+ BadTrunc = 22,
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.DnsResourceRecord
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Mono.Net.Dns {
+ class DnsResourceRecord {
+ string name;
+ DnsType type;
+ DnsClass klass;
+ int ttl;
+ ushort rdlength;
+ ArraySegment<byte> m_rdata;
+
+ internal DnsResourceRecord() {
+ }
+
+ internal void CopyFrom(DnsResourceRecord rr) {
+ name = rr.name;
+ type = rr.type;
+ klass = rr.klass;
+ ttl = rr.ttl;
+ rdlength = rr.rdlength;
+ m_rdata = rr.m_rdata;
+ }
+
+ static internal DnsResourceRecord CreateFromBuffer(DnsPacket packet, int size, ref int offset) {
+ string pname = packet.ReadName(ref offset);
+ DnsType ptype = (DnsType)packet.ReadUInt16(ref offset);
+ DnsClass pclass = (DnsClass)packet.ReadUInt16(ref offset);
+ int pttl = packet.ReadInt32(ref offset);
+ ushort prdlength = packet.ReadUInt16(ref offset);
+ DnsResourceRecord rr = new DnsResourceRecord();
+ rr.name = pname;
+ rr.type = ptype;
+ rr.klass = pclass;
+ rr.ttl = pttl;
+ rr.rdlength = prdlength;
+ rr.m_rdata = new ArraySegment<byte>(packet.Packet, offset, prdlength);
+ offset += prdlength;
+
+ switch(pclass) {
+ case DnsClass.IN:
+ switch(ptype) {
+ case DnsType.A:
+ rr = new DnsResourceRecordA(rr);
+ break;
+ case DnsType.AAAA:
+ rr = new DnsResourceRecordAAAA(rr);
+ break;
+ case DnsType.CNAME:
+ rr = new DnsResourceRecordCName(rr);
+ break;
+ case DnsType.PTR:
+ rr = new DnsResourceRecordPTR(rr);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return rr;
+ }
+
+ public string Name {
+ get { return name; }
+ }
+
+ public DnsType Type {
+ get { return type; }
+ }
+
+ public DnsClass Class {
+ get { return klass; }
+ }
+
+ public int Ttl {
+ get { return ttl; }
+ }
+
+ public ArraySegment<byte> Data {
+ get { return m_rdata; }
+ }
+
+ public override string ToString() {
+ return String.Format("Name: {0}, Type: {1}, Class: {2}, Ttl: {3}, Data length: {4}", name, type, klass, ttl, Data.Count);
+ }
+ }
+}
--- /dev/null
+//
+// Mono.Net.Dns.DnsResourceRecordA
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Text;
+
+namespace Mono.Net.Dns {
+ class DnsResourceRecordA : DnsResourceRecordIPAddress {
+ internal DnsResourceRecordA (DnsResourceRecord rr)
+ : base (rr, 4)
+ {
+ }
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.DnsResourceRecordAAAA
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Text;
+
+namespace Mono.Net.Dns {
+ class DnsResourceRecordAAAA : DnsResourceRecordIPAddress {
+ internal DnsResourceRecordAAAA (DnsResourceRecord rr)
+ : base (rr, 16)
+ {
+ }
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.DnsResourceRecordCName
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Mono.Net.Dns {
+ class DnsResourceRecordCName : DnsResourceRecord {
+ string cname;
+
+ internal DnsResourceRecordCName (DnsResourceRecord rr)
+ {
+ CopyFrom (rr);
+ int offset = rr.Data.Offset;
+ cname = DnsPacket.ReadName (rr.Data.Array, ref offset);
+ }
+
+ public string CName {
+ get { return cname; }
+ }
+
+ public override string ToString ()
+ {
+ return base.ToString () + " CNAME: " + cname.ToString ();
+ }
+ }
+}
--- /dev/null
+//
+// Mono.Net.Dns.DnsResourceRecordIPAddress
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Text;
+
+namespace Mono.Net.Dns {
+ abstract class DnsResourceRecordIPAddress : DnsResourceRecord {
+ IPAddress address;
+
+ internal DnsResourceRecordIPAddress (DnsResourceRecord rr, int address_size)
+ {
+ CopyFrom (rr);
+ ArraySegment<byte> segment = rr.Data;
+ byte [] bytes = new byte [address_size];
+ Buffer.BlockCopy (segment.Array, segment.Offset, bytes, 0, address_size);
+ address = new IPAddress (bytes);
+ }
+
+ public override string ToString ()
+ {
+ return base.ToString() + " Address: " + address;
+ }
+
+ public IPAddress Address {
+ get { return address; }
+ }
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.DnsResourceRecordPTR
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Mono.Net.Dns {
+ class DnsResourceRecordPTR : DnsResourceRecord {
+ string dname;
+
+ internal DnsResourceRecordPTR (DnsResourceRecord rr)
+ {
+ CopyFrom (rr);
+ int offset = rr.Data.Offset;
+ dname = DnsPacket.ReadName (rr.Data.Array, ref offset);
+ }
+
+ public string DName {
+ get { return dname; }
+ }
+
+ public override string ToString() {
+ return base.ToString () + " DNAME: " + dname.ToString ();
+ }
+ }
+}
--- /dev/null
+//
+// Mono.Net.Dns.DnsResponse
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Text;
+
+namespace Mono.Net.Dns {
+ class DnsResponse : DnsPacket {
+ static readonly ReadOnlyCollection<DnsResourceRecord> EmptyRR = new ReadOnlyCollection<DnsResourceRecord> (new DnsResourceRecord [0]);
+ static readonly ReadOnlyCollection<DnsQuestion> EmptyQS = new ReadOnlyCollection<DnsQuestion> (new DnsQuestion [0]);
+
+ ReadOnlyCollection<DnsQuestion> question;
+ ReadOnlyCollection<DnsResourceRecord> answer;
+ ReadOnlyCollection<DnsResourceRecord> authority;
+ ReadOnlyCollection<DnsResourceRecord> additional;
+ int offset = DnsHeader.DnsHeaderLength;
+
+ public DnsResponse (byte [] buffer, int length)
+ : base (buffer, length)
+ {
+ }
+
+ public void Reset ()
+ {
+ question = null;
+ answer = null;
+ authority = null;
+ additional = null;
+ for (int i = 0; i < packet.Length; i++)
+ packet [i] = 0;
+ }
+
+ ReadOnlyCollection<DnsResourceRecord> GetRRs (int count)
+ {
+ if (count <= 0)
+ return EmptyRR;
+
+ List<DnsResourceRecord> records = new List<DnsResourceRecord>(count);
+ for (int i = 0; i < count; i++)
+ records.Add (DnsResourceRecord.CreateFromBuffer (this, position, ref offset));
+ return records.AsReadOnly ();
+ }
+
+ ReadOnlyCollection<DnsQuestion> GetQuestions (int count)
+ {
+ if (count <= 0)
+ return EmptyQS;
+
+ List<DnsQuestion> records = new List<DnsQuestion> (count);
+ for(int i = 0; i < count; i++) {
+ DnsQuestion record = new DnsQuestion ();
+ offset = record.Init (this, offset);
+ records.Add (record);
+ }
+ return records.AsReadOnly ();
+ }
+
+ public ReadOnlyCollection<DnsQuestion> GetQuestions ()
+ {
+ if (question == null)
+ question = GetQuestions (Header.QuestionCount);
+ return question;
+ }
+
+ public ReadOnlyCollection<DnsResourceRecord> GetAnswers ()
+ {
+ if (answer == null) {
+ GetQuestions ();
+ answer = GetRRs (Header.AnswerCount);
+ }
+ return answer;
+ }
+
+ public ReadOnlyCollection<DnsResourceRecord> GetAuthority ()
+ {
+ if (authority == null) {
+ GetQuestions ();
+ GetAnswers ();
+ authority = GetRRs (Header.AuthorityCount);
+ }
+ return authority;
+ }
+
+ public ReadOnlyCollection<DnsResourceRecord> GetAdditional ()
+ {
+ if (additional == null) {
+ GetQuestions ();
+ GetAnswers ();
+ GetAuthority ();
+ additional = GetRRs (Header.AdditionalCount);
+ }
+ return additional;
+ }
+
+ public override string ToString ()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(Header);
+ sb.Append("Question:\r\n");
+ foreach(DnsQuestion q in GetQuestions()) {
+ sb.AppendFormat("\t{0}\r\n", q);
+ }
+ sb.Append("Answer(s):\r\n");
+ foreach(DnsResourceRecord q in GetAnswers()) {
+ sb.AppendFormat("\t{0}\r\n", q);
+ }
+ sb.Append("Authority:\r\n");
+ foreach(DnsResourceRecord q in GetAuthority()) {
+ sb.AppendFormat("\t{0}\r\n", q);
+ }
+ sb.Append("Additional:\r\n");
+ foreach(DnsResourceRecord q in GetAdditional()) {
+ sb.AppendFormat("\t{0}\r\n", q);
+ }
+ return sb.ToString();
+ }
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.DnsType
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+namespace Mono.Net.Dns {
+ enum DnsType : ushort {
+ A = 1,
+ NS = 2,
+ [Obsolete] MD = 3,
+ [Obsolete] MF = 4,
+ CNAME = 5,
+ SOA = 6,
+ [Obsolete] MB = 7,
+ [Obsolete] MG = 8,
+ [Obsolete] MR = 9,
+ [Obsolete] NULL = 10,
+ [Obsolete] WKS = 11,
+ PTR = 12,
+ [Obsolete] HINFO = 13,
+ [Obsolete] MINFO = 14,
+ MX = 15,
+ TXT = 16,
+ [Obsolete] RP = 17,
+ AFSDB = 18,
+ [Obsolete] X25 = 19,
+ [Obsolete] ISDN = 20,
+ [Obsolete] RT = 21,
+ [Obsolete] NSAP = 22,
+ [Obsolete] NSAPPTR = 23,
+ SIG = 24,
+ KEY = 25,
+ [Obsolete] PX = 26,
+ [Obsolete] GPOS = 27,
+ AAAA = 28,
+ LOC = 29,
+ [Obsolete] NXT = 30,
+ [Obsolete] EID = 31,
+ [Obsolete] NIMLOC = 32,
+ SRV = 33,
+ [Obsolete] ATMA = 34,
+ NAPTR = 35,
+ KX = 36,
+ CERT = 37,
+ [Obsolete] A6 = 38,
+ DNAME = 39,
+ [Obsolete] SINK = 40,
+ OPT = 41,
+ [Obsolete] APL = 42,
+ DS = 43,
+ SSHFP = 44,
+ IPSECKEY = 45,
+ RRSIG = 46,
+ NSEC = 47,
+ DNSKEY = 48,
+ DHCID = 49,
+ NSEC3 = 50,
+ NSEC3PARAM = 51,
+ HIP = 55,
+ NINFO = 56,
+ RKEY = 57,
+ TALINK = 58,
+ SPF = 99,
+ [Obsolete] UINFO = 100,
+ [Obsolete] UID = 101,
+ [Obsolete] GID = 102,
+ [Obsolete] UNSPEC = 103,
+ TKEY = 249,
+ TSIG = 250,
+ IXFR = 251,
+ AXFR = 252,
+ [Obsolete] MAILB = 253,
+ [Obsolete] MAILA = 254,
+ URI = 256,
+ TA = 32768,
+ DLV = 32769,
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.DnsUtil
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Mono.Net.Dns {
+ static class DnsUtil {
+ // RFC 2181 - Section 11
+ public static bool IsValidDnsName (string name)
+ {
+ if (name == null)
+ return false;
+
+ int len = name.Length;
+ if (len > 255)
+ return false;
+ int part_length = 0;
+ for (int i = 0; i < len; i++) {
+ char c = name [i];
+ if (c == '.') {
+ if (i == 0 && len > 1)
+ return false; // Can't begin with a dot unless it's "."
+ if (i > 0 && part_length == 0)
+ return false; // No ".." allowed
+ part_length = 0;
+ continue;
+ }
+ part_length++;
+ if (part_length > 63)
+ return false;
+ }
+ return true;
+ }
+
+ public static int GetEncodedLength (string name)
+ {
+ if (!IsValidDnsName (name))
+ return -1;
+
+ if (name == String.Empty)
+ return 1;
+
+ int len = name.Length;
+ if (name [len - 1] == '.')
+ return len + 1; // (length + label + ... + \0)
+ return len + 2; // need 1 more for the second to last label length
+ }
+
+ public static int GetNameLength (byte [] buffer)
+ {
+ return GetNameLength (buffer, 0);
+ }
+
+ public static int GetNameLength (byte [] buffer, int offset)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+ if (offset < 0 || offset >= buffer.Length)
+ throw new ArgumentOutOfRangeException ("offset");
+
+ int i = 0;
+ int len = 0;
+ while (len < 256) {
+ i = buffer [offset++];
+ if (i == 0)
+ return len > 0 ? --len : 0;
+ int ptr = i & 0x0C0;
+ if (ptr == 0x0C0) {
+ i = ((ptr & 0x3F) << 8) + buffer[offset++];
+ offset = i;
+ continue;
+ } else if (ptr >= 0x40) {
+ return -2; // Invalid ptr
+ }
+ len += i + 1;
+ offset += i;
+ }
+ return -1; // Invalid length
+ }
+
+ public static string ReadName (byte [] buffer, ref int offset)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+ if (offset < 0 || offset >= buffer.Length)
+ throw new ArgumentOutOfRangeException ("offset");
+
+ StringBuilder sb = new StringBuilder (32);
+ int i = 0;
+ bool no_ptr = true;
+ int off = offset;
+ while (sb.Length < 256) {
+ i = buffer [off++];
+ if (no_ptr) offset++;
+ if (i == 0) {
+ if (sb.Length > 0)
+ sb.Length--;
+ return sb.ToString ();
+ }
+ int ptr = i & 0x0C0;
+ if (ptr == 0x0C0) {
+ i = ((ptr & 0x3F) << 8) + buffer [off];
+ if (no_ptr) offset++;
+ no_ptr = false;
+ off = i;
+ continue;
+ } else if (i >= 0x40) {
+ return null; // Invalid ptr
+ }
+
+ for (int k = 0; k < i; k++)
+ sb.Append ((char) buffer [off + k]);
+ sb.Append ('.');
+ off += i;
+ if (no_ptr) offset += i;
+ }
+ return null; // never reached
+ }
+
+ }
+}
+
--- /dev/null
+SOURCES= \
+ DnsClass.cs \
+ DnsHeader.cs \
+ DnsPacket.cs \
+ DnsQClass.cs \
+ DnsQType.cs \
+ DnsQuery.cs \
+ DnsQuestion.cs \
+ DnsResourceRecordA.cs \
+ DnsResourceRecordCName.cs \
+ DnsResourceRecordPTR.cs \
+ DnsResourceRecord.cs \
+ DnsResponse.cs \
+ DnsType.cs \
+ ResolverAsyncOperation.cs \
+ Resolver.cs \
+ ResolverError.cs \
+ SimpleResolverEventArgs.cs
+
+EXES = resolver.exe \
+ plainolddns.exe
+
+all: $(EXES)
+
+resolver.exe: $(SOURCES)
+ @gmcs -out:$@ -debug $(SOURCES)
+
+plainolddns.exe: plainolddns.cs
+ @gmcs -out:$@ -debug $^
+clean:
+ rm -f resolver.exe* plainolddns.exe* *.mdb
--- /dev/null
+//
+// Mono.Net.Dns.ResolverAsyncOperation
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+namespace Mono.Net.Dns {
+ enum ResolverAsyncOperation {
+ None,
+ GetHostEntry,
+ GetHostAddresses,
+ }
+}
+
--- /dev/null
+// Mono.Net.Dns.ResolverError
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+namespace Mono.Net.Dns {
+ enum ResolverError {
+ NoError, // From DNS server
+ FormatError, //
+ ServerFailure, //
+ NameError, //
+ NotImplemented, //
+ Refused, //
+ // Resolver specific
+ ResponseHeaderError,
+ ResponseFormatError,
+ Timeout,
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.SimpleResolver
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Net;
+using System.Net.Sockets;
+using System.Net.NetworkInformation;
+using System.Text;
+using System.Threading;
+
+namespace Mono.Net.Dns {
+ sealed class SimpleResolver : IDisposable {
+ static string [] EmptyStrings = new string [0];
+ static IPAddress [] EmptyAddresses = new IPAddress [0];
+ IPEndPoint [] endpoints;
+ Socket client;
+ Dictionary<int, SimpleResolverEventArgs> queries;
+ AsyncCallback receive_cb;
+ TimerCallback timeout_cb;
+ bool disposed;
+#if REUSE_RESPONSES
+ Stack<DnsResponse> responses_avail = new Stack<DnsResponse> ();
+#endif
+
+ public SimpleResolver ()
+ {
+ queries = new Dictionary<int, SimpleResolverEventArgs> ();
+ receive_cb = new AsyncCallback (OnReceive);
+ timeout_cb = new TimerCallback (OnTimeout);
+ InitFromSystem ();
+ InitSocket ();
+ }
+
+ void IDisposable.Dispose ()
+ {
+ if (!disposed) {
+ disposed = true;
+ if (client != null) {
+ client.Close ();
+ client = null;
+ }
+ }
+ }
+
+ public void Close ()
+ {
+ ((IDisposable) this).Dispose ();
+ }
+
+ void GetLocalHost (SimpleResolverEventArgs args)
+ {
+ //FIXME
+ IPHostEntry entry = new IPHostEntry ();
+ entry.HostName = "localhost";
+ entry.AddressList = new IPAddress [] { IPAddress.Loopback };
+ entry.Aliases = EmptyStrings;
+ args.ResolverError = 0;
+ args.HostEntry = entry;
+ return;
+
+/*
+ List<IPEndPoint> eps = new List<IPEndPoint> ();
+ foreach (NetworkInterface iface in NetworkInterface.GetAllNetworkInterfaces ()) {
+ if (NetworkInterfaceType.Loopback == iface.NetworkInterfaceType)
+ continue;
+
+ foreach (IPAddress addr in iface.GetIPProperties ().DnsAddresses) {
+ if (AddressFamily.InterNetworkV6 == addr.AddressFamily)
+ continue;
+ IPEndPoint ep = new IPEndPoint (addr, 53);
+ if (eps.Contains (ep))
+ continue;
+
+ eps.Add (ep);
+ }
+ }
+ endpoints = eps.ToArray ();
+*/
+ }
+
+ // Type A query
+ // Might fill in Aliases
+ // -IPAddress -> return the same IPAddress
+ // -"" -> Local host ip addresses (filter out IPv6 if needed)
+ public bool GetHostAddressesAsync (SimpleResolverEventArgs args)
+ {
+ if (args == null)
+ throw new ArgumentNullException ("args");
+
+ if (args.HostName == null)
+ throw new ArgumentNullException ("args.HostName is null");
+
+ if (args.HostName.Length > 255)
+ throw new ArgumentException ("args.HostName is too long");
+
+ args.Reset (ResolverAsyncOperation.GetHostAddresses);
+ string host = args.HostName;
+ if (host == "") {
+ GetLocalHost (args);
+ return false;
+ }
+ IPAddress addr;
+ if (IPAddress.TryParse (host, out addr)) {
+ IPHostEntry entry = new IPHostEntry ();
+ entry.HostName = host;
+ entry.Aliases = EmptyStrings;
+ entry.AddressList = new IPAddress [1] { addr };
+ args.HostEntry = entry;
+ return false;
+ }
+
+ SendAQuery (args, true);
+ return true;
+ }
+
+ // For names -> type A Query
+ // For IP addresses -> PTR + A -> will at least return itself
+ // Careful: for IP addresses with PTR, the hostname might yield different IP addresses!
+ public bool GetHostEntryAsync (SimpleResolverEventArgs args)
+ {
+ if (args == null)
+ throw new ArgumentNullException ("args");
+
+ if (args.HostName == null)
+ throw new ArgumentNullException ("args.HostName is null");
+
+ if (args.HostName.Length > 255)
+ throw new ArgumentException ("args.HostName is too long");
+
+ args.Reset (ResolverAsyncOperation.GetHostEntry);
+ string host = args.HostName;
+ if (host == "") {
+ GetLocalHost (args);
+ return false;
+ }
+
+ IPAddress addr;
+ if (IPAddress.TryParse (host, out addr)) {
+ IPHostEntry entry = new IPHostEntry ();
+ entry.HostName = host;
+ entry.Aliases = EmptyStrings;
+ entry.AddressList = new IPAddress [1] { addr };
+ args.HostEntry = entry;
+ args.PTRAddress = addr;
+ SendPTRQuery (args, true);
+ return true;
+ }
+
+ // 3. For IP addresses:
+ // 3.1 Parsing IP succeeds
+ // 3.2 Reverse lookup of the IP fills in HostName -> fails? HostName = IP
+ // 3.3 The hostname resulting from this is used to query DNS again to get the IP addresses
+ //
+ // Exclude IPv6 addresses if not supported by the system
+ // .Aliases is always empty
+ // Length > 255
+ SendAQuery (args, true);
+ return true;
+ }
+
+ bool AddQuery (DnsQuery query, SimpleResolverEventArgs args)
+ {
+ lock (queries) {
+ if (queries.ContainsKey (query.Header.ID))
+ return false;
+ queries [query.Header.ID] = args;
+ }
+ return true;
+ }
+
+ static DnsQuery GetQuery (string host, DnsQType q, DnsQClass c)
+ {
+ return new DnsQuery (host, q, c);
+ }
+
+ void SendAQuery (SimpleResolverEventArgs args, bool add_it)
+ {
+ SendAQuery (args, args.HostName, add_it);
+ }
+
+ void SendAQuery (SimpleResolverEventArgs args, string host, bool add_it)
+ {
+ DnsQuery query = GetQuery (host, DnsQType.A, DnsQClass.IN);
+ SendQuery (args, query, add_it);
+ }
+
+ static string GetPTRName (IPAddress address)
+ {
+ // TODO: IPv6 PTR query?
+ byte [] bytes = address.GetAddressBytes ();
+ // "XXX.XXX.XXX.XXX.in-addr.arpa".Length
+ StringBuilder sb = new StringBuilder (28);
+ for (int i = bytes.Length - 1; i >= 0; i--) {
+ sb.AppendFormat ("{0}.", bytes [i]);
+ }
+ sb.Append ("in-addr.arpa");
+ return sb.ToString ();
+ }
+
+ void SendPTRQuery (SimpleResolverEventArgs args, bool add_it)
+ {
+ DnsQuery query = GetQuery (GetPTRName (args.PTRAddress), DnsQType.PTR, DnsQClass.IN);
+ SendQuery (args, query, add_it);
+ }
+
+ void SendQuery (SimpleResolverEventArgs args, DnsQuery query, bool add_it)
+ {
+ // TODO: not sure about reusing IDs when add_it == false
+ int count = 0;
+ if (add_it) {
+ do {
+ query.Header.ID = (ushort)new Random().Next(1, 65534);
+ if (count > 500)
+ throw new InvalidOperationException ("Too many pending queries (or really bad luck)");
+ } while (AddQuery (query, args) == false);
+ args.QueryID = query.Header.ID;
+ } else {
+ query.Header.ID = args.QueryID;
+ }
+ if (args.Timer == null)
+ args.Timer = new Timer (timeout_cb, args, 5000, Timeout.Infinite);
+ else
+ args.Timer.Change (5000, Timeout.Infinite);
+ client.BeginSend (query.Packet, 0, query.Length, SocketFlags.None, null, null);
+ }
+
+ byte [] GetFreshBuffer ()
+ {
+#if !REUSE_RESPONSES
+ return new byte [512];
+#else
+
+ DnsResponse response = null;
+ lock (responses_avail) {
+ if (responses_avail.Count > 0) {
+ response = responses_avail.Pop ();
+ }
+ }
+ if (response == null) {
+ response = new DnsResponse ();
+ } else {
+ response.Reset ();
+ }
+ return response;
+#endif
+ }
+
+ void FreeBuffer (byte [] buffer)
+ {
+#if REUSE_RESPONSES
+ // TODO: set some limit here. Configurable?
+ lock (responses_avail) {
+ responses_avail.Push (response);
+ }
+#endif
+ }
+
+ void InitSocket ()
+ {
+ client = new Socket (AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ client.Blocking = true;
+ client.Bind (new IPEndPoint (IPAddress.Any, 0));
+ client.Connect (endpoints [0]);
+ BeginReceive ();
+ }
+
+ void BeginReceive ()
+ {
+ byte [] buffer = GetFreshBuffer ();
+ client.BeginReceive (buffer, 0, buffer.Length, SocketFlags.None, receive_cb, buffer);
+ }
+
+ void OnTimeout (object obj)
+ {
+ SimpleResolverEventArgs args = (SimpleResolverEventArgs) obj;
+ SimpleResolverEventArgs args2;
+ lock (queries) {
+ if (!queries.TryGetValue (args.QueryID, out args2)) {
+ return; // Already processed.
+ }
+ if (args != args2)
+ throw new Exception ("Should not happen: args != args2");
+ args.Retries++;
+ if (args.Retries > 1) {
+ // Error timeout
+ args.ResolverError = ResolverError.Timeout;
+ args.OnCompleted (this);
+ } else {
+ SendAQuery (args, false);
+ }
+ }
+ }
+
+ void OnReceive (IAsyncResult ares)
+ {
+ if (disposed)
+ return;
+
+ int nread = 0;
+ EndPoint remote_ep = client.RemoteEndPoint;
+ try {
+ nread = client.EndReceive (ares);
+ } catch (Exception e) {
+ Console.Error.WriteLine (e);
+ }
+
+ BeginReceive ();
+
+ byte [] buffer = (byte []) ares.AsyncState;
+ if (nread > 12) {
+ DnsResponse response = new DnsResponse (buffer, nread);
+ int id = response.Header.ID;
+ SimpleResolverEventArgs args = null;
+ lock (queries) {
+ if (queries.TryGetValue (id, out args)) {
+ queries.Remove (id);
+ }
+ }
+
+ if (args != null) {
+ Timer t = args.Timer;
+ if (t != null)
+ t.Change (Timeout.Infinite, Timeout.Infinite);
+
+ try {
+ ProcessResponse (args, response, remote_ep);
+ } catch (Exception e) {
+ args.ResolverError = (ResolverError) (-1);
+ args.ErrorMessage = e.Message;
+ }
+
+ IPHostEntry entry = args.HostEntry;
+ if (args.ResolverError != 0 && args.PTRAddress != null && entry != null && entry.HostName != null) {
+ args.PTRAddress = null;
+ SendAQuery (args, entry.HostName, true);
+ args.Timer.Change (5000, Timeout.Infinite);
+ } else {
+ args.OnCompleted (this);
+ }
+ }
+ }
+ FreeBuffer (buffer);
+ }
+
+ void ProcessResponse (SimpleResolverEventArgs args, DnsResponse response, EndPoint server_ep)
+ {
+ DnsRCode status = response.Header.RCode;
+ if (status != 0) {
+ if (args.PTRAddress != null) {
+ // PTR query failed -> no error, we have the IP
+ return;
+ }
+ args.ResolverError = (ResolverError) status;
+ return;
+ }
+
+ // TODO: verify IP of the server is in our list and the same one that got the query
+ IPEndPoint ep = (IPEndPoint) server_ep;
+ if (ep.Port != 53) {
+ args.ResolverError = ResolverError.ResponseHeaderError;
+ args.ErrorMessage = "Port";
+ return;
+ }
+
+ DnsHeader header = response.Header;
+ if (!header.IsQuery) {
+ args.ResolverError = ResolverError.ResponseHeaderError;
+ args.ErrorMessage = "IsQuery";
+ return;
+ }
+
+ // TODO: handle Truncation. Retry with bigger buffer?
+
+ if (header.QuestionCount > 1) {
+ args.ResolverError = ResolverError.ResponseHeaderError;
+ args.ErrorMessage = "QuestionCount";
+ return;
+ }
+ ReadOnlyCollection<DnsQuestion> q = response.GetQuestions ();
+ if (q.Count != 1) {
+ args.ResolverError = ResolverError.ResponseHeaderError;
+ args.ErrorMessage = "QuestionCount 2";
+ return;
+ }
+ DnsQuestion question = q [0];
+ /* The answer might have dot at the end, etc...
+ if (String.Compare (question.Name, args.HostName) != 0) {
+ args.ResolverError = ResolverError.ResponseHeaderError;
+ args.ErrorMessage = "HostName - " + question.Name + " != " + args.HostName;
+ return;
+ }
+ */
+
+ DnsQType t = question.Type;
+ if (t != DnsQType.A && t != DnsQType.AAAA && t != DnsQType.PTR) {
+ args.ResolverError = ResolverError.ResponseHeaderError;
+ args.ErrorMessage = "QType " + question.Type;
+ return;
+ }
+
+ if (question.Class != DnsQClass.IN) {
+ args.ResolverError = ResolverError.ResponseHeaderError;
+ args.ErrorMessage = "QClass " + question.Class;
+ return;
+ }
+
+ ReadOnlyCollection<DnsResourceRecord> records = response.GetAnswers ();
+ if (records.Count == 0) {
+ if (args.PTRAddress != null) {
+ // PTR query failed -> no error
+ return;
+ }
+ args.ResolverError = ResolverError.NameError; // is this ok?
+ args.ErrorMessage = "NoAnswers";
+ return;
+ }
+
+ List<string> aliases = null;
+ List<IPAddress> addresses = null;
+ foreach (DnsResourceRecord r in records) {
+ if (r.Class != DnsClass.IN)
+ continue;
+ if (r.Type == DnsType.A || r.Type == DnsType.AAAA) {
+ if (addresses == null)
+ addresses = new List<IPAddress> ();
+ addresses.Add (((DnsResourceRecordIPAddress) r).Address);
+ } else if (r.Type == DnsType.CNAME) {
+ if (aliases == null)
+ aliases = new List<string> ();
+ aliases.Add (((DnsResourceRecordCName) r).CName);
+ } else if (r.Type == DnsType.PTR) {
+ args.HostEntry.HostName = ((DnsResourceRecordPTR) r).DName;
+ args.HostEntry.Aliases = aliases == null ? EmptyStrings : aliases.ToArray ();
+ args.HostEntry.AddressList = EmptyAddresses;
+ return;
+ }
+ }
+
+ IPHostEntry entry = args.HostEntry ?? new IPHostEntry ();
+ if (entry.HostName == null && aliases != null && aliases.Count > 0) {
+ entry.HostName = aliases [0];
+ aliases.RemoveAt (0);
+ }
+ entry.Aliases = aliases == null ? EmptyStrings : aliases.ToArray ();
+ entry.AddressList = addresses == null ? EmptyAddresses : addresses.ToArray ();
+ args.HostEntry = entry;
+ if ((question.Type == DnsQType.A || question.Type == DnsQType.AAAA) && entry.AddressList == EmptyAddresses) {
+ args.ResolverError = ResolverError.NameError;
+ args.ErrorMessage = "No addresses in response";
+ } else if (question.Type == DnsQType.PTR && entry.HostName == null) {
+ args.ResolverError = ResolverError.NameError;
+ args.ErrorMessage = "No PTR in response";
+ }
+
+ }
+
+ void InitFromSystem ()
+ {
+ List<IPEndPoint> eps = new List<IPEndPoint> ();
+ foreach (NetworkInterface iface in NetworkInterface.GetAllNetworkInterfaces ()) {
+ if (NetworkInterfaceType.Loopback == iface.NetworkInterfaceType)
+ continue;
+
+ foreach (IPAddress addr in iface.GetIPProperties ().DnsAddresses) {
+ if (AddressFamily.InterNetworkV6 == addr.AddressFamily)
+ continue;
+ IPEndPoint ep = new IPEndPoint (addr, 53);
+ if (eps.Contains (ep))
+ continue;
+
+ eps.Add (ep);
+ }
+ }
+ endpoints = eps.ToArray ();
+ }
+ }
+}
+
--- /dev/null
+//
+// Mono.Net.Dns.SimpleResolverEventArgs
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
+//
+// Copyright 2011 Gonzalo Paniagua Javier
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+using System;
+using System.Net;
+using System.Threading;
+
+namespace Mono.Net.Dns {
+ class SimpleResolverEventArgs : EventArgs {
+ public event EventHandler<SimpleResolverEventArgs> Completed;
+
+ public SimpleResolverEventArgs ()
+ {
+ }
+
+ public ResolverError ResolverError { get; set; }
+ public string ErrorMessage { get; set; }
+ public ResolverAsyncOperation LastOperation;
+ public string HostName { get; set; }
+ public IPHostEntry HostEntry { get; internal set; }
+ public object UserToken { get; set; }
+ internal ushort QueryID;
+ internal ushort Retries;
+ internal Timer Timer;
+ internal IPAddress PTRAddress;
+
+ internal void Reset (ResolverAsyncOperation op)
+ {
+ ResolverError = 0;
+ ErrorMessage = null;
+ HostEntry = null;
+ LastOperation = op;
+ QueryID = 0;
+ Retries = 0;
+ PTRAddress = null;
+ }
+
+ protected internal void OnCompleted (object sender)
+ {
+ var handler = Completed;
+ if (handler != null)
+ handler (sender, this);
+ }
+ }
+}
+
using System.Threading.Tasks;
#endif
-using Mono.Dns;
+using Mono.Net.Dns;
namespace System.Net {
public static class Dns {
// System.Net.DnsAsyncResult
//
// Authors:
-// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+// Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
//
-// (C) 2003 Ximian, Inc (http://www.ximian.com)
+// Copyright (c) 2011 Gonzalo Paniagua Javier
//
//
using System.IO;
using System.Threading;
-using Mono.Dns;
+using Mono.Net.Dns;
namespace System.Net
{
../corlib/System.Collections/CollectionDebuggerView.cs
../corlib/System.Collections.Generic/CollectionDebuggerView.cs
../corlib/Mono/DataConverter.cs
-Mono.Dns/DnsClass.cs
-Mono.Dns/DnsHeader.cs
-Mono.Dns/DnsOpCode.cs
-Mono.Dns/DnsPacket.cs
-Mono.Dns/DnsQClass.cs
-Mono.Dns/DnsQType.cs
-Mono.Dns/DnsQuery.cs
-Mono.Dns/DnsQuestion.cs
-Mono.Dns/DnsRCode.cs
-Mono.Dns/DnsResourceRecordA.cs
-Mono.Dns/DnsResourceRecordAAAA.cs
-Mono.Dns/DnsResourceRecordCName.cs
-Mono.Dns/DnsResourceRecord.cs
-Mono.Dns/DnsResourceRecordIPAddress.cs
-Mono.Dns/DnsResourceRecordPTR.cs
-Mono.Dns/DnsResponse.cs
-Mono.Dns/DnsType.cs
-Mono.Dns/DnsUtil.cs
-Mono.Dns/ResolverAsyncOperation.cs
-Mono.Dns/SimpleResolver.cs
-Mono.Dns/ResolverError.cs
-Mono.Dns/SimpleResolverEventArgs.cs
+Mono.Net.Dns/DnsClass.cs
+Mono.Net.Dns/DnsHeader.cs
+Mono.Net.Dns/DnsOpCode.cs
+Mono.Net.Dns/DnsPacket.cs
+Mono.Net.Dns/DnsQClass.cs
+Mono.Net.Dns/DnsQType.cs
+Mono.Net.Dns/DnsQuery.cs
+Mono.Net.Dns/DnsQuestion.cs
+Mono.Net.Dns/DnsRCode.cs
+Mono.Net.Dns/DnsResourceRecordA.cs
+Mono.Net.Dns/DnsResourceRecordAAAA.cs
+Mono.Net.Dns/DnsResourceRecordCName.cs
+Mono.Net.Dns/DnsResourceRecord.cs
+Mono.Net.Dns/DnsResourceRecordIPAddress.cs
+Mono.Net.Dns/DnsResourceRecordPTR.cs
+Mono.Net.Dns/DnsResponse.cs
+Mono.Net.Dns/DnsType.cs
+Mono.Net.Dns/DnsUtil.cs
+Mono.Net.Dns/ResolverAsyncOperation.cs
+Mono.Net.Dns/SimpleResolver.cs
+Mono.Net.Dns/ResolverError.cs
+Mono.Net.Dns/SimpleResolverEventArgs.cs
System.Net/DnsAsyncResult.cs