1 /* 2 * dname.h -- Domain name handling. 3 * 4 * Copyright (c) 2001-2011, 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 19 #if defined(NAMEDB_UPPERCASE) || defined(USE_NAMEDB_UPPERCASE) 20 #define DNAME_NORMALIZE toupper 21 #else 22 #define DNAME_NORMALIZE tolower 23 #endif 24 25 26 /* 27 * Domain names stored in memory add some additional information to be 28 * able to quickly index and compare by label. 29 */ 30 typedef struct dname dname_type; 31 struct dname 32 { 33 /* 34 * The size (in bytes) of the domain name in wire format. 35 */ 36 uint8_t name_size; 37 38 /* 39 * The number of labels in this domain name (including the 40 * root label). 41 */ 42 uint8_t label_count; 43 44 /* 45 uint8_t label_offsets[label_count]; 46 uint8_t name[name_size]; 47 */ 48 }; 49 50 51 /* 52 * Construct a new domain name based on NAME in wire format. NAME 53 * cannot contain compression pointers. 54 * 55 * Pre: NAME != NULL. 56 */ 57 const dname_type *dname_make(region_type *region, const uint8_t *name, 58 int normalize); 59 60 /* 61 * Construct a new domain name based on wire format dname stored at 62 * PACKET's current position. Compression pointers are followed. The 63 * PACKET's current position is changed to the end of the wire format 64 * dname or set to just after the first compression pointer. 65 */ 66 const dname_type *dname_make_from_packet(region_type *region, 67 buffer_type *packet, 68 int allow_pointers, 69 int normalize); 70 71 /* 72 * parse wireformat from packet (following pointers) into the 73 * given buffer. Returns length in buffer or 0 on error. 74 * buffer must be MAXDOMAINLEN+1 long. 75 */ 76 int dname_make_wire_from_packet(uint8_t *buf, 77 buffer_type *packet, 78 int allow_pointers); 79 80 /* 81 * Construct a new domain name based on the ASCII representation NAME. 82 * If ORIGIN is not NULL and NAME is not terminated by a "." the 83 * ORIGIN is appended to the result. NAME can contain escape 84 * sequences. 85 * 86 * Returns NULL on failure. Otherwise a newly allocated domain name 87 * is returned. 88 * 89 * Pre: name != NULL. 90 */ 91 const dname_type *dname_parse(region_type *region, const char *name); 92 93 /* 94 * parse ascii string to wireformat domain name (without compression ptrs) 95 * returns 0 on failure, the length of the wireformat on success. 96 * the result is stored in the wirefmt which must be at least MAXDOMAINLEN 97 * in size. On failure, the wirefmt can be altered. 98 */ 99 int dname_parse_wire(uint8_t* wirefmt, const char* name); 100 101 /* 102 * Return NULL if DNAME is NULL or a copy of DNAME otherwise. 103 */ 104 const dname_type *dname_copy(region_type *region, const dname_type *dname); 105 106 107 /* 108 * Copy the most significant LABEL_COUNT labels from dname. 109 */ 110 const dname_type *dname_partial_copy(region_type *region, 111 const dname_type *dname, 112 uint8_t label_count); 113 114 115 /* 116 * The origin of DNAME. 117 */ 118 const dname_type *dname_origin(region_type *region, const dname_type *dname); 119 120 /* 121 * Return true if LEFT is a subdomain of RIGHT. 122 */ 123 int dname_is_subdomain(const dname_type *left, const dname_type *right); 124 125 126 /* 127 * Offsets into NAME for each label starting with the most 128 * significant label (the root label, followed by the TLD, 129 * etc). 130 */ 131 static inline const uint8_t * 132 dname_label_offsets(const dname_type *dname) 133 { 134 return (const uint8_t *) ((const char *) dname + sizeof(dname_type)); 135 } 136 137 138 /* 139 * The actual name in wire format (a sequence of label, each 140 * prefixed by a length byte, terminated by a zero length 141 * label). 142 */ 143 static inline const uint8_t * 144 dname_name(const dname_type *dname) 145 { 146 return (const uint8_t *) ((const char *) dname 147 + sizeof(dname_type) 148 + dname->label_count * sizeof(uint8_t)); 149 } 150 151 152 /* 153 * Return the label for DNAME specified by LABEL_INDEX. The first 154 * label (LABEL_INDEX == 0) is the root label, the next label is the 155 * TLD, etc. 156 * 157 * Pre: dname != NULL && label_index < dname->label_count. 158 */ 159 static inline const uint8_t * 160 dname_label(const dname_type *dname, uint8_t label) 161 { 162 uint8_t label_index; 163 164 assert(dname != NULL); 165 assert(label < dname->label_count); 166 167 label_index = dname_label_offsets(dname)[label]; 168 assert(label_index < dname->name_size); 169 170 return dname_name(dname) + label_index; 171 } 172 173 174 /* 175 * Compare two domain names. The comparison defines a lexographical 176 * ordering based on the domain name's labels, starting with the most 177 * significant label. 178 * 179 * Return < 0 if LEFT < RIGHT, 0 if LEFT == RIGHT, and > 0 if LEFT > 180 * RIGHT. The comparison is case sensitive. 181 * 182 * Pre: left != NULL && right != NULL 183 */ 184 int dname_compare(const dname_type *left, const dname_type *right); 185 186 187 /* 188 * Compare two labels. The comparison defines a lexographical 189 * ordering based on the characters in the labels. 190 * 191 * Return < 0 if LEFT < RIGHT, 0 if LEFT == RIGHT, and > 0 if LEFT > 192 * RIGHT. The comparison is case sensitive. 193 * 194 * Pre: left != NULL && right != NULL 195 * label_is_normal(left) && label_is_normal(right) 196 */ 197 int label_compare(const uint8_t *left, const uint8_t *right); 198 199 200 /* 201 * Returns the number of labels that match in LEFT and RIGHT, starting 202 * with the most significant label. Because the root label always 203 * matches, the result will always be >= 1. 204 * 205 * Pre: left != NULL && right != NULL 206 */ 207 uint8_t dname_label_match_count(const dname_type *left, 208 const dname_type *right); 209 210 211 /* 212 * The total size (in bytes) allocated to store DNAME. 213 * 214 * Pre: dname != NULL 215 */ 216 static inline size_t 217 dname_total_size(const dname_type *dname) 218 { 219 return (sizeof(dname_type) 220 + ((dname->label_count + dname->name_size) 221 * sizeof(uint8_t))); 222 } 223 224 225 /* 226 * Is LABEL a normal LABEL (not a pointer or reserved)? 227 * 228 * Pre: label != NULL; 229 */ 230 static inline int 231 label_is_normal(const uint8_t *label) 232 { 233 assert(label); 234 return (label[0] & 0xc0) == 0; 235 } 236 237 238 /* 239 * Is LABEL a pointer? 240 * 241 * Pre: label != NULL; 242 */ 243 static inline int 244 label_is_pointer(const uint8_t *label) 245 { 246 assert(label); 247 return (label[0] & 0xc0) == 0xc0; 248 } 249 250 251 /* 252 * LABEL's pointer location. 253 * 254 * Pre: label != NULL && label_is_pointer(label) 255 */ 256 static inline uint16_t 257 label_pointer_location(const uint8_t *label) 258 { 259 assert(label); 260 assert(label_is_pointer(label)); 261 return ((uint16_t) (label[0] & ~0xc0) << 8) | (uint16_t) label[1]; 262 } 263 264 265 /* 266 * Length of LABEL. 267 * 268 * Pre: label != NULL && label_is_normal(label) 269 */ 270 static inline uint8_t 271 label_length(const uint8_t *label) 272 { 273 assert(label); 274 assert(label_is_normal(label)); 275 return label[0]; 276 } 277 278 279 /* 280 * The data of LABEL. 281 * 282 * Pre: label != NULL && label_is_normal(label) 283 */ 284 static inline const uint8_t * 285 label_data(const uint8_t *label) 286 { 287 assert(label); 288 assert(label_is_normal(label)); 289 return label + 1; 290 } 291 292 293 /* 294 * Is LABEL the root label? 295 * 296 * Pre: label != NULL 297 */ 298 static inline int 299 label_is_root(const uint8_t *label) 300 { 301 assert(label); 302 return label[0] == 0; 303 } 304 305 306 /* 307 * Is LABEL the wildcard label? 308 * 309 * Pre: label != NULL 310 */ 311 static inline int 312 label_is_wildcard(const uint8_t *label) 313 { 314 assert(label); 315 return label[0] == 1 && label[1] == '*'; 316 } 317 318 319 /* 320 * The next label of LABEL. 321 * 322 * Pre: label != NULL 323 * label_is_normal(label) 324 * !label_is_root(label) 325 */ 326 static inline const uint8_t * 327 label_next(const uint8_t *label) 328 { 329 assert(label); 330 assert(label_is_normal(label)); 331 assert(!label_is_root(label)); 332 return label + label_length(label) + 1; 333 } 334 335 336 /* 337 * Convert DNAME to its string representation. The result points to a 338 * static buffer that is overwritten the next time this function is 339 * invoked. 340 * 341 * If ORIGIN is provided and DNAME is a subdomain of ORIGIN the dname 342 * will be represented relative to ORIGIN. 343 * 344 * Pre: dname != NULL 345 */ 346 const char *dname_to_string(const dname_type *dname, 347 const dname_type *origin); 348 349 350 /* 351 * Create a dname containing the single label specified by STR 352 * followed by the root label. 353 */ 354 const dname_type *dname_make_from_label(region_type *region, 355 const uint8_t *label, 356 const size_t length); 357 358 359 /* 360 * Concatenate two dnames. 361 */ 362 const dname_type *dname_concatenate(region_type *region, 363 const dname_type *left, 364 const dname_type *right); 365 366 367 /* 368 * Perform DNAME substitution on a name, replace src with dest. 369 * Name must be a subdomain of src. The returned name is a subdomain of dest. 370 * Returns NULL if the result domain name is too long. 371 */ 372 const dname_type *dname_replace(region_type* region, 373 const dname_type* name, 374 const dname_type* src, 375 const dname_type* dest); 376 377 #endif /* _DNAME_H_ */ 378