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