| 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 | } |