Home | History | Annotate | Line # | Download | only in data
      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 if 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, 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  * Upon return, the buffer will always have a terminating \0 value.
    249  * @param dname: uncompressed wireformat.
    250  * @param str: buffer of at least 255 length.
    251  */
    252 void dname_str(uint8_t* dname, char* str);
    253 
    254 /**
    255  * Returns true if the uncompressed wireformat dname is the root "."
    256  * @param dname: the dname to check
    257  * @return true if ".", false if not.
    258  */
    259 int dname_is_root(uint8_t* dname);
    260 
    261 /**
    262  * Snip off first label from a dname, returning the parent zone.
    263  * @param dname: from what to strip off. uncompressed wireformat.
    264  * @param len: length, adjusted to become less.
    265  * return dname stripped off, or "." if input was ".".
    266  */
    267 void dname_remove_label(uint8_t** dname, size_t* len);
    268 
    269 /**
    270  * Same as dname_remove_label but fails if removal would surpass lenlimit.
    271  * If no failure,
    272  * snip off first label from a dname, returning the parent zone.
    273  * @param dname: from what to strip off. uncompressed wireformat.
    274  * @param len: length, adjusted to become less.
    275  * @param lenlimit: length limit that we can't surpass (usually the zone apex).
    276  * @return
    277  *	o 1,  and dname stripped off, or "." if input was ".", else
    278  *	o 0, if going up would surpass lenlimit.
    279  */
    280 int dname_remove_label_limit_len(uint8_t** dname, size_t* len, size_t lenlimit);
    281 
    282 /**
    283  * Snip off first N labels from a dname, returning the parent zone.
    284  * @param dname: from what to strip off. uncompressed wireformat.
    285  * @param len: length, adjusted to become less.
    286  * @param n: number of labels to strip off (from the left).
    287  * 	if 0, nothing happens.
    288  * return stripped off, or "." if input was ".".
    289  */
    290 void dname_remove_labels(uint8_t** dname, size_t* len, int n);
    291 
    292 /**
    293  * Count labels for the RRSIG signature label field.
    294  * Like a normal labelcount, but "*" wildcard and "." root are not counted.
    295  * @param dname: valid uncompressed wireformat.
    296  * @return number of labels like in RRSIG; '*' and '.' are not counted.
    297  */
    298 int dname_signame_label_count(uint8_t* dname);
    299 
    300 /**
    301  * Return true if the label is a wildcard, *.example.com.
    302  * @param dname: valid uncompressed wireformat.
    303  * @return true if wildcard, or false.
    304  */
    305 int dname_is_wild(uint8_t* dname);
    306 
    307 /**
    308  * Compare dnames, Canonical in rfc4034 sense, but by label.
    309  * Such that zone contents follows zone apex.
    310  *
    311  * @param d1: first dname. pointer to uncompressed wireformat.
    312  * @param labs1: number of labels in first dname.
    313  * @param d2: second dname. pointer to uncompressed wireformat.
    314  * @param labs2: number of labels in second dname.
    315  * @param mlabs: number of labels that matched exactly (the shared topdomain).
    316  * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2.
    317  */
    318 int dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2,
    319 	int* mlabs);
    320 
    321 /**
    322  * Canonical dname compare. Takes care of counting labels.
    323  * Per rfc 4034 canonical order.
    324  *
    325  * @param d1: first dname. pointer to uncompressed wireformat.
    326  * @param d2: second dname. pointer to uncompressed wireformat.
    327  * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2.
    328  */
    329 int dname_canonical_compare(uint8_t* d1, uint8_t* d2);
    330 
    331 /**
    332  * Get the shared topdomain between two names. Root "." or longer.
    333  * @param d1: first dname. pointer to uncompressed wireformat.
    334  * @param d2: second dname. pointer to uncompressed wireformat.
    335  * @return pointer to shared topdomain. Ptr to a part of d1.
    336  */
    337 uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2);
    338 
    339 #endif /* UTIL_DATA_DNAME_H */
    340