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 /*
656 * Label tracking ignores offsets past 2^14, so search the whole buffer instead.
657 */
658 memset(pkt, 0, sizeof(pkt));
659
660 /*
661 * "example" is 8 bytes, which puts the "com" label at offset 16384.
662 */
663 where = pkt + (1 << 14) - 8;
664 slen1 = encode_label(pkt, sizeof(pkt), where, "example.com", true, NULL);
665 TEST_CHECK(slen1 == 13);
666 TEST_MSG("First encode: %zd", slen1);
667
668 /*
669 * "foo.com" must not compress "com" into a pointer to offset 16384.
670 */
671 where += slen1;
672 slen2 = encode_label(pkt, sizeof(pkt), where, "foo.com", true, NULL);
673 TEST_CHECK(slen2 == 9);
674 TEST_MSG("Second encode should not compress, got %zd bytes", slen2);
675}
676
677/* ----------------------------------------------------------------
678 * Decode: fr_dns_label_to_value_box error paths
679 * ---------------------------------------------------------------- */
680
682{
684 ssize_t slen;
685 uint8_t pkt[1] = {};
686
687 slen = fr_dns_label_to_value_box(NULL, &vb, pkt, 0, pkt, false, NULL);
688 TEST_CHECK(slen < 0);
689}
690
692{
694 ssize_t slen;
695 uint8_t other[16] = {};
696 uint8_t pkt[16] = {};
697
698 slen = fr_dns_label_to_value_box(NULL, &vb, pkt, sizeof(pkt), other, false, NULL);
699 TEST_CHECK(slen < 0);
700}
701
702/* ----------------------------------------------------------------
703 * Compression with label tracking (block-based)
704 * ---------------------------------------------------------------- */
705
707{
708 ssize_t slen;
710 uint8_t pkt[256] = {};
711
712 labels_init(&lb, pkt, sizeof(pkt), false);
713
714 slen = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN, "test.example.org", true, &lb);
715 TEST_CHECK(slen > 0);
716 TEST_MSG("encode returned %zd", slen);
717
718 TEST_CHECK(lb.num >= 1);
720}
721
723{
724 ssize_t slen;
725 uint8_t const *next;
726 uint8_t pkt[DNS_HDR_LEN + 11];
727
728 memset(pkt, 0, DNS_HDR_LEN);
729 pkt[12] = 3; pkt[13] = 'c'; pkt[14] = 'o'; pkt[15] = 'm'; pkt[16] = 0x00;
730 pkt[17] = 3; pkt[18] = 'f'; pkt[19] = 'o'; pkt[20] = 'o';
731 pkt[21] = 0xc0; pkt[22] = 0x0c;
732
733 next = pkt + 17;
734 slen = fr_dns_label_uncompressed_length(pkt, pkt + 17, 6, &next, NULL);
735 TEST_CHECK(slen == 7);
736 TEST_MSG("Expected 7, got %zd", slen);
737}
738
740{
741 ssize_t slen;
742 uint8_t const *next;
744 uint8_t pkt[DNS_HDR_LEN + 11];
745
746 memset(pkt, 0, DNS_HDR_LEN);
747 pkt[12] = 3; pkt[13] = 'c'; pkt[14] = 'o'; pkt[15] = 'm'; pkt[16] = 0x00;
748 pkt[17] = 3; pkt[18] = 'f'; pkt[19] = 'o'; pkt[20] = 'o';
749 pkt[21] = 0xc0; pkt[22] = 0x0c;
750
751 labels_init(&lb, pkt, sizeof(pkt), true);
752 /* Do NOT mark offset 12 */
753
754 next = pkt + 17;
755 slen = fr_dns_label_uncompressed_length(pkt, pkt + 17, 6, &next, &lb);
756 TEST_CHECK(slen <= 0);
757 TEST_MSG("Unmarked pointer target should be rejected, got %zd", slen);
758}
759
761{
762 ssize_t slen;
763 uint8_t const *next;
764 uint8_t pkt[DNS_HDR_LEN + 8];
765
766 memset(pkt, 0, DNS_HDR_LEN);
767 pkt[12] = 3; pkt[13] = 'c'; pkt[14] = 'o'; pkt[15] = 'm'; pkt[16] = 0x00;
768 pkt[17] = 0xc0; pkt[18] = 0x10; /* pointer to offset 16 (0x00 byte) */
769
770 next = pkt + 17;
771 slen = fr_dns_label_uncompressed_length(pkt, pkt + 17, 2, &next, NULL);
772 TEST_CHECK(slen <= 0);
773 TEST_MSG("Pointer to 0x00 should be rejected, got %zd", slen);
774}
775
776/*
777 * Encode: max label length (63 bytes exactly)
778 */
779
781{
782 ssize_t slen;
783 char label[64];
784 uint8_t buf[256] = {};
785
786 memset(label, 'a', 63);
787 label[63] = '\0';
788 slen = encode_label(buf, sizeof(buf), buf, label, false, NULL);
789 TEST_CHECK(slen == 65); /* 1 (length) + 63 (data) + 1 (terminator) */
790 TEST_MSG("Expected 65, got %zd", slen);
791}
792
794{
795 ssize_t slen;
796 uint8_t buf[256] = {};
797
798 slen = encode_label(buf, sizeof(buf), buf, "my-host-01.example.com", false, NULL);
799 TEST_CHECK(slen > 0);
800 TEST_MSG("Expected >0, got %zd", slen);
801}
802
803/* ----------------------------------------------------------------
804 * Roundtrip with compression
805 * ---------------------------------------------------------------- */
806
808{
809 ssize_t slen1, slen2, dec_len;
810 ssize_t uncomp_len;
811 uint8_t const *next_label;
812 fr_value_box_t vb_out;
814 TALLOC_CTX *ctx = talloc_init("test");
815 uint8_t pkt[256] = {};
816
817 labels_init(&lb, pkt, sizeof(pkt), false);
818
819 slen1 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN, "example.com", true, &lb);
820 TEST_CHECK(slen1 > 0);
821
822 slen2 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN + slen1, "foo.example.com", true, &lb);
823 TEST_CHECK(slen2 > 0);
824
825 next_label = pkt + DNS_HDR_LEN + slen1;
826 uncomp_len = fr_dns_label_uncompressed_length(pkt, pkt + DNS_HDR_LEN,
827 slen1 + slen2, &next_label, &lb);
828 TEST_CHECK(uncomp_len == 15);
829 TEST_MSG("Expected 15, got %zd", uncomp_len);
830
831 dec_len = fr_dns_label_to_value_box(ctx, &vb_out, pkt + DNS_HDR_LEN, slen1 + slen2,
832 pkt + DNS_HDR_LEN + slen1, false, &lb);
833 TEST_CHECK(dec_len > 0);
834 TEST_CHECK(vb_out.type == FR_TYPE_STRING);
835 TEST_CHECK(strcmp(vb_out.vb_strvalue, "foo.example.com") == 0);
836 TEST_MSG("Expected 'foo.example.com', got '%s'", vb_out.vb_strvalue);
837
838 fr_value_box_clear(&vb_out);
839 talloc_free(ctx);
840}
841
842/*
843 * Compression with 62 and 63 byte labels.
844 *
845 * These test both <= 63 checks in dns_label_compress():
846 *
847 * Path 1: recursive call when the NEXT label after the
848 * current one is still uncompressed. Tested by encoding "foo.LONG"
849 * where LONG is 62 or 63 bytes - the recursive call to compress LONG
850 * has *next == 62/63.
851 *
852 * Path 2: buffer scan where a candidate label is followed
853 * by an uncompressed label of length 62/63. Tested by encoding
854 * "bar.LONG" first (uncompressed), then "foo.LONG" - during the
855 * scan for "foo", we find "bar" whose next label (*ptr) is 62/63.
856 */
858{
859 ssize_t slen1, slen2, dec_len;
861 fr_value_box_t vb_out;
862 TALLOC_CTX *ctx = talloc_init("test");
863 char const *name1 = "bar.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
864 char const *name2 = "foo.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
865 uint8_t pkt[512] = {};
866
867 TEST_CHECK(strlen(name1) == 66);
868 TEST_CHECK(strlen(name2) == 66);
869
870 labels_init(&lb, pkt, sizeof(pkt), false);
871
872 /* First name goes in uncompressed */
873 slen1 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN, name1, true, &lb);
874 TEST_CHECK(slen1 > 0);
875 TEST_MSG("First encode: %zd", slen1);
876
877 /*
878 * Second name should compress the 62-byte suffix.
879 * Uncompressed would be 4 + 1 + 62 + 1 = 68 bytes.
880 * Compressed should be "foo" (4 bytes) + pointer (2 bytes) = 6 bytes.
881 */
882 slen2 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN + slen1, name2, true, &lb);
883 TEST_CHECK(slen2 > 0);
884 TEST_CHECK(slen2 < 68);
885 TEST_MSG("62-byte label compression: %zd (expected < 68)", slen2);
886
887 /* Round-trip decode to verify correctness */
888 dec_len = fr_dns_label_to_value_box(ctx, &vb_out, pkt + DNS_HDR_LEN,
889 slen1 + slen2,
890 pkt + DNS_HDR_LEN + slen1,
891 false, &lb);
892 TEST_CHECK(dec_len > 0);
893 TEST_CHECK(vb_out.type == FR_TYPE_STRING);
894 TEST_CHECK(strcmp(vb_out.vb_strvalue, name2) == 0);
895 TEST_MSG("Expected '%s', got '%s'", name2, vb_out.vb_strvalue);
896
897 fr_value_box_clear(&vb_out);
898 talloc_free(ctx);
899}
900
902{
903 ssize_t slen1, slen2, dec_len;
905 fr_value_box_t vb_out;
906 TALLOC_CTX *ctx = talloc_init("test");
907 char long63[64];
908 uint8_t pkt[512] = {};
909
910 /*
911 * The encoder limits non-first labels to 62 bytes (off-by-one in the dot tracking), so we test
912 * 63-byte labels as thue first (and only) label. Encode a standalone 63-byte label twice; the
913 * second should compress to a 2-byte pointer.
914 */
915 memset(long63, 'a', 63);
916 long63[63] = '\0';
917
918 labels_init(&lb, pkt, sizeof(pkt), false);
919
920 slen1 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN, long63, true, &lb);
921 TEST_CHECK(slen1 == 65); /* 1 (length) + 63 (data) + 1 (terminator) */
922 TEST_MSG("First encode: %zd", slen1);
923
924 /* Duplicate name should fully compress to a 2-byte pointer */
925 slen2 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN + slen1, long63, true, &lb);
926 TEST_CHECK(slen2 > 0);
927 TEST_CHECK(slen2 == 2);
928 TEST_MSG("63-byte duplicate compression: %zd (expected 2)", slen2);
929
930 /* Round-trip decode the compressed entry */
931 dec_len = fr_dns_label_to_value_box(ctx, &vb_out, pkt + DNS_HDR_LEN,
932 slen1 + slen2,
933 pkt + DNS_HDR_LEN + slen1,
934 false, &lb);
935 TEST_CHECK(dec_len > 0);
936 TEST_CHECK(vb_out.type == FR_TYPE_STRING);
937 TEST_CHECK(strcmp(vb_out.vb_strvalue, long63) == 0);
938 TEST_MSG("Expected '%s', got '%s'", long63, vb_out.vb_strvalue);
939
940 fr_value_box_clear(&vb_out);
941 talloc_free(ctx);
942}
943
944/*
945 * The same tests, but with a three-label name so that the 62/63-byte
946 * label is a middle suffix. This exercises the Path 2 more
947 * directly: when scanning the buffer, the candidate "bar" is
948 * followed by an uncompressed 62/63-byte label which IS the suffix
949 * pointer target.
950 */
952{
953 ssize_t slen1, slen2;
955 char const *name1 = "bar.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com";
956 char const *name2 = "foo.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com";
957 uint8_t pkt[512] = {};
958
959 TEST_CHECK(strlen(name1) == 70); /* "bar." + 62 + ".com"*/
960 TEST_CHECK(strlen(name2) == 70);
961
962 labels_init(&lb, pkt, sizeof(pkt), false);
963
964 slen1 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN, name1, true, &lb);
965 TEST_CHECK(slen1 > 0);
966 TEST_MSG("First encode: %zd", slen1);
967
968 /*
969 * Compression produces "foo" + pointer to the "aaa...com" suffix. When scanning for "foo" in
970 * the buffer, the code finds "bar" whose next label is the 62-byte 'a' label (*ptr == 62). The
971 * <= 63 check at line 523 allows this to be recognized as the suffix target.
972 */
973 slen2 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN + slen1, name2, true, &lb);
974 TEST_CHECK(slen2 > 0);
975 TEST_CHECK(slen2 < slen1);
976 TEST_MSG("Compressed size %zd should be < %zd", slen2, slen1);
977}
978
980{
981 ssize_t slen1, slen2, dec_len;
983 fr_value_box_t vb_out;
984 TALLOC_CTX *ctx = talloc_init("test");
985 char const *name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com";
986 uint8_t pkt[512] = {};
987
988 /*
989 * Test compression of a multi-label name where the first label is 63 bytes. Encode "<63
990 * a's>.com" twice.
991 *
992 * On the second encode, dns_label_compress recursively compresses "com" first, then scans the
993 * buffer for the 63-byte label. The buffer scan at checks *ptr <= 63 where ptr points to the
994 * "com" label (3 bytes) after the 63-byte label in the first entry. It then verifies ptr ==
995 * suffix (both point to "com" in name1) and compares the 63-byte labels.
996 */
997 TEST_CHECK(strlen(name) == 67);
998
999 labels_init(&lb, pkt, sizeof(pkt), false);
1000
1001 slen1 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN, name, true, &lb);
1002 TEST_CHECK(slen1 > 0);
1003 TEST_MSG("First encode: %zd", slen1);
1004
1005 /* Duplicate should fully compress to a 2-byte pointer */
1006 slen2 = encode_label(pkt, sizeof(pkt), pkt + DNS_HDR_LEN + slen1, name, true, &lb);
1007 TEST_CHECK(slen2 > 0);
1008 TEST_CHECK(slen2 == 2);
1009 TEST_MSG("Compressed size %zd (expected 2)", slen2);
1010
1011 /* Round-trip decode */
1012 dec_len = fr_dns_label_to_value_box(ctx, &vb_out, pkt + DNS_HDR_LEN,
1013 slen1 + slen2,
1014 pkt + DNS_HDR_LEN + slen1,
1015 false, &lb);
1016 TEST_CHECK(dec_len > 0);
1017 TEST_CHECK(vb_out.type == FR_TYPE_STRING);
1018 TEST_CHECK(strcmp(vb_out.vb_strvalue, name) == 0);
1019 TEST_MSG("Expected '%s', got '%s'", name, vb_out.vb_strvalue);
1020
1021 fr_value_box_clear(&vb_out);
1022 talloc_free(ctx);
1023}
1024
1026 /* Encoding */
1027 { "encode_empty_string", test_encode_empty_string },
1028 { "encode_root_dot", test_encode_root_dot },
1029 { "encode_simple_label", test_encode_simple_label },
1030 { "encode_multi_label", test_encode_multi_label },
1031 { "encode_trailing_dot", test_encode_trailing_dot },
1032 { "encode_underscore_prefix", test_encode_underscore_prefix },
1033 { "encode_max_label_length", test_encode_max_label_length },
1034 { "encode_hyphen_and_digits", test_encode_hyphen_and_digits },
1035
1036 /* Encoding errors */
1037 { "encode_null_inputs", test_encode_null_inputs },
1038 { "encode_non_string_type", test_encode_non_string_type },
1039 { "encode_invalid_chars", test_encode_invalid_chars },
1040 { "encode_double_dot", test_encode_double_dot },
1041 { "encode_leading_dot", test_encode_leading_dot },
1042 { "encode_label_too_long", test_encode_label_too_long },
1043 { "encode_buffer_too_small", test_encode_buffer_too_small },
1044 { "encode_where_outside_buf", test_encode_where_outside_buf },
1045
1046 /* Decoding / uncompressed length */
1047 { "decode_simple_label", test_decode_simple_label },
1048 { "decode_multi_label", test_decode_multi_label },
1049 { "decode_root_label", test_decode_root_label },
1050 { "decode_compressed_pointer", test_decode_compressed_pointer },
1051 { "decode_null_inputs", test_decode_null_inputs },
1052 { "decode_label_invalid_chars", test_decode_label_invalid_chars },
1053 { "decode_total_length_exceeds_255", test_decode_total_length_exceeds_255 },
1054
1055 /* Decode error paths */
1056 { "decode_forward_pointer_rejected", test_decode_forward_pointer_rejected },
1057 { "decode_self_pointer_rejected", test_decode_self_pointer_rejected },
1058 { "decode_pointer_to_pointer_rejected", test_decode_pointer_to_pointer_rejected },
1059 { "decode_invalid_high_bits", test_decode_invalid_high_bits },
1060 { "decode_label_overflow", test_decode_label_overflow },
1061 { "decode_pointer_to_zero_rejected", test_pointer_to_zero_label_rejected },
1062
1063 /* Network verify */
1064 { "verify_simple", test_verify_simple },
1065 { "verify_empty", test_verify_empty },
1066
1067 /* Value box decode errors */
1068 { "decode_vb_zero_len", test_decode_to_value_box_zero_len },
1069 { "decode_vb_label_outside_buf", test_decode_to_value_box_label_outside_buf },
1070
1071 /* Pointer tracking */
1072 { "pointer_valid_no_tracking", test_pointer_valid_no_tracking },
1073 { "pointer_invalid_with_mark", test_pointer_invalid_with_mark_tracking },
1074
1075 /* Label block tracking */
1076 { "labels_block_tracking", test_labels_block_tracking },
1077
1078 /* Round-trip */
1079 { "roundtrip_simple", test_roundtrip_simple },
1080 { "roundtrip_trailing_dot", test_roundtrip_trailing_dot },
1081 { "roundtrip_root", test_roundtrip_root },
1082 { "roundtrip_underscore", test_roundtrip_underscore },
1083 { "roundtrip_case_preservation", test_roundtrip_case_preservation },
1084
1085 /* Compression */
1086 { "compress_two_names", test_compress_two_names },
1087 { "compress_offset_too_large", test_compress_offset_too_large },
1088 { "roundtrip_compressed", test_roundtrip_compressed },
1089 { "compress_62_byte_label", test_compress_62_byte_label },
1090 { "compress_63_byte_label", test_compress_63_byte_label },
1091 { "compress_middle_62_byte_label", test_compress_middle_62_byte_label },
1092 { "compress_middle_63_byte_label", test_compress_middle_63_byte_label },
1093
1095};
#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:1025
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:807
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:780
static void test_compress_middle_63_byte_label(void)
Definition dns_tests.c:979
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:681
#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:901
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:739
static void test_roundtrip_root(void)
Definition dns_tests.c:556
static void test_labels_block_tracking(void)
Definition dns_tests.c:706
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:857
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:691
static void test_compress_middle_62_byte_label(void)
Definition dns_tests.c:951
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:722
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:760
static void test_encode_empty_string(void)
Definition dns_tests.c:71
static void test_encode_hyphen_and_digits(void)
Definition dns_tests.c:793
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:4448
#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