/** <summary>Creates a response given the entire packet.</summary> <remarks>The entire packet must be given, because some name servers take advantage of pointers to reduce their size.</remarks> <param name="Data">The entire DNS packet.</param> <param name="Start">The starting position of the Response.</param> */ public Response(MemBlock Data, int Start) { int idx = 0; NAME_BLOB = DNSPacket.RetrieveBlob(Data, Start, out idx); int type = (Data[idx++] << 8) + Data[idx++]; TYPE = (DNSPacket.TYPES) type; CACHE_FLUSH = ((Data[idx] & 0x80) == 0x80) ? true : false; int rclass = ((Data[idx++] << 8) & 0x7F) + Data[idx++]; CLASS = (DNSPacket.CLASSES) rclass; TTL = (Data[idx++] << 24); TTL |= (Data[idx++] << 16); TTL |= (Data[idx++] << 8); TTL |= (Data[idx++]); RDLENGTH = (short) ((Data[idx++] << 8) + Data[idx++]); RDATA_BLOB = Data.Slice(idx, RDLENGTH); if(TYPE == DNSPacket.TYPES.PTR) { try { NAME = DNSPacket.PtrMemBlockToString(NAME_BLOB); } catch { NAME = DNSPacket.HostnameMemBlockToString(NAME_BLOB); } int End = 0; RDATA_BLOB = DNSPacket.RetrieveBlob(Data, idx, out End); RDATA = DNSPacket.HostnameMemBlockToString(RDATA_BLOB); } else if(TYPE == DNSPacket.TYPES.A) { NAME = DNSPacket.HostnameMemBlockToString(NAME_BLOB); RDATA = DNSPacket.IPMemBlockToString(RDATA_BLOB); } _icpacket = _packet = Data.Slice(Start, idx + RDLENGTH - Start); }
/** <summary>Constructor when creating a DNS Query</summary> <param name="QNAME">the name of resource you are looking up, IP Address when QTYPE = PTR otherwise hostname</param> <param name="QTYPE"> the type of look up to perform</param> <param name="QCLASS">should always be IN</param> */ public Question(String QNAME, DNSPacket.TYPES QTYPE, DNSPacket.CLASSES QCLASS) { this.QNAME = QNAME; this.QTYPE = QTYPE; this.QCLASS = QCLASS; if(QTYPE == DNSPacket.TYPES.A) { QNAME_BLOB = DNSPacket.HostnameStringToMemBlock(QNAME); } else if(QTYPE == DNSPacket.TYPES.PTR) { QNAME_BLOB = DNSPacket.PtrStringToMemBlock(QNAME); } else { throw new Exception("Invalid QTYPE: " + QTYPE + "!"); } // 2 for QTYPE + 2 for QCLASS byte[] data = new byte[4]; int idx = 0; data[idx++] = (byte) ((((int) QTYPE) >> 8) & 0xFF); data[idx++] = (byte) (((int) QTYPE) & 0xFF); data[idx++] = (byte) ((((int) QCLASS) >> 8) & 0xFF); data[idx++] = (byte) (((int) QCLASS) & 0xFF); _icpacket = new CopyList(QNAME_BLOB, MemBlock.Reference(data)); }
/** <summary>Creates a response from the parameter fields with RDATA being a memory chunk. This is for MDNS which supports caching</summary> <param name="NAME">The name resolved.</param> <param name="TYPE">The query type.</param> <param name="CLASS">The network type.</param> <param name="CACHE_FLUSH">Flush the dns cache in the client.</param> <param name="TTL">How long to hold the result in the local dns cache.</param> <param name="RDATA">RDATA in String format.</param> */ public Response(String NAME, DNSPacket.TYPES TYPE, DNSPacket.CLASSES CLASS, bool CACHE_FLUSH, int TTL, String RDATA) { this.NAME = NAME; this.CLASS = CLASS; this.TTL = TTL; this.TYPE = TYPE; this.CLASS = CLASS; this.CACHE_FLUSH = CACHE_FLUSH; this.RDATA = RDATA; if(TYPE == DNSPacket.TYPES.A) { NAME_BLOB = DNSPacket.HostnameStringToMemBlock(NAME); RDATA_BLOB = DNSPacket.IPStringToMemBlock(RDATA); } else if(TYPE == DNSPacket.TYPES.PTR) { if(DNSPacket.StringIsIP(NAME)) { NAME_BLOB = DNSPacket.PtrStringToMemBlock(NAME); } else { NAME_BLOB = DNSPacket.HostnameStringToMemBlock(NAME); } RDATA_BLOB = DNSPacket.HostnameStringToMemBlock(RDATA); } else { throw new Exception("Invalid Query TYPE: " + TYPE + "!"); } RDLENGTH = (short) RDATA_BLOB.Length; // 2 for TYPE + 2 for CLASS + 4 for TTL + 2 for RDLENGTH byte[] data = new byte[10]; int idx = 0; data[idx++] = (byte) ((((int) TYPE) >> 8) & 0xFF); data[idx++] = (byte) (((int) TYPE) & 0xFF); byte cache_flush = 0x80; if(!CACHE_FLUSH) { cache_flush = 0x00; } data[idx++] = (byte) (((((int) CLASS) >> 8) & 0x7F) | cache_flush); data[idx++] = (byte) (((int) CLASS) & 0xFF); data[idx++] = (byte) ((TTL >> 24) & 0xFF); data[idx++] = (byte) ((TTL >> 16) & 0xFF); data[idx++] = (byte) ((TTL >> 8) & 0xFF); data[idx++] = (byte) (TTL & 0xFF); data[idx++] = (byte) ((RDLENGTH >> 8) & 0xFF); data[idx] = (byte) (RDLENGTH & 0xFF); _icpacket = new CopyList(NAME_BLOB, MemBlock.Reference(data), RDATA_BLOB); }
/** <summary>Constructor when parsing a DNS Query</summary> <param name="Data"> must pass in the entire packet from where the question begins, after parsing, can check Data.Length to find where next container begins.</param> */ public Question(MemBlock Data, int Start) { int idx = 0; QNAME_BLOB = DNSPacket.RetrieveBlob(Data, Start, out idx); int qtype = (Data[idx++] << 8) + Data[idx++]; QTYPE = (DNSPacket.TYPES) qtype; int qclass = (Data[idx++] << 8) + Data[idx]; QCLASS = (DNSPacket.CLASSES) qclass; if(QTYPE == DNSPacket.TYPES.A) { QNAME = DNSPacket.HostnameMemBlockToString(QNAME_BLOB); } else if(QTYPE == DNSPacket.TYPES.PTR) { QNAME = DNSPacket.PtrMemBlockToString(QNAME_BLOB); } _icpacket = _packet = Data.Slice(Start, idx + 1 - Start); }