1 /*
2  * Copyright (c) 2020 Friedt Professional Engineering Services, Inc
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdbool.h>
8 #include <stdint.h>
9 
10 #include <zephyr/ztest.h>
11 
12 #include <zephyr/net/dns_sd.h>
13 #include <zephyr/net/net_context.h>
14 #include <zephyr/net/net_pkt.h>
15 #include <zephyr/net/socket.h>
16 
17 #include "dns_pack.h"
18 #include "dns_sd.h"
19 
20 #define BUFSZ 256
21 #define IP_ADDR(a, b, c, d) ((uint32_t)		  \
22 			     0			  \
23 			     | ((a & 0xff) << 24) \
24 			     | ((b & 0xff) << 16) \
25 			     | ((c & 0xff) <<  8) \
26 			     | ((d & 0xff) <<  0) \
27 			     )
28 
29 extern bool label_is_valid(const char *label, size_t label_size);
30 extern int add_a_record(const struct dns_sd_rec *inst, uint32_t ttl,
31 			uint16_t host_offset, uint32_t addr,
32 			uint8_t *buf,
33 			uint16_t buf_offset, uint16_t buf_size);
34 extern int add_ptr_record(const struct dns_sd_rec *inst, uint32_t ttl,
35 			  uint8_t *buf, uint16_t buf_offset,
36 			  uint16_t buf_size,
37 			  uint16_t *service_offset,
38 			  uint16_t *instance_offset,
39 			  uint16_t *domain_offset);
40 extern int add_txt_record(const struct dns_sd_rec *inst, uint32_t ttl,
41 			  uint16_t instance_offset, uint8_t *buf,
42 			  uint16_t buf_offset, uint16_t buf_size);
43 extern int add_aaaa_record(const struct dns_sd_rec *inst, uint32_t ttl,
44 			   uint16_t host_offset, const uint8_t addr[16],
45 			   uint8_t *buf, uint16_t buf_offset,
46 			   uint16_t buf_size);
47 extern int add_srv_record(const struct dns_sd_rec *inst, uint32_t ttl,
48 			  uint16_t instance_offset,
49 			  uint16_t domain_offset,
50 			  uint8_t *buf, uint16_t buf_offset,
51 			  uint16_t buf_size,
52 			  uint16_t *host_offset);
53 extern size_t service_proto_size(const struct dns_sd_rec *ref);
54 extern bool rec_is_valid(const struct dns_sd_rec *ref);
55 extern int setup_dst_addr(int sock, sa_family_t family,
56 			  struct sockaddr *src, socklen_t src_len,
57 			  struct sockaddr *dst, socklen_t *dst_len);
58 
59 
60 /** Text for advertised service */
61 static const uint8_t nasxxxxxx_text[] = "\x06" "path=/";
62 
63 /** A completely invalid record */
64 DNS_SD_REGISTER_SERVICE(invalid_dns_sd_record, NULL, NULL,
65 	NULL, NULL, NULL, NULL);
66 
67 /* initialized to zero for illustrative purposes */
68 static uint16_t nonconst_port;
69 DNS_SD_REGISTER_SERVICE(nasxxxxxx_ephemeral, "NASXXXXXX", "_http",
70 	"_tcp", "local", nasxxxxxx_text, &nonconst_port);
71 
72 /** Sample advertised service */
73 #define CONST_PORT 8080
74 DNS_SD_REGISTER_TCP_SERVICE(nasxxxxxx, "NASXXXXXX", "_http",
75 	"local", nasxxxxxx_text, CONST_PORT);
76 
77 /** Buffer for  DNS queries */
78 static uint8_t create_query_buf[BUFSZ];
79 
80 /**
81  * @brief Create a DNS query
82  *
83  * @param inst the service instance to query
84  * @param the type of DNS Resource Record to query
85  * @param[out] size the size of the resulting query
86  *
87  * @return on success a pointer to the buffer containing the query
88  * @return NULL on failure
89  */
create_query(const struct dns_sd_rec * inst,uint8_t rr_type,size_t * size)90 static uint8_t *create_query(const struct dns_sd_rec *inst,
91 			     uint8_t rr_type, size_t *size)
92 {
93 	uint16_t offs = 0;
94 	uint8_t label_size;
95 	uint16_t sp_size = service_proto_size(inst);
96 
97 	uint16_t expected_req_buf_size = 0
98 					 + sizeof(struct dns_header)
99 					 + sp_size
100 					 + sizeof(struct dns_query);
101 
102 	struct dns_header *hdr =
103 		(struct dns_header *)&create_query_buf[0];
104 
105 	hdr->id = htons(0);
106 	hdr->qdcount = htons(1);
107 	offs += sizeof(struct dns_header);
108 
109 	label_size = strlen(inst->service);
110 	create_query_buf[offs++] = label_size;
111 	memcpy(&create_query_buf[offs], inst->service, label_size);
112 	offs += label_size;
113 
114 	label_size = strlen(inst->proto);
115 	create_query_buf[offs++] = label_size;
116 	memcpy(&create_query_buf[offs], inst->proto, label_size);
117 	offs += label_size;
118 
119 	label_size = strlen(inst->domain);
120 	create_query_buf[offs++] = label_size;
121 	memcpy(&create_query_buf[offs], inst->domain, label_size);
122 	offs += label_size;
123 
124 	create_query_buf[offs++] = '\0';
125 
126 	struct dns_query *query =
127 		(struct dns_query *)&create_query_buf[offs];
128 	query->type = htons(rr_type);
129 	query->class_ = htons(DNS_CLASS_IN);
130 	offs += sizeof(struct dns_query);
131 
132 	zassert_equal(expected_req_buf_size, offs,
133 		      "sz: %zu offs: %u", expected_req_buf_size, offs);
134 
135 	*size = offs;
136 
137 	return create_query_buf;
138 }
139 
140 /** Test for @ref label_is_valid */
ZTEST(dns_sd,test_label_is_valid)141 ZTEST(dns_sd, test_label_is_valid)
142 {
143 	zassert_equal(false, label_is_valid(NULL,
144 					    DNS_LABEL_MIN_SIZE), "");
145 	zassert_equal(false, label_is_valid("",
146 					    DNS_LABEL_MIN_SIZE - 1),
147 		      "");
148 	zassert_equal(false, label_is_valid(
149 			      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
150 			      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
151 			      DNS_LABEL_MAX_SIZE + 1), "");
152 	zassert_equal(true,  label_is_valid("a",
153 					    DNS_LABEL_MIN_SIZE), "");
154 	zassert_equal(true,  label_is_valid(
155 			      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
156 			      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
157 			      DNS_LABEL_MAX_SIZE), "");
158 	zassert_equal(false, label_is_valid("9abc", 4), "");
159 	zassert_equal(true,  label_is_valid("a9bc", 4), "");
160 	zassert_equal(false, label_is_valid("-abc", 4), "");
161 	zassert_equal(true,  label_is_valid("a-bc", 4), "");
162 	zassert_equal(true,  label_is_valid("A-Bc", 4), "");
163 }
164 
165 /** Test for @ref dns_sd_rec_is_valid */
ZTEST(dns_sd,test_dns_sd_rec_is_valid)166 ZTEST(dns_sd, test_dns_sd_rec_is_valid)
167 {
168 	DNS_SD_REGISTER_TCP_SERVICE(name_min,
169 				"x",
170 				"_x",
171 				"xx",
172 				DNS_SD_EMPTY_TXT,
173 				CONST_PORT);
174 	zassert_equal(true, rec_is_valid(&name_min), "");
175 
176 	DNS_SD_REGISTER_TCP_SERVICE(name_max,
177 				"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
178 				"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
179 				"_xxxxxxxxxxxxxxx",
180 				"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
181 				"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
182 				DNS_SD_EMPTY_TXT,
183 				CONST_PORT);
184 	zassert_equal(true, rec_is_valid(&name_max), "");
185 
186 	DNS_SD_REGISTER_TCP_SERVICE(label_too_small,
187 				"x",
188 				"_",
189 				"xx",
190 				DNS_SD_EMPTY_TXT,
191 				CONST_PORT);
192 	zassert_equal(false, rec_is_valid(&label_too_small), "");
193 
194 	DNS_SD_REGISTER_TCP_SERVICE(label_too_big,
195 				"x",
196 				"_x",
197 				"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
198 				"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
199 				DNS_SD_EMPTY_TXT,
200 				CONST_PORT);
201 	zassert_equal(false, rec_is_valid(&label_too_big), "");
202 
203 	DNS_SD_REGISTER_TCP_SERVICE(invalid_instance,
204 				"abc" "\x01" "def",
205 				"_x",
206 				"xx",
207 				DNS_SD_EMPTY_TXT,
208 				CONST_PORT);
209 	zassert_equal(false, rec_is_valid(&invalid_instance), "");
210 
211 	DNS_SD_REGISTER_TCP_SERVICE(invalid_service_prefix,
212 				"x",
213 				"xx",
214 				"xx",
215 				DNS_SD_EMPTY_TXT,
216 				CONST_PORT);
217 	zassert_equal(false, rec_is_valid(
218 			      &invalid_service_prefix), "");
219 
220 	DNS_SD_REGISTER_TCP_SERVICE(invalid_service,
221 				"x",
222 				"_x.y",
223 				"xx",
224 				DNS_SD_EMPTY_TXT,
225 				CONST_PORT);
226 	zassert_equal(false, rec_is_valid(&invalid_service), "");
227 
228 	DNS_SD_REGISTER_SERVICE(invalid_proto,
229 				"x",
230 				"_y",
231 				"_wtf",
232 				"xx",
233 				DNS_SD_EMPTY_TXT,
234 				&nonconst_port);
235 	zassert_equal(false, rec_is_valid(&invalid_proto), "");
236 
237 	/* We do not currently support subdomains */
238 	DNS_SD_REGISTER_TCP_SERVICE(invalid_domain,
239 				"x",
240 				"_x",
241 				"x.y",
242 				DNS_SD_EMPTY_TXT,
243 				CONST_PORT);
244 	zassert_equal(false, rec_is_valid(&invalid_domain), "");
245 
246 	zassert_equal(true, rec_is_valid(&nasxxxxxx), "");
247 }
248 
249 /** Test for @ref creqte_query */
ZTEST(dns_sd,test_create_query)250 ZTEST(dns_sd, test_create_query)
251 {
252 	size_t actual_query_size = -1;
253 	uint8_t *actual_query = create_query(&nasxxxxxx,
254 					     DNS_RR_TYPE_PTR,
255 					     &actual_query_size);
256 	uint8_t expected_query[] = {
257 		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
258 		0x00, 0x00, 0x00, 0x00, 0x05, 0x5f, 0x68, 0x74,
259 		0x74, 0x70, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05,
260 		0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c,
261 		0x00, 0x01
262 	};
263 	size_t expected_query_size = sizeof(expected_query);
264 
265 	zassert_equal(actual_query_size, expected_query_size, "");
266 	zassert_mem_equal(expected_query, actual_query,
267 			  MIN(actual_query_size, expected_query_size),
268 			  "");
269 }
270 
271 /** Test for @ref add_ptr_record */
ZTEST(dns_sd,test_add_ptr_record)272 ZTEST(dns_sd, test_add_ptr_record)
273 {
274 	const uint32_t ttl = DNS_SD_PTR_TTL;
275 	const uint32_t offset = sizeof(struct dns_header);
276 
277 	uint16_t service_offset = -1;
278 	uint16_t instance_offset = -1;
279 	uint16_t domain_offset = -1;
280 
281 	static uint8_t actual_buf[BUFSZ];
282 	static const uint8_t expected_buf[] = {
283 		0x05, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x04, 0x5f,
284 		0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, 0x63, 0x61,
285 		0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00,
286 		0x11, 0x94, 0x00, 0x0c, 0x09, 0x4e, 0x41, 0x53,
287 		0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc0, 0x0c,
288 	};
289 	int expected_int = sizeof(expected_buf);
290 
291 	int actual_int = add_ptr_record(&nasxxxxxx, ttl,
292 					actual_buf, offset,
293 					sizeof(actual_buf),
294 					&service_offset,
295 					&instance_offset,
296 					&domain_offset);
297 
298 	zassert_equal(actual_int, expected_int, "");
299 
300 	zassert_equal(instance_offset, 40, "");
301 	zassert_equal(domain_offset, 23, "");
302 
303 	memmove(actual_buf, actual_buf + offset, actual_int);
304 	zassert_mem_equal(actual_buf, expected_buf,
305 			  MIN(actual_int, expected_int), "");
306 
307 	/* dns_sd_rec_is_valid failure */
308 	DNS_SD_REGISTER_TCP_SERVICE(null_label,
309 				NULL,
310 				"_x",
311 				"xx",
312 				DNS_SD_EMPTY_TXT,
313 				CONST_PORT);
314 	zassert_equal(-EINVAL, add_ptr_record(&null_label, ttl,
315 					      actual_buf, offset,
316 					      actual_int,
317 					      &service_offset,
318 					      &instance_offset,
319 					      &domain_offset), "");
320 
321 	/* buffer too small failure */
322 	zassert_equal(-ENOSPC, add_ptr_record(&nasxxxxxx, ttl,
323 					      actual_buf, offset, 0,
324 					      &service_offset,
325 					      &instance_offset,
326 					      &domain_offset), "");
327 
328 	/* offset too big for message compression (service) */
329 	zassert_equal(-E2BIG, add_ptr_record(&nasxxxxxx, ttl,
330 					     actual_buf, DNS_SD_PTR_MASK,
331 					     0xffff, &service_offset,
332 					     &instance_offset,
333 					     &domain_offset), "");
334 
335 	/* offset too big for message compression (instance) */
336 	zassert_equal(-E2BIG, add_ptr_record(&nasxxxxxx, ttl,
337 					     actual_buf, 0x3fff,
338 					     0xffff, &service_offset,
339 					     &instance_offset,
340 					     &domain_offset), "");
341 }
342 
343 /** Test for @ref add_txt_record */
ZTEST(dns_sd,test_add_txt_record)344 ZTEST(dns_sd, test_add_txt_record)
345 {
346 	const uint32_t ttl = DNS_SD_TXT_TTL;
347 	const uint32_t offset = 0;
348 	const uint16_t instance_offset = 0x28;
349 
350 	static uint8_t actual_buf[BUFSZ];
351 	static const uint8_t expected_buf[] = {
352 		0xc0, 0x28, 0x00, 0x10, 0x80, 0x01, 0x00, 0x00,
353 		0x11, 0x94, 0x00, 0x07, 0x06, 0x70, 0x61, 0x74,
354 		0x68, 0x3d, 0x2f
355 	};
356 	int expected_int = sizeof(expected_buf);
357 
358 	int actual_int = add_txt_record(&nasxxxxxx, ttl,
359 					instance_offset, actual_buf,
360 					offset,
361 					sizeof(actual_buf));
362 
363 	zassert_equal(actual_int, expected_int, "");
364 
365 	zassert_mem_equal(actual_buf, expected_buf, MIN(actual_int,
366 							expected_int),
367 			  "");
368 
369 	/* too big for message compression */
370 	zassert_equal(-E2BIG,
371 		      add_txt_record(&nasxxxxxx, ttl, DNS_SD_PTR_MASK,
372 				     actual_buf, offset,
373 				     sizeof(actual_buf)), "");
374 
375 	/* buffer too small */
376 	zassert_equal(-ENOSPC, add_txt_record(&nasxxxxxx, ttl, offset,
377 					      actual_buf, offset,
378 					      0), "");
379 }
380 
381 /** Test for @ref add_srv_record */
ZTEST(dns_sd,test_add_srv_record)382 ZTEST(dns_sd, test_add_srv_record)
383 {
384 	const uint32_t ttl = DNS_SD_SRV_TTL;
385 	const uint32_t offset = 0;
386 	const uint16_t instance_offset = 0x28;
387 	const uint16_t domain_offset = 0x17;
388 
389 	uint16_t host_offset = -1;
390 	static uint8_t actual_buf[BUFSZ];
391 	static const uint8_t expected_buf[] = {
392 		0xc0, 0x28, 0x00, 0x21, 0x80, 0x01, 0x00, 0x00,
393 		0x00, 0x78, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00,
394 		0x1f, 0x90, 0x09, 0x4e, 0x41, 0x53, 0x58, 0x58,
395 		0x58, 0x58, 0x58, 0x58, 0xc0, 0x17
396 	};
397 
398 	int expected_int = sizeof(expected_buf);
399 	int actual_int = add_srv_record(&nasxxxxxx, ttl,
400 					instance_offset, domain_offset,
401 					actual_buf,
402 					offset, sizeof(actual_buf),
403 					&host_offset);
404 
405 	zassert_equal(actual_int, expected_int, "");
406 
407 	zassert_equal(host_offset, 18, "");
408 
409 	zassert_mem_equal(actual_buf, expected_buf,
410 			  MIN(actual_int, expected_int), "");
411 
412 	/* offset too big for message compression (instance) */
413 	zassert_equal(-E2BIG,
414 		      add_srv_record(&nasxxxxxx, ttl, DNS_SD_PTR_MASK,
415 				     domain_offset,
416 				     actual_buf, offset,
417 				     sizeof(actual_buf),
418 				     &host_offset), "");
419 
420 	/* offset too big for message compression (domain) */
421 	zassert_equal(-E2BIG, add_srv_record(&nasxxxxxx, ttl,
422 					     instance_offset,
423 					     DNS_SD_PTR_MASK,
424 					     actual_buf, offset,
425 					     sizeof(actual_buf),
426 					     &host_offset), "");
427 
428 	/* buffer too small */
429 	zassert_equal(-ENOSPC, add_srv_record(&nasxxxxxx, ttl,
430 					      instance_offset,
431 					      domain_offset,
432 					      actual_buf,
433 					      offset, 0,
434 					      &host_offset), "");
435 }
436 
437 /** Test for @ref add_a_record */
ZTEST(dns_sd,test_add_a_record)438 ZTEST(dns_sd, test_add_a_record)
439 {
440 	const uint32_t ttl = DNS_SD_A_TTL;
441 	const uint32_t offset = 0;
442 	const uint16_t host_offset = 0x59;
443 	/* this one is made up */
444 	const uint32_t addr = IP_ADDR(177, 5, 240, 13);
445 
446 	static uint8_t actual_buf[BUFSZ];
447 	static const uint8_t expected_buf[] = {
448 		0xc0, 0x59, 0x00, 0x01, 0x80, 0x01, 0x00, 0x00,
449 		0x00, 0x78, 0x00, 0x04, 0xb1, 0x05, 0xf0, 0x0d,
450 	};
451 
452 	int expected_int = sizeof(expected_buf);
453 	int actual_int = add_a_record(&nasxxxxxx, ttl, host_offset,
454 				      addr, actual_buf, offset,
455 				      sizeof(actual_buf));
456 
457 	zassert_equal(actual_int, expected_int, "");
458 
459 	zassert_mem_equal(actual_buf, expected_buf,
460 			  MIN(actual_int, expected_int), "");
461 
462 	/* test offset too large */
463 	zassert_equal(-E2BIG,
464 		      add_a_record(&nasxxxxxx, ttl, DNS_SD_PTR_MASK,
465 				   addr, actual_buf, offset,
466 				   sizeof(actual_buf)), "");
467 
468 	/* test buffer too small */
469 	zassert_equal(-ENOSPC, add_a_record(&nasxxxxxx, ttl,
470 					    host_offset, addr,
471 					    actual_buf, offset,
472 					    0), "");
473 }
474 
475 /** Test for @ref add_aaaa_record */
ZTEST(dns_sd,test_add_aaaa_record)476 ZTEST(dns_sd, test_add_aaaa_record)
477 {
478 	const uint32_t ttl = DNS_SD_AAAA_TTL;
479 	const uint32_t offset = 0;
480 	const uint16_t host_offset = 0x59;
481 	/* this one is made up */
482 	const uint8_t addr[16] = {
483 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
484 	};
485 
486 	static uint8_t actual_buf[BUFSZ];
487 	static const uint8_t expected_buf[] = {
488 		0xc0, 0x59, 0x00, 0x1c, 0x80, 0x01, 0x00, 0x00,
489 		0x00, 0x78, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
490 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 		0x00, 0x00, 0x00, 0x01,
492 	};
493 
494 	int expected_int = sizeof(expected_buf);
495 	int actual_int = add_aaaa_record(&nasxxxxxx, ttl, host_offset,
496 					 addr, actual_buf, offset,
497 					 sizeof(actual_buf));
498 
499 	zassert_equal(actual_int, expected_int, "");
500 
501 	zassert_mem_equal(actual_buf, expected_buf,
502 			  MIN(actual_int, expected_int), "");
503 
504 	/* offset too large for message compression */
505 	zassert_equal(-E2BIG,
506 		      add_aaaa_record(&nasxxxxxx, ttl, DNS_SD_PTR_MASK,
507 				      addr, actual_buf,
508 				      offset,
509 				      sizeof(actual_buf)), "");
510 
511 	/* buffer too small */
512 	zassert_equal(-ENOSPC,
513 		      add_aaaa_record(&nasxxxxxx, ttl, host_offset,
514 				      addr, actual_buf,
515 				      offset, 0), "");
516 }
517 
518 /** Test for @ref dns_sd_handle_ptr_query */
ZTEST(dns_sd,test_dns_sd_handle_ptr_query)519 ZTEST(dns_sd, test_dns_sd_handle_ptr_query)
520 {
521 	struct in_addr addr = {
522 		.s_addr = htonl(IP_ADDR(177, 5, 240, 13)),
523 	};
524 	static uint8_t actual_rsp[512];
525 	static uint8_t expected_rsp[] = {
526 		0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x01,
527 		0x00, 0x00, 0x00, 0x03, 0x05, 0x5f, 0x68, 0x74,
528 		0x74, 0x70, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05,
529 		0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c,
530 		0x00, 0x01, 0x00, 0x00, 0x11, 0x94, 0x00, 0x0c,
531 		0x09, 0x4e, 0x41, 0x53, 0x58, 0x58, 0x58, 0x58,
532 		0x58, 0x58, 0xc0, 0x0c, 0xc0, 0x28, 0x00, 0x10,
533 		0x80, 0x01, 0x00, 0x00, 0x11, 0x94, 0x00, 0x07,
534 		0x06, 0x70, 0x61, 0x74, 0x68, 0x3d, 0x2f, 0xc0,
535 		0x28, 0x00, 0x21, 0x80, 0x01, 0x00, 0x00, 0x00,
536 		0x78, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x1f,
537 		0x90, 0x09, 0x4e, 0x41, 0x53, 0x58, 0x58, 0x58,
538 		0x58, 0x58, 0x58, 0xc0, 0x17, 0xc0, 0x59, 0x00,
539 		0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00,
540 		0x04, 0xb1, 0x05, 0xf0, 0x0d,
541 	};
542 	int expected_int = sizeof(expected_rsp);
543 	int actual_int = dns_sd_handle_ptr_query(&nasxxxxxx,
544 						 &addr,
545 						 NULL,
546 						 &actual_rsp[0],
547 						 sizeof(actual_rsp) -
548 						 sizeof(struct dns_header));
549 
550 	zassert_true(actual_int > 0,
551 		     "dns_sd_handle_ptr_query() failed (%d)",
552 		     actual_int);
553 
554 	zassert_equal(actual_int, expected_int, "act: %d exp: %d", actual_int, expected_int);
555 
556 	zassert_mem_equal(actual_rsp, expected_rsp,
557 			  MIN(actual_int, expected_int), "");
558 
559 	/* show non-advertisement for uninitialized port */
560 	nonconst_port = 0;
561 	zassert_equal(-EHOSTDOWN, dns_sd_handle_ptr_query(&nasxxxxxx_ephemeral,
562 		&addr, NULL, &actual_rsp[0], sizeof(actual_rsp) -
563 		sizeof(struct dns_header)), "port zero should not "
564 		"produce any DNS-SD query response");
565 
566 	/* show advertisement for initialized port */
567 	nonconst_port = CONST_PORT;
568 	expected_int = sizeof(expected_rsp);
569 	zassert_equal(expected_int, dns_sd_handle_ptr_query(&nasxxxxxx_ephemeral,
570 		&addr, NULL, &actual_rsp[0], sizeof(actual_rsp) -
571 		sizeof(struct dns_header)), "");
572 
573 	zassert_equal(-EINVAL, dns_sd_handle_ptr_query(
574 		&invalid_dns_sd_record,
575 		&addr, NULL, &actual_rsp[0], sizeof(actual_rsp) -
576 		sizeof(struct dns_header)), "");
577 }
578 
579 /** Test for @ref dns_sd_handle_ptr_query */
ZTEST(dns_sd,test_dns_sd_handle_service_type_enum)580 ZTEST(dns_sd, test_dns_sd_handle_service_type_enum)
581 {
582 	DNS_SD_REGISTER_TCP_SERVICE(chromecast,
583 				"Chromecast-abcd",
584 				"_googlecast",
585 				"local",
586 				DNS_SD_EMPTY_TXT,
587 				CONST_PORT);
588 
589 	struct in_addr addr = {
590 		.s_addr = htonl(IP_ADDR(177, 5, 240, 13)),
591 	};
592 	static uint8_t actual_rsp[512];
593 	static uint8_t expected_rsp[] = {
594 		0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
595 		0x00, 0x00, 0x00, 0x09, 0x5f, 0x73, 0x65, 0x72, 0x76,
596 		0x69, 0x63, 0x65, 0x73, 0x07, 0x5f, 0x64, 0x6e, 0x73,
597 		0x2d, 0x73, 0x64, 0x04, 0x5f, 0x75, 0x64, 0x70, 0x05,
598 		0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00,
599 		0x01, 0x00, 0x00, 0x11, 0x94, 0x00, 0x13, 0x0b, 0x5f,
600 		0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73,
601 		0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0xc0, 0x23,
602 	};
603 	int expected_int = sizeof(expected_rsp);
604 	int actual_int = dns_sd_handle_service_type_enum(&chromecast,
605 						 &addr,
606 						 NULL,
607 						 &actual_rsp[0],
608 						 sizeof(actual_rsp) -
609 						 sizeof(struct dns_header));
610 
611 	zassert_true(actual_int > 0, "dns_sd_handle_service_type_enum() failed (%d)", actual_int);
612 
613 	zassert_equal(actual_int, expected_int, "act: %d exp: %d", actual_int, expected_int);
614 
615 	zassert_mem_equal(actual_rsp, expected_rsp, MIN(actual_int, expected_int), "");
616 
617 	/* show non-advertisement for uninitialized port */
618 	nonconst_port = 0;
619 	zassert_equal(-EHOSTDOWN,
620 		      dns_sd_handle_service_type_enum(&nasxxxxxx_ephemeral, &addr, NULL,
621 				&actual_rsp[0], sizeof(actual_rsp) - sizeof(struct dns_header)),
622 		      "port zero should not "
623 		      "produce any DNS-SD query response");
624 
625 	zassert_equal(-EINVAL,
626 		      dns_sd_handle_service_type_enum(&invalid_dns_sd_record, &addr, NULL,
627 			  &actual_rsp[0], sizeof(actual_rsp) - sizeof(struct dns_header)),
628 		      "");
629 }
630 
631 /** Test @ref dns_sd_rec_match */
ZTEST(dns_sd,test_dns_sd_rec_match)632 ZTEST(dns_sd, test_dns_sd_rec_match)
633 {
634 	DNS_SD_REGISTER_TCP_SERVICE(record,
635 				    "NGINX",
636 				    "_http",
637 				    "local",
638 				    DNS_SD_EMPTY_TXT,
639 				    CONST_PORT);
640 
641 	static const struct dns_sd_rec filter_ok = {
642 		.instance = NULL,
643 		.service = "_http",
644 		.proto = "_tcp",
645 		.domain = NULL,
646 		.text = NULL,
647 		.text_size = 0,
648 		.port = NULL,
649 	};
650 
651 	static const struct dns_sd_rec filter_nok = {
652 		.instance = NULL,
653 		.service = "_wtftp",
654 		.proto = "_udp",
655 		.domain = NULL,
656 		.text = NULL,
657 		.text_size = 0,
658 		.port = NULL,
659 	};
660 
661 	zassert_equal(false, dns_sd_rec_match(NULL, NULL), "");
662 	zassert_equal(false, dns_sd_rec_match(NULL, &filter_ok), "");
663 	zassert_equal(false, dns_sd_rec_match(&record, NULL), "");
664 	zassert_equal(false, dns_sd_rec_match(&record, &filter_nok), "");
665 	zassert_equal(true, dns_sd_rec_match(&record, &filter_ok), "");
666 }
667 
668 /** Test @ref setup_dst_addr */
ZTEST(dns_sd,test_setup_dst_addr)669 ZTEST(dns_sd, test_setup_dst_addr)
670 {
671 	struct net_if *iface;
672 	struct sockaddr dst;
673 	socklen_t dst_len;
674 	socklen_t optlen;
675 	int ttl;
676 
677 	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY));
678 	zassert_not_null(iface, "Interface not available");
679 
680 	/* IPv4 case */
681 	int v4;
682 	struct in_addr addr_v4_expect = { { { 224, 0, 0, 251 } } };
683 
684 	memset(&dst, 0, sizeof(struct sockaddr));
685 
686 	v4 = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
687 	zassert_true(v4 >= 0, "Create IPv4 UDP context failed (%d)", -errno);
688 
689 	zassert_equal(0, setup_dst_addr(v4, AF_INET, NULL, 0, &dst, &dst_len), "");
690 
691 	optlen = sizeof(int);
692 	(void)zsock_getsockopt(v4, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, &optlen);
693 
694 	zassert_equal(255, ttl, "TTL invalid (%d vs %d)", 255, ttl);
695 	zassert_true(net_ipv4_addr_cmp(&addr_v4_expect,
696 				       &net_sin(&dst)->sin_addr), "");
697 	zassert_equal(8, dst_len, "");
698 
699 	(void)zsock_close(v4);
700 
701 #if defined(CONFIG_NET_IPV6)
702 	/* IPv6 case */
703 	int v6;
704 	struct in6_addr addr_v6_expect = { { { 0xff, 0x02, 0, 0, 0, 0, 0, 0,
705 		0, 0, 0, 0, 0, 0, 0, 0xfb } } };
706 
707 	memset(&dst, 0, sizeof(struct sockaddr));
708 
709 	v6 = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
710 	zassert_true(v6 >= 0, "Create IPv6 UDP context failed (%d)", -errno);
711 
712 	zassert_equal(0, setup_dst_addr(v6, AF_INET6, NULL, 0, &dst, &dst_len), "");
713 
714 	optlen = sizeof(int);
715 	(void)zsock_getsockopt(v6, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, &optlen);
716 
717 	zassert_equal(255, ttl, "Hoplimit invalid (%d vs %d)", 255, ttl);
718 	zassert_true(net_ipv6_addr_cmp(&addr_v6_expect,
719 				       &net_sin6(&dst)->sin6_addr), "");
720 	zassert_equal(24, dst_len, "");
721 
722 	(void)zsock_close(v6);
723 #endif
724 
725 	/* Unknown family case */
726 
727 	int xx;
728 
729 	xx = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
730 	zassert_true(xx >= 0, "Create IPV4 udp socket failed");
731 
732 	zassert_equal(-EPFNOSUPPORT,
733 		      setup_dst_addr(xx, AF_PACKET, NULL, 0, &dst, &dst_len), "");
734 }
735 
736 /** test for @ref dns_sd_is_service_type_enumeration */
ZTEST(dns_sd,test_is_service_type_enumeration)737 ZTEST(dns_sd, test_is_service_type_enumeration)
738 {
739 	static const struct dns_sd_rec filter_ok = {
740 		.instance = "_services",
741 		.service = "_dns-sd",
742 		.proto = "_udp",
743 		/* TODO: support additional service domains */
744 		.domain = "local",
745 		.text = dns_sd_empty_txt,
746 		.text_size = sizeof(dns_sd_empty_txt),
747 		.port = &dns_sd_port_zero,
748 	};
749 
750 	zassert_true(dns_sd_is_service_type_enumeration(&filter_ok), "");
751 
752 	static const struct dns_sd_rec filter_nok = {
753 		/* not a service_type_enumeration */
754 		.instance = "_serv1c3s",   .service = "_dns-sd",
755 		.proto = "_udp",	   .domain = "local",
756 		.text = dns_sd_empty_txt,  .text_size = sizeof(dns_sd_empty_txt),
757 		.port = &dns_sd_port_zero,
758 	};
759 
760 	zassert_false(dns_sd_is_service_type_enumeration(&filter_nok), "");
761 }
762 
ZTEST(dns_sd,test_extract_service_type_enumeration)763 ZTEST(dns_sd, test_extract_service_type_enumeration)
764 {
765 	static const uint8_t query[] = {
766 		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x09, 0x5f,
767 		0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x07, 0x5f, 0x64, 0x6e, 0x73, 0x2d,
768 		0x73, 0x64, 0x04, 0x5f, 0x75, 0x64, 0x70, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00,
769 	};
770 
771 	struct dns_sd_rec record;
772 	char instance[DNS_SD_INSTANCE_MAX_SIZE + 1];
773 	char service[DNS_SD_SERVICE_MAX_SIZE + 1];
774 	char proto[DNS_SD_PROTO_SIZE + 1];
775 	char domain[DNS_SD_DOMAIN_MAX_SIZE + 1];
776 	char *label[4];
777 	size_t size[] = {
778 		ARRAY_SIZE(instance),
779 		ARRAY_SIZE(service),
780 		ARRAY_SIZE(proto),
781 		ARRAY_SIZE(domain),
782 	};
783 	size_t n = ARRAY_SIZE(label);
784 
785 	BUILD_ASSERT(ARRAY_SIZE(label) == ARRAY_SIZE(size), "");
786 
787 	/*
788 	 * work around for bug in compliance scripts which say that the array
789 	 * should be static const (incorrect)
790 	 */
791 	label[0] = instance;
792 	label[1] = service;
793 	label[2] = proto;
794 	label[3] = domain;
795 
796 	zassert_equal(ARRAY_SIZE(query),
797 		      dns_sd_query_extract(query, ARRAY_SIZE(query), &record, label, size, &n),
798 		      "failed to extract service type enumeration");
799 
800 	zassert_true(dns_sd_is_service_type_enumeration(&record), "");
801 }
802 
ZTEST(dns_sd,test_wildcard_comparison)803 ZTEST(dns_sd, test_wildcard_comparison)
804 {
805 	size_t n_matches = 0;
806 	size_t n_records = 0;
807 	struct dns_sd_rec filter;
808 
809 	dns_sd_create_wildcard_filter(&filter);
810 
811 	DNS_SD_FOREACH(record) {
812 		if (!rec_is_valid(record)) {
813 			continue;
814 		}
815 
816 		++n_records;
817 	}
818 
819 	DNS_SD_FOREACH(record) {
820 		if (!rec_is_valid(record)) {
821 			continue;
822 		}
823 
824 		if (dns_sd_rec_match(record, &filter)) {
825 			++n_matches;
826 		}
827 	}
828 
829 	zassert_true(n_records > 0, "there must be > 0 records");
830 	zassert_equal(n_matches, n_records, "wildcard filter does not match "
831 		"all records: n_records: %zu n_matches: %zu", n_records, n_matches);
832 }
833 
834 ZTEST_SUITE(dns_sd, NULL, NULL, NULL, NULL, NULL);
835