1 /*
2  * Copyright (c) 2017 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/ztest.h>
9 #include <zephyr/sys/crc.h>
10 #include <dns_pack.h>
11 #include <dns_internal.h>
12 
13 #define MAX_BUF_SIZE	512
14 /* RFC 1035, 4.1.1. Header section format */
15 #define DNS_HEADER_SIZE	12
16 
17 static uint8_t dns_buf[MAX_BUF_SIZE];
18 static uint16_t dns_buf_len;
19 
20 static uint8_t qname[MAX_BUF_SIZE];
21 static uint16_t qname_len;
22 
23 static struct dns_resolve_context dns_ctx;
24 
25 /* Domain: www.zephyrproject.org
26  * Type: standard query (IPv4)
27  * Transaction ID: 0xda0f
28  * Recursion desired
29  */
30 static uint8_t query_ipv4[] = { 0xda, 0x0f, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
31 				0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77,
32 				0x0d, 0x7a, 0x65, 0x70, 0x68, 0x79, 0x72, 0x70,
33 				0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x03, 0x6f,
34 				0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01 };
35 
36 #define DNAME1 "www.zephyrproject.org"
37 
38 /* Domain: zephyr.local
39  * Type: standard query (IPv6)
40  * Recursion not desired
41  */
42 static uint8_t query_mdns[] = {
43 	0xda, 0x0f, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
44 	0x00, 0x00, 0x00, 0x00, 0x06, 0x7a, 0x65, 0x70,
45 	0x68, 0x79, 0x72, 0x05, 0x6c, 0x6f, 0x63, 0x61,
46 	0x6c, 0x00, 0x00, 0x01, 0x00, 0x01,
47 };
48 
49 #define ZEPHYR_LOCAL "zephyr.local"
50 
51 static uint16_t tid1 = 0xda0f;
52 
eval_query(const char * dname,uint16_t tid,enum dns_rr_type type,uint8_t * expected,uint16_t expected_len)53 static int eval_query(const char *dname, uint16_t tid, enum dns_rr_type type,
54 		      uint8_t *expected, uint16_t expected_len)
55 {
56 	uint8_t *question;
57 	int rc;
58 
59 	rc = dns_msg_pack_qname(&qname_len, qname, MAX_BUF_SIZE, dname);
60 	if (rc != 0) {
61 		goto lb_exit;
62 	}
63 
64 	rc = dns_msg_pack_query(dns_buf, &dns_buf_len, MAX_BUF_SIZE, qname, qname_len,
65 				tid, type);
66 	if (rc != 0) {
67 		goto lb_exit;
68 	}
69 
70 	if (dns_unpack_header_id(dns_buf) != tid) {
71 		rc = -EINVAL;
72 		goto lb_exit;
73 	}
74 
75 	/* This is a query */
76 	if (dns_header_qr(dns_buf) != DNS_QUERY) {
77 		rc = -EINVAL;
78 		goto lb_exit;
79 	}
80 
81 	/* This is a query (standard query) */
82 	if (dns_header_opcode(dns_buf) != DNS_QUERY) {
83 		rc = -EINVAL;
84 		goto lb_exit;
85 	}
86 
87 	/* Authoritative Answer must be 0 for a Query */
88 	if (dns_header_aa(dns_buf) != 0) {
89 		rc = -EINVAL;
90 		goto lb_exit;
91 	}
92 
93 	/* TrunCation is always 0 */
94 	if (dns_header_tc(dns_buf) != 0) {
95 		rc = -EINVAL;
96 		goto lb_exit;
97 	}
98 
99 	/* Recursion Desired is always 1 */
100 	if (dns_header_rd(dns_buf) != 1) {
101 		rc = -EINVAL;
102 		goto lb_exit;
103 	}
104 
105 	/* Recursion Available is always 0 */
106 	if (dns_header_ra(dns_buf) != 0) {
107 		rc = -EINVAL;
108 		goto lb_exit;
109 	}
110 
111 	/* Z is always 0 */
112 	if (dns_header_z(dns_buf) != 0) {
113 		rc = -EINVAL;
114 		goto lb_exit;
115 	}
116 
117 	/* Response code must be 0 (no error) */
118 	if (dns_header_rcode(dns_buf) != DNS_HEADER_NOERROR) {
119 		rc = -EINVAL;
120 		goto lb_exit;
121 	}
122 
123 	/* Question counter must be 1 */
124 	if (dns_header_qdcount(dns_buf) != 1) {
125 		rc = -EINVAL;
126 		goto lb_exit;
127 	}
128 
129 	/* Answer counter must be 0 */
130 	if (dns_header_ancount(dns_buf) != 0) {
131 		rc = -EINVAL;
132 		goto lb_exit;
133 	}
134 
135 	/* Name server resource records counter must be 0 */
136 	if (dns_header_nscount(dns_buf) != 0) {
137 		rc = -EINVAL;
138 		goto lb_exit;
139 	}
140 
141 	/* Additional records counter must be 0 */
142 	if (dns_header_arcount(dns_buf) != 0) {
143 		rc = -EINVAL;
144 		goto lb_exit;
145 	}
146 
147 	question = dns_buf + DNS_HEADER_SIZE;
148 
149 	/* QClass */
150 	if (dns_unpack_query_qclass(question + qname_len) != DNS_CLASS_IN) {
151 		rc = -EINVAL;
152 		goto lb_exit;
153 	}
154 
155 	/* QType */
156 	if (dns_unpack_query_qtype(question + qname_len) != type) {
157 		rc = -EINVAL;
158 		goto lb_exit;
159 	}
160 
161 	/* compare with the expected result */
162 	if (dns_buf_len != expected_len) {
163 		rc = -EINVAL;
164 		goto lb_exit;
165 	}
166 
167 	if (memcmp(expected, dns_buf, dns_buf_len) != 0) {
168 		rc = -EINVAL;
169 		goto lb_exit;
170 	}
171 
172 lb_exit:
173 	return rc;
174 }
175 
176 /* The DNS response min size is computed as follows:
177  * (hdr size) + (question min size) +  (RR min size)
178  */
179 #define RESPONSE_MIN_SIZE	(DNS_HEADER_SIZE + 6 + 14)
180 
181 /* DNS QNAME size here is 2 because we use DNS pointers */
182 #define NAME_PTR_SIZE	2
183 /* DNS integer size */
184 #define INT_SIZE	2
185 /* DNS answer TTL size */
186 #define ANS_TTL_SIZE	4
187 
188 struct dns_response_test {
189 	/* domain name: example.com */
190 	const char *dname;
191 
192 	/* expected result */
193 	uint8_t *res;
194 	/* expected result length */
195 	uint16_t res_len;
196 
197 	/* transaction id */
198 	uint16_t tid;
199 	/* A, AAAA */
200 	uint8_t answer_type;
201 	/* answer counter */
202 	uint8_t ancount;
203 	/* answer TTL */
204 	uint32_t ttl;
205 	/* recursion available */
206 	uint8_t ra;
207 	/* recursion desired */
208 	uint8_t rd;
209 	/* data len */
210 	uint8_t rdlen;
211 	/* data */
212 	const uint8_t *rdata;
213 };
214 
215 /* This routine evaluates DNS responses with one RR, and assumes that the
216  * RR's name points to the DNS question's qname.
217  */
eval_response1(struct dns_response_test * resp,bool unpack_answer)218 static int eval_response1(struct dns_response_test *resp, bool unpack_answer)
219 {
220 	uint8_t *ptr = resp->res;
221 	uint16_t offset;
222 	int  rc;
223 
224 	if (resp->res_len < RESPONSE_MIN_SIZE) {
225 		rc = __LINE__;
226 		goto lb_exit;
227 	}
228 
229 	if (dns_unpack_header_id(resp->res) != resp->tid) {
230 		rc = __LINE__;
231 		goto lb_exit;
232 	}
233 
234 	/* This is a response */
235 	if (dns_header_qr(resp->res) != DNS_RESPONSE) {
236 		rc = __LINE__;
237 		goto lb_exit;
238 	}
239 
240 	/* For the DNS response, this value is standard query */
241 	if (dns_header_opcode(resp->res) != DNS_QUERY) {
242 		rc = __LINE__;
243 		goto lb_exit;
244 	}
245 
246 	/* Authoritative Answer */
247 	if (dns_header_aa(resp->res) != 0) {
248 		rc = __LINE__;
249 		goto lb_exit;
250 	}
251 
252 	/* TrunCation is always 0 */
253 	if (dns_header_tc(resp->res) != 0) {
254 		rc = __LINE__;
255 		goto lb_exit;
256 	}
257 
258 	/* Recursion Desired */
259 	if (dns_header_rd(resp->res) != resp->rd) {
260 		rc = __LINE__;
261 		goto lb_exit;
262 	}
263 
264 	/* Recursion Available */
265 	if (dns_header_ra(resp->res) != resp->ra) {
266 		rc = __LINE__;
267 		goto lb_exit;
268 	}
269 
270 	/* Z is always 0 */
271 	if (dns_header_z(resp->res) != 0) {
272 		rc = __LINE__;
273 		goto lb_exit;
274 	}
275 
276 	/* Response code must be 0 (no error) */
277 	if (dns_header_rcode(resp->res) != DNS_HEADER_NOERROR) {
278 		rc = __LINE__;
279 		goto lb_exit;
280 	}
281 
282 	/* Question counter must be 1 */
283 	if (dns_header_qdcount(resp->res) != 1) {
284 		rc = __LINE__;
285 		goto lb_exit;
286 	}
287 
288 	/* Answer counter */
289 	if (dns_header_ancount(resp->res) != resp->ancount) {
290 		rc = __LINE__;
291 		goto lb_exit;
292 	}
293 
294 	/* Name server resource records counter must be 0 */
295 	if (dns_header_nscount(resp->res) != 0) {
296 		rc = __LINE__;
297 		goto lb_exit;
298 	}
299 
300 	/* Additional records counter must be 0 */
301 	if (dns_header_arcount(resp->res) != 0) {
302 		rc = __LINE__;
303 		goto lb_exit;
304 	}
305 
306 	rc = dns_msg_pack_qname(&qname_len, qname, MAX_BUF_SIZE, resp->dname);
307 	if (rc != 0) {
308 		goto lb_exit;
309 	}
310 
311 	offset = DNS_HEADER_SIZE;
312 
313 	/* DNS header + qname + qtype (int size) + qclass (int size) */
314 	if (offset + qname_len + 2 * INT_SIZE >= resp->res_len) {
315 		rc = __LINE__;
316 		goto lb_exit;
317 	}
318 
319 	if (memcmp(qname, resp->res + offset, qname_len) != 0) {
320 		rc = __LINE__;
321 		goto lb_exit;
322 	}
323 
324 	offset += qname_len;
325 
326 	if (dns_unpack_query_qtype(resp->res + offset) != resp->answer_type) {
327 		rc = __LINE__;
328 		goto lb_exit;
329 	}
330 
331 	if (dns_unpack_query_qclass(resp->res + offset) != DNS_CLASS_IN) {
332 		rc = __LINE__;
333 		goto lb_exit;
334 	}
335 
336 	/* qtype and qclass */
337 	offset += INT_SIZE + INT_SIZE;
338 
339 	if (unpack_answer) {
340 		uint32_t ttl;
341 		struct dns_msg_t msg;
342 		enum dns_rr_type answer_type;
343 
344 		msg.msg = resp->res;
345 		msg.msg_size = resp->res_len;
346 		msg.answer_offset = offset;
347 
348 		if (dns_unpack_answer(&msg, DNS_ANSWER_MIN_SIZE, &ttl, &answer_type) < 0) {
349 			rc = __LINE__;
350 			goto lb_exit;
351 		}
352 
353 		offset = msg.response_position;
354 	} else {
355 		/* 0xc0 and 0x0c are derived from RFC 1035 4.1.4 Message
356 		 * compression. 0x0c is the DNS Header Size (fixed size) and
357 		 * 0xc0 is the DNS pointer marker.
358 		 */
359 		if (resp->res[offset + 0] != 0xc0 ||
360 		    resp->res[offset + 1] != 0x0c) {
361 			rc = __LINE__;
362 			goto lb_exit;
363 		}
364 
365 		/* simplify the following lines by applying the offset here */
366 		resp->res += offset;
367 		offset = NAME_PTR_SIZE;
368 
369 		if (dns_answer_type(NAME_PTR_SIZE,
370 				    resp->res) != resp->answer_type) {
371 			rc = __LINE__;
372 			goto lb_exit;
373 		}
374 
375 		offset += INT_SIZE;
376 
377 		if (dns_answer_class(NAME_PTR_SIZE,
378 				     resp->res) != DNS_CLASS_IN) {
379 			rc = __LINE__;
380 			goto lb_exit;
381 		}
382 
383 		offset += INT_SIZE;
384 
385 		if (dns_answer_ttl(NAME_PTR_SIZE, resp->res) != resp->ttl) {
386 			rc = __LINE__;
387 			goto lb_exit;
388 		}
389 
390 		offset += ANS_TTL_SIZE;
391 
392 		if (dns_answer_rdlength(NAME_PTR_SIZE,
393 					resp->res) != resp->rdlen) {
394 			rc = __LINE__;
395 			goto lb_exit;
396 		}
397 
398 		offset += INT_SIZE;
399 	}
400 
401 	if (resp->rdlen + offset > resp->res_len) {
402 		rc = __LINE__;
403 		goto lb_exit;
404 	}
405 
406 	if (memcmp(resp->res + offset, resp->rdata, resp->rdlen) != 0) {
407 		rc = __LINE__;
408 	}
409 
410 lb_exit:
411 	resp->res = ptr;
412 
413 	return -rc;
414 }
415 
416 
ZTEST(dns_packet,test_dns_query)417 ZTEST(dns_packet, test_dns_query)
418 {
419 	int rc;
420 
421 	rc = eval_query(DNAME1, tid1, DNS_RR_TYPE_A,
422 			query_ipv4, sizeof(query_ipv4));
423 	zassert_equal(rc, 0, "Query test failed for domain: "DNAME1);
424 
425 	rc = eval_query(NULL, tid1, DNS_RR_TYPE_A,
426 			query_ipv4, sizeof(query_ipv4));
427 	zassert_not_equal(rc, 0, "Query test with invalid domain name failed");
428 
429 	rc = eval_query(DNAME1, tid1, DNS_RR_TYPE_AAAA,
430 			query_ipv4, sizeof(query_ipv4));
431 	zassert_not_equal(rc, 0, "Query test for IPv4 with RR type AAAA failed");
432 
433 	rc = eval_query(DNAME1, tid1 + 1, DNS_RR_TYPE_A,
434 			query_ipv4, sizeof(query_ipv4));
435 	zassert_not_equal(rc, 0, "Query test with invalid ID failed");
436 }
437 
438 /* DNS response for www.zephyrproject.org with the following parameters:
439  * Transaction ID: 0xb041
440  * Answer type: RR A
441  * Answer counter: 1
442  * TTL: 3028
443  * Recursion Available: 1
444  * RD len: 4 (IPv4 Address)
445  * RData: 140.211.169.8
446  */
447 static uint8_t resp_ipv4[] = { 0xb0, 0x41, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
448 			       0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77,
449 			       0x0d, 0x7a, 0x65, 0x70, 0x68, 0x79, 0x72, 0x70,
450 			       0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x03, 0x6f,
451 			       0x72, 0x67, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0,
452 			       0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0b,
453 			       0xd4, 0x00, 0x04, 0x8c, 0xd3, 0xa9, 0x08 };
454 
455 static const uint8_t resp_ipv4_addr[] = {140, 211, 169, 8};
456 
ZTEST(dns_packet,test_dns_response)457 ZTEST(dns_packet, test_dns_response)
458 {
459 	struct dns_response_test test = {
460 		.dname = DNAME1,
461 		.res = resp_ipv4,
462 		.res_len = sizeof(resp_ipv4),
463 		.tid = 0xb041,
464 		.answer_type = DNS_RR_TYPE_A,
465 		.ancount = 1,
466 		.ttl = 3028,
467 		.ra = 1,
468 		.rd = 1,
469 		.rdlen = 4, /* IPv4 test */
470 		.rdata = resp_ipv4_addr
471 	};
472 	struct dns_response_test test1, test2;
473 	int rc;
474 
475 	memcpy(&test1, &test, sizeof(test1));
476 	rc = eval_response1(&test1, false);
477 	zassert_equal(rc, 0,
478 		      "Response test failed for domain: " DNAME1
479 		      " at line %d", -rc);
480 
481 	/* Test also using dns_unpack_answer() API */
482 	memcpy(&test2, &test, sizeof(test2));
483 	rc = eval_response1(&test2, true);
484 	zassert_equal(rc, 0,
485 		      "Response test 2 failed for domain: " DNAME1
486 		      " at line %d", -rc);
487 }
488 
489 /* Domain: www.wireshark.org
490  * Type: standard query (IPv4)
491  * Transaction ID: 0x2121
492  * Answer is for a.www.wireshark.org for testing purposes.
493  */
494 char answer_ipv4[] = {
495 	0x21, 0x21, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
496 	0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77,
497 	0x09, 0x77, 0x69, 0x72, 0x65, 0x73, 0x68, 0x61,
498 	0x72, 0x6b, 0x03, 0x6f, 0x72, 0x67, 0x00, 0x00,
499 	0x01, 0x00, 0x01, 0x01, 0x61, 0xc0, 0x0c, 0x00, 0x01, 0x00,
500 	0x01, 0x00, 0x00, 0x02, 0x58, 0x00, 0x04, 0xae,
501 	0x89, 0x2a, 0x41
502 };
503 
504 #define DNAME2 "www.wireshark.org"
505 
506 static const uint8_t answer_ipv4_addr[] = { 174, 137, 42, 65 };
507 
ZTEST(dns_packet,test_dns_response2)508 ZTEST(dns_packet, test_dns_response2)
509 {
510 	struct dns_response_test test1 = {
511 		.dname = DNAME2,
512 		.res = answer_ipv4,
513 		.res_len = sizeof(answer_ipv4),
514 		.tid = 0x2121,
515 		.answer_type = DNS_RR_TYPE_A,
516 		.ancount = 1,
517 		.ttl = 600,
518 		.ra = 1,
519 		.rd = 1,
520 		.rdlen = 4, /* IPv4 test */
521 		.rdata = answer_ipv4_addr
522 	};
523 	int rc;
524 
525 	/* Test also using dns_unpack_answer() API */
526 	rc = eval_response1(&test1, true);
527 	zassert_equal(rc, 0,
528 		      "Response test 2 failed for domain: " DNAME2
529 		      " at line %d", -rc);
530 }
531 
ZTEST(dns_packet,test_mdns_query)532 ZTEST(dns_packet, test_mdns_query)
533 {
534 	int rc;
535 
536 	rc = eval_query(ZEPHYR_LOCAL, tid1, DNS_RR_TYPE_A,
537 			query_mdns, sizeof(query_mdns));
538 	zassert_equal(rc, 0, "Query test failed for domain: " ZEPHYR_LOCAL);
539 }
540 
541 /* DNS response for zephyr.local with the following parameters:
542  * Transaction ID: 0xf2b6
543  * Answer type: RR AAAA
544  * Answer counter: 1
545  * TTL: 30
546  * Recursion Available: 0
547  * RD len: 16 (IPv6 Address)
548  * RData: fe80:0000:0000:0000:0200:5eff:fe00:5337
549  */
550 static uint8_t resp_ipv6[] = {
551 	0xf2, 0xb6, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01,
552 	0x00, 0x00, 0x00, 0x00, 0x06, 0x7a, 0x65, 0x70,
553 	0x68, 0x79, 0x72, 0x05, 0x6c, 0x6f, 0x63, 0x61,
554 	0x6c, 0x00, 0x00, 0x1c, 0x00, 0x01, 0x06, 0x7a,
555 	0x65, 0x70, 0x68, 0x79, 0x72, 0x05, 0x6c, 0x6f,
556 	0x63, 0x61, 0x6c, 0x00, 0x00, 0x1c, 0x00, 0x01,
557 	0x00, 0x00, 0x00, 0x1e, 0x00, 0x10, 0xfe, 0x80,
558 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
559 	0x5e, 0xff, 0xfe, 0x00, 0x53, 0x37,
560 };
561 
562 static const uint8_t resp_ipv6_addr[] = {
563 	0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 	0x02, 0x00, 0x5e, 0xff, 0xfe, 0x00, 0x53, 0x37
565 };
566 
ZTEST(dns_packet,test_mdns_response)567 ZTEST(dns_packet, test_mdns_response)
568 {
569 	struct dns_response_test test1 = {
570 		.dname = ZEPHYR_LOCAL,
571 		.res = resp_ipv6,
572 		.res_len = sizeof(resp_ipv6),
573 		.tid = 0xf2b6,
574 		.answer_type = DNS_RR_TYPE_AAAA,
575 		.ancount = 1,
576 		.ttl = 30,
577 		.ra = 0,
578 		.rd = 0,
579 		.rdlen = 16, /* IPv6 test */
580 		.rdata = resp_ipv6_addr,
581 	};
582 	int rc;
583 
584 	rc = eval_response1(&test1, true);
585 	zassert_equal(rc, 0,
586 		      "Response test failed for domain: " ZEPHYR_LOCAL
587 		      " at line %d", -rc);
588 }
589 
590 static uint8_t resp_truncated_response_ipv4_1[] = {
591 	/* DNS msg header (12 bytes) */
592 	0xb0, 0x41, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
593 	0x00, 0x00, 0x00, 0x00,
594 
595 	/* Query string (www.zephyrproject.org) */
596 	0x03, 0x77, 0x77, 0x77, 0x0d, 0x7a, 0x65, 0x70,
597 	0x68, 0x79, 0x72, 0x70, 0x72, 0x6f, 0x6a, 0x65,
598 	0x63, 0x74, 0x03, 0x6f, 0x72, 0x67, 0x00,
599 
600 	/* Query type */
601 	0x00, 0x01,
602 
603 	/* Query class */
604 	0x00, 0x01,
605 
606 	/* Answer data is missing */
607 };
608 
609 static uint8_t resp_truncated_response_ipv4_2[] = {
610 	/* DNS msg header (12 bytes) */
611 	0xb0, 0x41, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
612 	0x00, 0x00, 0x00, 0x00,
613 
614 	/* Query string (www.zephyrproject.org) */
615 	0x03, 0x77, 0x77, 0x77, 0x0d, 0x7a, 0x65, 0x70,
616 	0x68, 0x79, 0x72, 0x70, 0x72, 0x6f, 0x6a, 0x65,
617 	0x63, 0x74, 0x03, 0x6f, 0x72, 0x67, 0x00,
618 
619 	/* Rest of the data is missing */
620 };
621 
622 static uint8_t resp_truncated_response_ipv4_3[] = {
623 	/* DNS msg header (12 bytes) */
624 	0xb0, 0x41, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
625 	0x00, 0x00, 0x00, 0x00,
626 
627 	/* Query string (www.zephyrproject.org) */
628 	0x03, 0x77, 0x77, 0x77, 0x0d, 0x7a, 0x65, 0x70,
629 	0x68, 0x79, 0x72, 0x70, 0x72, 0x6f, 0x6a, 0x65,
630 	0x63, 0x74, 0x03, 0x6f, 0x72, 0x67, 0x00,
631 
632 	/* Query type */
633 	0x00, 0x01,
634 
635 	/* Query class */
636 	0x00, 0x01,
637 
638 	/* Answer name */
639 	0xc0, 0x1c,
640 
641 	/* Answer type */
642 	0x00, 0x01,
643 
644 	/* Answer class */
645 	0x00, 0x01,
646 
647 	/* TTL */
648 	0x00, 0x00, 0x0b, 0xd4,
649 };
650 
651 static uint8_t resp_truncated_response_ipv4_4[] = {
652 	/* DNS msg header (12 bytes) */
653 	0xb0, 0x41, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
654 	0x00, 0x00, 0x00, 0x00,
655 
656 	/* Query string (www.zephyrproject.org) */
657 	0x03, 0x77, 0x77, 0x77, 0x0d, 0x7a, 0x65, 0x70,
658 	0x68, 0x79, 0x72, 0x70, 0x72, 0x6f, 0x6a, 0x65,
659 	0x63, 0x74, 0x03, 0x6f, 0x72, 0x67, 0x00,
660 
661 	/* Query type */
662 	0x00, 0x01,
663 
664 	/* Query class */
665 	0x00, 0x01,
666 
667 	/* Answer name */
668 	0xc0, 0x1c,
669 
670 	/* Answer type */
671 	0x00, 0x01,
672 
673 	/* Answer class */
674 	0x00, 0x01,
675 
676 	/* TTL */
677 	0x00, 0x00, 0x0b, 0xd4,
678 };
679 
680 static uint8_t resp_truncated_response_ipv4_5[] = {
681 	/* DNS msg header (12 bytes) */
682 	0xb0, 0x41, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
683 	0x00, 0x00, 0x00, 0x00,
684 
685 	/* Query string (www.zephyrproject.org) */
686 	0x03, 0x77, 0x77, 0x77, 0x0d, 0x7a, 0x65, 0x70,
687 	0x68, 0x79, 0x72, 0x70, 0x72, 0x6f, 0x6a, 0x65,
688 	0x63, 0x74, 0x03, 0x6f, 0x72, 0x67, 0x00,
689 
690 	/* Query type */
691 	0x00, 0x01,
692 
693 	/* Query class */
694 	0x00, 0x01,
695 
696 	/* Answer name */
697 	0xc0, 0x1c,
698 
699 	/* Answer type */
700 	0x00, 0x01,
701 
702 	/* Answer class */
703 	0x00, 0x01,
704 
705 	/* TTL */
706 	0x00, 0x00, 0x0b, 0xd4,
707 
708 	/* Resource data length */
709 	0x00, 0x04,
710 };
711 
712 static uint8_t resp_truncated_response_ipv4_6[] = {
713 	/* DNS msg header (12 bytes) */
714 	/* Id (0) */
715 	0x00, 0x00,
716 	/* Flags (response, rcode = 1) */
717 	0x80, 0x01,
718 	/* Number of questions */
719 	0x00, 0x01,
720 	/* Number of answers */
721 	0x00, 0x00,
722 	/* Number of authority RRs */
723 	0x00, 0x00,
724 	/* Number of additional RRs */
725 	0x00, 0x00,
726 
727 	/* Rest of the data is missing */
728 };
729 
730 static uint8_t resp_valid_response_ipv4_6[] = {
731 	/* DNS msg header (12 bytes) */
732 	0xb0, 0x41, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
733 	0x00, 0x00, 0x00, 0x00,
734 
735 	/* Query string (www.zephyrproject.org) */
736 	0x03, 0x77, 0x77, 0x77, 0x0d, 0x7a, 0x65, 0x70,
737 	0x68, 0x79, 0x72, 0x70, 0x72, 0x6f, 0x6a, 0x65,
738 	0x63, 0x74, 0x03, 0x6f, 0x72, 0x67, 0x00,
739 
740 	/* Query type */
741 	0x00, 0x01,
742 
743 	/* Query class */
744 	0x00, 0x01,
745 
746 	/* Answer name */
747 	0xc0, 0x1c,
748 
749 	/* Answer type */
750 	0x00, 0x01,
751 
752 	/* Answer class */
753 	0x00, 0x01,
754 
755 	/* TTL */
756 	0x00, 0x00, 0x0b, 0xd4,
757 
758 	/* Resource data length */
759 	0x00, 0x04,
760 
761 	/* Resource data (IP address) */
762 	0x8c, 0xd3, 0xa9, 0x08
763 };
764 
765 static uint8_t resp_valid_response_ipv4_7[] = {
766 	/* DNS msg header (12 bytes) */
767 	0xb0, 0x41, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
768 	0x00, 0x00, 0x00, 0x00,
769 
770 	/* Query string (www.zephyrproject.org) */
771 	0x03, 0x77, 0x77, 0x77, 0x0d, 0x7a, 0x65, 0x70,
772 	0x68, 0x79, 0x72, 0x70, 0x72, 0x6f, 0x6a, 0x65,
773 	0x63, 0x74, 0x03, 0x6f, 0x72, 0x67, 0x00,
774 
775 	/* Query type */
776 	0x00, 0x01,
777 
778 	/* Query class */
779 	0x00, 0x01,
780 
781 	/* Answer name (do not use pointer here) */
782 	0x03, 0x77, 0x77, 0x77, 0x0d, 0x7a, 0x65, 0x70,
783 	0x68, 0x79, 0x72, 0x70, 0x72, 0x6f, 0x6a, 0x65,
784 	0x63, 0x74, 0x03, 0x6f, 0x72, 0x67, 0x00,
785 
786 	/* Answer type */
787 	0x00, 0x01,
788 
789 	/* Answer class */
790 	0x00, 0x01,
791 
792 	/* TTL */
793 	0x00, 0x00, 0x0b, 0xd4,
794 
795 	/* Resource data length */
796 	0x00, 0x04,
797 
798 	/* Resource data (IP address) */
799 	0x8c, 0xd3, 0xa9, 0x08
800 };
801 
802 static uint8_t resp_valid_response_ipv4_8[] = {
803 	/* DNS msg header (12 bytes) */
804 	0xb0, 0x41, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02,
805 	0x00, 0x00, 0x00, 0x00,
806 
807 	/* Query string (www.zephyrproject.org) */
808 	0x03, 0x77, 0x77, 0x77, 0x0d, 0x7a, 0x65, 0x70,
809 	0x68, 0x79, 0x72, 0x70, 0x72, 0x6f, 0x6a, 0x65,
810 	0x63, 0x74, 0x03, 0x6f, 0x72, 0x67, 0x00,
811 
812 	/* Query type */
813 	0x00, 0x01,
814 
815 	/* Query class */
816 	0x00, 0x01,
817 
818 	/* 1st answer name (do not use pointer here) */
819 	0x03, 0x77, 0x77, 0x77, 0x0d, 0x7a, 0x65, 0x70,
820 	0x68, 0x79, 0x72, 0x70, 0x72, 0x6f, 0x6a, 0x65,
821 	0x63, 0x74, 0x03, 0x6f, 0x72, 0x67, 0x00,
822 
823 	/* Answer type */
824 	0x00, 0x01,
825 
826 	/* Answer class */
827 	0x00, 0x01,
828 
829 	/* TTL */
830 	0x00, 0x00, 0x0b, 0xd4,
831 
832 	/* Resource data length */
833 	0x00, 0x04,
834 
835 	/* Resource data (IP address) */
836 	0x8c, 0xd3, 0xa9, 0x08,
837 
838 	/* 2nd answer name (do not use pointer here) */
839 	0x03, 0x77, 0x77, 0x77, 0x0d, 0x7a, 0x65, 0x70,
840 	0x68, 0x79, 0x72, 0x70, 0x72, 0x6f, 0x6a, 0x65,
841 	0x63, 0x74, 0x03, 0x6f, 0x72, 0x67, 0x00,
842 
843 	/* Answer type */
844 	0x00, 0x01,
845 
846 	/* Answer class */
847 	0x00, 0x01,
848 
849 	/* TTL */
850 	0x00, 0x00, 0x0b, 0xd4,
851 
852 	/* Resource data length */
853 	0x00, 0x04,
854 
855 	/* Resource data (IP address) */
856 	0x8c, 0xd3, 0xa9, 0x09
857 };
858 
859 static uint8_t resp_valid_response_ipv4_9[] = {
860 	/* DNS msg header (12 bytes) */
861 	0xb0, 0x41, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02,
862 	0x00, 0x00, 0x00, 0x00,
863 
864 	/* Query string (www.zephyrproject.org) */
865 	0x03, 0x77, 0x77, 0x77, 0x0d, 0x7a, 0x65, 0x70,
866 	0x68, 0x79, 0x72, 0x70, 0x72, 0x6f, 0x6a, 0x65,
867 	0x63, 0x74, 0x03, 0x6f, 0x72, 0x67, 0x00,
868 
869 	/* Query type */
870 	0x00, 0x01,
871 
872 	/* Query class */
873 	0x00, 0x01,
874 
875 	/* 1st answer name (use pointer for 1st answer) */
876 	0xc0, 0x1c,
877 
878 	/* Answer type */
879 	0x00, 0x01,
880 
881 	/* Answer class */
882 	0x00, 0x01,
883 
884 	/* TTL */
885 	0x00, 0x00, 0x0b, 0xd4,
886 
887 	/* Resource data length */
888 	0x00, 0x04,
889 
890 	/* Resource data (IP address) */
891 	0x8c, 0xd3, 0xa9, 0x08,
892 
893 	/* 2nd answer name (do not use pointer here) */
894 	0x03, 0x77, 0x77, 0x77, 0x0d, 0x7a, 0x65, 0x70,
895 	0x68, 0x79, 0x72, 0x70, 0x72, 0x6f, 0x6a, 0x65,
896 	0x63, 0x74, 0x03, 0x6f, 0x72, 0x67, 0x00,
897 
898 	/* Answer type */
899 	0x00, 0x01,
900 
901 	/* Answer class */
902 	0x00, 0x01,
903 
904 	/* TTL */
905 	0x00, 0x00, 0x0b, 0xd4,
906 
907 	/* Resource data length */
908 	0x00, 0x04,
909 
910 	/* Resource data (IP address) */
911 	0x8c, 0xd3, 0xa9, 0x09
912 };
913 
914 static uint8_t resp_valid_response_ipv4_10[] = {
915 	/* DNS msg header (12 bytes) */
916 	0x74, 0xe1, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02,
917 	0x00, 0x00, 0x00, 0x00,
918 
919 	/* Query string */
920 	0x0e, 0x77, 0x65, 0x73,	0x74, 0x75, 0x73, 0x32,
921 	0x2d, 0x70, 0x72, 0x6f, 0x64, 0x2d, 0x32, 0x0d,
922 	0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
923 	0x74, 0x69, 0x6f, 0x6e, 0x73, 0x05, 0x74, 0x65,
924 	0x61, 0x6d, 0x73, 0x09, 0x6d, 0x69, 0x63, 0x72,
925 	0x6f, 0x73, 0x6f, 0x66, 0x74, 0x03, 0x63, 0x6f,
926 	0x6d, 0x00,
927 
928 	/* Type */
929 	0x00, 0x01,
930 
931 	/* Class */
932 	0x00, 0x01,
933 
934 	/* Answer 1 */
935 	0xc0, 0x0c,
936 
937 	/* Answer type (cname) */
938 	0x00, 0x05,
939 
940 	/* Class */
941 	0x00, 0x01,
942 
943 	/* TTL */
944 	0x00, 0x00, 0x00, 0x04,
945 
946 	/* RR data length */
947 	0x00, 0x26,
948 
949 	/* Data */
950 	0x11, 0x77, 0x65, 0x73, 0x74, 0x75, 0x73, 0x32,
951 	0x63, 0x6e, 0x73, 0x2d, 0x70, 0x72, 0x6f, 0x64,
952 	0x2d, 0x32, 0x0e, 0x74, 0x72, 0x61, 0x66, 0x66,
953 	0x69, 0x63, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
954 	0x72, 0x03, 0x6e, 0x65, 0x74, 0x00,
955 
956 	/* Answer 2 */
957 	0xc0, 0x4e,
958 
959 	/* cname */
960 	0x00, 0x05,
961 
962 	/* Class */
963 	0x00, 0x01,
964 
965 	/* TTL */
966 	0x00, 0x00, 0x00, 0x04,
967 
968 	/* RR data length */
969 	0x00, 0x2e,
970 
971 	/* Data */
972 	0x14, 0x77, 0x65, 0x73, 0x74, 0x75, 0x73, 0x32,
973 	0x63, 0x6e, 0x73, 0x2d, 0x70, 0x72, 0x6f, 0x64,
974 	0x2d, 0x32, 0x2d, 0x31, 0x36, 0x07, 0x77, 0x65,
975 	0x73, 0x74, 0x75, 0x73, 0x32, 0x08, 0x63, 0x6c,
976 	0x6f, 0x75, 0x64, 0x61, 0x70, 0x70, 0x05, 0x61,
977 	0x7a, 0x75, 0x72, 0x65, 0xc0, 0x39,
978 };
979 
980 static uint8_t resp_valid_response_ipv4_11[] = {
981 	/* DNS msg header (12 bytes) */
982 	0x74, 0xe1, 0x81, 0x80, 0x00, 0x01, 0x00, 0x03,
983 	0x00, 0x00, 0x00, 0x00,
984 
985 	/* Query string */
986 	0x0e, 0x77, 0x65, 0x73,	0x74, 0x75, 0x73, 0x32,
987 	0x2d, 0x70, 0x72, 0x6f, 0x64, 0x2d, 0x32, 0x0d,
988 	0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
989 	0x74, 0x69, 0x6f, 0x6e, 0x73, 0x05, 0x74, 0x65,
990 	0x61, 0x6d, 0x73, 0x09, 0x6d, 0x69, 0x63, 0x72,
991 	0x6f, 0x73, 0x6f, 0x66, 0x74, 0x03, 0x63, 0x6f,
992 	0x6d, 0x00,
993 
994 	/* Type */
995 	0x00, 0x01,
996 
997 	/* Class */
998 	0x00, 0x01,
999 
1000 	/* Answer 1 */
1001 	0xc0, 0x0c,
1002 
1003 	/* Answer type (cname) */
1004 	0x00, 0x05,
1005 
1006 	/* Class */
1007 	0x00, 0x01,
1008 
1009 	/* TTL */
1010 	0x00, 0x00, 0x00, 0x04,
1011 
1012 	/* RR data length */
1013 	0x00, 0x26,
1014 
1015 	/* Data */
1016 	0x11, 0x77, 0x65, 0x73, 0x74, 0x75, 0x73, 0x32,
1017 	0x63, 0x6e, 0x73, 0x2d, 0x70, 0x72, 0x6f, 0x64,
1018 	0x2d, 0x32, 0x0e, 0x74, 0x72, 0x61, 0x66, 0x66,
1019 	0x69, 0x63, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
1020 	0x72, 0x03, 0x6e, 0x65, 0x74, 0x00,
1021 
1022 	/* Answer 2 */
1023 	0xc0, 0x4e,
1024 
1025 	/* cname */
1026 	0x00, 0x05,
1027 
1028 	/* Class */
1029 	0x00, 0x01,
1030 
1031 	/* TTL */
1032 	0x00, 0x00, 0x00, 0x04,
1033 
1034 	/* RR data length */
1035 	0x00, 0x2e,
1036 
1037 	/* Data */
1038 	0x14, 0x77, 0x65, 0x73, 0x74, 0x75, 0x73, 0x32,
1039 	0x63, 0x6e, 0x73, 0x2d, 0x70, 0x72, 0x6f, 0x64,
1040 	0x2d, 0x32, 0x2d, 0x31, 0x36, 0x07, 0x77, 0x65,
1041 	0x73, 0x74, 0x75, 0x73, 0x32, 0x08, 0x63, 0x6c,
1042 	0x6f, 0x75, 0x64, 0x61, 0x70, 0x70, 0x05, 0x61,
1043 	0x7a, 0x75, 0x72, 0x65, 0xc0, 0x39,
1044 
1045 	/* Answer 3 */
1046 	0xc0, 0x80,
1047 
1048 	/* A record */
1049 	0x00, 0x01,
1050 
1051 	/* Class */
1052 	0x00, 0x01,
1053 
1054 	/* TTL */
1055 	0x00, 0x00, 0x00, 0x04,
1056 
1057 	/* RR length */
1058 	0x00, 0x04,
1059 
1060 	/* IP address */
1061 	0x34, 0x72, 0x94, 0x90
1062 };
1063 
resolve_cb(enum dns_resolve_status status,struct dns_addrinfo * info,void * user_data)1064 static void resolve_cb(enum dns_resolve_status status,
1065 		       struct dns_addrinfo *info,
1066 		       void *user_data)
1067 {
1068 	ARG_UNUSED(status);
1069 	ARG_UNUSED(info);
1070 	ARG_UNUSED(user_data);
1071 }
1072 
setup_dns_context(struct dns_resolve_context * ctx,int idx,uint16_t dns_id,const uint8_t * query,size_t query_len,enum dns_query_type query_type)1073 static void setup_dns_context(struct dns_resolve_context *ctx,
1074 			      int idx,
1075 			      uint16_t dns_id,
1076 			      const uint8_t *query,
1077 			      size_t query_len,
1078 			      enum dns_query_type query_type)
1079 {
1080 	ctx->queries[idx].cb = resolve_cb;
1081 	ctx->queries[idx].id = dns_id;
1082 	ctx->queries[idx].query = query;
1083 	ctx->queries[idx].query_type = query_type;
1084 	ctx->queries[idx].query_hash = crc16_ansi(query, query_len);
1085 	ctx->state = DNS_RESOLVE_CONTEXT_ACTIVE;
1086 
1087 }
1088 
run_dns_malformed_response(const char * test_case,uint8_t * buf,size_t len)1089 static void run_dns_malformed_response(const char *test_case,
1090 				       uint8_t *buf, size_t len)
1091 {
1092 	/* Query is used to calculate the hash, it contains the
1093 	 * labels + query type
1094 	 */
1095 	static const uint8_t query[] = {
1096 		/* Labels */
1097 		0x03, 0x77, 0x77, 0x77, 0x0d, 0x7a, 0x65, 0x70,
1098 		0x68, 0x79, 0x72, 0x70, 0x72, 0x6f, 0x6a, 0x65,
1099 		0x63, 0x74, 0x03, 0x6f, 0x72, 0x67, 0x00,
1100 		/* Query type */
1101 		0x00, 0x01
1102 	};
1103 	struct dns_msg_t dns_msg = { 0 };
1104 	uint16_t dns_id = 0;
1105 	int query_idx = -1;
1106 	uint16_t query_hash = 0;
1107 	int ret;
1108 
1109 	dns_msg.msg = buf;
1110 	dns_msg.msg_size = len;
1111 
1112 	dns_id = dns_unpack_header_id(dns_msg.msg);
1113 
1114 	/* If the message is longer than 12 bytes, it could be a valid DNS message
1115 	 * in which case setup the context for the reply.
1116 	 */
1117 	if (len > 12) {
1118 		setup_dns_context(&dns_ctx, 0, dns_id, query, sizeof(query),
1119 				  DNS_QUERY_TYPE_A);
1120 	}
1121 
1122 	ret = dns_validate_msg(&dns_ctx, &dns_msg, &dns_id, &query_idx,
1123 			       NULL, &query_hash);
1124 	zassert_not_equal(ret, DNS_EAI_ALLDONE,
1125 			  "[%s] DNS message was valid (%d)",
1126 			  test_case, ret);
1127 }
1128 
run_dns_valid_response(const char * test_case,uint8_t * buf,size_t len)1129 static void run_dns_valid_response(const char *test_case,
1130 				   uint8_t *buf, size_t len)
1131 {
1132 	struct dns_msg_t dns_msg = { 0 };
1133 	uint16_t dns_id = 0;
1134 	int query_idx = -1;
1135 	uint16_t query_hash = 0;
1136 	int ret;
1137 
1138 	dns_msg.msg = buf;
1139 	dns_msg.msg_size = len;
1140 
1141 	ret = dns_validate_msg(&dns_ctx, &dns_msg, &dns_id, &query_idx,
1142 			       NULL, &query_hash);
1143 	zassert_equal(ret, DNS_EAI_ALLDONE, "[%s] DNS message failed (%d)",
1144 		      test_case, ret);
1145 }
1146 
1147 #define DNS_RESOLVER_MIN_BUF	1
1148 #define DNS_RESOLVER_BUF_CTR	(DNS_RESOLVER_MIN_BUF + 1)
1149 #define DNS_MAX_NAME_LEN	255
1150 
1151 NET_BUF_POOL_DEFINE(dns_qname_pool, DNS_RESOLVER_BUF_CTR, DNS_MAX_NAME_LEN,
1152 		    0, NULL);
1153 
run_dns_valid_cname_response(const char * test_case,uint8_t * buf,size_t len,int expected_ret)1154 static void run_dns_valid_cname_response(const char *test_case,
1155 					 uint8_t *buf, size_t len,
1156 					 int expected_ret)
1157 {
1158 	static const uint8_t query[] = {
1159 		/* Query string */
1160 		0x0e, 0x77, 0x65, 0x73,	0x74, 0x75, 0x73, 0x32,
1161 		0x2d, 0x70, 0x72, 0x6f, 0x64, 0x2d, 0x32, 0x0d,
1162 		0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
1163 		0x74, 0x69, 0x6f, 0x6e, 0x73, 0x05, 0x74, 0x65,
1164 		0x61, 0x6d, 0x73, 0x09, 0x6d, 0x69, 0x63, 0x72,
1165 		0x6f, 0x73, 0x6f, 0x66, 0x74, 0x03, 0x63, 0x6f,
1166 		0x6d, 0x00,
1167 
1168 		/* Type */
1169 		0x00, 0x01,
1170 	};
1171 	struct dns_msg_t dns_msg = { 0 };
1172 	struct net_buf *dns_cname;
1173 	uint16_t dns_id = 0;
1174 	int query_idx = -1;
1175 	uint16_t query_hash = 0;
1176 	int ret;
1177 
1178 	dns_msg.msg = buf;
1179 	dns_msg.msg_size = len;
1180 
1181 	dns_cname = net_buf_alloc(&dns_qname_pool, K_MSEC(100));
1182 	zassert_not_null(dns_cname, "Out of mem");
1183 
1184 	dns_id = dns_unpack_header_id(dns_msg.msg);
1185 
1186 	setup_dns_context(&dns_ctx, 0, dns_id, query, sizeof(query),
1187 			  DNS_QUERY_TYPE_A);
1188 
1189 	ret = dns_validate_msg(&dns_ctx, &dns_msg, &dns_id, &query_idx,
1190 			       dns_cname, &query_hash);
1191 	zassert_equal(ret, expected_ret, "[%s] DNS message failed (%d)",
1192 		      test_case, ret);
1193 }
1194 
1195 #define RUN_VALID_TEST(test_name)					\
1196 	run_dns_valid_response(#test_name, test_name, sizeof(test_name))
1197 
1198 #define RUN_VALID_CNAME_TEST(test_name, expected_ret)			\
1199 	run_dns_valid_cname_response(#test_name, test_name,		\
1200 				     sizeof(test_name), expected_ret)
1201 
test_dns_valid_responses(void)1202 static void test_dns_valid_responses(void)
1203 {
1204 	RUN_VALID_TEST(resp_valid_response_ipv4_6);
1205 	RUN_VALID_TEST(resp_valid_response_ipv4_7);
1206 	RUN_VALID_TEST(resp_valid_response_ipv4_8);
1207 	RUN_VALID_TEST(resp_valid_response_ipv4_9);
1208 
1209 	RUN_VALID_CNAME_TEST(resp_valid_response_ipv4_10, DNS_EAI_AGAIN);
1210 	RUN_VALID_CNAME_TEST(resp_valid_response_ipv4_11, DNS_EAI_ALLDONE);
1211 }
1212 
1213 #define RUN_MALFORMED_TEST(test_name) \
1214 	run_dns_malformed_response(#test_name, test_name, sizeof(test_name))
1215 
test_dns_malformed_responses(void)1216 static void test_dns_malformed_responses(void)
1217 {
1218 	RUN_MALFORMED_TEST(resp_truncated_response_ipv4_1);
1219 	RUN_MALFORMED_TEST(resp_truncated_response_ipv4_2);
1220 	RUN_MALFORMED_TEST(resp_truncated_response_ipv4_3);
1221 	RUN_MALFORMED_TEST(resp_truncated_response_ipv4_4);
1222 	RUN_MALFORMED_TEST(resp_truncated_response_ipv4_5);
1223 	RUN_MALFORMED_TEST(resp_truncated_response_ipv4_6);
1224 }
1225 
ZTEST(dns_packet,test_dns_malformed_and_valid_responses)1226 ZTEST(dns_packet, test_dns_malformed_and_valid_responses)
1227 {
1228 	test_dns_malformed_responses();
1229 	test_dns_valid_responses();
1230 }
1231 
ZTEST(dns_packet,test_dns_id_len)1232 ZTEST(dns_packet, test_dns_id_len)
1233 {
1234 	struct dns_msg_t dns_msg = { 0 };
1235 	uint8_t buf[1];
1236 	uint16_t dns_id = 0;
1237 	int query_idx = -1;
1238 	uint16_t query_hash = 0;
1239 	int ret;
1240 
1241 	dns_msg.msg = buf;
1242 	dns_msg.msg_size = sizeof(buf);
1243 
1244 	ret = dns_validate_msg(&dns_ctx, &dns_msg, &dns_id, &query_idx,
1245 			       NULL, &query_hash);
1246 	zassert_equal(ret, DNS_EAI_FAIL,
1247 		      "DNS message length check failed (%d)", ret);
1248 }
1249 
ZTEST(dns_packet,test_dns_flags_len)1250 ZTEST(dns_packet, test_dns_flags_len)
1251 {
1252 	struct dns_msg_t dns_msg = { 0 };
1253 	uint8_t buf[3];
1254 	uint16_t dns_id = 0;
1255 	int query_idx = -1;
1256 	uint16_t query_hash = 0;
1257 	int ret;
1258 
1259 	dns_msg.msg = buf;
1260 	dns_msg.msg_size = sizeof(buf);
1261 
1262 	ret = dns_validate_msg(&dns_ctx, &dns_msg, &dns_id, &query_idx,
1263 			       NULL, &query_hash);
1264 	zassert_equal(ret, DNS_EAI_FAIL,
1265 		      "DNS message length check failed (%d)", ret);
1266 }
1267 
1268 static uint8_t invalid_answer_resp_ipv4[18] = {
1269 	/* DNS msg header (12 bytes) */
1270 	0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
1271 	0x00, 0x00, 0x01, 0x00, 0x01,
1272 };
1273 
ZTEST(dns_packet,test_dns_invalid_answer)1274 ZTEST(dns_packet, test_dns_invalid_answer)
1275 {
1276 	struct dns_msg_t dns_msg = { 0 };
1277 	enum dns_rr_type type;
1278 	uint32_t ttl;
1279 	int ret;
1280 
1281 	dns_msg.msg = invalid_answer_resp_ipv4;
1282 	dns_msg.msg_size = sizeof(invalid_answer_resp_ipv4);
1283 	dns_msg.answer_offset = 12;
1284 
1285 	ret = dns_unpack_answer(&dns_msg, 0, &ttl, &type);
1286 	zassert_equal(ret, -EINVAL, "DNS message answer check succeed (%d)", ret);
1287 }
1288 
1289 static uint8_t recursive_query_resp_ipv4[] = {
1290 	/* DNS msg header (12 bytes) */
1291 	0x74, 0xe1, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
1292 	0x00, 0x00, 0x00, 0x00,
1293 
1294 	/* Query string (westus2-prod-2.notifications.teams.microsoft.com)
1295 	 * (length 50)
1296 	 */
1297 	0x0e, 0x77, 0x65, 0x73,	0x74, 0x75, 0x73, 0x32,
1298 	0x2d, 0x70, 0x72, 0x6f, 0x64, 0x2d, 0x32, 0x0d,
1299 	0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
1300 	0x74, 0x69, 0x6f, 0x6e, 0x73, 0x05, 0x74, 0x65,
1301 	0x61, 0x6d, 0x73, 0x09, 0x6d, 0x69, 0x63, 0x72,
1302 	0x6f, 0x73, 0x6f, 0x66, 0x74, 0x03, 0x63, 0x6f,
1303 	0x6d, 0x00,
1304 
1305 	/* Type (2 bytes) */
1306 	0x00, 0x01,
1307 
1308 	/* Class (2 bytes) */
1309 	0x00, 0x01,
1310 
1311 	/* Answer 1 */
1312 	0xc0, 0x0c,
1313 
1314 	/* Answer type (cname) */
1315 	0x00, 0x05,
1316 
1317 	/* Class */
1318 	0x00, 0x01,
1319 
1320 	/* TTL */
1321 	0x00, 0x00, 0x00, 0x04,
1322 
1323 	/* RR data length */
1324 	0x00, 0x02,
1325 
1326 	/* Data */
1327 	0xc0, 0x4e, /* <--- recursive pointer */
1328 };
1329 
1330 NET_BUF_POOL_DEFINE(dns_qname_pool_for_test, 2, 128, 0, NULL);
1331 
ZTEST(dns_packet,test_dns_recursive_query)1332 ZTEST(dns_packet, test_dns_recursive_query)
1333 {
1334 	static const uint8_t query[] = {
1335 		/* Query string */
1336 		0x0e, 0x77, 0x65, 0x73,	0x74, 0x75, 0x73, 0x32,
1337 		0x2d, 0x70, 0x72, 0x6f, 0x64, 0x2d, 0x32, 0x0d,
1338 		0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
1339 		0x74, 0x69, 0x6f, 0x6e, 0x73, 0x05, 0x74, 0x65,
1340 		0x61, 0x6d, 0x73, 0x09, 0x6d, 0x69, 0x63, 0x72,
1341 		0x6f, 0x73, 0x6f, 0x66, 0x74, 0x03, 0x63, 0x6f,
1342 		0x6d, 0x00,
1343 
1344 		/* Type */
1345 		0x00, 0x01,
1346 	};
1347 	struct dns_msg_t dns_msg = { 0 };
1348 	uint16_t dns_id = 0;
1349 	int query_idx = -1;
1350 	uint16_t query_hash = 0;
1351 	struct net_buf *dns_cname;
1352 	int ret;
1353 
1354 	dns_cname = net_buf_alloc(&dns_qname_pool_for_test, dns_ctx.buf_timeout);
1355 	zassert_not_null(dns_cname, "Out of mem");
1356 
1357 	dns_msg.msg = recursive_query_resp_ipv4;
1358 	dns_msg.msg_size = sizeof(recursive_query_resp_ipv4);
1359 
1360 	dns_id = dns_unpack_header_id(dns_msg.msg);
1361 
1362 	setup_dns_context(&dns_ctx, 0, dns_id, query, sizeof(query),
1363 			  DNS_QUERY_TYPE_A);
1364 
1365 	ret = dns_validate_msg(&dns_ctx, &dns_msg, &dns_id, &query_idx,
1366 			       dns_cname, &query_hash);
1367 	zassert_true(ret == DNS_EAI_SYSTEM && errno == ELOOP,
1368 		     "[%s] DNS message was valid (%d / %d)",
1369 		     "recursive rsp", ret, errno);
1370 
1371 	net_buf_unref(dns_cname);
1372 }
1373 
1374 static uint8_t invalid_compression_response_ipv4[] = {
1375 	/* DNS msg header (12 bytes) */
1376 	0x74, 0xe1, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
1377 	0x00, 0x00, 0x00, 0x00,
1378 
1379 	/* Query string */
1380 	0x0e, 0x77, 0x65, 0x73,	0x74, 0x75, 0x73, 0x32,
1381 	0x2d, 0x70, 0x72, 0x6f, 0x64, 0x2d, 0x32, 0x0d,
1382 	0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
1383 	0x74, 0x69, 0x6f, 0x6e, 0x73, 0x05, 0x74, 0x65,
1384 	0x61, 0x6d, 0x73, 0x09, 0x6d, 0x69, 0x63, 0x72,
1385 	0x6f, 0x73, 0x6f, 0x66, 0x74, 0x03, 0x63, 0x6f,
1386 	0x6d, 0x00,
1387 
1388 	/* Type */
1389 	0x00, 0x01,
1390 
1391 	/* Class */
1392 	0x00, 0x01,
1393 
1394 	/* Answer 1 */
1395 	0xb0, 0x0c, /* <--- invalid compression pointer */
1396 
1397 	/* Answer type (cname) */
1398 	0x00, 0x05,
1399 
1400 	/* Class */
1401 	0x00, 0x01,
1402 
1403 	/* TTL */
1404 	0x00, 0x00, 0x00, 0x04,
1405 
1406 	/* RR data length */
1407 	0x00, 0x02,
1408 
1409 	/* Data */
1410 	0xc0, 0x0c,
1411 };
1412 
ZTEST(dns_packet,test_dns_invalid_compress_bits)1413 ZTEST(dns_packet, test_dns_invalid_compress_bits)
1414 {
1415 	static const uint8_t query[] = {
1416 		/* Query string */
1417 		0x0e, 0x77, 0x65, 0x73,	0x74, 0x75, 0x73, 0x32,
1418 		0x2d, 0x70, 0x72, 0x6f, 0x64, 0x2d, 0x32, 0x0d,
1419 		0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
1420 		0x74, 0x69, 0x6f, 0x6e, 0x73, 0x05, 0x74, 0x65,
1421 		0x61, 0x6d, 0x73, 0x09, 0x6d, 0x69, 0x63, 0x72,
1422 		0x6f, 0x73, 0x6f, 0x66, 0x74, 0x03, 0x63, 0x6f,
1423 		0x6d, 0x00,
1424 
1425 		/* Type */
1426 		0x00, 0x01,
1427 	};
1428 	struct dns_msg_t dns_msg = { 0 };
1429 	uint16_t dns_id = 0;
1430 	int query_idx = -1;
1431 	uint16_t query_hash = 0;
1432 	struct net_buf *dns_cname;
1433 	int ret;
1434 
1435 	dns_cname = net_buf_alloc(&dns_qname_pool_for_test, dns_ctx.buf_timeout);
1436 	zassert_not_null(dns_cname, "Out of mem");
1437 
1438 	dns_msg.msg = invalid_compression_response_ipv4;
1439 	dns_msg.msg_size = sizeof(invalid_compression_response_ipv4);
1440 
1441 	dns_id = dns_unpack_header_id(dns_msg.msg);
1442 
1443 	setup_dns_context(&dns_ctx, 0, dns_id, query, sizeof(query),
1444 			  DNS_QUERY_TYPE_A);
1445 
1446 	ret = dns_validate_msg(&dns_ctx, &dns_msg, &dns_id, &query_idx,
1447 			       dns_cname, &query_hash);
1448 	zassert_true(ret == DNS_EAI_SYSTEM && errno == EINVAL,
1449 		     "[%s] DNS message was valid (%d / %d)",
1450 		     "invalid compression rsp", ret, errno);
1451 
1452 	net_buf_unref(dns_cname);
1453 }
1454 
1455 static uint8_t invalid_compression_response_cname_ipv4[] = {
1456 	/* DNS msg header (12 bytes) */
1457 	0x74, 0xe1, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
1458 	0x00, 0x00, 0x00, 0x00,
1459 
1460 	/* Query string */
1461 	0x0e, 0x77, 0x65, 0x73,	0x74, 0x75, 0x73, 0x32,
1462 	0x2d, 0x70, 0x72, 0x6f, 0x64, 0x2d, 0x32, 0x0d,
1463 	0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
1464 	0x74, 0x69, 0x6f, 0x6e, 0x73, 0x05, 0x74, 0x65,
1465 	0x61, 0x6d, 0x73, 0x09, 0x6d, 0x69, 0x63, 0x72,
1466 	0x6f, 0x73, 0x6f, 0x66, 0x74, 0x03, 0x63, 0x6f,
1467 	0x6d, 0x00,
1468 
1469 	/* Type */
1470 	0x00, 0x01,
1471 
1472 	/* Class */
1473 	0x00, 0x01,
1474 
1475 	/* Answer 1 */
1476 	0xc0, 0x0c,
1477 
1478 	/* Answer type (cname) */
1479 	0x00, 0x05,
1480 
1481 	/* Class */
1482 	0x00, 0x01,
1483 
1484 	/* TTL */
1485 	0x00, 0x00, 0x00, 0x04,
1486 
1487 	/* RR data length */
1488 	0x00, 0x02,
1489 
1490 	/* Data */
1491 	0xb0, 0x0c, /* <--- invalid compression pointer */
1492 };
1493 
ZTEST(dns_packet,test_dns_invalid_compress_bits_cname)1494 ZTEST(dns_packet, test_dns_invalid_compress_bits_cname)
1495 {
1496 	static const uint8_t query[] = {
1497 		/* Query string */
1498 		0x0e, 0x77, 0x65, 0x73,	0x74, 0x75, 0x73, 0x32,
1499 		0x2d, 0x70, 0x72, 0x6f, 0x64, 0x2d, 0x32, 0x0d,
1500 		0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
1501 		0x74, 0x69, 0x6f, 0x6e, 0x73, 0x05, 0x74, 0x65,
1502 		0x61, 0x6d, 0x73, 0x09, 0x6d, 0x69, 0x63, 0x72,
1503 		0x6f, 0x73, 0x6f, 0x66, 0x74, 0x03, 0x63, 0x6f,
1504 		0x6d, 0x00,
1505 
1506 		/* Type */
1507 		0x00, 0x01,
1508 	};
1509 	struct dns_msg_t dns_msg = { 0 };
1510 	uint16_t dns_id = 0;
1511 	int query_idx = -1;
1512 	uint16_t query_hash = 0;
1513 	struct net_buf *dns_cname;
1514 	int ret;
1515 
1516 	dns_cname = net_buf_alloc(&dns_qname_pool_for_test, dns_ctx.buf_timeout);
1517 	zassert_not_null(dns_cname, "Out of mem");
1518 
1519 	dns_msg.msg = invalid_compression_response_cname_ipv4;
1520 	dns_msg.msg_size = sizeof(invalid_compression_response_cname_ipv4);
1521 
1522 	dns_id = dns_unpack_header_id(dns_msg.msg);
1523 
1524 	setup_dns_context(&dns_ctx, 0, dns_id, query, sizeof(query),
1525 			  DNS_QUERY_TYPE_A);
1526 
1527 	ret = dns_validate_msg(&dns_ctx, &dns_msg, &dns_id, &query_idx,
1528 			       dns_cname, &query_hash);
1529 	zassert_true(ret == DNS_EAI_SYSTEM && errno == EINVAL,
1530 		     "[%s] DNS message was valid (%d / %d)",
1531 		     "invalid compression rsp", ret, errno);
1532 
1533 	net_buf_unref(dns_cname);
1534 }
1535 
1536 ZTEST_SUITE(dns_packet, NULL, NULL, NULL, NULL, NULL);
1537 /* TODO:
1538  *	1) add malformed DNS data (mostly done)
1539  *	2) add validations against buffer overflows
1540  *	3) add debug info to detect the exit point (or split the tests)
1541  *	4) add test data with CNAME and more RR
1542  */
1543