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