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 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. 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 struct sldns_buffer; 49 50 /** max number of compression ptrs to follow */ 51 #define MAX_COMPRESS_PTRS 256 52 53 /** 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. 58 */ 59 size_t query_dname_len(struct sldns_buffer* query); 60 61 /** 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. 66 */ 67 size_t dname_valid(uint8_t* dname, size_t len); 68 69 /** lowercase query dname */ 70 void query_dname_tolower(uint8_t* dname); 71 72 /** 73 * lowercase pkt dname (follows compression pointers) 74 * @param pkt: the packet, used to follow compression pointers. Position 75 * is unchanged. 76 * @param dname: start of dname in packet. 77 */ 78 void pkt_dname_tolower(struct sldns_buffer* pkt, uint8_t* dname); 79 80 /** 81 * Compare query dnames (uncompressed storage). The Dnames passed do not 82 * have to be lowercased, comparison routine does this. 83 * 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. 89 * 90 * This routine does not compute the canonical order needed for NSEC 91 * processing. 92 * 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. 98 */ 99 int query_dname_compare(uint8_t* d1, uint8_t* d2); 100 101 /** 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. 109 */ 110 size_t pkt_dname_len(struct sldns_buffer* pkt); 111 112 /** 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. 120 */ 121 int dname_pkt_compare(struct sldns_buffer* pkt, uint8_t* d1, uint8_t* d2); 122 123 /** 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. 129 */ 130 hashvalue_type dname_query_hash(uint8_t* dname, hashvalue_type h); 131 132 /** 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. 141 */ 142 hashvalue_type dname_pkt_hash(struct sldns_buffer* pkt, uint8_t* dname, 143 hashvalue_type h); 144 145 /** 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. 150 */ 151 void dname_pkt_copy(struct sldns_buffer* pkt, uint8_t* to, uint8_t* dname); 152 153 /** 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. 158 */ 159 int dname_buffer_write(struct sldns_buffer* pkt, uint8_t* dname); 160 161 /** 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. 165 */ 166 int dname_count_labels(uint8_t* dname); 167 168 /** 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. 173 */ 174 int dname_count_size_labels(uint8_t* dname, size_t* size); 175 176 /** 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. 185 */ 186 int dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs); 187 188 /** 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 196 */ 197 int dname_lab_startswith(uint8_t* label, char* prefix, char** endptr); 198 199 /** 200 * Check if dname contains label 201 * @param dname: dname 202 * @param dnamelen: length of dname 203 * @param label: label to be checked for presence in dname 204 * @return: 1 if dname has this label, 0 otherwise 205 */ 206 int dname_has_label(uint8_t* dname, size_t dnamelen, uint8_t* label); 207 208 /** 209 * See if domain name d1 is a strict subdomain of d2. 210 * That is a subdomain, but not equal. 211 * @param d1: domain name, uncompressed wireformat 212 * @param labs1: number of labels in d1, including root label. 213 * @param d2: domain name, uncompressed wireformat 214 * @param labs2: number of labels in d2, including root label. 215 * @return true if d1 is a subdomain of d2, but not equal to d2. 216 */ 217 int dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2); 218 219 /** 220 * Like dname_strict_subdomain but counts labels 221 * @param d1: domain name, uncompressed wireformat 222 * @param d2: domain name, uncompressed wireformat 223 * @return true if d1 is a subdomain of d2, but not equal to d2. 224 */ 225 int dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2); 226 227 /** 228 * Counts labels. Tests is d1 is a subdomain of d2. 229 * @param d1: domain name, uncompressed wireformat 230 * @param d2: domain name, uncompressed wireformat 231 * @return true if d1 is a subdomain of d2. 232 */ 233 int dname_subdomain_c(uint8_t* d1, uint8_t* d2); 234 235 /** 236 * Debug helper. Print wireformat dname to output. 237 * @param out: like stdout or a file. 238 * @param pkt: if not NULL, the packet for resolving compression ptrs. 239 * @param dname: pointer to (start of) dname. 240 */ 241 void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname); 242 243 /** 244 * Debug helper. Print dname to given string buffer (string buffer must 245 * be at least 255 chars + 1 for the 0, in printable form. 246 * This may lose information (? for nonprintable characters, or & if 247 * the name is too long, # for a bad label length). 248 * @param dname: uncompressed wireformat. 249 * @param str: buffer of 255+1 length. 250 */ 251 void dname_str(uint8_t* dname, char* str); 252 253 /** 254 * Returns true if the uncompressed wireformat dname is the root "." 255 * @param dname: the dname to check 256 * @return true if ".", false if not. 257 */ 258 int dname_is_root(uint8_t* dname); 259 260 /** 261 * Snip off first label from a dname, returning the parent zone. 262 * @param dname: from what to strip off. uncompressed wireformat. 263 * @param len: length, adjusted to become less. 264 * return stripped off, or "." if input was ".". 265 */ 266 void dname_remove_label(uint8_t** dname, size_t* len); 267 268 /** 269 * Snip off first N labels from a dname, returning the parent zone. 270 * @param dname: from what to strip off. uncompressed wireformat. 271 * @param len: length, adjusted to become less. 272 * @param n: number of labels to strip off (from the left). 273 * if 0, nothing happens. 274 * return stripped off, or "." if input was ".". 275 */ 276 void dname_remove_labels(uint8_t** dname, size_t* len, int n); 277 278 /** 279 * Count labels for the RRSIG signature label field. 280 * Like a normal labelcount, but "*" wildcard and "." root are not counted. 281 * @param dname: valid uncompressed wireformat. 282 * @return number of labels like in RRSIG; '*' and '.' are not counted. 283 */ 284 int dname_signame_label_count(uint8_t* dname); 285 286 /** 287 * Return true if the label is a wildcard, *.example.com. 288 * @param dname: valid uncompressed wireformat. 289 * @return true if wildcard, or false. 290 */ 291 int dname_is_wild(uint8_t* dname); 292 293 /** 294 * Compare dnames, Canonical in rfc4034 sense, but by label. 295 * Such that zone contents follows zone apex. 296 * 297 * @param d1: first dname. pointer to uncompressed wireformat. 298 * @param labs1: number of labels in first dname. 299 * @param d2: second dname. pointer to uncompressed wireformat. 300 * @param labs2: number of labels in second dname. 301 * @param mlabs: number of labels that matched exactly (the shared topdomain). 302 * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2. 303 */ 304 int dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, 305 int* mlabs); 306 307 /** 308 * Canonical dname compare. Takes care of counting labels. 309 * Per rfc 4034 canonical order. 310 * 311 * @param d1: first dname. pointer to uncompressed wireformat. 312 * @param d2: second dname. pointer to uncompressed wireformat. 313 * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2. 314 */ 315 int dname_canonical_compare(uint8_t* d1, uint8_t* d2); 316 317 /** 318 * Get the shared topdomain between two names. Root "." or longer. 319 * @param d1: first dname. pointer to uncompressed wireformat. 320 * @param d2: second dname. pointer to uncompressed wireformat. 321 * @return pointer to shared topdomain. Ptr to a part of d1. 322 */ 323 uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2); 324 325 #endif /* UTIL_DATA_DNAME_H */ 326