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