1 module dnslib.unittesting; 2 3 import dnslib.defs; 4 import dnslib.parser; 5 import dnslib.aux; 6 7 import std.stdio; 8 9 unittest 10 { 11 DnsOptions dnsOptions; 12 //dnsOptions.printParsing = true; 13 14 { 15 // Source: https://www2.cs.duke.edu/courses/fall16/compsci356/DNS/DNS-primer.pdf 16 string hexData = "db4201000001000000000000037777770c6e6f7274686561737465726e036564750000010001"; 17 auto messageData = readHexString(hexData); 18 19 dnsMessage message; 20 dnsParserResult requestParserResult = dnsParse(messageData, message, dnsOptions.printParsing); 21 writeln(requestParserResult); 22 assert (requestParserResult == dnsParserResult.success); 23 auto validateResult = message.validate(dnsHeaderFlagQueryResponse.query, false); 24 writeln(validateResult); 25 assert (validateResult == dnsMessageValidateCode.success); 26 27 writeln(message); 28 29 assert (message.header.ID == 56130); 30 assert (message.header.flags.queryResponse == dnsHeaderFlagQueryResponse.query); 31 assert (message.header.flags.recursionDesired == true); 32 assert (message.header.flags.recursionAvailable == false); 33 assert (message.header.flags.authoritativeAnswer == false); 34 assert (message.header.flags.truncation == false); 35 assert (message.header.flags.opCode == dnsOpCode.QUERY); 36 assert (message.header.flags.responseCode == dnsResponseCode.NOERROR); 37 38 assert (message.header.flags.reserved == 0); 39 40 assert (message.header.QDCOUNT == 1); 41 assert (message.header.ANCOUNT == 0); 42 assert (message.header.NSCOUNT == 0); 43 assert (message.header.ARCOUNT == 0); 44 45 assert (message.query.length == 1); 46 assert (message.answer.length == 0); 47 assert (message.authority.length == 0); 48 assert (message.additional.length == 0); 49 50 assert (message.query[0].domainName == "www.northeastern.edu"); 51 assert (message.query[0].queryType == dnsType.A); 52 assert (message.query[0].queryClass == dnsClass.INET); 53 } 54 55 // --------------------------------------------------------------------- 56 57 { 58 // Source: https://www2.cs.duke.edu/courses/fall16/compsci356/DNS/DNS-primer.pdf 59 string hexData = "db4281800001000100000000037777770c6e6f7274686561737465726e036564750000010001c00c000100010000025800049b211144"; 60 auto messageData = readHexString(hexData); 61 62 dnsMessage message; 63 dnsParserResult requestParserResult = dnsParse(messageData, message, dnsOptions.printParsing); 64 writeln(requestParserResult); 65 assert (requestParserResult == dnsParserResult.success); 66 auto validateResult = message.validate(dnsHeaderFlagQueryResponse.response, false); 67 writeln(validateResult); 68 assert (validateResult == dnsMessageValidateCode.success); 69 70 writeln(message); 71 72 assert (message.header.ID == 56130); 73 assert (message.header.flags.queryResponse == dnsHeaderFlagQueryResponse.response); 74 assert (message.header.flags.recursionDesired == true); 75 assert (message.header.flags.recursionAvailable == true); 76 assert (message.header.flags.authoritativeAnswer == false); 77 assert (message.header.flags.truncation == false); 78 assert (message.header.flags.opCode == dnsOpCode.QUERY); 79 assert (message.header.flags.responseCode == dnsResponseCode.NOERROR); 80 81 assert (message.header.flags.reserved == 0); 82 83 assert (message.header.QDCOUNT == 1); 84 assert (message.header.ANCOUNT == 1); 85 assert (message.header.NSCOUNT == 0); 86 assert (message.header.ARCOUNT == 0); 87 88 assert (message.query.length == 1); 89 assert (message.answer.length == 1); 90 assert (message.authority.length == 0); 91 assert (message.additional.length == 0); 92 93 assert (message.query[0].domainName == "www.northeastern.edu"); 94 assert (message.query[0].queryType == dnsType.A); 95 assert (message.query[0].queryClass == dnsClass.INET); 96 97 assert (message.answer[0].domainName == "www.northeastern.edu"); 98 assert (message.answer[0].responseType == dnsType.A); 99 assert (message.answer[0].responseClass == dnsClass.INET); 100 101 assert (message.answer[0].TTL == 600); 102 103 assert (message.answer[0].responseDataLength== 4); 104 assert (message.answer[0].responseData == [0x9b, 0x21, 0x11, 0x44]); 105 assert (message.answer[0].responseString == "155.33.17.68"); 106 107 } 108 109 // --------------------------------------------------------------------- 110 111 { 112 // Source: https://pypi.org/project/dnslib/ 113 string hexData = "d5ad818000010005000000000377777706676f6f676c6503636f6d0000010001c00c0005000100000005000803777777016cc010c02c0001000100000005000442f95b68c02c0001000100000005000442f95b63c02c0001000100000005000442f95b67c02c0001000100000005000442f95b93"; 114 auto messageData = readHexString(hexData); 115 116 dnsMessage message; 117 dnsParserResult requestParserResult = dnsParse(messageData, message, dnsOptions.printParsing); 118 writeln(requestParserResult); 119 assert (requestParserResult == dnsParserResult.success); 120 auto validateResult = message.validate(dnsHeaderFlagQueryResponse.response, false); 121 writeln(validateResult); 122 assert (validateResult == dnsMessageValidateCode.success); 123 124 writeln(message); 125 126 assert (message.header.ID == 0xd5ad); 127 assert (message.header.flags.queryResponse == dnsHeaderFlagQueryResponse.response); 128 assert (message.header.flags.recursionDesired == true); 129 assert (message.header.flags.recursionAvailable == true); 130 assert (message.header.flags.authoritativeAnswer == false); 131 assert (message.header.flags.truncation == false); 132 assert (message.header.flags.opCode == dnsOpCode.QUERY); 133 assert (message.header.flags.responseCode == dnsResponseCode.NOERROR); 134 135 assert (message.header.flags.reserved == 0); 136 137 assert (message.header.QDCOUNT == 1); 138 assert (message.header.ANCOUNT == 5); 139 assert (message.header.NSCOUNT == 0); 140 assert (message.header.ARCOUNT == 0); 141 142 assert (message.query.length == 1); 143 assert (message.answer.length == 5); 144 assert (message.authority.length == 0); 145 assert (message.additional.length == 0); 146 147 assert (message.query[0].domainName == "www.google.com"); 148 assert (message.query[0].queryType == dnsType.A); 149 assert (message.query[0].queryClass == dnsClass.INET); 150 151 assert (message.answer[0].domainName == "www.google.com"); 152 assert (message.answer[0].responseType == dnsType.CNAME); 153 assert (message.answer[0].responseClass == dnsClass.INET); 154 155 assert (message.answer[0].TTL == 5); 156 157 assert (message.answer[0].responseDataLength== 8); 158 assert (message.answer[0].responseData == [3, 119, 119, 119, 1, 108, 192, 16]); 159 assert (message.answer[0].responseString == "www.l.google.com"); 160 161 assert (message.answer[1].domainName == "www.l.google.com"); 162 assert (message.answer[1].responseType == dnsType.A); 163 assert (message.answer[1].responseClass == dnsClass.INET); 164 165 assert (message.answer[1].TTL == 5); 166 167 assert (message.answer[1].responseDataLength== 4); 168 assert (message.answer[1].responseData == [66, 249, 91, 104]); 169 assert (message.answer[1].responseString == "66.249.91.104"); 170 } 171 } 172 173 // --------------------------------------------------------------------- 174 175 // Example usage 176 unittest 177 { 178 import dnslib.defs; 179 180 import std.stdio; 181 import core.stdc.stdlib: exit, EXIT_FAILURE, EXIT_SUCCESS; 182 183 // Example data 184 string name = "www.yahoo.com"; 185 dnsType type = dnsType.A; 186 bool recursionDesired = true; 187 188 ushort dnsId; 189 ubyte[] requestData; 190 import dnslib.generator: generateRequest; 191 generateRequest(name, type, dnsId, requestData, recursionDesired); 192 193 ubyte[] responseData; 194 import dnslib.net: DnsNetConfig, DnsNetStat, query, dnsQueryResult; 195 DnsNetStat netStat; 196 197 DnsNetConfig netConfig; 198 netConfig.server = "127.0.0.1"; 199 netConfig.udpTcpPort = 53; 200 netConfig.protocol = Protocol.tcp; 201 202 auto myDnsQueryResult = query(netConfig, requestData, responseData, netStat); 203 if (myDnsQueryResult != dnsQueryResult.success) 204 { 205 writefln("QUERYING ERROR: %s", myDnsQueryResult); 206 //return EXIT_FAILURE; 207 } 208 209 dnsMessage responseMessage; 210 211 import dnslib.parser: dnsParse; 212 bool printParsing = false; 213 auto responseParserResult = dnsParse(responseData, responseMessage, printParsing); 214 if (responseParserResult != dnsParserResult.success) 215 { 216 writefln("PARSNING ERROR: %s", responseParserResult); 217 //return EXIT_FAILURE; 218 } 219 220 auto validateCodeResponse = responseMessage.validate(dnsHeaderFlagQueryResponse.response); 221 222 if (validateCodeResponse != dnsMessageValidateCode.success) 223 { 224 writefln("VALIDATING RESPONSE MESSAGE: %s", validateCodeResponse.messageValidateCodeToString); 225 //return EXIT_FAILURE; 226 } 227 228 string[] shortResult = responseMessage.getShortResult(type); 229 writefln("SHORT RESULT: %s", shortResult); 230 } 231