1/*
2 * util/data/dname.h - domain name routines
3 *
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
5 *
6 * This software is open source.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * Neither the name of the NLNET LABS nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36/**
37 * \file
38 *
39 * This file contains functions to deal with domain names (dnames).
40 *
41 * Some of the functions deal with domain names as a wireformat buffer,
42 * with a length.
43 */
44
45#ifndef UTIL_DATA_DNAME_H
46#define UTIL_DATA_DNAME_H
47#include "util/storage/lruhash.h"
48
49/** max number of compression ptrs to follow */
50#define MAX_COMPRESS_PTRS 256
51
52/**
53 * Determine length of dname in buffer, no compression ptrs allowed,
54 * @param query: the ldns buffer, current position at start of dname.
55 *	at end, position is at end of the dname.
56 * @return: 0 on parse failure, or length including ending 0 of dname.
57 */
58size_t query_dname_len(ldns_buffer* query);
59
60/**
61 * Determine if dname in memory is correct. no compression ptrs allowed.
62 * @param dname: where dname starts in memory.
63 * @param len: dname is not allowed to exceed this length (i.e. of allocation).
64 * @return length of dname if dname is ok, 0 on a parse error.
65 */
66size_t dname_valid(uint8_t* dname, size_t len);
67
68/** lowercase query dname */
69void query_dname_tolower(uint8_t* dname);
70
71/**
72 * lowercase pkt dname (follows compression pointers)
73 * @param pkt: the packet, used to follow compression pointers. Position
74 *	is unchanged.
75 * @param dname: start of dname in packet.
76 */
77void pkt_dname_tolower(ldns_buffer* pkt, uint8_t* dname);
78
79/**
80 * Compare query dnames (uncompressed storage). The Dnames passed do not
81 * have to be lowercased, comparison routine does this.
82 *
83 * This routine is special, in that the comparison that it does corresponds
84 * with the canonical comparison needed when comparing dnames inside rdata
85 * for RR types that need canonicalization. That means that the first byte
86 * that is smaller (possibly after lowercasing) makes an RR smaller, or the
87 * shortest name makes an RR smaller.
88 *
89 * This routine does not compute the canonical order needed for NSEC
90 * processing.
91 *
92 * Dnames have to be valid format.
93 * @param d1: dname to compare
94 * @param d2: dname to compare
95 * @return: -1, 0, or +1 depending on comparison results.
96 * 	Sort order is first difference found. not the canonical ordering.
97 */
98int query_dname_compare(uint8_t* d1, uint8_t* d2);
99
100/**
101 * Determine correct, compressed, dname present in packet.
102 * Checks for parse errors.
103 * @param pkt: packet to read from (from current start position).
104 * @return: 0 on parse error.
105 *	At exit the position is right after the (compressed) dname.
106 *	Compression pointers are followed and checked for loops.
107 *	The uncompressed wireformat length is returned.
108 */
109size_t pkt_dname_len(ldns_buffer* pkt);
110
111/**
112 * Compare dnames in packet (compressed). Dnames must be valid.
113 * routine performs lowercasing, so the packet casing is preserved.
114 * @param pkt: packet, used to resolve compression pointers.
115 * @param d1: dname to compare
116 * @param d2: dname to compare
117 * @return: -1, 0, or +1 depending on comparison results.
118 * 	Sort order is first difference found. not the canonical ordering.
119 */
120int dname_pkt_compare(ldns_buffer* pkt, uint8_t* d1, uint8_t* d2);
121
122/**
123 * Hash dname, label by label, lowercasing, into hashvalue.
124 * Dname in query format (not compressed).
125 * @param dname: dname to hash.
126 * @param h: initial hash value.
127 * @return: result hash value.
128 */
129hashvalue_t dname_query_hash(uint8_t* dname, hashvalue_t h);
130
131/**
132 * Hash dname, label by label, lowercasing, into hashvalue.
133 * Dname in pkt format (compressed).
134 * @param pkt: packet, for resolving compression pointers.
135 * @param dname: dname to hash, pointer to the pkt buffer.
136 * 	Must be valid format. No loops, etc.
137 * @param h: initial hash value.
138 * @return: result hash value.
139 * 	Result is the same as dname_query_hash, even if compression is used.
140 */
141hashvalue_t dname_pkt_hash(ldns_buffer* pkt, uint8_t* dname, hashvalue_t h);
142
143/**
144 * Copy over a valid dname and decompress it.
145 * @param pkt: packet to resolve compression pointers.
146 * @param to: buffer of size from pkt_len function to hold result.
147 * @param dname: pointer into packet where dname starts.
148 */
149void dname_pkt_copy(ldns_buffer* pkt, uint8_t* to, uint8_t* dname);
150
151/**
152 * Copy over a valid dname to a packet.
153 * @param pkt: packet to copy to.
154 * @param dname: dname to copy.
155 * @return: 0 if not enough space in buffer.
156 */
157int dname_buffer_write(ldns_buffer* pkt, uint8_t* dname);
158
159/**
160 * Count the number of labels in an uncompressed dname in memory.
161 * @param dname: pointer to uncompressed dname.
162 * @return: count of labels, including root label, "com." has 2 labels.
163 */
164int dname_count_labels(uint8_t* dname);
165
166/**
167 * Count labels and dname length both, for uncompressed dname in memory.
168 * @param dname: pointer to uncompressed dname.
169 * @param size: length of dname, including root label.
170 * @return: count of labels, including root label, "com." has 2 labels.
171 */
172int dname_count_size_labels(uint8_t* dname, size_t* size);
173
174/**
175 * Compare dnames, sorted not canonical, but by label.
176 * Such that zone contents follows zone apex.
177 * @param d1: first dname. pointer to uncompressed wireformat.
178 * @param labs1: number of labels in first dname.
179 * @param d2: second dname. pointer to uncompressed wireformat.
180 * @param labs2: number of labels in second dname.
181 * @param mlabs: number of labels that matched exactly (the shared topdomain).
182 * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2.
183 */
184int dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs);
185
186/**
187 * See if domain name d1 is a strict subdomain of d2.
188 * That is a subdomain, but not equal.
189 * @param d1: domain name, uncompressed wireformat
190 * @param labs1: number of labels in d1, including root label.
191 * @param d2: domain name, uncompressed wireformat
192 * @param labs2: number of labels in d2, including root label.
193 * @return true if d1 is a subdomain of d2, but not equal to d2.
194 */
195int dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2);
196
197/**
198 * Like dname_strict_subdomain but counts labels
199 * @param d1: domain name, uncompressed wireformat
200 * @param d2: domain name, uncompressed wireformat
201 * @return true if d1 is a subdomain of d2, but not equal to d2.
202 */
203int dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2);
204
205/**
206 * Counts labels. Tests is d1 is a subdomain of d2.
207 * @param d1: domain name, uncompressed wireformat
208 * @param d2: domain name, uncompressed wireformat
209 * @return true if d1 is a subdomain of d2.
210 */
211int dname_subdomain_c(uint8_t* d1, uint8_t* d2);
212
213/**
214 * Debug helper. Print wireformat dname to output.
215 * @param out: like stdout or a file.
216 * @param pkt: if not NULL, the packet for resolving compression ptrs.
217 * @param dname: pointer to (start of) dname.
218 */
219void dname_print(FILE* out, ldns_buffer* pkt, uint8_t* dname);
220
221/**
222 * Debug helper. Print dname to given string buffer (string buffer must
223 * be at least 255 chars + 1 for the 0, in printable form.
224 * This may lose information (? for nonprintable characters, or & if
225 * the name is too long, # for a bad label length).
226 * @param dname: uncompressed wireformat.
227 * @param str: buffer of 255+1 length.
228 */
229void dname_str(uint8_t* dname, char* str);
230
231/**
232 * Returns true if the uncompressed wireformat dname is the root "."
233 * @param dname: the dname to check
234 * @return true if ".", false if not.
235 */
236int dname_is_root(uint8_t* dname);
237
238/**
239 * Snip off first label from a dname, returning the parent zone.
240 * @param dname: from what to strip off. uncompressed wireformat.
241 * @param len: length, adjusted to become less.
242 * @return stripped off, or "." if input was ".".
243 */
244void dname_remove_label(uint8_t** dname, size_t* len);
245
246/**
247 * Snip off first N labels from a dname, returning the parent zone.
248 * @param dname: from what to strip off. uncompressed wireformat.
249 * @param len: length, adjusted to become less.
250 * @param n: number of labels to strip off (from the left).
251 * 	if 0, nothing happens.
252 * @return stripped off, or "." if input was ".".
253 */
254void dname_remove_labels(uint8_t** dname, size_t* len, int n);
255
256/**
257 * Count labels for the RRSIG signature label field.
258 * Like a normal labelcount, but "*" wildcard and "." root are not counted.
259 * @param dname: valid uncompressed wireformat.
260 * @return number of labels like in RRSIG; '*' and '.' are not counted.
261 */
262int dname_signame_label_count(uint8_t* dname);
263
264/**
265 * Return true if the label is a wildcard, *.example.com.
266 * @param dname: valid uncompressed wireformat.
267 * @return true if wildcard, or false.
268 */
269int dname_is_wild(uint8_t* dname);
270
271/**
272 * Compare dnames, Canonical in rfc4034 sense, but by label.
273 * Such that zone contents follows zone apex.
274 *
275 * @param d1: first dname. pointer to uncompressed wireformat.
276 * @param labs1: number of labels in first dname.
277 * @param d2: second dname. pointer to uncompressed wireformat.
278 * @param labs2: number of labels in second dname.
279 * @param mlabs: number of labels that matched exactly (the shared topdomain).
280 * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2.
281 */
282int dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2,
283	int* mlabs);
284
285/**
286 * Canonical dname compare. Takes care of counting labels.
287 * Per rfc 4034 canonical order.
288 *
289 * @param d1: first dname. pointer to uncompressed wireformat.
290 * @param d2: second dname. pointer to uncompressed wireformat.
291 * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2.
292 */
293int dname_canonical_compare(uint8_t* d1, uint8_t* d2);
294
295/**
296 * Get the shared topdomain between two names. Root "." or longer.
297 * @param d1: first dname. pointer to uncompressed wireformat.
298 * @param d2: second dname. pointer to uncompressed wireformat.
299 * @return pointer to shared topdomain. Ptr to a part of d1.
300 */
301uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2);
302
303#endif /* UTIL_DATA_DNAME_H */
304