2 * util/data/dname.h - domain name routines
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
6 * This software is open source.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
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.
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.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 * This file contains functions to deal with domain names (dnames).
41 * Some of the functions deal with domain names as a wireformat buffer,
45 #ifndef UTIL_DATA_DNAME_H
46 #define UTIL_DATA_DNAME_H
47 #include "util/storage/lruhash.h"
50 /** max number of compression ptrs to follow */
51 #define MAX_COMPRESS_PTRS 256
54 * Determine length of dname in buffer, no compression ptrs allowed,
55 * @param query: the ldns buffer, current position at start of dname.
56 * at end, position is at end of the dname.
57 * @return: 0 on parse failure, or length including ending 0 of dname.
59 size_t query_dname_len(struct sldns_buffer* query);
62 * Determine if dname in memory is correct. no compression ptrs allowed.
63 * @param dname: where dname starts in memory.
64 * @param len: dname is not allowed to exceed this length (i.e. of allocation).
65 * @return length of dname if dname is ok, 0 on a parse error.
67 size_t dname_valid(uint8_t* dname, size_t len);
69 /** lowercase query dname */
70 void query_dname_tolower(uint8_t* dname);
73 * lowercase pkt dname (follows compression pointers)
74 * @param pkt: the packet, used to follow compression pointers. Position
76 * @param dname: start of dname in packet.
78 void pkt_dname_tolower(struct sldns_buffer* pkt, uint8_t* dname);
81 * Compare query dnames (uncompressed storage). The Dnames passed do not
82 * have to be lowercased, comparison routine does this.
84 * This routine is special, in that the comparison that it does corresponds
85 * with the canonical comparison needed when comparing dnames inside rdata
86 * for RR types that need canonicalization. That means that the first byte
87 * that is smaller (possibly after lowercasing) makes an RR smaller, or the
88 * shortest name makes an RR smaller.
90 * This routine does not compute the canonical order needed for NSEC
93 * Dnames have to be valid format.
94 * @param d1: dname to compare
95 * @param d2: dname to compare
96 * @return: -1, 0, or +1 depending on comparison results.
97 * Sort order is first difference found. not the canonical ordering.
99 int query_dname_compare(uint8_t* d1, uint8_t* d2);
102 * Determine correct, compressed, dname present in packet.
103 * Checks for parse errors.
104 * @param pkt: packet to read from (from current start position).
105 * @return: 0 on parse error.
106 * At exit the position is right after the (compressed) dname.
107 * Compression pointers are followed and checked for loops.
108 * The uncompressed wireformat length is returned.
110 size_t pkt_dname_len(struct sldns_buffer* pkt);
113 * Compare dnames in packet (compressed). Dnames must be valid.
114 * routine performs lowercasing, so the packet casing is preserved.
115 * @param pkt: packet, used to resolve compression pointers.
116 * @param d1: dname to compare
117 * @param d2: dname to compare
118 * @return: -1, 0, or +1 depending on comparison results.
119 * Sort order is first difference found. not the canonical ordering.
121 int dname_pkt_compare(struct sldns_buffer* pkt, uint8_t* d1, uint8_t* d2);
124 * Hash dname, label by label, lowercasing, into hashvalue.
125 * Dname in query format (not compressed).
126 * @param dname: dname to hash.
127 * @param h: initial hash value.
128 * @return: result hash value.
130 hashvalue_type dname_query_hash(uint8_t* dname, hashvalue_type h);
133 * Hash dname, label by label, lowercasing, into hashvalue.
134 * Dname in pkt format (compressed).
135 * @param pkt: packet, for resolving compression pointers.
136 * @param dname: dname to hash, pointer to the pkt buffer.
137 * Must be valid format. No loops, etc.
138 * @param h: initial hash value.
139 * @return: result hash value.
140 * Result is the same as dname_query_hash, even if compression is used.
142 hashvalue_type dname_pkt_hash(struct sldns_buffer* pkt, uint8_t* dname,
146 * Copy over a valid dname and decompress it.
147 * @param pkt: packet to resolve compression pointers.
148 * @param to: buffer of size from pkt_len function to hold result.
149 * @param dname: pointer into packet where dname starts.
151 void dname_pkt_copy(struct sldns_buffer* pkt, uint8_t* to, uint8_t* dname);
154 * Copy over a valid dname to a packet.
155 * @param pkt: packet to copy to.
156 * @param dname: dname to copy.
157 * @return: 0 if not enough space in buffer.
159 int dname_buffer_write(struct sldns_buffer* pkt, uint8_t* dname);
162 * Count the number of labels in an uncompressed dname in memory.
163 * @param dname: pointer to uncompressed dname.
164 * @return: count of labels, including root label, "com." has 2 labels.
166 int dname_count_labels(uint8_t* dname);
169 * Count labels and dname length both, for uncompressed dname in memory.
170 * @param dname: pointer to uncompressed dname.
171 * @param size: length of dname, including root label.
172 * @return: count of labels, including root label, "com." has 2 labels.
174 int dname_count_size_labels(uint8_t* dname, size_t* size);
177 * Compare dnames, sorted not canonical, but by label.
178 * Such that zone contents follows zone apex.
179 * @param d1: first dname. pointer to uncompressed wireformat.
180 * @param labs1: number of labels in first dname.
181 * @param d2: second dname. pointer to uncompressed wireformat.
182 * @param labs2: number of labels in second dname.
183 * @param mlabs: number of labels that matched exactly (the shared topdomain).
184 * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2.
186 int dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs);
189 * Check if labels starts with given prefix
190 * @param label: dname label
191 * @param prefix: the string to match label with, null terminated.
192 * @param endptr: pointer to location in label after prefix, only if return
193 * value is 1. NULL if nothing in the label after the prefix, i.e. prefix
194 * and label are the same.
195 * @return: 1 if label starts with prefix, else 0
197 int dname_lab_startswith(uint8_t* label, char* prefix, char** endptr);
200 * See if domain name d1 is a strict subdomain of d2.
201 * That is a subdomain, but not equal.
202 * @param d1: domain name, uncompressed wireformat
203 * @param labs1: number of labels in d1, including root label.
204 * @param d2: domain name, uncompressed wireformat
205 * @param labs2: number of labels in d2, including root label.
206 * @return true if d1 is a subdomain of d2, but not equal to d2.
208 int dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2);
211 * Like dname_strict_subdomain but counts labels
212 * @param d1: domain name, uncompressed wireformat
213 * @param d2: domain name, uncompressed wireformat
214 * @return true if d1 is a subdomain of d2, but not equal to d2.
216 int dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2);
219 * Counts labels. Tests is d1 is a subdomain of d2.
220 * @param d1: domain name, uncompressed wireformat
221 * @param d2: domain name, uncompressed wireformat
222 * @return true if d1 is a subdomain of d2.
224 int dname_subdomain_c(uint8_t* d1, uint8_t* d2);
227 * Debug helper. Print wireformat dname to output.
228 * @param out: like stdout or a file.
229 * @param pkt: if not NULL, the packet for resolving compression ptrs.
230 * @param dname: pointer to (start of) dname.
232 void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname);
235 * Debug helper. Print dname to given string buffer (string buffer must
236 * be at least 255 chars + 1 for the 0, in printable form.
237 * This may lose information (? for nonprintable characters, or & if
238 * the name is too long, # for a bad label length).
239 * @param dname: uncompressed wireformat.
240 * @param str: buffer of 255+1 length.
242 void dname_str(uint8_t* dname, char* str);
245 * Returns true if the uncompressed wireformat dname is the root "."
246 * @param dname: the dname to check
247 * @return true if ".", false if not.
249 int dname_is_root(uint8_t* dname);
252 * Snip off first label from a dname, returning the parent zone.
253 * @param dname: from what to strip off. uncompressed wireformat.
254 * @param len: length, adjusted to become less.
255 * @return stripped off, or "." if input was ".".
257 void dname_remove_label(uint8_t** dname, size_t* len);
260 * Snip off first N labels from a dname, returning the parent zone.
261 * @param dname: from what to strip off. uncompressed wireformat.
262 * @param len: length, adjusted to become less.
263 * @param n: number of labels to strip off (from the left).
264 * if 0, nothing happens.
265 * @return stripped off, or "." if input was ".".
267 void dname_remove_labels(uint8_t** dname, size_t* len, int n);
270 * Count labels for the RRSIG signature label field.
271 * Like a normal labelcount, but "*" wildcard and "." root are not counted.
272 * @param dname: valid uncompressed wireformat.
273 * @return number of labels like in RRSIG; '*' and '.' are not counted.
275 int dname_signame_label_count(uint8_t* dname);
278 * Return true if the label is a wildcard, *.example.com.
279 * @param dname: valid uncompressed wireformat.
280 * @return true if wildcard, or false.
282 int dname_is_wild(uint8_t* dname);
285 * Compare dnames, Canonical in rfc4034 sense, but by label.
286 * Such that zone contents follows zone apex.
288 * @param d1: first dname. pointer to uncompressed wireformat.
289 * @param labs1: number of labels in first dname.
290 * @param d2: second dname. pointer to uncompressed wireformat.
291 * @param labs2: number of labels in second dname.
292 * @param mlabs: number of labels that matched exactly (the shared topdomain).
293 * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2.
295 int dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2,
299 * Canonical dname compare. Takes care of counting labels.
300 * Per rfc 4034 canonical order.
302 * @param d1: first dname. pointer to uncompressed wireformat.
303 * @param d2: second dname. pointer to uncompressed wireformat.
304 * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2.
306 int dname_canonical_compare(uint8_t* d1, uint8_t* d2);
309 * Get the shared topdomain between two names. Root "." or longer.
310 * @param d1: first dname. pointer to uncompressed wireformat.
311 * @param d2: second dname. pointer to uncompressed wireformat.
312 * @return pointer to shared topdomain. Ptr to a part of d1.
314 uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2);
316 #endif /* UTIL_DATA_DNAME_H */