using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Globalization;
namespace Dimon.NetQueries {
/// <summary>
/// Summary description for Class1.
/// </summary>
///
public enum DNSQueryType {
Qtype_A =1,
Qtype_NS =2,
Qtype_MD =3,
Qtype_MF =4,
Qtype_CNAME =5,
Qtype_SOA =6,
Qtype_MB =7,
Qtype_MG =8,
Qtype_MR =9,
Qtype_NULL =10,
Qtype_WKS =11, //
Qtype_PTR =12,
Qtype_HINFO =13,
Qtype_MINFO =14,
Qtype_MX =15,
Qtype_TXT =16,
Qtype_RP =17,
Qtype_AFSDB =18,
Qtype_X25 =19,
Qtype_ISDN =20,
Qtype_RT =21,
Qtype_NSAP =22,
Qtype_NSAPPTR=23,
Qtype_SIG =24, //RFC-2065
Qtype_KEY =25, //RFC-2065
Qtype_PX =26,
Qtype_GPOS =27,
Qtype_AAAA =28, //IP6 Address [Susan Thomson]
Qtype_LOC =29, //RFC-1876
Qtype_NXT =30, //RFC-2065
Qtype_SRV =33, //RFC-2052
Qtype_NAPTR =35, //RFC-2168
Qtype_KX =36,
Qtype_AXFR =252, //
Qtype_MAILB =253, //
Qtype_MAILA =254, //
Qtype_ALL =255 //
}
public class DNSQuery {
string DNSHost;
byte[] Buffer;
Socket sock;
int BufferPos = 0;
System.Collections.SortedList results;
public string DNSServer {
get {
return DNSHost;
}
set {
DNSHost = value;
}
}
public int Count {
get {
return results.Count;
}
}
public string this[int Index] {
get {
return (string)results.GetByIndex(Index);
}
}
public DNSQuery() {
sock = new Socket(AddressFamily.AfINet,
SocketType.SockDgram,
ProtocolType.ProtUDP);
DNSHost = "localhost";
Buffer = new byte[8192];
results = new System.Collections.SortedList();
}
~DNSQuery() {
results = null;
if (sock.Connected) {
sock.Shutdown(SocketShutdown.SdBoth);
sock.Close();
}
sock = null;
}
private int CompressName(string Value, out byte[] ret) {
byte[] result = new byte[255];
byte[] temp;
int i = 0;
if (Value == "") {
result[i++] = 0;
} else {
string s = "";
for (int n = 0; n < Value.Length; n++) {
if (Value[n] == '.') {
result[i++] = s.Length.ToByte();
temp = Encoding.ASCII.GetBytes(s);
for (int t =0; t < temp.Length; t++) {
result[i++] = temp[t];
}
s = "";
} else {
s += Value[n];
}
}
if (s != "") {
result[i++] = s.Length.ToByte();
temp = Encoding.ASCII.GetBytes(s);
for (int t = 0; t < temp.Length; t++) {
result[i++] = temp[t];
}
}
}
result[i++] = 0;
ret = result;
return i;
}
private byte[] CodeInt(ushort Value) {
byte[] retArr = new byte[2];
retArr[0] = (byte)(Value / 256);
retArr[1] = (byte)(Value % 256);
return (retArr);
}
private byte[] CodeHeader() {
byte[] ret = new byte[12];
Random rnd = new Random(32767);
CodeInt((ushort)rnd.Next()).CopyTo(ret, 0);
CodeInt(256).CopyTo(ret, 2);
CodeInt(1).CopyTo(ret, 4);
CodeInt(0).CopyTo(ret, 6);
CodeInt(0).CopyTo(ret, 8);
CodeInt(0).CopyTo(ret, 10);
return ret;
}
private int CodeQuery(string Name, int Qtype,
out byte[] ret) {
byte[] res = new byte[255];
int i;
i = CompressName(Name, out res);
CodeInt((ushort)Qtype).CopyTo(res, i);
i += 2;
CodeInt(1).CopyTo(res, i);
i += 2;
ret = res;
return i;
}
private string DecodeLabels(ref int From) {
string ret = "";
int l, f;
while (true) {
l = (int) Buffer[From++];
if (l == 0) {
break;
}
if (ret != "") {
ret += ".";
}
if ((l & 0xC0) != 0) {
f = l & 0x3F;
f = f * 256 + (int) Buffer[From++];
ret += this.DecodeLabels(ref f);
break;
} else {
ret += Encoding.ASCII.GetString(Buffer, From, l);
From += l;
}
}
return ret;
}
private ushort DecodeInt(byte[] Value, int Index) {
byte x, y;
if (Value.Length > Index) {
x = Value[Index];
} else {
x = 0;
}
if (Value.Length > Index + 1) {
y = Value[Index + 1];
} else {
y = 0;
}
return (ushort) (x * 256 + y);
}
private string DecodeResource(ref int i, string Name,
DNSQueryType Qtype) {
string Rname;
int Rtype, len, j, x, n;
string ret = "";
Rname = DecodeLabels(ref i);
Rtype = DecodeInt(Buffer,i);
i += 8;
len = DecodeInt(Buffer,i);
i += 2;
j = i;
i += len; //i point to next record
if ((Name == Rname) && ((int)Qtype == Rtype)) {
switch(Qtype) {
case DNSQueryType.Qtype_A:
ret = ((byte)(Buffer[j++])).ToString();
ret += "." + ((byte)(Buffer[j++])).ToString();
ret += "." + ((byte)(Buffer[j++])).ToString();
ret += "." + ((byte)(Buffer[j++])).ToString();
break;
case DNSQueryType.Qtype_NS:
case DNSQueryType.Qtype_MD:
case DNSQueryType.Qtype_MF:
case DNSQueryType.Qtype_CNAME:
case DNSQueryType.Qtype_MB:
case DNSQueryType.Qtype_MG:
case DNSQueryType.Qtype_MR:
case DNSQueryType.Qtype_PTR:
case DNSQueryType.Qtype_X25:
case DNSQueryType.Qtype_NSAP:
case DNSQueryType.Qtype_NSAPPTR:
ret = DecodeLabels(ref j);
break;
case DNSQueryType.Qtype_SOA:
ret = DecodeLabels(ref j);
ret += "," + DecodeLabels(ref j);
for (n = 1; n <= 5; n++) {
x = DecodeInt(Buffer,j)*65536 + DecodeInt(Buffer,j+2);
j += 4;
ret += "," + x.ToString();
}
break;
case DNSQueryType.Qtype_NULL:
case DNSQueryType.Qtype_WKS:
break;
case DNSQueryType.Qtype_HINFO:
case DNSQueryType.Qtype_MINFO:
case DNSQueryType.Qtype_RP:
case DNSQueryType.Qtype_ISDN:
ret = DecodeLabels(ref j);
ret += "," + DecodeLabels(ref j);
break;
case DNSQueryType.Qtype_MX:
case DNSQueryType.Qtype_AFSDB:
case DNSQueryType.Qtype_RT:
case DNSQueryType.Qtype_KX:
x = DecodeInt(Buffer,j);
j += 2;
ret = x.ToString();
ret += "," + DecodeLabels(ref j);
break;
case DNSQueryType.Qtype_TXT:
ret = DecodeLabels(ref j);
break;
case DNSQueryType.Qtype_GPOS:
ret = DecodeLabels(ref j);
ret += "," + DecodeLabels(ref j);
ret += "," + DecodeLabels(ref j);
break;
case DNSQueryType.Qtype_PX:
x = DecodeInt(Buffer,j);
j += 2;
ret = x.ToString();
ret += "," + DecodeLabels(ref j);
ret += "," + DecodeLabels(ref j);
}
}
return ret;
}
private bool IsIP(string Value) {
int x = 0;
string correctChars = "0123456789.";
bool ret = true;
for (int n = 1; n <= Value.Length; n++) {
if (correctChars.IndexOf(Value[n]) == -1) {
ret = false;
break;
} else {
if (Value[n] == '.') {
x++;
}
}
}
if (x != 3) {
ret = false;
}
return ret;
}
private string ReverseIP(string Value) {
int x;
string ret = "";
x = Value.LastIndexOf(".");
while (x > 0) {
ret += Value.Substring(x + 1);
Value.Remove(x, Value.Length - x + 1);
x = Value.LastIndexOf(".");
}
if (ret.Length > 0) {
if(ret[0] == '.') {
ret.Remove(0, 1);
}
}
return ret;
}
public bool MakeQuery(string Name,
DNSQueryType QType) {
int n, i;
int flag,qdcount, ancount, nscount, arcount;
string s;
byte[] tmp;
bool ret = false;
results.Clear();
if (IsIP(Name)) {
Name = ReverseIP(Name) + ".in-addr.arpa";
}
CodeHeader().CopyTo(Buffer, 0);
BufferPos += 12;
int len = CodeQuery(Name, (int)QType, out tmp);
tmp.CopyTo(Buffer, BufferPos);
BufferPos += len;
sock.Connect(new IPEndPoint(new IPAddress(DNSHost), 53));
sock.Send(Buffer, BufferPos, 0);
int bytes = sock.Receive(Buffer, 8192, 0);
flag = DecodeInt(Buffer, 2);
byte RCode = (byte)(flag & 0x000F);
if (RCode == 0) {
qdcount = DecodeInt(Buffer, 4);
ancount = DecodeInt(Buffer, 6);
nscount = DecodeInt(Buffer, 8);
arcount = DecodeInt(Buffer, 10);
i = 13;
if (qdcount > 0) {
for(n = 1; n <= qdcount ; n++) {
while ((Buffer[i] != 0) &&
((Buffer[i] & 0xC0) != 0xC0)) {
i++;
}
i += 5;
}
}
if (ancount > 0) {
for(n = 1; n <= ancount; n++) {
s = DecodeResource(ref i, Name, QType);
if (s != "") {
results.Add(s, s);
}
}
}
ret = true;
}
return ret;
}
public bool MakeQuery(string Name, int QType) {
return MakeQuery(Name, (DNSQueryType) QType);
}
public bool GetMXRecords(string Name) {
bool retValue;
retValue = MakeQuery(Name, DNSQueryType.Qtype_MX);
if (retValue) {
string val;
for (int i = 0; i < results.Count; i++) {
val = (string)results.GetByIndex(i);
val = val.Remove(0, val.IndexOf(",") + 1);
results.SetByIndex(i, val);
}
}
return retValue;
}
}
} |