dname.h revision 269257
1238106Sdes/* 2238106Sdes * util/data/dname.h - domain name routines 3238106Sdes * 4238106Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved. 5238106Sdes * 6238106Sdes * This software is open source. 7238106Sdes * 8238106Sdes * Redistribution and use in source and binary forms, with or without 9238106Sdes * modification, are permitted provided that the following conditions 10238106Sdes * are met: 11238106Sdes * 12238106Sdes * Redistributions of source code must retain the above copyright notice, 13238106Sdes * this list of conditions and the following disclaimer. 14238106Sdes * 15238106Sdes * Redistributions in binary form must reproduce the above copyright notice, 16238106Sdes * this list of conditions and the following disclaimer in the documentation 17238106Sdes * and/or other materials provided with the distribution. 18238106Sdes * 19238106Sdes * Neither the name of the NLNET LABS nor the names of its contributors may 20238106Sdes * be used to endorse or promote products derived from this software without 21238106Sdes * specific prior written permission. 22238106Sdes * 23238106Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24269257Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25269257Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26269257Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27269257Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28269257Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29269257Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30269257Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31269257Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32269257Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33269257Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34238106Sdes */ 35238106Sdes 36238106Sdes/** 37238106Sdes * \file 38238106Sdes * 39238106Sdes * This file contains functions to deal with domain names (dnames). 40238106Sdes * 41238106Sdes * Some of the functions deal with domain names as a wireformat buffer, 42238106Sdes * with a length. 43238106Sdes */ 44238106Sdes 45238106Sdes#ifndef UTIL_DATA_DNAME_H 46238106Sdes#define UTIL_DATA_DNAME_H 47238106Sdes#include "util/storage/lruhash.h" 48269257Sdesstruct sldns_buffer; 49238106Sdes 50238106Sdes/** max number of compression ptrs to follow */ 51238106Sdes#define MAX_COMPRESS_PTRS 256 52238106Sdes 53238106Sdes/** 54238106Sdes * Determine length of dname in buffer, no compression ptrs allowed, 55238106Sdes * @param query: the ldns buffer, current position at start of dname. 56238106Sdes * at end, position is at end of the dname. 57238106Sdes * @return: 0 on parse failure, or length including ending 0 of dname. 58238106Sdes */ 59269257Sdessize_t query_dname_len(struct sldns_buffer* query); 60238106Sdes 61238106Sdes/** 62238106Sdes * Determine if dname in memory is correct. no compression ptrs allowed. 63238106Sdes * @param dname: where dname starts in memory. 64238106Sdes * @param len: dname is not allowed to exceed this length (i.e. of allocation). 65238106Sdes * @return length of dname if dname is ok, 0 on a parse error. 66238106Sdes */ 67238106Sdessize_t dname_valid(uint8_t* dname, size_t len); 68238106Sdes 69238106Sdes/** lowercase query dname */ 70238106Sdesvoid query_dname_tolower(uint8_t* dname); 71238106Sdes 72238106Sdes/** 73238106Sdes * lowercase pkt dname (follows compression pointers) 74238106Sdes * @param pkt: the packet, used to follow compression pointers. Position 75238106Sdes * is unchanged. 76238106Sdes * @param dname: start of dname in packet. 77238106Sdes */ 78269257Sdesvoid pkt_dname_tolower(struct sldns_buffer* pkt, uint8_t* dname); 79238106Sdes 80238106Sdes/** 81238106Sdes * Compare query dnames (uncompressed storage). The Dnames passed do not 82238106Sdes * have to be lowercased, comparison routine does this. 83238106Sdes * 84238106Sdes * This routine is special, in that the comparison that it does corresponds 85238106Sdes * with the canonical comparison needed when comparing dnames inside rdata 86238106Sdes * for RR types that need canonicalization. That means that the first byte 87238106Sdes * that is smaller (possibly after lowercasing) makes an RR smaller, or the 88238106Sdes * shortest name makes an RR smaller. 89238106Sdes * 90238106Sdes * This routine does not compute the canonical order needed for NSEC 91238106Sdes * processing. 92238106Sdes * 93238106Sdes * Dnames have to be valid format. 94238106Sdes * @param d1: dname to compare 95238106Sdes * @param d2: dname to compare 96238106Sdes * @return: -1, 0, or +1 depending on comparison results. 97238106Sdes * Sort order is first difference found. not the canonical ordering. 98238106Sdes */ 99238106Sdesint query_dname_compare(uint8_t* d1, uint8_t* d2); 100238106Sdes 101238106Sdes/** 102238106Sdes * Determine correct, compressed, dname present in packet. 103238106Sdes * Checks for parse errors. 104238106Sdes * @param pkt: packet to read from (from current start position). 105238106Sdes * @return: 0 on parse error. 106238106Sdes * At exit the position is right after the (compressed) dname. 107238106Sdes * Compression pointers are followed and checked for loops. 108238106Sdes * The uncompressed wireformat length is returned. 109238106Sdes */ 110269257Sdessize_t pkt_dname_len(struct sldns_buffer* pkt); 111238106Sdes 112238106Sdes/** 113238106Sdes * Compare dnames in packet (compressed). Dnames must be valid. 114238106Sdes * routine performs lowercasing, so the packet casing is preserved. 115238106Sdes * @param pkt: packet, used to resolve compression pointers. 116238106Sdes * @param d1: dname to compare 117238106Sdes * @param d2: dname to compare 118238106Sdes * @return: -1, 0, or +1 depending on comparison results. 119238106Sdes * Sort order is first difference found. not the canonical ordering. 120238106Sdes */ 121269257Sdesint dname_pkt_compare(struct sldns_buffer* pkt, uint8_t* d1, uint8_t* d2); 122238106Sdes 123238106Sdes/** 124238106Sdes * Hash dname, label by label, lowercasing, into hashvalue. 125238106Sdes * Dname in query format (not compressed). 126238106Sdes * @param dname: dname to hash. 127238106Sdes * @param h: initial hash value. 128238106Sdes * @return: result hash value. 129238106Sdes */ 130238106Sdeshashvalue_t dname_query_hash(uint8_t* dname, hashvalue_t h); 131238106Sdes 132238106Sdes/** 133238106Sdes * Hash dname, label by label, lowercasing, into hashvalue. 134238106Sdes * Dname in pkt format (compressed). 135238106Sdes * @param pkt: packet, for resolving compression pointers. 136238106Sdes * @param dname: dname to hash, pointer to the pkt buffer. 137238106Sdes * Must be valid format. No loops, etc. 138238106Sdes * @param h: initial hash value. 139238106Sdes * @return: result hash value. 140238106Sdes * Result is the same as dname_query_hash, even if compression is used. 141238106Sdes */ 142269257Sdeshashvalue_t dname_pkt_hash(struct sldns_buffer* pkt, uint8_t* dname, hashvalue_t h); 143238106Sdes 144238106Sdes/** 145238106Sdes * Copy over a valid dname and decompress it. 146238106Sdes * @param pkt: packet to resolve compression pointers. 147238106Sdes * @param to: buffer of size from pkt_len function to hold result. 148238106Sdes * @param dname: pointer into packet where dname starts. 149238106Sdes */ 150269257Sdesvoid dname_pkt_copy(struct sldns_buffer* pkt, uint8_t* to, uint8_t* dname); 151238106Sdes 152238106Sdes/** 153238106Sdes * Copy over a valid dname to a packet. 154238106Sdes * @param pkt: packet to copy to. 155238106Sdes * @param dname: dname to copy. 156238106Sdes * @return: 0 if not enough space in buffer. 157238106Sdes */ 158269257Sdesint dname_buffer_write(struct sldns_buffer* pkt, uint8_t* dname); 159238106Sdes 160238106Sdes/** 161238106Sdes * Count the number of labels in an uncompressed dname in memory. 162238106Sdes * @param dname: pointer to uncompressed dname. 163238106Sdes * @return: count of labels, including root label, "com." has 2 labels. 164238106Sdes */ 165238106Sdesint dname_count_labels(uint8_t* dname); 166238106Sdes 167238106Sdes/** 168238106Sdes * Count labels and dname length both, for uncompressed dname in memory. 169238106Sdes * @param dname: pointer to uncompressed dname. 170238106Sdes * @param size: length of dname, including root label. 171238106Sdes * @return: count of labels, including root label, "com." has 2 labels. 172238106Sdes */ 173238106Sdesint dname_count_size_labels(uint8_t* dname, size_t* size); 174238106Sdes 175238106Sdes/** 176238106Sdes * Compare dnames, sorted not canonical, but by label. 177238106Sdes * Such that zone contents follows zone apex. 178238106Sdes * @param d1: first dname. pointer to uncompressed wireformat. 179238106Sdes * @param labs1: number of labels in first dname. 180238106Sdes * @param d2: second dname. pointer to uncompressed wireformat. 181238106Sdes * @param labs2: number of labels in second dname. 182238106Sdes * @param mlabs: number of labels that matched exactly (the shared topdomain). 183238106Sdes * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2. 184238106Sdes */ 185238106Sdesint dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs); 186238106Sdes 187238106Sdes/** 188238106Sdes * See if domain name d1 is a strict subdomain of d2. 189238106Sdes * That is a subdomain, but not equal. 190238106Sdes * @param d1: domain name, uncompressed wireformat 191238106Sdes * @param labs1: number of labels in d1, including root label. 192238106Sdes * @param d2: domain name, uncompressed wireformat 193238106Sdes * @param labs2: number of labels in d2, including root label. 194238106Sdes * @return true if d1 is a subdomain of d2, but not equal to d2. 195238106Sdes */ 196238106Sdesint dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2); 197238106Sdes 198238106Sdes/** 199238106Sdes * Like dname_strict_subdomain but counts labels 200238106Sdes * @param d1: domain name, uncompressed wireformat 201238106Sdes * @param d2: domain name, uncompressed wireformat 202238106Sdes * @return true if d1 is a subdomain of d2, but not equal to d2. 203238106Sdes */ 204238106Sdesint dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2); 205238106Sdes 206238106Sdes/** 207238106Sdes * Counts labels. Tests is d1 is a subdomain of d2. 208238106Sdes * @param d1: domain name, uncompressed wireformat 209238106Sdes * @param d2: domain name, uncompressed wireformat 210238106Sdes * @return true if d1 is a subdomain of d2. 211238106Sdes */ 212238106Sdesint dname_subdomain_c(uint8_t* d1, uint8_t* d2); 213238106Sdes 214238106Sdes/** 215238106Sdes * Debug helper. Print wireformat dname to output. 216238106Sdes * @param out: like stdout or a file. 217238106Sdes * @param pkt: if not NULL, the packet for resolving compression ptrs. 218238106Sdes * @param dname: pointer to (start of) dname. 219238106Sdes */ 220269257Sdesvoid dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname); 221238106Sdes 222238106Sdes/** 223238106Sdes * Debug helper. Print dname to given string buffer (string buffer must 224238106Sdes * be at least 255 chars + 1 for the 0, in printable form. 225238106Sdes * This may lose information (? for nonprintable characters, or & if 226238106Sdes * the name is too long, # for a bad label length). 227238106Sdes * @param dname: uncompressed wireformat. 228238106Sdes * @param str: buffer of 255+1 length. 229238106Sdes */ 230238106Sdesvoid dname_str(uint8_t* dname, char* str); 231238106Sdes 232238106Sdes/** 233238106Sdes * Returns true if the uncompressed wireformat dname is the root "." 234238106Sdes * @param dname: the dname to check 235238106Sdes * @return true if ".", false if not. 236238106Sdes */ 237238106Sdesint dname_is_root(uint8_t* dname); 238238106Sdes 239238106Sdes/** 240238106Sdes * Snip off first label from a dname, returning the parent zone. 241238106Sdes * @param dname: from what to strip off. uncompressed wireformat. 242238106Sdes * @param len: length, adjusted to become less. 243238106Sdes * @return stripped off, or "." if input was ".". 244238106Sdes */ 245238106Sdesvoid dname_remove_label(uint8_t** dname, size_t* len); 246238106Sdes 247238106Sdes/** 248238106Sdes * Snip off first N labels from a dname, returning the parent zone. 249238106Sdes * @param dname: from what to strip off. uncompressed wireformat. 250238106Sdes * @param len: length, adjusted to become less. 251238106Sdes * @param n: number of labels to strip off (from the left). 252238106Sdes * if 0, nothing happens. 253238106Sdes * @return stripped off, or "." if input was ".". 254238106Sdes */ 255238106Sdesvoid dname_remove_labels(uint8_t** dname, size_t* len, int n); 256238106Sdes 257238106Sdes/** 258238106Sdes * Count labels for the RRSIG signature label field. 259238106Sdes * Like a normal labelcount, but "*" wildcard and "." root are not counted. 260238106Sdes * @param dname: valid uncompressed wireformat. 261238106Sdes * @return number of labels like in RRSIG; '*' and '.' are not counted. 262238106Sdes */ 263238106Sdesint dname_signame_label_count(uint8_t* dname); 264238106Sdes 265238106Sdes/** 266238106Sdes * Return true if the label is a wildcard, *.example.com. 267238106Sdes * @param dname: valid uncompressed wireformat. 268238106Sdes * @return true if wildcard, or false. 269238106Sdes */ 270238106Sdesint dname_is_wild(uint8_t* dname); 271238106Sdes 272238106Sdes/** 273238106Sdes * Compare dnames, Canonical in rfc4034 sense, but by label. 274238106Sdes * Such that zone contents follows zone apex. 275238106Sdes * 276238106Sdes * @param d1: first dname. pointer to uncompressed wireformat. 277238106Sdes * @param labs1: number of labels in first dname. 278238106Sdes * @param d2: second dname. pointer to uncompressed wireformat. 279238106Sdes * @param labs2: number of labels in second dname. 280238106Sdes * @param mlabs: number of labels that matched exactly (the shared topdomain). 281238106Sdes * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2. 282238106Sdes */ 283238106Sdesint dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, 284238106Sdes int* mlabs); 285238106Sdes 286238106Sdes/** 287238106Sdes * Canonical dname compare. Takes care of counting labels. 288238106Sdes * Per rfc 4034 canonical order. 289238106Sdes * 290238106Sdes * @param d1: first dname. pointer to uncompressed wireformat. 291238106Sdes * @param d2: second dname. pointer to uncompressed wireformat. 292238106Sdes * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2. 293238106Sdes */ 294238106Sdesint dname_canonical_compare(uint8_t* d1, uint8_t* d2); 295238106Sdes 296238106Sdes/** 297238106Sdes * Get the shared topdomain between two names. Root "." or longer. 298238106Sdes * @param d1: first dname. pointer to uncompressed wireformat. 299238106Sdes * @param d2: second dname. pointer to uncompressed wireformat. 300238106Sdes * @return pointer to shared topdomain. Ptr to a part of d1. 301238106Sdes */ 302238106Sdesuint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2); 303238106Sdes 304238106Sdes#endif /* UTIL_DATA_DNAME_H */ 305