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.
4
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.
9
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.
14
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/>. */
18
19#include <arpa/nameser.h>
20#include <string.h>
21#include <support/check.h>
22#include <support/next_to_fault.h>
23
24/* Reference packet for packet parsing. */
25static 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. */
47 };
48
49/* Special offsets in valid_packet. */
50enum
51 {
52 offset_of_first_record = 29,
53 offset_of_second_record = 57,
54 };
55
56/* Check that parsing valid_packet succeeds. */
57static void
58test_valid (void)
59{
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);
71
72 struct ns_rr_wire r;
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);
89}
90
91/* Check that trying to parse a packet with a compressed QNAME fails. */
92static void
93test_compressed_qname (void)
94{
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. */
103 };
104
105 struct ns_rr_cursor c;
106 TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, packet, sizeof (packet)));
107}
108
109/* Check that trying to parse a packet with two questions fails. */
110static void
111test_two_questions (void)
112{
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. */
124 };
125
126 struct ns_rr_cursor c;
127 TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, packet, sizeof (packet)));
128}
129
130/* Used to check that parsing truncated packets does not over-read. */
131static struct support_next_to_fault ntf;
132
133/* Truncated packet in the second resource record. */
134static void
135test_truncated_one_rr (size_t length)
136{
137 unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
138 unsigned char *start = end - length;
139
140 /* Produce the truncated packet. */
141 memcpy (dest: start, src: valid_packet, n: length);
142
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);
153
154 struct ns_rr_wire r;
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));
164}
165
166/* Truncated packet in the first resource record. */
167static void
168test_truncated_no_rr (size_t length)
169{
170 unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
171 unsigned char *start = end - length;
172
173 /* Produce the truncated packet. */
174 memcpy (dest: start, src: valid_packet, n: length);
175
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);
186
187 struct ns_rr_wire r;
188 TEST_VERIFY (!__ns_rr_cursor_next (&c, &r));
189}
190
191/* Truncated packet before first resource record. */
192static void
193test_truncated_before_rr (size_t length)
194{
195 unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
196 unsigned char *start = end - length;
197
198 /* Produce the truncated packet. */
199 memcpy (dest: start, src: valid_packet, n: length);
200
201 struct ns_rr_cursor c;
202 TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, start, length));
203}
204
205static int
206do_test (void)
207{
208 ntf = support_next_to_fault_allocate (size: sizeof (valid_packet));
209
210 test_valid ();
211 test_compressed_qname ();
212 test_two_questions ();
213
214 for (int length = offset_of_second_record; length < sizeof (valid_packet);
215 ++length)
216 test_truncated_one_rr (length);
217 for (int length = offset_of_first_record; length < offset_of_second_record;
218 ++length)
219 test_truncated_no_rr (length);
220 for (int length = 0; length < offset_of_first_record; ++length)
221 test_truncated_before_rr (length);
222
223 support_next_to_fault_free (&ntf);
224 return 0;
225}
226
227#include <support/test-driver.c>
228

source code of glibc/resolv/tst-ns_rr_cursor.c