1 /* Tests for resource record parsing.
2 Copyright (C) 2022-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <arpa/nameser.h>
21 #include <support/check.h>
22 #include <support/next_to_fault.h>
24 /* Reference packet for packet parsing. */
25 static const unsigned char valid_packet
[] =
26 { 0x11, 0x12, 0x13, 0x14,
27 0x00, 0x01, /* Question count. */
28 0x00, 0x02, /* Answer count. */
29 0x21, 0x22, 0x23, 0x24, /* Other counts (not actually in packet). */
30 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0,
31 0x00, 0x1c, /* Question type: AAAA. */
32 0x00, 0x01, /* Question class: IN. */
33 0xc0, 0x0c, /* Compression reference to QNAME. */
34 0x00, 0x1c, /* Record type: AAAA. */
35 0x00, 0x01, /* Record class: IN. */
36 0x12, 0x34, 0x56, 0x78, /* Record TTL. */
37 0x00, 0x10, /* Record data length (16 bytes). */
38 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
39 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* IPv6 address. */
40 0xc0, 0x0c, /* Compression reference to QNAME. */
41 0x00, 0x1c, /* Record type: AAAA. */
42 0x00, 0x01, /* Record class: IN. */
43 0x11, 0x33, 0x55, 0x77, /* Record TTL. */
44 0x00, 0x10, /* Record data length (16 bytes). */
45 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
46 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* IPv6 address. */
49 /* Special offsets in valid_packet. */
52 offset_of_first_record
= 29,
53 offset_of_second_record
= 57,
56 /* Check that parsing valid_packet succeeds. */
60 struct ns_rr_cursor c
;
61 TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c
, valid_packet
,
62 sizeof (valid_packet
)));
63 TEST_COMPARE (ns_rr_cursor_rcode (&c
), 4);
64 TEST_COMPARE (ns_rr_cursor_ancount (&c
), 2);
65 TEST_COMPARE (ns_rr_cursor_nscount (&c
), 0x2122);
66 TEST_COMPARE (ns_rr_cursor_adcount (&c
), 0x2324);
67 TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c
), 13, &valid_packet
[12], 13);
68 TEST_COMPARE (ns_rr_cursor_qtype (&c
), T_AAAA
);
69 TEST_COMPARE (ns_rr_cursor_qclass (&c
), C_IN
);
70 TEST_COMPARE (c
.current
- valid_packet
, offset_of_first_record
);
73 TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c
, &r
));
74 TEST_COMPARE (r
.rtype
, T_AAAA
);
75 TEST_COMPARE (r
.rclass
, C_IN
);
76 TEST_COMPARE (r
.ttl
, 0x12345678);
77 TEST_COMPARE_BLOB (r
.rdata
, r
.rdlength
,
78 "\x90\x91\x92\x93\x94\x95\x96\x97"
79 "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", 16);
80 TEST_COMPARE (c
.current
- valid_packet
, offset_of_second_record
);
81 TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c
, &r
));
82 TEST_COMPARE (r
.rtype
, T_AAAA
);
83 TEST_COMPARE (r
.rclass
, C_IN
);
84 TEST_COMPARE (r
.ttl
, 0x11335577);
85 TEST_COMPARE_BLOB (r
.rdata
, r
.rdlength
,
86 "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
87 "\xa8\xa9\xaa\xab\xac\xad\xae\xaf", 16);
88 TEST_VERIFY (c
.current
== c
.end
);
91 /* Check that trying to parse a packet with a compressed QNAME fails. */
93 test_compressed_qname (void)
95 static const unsigned char packet
[] =
96 { 0x11, 0x12, 0x13, 0x14,
97 0x00, 0x01, /* Question count. */
98 0x00, 0x00, /* Answer count. */
99 0x00, 0x00, 0x00, 0x00, /* Other counts. */
100 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
101 0x00, 0x01, /* Question type: A. */
102 0x00, 0x01, /* Question class: IN. */
105 struct ns_rr_cursor c
;
106 TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c
, packet
, sizeof (packet
)));
109 /* Check that trying to parse a packet with two questions fails. */
111 test_two_questions (void)
113 static const unsigned char packet
[] =
114 { 0x11, 0x12, 0x13, 0x14,
115 0x00, 0x02, /* Question count. */
116 0x00, 0x00, /* Answer count. */
117 0x00, 0x00, 0x00, 0x00, /* Other counts. */
118 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
119 0x00, 0x01, /* Question type: A. */
120 0x00, 0x01, /* Question class: IN. */
121 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
122 0x00, 0x1c, /* Question type: AAAA. */
123 0x00, 0x01, /* Question class: IN. */
126 struct ns_rr_cursor c
;
127 TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c
, packet
, sizeof (packet
)));
130 /* Used to check that parsing truncated packets does not over-read. */
131 static struct support_next_to_fault ntf
;
133 /* Truncated packet in the second resource record. */
135 test_truncated_one_rr (size_t length
)
137 unsigned char *end
= (unsigned char *) ntf
.buffer
- ntf
.length
;
138 unsigned char *start
= end
- length
;
140 /* Produce the truncated packet. */
141 memcpy (start
, valid_packet
, length
);
143 struct ns_rr_cursor c
;
144 TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c
, start
, length
));
145 TEST_COMPARE (ns_rr_cursor_rcode (&c
), 4);
146 TEST_COMPARE (ns_rr_cursor_ancount (&c
), 2);
147 TEST_COMPARE (ns_rr_cursor_nscount (&c
), 0x2122);
148 TEST_COMPARE (ns_rr_cursor_adcount (&c
), 0x2324);
149 TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c
), 13, &valid_packet
[12], 13);
150 TEST_COMPARE (ns_rr_cursor_qtype (&c
), T_AAAA
);
151 TEST_COMPARE (ns_rr_cursor_qclass (&c
), C_IN
);
152 TEST_COMPARE (c
.current
- start
, offset_of_first_record
);
155 TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c
, &r
));
156 TEST_COMPARE (r
.rtype
, T_AAAA
);
157 TEST_COMPARE (r
.rclass
, C_IN
);
158 TEST_COMPARE (r
.ttl
, 0x12345678);
159 TEST_COMPARE_BLOB (r
.rdata
, r
.rdlength
,
160 "\x90\x91\x92\x93\x94\x95\x96\x97"
161 "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", 16);
162 TEST_COMPARE (c
.current
- start
, offset_of_second_record
);
163 TEST_VERIFY (!__ns_rr_cursor_next (&c
, &r
));
166 /* Truncated packet in the first resource record. */
168 test_truncated_no_rr (size_t length
)
170 unsigned char *end
= (unsigned char *) ntf
.buffer
- ntf
.length
;
171 unsigned char *start
= end
- length
;
173 /* Produce the truncated packet. */
174 memcpy (start
, valid_packet
, length
);
176 struct ns_rr_cursor c
;
177 TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c
, start
, length
));
178 TEST_COMPARE (ns_rr_cursor_rcode (&c
), 4);
179 TEST_COMPARE (ns_rr_cursor_ancount (&c
), 2);
180 TEST_COMPARE (ns_rr_cursor_nscount (&c
), 0x2122);
181 TEST_COMPARE (ns_rr_cursor_adcount (&c
), 0x2324);
182 TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c
), 13, &valid_packet
[12], 13);
183 TEST_COMPARE (ns_rr_cursor_qtype (&c
), T_AAAA
);
184 TEST_COMPARE (ns_rr_cursor_qclass (&c
), C_IN
);
185 TEST_COMPARE (c
.current
- start
, offset_of_first_record
);
188 TEST_VERIFY (!__ns_rr_cursor_next (&c
, &r
));
191 /* Truncated packet before first resource record. */
193 test_truncated_before_rr (size_t length
)
195 unsigned char *end
= (unsigned char *) ntf
.buffer
- ntf
.length
;
196 unsigned char *start
= end
- length
;
198 /* Produce the truncated packet. */
199 memcpy (start
, valid_packet
, length
);
201 struct ns_rr_cursor c
;
202 TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c
, start
, length
));
208 ntf
= support_next_to_fault_allocate (sizeof (valid_packet
));
211 test_compressed_qname ();
212 test_two_questions ();
214 for (int length
= offset_of_second_record
; length
< sizeof (valid_packet
);
216 test_truncated_one_rr (length
);
217 for (int length
= offset_of_first_record
; length
< offset_of_second_record
;
219 test_truncated_no_rr (length
);
220 for (int length
= 0; length
< offset_of_first_record
; ++length
)
221 test_truncated_before_rr (length
);
223 support_next_to_fault_free (&ntf
);
227 #include <support/test-driver.c>