Home | History | Annotate | Line # | Download | only in dist
      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