File: | src/usr.bin/dig/lib/dns/name.c |
Warning: | line 1250, column 10 Access to field 'base' results in a dereference of a null pointer (loaded from variable 'target') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright (C) Internet Systems Consortium, Inc. ("ISC") | |||
3 | * | |||
4 | * Permission to use, copy, modify, and/or distribute this software for any | |||
5 | * purpose with or without fee is hereby granted, provided that the above | |||
6 | * copyright notice and this permission notice appear in all copies. | |||
7 | * | |||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH | |||
9 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | |||
10 | * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, | |||
11 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | |||
12 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE | |||
13 | * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |||
14 | * PERFORMANCE OF THIS SOFTWARE. | |||
15 | */ | |||
16 | ||||
17 | /* $Id: name.c,v 1.14 2020/09/14 08:40:43 florian Exp $ */ | |||
18 | ||||
19 | /*! \file */ | |||
20 | #include <ctype.h> | |||
21 | #include <stdlib.h> | |||
22 | #include <isc/buffer.h> | |||
23 | #include <isc/hash.h> | |||
24 | ||||
25 | #include <string.h> | |||
26 | #include <isc/util.h> | |||
27 | ||||
28 | #include <dns/compress.h> | |||
29 | #include <dns/fixedname.h> | |||
30 | #include <dns/name.h> | |||
31 | #include <dns/result.h> | |||
32 | ||||
33 | typedef enum { | |||
34 | ft_init = 0, | |||
35 | ft_start, | |||
36 | ft_ordinary, | |||
37 | ft_initialescape, | |||
38 | ft_escape, | |||
39 | ft_escdecimal, | |||
40 | ft_at | |||
41 | } ft_state; | |||
42 | ||||
43 | typedef enum { | |||
44 | fw_start = 0, | |||
45 | fw_ordinary, | |||
46 | fw_newcurrent | |||
47 | } fw_state; | |||
48 | ||||
49 | static char digitvalue[256] = { | |||
50 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ | |||
51 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ | |||
52 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/ | |||
53 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/ | |||
54 | -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/ | |||
55 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/ | |||
56 | -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/ | |||
57 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/ | |||
58 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||
59 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||
60 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||
61 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||
62 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||
63 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||
64 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |||
65 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/ | |||
66 | }; | |||
67 | ||||
68 | static unsigned char maptolower[] = { | |||
69 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | |||
70 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, | |||
71 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, | |||
72 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, | |||
73 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, | |||
74 | 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, | |||
75 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, | |||
76 | 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, | |||
77 | 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, | |||
78 | 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, | |||
79 | 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, | |||
80 | 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, | |||
81 | 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, | |||
82 | 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, | |||
83 | 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, | |||
84 | 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, | |||
85 | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, | |||
86 | 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, | |||
87 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, | |||
88 | 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, | |||
89 | 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, | |||
90 | 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, | |||
91 | 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, | |||
92 | 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, | |||
93 | 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, | |||
94 | 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, | |||
95 | 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, | |||
96 | 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, | |||
97 | 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, | |||
98 | 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, | |||
99 | 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, | |||
100 | 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff | |||
101 | }; | |||
102 | ||||
103 | #define CONVERTTOASCII(c) | |||
104 | #define CONVERTFROMASCII(c) | |||
105 | ||||
106 | #define INIT_OFFSETS(name, var, default_offsets)if ((name)->offsets != ((void *)0)) var = (name)->offsets ; else var = (default_offsets); \ | |||
107 | if ((name)->offsets != NULL((void *)0)) \ | |||
108 | var = (name)->offsets; \ | |||
109 | else \ | |||
110 | var = (default_offsets); | |||
111 | ||||
112 | #define SETUP_OFFSETS(name, var, default_offsets)if ((name)->offsets != ((void *)0)) var = (name)->offsets ; else { var = (default_offsets); set_offsets(name, var, ((void *)0)); } \ | |||
113 | if ((name)->offsets != NULL((void *)0)) \ | |||
114 | var = (name)->offsets; \ | |||
115 | else { \ | |||
116 | var = (default_offsets); \ | |||
117 | set_offsets(name, var, NULL((void *)0)); \ | |||
118 | } | |||
119 | ||||
120 | /*% | |||
121 | * Note: If additional attributes are added that should not be set for | |||
122 | * empty names, MAKE_EMPTY() must be changed so it clears them. | |||
123 | */ | |||
124 | #define MAKE_EMPTY(name)do { name->ndata = ((void *)0); name->length = 0; name-> labels = 0; name->attributes &= ~0x00000001; } while ( 0); \ | |||
125 | do { \ | |||
126 | name->ndata = NULL((void *)0); \ | |||
127 | name->length = 0; \ | |||
128 | name->labels = 0; \ | |||
129 | name->attributes &= ~DNS_NAMEATTR_ABSOLUTE0x00000001; \ | |||
130 | } while (0); | |||
131 | ||||
132 | /*% | |||
133 | * A name is "bindable" if it can be set to point to a new value, i.e. | |||
134 | * name->ndata and name->length may be changed. | |||
135 | */ | |||
136 | #define BINDABLE(name)((name->attributes & (0x00000002|0x00000004)) == 0) \ | |||
137 | ((name->attributes & (DNS_NAMEATTR_READONLY0x00000002|DNS_NAMEATTR_DYNAMIC0x00000004)) \ | |||
138 | == 0) | |||
139 | ||||
140 | /*% | |||
141 | * Note that the name data must be a char array, not a string | |||
142 | * literal, to avoid compiler warnings about discarding | |||
143 | * the const attribute of a string. | |||
144 | */ | |||
145 | static unsigned char root_ndata[] = { "" }; | |||
146 | static unsigned char root_offsets[] = { 0 }; | |||
147 | ||||
148 | static dns_name_t root = DNS_NAME_INITABSOLUTE(root_ndata, root_offsets){ root_ndata, sizeof(root_ndata), sizeof(root_offsets), 0x00000002 | 0x00000001, root_offsets, ((void *)0), { (void *)-1, (void *)-1}, {((void *)0), ((void *)0)} }; | |||
149 | ||||
150 | /* XXXDCL make const? */ | |||
151 | dns_name_t *dns_rootname = &root; | |||
152 | ||||
153 | static void | |||
154 | set_offsets(const dns_name_t *name, unsigned char *offsets, | |||
155 | dns_name_t *set_name); | |||
156 | ||||
157 | void | |||
158 | dns_name_init(dns_name_t *name, unsigned char *offsets) { | |||
159 | /* | |||
160 | * Initialize 'name'. | |||
161 | */ | |||
162 | name->ndata = NULL((void *)0); | |||
163 | name->length = 0; | |||
164 | name->labels = 0; | |||
165 | name->attributes = 0; | |||
166 | name->offsets = offsets; | |||
167 | name->buffer = NULL((void *)0); | |||
168 | ISC_LINK_INIT(name, link)do { (name)->link.prev = (void *)(-1); (name)->link.next = (void *)(-1); } while (0); | |||
169 | ISC_LIST_INIT(name->list)do { (name->list).head = ((void *)0); (name->list).tail = ((void *)0); } while (0); | |||
170 | ||||
171 | } | |||
172 | ||||
173 | void | |||
174 | dns_name_reset(dns_name_t *name) { | |||
175 | REQUIRE(BINDABLE(name))((void) ((((name->attributes & (0x00000002|0x00000004) ) == 0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 175, isc_assertiontype_require, "((name->attributes & (0x00000002|0x00000004)) == 0)" ), 0))); | |||
176 | ||||
177 | name->ndata = NULL((void *)0); | |||
178 | name->length = 0; | |||
179 | name->labels = 0; | |||
180 | name->attributes &= ~DNS_NAMEATTR_ABSOLUTE0x00000001; | |||
181 | if (name->buffer != NULL((void *)0)) | |||
182 | isc_buffer_clearisc__buffer_clear(name->buffer); | |||
183 | } | |||
184 | ||||
185 | void | |||
186 | dns_name_invalidate(dns_name_t *name) { | |||
187 | /* | |||
188 | * Make 'name' invalid. | |||
189 | */ | |||
190 | ||||
191 | name->ndata = NULL((void *)0); | |||
192 | name->length = 0; | |||
193 | name->labels = 0; | |||
194 | name->attributes = 0; | |||
195 | name->offsets = NULL((void *)0); | |||
196 | name->buffer = NULL((void *)0); | |||
197 | ISC_LINK_INIT(name, link)do { (name)->link.prev = (void *)(-1); (name)->link.next = (void *)(-1); } while (0); | |||
198 | } | |||
199 | ||||
200 | void | |||
201 | dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) { | |||
202 | /* | |||
203 | * Dedicate a buffer for use with 'name'. | |||
204 | */ | |||
205 | ||||
206 | REQUIRE((buffer != NULL && name->buffer == NULL) ||((void) (((buffer != ((void *)0) && name->buffer == ((void *)0)) || (buffer == ((void *)0))) || ((isc_assertion_failed )("/usr/src/usr.bin/dig/lib/dns/name.c", 207, isc_assertiontype_require , "(buffer != ((void *)0) && name->buffer == ((void *)0)) || (buffer == ((void *)0))" ), 0))) | |||
207 | (buffer == NULL))((void) (((buffer != ((void *)0) && name->buffer == ((void *)0)) || (buffer == ((void *)0))) || ((isc_assertion_failed )("/usr/src/usr.bin/dig/lib/dns/name.c", 207, isc_assertiontype_require , "(buffer != ((void *)0) && name->buffer == ((void *)0)) || (buffer == ((void *)0))" ), 0))); | |||
208 | ||||
209 | name->buffer = buffer; | |||
210 | } | |||
211 | ||||
212 | int | |||
213 | dns_name_isabsolute(const dns_name_t *name) { | |||
214 | ||||
215 | /* | |||
216 | * Does 'name' end in the root label? | |||
217 | */ | |||
218 | ||||
219 | if ((name->attributes & DNS_NAMEATTR_ABSOLUTE0x00000001) != 0) | |||
220 | return (1); | |||
221 | return (0); | |||
222 | } | |||
223 | ||||
224 | unsigned int | |||
225 | dns_name_hash(dns_name_t *name, int case_sensitive) { | |||
226 | unsigned int length; | |||
227 | ||||
228 | /* | |||
229 | * Provide a hash value for 'name'. | |||
230 | */ | |||
231 | ||||
232 | if (name->labels == 0) | |||
233 | return (0); | |||
234 | ||||
235 | length = name->length; | |||
236 | if (length > 16) | |||
237 | length = 16; | |||
238 | ||||
239 | return (isc_hash_function_reverse(name->ndata, length, | |||
240 | case_sensitive, NULL((void *)0))); | |||
241 | } | |||
242 | ||||
243 | dns_namereln_t | |||
244 | dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2, | |||
245 | int *orderp, unsigned int *nlabelsp) | |||
246 | { | |||
247 | unsigned int l1, l2, l, count1, count2, count, nlabels; | |||
248 | int cdiff, ldiff, chdiff; | |||
249 | unsigned char *label1, *label2; | |||
250 | unsigned char *offsets1, *offsets2; | |||
251 | dns_offsets_t odata1, odata2; | |||
252 | dns_namereln_t namereln = dns_namereln_none; | |||
253 | ||||
254 | /* | |||
255 | * Determine the relative ordering under the DNSSEC order relation of | |||
256 | * 'name1' and 'name2', and also determine the hierarchical | |||
257 | * relationship of the names. | |||
258 | * | |||
259 | * Note: It makes no sense for one of the names to be relative and the | |||
260 | * other absolute. If both names are relative, then to be meaningfully | |||
261 | * compared the caller must ensure that they are both relative to the | |||
262 | * same domain. | |||
263 | */ | |||
264 | ||||
265 | REQUIRE(orderp != NULL)((void) ((orderp != ((void *)0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 265, isc_assertiontype_require, "orderp != ((void *)0)"), 0 ))); | |||
266 | REQUIRE(nlabelsp != NULL)((void) ((nlabelsp != ((void *)0)) || ((isc_assertion_failed) ("/usr/src/usr.bin/dig/lib/dns/name.c", 266, isc_assertiontype_require , "nlabelsp != ((void *)0)"), 0))); | |||
267 | /* | |||
268 | * Either name1 is absolute and name2 is absolute, or neither is. | |||
269 | */ | |||
270 | REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==((void) (((name1->attributes & 0x00000001) == (name2-> attributes & 0x00000001)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 271, isc_assertiontype_require, "(name1->attributes & 0x00000001) == (name2->attributes & 0x00000001)" ), 0))) | |||
271 | (name2->attributes & DNS_NAMEATTR_ABSOLUTE))((void) (((name1->attributes & 0x00000001) == (name2-> attributes & 0x00000001)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 271, isc_assertiontype_require, "(name1->attributes & 0x00000001) == (name2->attributes & 0x00000001)" ), 0))); | |||
272 | ||||
273 | if (name1 == name2) { | |||
274 | *orderp = 0; | |||
275 | *nlabelsp = name1->labels; | |||
276 | return (dns_namereln_equal); | |||
277 | } | |||
278 | ||||
279 | SETUP_OFFSETS(name1, offsets1, odata1)if ((name1)->offsets != ((void *)0)) offsets1 = (name1)-> offsets; else { offsets1 = (odata1); set_offsets(name1, offsets1 , ((void *)0)); }; | |||
280 | SETUP_OFFSETS(name2, offsets2, odata2)if ((name2)->offsets != ((void *)0)) offsets2 = (name2)-> offsets; else { offsets2 = (odata2); set_offsets(name2, offsets2 , ((void *)0)); }; | |||
281 | ||||
282 | nlabels = 0; | |||
283 | l1 = name1->labels; | |||
284 | l2 = name2->labels; | |||
285 | if (l2 > l1) { | |||
286 | l = l1; | |||
287 | ldiff = 0 - (l2 - l1); | |||
288 | } else { | |||
289 | l = l2; | |||
290 | ldiff = l1 - l2; | |||
291 | } | |||
292 | ||||
293 | offsets1 += l1; | |||
294 | offsets2 += l2; | |||
295 | ||||
296 | while (l > 0) { | |||
297 | l--; | |||
298 | offsets1--; | |||
299 | offsets2--; | |||
300 | label1 = &name1->ndata[*offsets1]; | |||
301 | label2 = &name2->ndata[*offsets2]; | |||
302 | count1 = *label1++; | |||
303 | count2 = *label2++; | |||
304 | ||||
305 | /* | |||
306 | * We dropped bitstring labels, and we don't support any | |||
307 | * other extended label types. | |||
308 | */ | |||
309 | INSIST(count1 <= 63 && count2 <= 63)((void) ((count1 <= 63 && count2 <= 63) || ((isc_assertion_failed )("/usr/src/usr.bin/dig/lib/dns/name.c", 309, isc_assertiontype_insist , "count1 <= 63 && count2 <= 63"), 0))); | |||
310 | ||||
311 | cdiff = (int)count1 - (int)count2; | |||
312 | if (cdiff < 0) | |||
313 | count = count1; | |||
314 | else | |||
315 | count = count2; | |||
316 | ||||
317 | /* Loop unrolled for performance */ | |||
318 | while (count > 3) { | |||
319 | chdiff = (int)maptolower[label1[0]] - | |||
320 | (int)maptolower[label2[0]]; | |||
321 | if (chdiff != 0) { | |||
322 | *orderp = chdiff; | |||
323 | goto done; | |||
324 | } | |||
325 | chdiff = (int)maptolower[label1[1]] - | |||
326 | (int)maptolower[label2[1]]; | |||
327 | if (chdiff != 0) { | |||
328 | *orderp = chdiff; | |||
329 | goto done; | |||
330 | } | |||
331 | chdiff = (int)maptolower[label1[2]] - | |||
332 | (int)maptolower[label2[2]]; | |||
333 | if (chdiff != 0) { | |||
334 | *orderp = chdiff; | |||
335 | goto done; | |||
336 | } | |||
337 | chdiff = (int)maptolower[label1[3]] - | |||
338 | (int)maptolower[label2[3]]; | |||
339 | if (chdiff != 0) { | |||
340 | *orderp = chdiff; | |||
341 | goto done; | |||
342 | } | |||
343 | count -= 4; | |||
344 | label1 += 4; | |||
345 | label2 += 4; | |||
346 | } | |||
347 | while (count-- > 0) { | |||
348 | chdiff = (int)maptolower[*label1++] - | |||
349 | (int)maptolower[*label2++]; | |||
350 | if (chdiff != 0) { | |||
351 | *orderp = chdiff; | |||
352 | goto done; | |||
353 | } | |||
354 | } | |||
355 | if (cdiff != 0) { | |||
356 | *orderp = cdiff; | |||
357 | goto done; | |||
358 | } | |||
359 | nlabels++; | |||
360 | } | |||
361 | ||||
362 | *orderp = ldiff; | |||
363 | if (ldiff < 0) | |||
364 | namereln = dns_namereln_contains; | |||
365 | else if (ldiff > 0) | |||
366 | namereln = dns_namereln_subdomain; | |||
367 | else | |||
368 | namereln = dns_namereln_equal; | |||
369 | *nlabelsp = nlabels; | |||
370 | return (namereln); | |||
371 | ||||
372 | done: | |||
373 | *nlabelsp = nlabels; | |||
374 | if (nlabels > 0) | |||
375 | namereln = dns_namereln_commonancestor; | |||
376 | ||||
377 | return (namereln); | |||
378 | } | |||
379 | ||||
380 | int | |||
381 | dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) { | |||
382 | int order; | |||
383 | unsigned int nlabels; | |||
384 | ||||
385 | /* | |||
386 | * Determine the relative ordering under the DNSSEC order relation of | |||
387 | * 'name1' and 'name2'. | |||
388 | * | |||
389 | * Note: It makes no sense for one of the names to be relative and the | |||
390 | * other absolute. If both names are relative, then to be meaningfully | |||
391 | * compared the caller must ensure that they are both relative to the | |||
392 | * same domain. | |||
393 | */ | |||
394 | ||||
395 | (void)dns_name_fullcompare(name1, name2, &order, &nlabels); | |||
396 | ||||
397 | return (order); | |||
398 | } | |||
399 | ||||
400 | int | |||
401 | dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) { | |||
402 | unsigned int l, count; | |||
403 | unsigned char c; | |||
404 | unsigned char *label1, *label2; | |||
405 | ||||
406 | /* | |||
407 | * Are 'name1' and 'name2' equal? | |||
408 | * | |||
409 | * Note: It makes no sense for one of the names to be relative and the | |||
410 | * other absolute. If both names are relative, then to be meaningfully | |||
411 | * compared the caller must ensure that they are both relative to the | |||
412 | * same domain. | |||
413 | */ | |||
414 | ||||
415 | /* | |||
416 | * Either name1 is absolute and name2 is absolute, or neither is. | |||
417 | */ | |||
418 | REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==((void) (((name1->attributes & 0x00000001) == (name2-> attributes & 0x00000001)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 419, isc_assertiontype_require, "(name1->attributes & 0x00000001) == (name2->attributes & 0x00000001)" ), 0))) | |||
419 | (name2->attributes & DNS_NAMEATTR_ABSOLUTE))((void) (((name1->attributes & 0x00000001) == (name2-> attributes & 0x00000001)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 419, isc_assertiontype_require, "(name1->attributes & 0x00000001) == (name2->attributes & 0x00000001)" ), 0))); | |||
420 | ||||
421 | if (name1 == name2) | |||
422 | return (1); | |||
423 | ||||
424 | if (name1->length != name2->length) | |||
425 | return (0); | |||
426 | ||||
427 | l = name1->labels; | |||
428 | ||||
429 | if (l != name2->labels) | |||
430 | return (0); | |||
431 | ||||
432 | label1 = name1->ndata; | |||
433 | label2 = name2->ndata; | |||
434 | while (l-- > 0) { | |||
435 | count = *label1++; | |||
436 | if (count != *label2++) | |||
437 | return (0); | |||
438 | ||||
439 | INSIST(count <= 63)((void) ((count <= 63) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 439, isc_assertiontype_insist, "count <= 63"), 0))); /* no bitstring support */ | |||
440 | ||||
441 | /* Loop unrolled for performance */ | |||
442 | while (count > 3) { | |||
443 | c = maptolower[label1[0]]; | |||
444 | if (c != maptolower[label2[0]]) | |||
445 | return (0); | |||
446 | c = maptolower[label1[1]]; | |||
447 | if (c != maptolower[label2[1]]) | |||
448 | return (0); | |||
449 | c = maptolower[label1[2]]; | |||
450 | if (c != maptolower[label2[2]]) | |||
451 | return (0); | |||
452 | c = maptolower[label1[3]]; | |||
453 | if (c != maptolower[label2[3]]) | |||
454 | return (0); | |||
455 | count -= 4; | |||
456 | label1 += 4; | |||
457 | label2 += 4; | |||
458 | } | |||
459 | while (count-- > 0) { | |||
460 | c = maptolower[*label1++]; | |||
461 | if (c != maptolower[*label2++]) | |||
462 | return (0); | |||
463 | } | |||
464 | } | |||
465 | ||||
466 | return (1); | |||
467 | } | |||
468 | ||||
469 | int | |||
470 | dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) { | |||
471 | ||||
472 | /* | |||
473 | * Are 'name1' and 'name2' equal? | |||
474 | * | |||
475 | * Note: It makes no sense for one of the names to be relative and the | |||
476 | * other absolute. If both names are relative, then to be meaningfully | |||
477 | * compared the caller must ensure that they are both relative to the | |||
478 | * same domain. | |||
479 | */ | |||
480 | ||||
481 | /* | |||
482 | * Either name1 is absolute and name2 is absolute, or neither is. | |||
483 | */ | |||
484 | REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==((void) (((name1->attributes & 0x00000001) == (name2-> attributes & 0x00000001)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 485, isc_assertiontype_require, "(name1->attributes & 0x00000001) == (name2->attributes & 0x00000001)" ), 0))) | |||
485 | (name2->attributes & DNS_NAMEATTR_ABSOLUTE))((void) (((name1->attributes & 0x00000001) == (name2-> attributes & 0x00000001)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 485, isc_assertiontype_require, "(name1->attributes & 0x00000001) == (name2->attributes & 0x00000001)" ), 0))); | |||
486 | ||||
487 | if (name1->length != name2->length) | |||
488 | return (0); | |||
489 | ||||
490 | if (memcmp(name1->ndata, name2->ndata, name1->length) != 0) | |||
491 | return (0); | |||
492 | ||||
493 | return (1); | |||
494 | } | |||
495 | ||||
496 | int | |||
497 | dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) { | |||
498 | int order; | |||
499 | unsigned int nlabels; | |||
500 | dns_namereln_t namereln; | |||
501 | ||||
502 | /* | |||
503 | * Is 'name1' a subdomain of 'name2'? | |||
504 | * | |||
505 | * Note: It makes no sense for one of the names to be relative and the | |||
506 | * other absolute. If both names are relative, then to be meaningfully | |||
507 | * compared the caller must ensure that they are both relative to the | |||
508 | * same domain. | |||
509 | */ | |||
510 | ||||
511 | namereln = dns_name_fullcompare(name1, name2, &order, &nlabels); | |||
512 | if (namereln == dns_namereln_subdomain || | |||
513 | namereln == dns_namereln_equal) | |||
514 | return (1); | |||
515 | ||||
516 | return (0); | |||
517 | } | |||
518 | ||||
519 | unsigned int | |||
520 | dns_name_countlabels(const dns_name_t *name) { | |||
521 | /* | |||
522 | * How many labels does 'name' have? | |||
523 | */ | |||
524 | ||||
525 | ENSURE(name->labels <= 128)((void) ((name->labels <= 128) || ((isc_assertion_failed )("/usr/src/usr.bin/dig/lib/dns/name.c", 525, isc_assertiontype_ensure , "name->labels <= 128"), 0))); | |||
526 | ||||
527 | return (name->labels); | |||
528 | } | |||
529 | ||||
530 | void | |||
531 | dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) { | |||
532 | unsigned char *offsets; | |||
533 | dns_offsets_t odata; | |||
534 | ||||
535 | /* | |||
536 | * Make 'label' refer to the 'n'th least significant label of 'name'. | |||
537 | */ | |||
538 | ||||
539 | REQUIRE(name->labels > 0)((void) ((name->labels > 0) || ((isc_assertion_failed)( "/usr/src/usr.bin/dig/lib/dns/name.c", 539, isc_assertiontype_require , "name->labels > 0"), 0))); | |||
540 | REQUIRE(n < name->labels)((void) ((n < name->labels) || ((isc_assertion_failed)( "/usr/src/usr.bin/dig/lib/dns/name.c", 540, isc_assertiontype_require , "n < name->labels"), 0))); | |||
541 | REQUIRE(label != NULL)((void) ((label != ((void *)0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 541, isc_assertiontype_require, "label != ((void *)0)"), 0) )); | |||
542 | ||||
543 | SETUP_OFFSETS(name, offsets, odata)if ((name)->offsets != ((void *)0)) offsets = (name)->offsets ; else { offsets = (odata); set_offsets(name, offsets, ((void *)0)); }; | |||
544 | ||||
545 | label->base = &name->ndata[offsets[n]]; | |||
546 | if (n == name->labels - 1) | |||
547 | label->length = name->length - offsets[n]; | |||
548 | else | |||
549 | label->length = offsets[n + 1] - offsets[n]; | |||
550 | } | |||
551 | ||||
552 | void | |||
553 | dns_name_getlabelsequence(const dns_name_t *source, | |||
554 | unsigned int first, unsigned int n, | |||
555 | dns_name_t *target) | |||
556 | { | |||
557 | unsigned char *offsets; | |||
558 | dns_offsets_t odata; | |||
559 | unsigned int firstoffset, endoffset; | |||
560 | ||||
561 | /* | |||
562 | * Make 'target' refer to the 'n' labels including and following | |||
563 | * 'first' in 'source'. | |||
564 | */ | |||
565 | ||||
566 | REQUIRE(first <= source->labels)((void) ((first <= source->labels) || ((isc_assertion_failed )("/usr/src/usr.bin/dig/lib/dns/name.c", 566, isc_assertiontype_require , "first <= source->labels"), 0))); | |||
567 | REQUIRE(n <= source->labels - first)((void) ((n <= source->labels - first) || ((isc_assertion_failed )("/usr/src/usr.bin/dig/lib/dns/name.c", 567, isc_assertiontype_require , "n <= source->labels - first"), 0))); /* note first+n could overflow */ | |||
568 | REQUIRE(BINDABLE(target))((void) ((((target->attributes & (0x00000002|0x00000004 )) == 0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 568, isc_assertiontype_require, "((target->attributes & (0x00000002|0x00000004)) == 0)" ), 0))); | |||
569 | ||||
570 | SETUP_OFFSETS(source, offsets, odata)if ((source)->offsets != ((void *)0)) offsets = (source)-> offsets; else { offsets = (odata); set_offsets(source, offsets , ((void *)0)); }; | |||
571 | ||||
572 | if (first == source->labels) | |||
573 | firstoffset = source->length; | |||
574 | else | |||
575 | firstoffset = offsets[first]; | |||
576 | ||||
577 | if (first + n == source->labels) | |||
578 | endoffset = source->length; | |||
579 | else | |||
580 | endoffset = offsets[first + n]; | |||
581 | ||||
582 | target->ndata = &source->ndata[firstoffset]; | |||
583 | target->length = endoffset - firstoffset; | |||
584 | ||||
585 | if (first + n == source->labels && n > 0 && | |||
586 | (source->attributes & DNS_NAMEATTR_ABSOLUTE0x00000001) != 0) | |||
587 | target->attributes |= DNS_NAMEATTR_ABSOLUTE0x00000001; | |||
588 | else | |||
589 | target->attributes &= ~DNS_NAMEATTR_ABSOLUTE0x00000001; | |||
590 | ||||
591 | target->labels = n; | |||
592 | ||||
593 | /* | |||
594 | * If source and target are the same, and we're making target | |||
595 | * a prefix of source, the offsets table is correct already | |||
596 | * so we don't need to call set_offsets(). | |||
597 | */ | |||
598 | if (target->offsets != NULL((void *)0) && | |||
599 | (target != source || first != 0)) | |||
600 | set_offsets(target, target->offsets, NULL((void *)0)); | |||
601 | } | |||
602 | ||||
603 | void | |||
604 | dns_name_clone(const dns_name_t *source, dns_name_t *target) { | |||
605 | ||||
606 | /* | |||
607 | * Make 'target' refer to the same name as 'source'. | |||
608 | */ | |||
609 | ||||
610 | REQUIRE(BINDABLE(target))((void) ((((target->attributes & (0x00000002|0x00000004 )) == 0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 610, isc_assertiontype_require, "((target->attributes & (0x00000002|0x00000004)) == 0)" ), 0))); | |||
611 | ||||
612 | target->ndata = source->ndata; | |||
613 | target->length = source->length; | |||
614 | target->labels = source->labels; | |||
615 | target->attributes = source->attributes & | |||
616 | (unsigned int)~(DNS_NAMEATTR_READONLY0x00000002 | DNS_NAMEATTR_DYNAMIC0x00000004 | | |||
617 | DNS_NAMEATTR_DYNOFFSETS0x00000008); | |||
618 | if (target->offsets != NULL((void *)0) && source->labels > 0) { | |||
619 | if (source->offsets != NULL((void *)0)) | |||
620 | memmove(target->offsets, source->offsets, | |||
621 | source->labels); | |||
622 | else | |||
623 | set_offsets(target, target->offsets, NULL((void *)0)); | |||
624 | } | |||
625 | } | |||
626 | ||||
627 | void | |||
628 | dns_name_fromregion(dns_name_t *name, const isc_region_t *r) { | |||
629 | unsigned char *offsets; | |||
630 | dns_offsets_t odata; | |||
631 | unsigned int len; | |||
632 | isc_region_t r2; | |||
633 | ||||
634 | /* | |||
635 | * Make 'name' refer to region 'r'. | |||
636 | */ | |||
637 | ||||
638 | REQUIRE(r != NULL)((void) ((r != ((void *)0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 638, isc_assertiontype_require, "r != ((void *)0)"), 0))); | |||
639 | REQUIRE(BINDABLE(name))((void) ((((name->attributes & (0x00000002|0x00000004) ) == 0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 639, isc_assertiontype_require, "((name->attributes & (0x00000002|0x00000004)) == 0)" ), 0))); | |||
640 | ||||
641 | INIT_OFFSETS(name, offsets, odata)if ((name)->offsets != ((void *)0)) offsets = (name)->offsets ; else offsets = (odata);; | |||
642 | ||||
643 | if (name->buffer != NULL((void *)0)) { | |||
644 | isc_buffer_clearisc__buffer_clear(name->buffer); | |||
645 | isc_buffer_availableregionisc__buffer_availableregion(name->buffer, &r2); | |||
646 | len = (r->length < r2.length) ? r->length : r2.length; | |||
647 | if (len > DNS_NAME_MAXWIRE255) | |||
648 | len = DNS_NAME_MAXWIRE255; | |||
649 | if (len != 0) | |||
650 | memmove(r2.base, r->base, len); | |||
651 | name->ndata = r2.base; | |||
652 | name->length = len; | |||
653 | } else { | |||
654 | name->ndata = r->base; | |||
655 | name->length = (r->length <= DNS_NAME_MAXWIRE255) ? | |||
656 | r->length : DNS_NAME_MAXWIRE255; | |||
657 | } | |||
658 | ||||
659 | if (r->length > 0) | |||
660 | set_offsets(name, offsets, name); | |||
661 | else { | |||
662 | name->labels = 0; | |||
663 | name->attributes &= ~DNS_NAMEATTR_ABSOLUTE0x00000001; | |||
664 | } | |||
665 | ||||
666 | if (name->buffer != NULL((void *)0)) | |||
667 | isc_buffer_addisc__buffer_add(name->buffer, name->length); | |||
668 | } | |||
669 | ||||
670 | void | |||
671 | dns_name_toregion(dns_name_t *name, isc_region_t *r) { | |||
672 | /* | |||
673 | * Make 'r' refer to 'name'. | |||
674 | */ | |||
675 | ||||
676 | REQUIRE(r != NULL)((void) ((r != ((void *)0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 676, isc_assertiontype_require, "r != ((void *)0)"), 0))); | |||
677 | ||||
678 | r->base = name->ndata; | |||
679 | r->length = name->length; | |||
680 | } | |||
681 | ||||
682 | isc_result_t | |||
683 | dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, | |||
684 | const dns_name_t *origin, unsigned int options, | |||
685 | isc_buffer_t *target) | |||
686 | { | |||
687 | unsigned char *ndata, *label = NULL((void *)0); | |||
688 | char *tdata; | |||
689 | char c; | |||
690 | ft_state state; | |||
691 | unsigned int value = 0, count = 0; | |||
692 | unsigned int n1 = 0, n2 = 0; | |||
693 | unsigned int tlen, nrem, nused, digits = 0, labels, tused; | |||
694 | int done; | |||
695 | unsigned char *offsets; | |||
696 | dns_offsets_t odata; | |||
697 | int downcase; | |||
698 | ||||
699 | /* | |||
700 | * Convert the textual representation of a DNS name at source | |||
701 | * into uncompressed wire form stored in target. | |||
702 | * | |||
703 | * Notes: | |||
704 | * Relative domain names will have 'origin' appended to them | |||
705 | * unless 'origin' is NULL, in which case relative domain names | |||
706 | * will remain relative. | |||
707 | */ | |||
708 | ||||
709 | downcase = (options & DNS_NAME_DOWNCASE0x0001) != 0; | |||
710 | ||||
711 | if (target == NULL((void *)0) && name->buffer != NULL((void *)0)) { | |||
712 | target = name->buffer; | |||
713 | isc_buffer_clearisc__buffer_clear(target); | |||
714 | } | |||
715 | ||||
716 | REQUIRE(BINDABLE(name))((void) ((((name->attributes & (0x00000002|0x00000004) ) == 0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 716, isc_assertiontype_require, "((name->attributes & (0x00000002|0x00000004)) == 0)" ), 0))); | |||
717 | ||||
718 | INIT_OFFSETS(name, offsets, odata)if ((name)->offsets != ((void *)0)) offsets = (name)->offsets ; else offsets = (odata);; | |||
719 | offsets[0] = 0; | |||
720 | ||||
721 | /* | |||
722 | * Make 'name' empty in case of failure. | |||
723 | */ | |||
724 | MAKE_EMPTY(name)do { name->ndata = ((void *)0); name->length = 0; name-> labels = 0; name->attributes &= ~0x00000001; } while ( 0);; | |||
725 | ||||
726 | /* | |||
727 | * Set up the state machine. | |||
728 | */ | |||
729 | tdata = (char *)source->base + source->current; | |||
730 | tlen = isc_buffer_remaininglength(source)((source)->used - (source)->current); | |||
731 | tused = 0; | |||
732 | ndata = isc_buffer_used(target)((void *)((unsigned char *)(target)->base + (target)->used )); | |||
733 | nrem = isc_buffer_availablelength(target)((target)->length - (target)->used); | |||
734 | if (nrem > 255) | |||
735 | nrem = 255; | |||
736 | nused = 0; | |||
737 | labels = 0; | |||
738 | done = 0; | |||
739 | state = ft_init; | |||
740 | ||||
741 | while (nrem > 0 && tlen > 0 && !done) { | |||
742 | c = *tdata++; | |||
743 | tlen--; | |||
744 | tused++; | |||
745 | ||||
746 | switch (state) { | |||
747 | case ft_init: | |||
748 | /* | |||
749 | * Is this the root name? | |||
750 | */ | |||
751 | if (c == '.') { | |||
752 | if (tlen != 0) | |||
753 | return (DNS_R_EMPTYLABEL(((1) << 16) + 4)); | |||
754 | labels++; | |||
755 | *ndata++ = 0; | |||
756 | nrem--; | |||
757 | nused++; | |||
758 | done = 1; | |||
759 | break; | |||
760 | } | |||
761 | if (c == '@' && tlen == 0) { | |||
762 | state = ft_at; | |||
763 | break; | |||
764 | } | |||
765 | ||||
766 | /* FALLTHROUGH */ | |||
767 | case ft_start: | |||
768 | label = ndata; | |||
769 | ndata++; | |||
770 | nrem--; | |||
771 | nused++; | |||
772 | count = 0; | |||
773 | if (c == '\\') { | |||
774 | state = ft_initialescape; | |||
775 | break; | |||
776 | } | |||
777 | state = ft_ordinary; | |||
778 | if (nrem == 0) | |||
779 | return (ISC_R_NOSPACE19); | |||
780 | /* FALLTHROUGH */ | |||
781 | case ft_ordinary: | |||
782 | if (c == '.') { | |||
783 | if (count == 0) | |||
784 | return (DNS_R_EMPTYLABEL(((1) << 16) + 4)); | |||
785 | *label = count; | |||
786 | labels++; | |||
787 | INSIST(labels <= 127)((void) ((labels <= 127) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 787, isc_assertiontype_insist, "labels <= 127"), 0))); | |||
788 | offsets[labels] = nused; | |||
789 | if (tlen == 0) { | |||
790 | labels++; | |||
791 | *ndata++ = 0; | |||
792 | nrem--; | |||
793 | nused++; | |||
794 | done = 1; | |||
795 | } | |||
796 | state = ft_start; | |||
797 | } else if (c == '\\') { | |||
798 | state = ft_escape; | |||
799 | } else { | |||
800 | if (count >= 63) | |||
801 | return (DNS_R_LABELTOOLONG(((1) << 16) + 0)); | |||
802 | count++; | |||
803 | CONVERTTOASCII(c); | |||
804 | if (downcase) | |||
805 | c = maptolower[c & 0xff]; | |||
806 | *ndata++ = c; | |||
807 | nrem--; | |||
808 | nused++; | |||
809 | } | |||
810 | break; | |||
811 | case ft_initialescape: | |||
812 | if (c == '[') { | |||
813 | /* | |||
814 | * This looks like a bitstring label, which | |||
815 | * was deprecated. Intentionally drop it. | |||
816 | */ | |||
817 | return (DNS_R_BADLABELTYPE(((1) << 16) + 8)); | |||
818 | } | |||
819 | state = ft_escape; | |||
820 | POST(state)(void)(state); | |||
821 | /* FALLTHROUGH */ | |||
822 | case ft_escape: | |||
823 | if (!isdigit(c & 0xff)) { | |||
824 | if (count >= 63) | |||
825 | return (DNS_R_LABELTOOLONG(((1) << 16) + 0)); | |||
826 | count++; | |||
827 | CONVERTTOASCII(c); | |||
828 | if (downcase) | |||
829 | c = maptolower[c & 0xff]; | |||
830 | *ndata++ = c; | |||
831 | nrem--; | |||
832 | nused++; | |||
833 | state = ft_ordinary; | |||
834 | break; | |||
835 | } | |||
836 | digits = 0; | |||
837 | value = 0; | |||
838 | state = ft_escdecimal; | |||
839 | /* FALLTHROUGH */ | |||
840 | case ft_escdecimal: | |||
841 | if (!isdigit(c & 0xff)) | |||
842 | return (DNS_R_BADESCAPE(((1) << 16) + 1)); | |||
843 | value *= 10; | |||
844 | value += digitvalue[c & 0xff]; | |||
845 | digits++; | |||
846 | if (digits == 3) { | |||
847 | if (value > 255) | |||
848 | return (DNS_R_BADESCAPE(((1) << 16) + 1)); | |||
849 | if (count >= 63) | |||
850 | return (DNS_R_LABELTOOLONG(((1) << 16) + 0)); | |||
851 | count++; | |||
852 | if (downcase) | |||
853 | value = maptolower[value]; | |||
854 | *ndata++ = value; | |||
855 | nrem--; | |||
856 | nused++; | |||
857 | state = ft_ordinary; | |||
858 | } | |||
859 | break; | |||
860 | default: | |||
861 | FATAL_ERRORisc_error_fatal(__FILE__"/usr/src/usr.bin/dig/lib/dns/name.c", __LINE__861, | |||
862 | "Unexpected state %d", state); | |||
863 | /* Does not return. */ | |||
864 | } | |||
865 | } | |||
866 | ||||
867 | if (!done) { | |||
868 | if (nrem == 0) | |||
869 | return (ISC_R_NOSPACE19); | |||
870 | INSIST(tlen == 0)((void) ((tlen == 0) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 870, isc_assertiontype_insist, "tlen == 0"), 0))); | |||
871 | if (state != ft_ordinary && state != ft_at) | |||
872 | return (ISC_R_UNEXPECTEDEND24); | |||
873 | if (state == ft_ordinary) { | |||
874 | INSIST(count != 0)((void) ((count != 0) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 874, isc_assertiontype_insist, "count != 0"), 0))); | |||
875 | *label = count; | |||
876 | labels++; | |||
877 | INSIST(labels <= 127)((void) ((labels <= 127) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 877, isc_assertiontype_insist, "labels <= 127"), 0))); | |||
878 | offsets[labels] = nused; | |||
879 | } | |||
880 | if (origin != NULL((void *)0)) { | |||
881 | if (nrem < origin->length) | |||
882 | return (ISC_R_NOSPACE19); | |||
883 | label = origin->ndata; | |||
884 | n1 = origin->length; | |||
885 | nrem -= n1; | |||
886 | POST(nrem)(void)(nrem); | |||
887 | while (n1 > 0) { | |||
888 | n2 = *label++; | |||
889 | INSIST(n2 <= 63)((void) ((n2 <= 63) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 889, isc_assertiontype_insist, "n2 <= 63"), 0))); /* no bitstring support */ | |||
890 | *ndata++ = n2; | |||
891 | n1 -= n2 + 1; | |||
892 | nused += n2 + 1; | |||
893 | while (n2 > 0) { | |||
894 | c = *label++; | |||
895 | if (downcase) | |||
896 | c = maptolower[c & 0xff]; | |||
897 | *ndata++ = c; | |||
898 | n2--; | |||
899 | } | |||
900 | labels++; | |||
901 | if (n1 > 0) { | |||
902 | INSIST(labels <= 127)((void) ((labels <= 127) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 902, isc_assertiontype_insist, "labels <= 127"), 0))); | |||
903 | offsets[labels] = nused; | |||
904 | } | |||
905 | } | |||
906 | if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE0x00000001) != 0) | |||
907 | name->attributes |= DNS_NAMEATTR_ABSOLUTE0x00000001; | |||
908 | } | |||
909 | } else | |||
910 | name->attributes |= DNS_NAMEATTR_ABSOLUTE0x00000001; | |||
911 | ||||
912 | name->ndata = (unsigned char *)target->base + target->used; | |||
913 | name->labels = labels; | |||
914 | name->length = nused; | |||
915 | ||||
916 | isc_buffer_forwardisc__buffer_forward(source, tused); | |||
917 | isc_buffer_addisc__buffer_add(target, name->length); | |||
918 | ||||
919 | return (ISC_R_SUCCESS0); | |||
920 | } | |||
921 | ||||
922 | isc_result_t | |||
923 | dns_name_totext(dns_name_t *name, int omit_final_dot, | |||
924 | isc_buffer_t *target) | |||
925 | { | |||
926 | unsigned int options = DNS_NAME_MASTERFILE0x02U; | |||
927 | ||||
928 | if (omit_final_dot) | |||
929 | options |= DNS_NAME_OMITFINALDOT0x01U; | |||
930 | return (dns_name_totext2(name, options, target)); | |||
931 | } | |||
932 | ||||
933 | isc_result_t | |||
934 | dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target) | |||
935 | { | |||
936 | unsigned char *ndata; | |||
937 | char *tdata; | |||
938 | unsigned int nlen, tlen; | |||
939 | unsigned char c; | |||
940 | unsigned int trem, count; | |||
941 | unsigned int labels; | |||
942 | int saw_root = 0; | |||
943 | int omit_final_dot = options & DNS_NAME_OMITFINALDOT0x01U; | |||
944 | ||||
945 | /* | |||
946 | * This function assumes the name is in proper uncompressed | |||
947 | * wire format. | |||
948 | */ | |||
949 | ||||
950 | ndata = name->ndata; | |||
951 | nlen = name->length; | |||
952 | labels = name->labels; | |||
953 | tdata = isc_buffer_used(target)((void *)((unsigned char *)(target)->base + (target)->used )); | |||
954 | tlen = isc_buffer_availablelength(target)((target)->length - (target)->used); | |||
955 | ||||
956 | trem = tlen; | |||
957 | ||||
958 | if (labels == 0 && nlen == 0) { | |||
959 | /* | |||
960 | * Special handling for an empty name. | |||
961 | */ | |||
962 | if (trem == 0) | |||
963 | return (ISC_R_NOSPACE19); | |||
964 | ||||
965 | /* | |||
966 | * The names of these booleans are misleading in this case. | |||
967 | * This empty name is not necessarily from the root node of | |||
968 | * the DNS root zone, nor is a final dot going to be included. | |||
969 | * They need to be set this way, though, to keep the "@" | |||
970 | * from being trounced. | |||
971 | */ | |||
972 | saw_root = 1; | |||
973 | omit_final_dot = 0; | |||
974 | *tdata++ = '@'; | |||
975 | trem--; | |||
976 | ||||
977 | /* | |||
978 | * Skip the while() loop. | |||
979 | */ | |||
980 | nlen = 0; | |||
981 | } else if (nlen == 1 && labels == 1 && *ndata == '\0') { | |||
982 | /* | |||
983 | * Special handling for the root label. | |||
984 | */ | |||
985 | if (trem == 0) | |||
986 | return (ISC_R_NOSPACE19); | |||
987 | ||||
988 | saw_root = 1; | |||
989 | omit_final_dot = 0; | |||
990 | *tdata++ = '.'; | |||
991 | trem--; | |||
992 | ||||
993 | /* | |||
994 | * Skip the while() loop. | |||
995 | */ | |||
996 | nlen = 0; | |||
997 | } | |||
998 | ||||
999 | while (labels > 0 && nlen > 0 && trem > 0) { | |||
1000 | labels--; | |||
1001 | count = *ndata++; | |||
1002 | nlen--; | |||
1003 | if (count == 0) { | |||
1004 | saw_root = 1; | |||
1005 | break; | |||
1006 | } | |||
1007 | if (count < 64) { | |||
1008 | INSIST(nlen >= count)((void) ((nlen >= count) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1008, isc_assertiontype_insist, "nlen >= count"), 0))); | |||
1009 | while (count > 0) { | |||
1010 | c = *ndata; | |||
1011 | switch (c) { | |||
1012 | /* Special modifiers in zone files. */ | |||
1013 | case 0x40: /* '@' */ | |||
1014 | case 0x24: /* '$' */ | |||
1015 | if ((options & DNS_NAME_MASTERFILE0x02U) == 0) | |||
1016 | goto no_escape; | |||
1017 | /* FALLTHROUGH */ | |||
1018 | case 0x22: /* '"' */ | |||
1019 | case 0x28: /* '(' */ | |||
1020 | case 0x29: /* ')' */ | |||
1021 | case 0x2E: /* '.' */ | |||
1022 | case 0x3B: /* ';' */ | |||
1023 | case 0x5C: /* '\\' */ | |||
1024 | if (trem < 2) | |||
1025 | return (ISC_R_NOSPACE19); | |||
1026 | *tdata++ = '\\'; | |||
1027 | CONVERTFROMASCII(c); | |||
1028 | *tdata++ = c; | |||
1029 | ndata++; | |||
1030 | trem -= 2; | |||
1031 | nlen--; | |||
1032 | break; | |||
1033 | no_escape: | |||
1034 | default: | |||
1035 | if (c > 0x20 && c < 0x7f) { | |||
1036 | if (trem == 0) | |||
1037 | return (ISC_R_NOSPACE19); | |||
1038 | CONVERTFROMASCII(c); | |||
1039 | *tdata++ = c; | |||
1040 | ndata++; | |||
1041 | trem--; | |||
1042 | nlen--; | |||
1043 | } else { | |||
1044 | if (trem < 4) | |||
1045 | return (ISC_R_NOSPACE19); | |||
1046 | *tdata++ = 0x5c; | |||
1047 | *tdata++ = 0x30 + | |||
1048 | ((c / 100) % 10); | |||
1049 | *tdata++ = 0x30 + | |||
1050 | ((c / 10) % 10); | |||
1051 | *tdata++ = 0x30 + (c % 10); | |||
1052 | trem -= 4; | |||
1053 | ndata++; | |||
1054 | nlen--; | |||
1055 | } | |||
1056 | } | |||
1057 | count--; | |||
1058 | } | |||
1059 | } else { | |||
1060 | FATAL_ERRORisc_error_fatal(__FILE__"/usr/src/usr.bin/dig/lib/dns/name.c", __LINE__1060, | |||
1061 | "Unexpected label type %02x", count); | |||
1062 | /* NOTREACHED */ | |||
1063 | } | |||
1064 | ||||
1065 | /* | |||
1066 | * The following assumes names are absolute. If not, we | |||
1067 | * fix things up later. Note that this means that in some | |||
1068 | * cases one more byte of text buffer is required than is | |||
1069 | * needed in the final output. | |||
1070 | */ | |||
1071 | if (trem == 0) | |||
1072 | return (ISC_R_NOSPACE19); | |||
1073 | *tdata++ = '.'; | |||
1074 | trem--; | |||
1075 | } | |||
1076 | ||||
1077 | if (nlen != 0 && trem == 0) | |||
1078 | return (ISC_R_NOSPACE19); | |||
1079 | ||||
1080 | if (!saw_root || omit_final_dot) | |||
1081 | trem++; | |||
1082 | ||||
1083 | isc_buffer_addisc__buffer_add(target, tlen - trem); | |||
1084 | ||||
1085 | return (ISC_R_SUCCESS0); | |||
1086 | } | |||
1087 | ||||
1088 | isc_result_t | |||
1089 | dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) { | |||
1090 | unsigned char *sndata, *ndata; | |||
1091 | unsigned int nlen, count, labels; | |||
1092 | isc_buffer_t buffer; | |||
1093 | ||||
1094 | /* | |||
1095 | * Downcase 'source'. | |||
1096 | */ | |||
1097 | ||||
1098 | if (source == name) { | |||
1099 | REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0)((void) (((name->attributes & 0x00000002) == 0) || ((isc_assertion_failed )("/usr/src/usr.bin/dig/lib/dns/name.c", 1099, isc_assertiontype_require , "(name->attributes & 0x00000002) == 0"), 0))); | |||
1100 | isc_buffer_initisc__buffer_init(&buffer, source->ndata, source->length); | |||
1101 | target = &buffer; | |||
1102 | ndata = source->ndata; | |||
1103 | } else { | |||
1104 | REQUIRE(BINDABLE(name))((void) ((((name->attributes & (0x00000002|0x00000004) ) == 0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1104, isc_assertiontype_require, "((name->attributes & (0x00000002|0x00000004)) == 0)" ), 0))); | |||
1105 | if (target == NULL((void *)0)) { | |||
1106 | target = name->buffer; | |||
1107 | isc_buffer_clearisc__buffer_clear(name->buffer); | |||
1108 | } | |||
1109 | ndata = (unsigned char *)target->base + target->used; | |||
1110 | name->ndata = ndata; | |||
1111 | } | |||
1112 | ||||
1113 | sndata = source->ndata; | |||
1114 | nlen = source->length; | |||
1115 | labels = source->labels; | |||
1116 | ||||
1117 | if (nlen > (target->length - target->used)) { | |||
1118 | MAKE_EMPTY(name)do { name->ndata = ((void *)0); name->length = 0; name-> labels = 0; name->attributes &= ~0x00000001; } while ( 0);; | |||
1119 | return (ISC_R_NOSPACE19); | |||
1120 | } | |||
1121 | ||||
1122 | while (labels > 0 && nlen > 0) { | |||
1123 | labels--; | |||
1124 | count = *sndata++; | |||
1125 | *ndata++ = count; | |||
1126 | nlen--; | |||
1127 | if (count < 64) { | |||
1128 | INSIST(nlen >= count)((void) ((nlen >= count) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1128, isc_assertiontype_insist, "nlen >= count"), 0))); | |||
1129 | while (count > 0) { | |||
1130 | *ndata++ = maptolower[(*sndata++)]; | |||
1131 | nlen--; | |||
1132 | count--; | |||
1133 | } | |||
1134 | } else { | |||
1135 | FATAL_ERRORisc_error_fatal(__FILE__"/usr/src/usr.bin/dig/lib/dns/name.c", __LINE__1135, | |||
1136 | "Unexpected label type %02x", count); | |||
1137 | /* Does not return. */ | |||
1138 | } | |||
1139 | } | |||
1140 | ||||
1141 | if (source != name) { | |||
1142 | name->labels = source->labels; | |||
1143 | name->length = source->length; | |||
1144 | if ((source->attributes & DNS_NAMEATTR_ABSOLUTE0x00000001) != 0) | |||
1145 | name->attributes = DNS_NAMEATTR_ABSOLUTE0x00000001; | |||
1146 | else | |||
1147 | name->attributes = 0; | |||
1148 | if (name->labels > 0 && name->offsets != NULL((void *)0)) | |||
1149 | set_offsets(name, name->offsets, NULL((void *)0)); | |||
1150 | } | |||
1151 | ||||
1152 | isc_buffer_addisc__buffer_add(target, name->length); | |||
1153 | ||||
1154 | return (ISC_R_SUCCESS0); | |||
1155 | } | |||
1156 | ||||
1157 | static void | |||
1158 | set_offsets(const dns_name_t *name, unsigned char *offsets, | |||
1159 | dns_name_t *set_name) | |||
1160 | { | |||
1161 | unsigned int offset, count, length, nlabels; | |||
1162 | unsigned char *ndata; | |||
1163 | int absolute; | |||
1164 | ||||
1165 | ndata = name->ndata; | |||
1166 | length = name->length; | |||
1167 | offset = 0; | |||
1168 | nlabels = 0; | |||
1169 | absolute = 0; | |||
1170 | while (offset != length) { | |||
1171 | INSIST(nlabels < 128)((void) ((nlabels < 128) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1171, isc_assertiontype_insist, "nlabels < 128"), 0))); | |||
1172 | offsets[nlabels++] = offset; | |||
1173 | count = *ndata++; | |||
1174 | offset++; | |||
1175 | INSIST(count <= 63)((void) ((count <= 63) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1175, isc_assertiontype_insist, "count <= 63"), 0))); | |||
1176 | offset += count; | |||
1177 | ndata += count; | |||
1178 | INSIST(offset <= length)((void) ((offset <= length) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1178, isc_assertiontype_insist, "offset <= length"), 0)) ); | |||
1179 | if (count == 0) { | |||
1180 | absolute = 1; | |||
1181 | break; | |||
1182 | } | |||
1183 | } | |||
1184 | if (set_name != NULL((void *)0)) { | |||
1185 | INSIST(set_name == name)((void) ((set_name == name) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1185, isc_assertiontype_insist, "set_name == name"), 0))); | |||
1186 | ||||
1187 | set_name->labels = nlabels; | |||
1188 | set_name->length = offset; | |||
1189 | if (absolute) | |||
1190 | set_name->attributes |= DNS_NAMEATTR_ABSOLUTE0x00000001; | |||
1191 | else | |||
1192 | set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE0x00000001; | |||
1193 | } | |||
1194 | INSIST(nlabels == name->labels)((void) ((nlabels == name->labels) || ((isc_assertion_failed )("/usr/src/usr.bin/dig/lib/dns/name.c", 1194, isc_assertiontype_insist , "nlabels == name->labels"), 0))); | |||
1195 | INSIST(offset == name->length)((void) ((offset == name->length) || ((isc_assertion_failed )("/usr/src/usr.bin/dig/lib/dns/name.c", 1195, isc_assertiontype_insist , "offset == name->length"), 0))); | |||
1196 | } | |||
1197 | ||||
1198 | isc_result_t | |||
1199 | dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, | |||
1200 | dns_decompress_t *dctx, unsigned int options, | |||
1201 | isc_buffer_t *target) | |||
1202 | { | |||
1203 | unsigned char *cdata, *ndata; | |||
1204 | unsigned int cused; /* Bytes of compressed name data used */ | |||
1205 | unsigned int nused, labels, n, nmax; | |||
1206 | unsigned int current, new_current, biggest_pointer; | |||
1207 | int done; | |||
1208 | fw_state state = fw_start; | |||
1209 | unsigned int c; | |||
1210 | unsigned char *offsets; | |||
1211 | dns_offsets_t odata; | |||
1212 | int downcase; | |||
1213 | int seen_pointer; | |||
1214 | ||||
1215 | /* | |||
1216 | * Copy the possibly-compressed name at source into target, | |||
1217 | * decompressing it. Loop prevention is performed by checking | |||
1218 | * the new pointer against biggest_pointer. | |||
1219 | */ | |||
1220 | ||||
1221 | downcase = (options & DNS_NAME_DOWNCASE0x0001) != 0; | |||
| ||||
1222 | ||||
1223 | if (target == NULL((void *)0) && name->buffer != NULL((void *)0)) { | |||
1224 | target = name->buffer; | |||
1225 | isc_buffer_clearisc__buffer_clear(target); | |||
1226 | } | |||
1227 | ||||
1228 | REQUIRE(dctx != NULL)((void) ((dctx != ((void *)0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1228, isc_assertiontype_require, "dctx != ((void *)0)"), 0) )); | |||
1229 | REQUIRE(BINDABLE(name))((void) ((((name->attributes & (0x00000002|0x00000004) ) == 0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1229, isc_assertiontype_require, "((name->attributes & (0x00000002|0x00000004)) == 0)" ), 0))); | |||
1230 | ||||
1231 | INIT_OFFSETS(name, offsets, odata)if ((name)->offsets != ((void *)0)) offsets = (name)->offsets ; else offsets = (odata);; | |||
1232 | ||||
1233 | /* | |||
1234 | * Make 'name' empty in case of failure. | |||
1235 | */ | |||
1236 | MAKE_EMPTY(name)do { name->ndata = ((void *)0); name->length = 0; name-> labels = 0; name->attributes &= ~0x00000001; } while ( 0);; | |||
1237 | ||||
1238 | /* | |||
1239 | * Initialize things to make the compiler happy; they're not required. | |||
1240 | */ | |||
1241 | n = 0; | |||
1242 | new_current = 0; | |||
1243 | ||||
1244 | /* | |||
1245 | * Set up. | |||
1246 | */ | |||
1247 | labels = 0; | |||
1248 | done = 0; | |||
1249 | ||||
1250 | ndata = isc_buffer_used(target)((void *)((unsigned char *)(target)->base + (target)->used )); | |||
| ||||
1251 | nused = 0; | |||
1252 | seen_pointer = 0; | |||
1253 | ||||
1254 | /* | |||
1255 | * Find the maximum number of uncompressed target name | |||
1256 | * bytes we are willing to generate. This is the smaller | |||
1257 | * of the available target buffer length and the | |||
1258 | * maximum legal domain name length (255). | |||
1259 | */ | |||
1260 | nmax = isc_buffer_availablelength(target)((target)->length - (target)->used); | |||
1261 | if (nmax > DNS_NAME_MAXWIRE255) | |||
1262 | nmax = DNS_NAME_MAXWIRE255; | |||
1263 | ||||
1264 | cdata = isc_buffer_current(source)((void *)((unsigned char *)(source)->base + (source)->current )); | |||
1265 | cused = 0; | |||
1266 | ||||
1267 | current = source->current; | |||
1268 | biggest_pointer = current; | |||
1269 | ||||
1270 | /* | |||
1271 | * Note: The following code is not optimized for speed, but | |||
1272 | * rather for correctness. Speed will be addressed in the future. | |||
1273 | */ | |||
1274 | ||||
1275 | while (current < source->active && !done) { | |||
1276 | c = *cdata++; | |||
1277 | current++; | |||
1278 | if (!seen_pointer) | |||
1279 | cused++; | |||
1280 | ||||
1281 | switch (state) { | |||
1282 | case fw_start: | |||
1283 | if (c < 64) { | |||
1284 | offsets[labels] = nused; | |||
1285 | labels++; | |||
1286 | if (nused + c + 1 > nmax) | |||
1287 | goto full; | |||
1288 | nused += c + 1; | |||
1289 | *ndata++ = c; | |||
1290 | if (c == 0) | |||
1291 | done = 1; | |||
1292 | n = c; | |||
1293 | state = fw_ordinary; | |||
1294 | } else if (c >= 128 && c < 192) { | |||
1295 | /* | |||
1296 | * 14 bit local compression pointer. | |||
1297 | * Local compression is no longer an | |||
1298 | * IETF draft. | |||
1299 | */ | |||
1300 | return (DNS_R_BADLABELTYPE(((1) << 16) + 8)); | |||
1301 | } else if (c >= 192) { | |||
1302 | /* | |||
1303 | * Ordinary 14-bit pointer. | |||
1304 | */ | |||
1305 | if ((dctx->allowed & DNS_COMPRESS_GLOBAL140x01) == | |||
1306 | 0) | |||
1307 | return (DNS_R_DISALLOWED(((1) << 16) + 11)); | |||
1308 | new_current = c & 0x3F; | |||
1309 | state = fw_newcurrent; | |||
1310 | } else | |||
1311 | return (DNS_R_BADLABELTYPE(((1) << 16) + 8)); | |||
1312 | break; | |||
1313 | case fw_ordinary: | |||
1314 | if (downcase) | |||
1315 | c = maptolower[c]; | |||
1316 | *ndata++ = c; | |||
1317 | n--; | |||
1318 | if (n == 0) | |||
1319 | state = fw_start; | |||
1320 | break; | |||
1321 | case fw_newcurrent: | |||
1322 | new_current *= 256; | |||
1323 | new_current += c; | |||
1324 | if (new_current >= biggest_pointer) | |||
1325 | return (DNS_R_BADPOINTER(((1) << 16) + 9)); | |||
1326 | biggest_pointer = new_current; | |||
1327 | current = new_current; | |||
1328 | cdata = (unsigned char *)source->base + current; | |||
1329 | seen_pointer = 1; | |||
1330 | state = fw_start; | |||
1331 | break; | |||
1332 | default: | |||
1333 | FATAL_ERRORisc_error_fatal(__FILE__"/usr/src/usr.bin/dig/lib/dns/name.c", __LINE__1333, | |||
1334 | "Unknown state %d", state); | |||
1335 | /* Does not return. */ | |||
1336 | } | |||
1337 | } | |||
1338 | ||||
1339 | if (!done) | |||
1340 | return (ISC_R_UNEXPECTEDEND24); | |||
1341 | ||||
1342 | name->ndata = (unsigned char *)target->base + target->used; | |||
1343 | name->labels = labels; | |||
1344 | name->length = nused; | |||
1345 | name->attributes |= DNS_NAMEATTR_ABSOLUTE0x00000001; | |||
1346 | ||||
1347 | isc_buffer_forwardisc__buffer_forward(source, cused); | |||
1348 | isc_buffer_addisc__buffer_add(target, name->length); | |||
1349 | ||||
1350 | return (ISC_R_SUCCESS0); | |||
1351 | ||||
1352 | full: | |||
1353 | if (nmax == DNS_NAME_MAXWIRE255) | |||
1354 | /* | |||
1355 | * The name did not fit even though we had a buffer | |||
1356 | * big enough to fit a maximum-length name. | |||
1357 | */ | |||
1358 | return (DNS_R_NAMETOOLONG(((1) << 16) + 22)); | |||
1359 | else | |||
1360 | /* | |||
1361 | * The name might fit if only the caller could give us a | |||
1362 | * big enough buffer. | |||
1363 | */ | |||
1364 | return (ISC_R_NOSPACE19); | |||
1365 | } | |||
1366 | ||||
1367 | isc_result_t | |||
1368 | dns_name_towire(const dns_name_t *name, dns_compress_t *cctx, | |||
1369 | isc_buffer_t *target) | |||
1370 | { | |||
1371 | unsigned int methods; | |||
1372 | uint16_t offset; | |||
1373 | dns_name_t gp; /* Global compression prefix */ | |||
1374 | int gf; /* Global compression target found */ | |||
1375 | uint16_t go; /* Global compression offset */ | |||
1376 | dns_offsets_t clo; | |||
1377 | dns_name_t clname; | |||
1378 | ||||
1379 | /* | |||
1380 | * Convert 'name' into wire format, compressing it as specified by the | |||
1381 | * compression context 'cctx', and storing the result in 'target'. | |||
1382 | */ | |||
1383 | ||||
1384 | REQUIRE(cctx != NULL)((void) ((cctx != ((void *)0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1384, isc_assertiontype_require, "cctx != ((void *)0)"), 0) )); | |||
1385 | ||||
1386 | /* | |||
1387 | * If 'name' doesn't have an offsets table, make a clone which | |||
1388 | * has one. | |||
1389 | */ | |||
1390 | if (name->offsets == NULL((void *)0)) { | |||
1391 | dns_name_init(&clname, clo); | |||
1392 | dns_name_clone(name, &clname); | |||
1393 | name = &clname; | |||
1394 | } | |||
1395 | dns_name_init(&gp, NULL((void *)0)); | |||
1396 | ||||
1397 | offset = target->used; /*XXX*/ | |||
1398 | ||||
1399 | methods = dns_compress_getmethods(cctx); | |||
1400 | ||||
1401 | if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS0x00000010) == 0 && | |||
1402 | (methods & DNS_COMPRESS_GLOBAL140x01) != 0) | |||
1403 | gf = dns_compress_findglobal(cctx, name, &gp, &go); | |||
1404 | else | |||
1405 | gf = 0; | |||
1406 | ||||
1407 | /* | |||
1408 | * If the offset is too high for 14 bit global compression, we're | |||
1409 | * out of luck. | |||
1410 | */ | |||
1411 | if (gf && go >= 0x4000) | |||
1412 | gf = 0; | |||
1413 | ||||
1414 | /* | |||
1415 | * Will the compression pointer reduce the message size? | |||
1416 | */ | |||
1417 | if (gf && (gp.length + 2) >= name->length) | |||
1418 | gf = 0; | |||
1419 | ||||
1420 | if (gf) { | |||
1421 | if (target->length - target->used < gp.length) | |||
1422 | return (ISC_R_NOSPACE19); | |||
1423 | if (gp.length != 0) { | |||
1424 | unsigned char *base = target->base; | |||
1425 | (void)memmove(base + target->used, gp.ndata, | |||
1426 | (size_t)gp.length); | |||
1427 | } | |||
1428 | isc_buffer_addisc__buffer_add(target, gp.length); | |||
1429 | go |= 0xc000; | |||
1430 | if (target->length - target->used < 2) | |||
1431 | return (ISC_R_NOSPACE19); | |||
1432 | isc_buffer_putuint16isc__buffer_putuint16(target, go); | |||
1433 | if (gp.length != 0) | |||
1434 | dns_compress_add(cctx, name, &gp, offset); | |||
1435 | } else { | |||
1436 | if (target->length - target->used < name->length) | |||
1437 | return (ISC_R_NOSPACE19); | |||
1438 | if (name->length != 0) { | |||
1439 | unsigned char *base = target->base; | |||
1440 | (void)memmove(base + target->used, name->ndata, | |||
1441 | (size_t)name->length); | |||
1442 | } | |||
1443 | isc_buffer_addisc__buffer_add(target, name->length); | |||
1444 | dns_compress_add(cctx, name, name, offset); | |||
1445 | } | |||
1446 | return (ISC_R_SUCCESS0); | |||
1447 | } | |||
1448 | ||||
1449 | isc_result_t | |||
1450 | dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name, | |||
1451 | isc_buffer_t *target) | |||
1452 | { | |||
1453 | unsigned char *ndata, *offsets; | |||
1454 | unsigned int nrem, labels, prefix_length, length; | |||
1455 | int copy_prefix = 1; | |||
1456 | int copy_suffix = 1; | |||
1457 | int absolute = 0; | |||
1458 | dns_name_t tmp_name; | |||
1459 | dns_offsets_t odata; | |||
1460 | ||||
1461 | /* | |||
1462 | * Concatenate 'prefix' and 'suffix'. | |||
1463 | */ | |||
1464 | ||||
1465 | if (prefix == NULL((void *)0) || prefix->labels == 0) | |||
1466 | copy_prefix = 0; | |||
1467 | if (suffix == NULL((void *)0) || suffix->labels == 0) | |||
1468 | copy_suffix = 0; | |||
1469 | if (copy_prefix && | |||
1470 | (prefix->attributes & DNS_NAMEATTR_ABSOLUTE0x00000001) != 0) { | |||
1471 | absolute = 1; | |||
1472 | REQUIRE(!copy_suffix)((void) ((!copy_suffix) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1472, isc_assertiontype_require, "!copy_suffix"), 0))); | |||
1473 | } | |||
1474 | if (name == NULL((void *)0)) { | |||
1475 | dns_name_init(&tmp_name, odata); | |||
1476 | name = &tmp_name; | |||
1477 | } | |||
1478 | if (target == NULL((void *)0)) { | |||
1479 | INSIST(name->buffer != NULL)((void) ((name->buffer != ((void *)0)) || ((isc_assertion_failed )("/usr/src/usr.bin/dig/lib/dns/name.c", 1479, isc_assertiontype_insist , "name->buffer != ((void *)0)"), 0))); | |||
1480 | target = name->buffer; | |||
1481 | isc_buffer_clearisc__buffer_clear(name->buffer); | |||
1482 | } | |||
1483 | ||||
1484 | REQUIRE(BINDABLE(name))((void) ((((name->attributes & (0x00000002|0x00000004) ) == 0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1484, isc_assertiontype_require, "((name->attributes & (0x00000002|0x00000004)) == 0)" ), 0))); | |||
1485 | ||||
1486 | /* | |||
1487 | * Set up. | |||
1488 | */ | |||
1489 | nrem = target->length - target->used; | |||
1490 | ndata = (unsigned char *)target->base + target->used; | |||
1491 | if (nrem > DNS_NAME_MAXWIRE255) | |||
1492 | nrem = DNS_NAME_MAXWIRE255; | |||
1493 | length = 0; | |||
1494 | prefix_length = 0; | |||
1495 | labels = 0; | |||
1496 | if (copy_prefix) { | |||
1497 | prefix_length = prefix->length; | |||
1498 | length += prefix_length; | |||
1499 | labels += prefix->labels; | |||
1500 | } | |||
1501 | if (copy_suffix) { | |||
1502 | length += suffix->length; | |||
1503 | labels += suffix->labels; | |||
1504 | } | |||
1505 | if (length > DNS_NAME_MAXWIRE255) { | |||
1506 | MAKE_EMPTY(name)do { name->ndata = ((void *)0); name->length = 0; name-> labels = 0; name->attributes &= ~0x00000001; } while ( 0);; | |||
1507 | return (DNS_R_NAMETOOLONG(((1) << 16) + 22)); | |||
1508 | } | |||
1509 | if (length > nrem) { | |||
1510 | MAKE_EMPTY(name)do { name->ndata = ((void *)0); name->length = 0; name-> labels = 0; name->attributes &= ~0x00000001; } while ( 0);; | |||
1511 | return (ISC_R_NOSPACE19); | |||
1512 | } | |||
1513 | ||||
1514 | if (copy_suffix) { | |||
1515 | if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE0x00000001) != 0) | |||
1516 | absolute = 1; | |||
1517 | memmove(ndata + prefix_length, suffix->ndata, suffix->length); | |||
1518 | } | |||
1519 | ||||
1520 | /* | |||
1521 | * If 'prefix' and 'name' are the same object, and the object has | |||
1522 | * a dedicated buffer, and we're using it, then we don't have to | |||
1523 | * copy anything. | |||
1524 | */ | |||
1525 | if (copy_prefix && (prefix != name || prefix->buffer != target)) | |||
1526 | memmove(ndata, prefix->ndata, prefix_length); | |||
1527 | ||||
1528 | name->ndata = ndata; | |||
1529 | name->labels = labels; | |||
1530 | name->length = length; | |||
1531 | if (absolute) | |||
1532 | name->attributes = DNS_NAMEATTR_ABSOLUTE0x00000001; | |||
1533 | else | |||
1534 | name->attributes = 0; | |||
1535 | ||||
1536 | if (name->labels > 0 && name->offsets != NULL((void *)0)) { | |||
1537 | INIT_OFFSETS(name, offsets, odata)if ((name)->offsets != ((void *)0)) offsets = (name)->offsets ; else offsets = (odata);; | |||
1538 | set_offsets(name, offsets, NULL((void *)0)); | |||
1539 | } | |||
1540 | ||||
1541 | isc_buffer_addisc__buffer_add(target, name->length); | |||
1542 | ||||
1543 | return (ISC_R_SUCCESS0); | |||
1544 | } | |||
1545 | ||||
1546 | isc_result_t | |||
1547 | dns_name_dup(const dns_name_t *source, | |||
1548 | dns_name_t *target) | |||
1549 | { | |||
1550 | /* | |||
1551 | * Make 'target' a dynamically allocated copy of 'source'. | |||
1552 | */ | |||
1553 | ||||
1554 | REQUIRE(source->length > 0)((void) ((source->length > 0) || ((isc_assertion_failed )("/usr/src/usr.bin/dig/lib/dns/name.c", 1554, isc_assertiontype_require , "source->length > 0"), 0))); | |||
1555 | REQUIRE(BINDABLE(target))((void) ((((target->attributes & (0x00000002|0x00000004 )) == 0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1555, isc_assertiontype_require, "((target->attributes & (0x00000002|0x00000004)) == 0)" ), 0))); | |||
1556 | ||||
1557 | /* | |||
1558 | * Make 'target' empty in case of failure. | |||
1559 | */ | |||
1560 | MAKE_EMPTY(target)do { target->ndata = ((void *)0); target->length = 0; target ->labels = 0; target->attributes &= ~0x00000001; } while (0);; | |||
1561 | ||||
1562 | target->ndata = malloc(source->length); | |||
1563 | if (target->ndata == NULL((void *)0)) | |||
1564 | return (ISC_R_NOMEMORY1); | |||
1565 | ||||
1566 | memmove(target->ndata, source->ndata, source->length); | |||
1567 | ||||
1568 | target->length = source->length; | |||
1569 | target->labels = source->labels; | |||
1570 | target->attributes = DNS_NAMEATTR_DYNAMIC0x00000004; | |||
1571 | if ((source->attributes & DNS_NAMEATTR_ABSOLUTE0x00000001) != 0) | |||
1572 | target->attributes |= DNS_NAMEATTR_ABSOLUTE0x00000001; | |||
1573 | if (target->offsets != NULL((void *)0)) { | |||
1574 | if (source->offsets != NULL((void *)0)) | |||
1575 | memmove(target->offsets, source->offsets, | |||
1576 | source->labels); | |||
1577 | else | |||
1578 | set_offsets(target, target->offsets, NULL((void *)0)); | |||
1579 | } | |||
1580 | ||||
1581 | return (ISC_R_SUCCESS0); | |||
1582 | } | |||
1583 | ||||
1584 | isc_result_t | |||
1585 | dns_name_dupwithoffsets(dns_name_t *source, | |||
1586 | dns_name_t *target) | |||
1587 | { | |||
1588 | /* | |||
1589 | * Make 'target' a read-only dynamically allocated copy of 'source'. | |||
1590 | * 'target' will also have a dynamically allocated offsets table. | |||
1591 | */ | |||
1592 | ||||
1593 | REQUIRE(source->length > 0)((void) ((source->length > 0) || ((isc_assertion_failed )("/usr/src/usr.bin/dig/lib/dns/name.c", 1593, isc_assertiontype_require , "source->length > 0"), 0))); | |||
1594 | REQUIRE(BINDABLE(target))((void) ((((target->attributes & (0x00000002|0x00000004 )) == 0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1594, isc_assertiontype_require, "((target->attributes & (0x00000002|0x00000004)) == 0)" ), 0))); | |||
1595 | REQUIRE(target->offsets == NULL)((void) ((target->offsets == ((void *)0)) || ((isc_assertion_failed )("/usr/src/usr.bin/dig/lib/dns/name.c", 1595, isc_assertiontype_require , "target->offsets == ((void *)0)"), 0))); | |||
1596 | ||||
1597 | /* | |||
1598 | * Make 'target' empty in case of failure. | |||
1599 | */ | |||
1600 | MAKE_EMPTY(target)do { target->ndata = ((void *)0); target->length = 0; target ->labels = 0; target->attributes &= ~0x00000001; } while (0);; | |||
1601 | ||||
1602 | target->ndata = malloc(source->length + source->labels); | |||
1603 | if (target->ndata == NULL((void *)0)) | |||
1604 | return (ISC_R_NOMEMORY1); | |||
1605 | ||||
1606 | memmove(target->ndata, source->ndata, source->length); | |||
1607 | ||||
1608 | target->length = source->length; | |||
1609 | target->labels = source->labels; | |||
1610 | target->attributes = DNS_NAMEATTR_DYNAMIC0x00000004 | DNS_NAMEATTR_DYNOFFSETS0x00000008 | | |||
1611 | DNS_NAMEATTR_READONLY0x00000002; | |||
1612 | if ((source->attributes & DNS_NAMEATTR_ABSOLUTE0x00000001) != 0) | |||
1613 | target->attributes |= DNS_NAMEATTR_ABSOLUTE0x00000001; | |||
1614 | target->offsets = target->ndata + source->length; | |||
1615 | if (source->offsets != NULL((void *)0)) | |||
1616 | memmove(target->offsets, source->offsets, source->labels); | |||
1617 | else | |||
1618 | set_offsets(target, target->offsets, NULL((void *)0)); | |||
1619 | ||||
1620 | return (ISC_R_SUCCESS0); | |||
1621 | } | |||
1622 | ||||
1623 | void | |||
1624 | dns_name_free(dns_name_t *name) { | |||
1625 | /* | |||
1626 | * Free 'name'. | |||
1627 | */ | |||
1628 | ||||
1629 | REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0)((void) (((name->attributes & 0x00000004) != 0) || ((isc_assertion_failed )("/usr/src/usr.bin/dig/lib/dns/name.c", 1629, isc_assertiontype_require , "(name->attributes & 0x00000004) != 0"), 0))); | |||
1630 | ||||
1631 | free(name->ndata); | |||
1632 | dns_name_invalidate(name); | |||
1633 | } | |||
1634 | ||||
1635 | int | |||
1636 | dns_name_dynamic(dns_name_t *name) { | |||
1637 | ||||
1638 | /* | |||
1639 | * Returns whether there is dynamic memory associated with this name. | |||
1640 | */ | |||
1641 | ||||
1642 | return ((name->attributes & DNS_NAMEATTR_DYNAMIC0x00000004) != 0 ? | |||
1643 | 1 : 0); | |||
1644 | } | |||
1645 | ||||
1646 | void | |||
1647 | dns_name_format(dns_name_t *name, char *cp, unsigned int size) { | |||
1648 | isc_result_t result; | |||
1649 | isc_buffer_t buf; | |||
1650 | ||||
1651 | REQUIRE(size > 0)((void) ((size > 0) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1651, isc_assertiontype_require, "size > 0"), 0))); | |||
1652 | ||||
1653 | /* | |||
1654 | * Leave room for null termination after buffer. | |||
1655 | */ | |||
1656 | isc_buffer_initisc__buffer_init(&buf, cp, size - 1); | |||
1657 | result = dns_name_totext(name, 1, &buf); | |||
1658 | if (result == ISC_R_SUCCESS0) { | |||
1659 | /* | |||
1660 | * Null terminate. | |||
1661 | */ | |||
1662 | isc_region_t r; | |||
1663 | isc_buffer_usedregionisc__buffer_usedregion(&buf, &r); | |||
1664 | ((char *) r.base)[r.length] = '\0'; | |||
1665 | ||||
1666 | } else | |||
1667 | snprintf(cp, size, "<unknown>"); | |||
1668 | } | |||
1669 | ||||
1670 | /* | |||
1671 | * dns_name_fromstring() -- convert directly from a string to a name, | |||
1672 | * allocating memory as needed | |||
1673 | */ | |||
1674 | isc_result_t | |||
1675 | dns_name_fromstring2(dns_name_t *target, const char *src, | |||
1676 | const dns_name_t *origin, unsigned int options) | |||
1677 | { | |||
1678 | isc_result_t result; | |||
1679 | isc_buffer_t buf; | |||
1680 | dns_fixedname_t fn; | |||
1681 | dns_name_t *name; | |||
1682 | ||||
1683 | REQUIRE(src != NULL)((void) ((src != ((void *)0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1683, isc_assertiontype_require, "src != ((void *)0)"), 0)) ); | |||
1684 | ||||
1685 | isc_buffer_initisc__buffer_init(&buf, (void *)src, strlen(src)); | |||
1686 | isc_buffer_addisc__buffer_add(&buf, strlen(src)); | |||
1687 | if (BINDABLE(target)((target->attributes & (0x00000002|0x00000004)) == 0) && target->buffer != NULL((void *)0)) | |||
1688 | name = target; | |||
1689 | else { | |||
1690 | dns_fixedname_init(&fn)do { dns_name_init(&((&fn)->name), (&fn)->offsets ); isc__buffer_init(&((&fn)->buffer), (&fn)-> data, 255); dns_name_setbuffer(&((&fn)->name), & ((&fn)->buffer)); } while (0); | |||
1691 | name = dns_fixedname_name(&fn)(&((&fn)->name)); | |||
1692 | } | |||
1693 | ||||
1694 | result = dns_name_fromtext(name, &buf, origin, options, NULL((void *)0)); | |||
1695 | if (result != ISC_R_SUCCESS0) | |||
1696 | return (result); | |||
1697 | ||||
1698 | if (name != target) | |||
1699 | result = dns_name_dupwithoffsets(name, target); | |||
1700 | return (result); | |||
1701 | } | |||
1702 | ||||
1703 | isc_result_t | |||
1704 | dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) { | |||
1705 | unsigned char *ndata; | |||
1706 | ||||
1707 | /* | |||
1708 | * Make dest a copy of source. | |||
1709 | */ | |||
1710 | ||||
1711 | REQUIRE(target != NULL || dest->buffer != NULL)((void) ((target != ((void *)0) || dest->buffer != ((void * )0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1711, isc_assertiontype_require, "target != ((void *)0) || dest->buffer != ((void *)0)" ), 0))); | |||
1712 | ||||
1713 | if (target == NULL((void *)0)) { | |||
1714 | target = dest->buffer; | |||
1715 | isc_buffer_clearisc__buffer_clear(dest->buffer); | |||
1716 | } | |||
1717 | ||||
1718 | REQUIRE(BINDABLE(dest))((void) ((((dest->attributes & (0x00000002|0x00000004) ) == 0)) || ((isc_assertion_failed)("/usr/src/usr.bin/dig/lib/dns/name.c" , 1718, isc_assertiontype_require, "((dest->attributes & (0x00000002|0x00000004)) == 0)" ), 0))); | |||
1719 | ||||
1720 | /* | |||
1721 | * Set up. | |||
1722 | */ | |||
1723 | if (target->length - target->used < source->length) | |||
1724 | return (ISC_R_NOSPACE19); | |||
1725 | ||||
1726 | ndata = (unsigned char *)target->base + target->used; | |||
1727 | dest->ndata = target->base; | |||
1728 | ||||
1729 | if (source->length != 0) | |||
1730 | memmove(ndata, source->ndata, source->length); | |||
1731 | ||||
1732 | dest->ndata = ndata; | |||
1733 | dest->labels = source->labels; | |||
1734 | dest->length = source->length; | |||
1735 | if ((source->attributes & DNS_NAMEATTR_ABSOLUTE0x00000001) != 0) | |||
1736 | dest->attributes = DNS_NAMEATTR_ABSOLUTE0x00000001; | |||
1737 | else | |||
1738 | dest->attributes = 0; | |||
1739 | ||||
1740 | if (dest->labels > 0 && dest->offsets != NULL((void *)0)) { | |||
1741 | if (source->offsets != NULL((void *)0)) | |||
1742 | memmove(dest->offsets, source->offsets, source->labels); | |||
1743 | else | |||
1744 | set_offsets(dest, dest->offsets, NULL((void *)0)); | |||
1745 | } | |||
1746 | ||||
1747 | isc_buffer_addisc__buffer_add(target, dest->length); | |||
1748 | ||||
1749 | return (ISC_R_SUCCESS0); | |||
1750 | } |