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