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