1 module dnslib.generator; 2 3 4 import dnslib.defs; 5 6 import std.conv: to; 7 import std.random; 8 9 ushort IDcounter = 0; 10 11 // Very simple random generator used for creating dns request ID values 12 auto randomEngine = MinstdRand(1); // Generator is reseeded in module constructor 13 14 static this() 15 { 16 randomEngine.seed(unpredictableSeed); 17 } 18 19 // --------------------------------------------------------------------- 20 21 ushort newDnsId() 22 { 23 IDcounter = to!ushort((IDcounter + uniform(1, ushort.max-1, randomEngine)) % ushort.max); 24 return IDcounter; 25 } 26 27 // --------------------------------------------------------------------- 28 29 bool generateRequest(string domainName, dnsType type, out ushort dnsId, out ubyte[] requestData, bool recursionDesired = true) 30 { 31 import std.bitmanip: swapEndian; 32 33 static assert (ushort.sizeof == 2); 34 dnsId = newDnsId(); 35 ushort[] requestHeader = [dnsId, recursionDesired ? 0x0100 : 0x0000, 1, 0, 0, 0]; // 0x0100 = standard query with recursion desired; Only one query section. 36 foreach(i,v; requestHeader) 37 { 38 requestHeader[i] = requestHeader[i].swapEndian(); 39 } 40 41 requestData = cast(ubyte[])requestHeader; 42 43 if (domainName.length == 0 || domainName.length > 253) { return false; } 44 45 import std..string: split; 46 string[] domainNameElements = domainName.split("."); 47 if (domainNameElements.length > 127) { return false; } 48 49 foreach(element; domainNameElements) 50 { 51 assert(1 <= element.length && element.length <= 63); 52 if (element.length == 0 || element.length > 63) { return false; } 53 requestData ~= to!ubyte(element.length); 54 requestData ~= cast(ubyte[])element; 55 } 56 requestData ~= 0; 57 58 ushort requestClass = dnsClass.INET; 59 ushort[] typeAndClass = [(cast(ushort)type).swapEndian(), requestClass.swapEndian()]; 60 requestData ~= cast(ubyte[])typeAndClass; 61 62 return true; 63 } // generateRequest 64 65 // --------------------------------------------------------------------- 66 67 bool generateReverseRequest(string ipstring, out ushort dnsId, out ubyte[] requestData) 68 { 69 if (ipstring.length < 7 || ipstring.length > 15) { return false; } 70 71 import std..string: split, join; 72 string[] ipstringElements = ipstring.split("."); 73 assert(ipstringElements.length == 4); 74 foreach(element; ipstringElements) 75 { 76 if (element.length == 0 || element.length > 3) { return false; } 77 foreach (c; element) 78 { 79 import std.ascii: isDigit; 80 if (!c.isDigit()) { return false; } 81 } 82 } 83 84 import std.algorithm.mutation: reverse; 85 string domainName = ipstringElements.reverse.join(".") ~ ".in-addr.arpa"; 86 87 dnsType reverseDnsType = dnsType.PTR; 88 generateRequest(domainName, reverseDnsType, dnsId, requestData, true); 89 90 return true; 91 } // generateReverseRequest 92