aboutsummaryrefslogtreecommitdiff
path: root/util/data/dname.h
blob: b942848a9dc7bb15e6c279bc16d653eb65a02c72 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
/*
 * util/data/dname.h - domain name routines
 *
 * Copyright (c) 2007, NLnet Labs. All rights reserved.
 *
 * This software is open source.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * 
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * 
 * Neither the name of the NLNET LABS nor the names of its contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * \file
 *
 * This file contains functions to deal with domain names (dnames).
 *
 * Some of the functions deal with domain names as a wireformat buffer,
 * with a length.
 */

#ifndef UTIL_DATA_DNAME_H
#define UTIL_DATA_DNAME_H
#include "util/storage/lruhash.h"

/** max number of compression ptrs to follow */
#define MAX_COMPRESS_PTRS 256

/** 
 * Determine length of dname in buffer, no compression ptrs allowed, 
 * @param query: the ldns buffer, current position at start of dname.
 *	at end, position is at end of the dname.
 * @return: 0 on parse failure, or length including ending 0 of dname. 
 */
size_t query_dname_len(ldns_buffer* query);

/**
 * Determine if dname in memory is correct. no compression ptrs allowed.
 * @param dname: where dname starts in memory.
 * @param len: dname is not allowed to exceed this length (i.e. of allocation).
 * @return length of dname if dname is ok, 0 on a parse error.
 */
size_t dname_valid(uint8_t* dname, size_t len);

/** lowercase query dname */
void query_dname_tolower(uint8_t* dname);

/** 
 * lowercase pkt dname (follows compression pointers)
 * @param pkt: the packet, used to follow compression pointers. Position 
 *	is unchanged.
 * @param dname: start of dname in packet.
 */
void pkt_dname_tolower(ldns_buffer* pkt, uint8_t* dname);

/**
 * Compare query dnames (uncompressed storage). The Dnames passed do not
 * have to be lowercased, comparison routine does this.
 *
 * This routine is special, in that the comparison that it does corresponds
 * with the canonical comparison needed when comparing dnames inside rdata
 * for RR types that need canonicalization. That means that the first byte
 * that is smaller (possibly after lowercasing) makes an RR smaller, or the
 * shortest name makes an RR smaller.
 *
 * This routine does not compute the canonical order needed for NSEC 
 * processing.
 *
 * Dnames have to be valid format.
 * @param d1: dname to compare
 * @param d2: dname to compare
 * @return: -1, 0, or +1 depending on comparison results.
 * 	Sort order is first difference found. not the canonical ordering.
 */
int query_dname_compare(uint8_t* d1, uint8_t* d2);

/**
 * Determine correct, compressed, dname present in packet.
 * Checks for parse errors.
 * @param pkt: packet to read from (from current start position).
 * @return: 0 on parse error.
 *	At exit the position is right after the (compressed) dname.
 *	Compression pointers are followed and checked for loops.
 *	The uncompressed wireformat length is returned.
 */
size_t pkt_dname_len(ldns_buffer* pkt);

/**
 * Compare dnames in packet (compressed). Dnames must be valid.
 * routine performs lowercasing, so the packet casing is preserved.
 * @param pkt: packet, used to resolve compression pointers.
 * @param d1: dname to compare
 * @param d2: dname to compare
 * @return: -1, 0, or +1 depending on comparison results.
 * 	Sort order is first difference found. not the canonical ordering.
 */
int dname_pkt_compare(ldns_buffer* pkt, uint8_t* d1, uint8_t* d2);

/**
 * Hash dname, label by label, lowercasing, into hashvalue.
 * Dname in query format (not compressed).
 * @param dname: dname to hash.
 * @param h: initial hash value.
 * @return: result hash value.
 */
hashvalue_t dname_query_hash(uint8_t* dname, hashvalue_t h);

/**
 * Hash dname, label by label, lowercasing, into hashvalue.
 * Dname in pkt format (compressed).
 * @param pkt: packet, for resolving compression pointers.
 * @param dname: dname to hash, pointer to the pkt buffer.
 * 	Must be valid format. No loops, etc.
 * @param h: initial hash value.
 * @return: result hash value.
 * 	Result is the same as dname_query_hash, even if compression is used.
 */
hashvalue_t dname_pkt_hash(ldns_buffer* pkt, uint8_t* dname, hashvalue_t h);

/**
 * Copy over a valid dname and decompress it.
 * @param pkt: packet to resolve compression pointers.
 * @param to: buffer of size from pkt_len function to hold result.
 * @param dname: pointer into packet where dname starts.
 */
void dname_pkt_copy(ldns_buffer* pkt, uint8_t* to, uint8_t* dname);

/**
 * Copy over a valid dname to a packet.
 * @param pkt: packet to copy to.
 * @param dname: dname to copy.
 * @return: 0 if not enough space in buffer.
 */
int dname_buffer_write(ldns_buffer* pkt, uint8_t* dname);

/**
 * Count the number of labels in an uncompressed dname in memory.
 * @param dname: pointer to uncompressed dname.
 * @return: count of labels, including root label, "com." has 2 labels.
 */
