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 *
dname_label_offsets(const dname_type * dname)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 *
dname_name(const dname_type * dname)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 *
dname_label(const dname_type * dname,uint8_t label)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 */
185 int dname_compare(const dname_type *left, const dname_type *right);
186
187
188 /*
189 * Compare two labels. The comparison defines a lexicographical
190 * ordering based on the characters in the labels.
191 *
192 * Return < 0 if LEFT < RIGHT, 0 if LEFT == RIGHT, and > 0 if LEFT >
193 * RIGHT. The comparison is case sensitive.
194 *
195 * Pre: left != NULL && right != NULL
196 * label_is_normal(left) && label_is_normal(right)
197 */
198 int label_compare(const uint8_t *left, const uint8_t *right);
199
200
201 /*
202 * Returns the number of labels that match in LEFT and RIGHT, starting
203 * with the most significant label. Because the root label always
204 * matches, the result will always be >= 1.
205 *
206 * Pre: left != NULL && right != NULL
207 */
208 uint8_t dname_label_match_count(const dname_type *left,
209 const dname_type *right);
210
211
212 /*
213 * The total size (in bytes) allocated to store DNAME.
214 *
215 * Pre: dname != NULL
216 */
217 static inline size_t
dname_total_size(const dname_type * dname)218 dname_total_size(const dname_type *dname)
219 {
220 return (sizeof(dname_type)
221 + ((((size_t)dname->label_count) + ((size_t)dname->name_size))
222 * sizeof(uint8_t)));
223 }
224
225
226 /*
227 * Is LABEL a normal LABEL (not a pointer or reserved)?
228 *
229 * Pre: label != NULL;
230 */
231 static inline int
label_is_normal(const uint8_t * label)232 label_is_normal(const uint8_t *label)
233 {
234 assert(label);
235 return (label[0] & 0xc0) == 0;
236 }
237
238
239 /*
240 * Is LABEL a pointer?
241 *
242 * Pre: label != NULL;
243 */
244 static inline int
label_is_pointer(const uint8_t * label)245 label_is_pointer(const uint8_t *label)
246 {
247 assert(label);
248 return (label[0] & 0xc0) == 0xc0;
249 }
250
251
252 /*
253 * LABEL's pointer location.
254 *
255 * Pre: label != NULL && label_is_pointer(label)
256 */
257 static inline uint16_t
label_pointer_location(const uint8_t * label)258 label_pointer_location(const uint8_t *label)
259 {
260 assert(label);
261 assert(label_is_pointer(label));
262 return ((uint16_t) (label[0] & ~0xc0) << 8) | (uint16_t) label[1];
263 }
264
265
266 /*
267 * Length of LABEL.
268 *
269 * Pre: label != NULL && label_is_normal(label)
270 */
271 static inline uint8_t
label_length(const uint8_t * label)272 label_length(const uint8_t *label)
273 {
274 assert(label);
275 assert(label_is_normal(label));
276 return label[0];
277 }
278
279
280 /*
281 * The data of LABEL.
282 *
283 * Pre: label != NULL && label_is_normal(label)
284 */
285 static inline const uint8_t *
label_data(const uint8_t * label)286 label_data(const uint8_t *label)
287 {
288 assert(label);
289 assert(label_is_normal(label));
290 return label + 1;
291 }
292
293
294 /*
295 * Is LABEL the root label?
296 *
297 * Pre: label != NULL
298 */
299 static inline int
label_is_root(const uint8_t * label)300 label_is_root(const uint8_t *label)
301 {
302 assert(label);
303 return label[0] == 0;
304 }
305
306
307 /*
308 * Is LABEL the wildcard label?
309 *
310 * Pre: label != NULL
311 */
312 static inline int
label_is_wildcard(const uint8_t * label)313 label_is_wildcard(const uint8_t *label)
314 {
315 assert(label);
316 return label[0] == 1 && label[1] == '*';
317 }
318
319
320 /*
321 * The next label of LABEL.
322 *
323 * Pre: label != NULL
324 * label_is_normal(label)
325 * !label_is_root(label)
326 */
327 static inline const uint8_t *
label_next(const uint8_t * label)328 label_next(const uint8_t *label)
329 {
330 assert(label);
331 assert(label_is_normal(label));
332 assert(!label_is_root(label));
333 return label + label_length(label) + 1;
334 }
335
336
337 /*
338 * Convert DNAME to its string representation. The result points to a
339 * static buffer that is overwritten the next time this function is
340 * invoked.
341 *
342 * If ORIGIN is provided and DNAME is a subdomain of ORIGIN the dname
343 * will be represented relative to ORIGIN.
344 *
345 * Pre: dname != NULL
346 */
347 const char *dname_to_string(const dname_type *dname,
348 const dname_type *origin);
349
350 /*
351 * Convert DNAME to its string representation. The result if written
352 * to the provided buffer buf, which must be at least 5 times
353 * MAXDOMAINNAMELEN.
354 *
355 * If ORIGIN is provided and DNAME is a subdomain of ORIGIN the dname
356 * will be represented relative to ORIGIN.
357 *
358 * Pre: dname != NULL
359 */
360 const char *dname_to_string_buf(const dname_type *dname,
361 const dname_type *origin,
362 char buf[MAXDOMAINLEN * 5]);
363
364 /*
365 * Create a dname containing the single label specified by STR
366 * followed by the root label.
367 */
368 const dname_type *dname_make_from_label(region_type *region,
369 const uint8_t *label,
370 const size_t length);
371
372
373 /*
374 * Concatenate two dnames.
375 */
376 const dname_type *dname_concatenate(region_type *region,
377 const dname_type *left,
378 const dname_type *right);
379
380
381 /*
382 * Perform DNAME substitution on a name, replace src with dest.
383 * Name must be a subdomain of src. The returned name is a subdomain of dest.
384 * Returns NULL if the result domain name is too long.
385 */
386 const dname_type *dname_replace(region_type* region,
387 const dname_type* name,
388 const dname_type* src,
389 const dname_type* dest);
390
391 /** Convert uncompressed wireformat dname to a string */
392 char* wiredname2str(const uint8_t* dname);
393 /** convert uncompressed label to string */
394 char* wirelabel2str(const uint8_t* label);
395 /** check if two uncompressed dnames of the same total length are equal */
396 int dname_equal_nocase(uint8_t* a, uint8_t* b, uint16_t len);
397
398 #endif /* DNAME_H */
399