162ac0c33Sjakob /*
262ac0c33Sjakob * dname.h -- Domain name handling.
362ac0c33Sjakob *
4d3fecca9Ssthen * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
562ac0c33Sjakob *
662ac0c33Sjakob * See LICENSE for the license.
762ac0c33Sjakob *
862ac0c33Sjakob */
962ac0c33Sjakob
103efee2e1Sflorian #ifndef DNAME_H
113efee2e1Sflorian #define DNAME_H
1262ac0c33Sjakob
1362ac0c33Sjakob #include <assert.h>
1462ac0c33Sjakob #include <stdio.h>
1562ac0c33Sjakob
1662ac0c33Sjakob #include "buffer.h"
1762ac0c33Sjakob #include "region-allocator.h"
18*bf87c3c0Sflorian #include "dns.h" /* for MAXDOMAINLEN */
1962ac0c33Sjakob
2062ac0c33Sjakob #if defined(NAMEDB_UPPERCASE) || defined(USE_NAMEDB_UPPERCASE)
2162ac0c33Sjakob #define DNAME_NORMALIZE toupper
2262ac0c33Sjakob #else
2362ac0c33Sjakob #define DNAME_NORMALIZE tolower
2462ac0c33Sjakob #endif
2562ac0c33Sjakob
2662ac0c33Sjakob
2762ac0c33Sjakob /*
2862ac0c33Sjakob * Domain names stored in memory add some additional information to be
2962ac0c33Sjakob * able to quickly index and compare by label.
3062ac0c33Sjakob */
3162ac0c33Sjakob typedef struct dname dname_type;
3262ac0c33Sjakob struct dname
3362ac0c33Sjakob {
3462ac0c33Sjakob /*
3562ac0c33Sjakob * The size (in bytes) of the domain name in wire format.
3662ac0c33Sjakob */
3762ac0c33Sjakob uint8_t name_size;
3862ac0c33Sjakob
3962ac0c33Sjakob /*
4062ac0c33Sjakob * The number of labels in this domain name (including the
4162ac0c33Sjakob * root label).
4262ac0c33Sjakob */
4362ac0c33Sjakob uint8_t label_count;
4462ac0c33Sjakob
4562ac0c33Sjakob /*
4662ac0c33Sjakob uint8_t label_offsets[label_count];
4762ac0c33Sjakob uint8_t name[name_size];
4862ac0c33Sjakob */
4962ac0c33Sjakob };
5062ac0c33Sjakob
5162ac0c33Sjakob
5262ac0c33Sjakob /*
5362ac0c33Sjakob * Construct a new domain name based on NAME in wire format. NAME
5462ac0c33Sjakob * cannot contain compression pointers.
5562ac0c33Sjakob *
5662ac0c33Sjakob * Pre: NAME != NULL.
5762ac0c33Sjakob */
5862ac0c33Sjakob const dname_type *dname_make(region_type *region, const uint8_t *name,
5962ac0c33Sjakob int normalize);
6062ac0c33Sjakob
6162ac0c33Sjakob /*
6262ac0c33Sjakob * Construct a new domain name based on wire format dname stored at
6362ac0c33Sjakob * PACKET's current position. Compression pointers are followed. The
6462ac0c33Sjakob * PACKET's current position is changed to the end of the wire format
6562ac0c33Sjakob * dname or set to just after the first compression pointer.
6662ac0c33Sjakob */
6762ac0c33Sjakob const dname_type *dname_make_from_packet(region_type *region,
6862ac0c33Sjakob buffer_type *packet,
6962ac0c33Sjakob int allow_pointers,
7062ac0c33Sjakob int normalize);
7162ac0c33Sjakob
7262ac0c33Sjakob /*
7362ac0c33Sjakob * parse wireformat from packet (following pointers) into the
7462ac0c33Sjakob * given buffer. Returns length in buffer or 0 on error.
7562ac0c33Sjakob * buffer must be MAXDOMAINLEN+1 long.
7662ac0c33Sjakob */
7762ac0c33Sjakob int dname_make_wire_from_packet(uint8_t *buf,
7862ac0c33Sjakob buffer_type *packet,
7962ac0c33Sjakob int allow_pointers);
8062ac0c33Sjakob
8162ac0c33Sjakob /*
8262ac0c33Sjakob * Construct a new domain name based on the ASCII representation NAME.
8362ac0c33Sjakob * If ORIGIN is not NULL and NAME is not terminated by a "." the
8462ac0c33Sjakob * ORIGIN is appended to the result. NAME can contain escape
8562ac0c33Sjakob * sequences.
8662ac0c33Sjakob *
8762ac0c33Sjakob * Returns NULL on failure. Otherwise a newly allocated domain name
8862ac0c33Sjakob * is returned.
8962ac0c33Sjakob *
9062ac0c33Sjakob * Pre: name != NULL.
9162ac0c33Sjakob */
9262ac0c33Sjakob const dname_type *dname_parse(region_type *region, const char *name);
9362ac0c33Sjakob
9462ac0c33Sjakob /*
9562ac0c33Sjakob * parse ascii string to wireformat domain name (without compression ptrs)
9662ac0c33Sjakob * returns 0 on failure, the length of the wireformat on success.
9762ac0c33Sjakob * the result is stored in the wirefmt which must be at least MAXDOMAINLEN
9862ac0c33Sjakob * in size. On failure, the wirefmt can be altered.
9962ac0c33Sjakob */
10062ac0c33Sjakob int dname_parse_wire(uint8_t* wirefmt, const char* name);
10162ac0c33Sjakob
10262ac0c33Sjakob /*
10362ac0c33Sjakob * Return NULL if DNAME is NULL or a copy of DNAME otherwise.
10462ac0c33Sjakob */
10562ac0c33Sjakob const dname_type *dname_copy(region_type *region, const dname_type *dname);
10662ac0c33Sjakob
10762ac0c33Sjakob
10862ac0c33Sjakob /*
10962ac0c33Sjakob * Copy the most significant LABEL_COUNT labels from dname.
11062ac0c33Sjakob */
11162ac0c33Sjakob const dname_type *dname_partial_copy(region_type *region,
11262ac0c33Sjakob const dname_type *dname,
11362ac0c33Sjakob uint8_t label_count);
11462ac0c33Sjakob
11562ac0c33Sjakob
11662ac0c33Sjakob /*
11762ac0c33Sjakob * The origin of DNAME.
11862ac0c33Sjakob */
11962ac0c33Sjakob const dname_type *dname_origin(region_type *region, const dname_type *dname);
12062ac0c33Sjakob
12162ac0c33Sjakob /*
12262ac0c33Sjakob * Return true if LEFT is a subdomain of RIGHT.
12362ac0c33Sjakob */
12462ac0c33Sjakob int dname_is_subdomain(const dname_type *left, const dname_type *right);
12562ac0c33Sjakob
12662ac0c33Sjakob
12762ac0c33Sjakob /*
12862ac0c33Sjakob * Offsets into NAME for each label starting with the most
12962ac0c33Sjakob * significant label (the root label, followed by the TLD,
13062ac0c33Sjakob * etc).
13162ac0c33Sjakob */
13262ac0c33Sjakob static inline const uint8_t *
dname_label_offsets(const dname_type * dname)13362ac0c33Sjakob dname_label_offsets(const dname_type *dname)
13462ac0c33Sjakob {
13562ac0c33Sjakob return (const uint8_t *) ((const char *) dname + sizeof(dname_type));
13662ac0c33Sjakob }
13762ac0c33Sjakob
13862ac0c33Sjakob
13962ac0c33Sjakob /*
14062ac0c33Sjakob * The actual name in wire format (a sequence of label, each
14162ac0c33Sjakob * prefixed by a length byte, terminated by a zero length
14262ac0c33Sjakob * label).
14362ac0c33Sjakob */
14462ac0c33Sjakob static inline const uint8_t *
dname_name(const dname_type * dname)14562ac0c33Sjakob dname_name(const dname_type *dname)
14662ac0c33Sjakob {
14762ac0c33Sjakob return (const uint8_t *) ((const char *) dname
14862ac0c33Sjakob + sizeof(dname_type)
14962ac0c33Sjakob + dname->label_count * sizeof(uint8_t));
15062ac0c33Sjakob }
15162ac0c33Sjakob
15262ac0c33Sjakob
15362ac0c33Sjakob /*
15462ac0c33Sjakob * Return the label for DNAME specified by LABEL_INDEX. The first
15562ac0c33Sjakob * label (LABEL_INDEX == 0) is the root label, the next label is the
15662ac0c33Sjakob * TLD, etc.
15762ac0c33Sjakob *
15862ac0c33Sjakob * Pre: dname != NULL && label_index < dname->label_count.
15962ac0c33Sjakob */
16062ac0c33Sjakob static inline const uint8_t *
dname_label(const dname_type * dname,uint8_t label)16162ac0c33Sjakob dname_label(const dname_type *dname, uint8_t label)
16262ac0c33Sjakob {
16362ac0c33Sjakob uint8_t label_index;
16462ac0c33Sjakob
16562ac0c33Sjakob assert(dname != NULL);
16662ac0c33Sjakob assert(label < dname->label_count);
16762ac0c33Sjakob
16862ac0c33Sjakob label_index = dname_label_offsets(dname)[label];
16962ac0c33Sjakob assert(label_index < dname->name_size);
17062ac0c33Sjakob
17162ac0c33Sjakob return dname_name(dname) + label_index;
17262ac0c33Sjakob }
17362ac0c33Sjakob
17462ac0c33Sjakob
17562ac0c33Sjakob /*
1762fd875a4Ssthen * Compare two domain names. The comparison defines a lexicographical
17762ac0c33Sjakob * ordering based on the domain name's labels, starting with the most
17862ac0c33Sjakob * significant label.
17962ac0c33Sjakob *
18062ac0c33Sjakob * Return < 0 if LEFT < RIGHT, 0 if LEFT == RIGHT, and > 0 if LEFT >
18162ac0c33Sjakob * RIGHT. The comparison is case sensitive.
18262ac0c33Sjakob *
183d3fecca9Ssthen * Pre: left != NULL && right != NULL
18462ac0c33Sjakob */
185d3fecca9Ssthen int dname_compare(const dname_type *left, const dname_type *right);
18662ac0c33Sjakob
18762ac0c33Sjakob
18862ac0c33Sjakob /*
1892fd875a4Ssthen * Compare two labels. The comparison defines a lexicographical
19062ac0c33Sjakob * ordering based on the characters in the labels.
19162ac0c33Sjakob *
19262ac0c33Sjakob * Return < 0 if LEFT < RIGHT, 0 if LEFT == RIGHT, and > 0 if LEFT >
19362ac0c33Sjakob * RIGHT. The comparison is case sensitive.
19462ac0c33Sjakob *
19562ac0c33Sjakob * Pre: left != NULL && right != NULL
19662ac0c33Sjakob * label_is_normal(left) && label_is_normal(right)
19762ac0c33Sjakob */
19862ac0c33Sjakob int label_compare(const uint8_t *left, const uint8_t *right);
19962ac0c33Sjakob
20062ac0c33Sjakob
20162ac0c33Sjakob /*
20262ac0c33Sjakob * Returns the number of labels that match in LEFT and RIGHT, starting
20362ac0c33Sjakob * with the most significant label. Because the root label always
20462ac0c33Sjakob * matches, the result will always be >= 1.
20562ac0c33Sjakob *
20662ac0c33Sjakob * Pre: left != NULL && right != NULL
20762ac0c33Sjakob */
20862ac0c33Sjakob uint8_t dname_label_match_count(const dname_type *left,
20962ac0c33Sjakob const dname_type *right);
21062ac0c33Sjakob
21162ac0c33Sjakob
21262ac0c33Sjakob /*
21362ac0c33Sjakob * The total size (in bytes) allocated to store DNAME.
21462ac0c33Sjakob *
21562ac0c33Sjakob * Pre: dname != NULL
21662ac0c33Sjakob */
21762ac0c33Sjakob static inline size_t
dname_total_size(const dname_type * dname)21862ac0c33Sjakob dname_total_size(const dname_type *dname)
21962ac0c33Sjakob {
22062ac0c33Sjakob return (sizeof(dname_type)
221c939baa4Ssthen + ((((size_t)dname->label_count) + ((size_t)dname->name_size))
22262ac0c33Sjakob * sizeof(uint8_t)));
22362ac0c33Sjakob }
22462ac0c33Sjakob
22562ac0c33Sjakob
22662ac0c33Sjakob /*
22762ac0c33Sjakob * Is LABEL a normal LABEL (not a pointer or reserved)?
22862ac0c33Sjakob *
22962ac0c33Sjakob * Pre: label != NULL;
23062ac0c33Sjakob */
23162ac0c33Sjakob static inline int
label_is_normal(const uint8_t * label)23262ac0c33Sjakob label_is_normal(const uint8_t *label)
23362ac0c33Sjakob {
23462ac0c33Sjakob assert(label);
23562ac0c33Sjakob return (label[0] & 0xc0) == 0;
23662ac0c33Sjakob }
23762ac0c33Sjakob
23862ac0c33Sjakob
23962ac0c33Sjakob /*
24062ac0c33Sjakob * Is LABEL a pointer?
24162ac0c33Sjakob *
24262ac0c33Sjakob * Pre: label != NULL;
24362ac0c33Sjakob */
24462ac0c33Sjakob static inline int
label_is_pointer(const uint8_t * label)24562ac0c33Sjakob label_is_pointer(const uint8_t *label)
24662ac0c33Sjakob {
24762ac0c33Sjakob assert(label);
24862ac0c33Sjakob return (label[0] & 0xc0) == 0xc0;
24962ac0c33Sjakob }
25062ac0c33Sjakob
25162ac0c33Sjakob
25262ac0c33Sjakob /*
25362ac0c33Sjakob * LABEL's pointer location.
25462ac0c33Sjakob *
25562ac0c33Sjakob * Pre: label != NULL && label_is_pointer(label)
25662ac0c33Sjakob */
25762ac0c33Sjakob static inline uint16_t
label_pointer_location(const uint8_t * label)25862ac0c33Sjakob label_pointer_location(const uint8_t *label)
25962ac0c33Sjakob {
26062ac0c33Sjakob assert(label);
26162ac0c33Sjakob assert(label_is_pointer(label));
26262ac0c33Sjakob return ((uint16_t) (label[0] & ~0xc0) << 8) | (uint16_t) label[1];
26362ac0c33Sjakob }
26462ac0c33Sjakob
26562ac0c33Sjakob
26662ac0c33Sjakob /*
26762ac0c33Sjakob * Length of LABEL.
26862ac0c33Sjakob *
26962ac0c33Sjakob * Pre: label != NULL && label_is_normal(label)
27062ac0c33Sjakob */
27162ac0c33Sjakob static inline uint8_t
label_length(const uint8_t * label)27262ac0c33Sjakob label_length(const uint8_t *label)
27362ac0c33Sjakob {
27462ac0c33Sjakob assert(label);
27562ac0c33Sjakob assert(label_is_normal(label));
27662ac0c33Sjakob return label[0];
27762ac0c33Sjakob }
27862ac0c33Sjakob
27962ac0c33Sjakob
28062ac0c33Sjakob /*
28162ac0c33Sjakob * The data of LABEL.
28262ac0c33Sjakob *
28362ac0c33Sjakob * Pre: label != NULL && label_is_normal(label)
28462ac0c33Sjakob */
28562ac0c33Sjakob static inline const uint8_t *
label_data(const uint8_t * label)28662ac0c33Sjakob label_data(const uint8_t *label)
28762ac0c33Sjakob {
28862ac0c33Sjakob assert(label);
28962ac0c33Sjakob assert(label_is_normal(label));
29062ac0c33Sjakob return label + 1;
29162ac0c33Sjakob }
29262ac0c33Sjakob
29362ac0c33Sjakob
29462ac0c33Sjakob /*
29562ac0c33Sjakob * Is LABEL the root label?
29662ac0c33Sjakob *
29762ac0c33Sjakob * Pre: label != NULL
29862ac0c33Sjakob */
29962ac0c33Sjakob static inline int
label_is_root(const uint8_t * label)30062ac0c33Sjakob label_is_root(const uint8_t *label)
30162ac0c33Sjakob {
30262ac0c33Sjakob assert(label);
30362ac0c33Sjakob return label[0] == 0;
30462ac0c33Sjakob }
30562ac0c33Sjakob
30662ac0c33Sjakob
30762ac0c33Sjakob /*
30862ac0c33Sjakob * Is LABEL the wildcard label?
30962ac0c33Sjakob *
31062ac0c33Sjakob * Pre: label != NULL
31162ac0c33Sjakob */
31262ac0c33Sjakob static inline int
label_is_wildcard(const uint8_t * label)31362ac0c33Sjakob label_is_wildcard(const uint8_t *label)
31462ac0c33Sjakob {
31562ac0c33Sjakob assert(label);
31662ac0c33Sjakob return label[0] == 1 && label[1] == '*';
31762ac0c33Sjakob }
31862ac0c33Sjakob
31962ac0c33Sjakob
32062ac0c33Sjakob /*
32162ac0c33Sjakob * The next label of LABEL.
32262ac0c33Sjakob *
32362ac0c33Sjakob * Pre: label != NULL
32462ac0c33Sjakob * label_is_normal(label)
32562ac0c33Sjakob * !label_is_root(label)
32662ac0c33Sjakob */
32762ac0c33Sjakob static inline const uint8_t *
label_next(const uint8_t * label)32862ac0c33Sjakob label_next(const uint8_t *label)
32962ac0c33Sjakob {
33062ac0c33Sjakob assert(label);
33162ac0c33Sjakob assert(label_is_normal(label));
33262ac0c33Sjakob assert(!label_is_root(label));
33362ac0c33Sjakob return label + label_length(label) + 1;
33462ac0c33Sjakob }
33562ac0c33Sjakob
33662ac0c33Sjakob
33762ac0c33Sjakob /*
33862ac0c33Sjakob * Convert DNAME to its string representation. The result points to a
33962ac0c33Sjakob * static buffer that is overwritten the next time this function is
34062ac0c33Sjakob * invoked.
34162ac0c33Sjakob *
34262ac0c33Sjakob * If ORIGIN is provided and DNAME is a subdomain of ORIGIN the dname
34362ac0c33Sjakob * will be represented relative to ORIGIN.
34462ac0c33Sjakob *
34562ac0c33Sjakob * Pre: dname != NULL
34662ac0c33Sjakob */
34762ac0c33Sjakob const char *dname_to_string(const dname_type *dname,
34862ac0c33Sjakob const dname_type *origin);
34962ac0c33Sjakob
350*bf87c3c0Sflorian /*
351*bf87c3c0Sflorian * Convert DNAME to its string representation. The result if written
352*bf87c3c0Sflorian * to the provided buffer buf, which must be at least 5 times
353*bf87c3c0Sflorian * MAXDOMAINNAMELEN.
354*bf87c3c0Sflorian *
355*bf87c3c0Sflorian * If ORIGIN is provided and DNAME is a subdomain of ORIGIN the dname
356*bf87c3c0Sflorian * will be represented relative to ORIGIN.
357*bf87c3c0Sflorian *
358*bf87c3c0Sflorian * Pre: dname != NULL
359*bf87c3c0Sflorian */
360*bf87c3c0Sflorian const char *dname_to_string_buf(const dname_type *dname,
361*bf87c3c0Sflorian const dname_type *origin,
362*bf87c3c0Sflorian char buf[MAXDOMAINLEN * 5]);
36362ac0c33Sjakob
36462ac0c33Sjakob /*
36562ac0c33Sjakob * Create a dname containing the single label specified by STR
36662ac0c33Sjakob * followed by the root label.
36762ac0c33Sjakob */
36862ac0c33Sjakob const dname_type *dname_make_from_label(region_type *region,
36962ac0c33Sjakob const uint8_t *label,
37062ac0c33Sjakob const size_t length);
37162ac0c33Sjakob
37262ac0c33Sjakob
37362ac0c33Sjakob /*
37462ac0c33Sjakob * Concatenate two dnames.
37562ac0c33Sjakob */
37662ac0c33Sjakob const dname_type *dname_concatenate(region_type *region,
37762ac0c33Sjakob const dname_type *left,
37862ac0c33Sjakob const dname_type *right);
37962ac0c33Sjakob
38062ac0c33Sjakob
38162ac0c33Sjakob /*
38262ac0c33Sjakob * Perform DNAME substitution on a name, replace src with dest.
38362ac0c33Sjakob * Name must be a subdomain of src. The returned name is a subdomain of dest.
38462ac0c33Sjakob * Returns NULL if the result domain name is too long.
38562ac0c33Sjakob */
38662ac0c33Sjakob const dname_type *dname_replace(region_type* region,
38762ac0c33Sjakob const dname_type* name,
38862ac0c33Sjakob const dname_type* src,
38962ac0c33Sjakob const dname_type* dest);
39062ac0c33Sjakob
391d3fecca9Ssthen /** Convert uncompressed wireformat dname to a string */
392d3fecca9Ssthen char* wiredname2str(const uint8_t* dname);
393d3fecca9Ssthen /** convert uncompressed label to string */
394d3fecca9Ssthen char* wirelabel2str(const uint8_t* label);
395d3fecca9Ssthen /** check if two uncompressed dnames of the same total length are equal */
396d3fecca9Ssthen int dname_equal_nocase(uint8_t* a, uint8_t* b, uint16_t len);
3970c2b6c02Sjakob
3983efee2e1Sflorian #endif /* DNAME_H */
399