The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
dns_tests.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** Tests for DNS label encoding / decoding
18 *
19 * @file src/lib/util/test/dns_tests.c
20 *
21 * @copyright 2026 Network RADIUS SAS (legal@networkradius.com)
22 */
23
24#include "acutest_common_init.h"
25#include "acutest_helpers.h"
26#include <freeradius-devel/util/value.h>
27#include <freeradius-devel/util/dns.h>
28
29#define DNS_HDR_LEN 12
30
31/*
32 * Helper: set up an fr_dns_labels_t with tracking blocks.
33 */
35static uint8_t test_marker[65536];
36
37static void labels_init(fr_dns_labels_t *lb, uint8_t const *packet, size_t packet_len, bool use_mark)
38{
39 lb->max = 256;
40 lb->blocks = test_blocks;
41 lb->start = packet;
42 lb->end = packet + packet_len;
43 lb->num = 1;
44 lb->blocks[0].start = DNS_HDR_LEN;
45 lb->blocks[0].end = DNS_HDR_LEN;
46
47 if (use_mark) {
48 fr_assert(packet_len <= sizeof(test_marker));
49 memset(test_marker, 0, packet_len);
50 lb->mark = test_marker;
51 } else {
52 lb->mark = NULL;
53 }
54}
55
56/*
57 * Helper: encode a string into DNS label format in a buffer.
58 * Returns total bytes written at 'where', or < 0 on error.
59 */
60static ssize_t encode_label(uint8_t *buf, size_t buf_len, uint8_t *where,
61 char const *str, bool compression, fr_dns_labels_t *lb)
62{
63 return fr_dns_label_from_value_box(NULL, buf, buf_len, where, compression, fr_box_strvalue(str), lb);
64}
65
66/*
67 * Encoding tests
68 *
69 */
70
71static void test_encode_empty_string(void)
72{
73 ssize_t slen;
74 uint8_t buf[256] = {};
75
76 /* empty string => single 0x00 byte */
77 slen = encode_label(buf, sizeof(buf), buf, "", false, NULL);
78 TEST_CHECK(slen == 1);
79 TEST_CHECK(buf[0] == 0x00);
80}
81
82static void test_encode_root_dot(void)
83{
84 ssize_t slen;
85 uint8_t buf[256] = {};
86
87 /* "." => single 0x00 byte */
88 slen = encode_label(buf, sizeof(buf), buf, ".", false, NULL);
89 TEST_CHECK(slen == 1);
90 TEST_CHECK(buf[0] == 0x00);
91}
92
93static void test_encode_simple_label(void)
94{
95 ssize_t slen;
96 uint8_t buf[256] = {};
97
98 /* "com" => 03 63 6f 6d 00 */
99 slen = encode_label(buf, sizeof(buf), buf, "com", false, NULL);
100 TEST_CHECK(slen == 5);
101 TEST_MSG("Expected 5, got %zd", slen);
102 TEST_CHECK(buf[0] == 3);
103 TEST_CHECK(memcmp(buf + 1, "com", 3) == 0);
104 TEST_CHECK(buf[4] == 0x00);
105}
106
107static void test_encode_multi_label(void)
108{
109 ssize_t slen;
110 uint8_t buf[256] = {};
111
112 /* "www.example.com" => 03 www 07 example 03 com 00 */
113 slen = encode_label(buf, sizeof(buf), buf, "www.example.com", false, NULL);
114 TEST_CHECK(slen == 17);
115 TEST_MSG("Expected 17, got %zd", slen);
116 TEST_CHECK(buf[0] == 3);
117 TEST_CHECK(memcmp(buf + 1, "www", 3) == 0);
118 TEST_CHECK(buf[4] == 7);
119 TEST_CHECK(memcmp(buf + 5, "example", 7) == 0);
120 TEST_CHECK(buf[12] == 3);
121 TEST_CHECK(memcmp(buf + 13, "com", 3) == 0);
122 TEST_CHECK(buf[16] == 0x00);
123}
124
126{
127 ssize_t slen;
128 uint8_t buf[256] = {};
129
130 /* "example.com." trailing dot should be stripped */
131 slen = encode_label(buf, sizeof(buf), buf, "example.com.", false, NULL);
132 TEST_CHECK(slen == 13);
133 TEST_MSG("Expected 13, got %zd", slen);
134 /* same as "example.com" */
135 TEST_CHECK(buf[0] == 7);
136 TEST_CHECK(buf[8] == 3);
137 TEST_CHECK(buf[12] == 0x00);
138}
139
141{
142 ssize_t slen;
143 uint8_t buf[256] = {};
144
145 /* "_srv.example.com" - underscore allowed at label start */
146 slen = encode_label(buf, sizeof(buf), buf, "_srv.example.com", false, NULL);
147 TEST_CHECK(slen > 0);
148 TEST_MSG("Expected >0, got %zd", slen);
149 TEST_CHECK(buf[0] == 4); /* _srv is 4 chars */
150 TEST_CHECK(buf[1] == '_');
151}
152
153/*
154 * Encoding error paths
155 */
156static void test_encode_null_inputs(void)
157{
158 ssize_t slen;
159 uint8_t buf[256] = {};
160
161 /* NULL buf */
162 slen = fr_dns_label_from_value_box(NULL, NULL, 100, (uint8_t[100]){0}, false, fr_box_strvalue("test"), NULL);
163 TEST_CHECK(slen < 0);
164
165 /* zero buf_len */
166 slen = fr_dns_label_from_value_box(NULL, buf, 0, buf, false, fr_box_strvalue("test"), NULL);
167 TEST_CHECK(slen < 0);
168
169 /* NULL value */
170 slen = fr_dns_label_from_value_box(NULL, buf, sizeof(buf), buf, false, NULL, NULL);
171 TEST_CHECK(slen < 0);
172}
173
175{
176 ssize_t slen;
178 uint8_t buf[256] = {};
179
181 slen = fr_dns_label_from_value_box(NULL, buf, sizeof(buf), buf, false, &vb, NULL);
182 TEST_CHECK(slen < 0);
183}
184
186{
187 ssize_t slen;
188 uint8_t buf[256] = {};
189
190 /* space is invalid */
191 slen = encode_label(buf, sizeof(buf), buf, "hello world", false, NULL);
192 TEST_CHECK(slen < 0);
193
194 /* @ is invalid */
195 slen = encode_label(buf, sizeof(buf), buf, "user@host", false, NULL);
196 TEST_CHECK(slen < 0);
197
198 /* tab is invalid */
199 slen = encode_label(buf, sizeof(buf), buf, "a\tb", false, NULL);
200 TEST_CHECK(slen < 0);
201}
202
203static void test_encode_double_dot(void)
204{
205 ssize_t slen;
206 uint8_t buf[256] = {};
207
208 slen = encode_label(buf, sizeof(buf), buf, "www..example.com", false, NULL);
209 TEST_CHECK(slen < 0);
210}
211
212static void test_encode_leading_dot(void)
213{
214 ssize_t slen;
215 uint8_t buf[256] = {};
216
217 slen = encode_label(buf, sizeof(buf), buf, ".example.com", false, NULL);
218 TEST_CHECK(slen < 0);
219}
220
222{
223 ssize_t slen;
224 char label[65];
225 uint8_t buf[256] = {};
226
227 /* 64-char label exceeds the 63-byte limit */
228 memset(label, 'a', 64);
229 label[64] = '\0';
230 slen = encode_label(buf, sizeof(buf), buf, label, false, NULL);
231 TEST_CHECK(slen < 0);
232}
233
235{
236 ssize_t slen;
237 size_t need = 0;
238 uint8_t buf[5] = {}; /* too small for "example.com" */
239
240 slen = fr_dns_label_from_value_box(&need, buf, sizeof(buf), buf, false,
241 fr_box_strvalue("example.com"), NULL);
242 TEST_CHECK(slen == 0); /* returns 0 when buffer too small */
243 TEST_CHECK(need == 13);
244 TEST_MSG("need=%zu, buf_len=%zu", need, sizeof(buf));
245}
246
248{
249 ssize_t slen;
250 uint8_t outside[16];
251 uint8_t buf[256] = {};
252
253 /* 'where' pointer is outside the buffer */
254 slen = fr_dns_label_from_value_box(NULL, buf, sizeof(buf), outside, false, fr_box_strvalue("test"), NULL);
255 TEST_CHECK(slen < 0);
256}
257
258/*
259 * Decode / uncompressed length tests
260 */
261
263{
264 uint8_t const *next;
265 ssize_t slen;
266 uint8_t pkt[DNS_HDR_LEN + 5];
267
268 memset(pkt, 0, DNS_HDR_LEN);
269 pkt[12] = 3;
270 pkt[13] = 'c'; pkt[14] = 'o'; pkt[15] = 'm';
271 pkt[16] = 0x00;
272
273 next = pkt + DNS_HDR_LEN;
274 slen = fr_dns_label_uncompressed_length(pkt, pkt + DNS_HDR_LEN, 5, &next, NULL);
275 TEST_CHECK(slen == 3);
276 TEST_MSG("Expected 3, got %zd", slen);
277 TEST_CHECK(next == pkt + 17);
278}
279
280static void test_decode_multi_label(void)
281{
282 ssize_t slen;
283 uint8_t const *next;
284 uint8_t pkt[DNS_HDR_LEN + 17]; /* "www.example.com" */
285
286 memset(pkt, 0, DNS_HDR_LEN);
287 pkt[12] = 3; memcpy(pkt + 13, "www", 3);
288 pkt[16] = 7; memcpy(pkt + 17, "example", 7);
289 pkt[24] = 3; memcpy(pkt + 25, "com", 3);
290 pkt[28] = 0x00;
291
292 next = pkt + DNS_HDR_LEN;
293 slen = fr_dns_label_uncompressed_length(pkt, pkt + DNS_HDR_LEN, 17, &next, NULL);
294 TEST_CHECK(slen == 15);
295 TEST_MSG("Expected 15, got %zd", slen);
296 TEST_CHECK(next == pkt + 29);
297}
298
299static void test_decode_root_label(void)
300{
301 ssize_t slen;
302 uint8_t const *next;
303 uint8_t pkt[DNS_HDR_LEN + 1];
304
305 memset(pkt, 0, DNS_HDR_LEN);
306 pkt[12] = 0x00;
307
308 next = pkt + DNS_HDR_LEN;
309 slen = fr_dns_label_uncompressed_length(pkt, pkt + DNS_HDR_LEN, 1, &next, NULL);
310 TEST_CHECK(slen == 1);
311 TEST_MSG("Expected 1, got %zd", slen);
312}
313
315{
316 ssize_t slen;
317 uint8_t const *next;
319 uint8_t pkt[DNS_HDR_LEN + 11];
320
321 memset(pkt, 0, DNS_HDR_LEN);
322 pkt[12] = 3; pkt[13] = 'c'; pkt[14] = 'o'; pkt[15] = 'm'; pkt[16] = 0x00;
323 pkt[17] = 3; pkt[18] = 'f'; pkt[19] = 'o'; pkt[20] = 'o';
324 pkt[21] = 0xc0; pkt[22] = 0x0c; /* pointer to offset 12 */
325
326 labels_init(&lb, pkt, sizeof(pkt), true);
327 test_marker[12] = 1;
328
329 next = pkt + 17;
330 slen = fr_dns_label_uncompressed_length(pkt, pkt + 17, 6, &next, &lb);
331 TEST_CHECK(slen == 7);
332 TEST_MSG("Expected 7, got %zd", slen);
333 TEST_CHECK(next == pkt + 23);
334}
335
337{
338 ssize_t slen;
339 uint8_t const *next;
340 uint8_t pkt[DNS_HDR_LEN + 8];
341
342 memset(pkt, 0, DNS_HDR_LEN);
343 pkt[12] = 0xc0; pkt[13] = 17; /* forward pointer */
344 pkt[14] = 3; pkt[15] = 'c'; pkt[16] = 'o'; pkt[17] = 'm'; pkt[18] = 0x00;
345
346 next = pkt + DNS_HDR_LEN;
347 slen = fr_dns_label_uncompressed_length(pkt, pkt + DNS_HDR_LEN, 8, &next, NULL);
348 TEST_CHECK(slen <= 0);
349 TEST_MSG("Forward pointer should be rejected, got %zd", slen);
350}
351
353{
354 ssize_t slen;
355 uint8_t const *next;
356 uint8_t pkt[DNS_HDR_LEN + 2];
357
358 memset(pkt, 0, DNS_HDR_LEN);
359 pkt[12] = 0xc0; pkt[13] = 12;
360
361 next = pkt + DNS_HDR_LEN;
362 slen = fr_dns_label_uncompressed_length(pkt, pkt + DNS_HDR_LEN, 2, &next, NULL);
363 TEST_CHECK(slen <= 0);
364 TEST_MSG("Self-pointer should be rejected, got %zd", slen);
365}
366
368{
369 ssize_t slen;
370 uint8_t const *next;
371 uint8_t pkt[DNS_HDR_LEN + 9];
372
373 memset(pkt, 0, DNS_HDR_LEN);
374 pkt[12] = 3; pkt[13] = 'c'; pkt[14] = 'o'; pkt[15] = 'm'; pkt[16] = 0x00;
375 pkt[17] = 0xc0; pkt[18] = 0x0c;
376 pkt[19] = 0xc0; pkt[20] = 0x11; /* pointer to offset 17 (which is a pointer) */
377
378 next = pkt + 19;
379 slen = fr_dns_label_uncompressed_length(pkt, pkt + 19, 2, &next, NULL);
380 TEST_CHECK(slen <= 0);
381 TEST_MSG("Pointer-to-pointer should be rejected, got %zd", slen);
382}
383
385{
386 ssize_t slen;
387 uint8_t const *next;
388 uint8_t pkt[DNS_HDR_LEN + 2];
389
390 memset(pkt, 0, DNS_HDR_LEN);
391 pkt[12] = 0x80; pkt[13] = 0x00;
392
393 next = pkt + DNS_HDR_LEN;
394 slen = fr_dns_label_uncompressed_length(pkt, pkt + DNS_HDR_LEN, 2, &next, NULL);
395 TEST_CHECK(slen <= 0);
396 TEST_MSG("0x80 high bits should be rejected, got %zd", slen);
397}
398
400{
401 ssize_t slen;
402 uint8_t const *next;
403 uint8_t pkt[DNS_HDR_LEN + 4];
404
405 memset(pkt, 0, DNS_HDR_LEN);
406 pkt[12] = 10; /* 10 bytes, but only 3 available */
407 pkt[13] = 'a'; pkt[14] = 'b'; pkt[15] = 'c';
408
409 next = pkt + DNS_HDR_LEN;
410 slen = fr_dns_label_uncompressed_length(pkt, pkt + DNS_HDR_LEN, 4, &next, NULL);
411 TEST_CHECK(slen <= 0);
412 TEST_MSG("Overflow should be rejected, got %zd", slen);
413}
414
415static void test_decode_null_inputs(void)
416{
417 ssize_t slen;
418 uint8_t const *next = NULL;
419
420 slen = fr_dns_label_uncompressed_length(NULL, (uint8_t const *)"x", 1, &next, NULL);
421 TEST_CHECK(slen == 0);
422
423 slen = fr_dns_label_uncompressed_length((uint8_t const *)"x", NULL, 1, &next, NULL);
424 TEST_CHECK(slen == 0);
425
426 {
427 uint8_t pkt[1] = {0};
428 slen = fr_dns_label_uncompressed_length(pkt, pkt, 0, &next, NULL);
429 TEST_CHECK(slen == 0);
430 }
431
432 {
433 uint8_t pkt[13];
434 memset(pkt, 0, sizeof(pkt));
435 slen = fr_dns_label_uncompressed_length(pkt, pkt + 12, 1, NULL, NULL);
436 TEST_CHECK(slen == 0);
437 }
438}
439
441{
442 ssize_t slen;
443 uint8_t const *next;
444 uint8_t pkt[DNS_HDR_LEN + 4];
445
446 memset(pkt, 0, DNS_HDR_LEN);
447 pkt[12] = 3; pkt[13] = 'a'; pkt[14] = ' '; pkt[15] = 'b';
448
449 next = pkt + DNS_HDR_LEN;
450 slen = fr_dns_label_uncompressed_length(pkt, pkt + DNS_HDR_LEN, 4, &next, NULL);
451 TEST_CHECK(slen <= 0);
452 TEST_MSG("Invalid char in label should be rejected, got %zd", slen);
453}
454
456{
457 uint8_t const *next;
458 ssize_t slen;
459 int i;
460 uint8_t pkt[DNS_HDR_LEN + 5*(1+52) + 1];
461 uint8_t *p = pkt + DNS_HDR_LEN;
462
463 memset(pkt, 0, DNS_HDR_LEN);
464
465 for (i = 0; i < 5; i++) {
466 *p++ = 52;
467 memset(p, 'a', 52);
468 p += 52;
469 }
470 *p++ = 0x00;
471
472 next = pkt + DNS_HDR_LEN;
473 slen = fr_dns_label_uncompressed_length(pkt, pkt + DNS_HDR_LEN, (size_t)(p - pkt - DNS_HDR_LEN), &next, NULL);
474 TEST_CHECK(slen <= 0);
475 TEST_MSG("Total length > 255 should be rejected, got %zd", slen);
476}
477
478/*
479 * network_verify tests
480 */
481
482static void test_verify_simple(void)
483{
484 ssize_t slen;
485 uint8_t pkt[DNS_HDR_LEN + 5];
486
487 memset(pkt, 0, DNS_HDR_LEN);
488 pkt[12] = 3; pkt[13] = 'c'; pkt[14] = 'o'; pkt[15] = 'm'; pkt[16] = 0x00;
489
490 slen = fr_dns_labels_network_verify(pkt, pkt + DNS_HDR_LEN, 5, pkt + DNS_HDR_LEN, NULL);
491 TEST_CHECK(slen > 0);
492 TEST_MSG("Expected >0, got %zd", slen);
493}
494
495static void test_verify_empty(void)
496{
497 ssize_t slen;
498 uint8_t pkt[DNS_HDR_LEN + 1];
499
500 memset(pkt, 0, DNS_HDR_LEN);
501 pkt[12] = 0x00;
502
503 slen = fr_dns_labels_network_verify(pkt, pkt + DNS_HDR_LEN, 1, pkt + DNS_HDR_LEN, NULL);
504 TEST_CHECK(slen > 0);
505}
506
507/* ----------------------------------------------------------------
508 * Round-trip tests: encode then decode
509 * ---------------------------------------------------------------- */
510
511static void test_roundtrip_simple(void)
512{
513 ssize_t enc_len, dec_len;
514 TALLOC_CTX *ctx = talloc_init("test");
515 fr_value_box_t vb_out;
516 uint8_t buf[256] = {};
517
518 enc_len = encode_label(buf, sizeof(buf), buf, "example.com", false, NULL);
519 TEST_CHECK(enc_len > 0);
520 TEST_MSG("encode returned %zd", enc_len);
521 if (enc_len <= 0) return;
522
523 dec_len = fr_dns_label_to_value_box(ctx, &vb_out, buf, enc_len, buf, false, NULL);
524 TEST_CHECK(dec_len > 0);
525 TEST_MSG("decode returned %zd", dec_len);
526
527 TEST_CHECK(vb_out.type == FR_TYPE_STRING);
528 TEST_CHECK(strcmp(vb_out.vb_strvalue, "example.com") == 0);
529 TEST_MSG("Expected 'example.com', got '%s'", vb_out.vb_strvalue);
530
531 fr_value_box_clear(&vb_out);
532 talloc_free(ctx);
533}
534
536{
537 ssize_t enc_len, dec_len;
538 TALLOC_CTX *ctx = talloc_init("test");
539 fr_value_box_t vb_out;
540 uint8_t buf[256] = {};
541
542 enc_len = encode_label(buf, sizeof(buf), buf, "example.com.", false, NULL);
543 TEST_CHECK(enc_len > 0);
544 if (enc_len <= 0) return;
545
546 dec_len = fr_dns_label_to_value_box(ctx, &vb_out, buf, enc_len, buf, false, NULL);
547 TEST_CHECK(dec_len > 0);
548 TEST_CHECK(vb_out.type == FR_TYPE_STRING);
549 TEST_CHECK(strcmp(vb_out.vb_strvalue, "example.com") == 0);
550 TEST_MSG("Expected 'example.com', got '%s'", vb_out.vb_strvalue);
551
552 fr_value_box_clear(&vb_out);
553 talloc_free(ctx);
554}
555
556static void test_roundtrip_root(void)
557{
558 ssize_t enc_len, dec_len;
559 TALLOC_CTX *ctx = talloc_init("test");
560 fr_value_box_t vb_out;
561 uint8_t buf[256] = {};
562
563 enc_len = encode_label(buf, sizeof(buf), buf, ".", false, NULL);
564 TEST_CHECK(enc_len == 1);
565 if (enc_len <= 0) return;
566
567 dec_len = fr_dns_label_to_value_box(ctx, &vb_out, buf, enc_len, buf, false, NULL);
568 TEST_CHECK(dec_len > 0);
569 TEST_CHECK(vb_out.type == FR_TYPE_STRING);
570 TEST_CHECK(strcmp(vb_out.vb_strvalue, ".") == 0);
571 TEST_MSG("Expected '.', got '%s'", vb_out.vb_strvalue);
572
573 fr_value_box_clear(&vb_out);
574 talloc_free(ctx);
575}
576
578{
579 ssize_t enc_len, dec_len;
580 TALLOC_CTX *ctx = talloc_init("test");
581 fr_value_box_t vb_out;
582 uint8_t buf[256] = {};
583
584 enc_len = encode_label(buf, sizeof(buf), buf, "_tcp.example.com", false, NULL);
585 TEST_CHECK(enc_len > 0);
586 if (enc_len <= 0) return;
587
588 dec_len = fr_dns_label_to_value_box(ctx, &vb_out, buf, enc_len, buf, false, NULL);
589 TEST_CHECK(dec_len > 0);
590 TEST_CHECK(strcmp(vb_out.vb_strvalue, "_tcp.example.com") == 0);
591 TEST_MSG("Expected '_tcp.example.com', got '%s'", vb_out.vb_strvalue);
592
593 fr_value_box_clear(&vb_out);
594 talloc_free(ctx);
595}
596
598{
599 ssize_t enc_len, dec_len;
600 TALLOC_CTX *ctx = talloc_init("test");
601 fr_value_box_t vb_out;
602 uint8_t buf[256] = {};
603
604 enc_len = encode_label(buf, sizeof(buf), buf, "WWW.Example.COM", false, NULL);
605 TEST_CHECK(enc_len > 0);
606 if (enc_len <= 0) return;
607
608 dec_len = fr_dns_label_to_value_box(ctx, &vb_out, buf, enc_len, buf, false, NULL);
609 TEST_CHECK(dec_len > 0);
610 TEST_CHECK(strcmp(vb_out.vb_strvalue, "WWW.Example.COM") == 0);
611 TEST_MSG("Expected 'WWW.Example.COM', got '%s'", vb_out.vb_strvalue);
612
613 fr_value_box_clear(&vb_out);
614 talloc_free(ctx);
615}
616
617/*
618 * Compression tests (encoding with compression)
619 */
620
621static void test_compress_two_names(void)
622{
623 ssize_t slen1, slen2;
625 uint8_t pkt[256] = {};
626
627 labels_init(&lb, pkt, sizeof(pkt), false);
628
629 slen1 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN, "example.com", true, &lb);
630 TEST_CHECK(slen1 > 0);
631 TEST_MSG("First encode: %zd", slen1);
632
633 slen2 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN + slen1, "foo.example.com", true, &lb);
634 TEST_CHECK(slen2 > 0);
635 TEST_MSG("Second encode: %zd", slen2);
636
637 /*
638 * Without compression: "foo.example.com" = 17 bytes
639 * With compression: "foo" (4 bytes) + pointer (2 bytes) = 6 bytes
640 */
641 TEST_CHECK(slen2 < 17);
642 TEST_MSG("Compressed size %zd should be < 17", slen2);
643}
644
645/** A compression pointer has 14 bits of offset, and cannot point at a label which starts at offset 16384
646 *
647 * (16384 >> 8) | 0xc0 is 0xc0, which with a low byte of 0 would point at the packet header.
648 */
650{
651 ssize_t slen1, slen2;
652 static uint8_t pkt[(1 << 14) + 256];
653 uint8_t *where;
654
655 memset(pkt, 0, sizeof(pkt));
656
657 where = pkt + (1 << 14) - 8;
658 slen1 = encode_label(pkt, sizeof(pkt), where, "example.com", true, NULL);
659 TEST_CHECK(slen1 == 13);
660 TEST_MSG("First encode: %zd", slen1);
661
662 where += slen1;
663 slen2 = encode_label(pkt, sizeof(pkt), where, "foo.com", true, NULL);
664 TEST_CHECK(slen2 == 9);
665 TEST_MSG("Second encode should not compress, got %zd bytes", slen2);
666}
667
668/* ----------------------------------------------------------------
669 * Decode: fr_dns_label_to_value_box error paths
670 * ---------------------------------------------------------------- */
671
673{
675 ssize_t slen;
676 uint8_t pkt[1] = {};
677
678 slen = fr_dns_label_to_value_box(NULL, &vb, pkt, 0, pkt, false, NULL);
679 TEST_CHECK(slen < 0);
680}
681
683{
685 ssize_t slen;
686 uint8_t other[16] = {};
687 uint8_t pkt[16] = {};
688
689 slen = fr_dns_label_to_value_box(NULL, &vb, pkt, sizeof(pkt), other, false, NULL);
690 TEST_CHECK(slen < 0);
691}
692
693/* ----------------------------------------------------------------
694 * Compression with label tracking (block-based)
695 * ---------------------------------------------------------------- */
696
698{
699 ssize_t slen;
701 uint8_t pkt[256] = {};
702
703 labels_init(&lb, pkt, sizeof(pkt), false);
704
705 slen = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN, "test.example.org", true, &lb);
706 TEST_CHECK(slen > 0);
707 TEST_MSG("encode returned %zd", slen);
708
709 TEST_CHECK(lb.num >= 1);
711}
712
714{
715 ssize_t slen;
716 uint8_t const *next;
717 uint8_t pkt[DNS_HDR_LEN + 11];
718
719 memset(pkt, 0, DNS_HDR_LEN);
720 pkt[12] = 3; pkt[13] = 'c'; pkt[14] = 'o'; pkt[15] = 'm'; pkt[16] = 0x00;
721 pkt[17] = 3; pkt[18] = 'f'; pkt[19] = 'o'; pkt[20] = 'o';
722 pkt[21] = 0xc0; pkt[22] = 0x0c;
723
724 next = pkt + 17;
725 slen = fr_dns_label_uncompressed_length(pkt, pkt + 17, 6, &next, NULL);
726 TEST_CHECK(slen == 7);
727 TEST_MSG("Expected 7, got %zd", slen);
728}
729
731{
732 ssize_t slen;
733 uint8_t const *next;
735 uint8_t pkt[DNS_HDR_LEN + 11];
736
737 memset(pkt, 0, DNS_HDR_LEN);
738 pkt[12] = 3; pkt[13] = 'c'; pkt[14] = 'o'; pkt[15] = 'm'; pkt[16] = 0x00;
739 pkt[17] = 3; pkt[18] = 'f'; pkt[19] = 'o'; pkt[20] = 'o';
740 pkt[21] = 0xc0; pkt[22] = 0x0c;
741
742 labels_init(&lb, pkt, sizeof(pkt), true);
743 /* Do NOT mark offset 12 */
744
745 next = pkt + 17;
746 slen = fr_dns_label_uncompressed_length(pkt, pkt + 17, 6, &next, &lb);
747 TEST_CHECK(slen <= 0);
748 TEST_MSG("Unmarked pointer target should be rejected, got %zd", slen);
749}
750
752{
753 ssize_t slen;
754 uint8_t const *next;
755 uint8_t pkt[DNS_HDR_LEN + 8];
756
757 memset(pkt, 0, DNS_HDR_LEN);
758 pkt[12] = 3; pkt[13] = 'c'; pkt[14] = 'o'; pkt[15] = 'm'; pkt[16] = 0x00;
759 pkt[17] = 0xc0; pkt[18] = 0x10; /* pointer to offset 16 (0x00 byte) */
760
761 next = pkt + 17;
762 slen = fr_dns_label_uncompressed_length(pkt, pkt + 17, 2, &next, NULL);
763 TEST_CHECK(slen <= 0);
764 TEST_MSG("Pointer to 0x00 should be rejected, got %zd", slen);
765}
766
767/*
768 * Encode: max label length (63 bytes exactly)
769 */
770
772{
773 ssize_t slen;
774 char label[64];
775 uint8_t buf[256] = {};
776
777 memset(label, 'a', 63);
778 label[63] = '\0';
779 slen = encode_label(buf, sizeof(buf), buf, label, false, NULL);
780 TEST_CHECK(slen == 65); /* 1 (length) + 63 (data) + 1 (terminator) */
781 TEST_MSG("Expected 65, got %zd", slen);
782}
783
785{
786 ssize_t slen;
787 uint8_t buf[256] = {};
788
789 slen = encode_label(buf, sizeof(buf), buf, "my-host-01.example.com", false, NULL);
790 TEST_CHECK(slen > 0);
791 TEST_MSG("Expected >0, got %zd", slen);
792}
793
794/* ----------------------------------------------------------------
795 * Roundtrip with compression
796 * ---------------------------------------------------------------- */
797
799{
800 ssize_t slen1, slen2, dec_len;
801 ssize_t uncomp_len;
802 uint8_t const *next_label;
803 fr_value_box_t vb_out;
805 TALLOC_CTX *ctx = talloc_init("test");
806 uint8_t pkt[256] = {};
807
808 labels_init(&lb, pkt, sizeof(pkt), false);
809
810 slen1 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN, "example.com", true, &lb);
811 TEST_CHECK(slen1 > 0);
812
813 slen2 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN + slen1, "foo.example.com", true, &lb);
814 TEST_CHECK(slen2 > 0);
815
816 next_label = pkt + DNS_HDR_LEN + slen1;
817 uncomp_len = fr_dns_label_uncompressed_length(pkt, pkt + DNS_HDR_LEN,
818 slen1 + slen2, &next_label, &lb);
819 TEST_CHECK(uncomp_len == 15);
820 TEST_MSG("Expected 15, got %zd", uncomp_len);
821
822 dec_len = fr_dns_label_to_value_box(ctx, &vb_out, pkt + DNS_HDR_LEN, slen1 + slen2,
823 pkt + DNS_HDR_LEN + slen1, false, &lb);
824 TEST_CHECK(dec_len > 0);
825 TEST_CHECK(vb_out.type == FR_TYPE_STRING);
826 TEST_CHECK(strcmp(vb_out.vb_strvalue, "foo.example.com") == 0);
827 TEST_MSG("Expected 'foo.example.com', got '%s'", vb_out.vb_strvalue);
828
829 fr_value_box_clear(&vb_out);
830 talloc_free(ctx);
831}
832
833/*
834 * Compression with 62 and 63 byte labels.
835 *
836 * These test both <= 63 checks in dns_label_compress():
837 *
838 * Path 1: recursive call when the NEXT label after the
839 * current one is still uncompressed. Tested by encoding "foo.LONG"
840 * where LONG is 62 or 63 bytes - the recursive call to compress LONG
841 * has *next == 62/63.
842 *
843 * Path 2: buffer scan where a candidate label is followed
844 * by an uncompressed label of length 62/63. Tested by encoding
845 * "bar.LONG" first (uncompressed), then "foo.LONG" - during the
846 * scan for "foo", we find "bar" whose next label (*ptr) is 62/63.
847 */
849{
850 ssize_t slen1, slen2, dec_len;
852 fr_value_box_t vb_out;
853 TALLOC_CTX *ctx = talloc_init("test");
854 char const *name1 = "bar.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
855 char const *name2 = "foo.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
856 uint8_t pkt[512] = {};
857
858 TEST_CHECK(strlen(name1) == 66);
859 TEST_CHECK(strlen(name2) == 66);
860
861 labels_init(&lb, pkt, sizeof(pkt), false);
862
863 /* First name goes in uncompressed */
864 slen1 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN, name1, true, &lb);
865 TEST_CHECK(slen1 > 0);
866 TEST_MSG("First encode: %zd", slen1);
867
868 /*
869 * Second name should compress the 62-byte suffix.
870 * Uncompressed would be 4 + 1 + 62 + 1 = 68 bytes.
871 * Compressed should be "foo" (4 bytes) + pointer (2 bytes) = 6 bytes.
872 */
873 slen2 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN + slen1, name2, true, &lb);
874 TEST_CHECK(slen2 > 0);
875 TEST_CHECK(slen2 < 68);
876 TEST_MSG("62-byte label compression: %zd (expected < 68)", slen2);
877
878 /* Round-trip decode to verify correctness */
879 dec_len = fr_dns_label_to_value_box(ctx, &vb_out, pkt + DNS_HDR_LEN,
880 slen1 + slen2,
881 pkt + DNS_HDR_LEN + slen1,
882 false, &lb);
883 TEST_CHECK(dec_len > 0);
884 TEST_CHECK(vb_out.type == FR_TYPE_STRING);
885 TEST_CHECK(strcmp(vb_out.vb_strvalue, name2) == 0);
886 TEST_MSG("Expected '%s', got '%s'", name2, vb_out.vb_strvalue);
887
888 fr_value_box_clear(&vb_out);
889 talloc_free(ctx);
890}
891
893{
894 ssize_t slen1, slen2, dec_len;
896 fr_value_box_t vb_out;
897 TALLOC_CTX *ctx = talloc_init("test");
898 char long63[64];
899 uint8_t pkt[512] = {};
900
901 /*
902 * The encoder limits non-first labels to 62 bytes (off-by-one in the dot tracking), so we test
903 * 63-byte labels as thue first (and only) label. Encode a standalone 63-byte label twice; the
904 * second should compress to a 2-byte pointer.
905 */
906 memset(long63, 'a', 63);
907 long63[63] = '\0';
908
909 labels_init(&lb, pkt, sizeof(pkt), false);
910
911 slen1 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN, long63, true, &lb);
912 TEST_CHECK(slen1 == 65); /* 1 (length) + 63 (data) + 1 (terminator) */
913 TEST_MSG("First encode: %zd", slen1);
914
915 /* Duplicate name should fully compress to a 2-byte pointer */
916 slen2 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN + slen1, long63, true, &lb);
917 TEST_CHECK(slen2 > 0);
918 TEST_CHECK(slen2 == 2);
919 TEST_MSG("63-byte duplicate compression: %zd (expected 2)", slen2);
920
921 /* Round-trip decode the compressed entry */
922 dec_len = fr_dns_label_to_value_box(ctx, &vb_out, pkt + DNS_HDR_LEN,
923 slen1 + slen2,
924 pkt + DNS_HDR_LEN + slen1,
925 false, &lb);
926 TEST_CHECK(dec_len > 0);
927 TEST_CHECK(vb_out.type == FR_TYPE_STRING);
928 TEST_CHECK(strcmp(vb_out.vb_strvalue, long63) == 0);
929 TEST_MSG("Expected '%s', got '%s'", long63, vb_out.vb_strvalue);
930
931 fr_value_box_clear(&vb_out);
932 talloc_free(ctx);
933}
934
935/*
936 * The same tests, but with a three-label name so that the 62/63-byte
937 * label is a middle suffix. This exercises the Path 2 more
938 * directly: when scanning the buffer, the candidate "bar" is
939 * followed by an uncompressed 62/63-byte label which IS the suffix
940 * pointer target.
941 */
943{
944 ssize_t slen1, slen2;
946 char const *name1 = "bar.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com";
947 char const *name2 = "foo.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com";
948 uint8_t pkt[512] = {};
949
950 TEST_CHECK(strlen(name1) == 70); /* "bar." + 62 + ".com"*/
951 TEST_CHECK(strlen(name2) == 70);
952
953 labels_init(&lb, pkt, sizeof(pkt), false);
954
955 slen1 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN, name1, true, &lb);
956 TEST_CHECK(slen1 > 0);
957 TEST_MSG("First encode: %zd", slen1);
958
959 /*
960 * Compression produces "foo" + pointer to the "aaa...com" suffix. When scanning for "foo" in
961 * the buffer, the code finds "bar" whose next label is the 62-byte 'a' label (*ptr == 62). The
962 * <= 63 check at line 523 allows this to be recognized as the suffix target.
963 */
964 slen2 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN + slen1, name2, true, &lb);
965 TEST_CHECK(slen2 > 0);
966 TEST_CHECK(slen2 < slen1);
967 TEST_MSG("Compressed size %zd should be < %zd", slen2, slen1);
968}
969
971{
972 ssize_t slen1, slen2, dec_len;
974 fr_value_box_t vb_out;
975 TALLOC_CTX *ctx = talloc_init("test");
976 char const *name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com";
977 uint8_t pkt[512] = {};
978
979 /*
980 * Test compression of a multi-label name where the first label is 63 bytes. Encode "<63
981 * a's>.com" twice.
982 *
983 * On the second encode, dns_label_compress recursively compresses "com" first, then scans the
984 * buffer for the 63-byte label. The buffer scan at checks *ptr <= 63 where ptr points to the
985 * "com" label (3 bytes) after the 63-byte label in the first entry. It then verifies ptr ==
986 * suffix (both point to "com" in name1) and compares the 63-byte labels.
987 */
988 TEST_CHECK(strlen(name) == 67);
989
990 labels_init(&lb, pkt, sizeof(pkt), false);
991
992 slen1 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN, name, true, &lb);
993 TEST_CHECK(slen1 > 0);
994 TEST_MSG("First encode: %zd", slen1);
995
996 /* Duplicate should fully compress to a 2-byte pointer */
997 slen2 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN + slen1, name, true, &lb);
998 TEST_CHECK(slen2 > 0);
999 TEST_CHECK(slen2 == 2);
1000 TEST_MSG("Compressed size %zd (expected 2)", slen2);
1001
1002 /* Round-trip decode */
1003 dec_len = fr_dns_label_to_value_box(ctx, &vb_out, pkt + DNS_HDR_LEN,
1004 slen1 + slen2,
1005 pkt + DNS_HDR_LEN + slen1,
1006 false, &lb);
1007 TEST_CHECK(dec_len > 0);
1008 TEST_CHECK(vb_out.type == FR_TYPE_STRING);
1009 TEST_CHECK(strcmp(vb_out.vb_strvalue, name) == 0);
1010 TEST_MSG("Expected '%s', got '%s'", name, vb_out.vb_strvalue);
1011
1012 fr_value_box_clear(&vb_out);
1013 talloc_free(ctx);
1014}
1015
1017 /* Encoding */
1018 { "encode_empty_string", test_encode_empty_string },
1019 { "encode_root_dot", test_encode_root_dot },
1020 { "encode_simple_label", test_encode_simple_label },
1021 { "encode_multi_label", test_encode_multi_label },
1022 { "encode_trailing_dot", test_encode_trailing_dot },
1023 { "encode_underscore_prefix", test_encode_underscore_prefix },
1024 { "encode_max_label_length", test_encode_max_label_length },
1025 { "encode_hyphen_and_digits", test_encode_hyphen_and_digits },
1026
1027 /* Encoding errors */
1028 { "encode_null_inputs", test_encode_null_inputs },
1029 { "encode_non_string_type", test_encode_non_string_type },
1030 { "encode_invalid_chars", test_encode_invalid_chars },
1031 { "encode_double_dot", test_encode_double_dot },
1032 { "encode_leading_dot", test_encode_leading_dot },
1033 { "encode_label_too_long", test_encode_label_too_long },
1034 { "encode_buffer_too_small", test_encode_buffer_too_small },
1035 { "encode_where_outside_buf", test_encode_where_outside_buf },
1036
1037 /* Decoding / uncompressed length */
1038 { "decode_simple_label", test_decode_simple_label },
1039 { "decode_multi_label", test_decode_multi_label },
1040 { "decode_root_label", test_decode_root_label },
1041 { "decode_compressed_pointer", test_decode_compressed_pointer },
1042 { "decode_null_inputs", test_decode_null_inputs },
1043 { "decode_label_invalid_chars", test_decode_label_invalid_chars },
1044 { "decode_total_length_exceeds_255", test_decode_total_length_exceeds_255 },
1045
1046 /* Decode error paths */
1047 { "decode_forward_pointer_rejected", test_decode_forward_pointer_rejected },
1048 { "decode_self_pointer_rejected", test_decode_self_pointer_rejected },
1049 { "decode_pointer_to_pointer_rejected", test_decode_pointer_to_pointer_rejected },
1050 { "decode_invalid_high_bits", test_decode_invalid_high_bits },
1051 { "decode_label_overflow", test_decode_label_overflow },
1052 { "decode_pointer_to_zero_rejected", test_pointer_to_zero_label_rejected },
1053
1054 /* Network verify */
1055 { "verify_simple", test_verify_simple },
1056 { "verify_empty", test_verify_empty },
1057
1058 /* Value box decode errors */
1059 { "decode_vb_zero_len", test_decode_to_value_box_zero_len },
1060 { "decode_vb_label_outside_buf", test_decode_to_value_box_label_outside_buf },
1061
1062 /* Pointer tracking */
1063 { "pointer_valid_no_tracking", test_pointer_valid_no_tracking },
1064 { "pointer_invalid_with_mark", test_pointer_invalid_with_mark_tracking },
1065
1066 /* Label block tracking */
1067 { "labels_block_tracking", test_labels_block_tracking },
1068
1069 /* Round-trip */
1070 { "roundtrip_simple", test_roundtrip_simple },
1071 { "roundtrip_trailing_dot", test_roundtrip_trailing_dot },
1072 { "roundtrip_root", test_roundtrip_root },
1073 { "roundtrip_underscore", test_roundtrip_underscore },
1074 { "roundtrip_case_preservation", test_roundtrip_case_preservation },
1075
1076 /* Compression */
1077 { "compress_two_names", test_compress_two_names },
1078 { "compress_offset_too_large", test_compress_offset_too_large },
1079 { "roundtrip_compressed", test_roundtrip_compressed },
1080 { "compress_62_byte_label", test_compress_62_byte_label },
1081 { "compress_63_byte_label", test_compress_63_byte_label },
1082 { "compress_middle_62_byte_label", test_compress_middle_62_byte_label },
1083 { "compress_middle_63_byte_label", test_compress_middle_63_byte_label },
1084
1086};
#define TEST_CHECK(cond)
Definition acutest.h:101
#define TEST_TERMINATOR
Definition acutest.h:77
#define TEST_MSG(...)
Definition acutest.h:234
Common initialisation for acutest binaries.
ssize_t fr_dns_label_uncompressed_length(uint8_t const *packet, uint8_t const *buf, size_t buf_len, uint8_t const **next, fr_dns_labels_t *lb)
Get the uncompressed length of a DNS label in a network buffer.
Definition dns.c:883
ssize_t fr_dns_label_from_value_box(size_t *need, uint8_t *buf, size_t buf_len, uint8_t *where, bool compression, fr_value_box_t const *value, fr_dns_labels_t *lb)
Encode a single value box of type string, serializing its contents to a dns label.
Definition dns.c:636
ssize_t fr_dns_labels_network_verify(uint8_t const *packet, uint8_t const *buf, size_t buf_len, uint8_t const *start, fr_dns_labels_t *lb)
Verify that a network buffer contains valid DNS labels.
Definition dns.c:1136
ssize_t fr_dns_label_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *dst, uint8_t const *src, size_t len, uint8_t const *label, bool tainted, fr_dns_labels_t *lb)
Decode a fr_value_box_t from one DNS label.
Definition dns.c:1224
static void test_encode_multi_label(void)
Definition dns_tests.c:107
static void test_roundtrip_simple(void)
Definition dns_tests.c:511
TEST_LIST
Definition dns_tests.c:1016
static void test_encode_underscore_prefix(void)
Definition dns_tests.c:140
static void test_decode_self_pointer_rejected(void)
Definition dns_tests.c:352
static void test_encode_buffer_too_small(void)
Definition dns_tests.c:234
static void test_roundtrip_compressed(void)
Definition dns_tests.c:798
static void test_encode_root_dot(void)
Definition dns_tests.c:82
static void test_encode_where_outside_buf(void)
Definition dns_tests.c:247
static void test_encode_double_dot(void)
Definition dns_tests.c:203
static void test_decode_pointer_to_pointer_rejected(void)
Definition dns_tests.c:367
static void test_encode_label_too_long(void)
Definition dns_tests.c:221
static void labels_init(fr_dns_labels_t *lb, uint8_t const *packet, size_t packet_len, bool use_mark)
Definition dns_tests.c:37
static void test_encode_max_label_length(void)
Definition dns_tests.c:771
static void test_compress_middle_63_byte_label(void)
Definition dns_tests.c:970
static void test_verify_empty(void)
Definition dns_tests.c:495
static void test_decode_to_value_box_zero_len(void)
Definition dns_tests.c:672
#define DNS_HDR_LEN
Definition dns_tests.c:29
static fr_dns_block_t test_blocks[256]
Definition dns_tests.c:34
static void test_encode_null_inputs(void)
Definition dns_tests.c:156
static void test_compress_two_names(void)
Definition dns_tests.c:621
static void test_compress_63_byte_label(void)
Definition dns_tests.c:892
static void test_decode_compressed_pointer(void)
Definition dns_tests.c:314
static void test_encode_non_string_type(void)
Definition dns_tests.c:174
static void test_decode_label_invalid_chars(void)
Definition dns_tests.c:440
static void test_encode_trailing_dot(void)
Definition dns_tests.c:125
static void test_decode_label_overflow(void)
Definition dns_tests.c:399
static void test_pointer_invalid_with_mark_tracking(void)
Definition dns_tests.c:730
static void test_roundtrip_root(void)
Definition dns_tests.c:556
static void test_labels_block_tracking(void)
Definition dns_tests.c:697
static void test_encode_leading_dot(void)
Definition dns_tests.c:212
static void test_verify_simple(void)
Definition dns_tests.c:482
static void test_encode_invalid_chars(void)
Definition dns_tests.c:185
static void test_decode_root_label(void)
Definition dns_tests.c:299
static void test_compress_62_byte_label(void)
Definition dns_tests.c:848
static void test_decode_forward_pointer_rejected(void)
Definition dns_tests.c:336
static ssize_t encode_label(uint8_t *buf, size_t buf_len, uint8_t *where, char const *str, bool compression, fr_dns_labels_t *lb)
Definition dns_tests.c:60
static void test_decode_to_value_box_label_outside_buf(void)
Definition dns_tests.c:682
static void test_compress_middle_62_byte_label(void)
Definition dns_tests.c:942
static void test_compress_offset_too_large(void)
A compression pointer has 14 bits of offset, and cannot point at a label which starts at offset 16384...
Definition dns_tests.c:649
static void test_pointer_valid_no_tracking(void)
Definition dns_tests.c:713
static void test_roundtrip_trailing_dot(void)
Definition dns_tests.c:535
static uint8_t test_marker[65536]
Definition dns_tests.c:35
static void test_pointer_to_zero_label_rejected(void)
Definition dns_tests.c:751
static void test_encode_empty_string(void)
Definition dns_tests.c:71
static void test_encode_hyphen_and_digits(void)
Definition dns_tests.c:784
static void test_decode_total_length_exceeds_255(void)
Definition dns_tests.c:455
static void test_decode_null_inputs(void)
Definition dns_tests.c:415
static void test_decode_invalid_high_bits(void)
Definition dns_tests.c:384
static void test_roundtrip_case_preservation(void)
Definition dns_tests.c:597
static void test_roundtrip_underscore(void)
Definition dns_tests.c:577
static void test_decode_simple_label(void)
Definition dns_tests.c:262
static void test_decode_multi_label(void)
Definition dns_tests.c:280
static void test_encode_simple_label(void)
Definition dns_tests.c:93
talloc_free(hp)
uint16_t start
Definition dns.h:31
uint8_t const * start
start of packet
Definition dns.h:36
uint8_t const * end
end of the packet
Definition dns.h:37
fr_dns_block_t * blocks
maximum number of labels
Definition dns.h:41
uint8_t * mark
markup buffer used for decoding.
Definition dns.h:38
uint16_t end
Definition dns.h:32
int num
number of used labels
Definition dns.h:39
@ FR_TYPE_STRING
String of printable characters.
long int ssize_t
unsigned char uint8_t
#define fr_assert(_expr)
Definition rad_assert.h:37
static char const * name
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition value.c:4509
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
Definition value.h:640
#define fr_box_strvalue(_val)
Definition value.h:339