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