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
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 *
dname_label_offsets(const dname_type * dname)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 *
dname_name(const dname_type * dname)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 *
dname_label(const dname_type * dname,uint8_t label)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 lexicographical
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 lexicographical
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
dname_total_size(const dname_type * dname)217 dname_total_size(const dname_type *dname)
218 {
219 return (sizeof(dname_type)
220 + ((((size_t)dname->label_count) + ((size_t)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
label_is_normal(const uint8_t * label)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
label_is_pointer(const uint8_t * label)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
label_pointer_location(const uint8_t * label)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
label_length(const uint8_t * label)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 *
label_data(const uint8_t * label)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
label_is_root(const uint8_t * label)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
label_is_wildcard(const uint8_t * label)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 *
label_next(const uint8_t * label)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 /** Convert uncompressed wireformat dname to a string */
378 char* wiredname2str(const uint8_t* dname);
379 /** convert uncompressed label to string */
380 char* wirelabel2str(const uint8_t* label);
381 /** check if two uncompressed dnames of the same total length are equal */
382 int dname_equal_nocase(uint8_t* a, uint8_t* b, uint16_t len);
383
384 #endif /* _DNAME_H_ */
385