int dname_count_labels(uint8_t* dname);

/**
 * Count labels and dname length both, for uncompressed dname in memory.
 * @param dname: pointer to uncompressed dname.
 * @param size: length of dname, including root label.
 * @return: count of labels, including root label, "com." has 2 labels.
 */
int dname_count_size_labels(uint8_t* dname, size_t* size);

/**
 * Compare dnames, sorted not canonical, but by label.
 * Such that zone contents follows zone apex.
 * @param d1: first dname. pointer to uncompressed wireformat.
 * @param labs1: number of labels in first dname.
 * @param d2: second dname. pointer to uncompressed wireformat.
 * @param labs2: number of labels in second dname.
 * @param mlabs: number of labels that matched exactly (the shared topdomain).
 * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2.
 */
int dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs);

/**
 * See if domain name d1 is a strict subdomain of d2.
 * That is a subdomain, but not equal. 
 * @param d1: domain name, uncompressed wireformat
 * @param labs1: number of labels in d1, including root label.
 * @param d2: domain name, uncompressed wireformat
 * @param labs2: number of labels in d2, including root label.
 * @return true if d1 is a subdomain of d2, but not equal to d2.
 */
int dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2);

/**
 * Like dname_strict_subdomain but counts labels 
 * @param d1: domain name, uncompressed wireformat
 * @param d2: domain name, uncompressed wireformat
 * @return true if d1 is a subdomain of d2, but not equal to d2.
 */
int dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2);

/**
 * Counts labels. Tests is d1 is a subdomain of d2.
 * @param d1: domain name, uncompressed wireformat
 * @param d2: domain name, uncompressed wireformat
 * @return true if d1 is a subdomain of d2.
 */
int dname_subdomain_c(uint8_t* d1, uint8_t* d2);

/** 
 * Debug helper. Print wireformat dname to output. 
 * @param out: like stdout or a file.
 * @param pkt: if not NULL, the packet for resolving compression ptrs.
 * @param dname: pointer to (start of) dname.
 */
void dname_print(FILE* out, ldns_buffer* pkt, uint8_t* dname);

/** 
 * Debug helper. Print dname to given string buffer (string buffer must
 * be at least 255 chars + 1 for the 0, in printable form.
 * This may lose information (? for nonprintable characters, or & if
 * the name is too long, # for a bad label length).
 * @param dname: uncompressed wireformat.
 * @param str: buffer of 255+1 length.
 */
void dname_str(uint8_t* dname, char* str);

/**
 * Returns true if the uncompressed wireformat dname is the root "."
 * @param dname: the dname to check
 * @return true if ".", false if not.
 */
int dname_is_root(uint8_t* dname);

/**
 * Snip off first label from a dname, returning the parent zone.
 * @param dname: from what to strip off. uncompressed wireformat.
 * @param len: length, adjusted to become less.
 * @return stripped off, or "." if input was ".".
 */
void dname_remove_label(uint8_t** dname, size_t* len);

/**
 * Snip off first N labels from a dname, returning the parent zone.
 * @param dname: from what to strip off. uncompressed wireformat.
 * @param len: length, adjusted to become less.
 * @param n: number of labels to strip off (from the left).
 * 	if 0, nothing happens.
 * @return stripped off, or "." if input was ".".
 */
void dname_remove_labels(uint8_t** dname, size_t* len, int n);

/**
 * Count labels for the RRSIG signature label field.
 * Like a normal labelcount, but "*" wildcard and "." root are not counted.
 * @param dname: valid uncompressed wireformat.
 * @return number of labels like in RRSIG; '*' and '.' are not counted.
 */
int dname_signame_label_count(uint8_t* dname);

/**
 * Return true if the label is a wildcard, *.example.com.
 * @param dname: valid uncompressed wireformat.
 * @return true if wildcard, or false.
 */
int dname_is_wild(uint8_t* dname);

/**
 * Compare dnames, Canonical in rfc4034 sense, but by label.
 * Such that zone contents follows zone apex.
 *
 * @param d1: first dname. pointer to uncompressed wireformat.
 * @param labs1: number of labels in first dname.
 * @param d2: second dname. pointer to uncompressed wireformat.
 * @param labs2: number of labels in second dname.
 * @param mlabs: number of labels that matched exactly (the shared topdomain).
 * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2.
 */
int dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, 
	int* mlabs);

/**
 * Canonical dname compare. Takes care of counting labels.
 * Per rfc 4034 canonical order.
 *
 * @param d1: first dname. pointer to uncompressed wireformat.
 * @param d2: second dname. pointer to uncompressed wireformat.
 * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2.
 */
int dname_canonical_compare(uint8_t* d1, uint8_t* d2);

/**
 * Get the shared topdomain between two names. Root "." or longer.
 * @param d1: first dname. pointer to uncompressed wireformat.
 * @param d2: second dname. pointer to uncompressed wireformat.
 * @return pointer to shared topdomain. Ptr to a part of d1.
 */
uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2);

#endif /* UTIL_DATA_DNAME_H */