1 /* 2 * dname.h -- Domain name handling. 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 #ifndef DNAME_H 11 #define DNAME_H 12 13 #include <assert.h> 14 #include <stdio.h> 15 16 #include "buffer.h" 17 #include "region-allocator.h" 18 #include "dns.h" /* for MAXDOMAINLEN */ 19 20 #if defined(NAMEDB_UPPERCASE) || defined(USE_NAMEDB_UPPERCASE) 21 #define DNAME_NORMALIZE toupper 22 #else 23 #define DNAME_NORMALIZE tolower 24 #endif 25 26 27 /* 28 * Domain names stored in memory add some additional information to be 29 * able to quickly index and compare by label. 30 */ 31 typedef struct dname dname_type; 32 struct dname 33 { 34 /* 35 * The size (in bytes) of the domain name in wire format. 36 */ 37 uint8_t name_size; 38 39 /* 40 * The number of labels in this domain name (including the 41 * root label). 42 */ 43 uint8_t label_count; 44 45 /* 46 uint8_t label_offsets[label_count]; 47 uint8_t name[name_size]; 48 */ 49 }; 50 51 52 /* 53 * Construct a new domain name based on NAME in wire format. NAME 54 * cannot contain compression pointers. 55 * 56 * Pre: NAME != NULL. 57 */ 58 const dname_type *dname_make(region_type *region, const uint8_t *name, 59 int normalize); 60 61 /* 62 * Construct a new domain name based on wire format dname stored at 63 * PACKET's current position. Compression pointers are followed. The 64 * PACKET's current position is changed to the end of the wire format 65 * dname or set to just after the first compression pointer. 66 */ 67 const dname_type *dname_make_from_packet(region_type *region, 68 buffer_type *packet, 69 int allow_pointers, 70 int normalize); 71 72 /* 73 * parse wireformat from packet (following pointers) into the 74 * given buffer. Returns length in buffer or 0 on error. 75 * buffer must be MAXDOMAINLEN+1 long. 76 */ 77 int dname_make_wire_from_packet(uint8_t *buf, 78 buffer_type *packet, 79 int allow_pointers); 80 81 /* 82 * Construct a new domain name based on the ASCII representation NAME. 83 * If ORIGIN is not NULL and NAME is not terminated by a "." the 84 * ORIGIN is appended to the result. NAME can contain escape 85 * sequences. 86 * 87 * Returns NULL on failure. Otherwise a newly allocated domain name 88 * is returned. 89 * 90 * Pre: name != NULL. 91 */ 92 const dname_type *dname_parse(region_type *region, const char *name); 93 94 /* 95 * parse ascii string to wireformat domain name (without compression ptrs) 96 * returns 0 on failure, the length of the wireformat on success. 97 * the result is stored in the wirefmt which must be at least MAXDOMAINLEN 98 * in size. On failure, the wirefmt can be altered. 99 */ 100 int dname_parse_wire(uint8_t* wirefmt, const char* name); 101 102 /* 103 * Return NULL if DNAME is NULL or a copy of DNAME otherwise. 104 */ 105 const dname_type *dname_copy(region_type *region, const dname_type *dname); 106 107 108 /* 109 * Copy the most significant LABEL_COUNT labels from dname. 110 */ 111 const dname_type *dname_partial_copy(region_type *region, 112 const dname_type *dname, 113 uint8_t label_count); 114 115 116 /* 117 * The origin of DNAME. 118 */ 119 const dname_type *dname_origin(region_type *region, const dname_type *dname); 120 121 /* 122 * Return true if LEFT is a subdomain of RIGHT. 123 */ 124 int dname_is_subdomain(const dname_type *left, const dname_type *right); 125 126 127 /* 128 * Offsets into NAME for each label starting with the most 129 * significant label (the root label, followed by the TLD, 130 * etc). 131 */ 132 static inline const uint8_t * 133 dname_label_offsets(const dname_type *dname) 134 { 135 return (const uint8_t *) ((const char *) dname + sizeof(dname_type)); 136 } 137 138 139 /* 140 * The actual name in wire format (a sequence of label, each 141 * prefixed by a length byte, terminated by a zero length 142 * label). 143 */ 144 static inline const uint8_t * 145 dname_name(const dname_type *dname) 146 { 147 return (const uint8_t *) ((const char *) dname 148 + sizeof(dname_type) 149 + dname->label_count * sizeof(uint8_t)); 150 } 151 152 153 /* 154 * Return the label for DNAME specified by LABEL_INDEX. The first 155 * label (LABEL_INDEX == 0) is the root label, the next label is the 156 * TLD, etc. 157 * 158 * Pre: dname != NULL && label_index < dname->label_count. 159 */ 160 static inline const uint8_t * 161 dname_label(const dname_type *dname, uint8_t label) 162 { 163 uint8_t label_index; 164 165 assert(dname != NULL); 166 assert(label < dname->label_count); 167 168 label_index = dname_label_offsets(dname)[label]; 169 assert(label_index < dname->name_size); 170 171 return dname_name(dname) + label_index; 172 } 173 174 175 /* 176 * Compare two domain names. The comparison defines a lexicographical 177 * ordering based on the domain name's labels, starting with the most 178 * significant label. 179 * 180 * Return < 0 if LEFT < RIGHT, 0 if LEFT == RIGHT, and > 0 if LEFT > 181 * RIGHT. The comparison is case sensitive. 182 * 183 * Pre: left != NULL && right != NULL 184 * left and right are dname_type*. 185 */ 186 int dname_compare(const void *left, const void *right); 187 188 189 /* 190 * Compare two labels. The comparison defines a lexicographical 191 * ordering based on the characters in the labels. 192 * 193 * Return < 0 if LEFT < RIGHT, 0 if LEFT == RIGHT, and > 0 if LEFT > 194 * RIGHT. The comparison is case sensitive. 195 * 196 * Pre: left != NULL && right != NULL 197 * label_is_normal(left) && label_is_normal(right) 198 */ 199 int label_compare(const uint8_t *left, const uint8_t *right); 200 201 202 /* 203 * Returns the number of labels that match in LEFT and RIGHT, starting 204 * with the most significant label. Because the root label always 205 * matches, the result will always be >= 1. 206 * 207 * Pre: left != NULL && right != NULL 208 */ 209 uint8_t dname_label_match_count(const dname_type *left, 210 const dname_type *right); 211 212 213 /* 214 * The total size (in bytes) allocated to store DNAME. 215 * 216 * Pre: dname != NULL 217 */ 218 static inline size_t 219 dname_total_size(const dname_type *dname) 220 { 221 return (sizeof(dname_type) 222 + ((((size_t)dname->label_count) + ((size_t)dname->name_size)) 223 * sizeof(uint8_t))); 224 } 225 226 227 /* 228 * Is LABEL a normal LABEL (not a pointer or reserved)? 229 * 230 * Pre: label != NULL; 231 */ 232 static inline int 233 label_is_normal(const uint8_t *label) 234 { 235 assert(label); 236 return (label[0] & 0xc0) == 0; 237 } 238 239 240 /* 241 * Is LABEL a pointer? 242 * 243 * Pre: label != NULL; 244 */ 245 static inline int 246 label_is_pointer(const uint8_t *label) 247 { 248 assert(label); 249 return (label[0] & 0xc0) == 0xc0; 250 } 251 252 253 /* 254 * LABEL's pointer location. 255 * 256 * Pre: label != NULL && label_is_pointer(label) 257 */ 258 static inline uint16_t 259 label_pointer_location(const uint8_t *label) 260 { 261 assert(label); 262 assert(label_is_pointer(label)); 263 return ((uint16_t) (label[0] & ~0xc0) << 8) | (uint16_t) label[1]; 264 } 265 266 267 /* 268 * Length of LABEL. 269 * 270 * Pre: label != NULL && label_is_normal(label) 271 */ 272 static inline uint8_t 273 label_length(const uint8_t *label) 274 { 275 assert(label); 276 assert(label_is_normal(label)); 277 return label[0]; 278 } 279 280 281 /* 282 * The data of LABEL. 283 * 284 * Pre: label != NULL && label_is_normal(label) 285 */ 286 static inline const uint8_t * 287 label_data(const uint8_t *label) 288 { 289 assert(label); 290 assert(label_is_normal(label)); 291 return label + 1; 292 } 293 294 295 /* 296 * Is LABEL the root label? 297 * 298 * Pre: label != NULL 299 */ 300 static inline int 301 label_is_root(const uint8_t *label) 302 { 303 assert(label); 304 return label[0] == 0; 305 } 306 307 308 /* 309 * Is LABEL the wildcard label? 310 * 311 * Pre: label != NULL 312 */ 313 static inline int 314 label_is_wildcard(const uint8_t *label) 315 { 316 assert(label); 317 return label[0] == 1 && label[1] == '*'; 318 } 319 320 321 /* 322 * The next label of LABEL. 323 * 324 * Pre: label != NULL 325 * label_is_normal(label) 326 * !label_is_root(label) 327 */ 328 static inline const uint8_t * 329 label_next(const uint8_t *label) 330 { 331 assert(label); 332 assert(label_is_normal(label)); 333 assert(!label_is_root(label)); 334 return label + label_length(label) + 1; 335 } 336 337 338 /* 339 * Convert DNAME to its string representation. The result points to a 340 * static buffer that is overwritten the next time this function is 341 * invoked. 342 * 343 * If ORIGIN is provided and DNAME is a subdomain of ORIGIN the dname 344 * will be represented relative to ORIGIN. 345 * 346 * Pre: dname != NULL 347 */ 348 const char *dname_to_string(const dname_type *dname, 349 const dname_type *origin); 350 351 /* 352 * Convert DNAME to its string representation. The result if written 353 * to the provided buffer buf, which must be at least 5 times 354 * MAXDOMAINNAMELEN. 355 * 356 * If ORIGIN is provided and DNAME is a subdomain of ORIGIN the dname 357 * will be represented relative to ORIGIN. 358 * 359 * Pre: dname != NULL 360 */ 361 const char *dname_to_string_buf(const dname_type *dname, 362 const dname_type *origin, 363 char buf[MAXDOMAINLEN * 5]); 364 365 /* 366 * Create a dname containing the single label specified by STR 367 * followed by the root label. 368 */ 369 const dname_type *dname_make_from_label(region_type *region, 370 const uint8_t *label, 371 const size_t length); 372 373 374 /* 375 * Concatenate two dnames. 376 */ 377 const dname_type *dname_concatenate(region_type *region, 378 const dname_type *left, 379 const dname_type *right); 380 381 382 /* 383 * Perform DNAME substitution on a name, replace src with dest. 384 * Name must be a subdomain of src. The returned name is a subdomain of dest. 385 * Returns NULL if the result domain name is too long. 386 */ 387 const dname_type *dname_replace(region_type* region, 388 const dname_type* name, 389 const dname_type* src, 390 const dname_type* dest); 391 392 /** Convert uncompressed wireformat dname to a string */ 393 char* wiredname2str(const uint8_t* dname); 394 /** convert uncompressed label to string */ 395 char* wirelabel2str(const uint8_t* label); 396 /** check if two uncompressed dnames of the same total length are equal */ 397 int dname_equal_nocase(uint8_t* a, uint8_t* b, uint16_t len); 398 399 /* Test is the name is a subdomain of the other name. Equal names return true. 400 * Subdomain d of d2 returns true, otherwise false. The names are in 401 * wireformat, uncompressed. Does not perform canonicalization, it is case 402 * sensitive. */ 403 int is_dname_subdomain_of_case(const uint8_t* d, unsigned int len, 404 const uint8_t* d2, unsigned int len2); 405 406 /* 407 * Calculate length of dname in uncompressed wireformat in buffer. 408 * @param buf: The buffer with the uncompressed dname. 409 * @param len: length of the buffer. 410 * @return 0 on error, otherwise the uncompressed wireformat dname 411 * length is returned. 412 */ 413 size_t buf_dname_length(const uint8_t* buf, size_t len); 414 415 /* This structure is sufficient in size for a struct dname. It can 416 * be cast to a struct dname*, since it has the same data. */ 417 struct dname_buffer { 418 struct dname dname; 419 /* storage for labelcount, and for the wireformat name. 420 * The labelcount can be 1 byte per label, maxlen/2 + 1(root label). 421 * The wireformat name, MAXDOMAINLEN+1. 422 * This allocates storage for it, due to alignment, the struct 423 * dname may have padding. The content is stored after the 424 * sizeof(struct dname), with label_offsets and name. */ 425 uint8_t storage[MAXDOMAINLEN/2 + 1 + MAXDOMAINLEN+1 ]; 426 }; 427 428 /* 429 * Make the dname and label offsets. 430 * @param dname: the buffer with size. The result is in here, at the 431 * start of the allocated size. The input is also buffered temporarily 432 * in here. 433 * @param name: input name, points into the buffer space of dname. 434 * @param normalize: if the dname has to be normalized. 435 * @return 0 on failure. 436 */ 437 int dname_make_buffered(struct dname_buffer* dname, uint8_t *name, 438 int normalize); 439 440 /* 441 * Parse a domain name from packet and store it in the buffer. 442 * @param dname: the buffer with sufficient size for the dname. 443 * @param packet: packet, at the position of the dname. The position is moved. 444 * @param allow_pointers: set to true if compression pointers are allowed. 445 * @param normalize: set to true if the domain name has to be normalized. 446 * @return 0 on failure, or name_length when done. 447 */ 448 int dname_make_from_packet_buffered(struct dname_buffer* dname, 449 buffer_type *packet, int allow_pointers, int normalize); 450 451 #endif /* DNAME_H */ 452