1b7579f77SDag-Erling Smørgrav /* 2b7579f77SDag-Erling Smørgrav * util/data/dname.h - domain name handling 3b7579f77SDag-Erling Smørgrav * 4b7579f77SDag-Erling Smørgrav * Copyright (c) 2007, NLnet Labs. All rights reserved. 5b7579f77SDag-Erling Smørgrav * 6b7579f77SDag-Erling Smørgrav * This software is open source. 7b7579f77SDag-Erling Smørgrav * 8b7579f77SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 9b7579f77SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 10b7579f77SDag-Erling Smørgrav * are met: 11b7579f77SDag-Erling Smørgrav * 12b7579f77SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 13b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer. 14b7579f77SDag-Erling Smørgrav * 15b7579f77SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 16b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 17b7579f77SDag-Erling Smørgrav * and/or other materials provided with the distribution. 18b7579f77SDag-Erling Smørgrav * 19b7579f77SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 20b7579f77SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 21b7579f77SDag-Erling Smørgrav * specific prior written permission. 22b7579f77SDag-Erling Smørgrav * 23b7579f77SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2417d15b25SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2517d15b25SDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2617d15b25SDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2717d15b25SDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2817d15b25SDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2917d15b25SDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 3017d15b25SDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 3117d15b25SDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 3217d15b25SDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3317d15b25SDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34b7579f77SDag-Erling Smørgrav */ 35b7579f77SDag-Erling Smørgrav 36b7579f77SDag-Erling Smørgrav /** 37b7579f77SDag-Erling Smørgrav * \file 38b7579f77SDag-Erling Smørgrav * 39b7579f77SDag-Erling Smørgrav * This file contains domain name handling functions. 40b7579f77SDag-Erling Smørgrav */ 41b7579f77SDag-Erling Smørgrav 42b7579f77SDag-Erling Smørgrav #include "config.h" 43b7579f77SDag-Erling Smørgrav #include <ctype.h> 44b7579f77SDag-Erling Smørgrav #include "util/data/dname.h" 45b7579f77SDag-Erling Smørgrav #include "util/data/msgparse.h" 46b7579f77SDag-Erling Smørgrav #include "util/log.h" 47b7579f77SDag-Erling Smørgrav #include "util/storage/lookup3.h" 4809a3aaf3SDag-Erling Smørgrav #include "sldns/sbuffer.h" 49b7579f77SDag-Erling Smørgrav 50b7579f77SDag-Erling Smørgrav /* determine length of a dname in buffer, no compression pointers allowed */ 51b7579f77SDag-Erling Smørgrav size_t 5217d15b25SDag-Erling Smørgrav query_dname_len(sldns_buffer* query) 53b7579f77SDag-Erling Smørgrav { 54b7579f77SDag-Erling Smørgrav size_t len = 0; 55b7579f77SDag-Erling Smørgrav size_t labellen; 56b7579f77SDag-Erling Smørgrav while(1) { 5717d15b25SDag-Erling Smørgrav if(sldns_buffer_remaining(query) < 1) 58b7579f77SDag-Erling Smørgrav return 0; /* parse error, need label len */ 5917d15b25SDag-Erling Smørgrav labellen = sldns_buffer_read_u8(query); 60b7579f77SDag-Erling Smørgrav if(labellen&0xc0) 61b7579f77SDag-Erling Smørgrav return 0; /* no compression allowed in queries */ 62b7579f77SDag-Erling Smørgrav len += labellen + 1; 63b7579f77SDag-Erling Smørgrav if(len > LDNS_MAX_DOMAINLEN) 64b7579f77SDag-Erling Smørgrav return 0; /* too long */ 65b7579f77SDag-Erling Smørgrav if(labellen == 0) 66b7579f77SDag-Erling Smørgrav return len; 6717d15b25SDag-Erling Smørgrav if(sldns_buffer_remaining(query) < labellen) 68b7579f77SDag-Erling Smørgrav return 0; /* parse error, need content */ 6917d15b25SDag-Erling Smørgrav sldns_buffer_skip(query, (ssize_t)labellen); 70b7579f77SDag-Erling Smørgrav } 71b7579f77SDag-Erling Smørgrav } 72b7579f77SDag-Erling Smørgrav 73b7579f77SDag-Erling Smørgrav size_t 74b7579f77SDag-Erling Smørgrav dname_valid(uint8_t* dname, size_t maxlen) 75b7579f77SDag-Erling Smørgrav { 76b7579f77SDag-Erling Smørgrav size_t len = 0; 77b7579f77SDag-Erling Smørgrav size_t labellen; 780eefd307SCy Schubert if(maxlen == 0) 790eefd307SCy Schubert return 0; /* too short, shortest is '0' root label */ 80b7579f77SDag-Erling Smørgrav labellen = *dname++; 81b7579f77SDag-Erling Smørgrav while(labellen) { 82b7579f77SDag-Erling Smørgrav if(labellen&0xc0) 83b7579f77SDag-Erling Smørgrav return 0; /* no compression ptrs allowed */ 84b7579f77SDag-Erling Smørgrav len += labellen + 1; 85b7579f77SDag-Erling Smørgrav if(len >= LDNS_MAX_DOMAINLEN) 86b7579f77SDag-Erling Smørgrav return 0; /* too long */ 87b7579f77SDag-Erling Smørgrav if(len > maxlen) 88b7579f77SDag-Erling Smørgrav return 0; /* does not fit in memory allocation */ 89b7579f77SDag-Erling Smørgrav dname += labellen; 90b7579f77SDag-Erling Smørgrav labellen = *dname++; 91b7579f77SDag-Erling Smørgrav } 92b7579f77SDag-Erling Smørgrav len += 1; 93b7579f77SDag-Erling Smørgrav if(len > maxlen) 94b7579f77SDag-Erling Smørgrav return 0; /* does not fit in memory allocation */ 95b7579f77SDag-Erling Smørgrav return len; 96b7579f77SDag-Erling Smørgrav } 97b7579f77SDag-Erling Smørgrav 98b7579f77SDag-Erling Smørgrav /** compare uncompressed, noncanonical, registers are hints for speed */ 99b7579f77SDag-Erling Smørgrav int 100b7579f77SDag-Erling Smørgrav query_dname_compare(register uint8_t* d1, register uint8_t* d2) 101b7579f77SDag-Erling Smørgrav { 102b7579f77SDag-Erling Smørgrav register uint8_t lab1, lab2; 103b7579f77SDag-Erling Smørgrav log_assert(d1 && d2); 104b7579f77SDag-Erling Smørgrav lab1 = *d1++; 105b7579f77SDag-Erling Smørgrav lab2 = *d2++; 106b7579f77SDag-Erling Smørgrav while( lab1 != 0 || lab2 != 0 ) { 107b7579f77SDag-Erling Smørgrav /* compare label length */ 108b7579f77SDag-Erling Smørgrav /* if one dname ends, it has labellength 0 */ 109b7579f77SDag-Erling Smørgrav if(lab1 != lab2) { 110b7579f77SDag-Erling Smørgrav if(lab1 < lab2) 111b7579f77SDag-Erling Smørgrav return -1; 112b7579f77SDag-Erling Smørgrav return 1; 113b7579f77SDag-Erling Smørgrav } 114b7579f77SDag-Erling Smørgrav log_assert(lab1 == lab2 && lab1 != 0); 115b7579f77SDag-Erling Smørgrav /* compare lowercased labels. */ 116b7579f77SDag-Erling Smørgrav while(lab1--) { 117b7579f77SDag-Erling Smørgrav /* compare bytes first for speed */ 118b7579f77SDag-Erling Smørgrav if(*d1 != *d2 && 119ff825849SDag-Erling Smørgrav tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) { 120ff825849SDag-Erling Smørgrav if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2)) 121b7579f77SDag-Erling Smørgrav return -1; 122b7579f77SDag-Erling Smørgrav return 1; 123b7579f77SDag-Erling Smørgrav } 124b7579f77SDag-Erling Smørgrav d1++; 125b7579f77SDag-Erling Smørgrav d2++; 126b7579f77SDag-Erling Smørgrav } 127b7579f77SDag-Erling Smørgrav /* next pair of labels. */ 128b7579f77SDag-Erling Smørgrav lab1 = *d1++; 129b7579f77SDag-Erling Smørgrav lab2 = *d2++; 130b7579f77SDag-Erling Smørgrav } 131b7579f77SDag-Erling Smørgrav return 0; 132b7579f77SDag-Erling Smørgrav } 133b7579f77SDag-Erling Smørgrav 134b7579f77SDag-Erling Smørgrav void 135b7579f77SDag-Erling Smørgrav query_dname_tolower(uint8_t* dname) 136b7579f77SDag-Erling Smørgrav { 137b7579f77SDag-Erling Smørgrav /* the dname is stored uncompressed */ 138b7579f77SDag-Erling Smørgrav uint8_t labellen; 139b7579f77SDag-Erling Smørgrav labellen = *dname; 140b7579f77SDag-Erling Smørgrav while(labellen) { 141b7579f77SDag-Erling Smørgrav dname++; 142b7579f77SDag-Erling Smørgrav while(labellen--) { 143ff825849SDag-Erling Smørgrav *dname = (uint8_t)tolower((unsigned char)*dname); 144b7579f77SDag-Erling Smørgrav dname++; 145b7579f77SDag-Erling Smørgrav } 146b7579f77SDag-Erling Smørgrav labellen = *dname; 147b7579f77SDag-Erling Smørgrav } 148b7579f77SDag-Erling Smørgrav } 149b7579f77SDag-Erling Smørgrav 150b7579f77SDag-Erling Smørgrav void 15117d15b25SDag-Erling Smørgrav pkt_dname_tolower(sldns_buffer* pkt, uint8_t* dname) 152b7579f77SDag-Erling Smørgrav { 153b7579f77SDag-Erling Smørgrav uint8_t lablen; 154b7579f77SDag-Erling Smørgrav int count = 0; 15517d15b25SDag-Erling Smørgrav if(dname >= sldns_buffer_end(pkt)) 156b7579f77SDag-Erling Smørgrav return; 157b7579f77SDag-Erling Smørgrav lablen = *dname++; 158b7579f77SDag-Erling Smørgrav while(lablen) { 159b7579f77SDag-Erling Smørgrav if(LABEL_IS_PTR(lablen)) { 160b7579f77SDag-Erling Smørgrav if((size_t)PTR_OFFSET(lablen, *dname) 16117d15b25SDag-Erling Smørgrav >= sldns_buffer_limit(pkt)) 162b7579f77SDag-Erling Smørgrav return; 16317d15b25SDag-Erling Smørgrav dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); 164b7579f77SDag-Erling Smørgrav lablen = *dname++; 165b7579f77SDag-Erling Smørgrav if(count++ > MAX_COMPRESS_PTRS) 166b7579f77SDag-Erling Smørgrav return; 167b7579f77SDag-Erling Smørgrav continue; 168b7579f77SDag-Erling Smørgrav } 16917d15b25SDag-Erling Smørgrav if(dname+lablen >= sldns_buffer_end(pkt)) 170b7579f77SDag-Erling Smørgrav return; 171b7579f77SDag-Erling Smørgrav while(lablen--) { 172ff825849SDag-Erling Smørgrav *dname = (uint8_t)tolower((unsigned char)*dname); 173b7579f77SDag-Erling Smørgrav dname++; 174b7579f77SDag-Erling Smørgrav } 17517d15b25SDag-Erling Smørgrav if(dname >= sldns_buffer_end(pkt)) 176b7579f77SDag-Erling Smørgrav return; 177b7579f77SDag-Erling Smørgrav lablen = *dname++; 178b7579f77SDag-Erling Smørgrav } 179b7579f77SDag-Erling Smørgrav } 180b7579f77SDag-Erling Smørgrav 181b7579f77SDag-Erling Smørgrav 182b7579f77SDag-Erling Smørgrav size_t 18317d15b25SDag-Erling Smørgrav pkt_dname_len(sldns_buffer* pkt) 184b7579f77SDag-Erling Smørgrav { 185b7579f77SDag-Erling Smørgrav size_t len = 0; 186b7579f77SDag-Erling Smørgrav int ptrcount = 0; 187b7579f77SDag-Erling Smørgrav uint8_t labellen; 188b7579f77SDag-Erling Smørgrav size_t endpos = 0; 189b7579f77SDag-Erling Smørgrav 190b7579f77SDag-Erling Smørgrav /* read dname and determine length */ 191b7579f77SDag-Erling Smørgrav /* check compression pointers, loops, out of bounds */ 192b7579f77SDag-Erling Smørgrav while(1) { 193b7579f77SDag-Erling Smørgrav /* read next label */ 19417d15b25SDag-Erling Smørgrav if(sldns_buffer_remaining(pkt) < 1) 195b7579f77SDag-Erling Smørgrav return 0; 19617d15b25SDag-Erling Smørgrav labellen = sldns_buffer_read_u8(pkt); 197b7579f77SDag-Erling Smørgrav if(LABEL_IS_PTR(labellen)) { 198b7579f77SDag-Erling Smørgrav /* compression ptr */ 199b7579f77SDag-Erling Smørgrav uint16_t ptr; 20017d15b25SDag-Erling Smørgrav if(sldns_buffer_remaining(pkt) < 1) 201b7579f77SDag-Erling Smørgrav return 0; 20217d15b25SDag-Erling Smørgrav ptr = PTR_OFFSET(labellen, sldns_buffer_read_u8(pkt)); 203b7579f77SDag-Erling Smørgrav if(ptrcount++ > MAX_COMPRESS_PTRS) 204b7579f77SDag-Erling Smørgrav return 0; /* loop! */ 20517d15b25SDag-Erling Smørgrav if(sldns_buffer_limit(pkt) <= ptr) 206b7579f77SDag-Erling Smørgrav return 0; /* out of bounds! */ 207b7579f77SDag-Erling Smørgrav if(!endpos) 20817d15b25SDag-Erling Smørgrav endpos = sldns_buffer_position(pkt); 20917d15b25SDag-Erling Smørgrav sldns_buffer_set_position(pkt, ptr); 210b7579f77SDag-Erling Smørgrav } else { 211b7579f77SDag-Erling Smørgrav /* label contents */ 212b7579f77SDag-Erling Smørgrav if(labellen > 0x3f) 213b7579f77SDag-Erling Smørgrav return 0; /* label too long */ 214b7579f77SDag-Erling Smørgrav len += 1 + labellen; 215b7579f77SDag-Erling Smørgrav if(len > LDNS_MAX_DOMAINLEN) 216b7579f77SDag-Erling Smørgrav return 0; 217b7579f77SDag-Erling Smørgrav if(labellen == 0) { 218b7579f77SDag-Erling Smørgrav /* end of dname */ 219b7579f77SDag-Erling Smørgrav break; 220b7579f77SDag-Erling Smørgrav } 22117d15b25SDag-Erling Smørgrav if(sldns_buffer_remaining(pkt) < labellen) 222b7579f77SDag-Erling Smørgrav return 0; 22317d15b25SDag-Erling Smørgrav sldns_buffer_skip(pkt, (ssize_t)labellen); 224b7579f77SDag-Erling Smørgrav } 225b7579f77SDag-Erling Smørgrav } 226b7579f77SDag-Erling Smørgrav if(endpos) 22717d15b25SDag-Erling Smørgrav sldns_buffer_set_position(pkt, endpos); 228b7579f77SDag-Erling Smørgrav 229b7579f77SDag-Erling Smørgrav return len; 230b7579f77SDag-Erling Smørgrav } 231b7579f77SDag-Erling Smørgrav 232b7579f77SDag-Erling Smørgrav int 23317d15b25SDag-Erling Smørgrav dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2) 234b7579f77SDag-Erling Smørgrav { 235b7579f77SDag-Erling Smørgrav uint8_t len1, len2; 236091e9e46SCy Schubert int count1 = 0, count2 = 0; 237b7579f77SDag-Erling Smørgrav log_assert(pkt && d1 && d2); 238b7579f77SDag-Erling Smørgrav len1 = *d1++; 239b7579f77SDag-Erling Smørgrav len2 = *d2++; 240b7579f77SDag-Erling Smørgrav while( len1 != 0 || len2 != 0 ) { 241b7579f77SDag-Erling Smørgrav /* resolve ptrs */ 242b7579f77SDag-Erling Smørgrav if(LABEL_IS_PTR(len1)) { 243091e9e46SCy Schubert if((size_t)PTR_OFFSET(len1, *d1) 244091e9e46SCy Schubert >= sldns_buffer_limit(pkt)) 245091e9e46SCy Schubert return -1; 246091e9e46SCy Schubert if(count1++ > MAX_COMPRESS_PTRS) 247091e9e46SCy Schubert return -1; 24817d15b25SDag-Erling Smørgrav d1 = sldns_buffer_at(pkt, PTR_OFFSET(len1, *d1)); 249b7579f77SDag-Erling Smørgrav len1 = *d1++; 250b7579f77SDag-Erling Smørgrav continue; 251b7579f77SDag-Erling Smørgrav } 252b7579f77SDag-Erling Smørgrav if(LABEL_IS_PTR(len2)) { 253091e9e46SCy Schubert if((size_t)PTR_OFFSET(len2, *d2) 254091e9e46SCy Schubert >= sldns_buffer_limit(pkt)) 255091e9e46SCy Schubert return 1; 256091e9e46SCy Schubert if(count2++ > MAX_COMPRESS_PTRS) 257091e9e46SCy Schubert return 1; 25817d15b25SDag-Erling Smørgrav d2 = sldns_buffer_at(pkt, PTR_OFFSET(len2, *d2)); 259b7579f77SDag-Erling Smørgrav len2 = *d2++; 260b7579f77SDag-Erling Smørgrav continue; 261b7579f77SDag-Erling Smørgrav } 262b7579f77SDag-Erling Smørgrav /* check label length */ 263b7579f77SDag-Erling Smørgrav log_assert(len1 <= LDNS_MAX_LABELLEN); 264b7579f77SDag-Erling Smørgrav log_assert(len2 <= LDNS_MAX_LABELLEN); 265b7579f77SDag-Erling Smørgrav if(len1 != len2) { 266b7579f77SDag-Erling Smørgrav if(len1 < len2) return -1; 267b7579f77SDag-Erling Smørgrav return 1; 268b7579f77SDag-Erling Smørgrav } 269b7579f77SDag-Erling Smørgrav log_assert(len1 == len2 && len1 != 0); 270b7579f77SDag-Erling Smørgrav /* compare labels */ 271b7579f77SDag-Erling Smørgrav while(len1--) { 272e2d15004SDag-Erling Smørgrav if(tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) { 273e2d15004SDag-Erling Smørgrav if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2)) 274b7579f77SDag-Erling Smørgrav return -1; 275b7579f77SDag-Erling Smørgrav return 1; 276b7579f77SDag-Erling Smørgrav } 277e2d15004SDag-Erling Smørgrav d1++; 278e2d15004SDag-Erling Smørgrav d2++; 279b7579f77SDag-Erling Smørgrav } 280b7579f77SDag-Erling Smørgrav len1 = *d1++; 281b7579f77SDag-Erling Smørgrav len2 = *d2++; 282b7579f77SDag-Erling Smørgrav } 283b7579f77SDag-Erling Smørgrav return 0; 284b7579f77SDag-Erling Smørgrav } 285b7579f77SDag-Erling Smørgrav 2863005e0a3SDag-Erling Smørgrav hashvalue_type 2873005e0a3SDag-Erling Smørgrav dname_query_hash(uint8_t* dname, hashvalue_type h) 288b7579f77SDag-Erling Smørgrav { 289b7579f77SDag-Erling Smørgrav uint8_t labuf[LDNS_MAX_LABELLEN+1]; 290b7579f77SDag-Erling Smørgrav uint8_t lablen; 291b7579f77SDag-Erling Smørgrav int i; 292b7579f77SDag-Erling Smørgrav 293b7579f77SDag-Erling Smørgrav /* preserve case of query, make hash label by label */ 294b7579f77SDag-Erling Smørgrav lablen = *dname++; 295b7579f77SDag-Erling Smørgrav while(lablen) { 296b7579f77SDag-Erling Smørgrav log_assert(lablen <= LDNS_MAX_LABELLEN); 297b7579f77SDag-Erling Smørgrav labuf[0] = lablen; 298b7579f77SDag-Erling Smørgrav i=0; 299e2d15004SDag-Erling Smørgrav while(lablen--) { 300e2d15004SDag-Erling Smørgrav labuf[++i] = (uint8_t)tolower((unsigned char)*dname); 301e2d15004SDag-Erling Smørgrav dname++; 302e2d15004SDag-Erling Smørgrav } 303b7579f77SDag-Erling Smørgrav h = hashlittle(labuf, labuf[0] + 1, h); 304b7579f77SDag-Erling Smørgrav lablen = *dname++; 305b7579f77SDag-Erling Smørgrav } 306b7579f77SDag-Erling Smørgrav 307b7579f77SDag-Erling Smørgrav return h; 308b7579f77SDag-Erling Smørgrav } 309b7579f77SDag-Erling Smørgrav 3103005e0a3SDag-Erling Smørgrav hashvalue_type 3113005e0a3SDag-Erling Smørgrav dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_type h) 312b7579f77SDag-Erling Smørgrav { 313b7579f77SDag-Erling Smørgrav uint8_t labuf[LDNS_MAX_LABELLEN+1]; 314b7579f77SDag-Erling Smørgrav uint8_t lablen; 315b7579f77SDag-Erling Smørgrav int i; 316091e9e46SCy Schubert int count = 0; 317b7579f77SDag-Erling Smørgrav 318b7579f77SDag-Erling Smørgrav /* preserve case of query, make hash label by label */ 319b7579f77SDag-Erling Smørgrav lablen = *dname++; 320b7579f77SDag-Erling Smørgrav while(lablen) { 321b7579f77SDag-Erling Smørgrav if(LABEL_IS_PTR(lablen)) { 322b7579f77SDag-Erling Smørgrav /* follow pointer */ 323091e9e46SCy Schubert if((size_t)PTR_OFFSET(lablen, *dname) 324091e9e46SCy Schubert >= sldns_buffer_limit(pkt)) 325091e9e46SCy Schubert return h; 326091e9e46SCy Schubert if(count++ > MAX_COMPRESS_PTRS) 327091e9e46SCy Schubert return h; 32817d15b25SDag-Erling Smørgrav dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); 329b7579f77SDag-Erling Smørgrav lablen = *dname++; 330b7579f77SDag-Erling Smørgrav continue; 331b7579f77SDag-Erling Smørgrav } 332b7579f77SDag-Erling Smørgrav log_assert(lablen <= LDNS_MAX_LABELLEN); 333b7579f77SDag-Erling Smørgrav labuf[0] = lablen; 334b7579f77SDag-Erling Smørgrav i=0; 335e2d15004SDag-Erling Smørgrav while(lablen--) { 336e2d15004SDag-Erling Smørgrav labuf[++i] = (uint8_t)tolower((unsigned char)*dname); 337e2d15004SDag-Erling Smørgrav dname++; 338e2d15004SDag-Erling Smørgrav } 339b7579f77SDag-Erling Smørgrav h = hashlittle(labuf, labuf[0] + 1, h); 340b7579f77SDag-Erling Smørgrav lablen = *dname++; 341b7579f77SDag-Erling Smørgrav } 342b7579f77SDag-Erling Smørgrav 343b7579f77SDag-Erling Smørgrav return h; 344b7579f77SDag-Erling Smørgrav } 345b7579f77SDag-Erling Smørgrav 34617d15b25SDag-Erling Smørgrav void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname) 347b7579f77SDag-Erling Smørgrav { 348b7579f77SDag-Erling Smørgrav /* copy over the dname and decompress it at the same time */ 3490eefd307SCy Schubert size_t comprcount = 0; 350b7579f77SDag-Erling Smørgrav size_t len = 0; 351b7579f77SDag-Erling Smørgrav uint8_t lablen; 352b7579f77SDag-Erling Smørgrav lablen = *dname++; 353b7579f77SDag-Erling Smørgrav while(lablen) { 354b7579f77SDag-Erling Smørgrav if(LABEL_IS_PTR(lablen)) { 3550eefd307SCy Schubert if(comprcount++ > MAX_COMPRESS_PTRS) { 3560eefd307SCy Schubert /* too many compression pointers */ 3570eefd307SCy Schubert *to = 0; /* end the result prematurely */ 3580eefd307SCy Schubert return; 3590eefd307SCy Schubert } 360b7579f77SDag-Erling Smørgrav /* follow pointer */ 361091e9e46SCy Schubert if((size_t)PTR_OFFSET(lablen, *dname) 362091e9e46SCy Schubert >= sldns_buffer_limit(pkt)) 363091e9e46SCy Schubert return; 36417d15b25SDag-Erling Smørgrav dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); 365b7579f77SDag-Erling Smørgrav lablen = *dname++; 366b7579f77SDag-Erling Smørgrav continue; 367b7579f77SDag-Erling Smørgrav } 3680eefd307SCy Schubert if(lablen > LDNS_MAX_LABELLEN) { 3690eefd307SCy Schubert *to = 0; /* end the result prematurely */ 3700eefd307SCy Schubert return; 3710eefd307SCy Schubert } 372b7579f77SDag-Erling Smørgrav log_assert(lablen <= LDNS_MAX_LABELLEN); 373b7579f77SDag-Erling Smørgrav len += (size_t)lablen+1; 374b7579f77SDag-Erling Smørgrav if(len >= LDNS_MAX_DOMAINLEN) { 375b7579f77SDag-Erling Smørgrav *to = 0; /* end the result prematurely */ 376b7579f77SDag-Erling Smørgrav log_err("bad dname in dname_pkt_copy"); 377b7579f77SDag-Erling Smørgrav return; 378b7579f77SDag-Erling Smørgrav } 379b7579f77SDag-Erling Smørgrav *to++ = lablen; 380b7579f77SDag-Erling Smørgrav memmove(to, dname, lablen); 381b7579f77SDag-Erling Smørgrav dname += lablen; 382b7579f77SDag-Erling Smørgrav to += lablen; 383b7579f77SDag-Erling Smørgrav lablen = *dname++; 384b7579f77SDag-Erling Smørgrav } 385b7579f77SDag-Erling Smørgrav /* copy last \0 */ 386b7579f77SDag-Erling Smørgrav *to = 0; 387b7579f77SDag-Erling Smørgrav } 388b7579f77SDag-Erling Smørgrav 38917d15b25SDag-Erling Smørgrav void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname) 390b7579f77SDag-Erling Smørgrav { 391b7579f77SDag-Erling Smørgrav uint8_t lablen; 392091e9e46SCy Schubert int count = 0; 393b7579f77SDag-Erling Smørgrav if(!out) out = stdout; 394b7579f77SDag-Erling Smørgrav if(!dname) return; 395b7579f77SDag-Erling Smørgrav 396b7579f77SDag-Erling Smørgrav lablen = *dname++; 397b7579f77SDag-Erling Smørgrav if(!lablen) 398b7579f77SDag-Erling Smørgrav fputc('.', out); 399b7579f77SDag-Erling Smørgrav while(lablen) { 400b7579f77SDag-Erling Smørgrav if(LABEL_IS_PTR(lablen)) { 401b7579f77SDag-Erling Smørgrav /* follow pointer */ 402b7579f77SDag-Erling Smørgrav if(!pkt) { 403b7579f77SDag-Erling Smørgrav fputs("??compressionptr??", out); 404b7579f77SDag-Erling Smørgrav return; 405b7579f77SDag-Erling Smørgrav } 406091e9e46SCy Schubert if((size_t)PTR_OFFSET(lablen, *dname) 407091e9e46SCy Schubert >= sldns_buffer_limit(pkt)) { 408091e9e46SCy Schubert fputs("??compressionptr??", out); 409091e9e46SCy Schubert return; 410091e9e46SCy Schubert } 411091e9e46SCy Schubert if(count++ > MAX_COMPRESS_PTRS) { 412091e9e46SCy Schubert fputs("??compressionptr??", out); 413091e9e46SCy Schubert return; 414091e9e46SCy Schubert } 41517d15b25SDag-Erling Smørgrav dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); 416b7579f77SDag-Erling Smørgrav lablen = *dname++; 417b7579f77SDag-Erling Smørgrav continue; 418b7579f77SDag-Erling Smørgrav } 419b7579f77SDag-Erling Smørgrav if(lablen > LDNS_MAX_LABELLEN) { 420b7579f77SDag-Erling Smørgrav fputs("??extendedlabel??", out); 421b7579f77SDag-Erling Smørgrav return; 422b7579f77SDag-Erling Smørgrav } 423b7579f77SDag-Erling Smørgrav while(lablen--) 424b7579f77SDag-Erling Smørgrav fputc((int)*dname++, out); 425b7579f77SDag-Erling Smørgrav fputc('.', out); 426b7579f77SDag-Erling Smørgrav lablen = *dname++; 427b7579f77SDag-Erling Smørgrav } 428b7579f77SDag-Erling Smørgrav } 429b7579f77SDag-Erling Smørgrav 430b7579f77SDag-Erling Smørgrav int 431b7579f77SDag-Erling Smørgrav dname_count_labels(uint8_t* dname) 432b7579f77SDag-Erling Smørgrav { 433b7579f77SDag-Erling Smørgrav uint8_t lablen; 434b7579f77SDag-Erling Smørgrav int labs = 1; 435b7579f77SDag-Erling Smørgrav 436b7579f77SDag-Erling Smørgrav lablen = *dname++; 437b7579f77SDag-Erling Smørgrav while(lablen) { 438b7579f77SDag-Erling Smørgrav labs++; 439b7579f77SDag-Erling Smørgrav dname += lablen; 440b7579f77SDag-Erling Smørgrav lablen = *dname++; 441b7579f77SDag-Erling Smørgrav } 442b7579f77SDag-Erling Smørgrav return labs; 443b7579f77SDag-Erling Smørgrav } 444b7579f77SDag-Erling Smørgrav 445b7579f77SDag-Erling Smørgrav int 446b7579f77SDag-Erling Smørgrav dname_count_size_labels(uint8_t* dname, size_t* size) 447b7579f77SDag-Erling Smørgrav { 448b7579f77SDag-Erling Smørgrav uint8_t lablen; 449b7579f77SDag-Erling Smørgrav int labs = 1; 450b7579f77SDag-Erling Smørgrav size_t sz = 1; 451b7579f77SDag-Erling Smørgrav 452b7579f77SDag-Erling Smørgrav lablen = *dname++; 453b7579f77SDag-Erling Smørgrav while(lablen) { 454b7579f77SDag-Erling Smørgrav labs++; 455b7579f77SDag-Erling Smørgrav sz += lablen+1; 456b7579f77SDag-Erling Smørgrav dname += lablen; 457b7579f77SDag-Erling Smørgrav lablen = *dname++; 458b7579f77SDag-Erling Smørgrav } 459b7579f77SDag-Erling Smørgrav *size = sz; 460b7579f77SDag-Erling Smørgrav return labs; 461b7579f77SDag-Erling Smørgrav } 462b7579f77SDag-Erling Smørgrav 463b7579f77SDag-Erling Smørgrav /** 464b7579f77SDag-Erling Smørgrav * Compare labels in memory, lowercase while comparing. 465b7579f77SDag-Erling Smørgrav * @param p1: label 1 466b7579f77SDag-Erling Smørgrav * @param p2: label 2 467b7579f77SDag-Erling Smørgrav * @param len: number of bytes to compare. 468b7579f77SDag-Erling Smørgrav * @return: 0, -1, +1 comparison result. 469b7579f77SDag-Erling Smørgrav */ 470b7579f77SDag-Erling Smørgrav static int 471b7579f77SDag-Erling Smørgrav memlowercmp(uint8_t* p1, uint8_t* p2, uint8_t len) 472b7579f77SDag-Erling Smørgrav { 473b7579f77SDag-Erling Smørgrav while(len--) { 474ff825849SDag-Erling Smørgrav if(*p1 != *p2 && tolower((unsigned char)*p1) != tolower((unsigned char)*p2)) { 475ff825849SDag-Erling Smørgrav if(tolower((unsigned char)*p1) < tolower((unsigned char)*p2)) 476b7579f77SDag-Erling Smørgrav return -1; 477b7579f77SDag-Erling Smørgrav return 1; 478b7579f77SDag-Erling Smørgrav } 479b7579f77SDag-Erling Smørgrav p1++; 480b7579f77SDag-Erling Smørgrav p2++; 481b7579f77SDag-Erling Smørgrav } 482b7579f77SDag-Erling Smørgrav return 0; 483b7579f77SDag-Erling Smørgrav } 484b7579f77SDag-Erling Smørgrav 485b7579f77SDag-Erling Smørgrav int 486b7579f77SDag-Erling Smørgrav dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs) 487b7579f77SDag-Erling Smørgrav { 488b7579f77SDag-Erling Smørgrav uint8_t len1, len2; 489b7579f77SDag-Erling Smørgrav int atlabel = labs1; 490b7579f77SDag-Erling Smørgrav int lastmlabs; 491b7579f77SDag-Erling Smørgrav int lastdiff = 0; 492b7579f77SDag-Erling Smørgrav /* first skip so that we compare same label. */ 493b7579f77SDag-Erling Smørgrav if(labs1 > labs2) { 494b7579f77SDag-Erling Smørgrav while(atlabel > labs2) { 495b7579f77SDag-Erling Smørgrav len1 = *d1++; 496b7579f77SDag-Erling Smørgrav d1 += len1; 497b7579f77SDag-Erling Smørgrav atlabel--; 498b7579f77SDag-Erling Smørgrav } 499b7579f77SDag-Erling Smørgrav log_assert(atlabel == labs2); 500b7579f77SDag-Erling Smørgrav } else if(labs1 < labs2) { 501b7579f77SDag-Erling Smørgrav atlabel = labs2; 502b7579f77SDag-Erling Smørgrav while(atlabel > labs1) { 503b7579f77SDag-Erling Smørgrav len2 = *d2++; 504b7579f77SDag-Erling Smørgrav d2 += len2; 505b7579f77SDag-Erling Smørgrav atlabel--; 506b7579f77SDag-Erling Smørgrav } 507b7579f77SDag-Erling Smørgrav log_assert(atlabel == labs1); 508b7579f77SDag-Erling Smørgrav } 509b7579f77SDag-Erling Smørgrav lastmlabs = atlabel+1; 510b7579f77SDag-Erling Smørgrav /* now at same label in d1 and d2, atlabel */ 511b7579f77SDag-Erling Smørgrav /* www.example.com. */ 512b7579f77SDag-Erling Smørgrav /* 4 3 2 1 atlabel number */ 513b7579f77SDag-Erling Smørgrav /* repeat until at root label (which is always the same) */ 514b7579f77SDag-Erling Smørgrav while(atlabel > 1) { 515b7579f77SDag-Erling Smørgrav len1 = *d1++; 516b7579f77SDag-Erling Smørgrav len2 = *d2++; 517b7579f77SDag-Erling Smørgrav if(len1 != len2) { 518b7579f77SDag-Erling Smørgrav log_assert(len1 != 0 && len2 != 0); 519b7579f77SDag-Erling Smørgrav if(len1<len2) 520b7579f77SDag-Erling Smørgrav lastdiff = -1; 521b7579f77SDag-Erling Smørgrav else lastdiff = 1; 522b7579f77SDag-Erling Smørgrav lastmlabs = atlabel; 523b7579f77SDag-Erling Smørgrav d1 += len1; 524b7579f77SDag-Erling Smørgrav d2 += len2; 525b7579f77SDag-Erling Smørgrav } else { 526b7579f77SDag-Erling Smørgrav /* memlowercmp is inlined here; or just like 527b7579f77SDag-Erling Smørgrav * if((c=memlowercmp(d1, d2, len1)) != 0) { 528b7579f77SDag-Erling Smørgrav * lastdiff = c; 529b7579f77SDag-Erling Smørgrav * lastmlabs = atlabel; } apart from d1++,d2++ */ 530b7579f77SDag-Erling Smørgrav while(len1) { 531ff825849SDag-Erling Smørgrav if(*d1 != *d2 && tolower((unsigned char)*d1) 532ff825849SDag-Erling Smørgrav != tolower((unsigned char)*d2)) { 533ff825849SDag-Erling Smørgrav if(tolower((unsigned char)*d1) < 534ff825849SDag-Erling Smørgrav tolower((unsigned char)*d2)) { 535b7579f77SDag-Erling Smørgrav lastdiff = -1; 536b7579f77SDag-Erling Smørgrav lastmlabs = atlabel; 537b7579f77SDag-Erling Smørgrav d1 += len1; 538b7579f77SDag-Erling Smørgrav d2 += len1; 539b7579f77SDag-Erling Smørgrav break; 540b7579f77SDag-Erling Smørgrav } 541b7579f77SDag-Erling Smørgrav lastdiff = 1; 542b7579f77SDag-Erling Smørgrav lastmlabs = atlabel; 543b7579f77SDag-Erling Smørgrav d1 += len1; 544b7579f77SDag-Erling Smørgrav d2 += len1; 545b7579f77SDag-Erling Smørgrav break; /* out of memlowercmp */ 546b7579f77SDag-Erling Smørgrav } 547b7579f77SDag-Erling Smørgrav d1++; 548b7579f77SDag-Erling Smørgrav d2++; 549b7579f77SDag-Erling Smørgrav len1--; 550b7579f77SDag-Erling Smørgrav } 551b7579f77SDag-Erling Smørgrav } 552b7579f77SDag-Erling Smørgrav atlabel--; 553b7579f77SDag-Erling Smørgrav } 554b7579f77SDag-Erling Smørgrav /* last difference atlabel number, so number of labels matching, 555b7579f77SDag-Erling Smørgrav * at the right side, is one less. */ 556b7579f77SDag-Erling Smørgrav *mlabs = lastmlabs-1; 557b7579f77SDag-Erling Smørgrav if(lastdiff == 0) { 558b7579f77SDag-Erling Smørgrav /* all labels compared were equal, check if one has more 559b7579f77SDag-Erling Smørgrav * labels, so that example.com. > com. */ 560b7579f77SDag-Erling Smørgrav if(labs1 > labs2) 561b7579f77SDag-Erling Smørgrav return 1; 562b7579f77SDag-Erling Smørgrav else if(labs1 < labs2) 563b7579f77SDag-Erling Smørgrav return -1; 564b7579f77SDag-Erling Smørgrav } 565b7579f77SDag-Erling Smørgrav return lastdiff; 566b7579f77SDag-Erling Smørgrav } 567b7579f77SDag-Erling Smørgrav 568b7579f77SDag-Erling Smørgrav int 5690fb34990SDag-Erling Smørgrav dname_lab_startswith(uint8_t* label, char* prefix, char** endptr) 5700fb34990SDag-Erling Smørgrav { 5710fb34990SDag-Erling Smørgrav size_t plen = strlen(prefix); 5720fb34990SDag-Erling Smørgrav size_t orig_plen = plen; 5730fb34990SDag-Erling Smørgrav size_t lablen = (size_t)*label; 5740fb34990SDag-Erling Smørgrav if(plen > lablen) 5750fb34990SDag-Erling Smørgrav return 0; 5760fb34990SDag-Erling Smørgrav label++; 5770fb34990SDag-Erling Smørgrav while(plen--) { 5780fb34990SDag-Erling Smørgrav if(*prefix != tolower((unsigned char)*label)) { 5790fb34990SDag-Erling Smørgrav return 0; 5800fb34990SDag-Erling Smørgrav } 5810fb34990SDag-Erling Smørgrav prefix++; label++; 5820fb34990SDag-Erling Smørgrav } 5830fb34990SDag-Erling Smørgrav if(orig_plen < lablen) 5840fb34990SDag-Erling Smørgrav *endptr = (char *)label; 5850fb34990SDag-Erling Smørgrav else 5860fb34990SDag-Erling Smørgrav /* prefix length == label length */ 5870fb34990SDag-Erling Smørgrav *endptr = NULL; 5880fb34990SDag-Erling Smørgrav return 1; 5890fb34990SDag-Erling Smørgrav } 5900fb34990SDag-Erling Smørgrav 5910fb34990SDag-Erling Smørgrav int 592091e9e46SCy Schubert dname_has_label(uint8_t* dname, size_t dnamelen, uint8_t* label) 593091e9e46SCy Schubert { 594091e9e46SCy Schubert size_t len; 595091e9e46SCy Schubert 596091e9e46SCy Schubert /* 1 byte needed for the label length */ 597091e9e46SCy Schubert if(dnamelen < 1) 598091e9e46SCy Schubert return 0; 599091e9e46SCy Schubert 600091e9e46SCy Schubert len = *dname; 601091e9e46SCy Schubert while(len <= dnamelen) { 602091e9e46SCy Schubert if(!(*dname)) { 603091e9e46SCy Schubert if(*dname == *label) 604091e9e46SCy Schubert return 1; /* empty label match */ 605091e9e46SCy Schubert /* termination label found, stop iterating */ 606091e9e46SCy Schubert return 0; 607091e9e46SCy Schubert } 608091e9e46SCy Schubert if(*dname == *label && *label && 609091e9e46SCy Schubert memlowercmp(dname+1, label+1, *dname) == 0) 610091e9e46SCy Schubert return 1; 611091e9e46SCy Schubert len += *dname; 612091e9e46SCy Schubert dname += *dname; 613091e9e46SCy Schubert dname++; 614091e9e46SCy Schubert len++; 615091e9e46SCy Schubert } 616091e9e46SCy Schubert return 0; 617091e9e46SCy Schubert } 618091e9e46SCy Schubert 619091e9e46SCy Schubert int 62017d15b25SDag-Erling Smørgrav dname_buffer_write(sldns_buffer* pkt, uint8_t* dname) 621b7579f77SDag-Erling Smørgrav { 622b7579f77SDag-Erling Smørgrav uint8_t lablen; 623b7579f77SDag-Erling Smørgrav 62417d15b25SDag-Erling Smørgrav if(sldns_buffer_remaining(pkt) < 1) 625b7579f77SDag-Erling Smørgrav return 0; 626b7579f77SDag-Erling Smørgrav lablen = *dname++; 62717d15b25SDag-Erling Smørgrav sldns_buffer_write_u8(pkt, lablen); 628b7579f77SDag-Erling Smørgrav while(lablen) { 62917d15b25SDag-Erling Smørgrav if(sldns_buffer_remaining(pkt) < (size_t)lablen+1) 630b7579f77SDag-Erling Smørgrav return 0; 63117d15b25SDag-Erling Smørgrav sldns_buffer_write(pkt, dname, lablen); 632b7579f77SDag-Erling Smørgrav dname += lablen; 633b7579f77SDag-Erling Smørgrav lablen = *dname++; 63417d15b25SDag-Erling Smørgrav sldns_buffer_write_u8(pkt, lablen); 635b7579f77SDag-Erling Smørgrav } 636b7579f77SDag-Erling Smørgrav return 1; 637b7579f77SDag-Erling Smørgrav } 638b7579f77SDag-Erling Smørgrav 639b7579f77SDag-Erling Smørgrav void dname_str(uint8_t* dname, char* str) 640b7579f77SDag-Erling Smørgrav { 641b7579f77SDag-Erling Smørgrav size_t len = 0; 642b7579f77SDag-Erling Smørgrav uint8_t lablen = 0; 643b7579f77SDag-Erling Smørgrav char* s = str; 644b7579f77SDag-Erling Smørgrav if(!dname || !*dname) { 645b7579f77SDag-Erling Smørgrav *s++ = '.'; 646b7579f77SDag-Erling Smørgrav *s = 0; 647*be771a7bSCy Schubert goto out; 648b7579f77SDag-Erling Smørgrav } 649b7579f77SDag-Erling Smørgrav lablen = *dname++; 650b7579f77SDag-Erling Smørgrav while(lablen) { 651b7579f77SDag-Erling Smørgrav if(lablen > LDNS_MAX_LABELLEN) { 652b7579f77SDag-Erling Smørgrav *s++ = '#'; 653b7579f77SDag-Erling Smørgrav *s = 0; 654*be771a7bSCy Schubert goto out; 655b7579f77SDag-Erling Smørgrav } 656b7579f77SDag-Erling Smørgrav len += lablen+1; 657*be771a7bSCy Schubert if(len >= LDNS_MAX_DOMAINLEN) { 658b7579f77SDag-Erling Smørgrav *s++ = '&'; 659b7579f77SDag-Erling Smørgrav *s = 0; 660*be771a7bSCy Schubert goto out; 661b7579f77SDag-Erling Smørgrav } 662b7579f77SDag-Erling Smørgrav while(lablen--) { 663ff825849SDag-Erling Smørgrav if(isalnum((unsigned char)*dname) 664b7579f77SDag-Erling Smørgrav || *dname == '-' || *dname == '_' 665b7579f77SDag-Erling Smørgrav || *dname == '*') 666b7579f77SDag-Erling Smørgrav *s++ = *(char*)dname++; 667b7579f77SDag-Erling Smørgrav else { 668b7579f77SDag-Erling Smørgrav *s++ = '?'; 669b7579f77SDag-Erling Smørgrav dname++; 670b7579f77SDag-Erling Smørgrav } 671b7579f77SDag-Erling Smørgrav } 672b7579f77SDag-Erling Smørgrav *s++ = '.'; 673b7579f77SDag-Erling Smørgrav lablen = *dname++; 674b7579f77SDag-Erling Smørgrav } 675b7579f77SDag-Erling Smørgrav *s = 0; 676*be771a7bSCy Schubert 677*be771a7bSCy Schubert out: 678*be771a7bSCy Schubert log_assert(s - str < LDNS_MAX_DOMAINLEN); 679*be771a7bSCy Schubert return; 680b7579f77SDag-Erling Smørgrav } 681b7579f77SDag-Erling Smørgrav 682b7579f77SDag-Erling Smørgrav int 683b7579f77SDag-Erling Smørgrav dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2) 684b7579f77SDag-Erling Smørgrav { 685b7579f77SDag-Erling Smørgrav int m; 686b7579f77SDag-Erling Smørgrav /* check subdomain: d1: www.example.com. and d2: example.com. */ 687b7579f77SDag-Erling Smørgrav if(labs2 >= labs1) 688b7579f77SDag-Erling Smørgrav return 0; 689b7579f77SDag-Erling Smørgrav if(dname_lab_cmp(d1, labs1, d2, labs2, &m) > 0) { 690b7579f77SDag-Erling Smørgrav /* subdomain if all labels match */ 691b7579f77SDag-Erling Smørgrav return (m == labs2); 692b7579f77SDag-Erling Smørgrav } 693b7579f77SDag-Erling Smørgrav return 0; 694b7579f77SDag-Erling Smørgrav } 695b7579f77SDag-Erling Smørgrav 696b7579f77SDag-Erling Smørgrav int 697b7579f77SDag-Erling Smørgrav dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2) 698b7579f77SDag-Erling Smørgrav { 699b7579f77SDag-Erling Smørgrav return dname_strict_subdomain(d1, dname_count_labels(d1), d2, 700b7579f77SDag-Erling Smørgrav dname_count_labels(d2)); 701b7579f77SDag-Erling Smørgrav } 702b7579f77SDag-Erling Smørgrav 703b7579f77SDag-Erling Smørgrav int 704b7579f77SDag-Erling Smørgrav dname_subdomain_c(uint8_t* d1, uint8_t* d2) 705b7579f77SDag-Erling Smørgrav { 706b7579f77SDag-Erling Smørgrav int m; 707b7579f77SDag-Erling Smørgrav /* check subdomain: d1: www.example.com. and d2: example.com. */ 708b7579f77SDag-Erling Smørgrav /* or d1: example.com. and d2: example.com. */ 709b7579f77SDag-Erling Smørgrav int labs1 = dname_count_labels(d1); 710b7579f77SDag-Erling Smørgrav int labs2 = dname_count_labels(d2); 711b7579f77SDag-Erling Smørgrav if(labs2 > labs1) 712b7579f77SDag-Erling Smørgrav return 0; 713b7579f77SDag-Erling Smørgrav if(dname_lab_cmp(d1, labs1, d2, labs2, &m) < 0) { 714b7579f77SDag-Erling Smørgrav /* must have been example.com , www.example.com - wrong */ 715b7579f77SDag-Erling Smørgrav /* or otherwise different dnames */ 716b7579f77SDag-Erling Smørgrav return 0; 717b7579f77SDag-Erling Smørgrav } 718b7579f77SDag-Erling Smørgrav return (m == labs2); 719b7579f77SDag-Erling Smørgrav } 720b7579f77SDag-Erling Smørgrav 721b7579f77SDag-Erling Smørgrav int 722b7579f77SDag-Erling Smørgrav dname_is_root(uint8_t* dname) 723b7579f77SDag-Erling Smørgrav { 724b7579f77SDag-Erling Smørgrav uint8_t len; 725b7579f77SDag-Erling Smørgrav log_assert(dname); 726b7579f77SDag-Erling Smørgrav len = dname[0]; 727b7579f77SDag-Erling Smørgrav log_assert(!LABEL_IS_PTR(len)); 728b7579f77SDag-Erling Smørgrav return (len == 0); 729b7579f77SDag-Erling Smørgrav } 730b7579f77SDag-Erling Smørgrav 731b7579f77SDag-Erling Smørgrav void 732b7579f77SDag-Erling Smørgrav dname_remove_label(uint8_t** dname, size_t* len) 733b7579f77SDag-Erling Smørgrav { 734b7579f77SDag-Erling Smørgrav size_t lablen; 735b7579f77SDag-Erling Smørgrav log_assert(dname && *dname && len); 736b7579f77SDag-Erling Smørgrav lablen = (*dname)[0]; 737b7579f77SDag-Erling Smørgrav log_assert(!LABEL_IS_PTR(lablen)); 738b7579f77SDag-Erling Smørgrav log_assert(*len > lablen); 739b7579f77SDag-Erling Smørgrav if(lablen == 0) 740b7579f77SDag-Erling Smørgrav return; /* do not modify root label */ 741b7579f77SDag-Erling Smørgrav *len -= lablen+1; 742b7579f77SDag-Erling Smørgrav *dname += lablen+1; 743b7579f77SDag-Erling Smørgrav } 744b7579f77SDag-Erling Smørgrav 745b7579f77SDag-Erling Smørgrav void 746b7579f77SDag-Erling Smørgrav dname_remove_labels(uint8_t** dname, size_t* len, int n) 747b7579f77SDag-Erling Smørgrav { 748b7579f77SDag-Erling Smørgrav int i; 749b7579f77SDag-Erling Smørgrav for(i=0; i<n; i++) 750b7579f77SDag-Erling Smørgrav dname_remove_label(dname, len); 751b7579f77SDag-Erling Smørgrav } 752b7579f77SDag-Erling Smørgrav 753b7579f77SDag-Erling Smørgrav int 754b7579f77SDag-Erling Smørgrav dname_signame_label_count(uint8_t* dname) 755b7579f77SDag-Erling Smørgrav { 756b7579f77SDag-Erling Smørgrav uint8_t lablen; 757b7579f77SDag-Erling Smørgrav int count = 0; 758b7579f77SDag-Erling Smørgrav if(!*dname) 759b7579f77SDag-Erling Smørgrav return 0; 760b7579f77SDag-Erling Smørgrav if(dname[0] == 1 && dname[1] == '*') 761b7579f77SDag-Erling Smørgrav dname += 2; 762b7579f77SDag-Erling Smørgrav lablen = dname[0]; 763b7579f77SDag-Erling Smørgrav while(lablen) { 764b7579f77SDag-Erling Smørgrav count++; 765b7579f77SDag-Erling Smørgrav dname += lablen; 766b7579f77SDag-Erling Smørgrav dname += 1; 767b7579f77SDag-Erling Smørgrav lablen = dname[0]; 768b7579f77SDag-Erling Smørgrav } 769b7579f77SDag-Erling Smørgrav return count; 770b7579f77SDag-Erling Smørgrav } 771b7579f77SDag-Erling Smørgrav 772b7579f77SDag-Erling Smørgrav int 773b7579f77SDag-Erling Smørgrav dname_is_wild(uint8_t* dname) 774b7579f77SDag-Erling Smørgrav { 775b7579f77SDag-Erling Smørgrav return (dname[0] == 1 && dname[1] == '*'); 776b7579f77SDag-Erling Smørgrav } 777b7579f77SDag-Erling Smørgrav 778b7579f77SDag-Erling Smørgrav /** 779b7579f77SDag-Erling Smørgrav * Compare labels in memory, lowercase while comparing. 780b7579f77SDag-Erling Smørgrav * Returns canonical order for labels. If all is equal, the 781b7579f77SDag-Erling Smørgrav * shortest is first. 782b7579f77SDag-Erling Smørgrav * 783b7579f77SDag-Erling Smørgrav * @param p1: label 1 784b7579f77SDag-Erling Smørgrav * @param len1: length of label 1. 785b7579f77SDag-Erling Smørgrav * @param p2: label 2 786b7579f77SDag-Erling Smørgrav * @param len2: length of label 2. 787b7579f77SDag-Erling Smørgrav * @return: 0, -1, +1 comparison result. 788b7579f77SDag-Erling Smørgrav */ 789b7579f77SDag-Erling Smørgrav static int 790b7579f77SDag-Erling Smørgrav memcanoncmp(uint8_t* p1, uint8_t len1, uint8_t* p2, uint8_t len2) 791b7579f77SDag-Erling Smørgrav { 792b7579f77SDag-Erling Smørgrav uint8_t min = (len1<len2)?len1:len2; 793b7579f77SDag-Erling Smørgrav int c = memlowercmp(p1, p2, min); 794b7579f77SDag-Erling Smørgrav if(c != 0) 795b7579f77SDag-Erling Smørgrav return c; 796b7579f77SDag-Erling Smørgrav /* equal, see who is shortest */ 797b7579f77SDag-Erling Smørgrav if(len1 < len2) 798b7579f77SDag-Erling Smørgrav return -1; 799b7579f77SDag-Erling Smørgrav if(len1 > len2) 800b7579f77SDag-Erling Smørgrav return 1; 801b7579f77SDag-Erling Smørgrav return 0; 802b7579f77SDag-Erling Smørgrav } 803b7579f77SDag-Erling Smørgrav 804b7579f77SDag-Erling Smørgrav 805b7579f77SDag-Erling Smørgrav int 806b7579f77SDag-Erling Smørgrav dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs) 807b7579f77SDag-Erling Smørgrav { 808b7579f77SDag-Erling Smørgrav /* like dname_lab_cmp, but with different label comparison, 809b7579f77SDag-Erling Smørgrav * empty character sorts before \000. 810b7579f77SDag-Erling Smørgrav * So ylyly is before z. */ 811b7579f77SDag-Erling Smørgrav uint8_t len1, len2; 812b7579f77SDag-Erling Smørgrav int atlabel = labs1; 813b7579f77SDag-Erling Smørgrav int lastmlabs; 814b7579f77SDag-Erling Smørgrav int lastdiff = 0; 815b7579f77SDag-Erling Smørgrav int c; 816b7579f77SDag-Erling Smørgrav /* first skip so that we compare same label. */ 817b7579f77SDag-Erling Smørgrav if(labs1 > labs2) { 818b7579f77SDag-Erling Smørgrav while(atlabel > labs2) { 819b7579f77SDag-Erling Smørgrav len1 = *d1++; 820b7579f77SDag-Erling Smørgrav d1 += len1; 821b7579f77SDag-Erling Smørgrav atlabel--; 822b7579f77SDag-Erling Smørgrav } 823b7579f77SDag-Erling Smørgrav log_assert(atlabel == labs2); 824b7579f77SDag-Erling Smørgrav } else if(labs1 < labs2) { 825b7579f77SDag-Erling Smørgrav atlabel = labs2; 826b7579f77SDag-Erling Smørgrav while(atlabel > labs1) { 827b7579f77SDag-Erling Smørgrav len2 = *d2++; 828b7579f77SDag-Erling Smørgrav d2 += len2; 829b7579f77SDag-Erling Smørgrav atlabel--; 830b7579f77SDag-Erling Smørgrav } 831b7579f77SDag-Erling Smørgrav log_assert(atlabel == labs1); 832b7579f77SDag-Erling Smørgrav } 833b7579f77SDag-Erling Smørgrav lastmlabs = atlabel+1; 834b7579f77SDag-Erling Smørgrav /* now at same label in d1 and d2, atlabel */ 835b7579f77SDag-Erling Smørgrav /* www.example.com. */ 836b7579f77SDag-Erling Smørgrav /* 4 3 2 1 atlabel number */ 837b7579f77SDag-Erling Smørgrav /* repeat until at root label (which is always the same) */ 838b7579f77SDag-Erling Smørgrav while(atlabel > 1) { 839b7579f77SDag-Erling Smørgrav len1 = *d1++; 840b7579f77SDag-Erling Smørgrav len2 = *d2++; 841b7579f77SDag-Erling Smørgrav 842b7579f77SDag-Erling Smørgrav if((c=memcanoncmp(d1, len1, d2, len2)) != 0) { 843b7579f77SDag-Erling Smørgrav if(c<0) 844b7579f77SDag-Erling Smørgrav lastdiff = -1; 845b7579f77SDag-Erling Smørgrav else lastdiff = 1; 846b7579f77SDag-Erling Smørgrav lastmlabs = atlabel; 847b7579f77SDag-Erling Smørgrav } 848b7579f77SDag-Erling Smørgrav 849b7579f77SDag-Erling Smørgrav d1 += len1; 850b7579f77SDag-Erling Smørgrav d2 += len2; 851b7579f77SDag-Erling Smørgrav atlabel--; 852b7579f77SDag-Erling Smørgrav } 853b7579f77SDag-Erling Smørgrav /* last difference atlabel number, so number of labels matching, 854b7579f77SDag-Erling Smørgrav * at the right side, is one less. */ 855b7579f77SDag-Erling Smørgrav *mlabs = lastmlabs-1; 856b7579f77SDag-Erling Smørgrav if(lastdiff == 0) { 857b7579f77SDag-Erling Smørgrav /* all labels compared were equal, check if one has more 858b7579f77SDag-Erling Smørgrav * labels, so that example.com. > com. */ 859b7579f77SDag-Erling Smørgrav if(labs1 > labs2) 860b7579f77SDag-Erling Smørgrav return 1; 861b7579f77SDag-Erling Smørgrav else if(labs1 < labs2) 862b7579f77SDag-Erling Smørgrav return -1; 863b7579f77SDag-Erling Smørgrav } 864b7579f77SDag-Erling Smørgrav return lastdiff; 865b7579f77SDag-Erling Smørgrav } 866b7579f77SDag-Erling Smørgrav 867b7579f77SDag-Erling Smørgrav int 868b7579f77SDag-Erling Smørgrav dname_canonical_compare(uint8_t* d1, uint8_t* d2) 869b7579f77SDag-Erling Smørgrav { 870b7579f77SDag-Erling Smørgrav int labs1, labs2, m; 871b7579f77SDag-Erling Smørgrav labs1 = dname_count_labels(d1); 872b7579f77SDag-Erling Smørgrav labs2 = dname_count_labels(d2); 873b7579f77SDag-Erling Smørgrav return dname_canon_lab_cmp(d1, labs1, d2, labs2, &m); 874b7579f77SDag-Erling Smørgrav } 875b7579f77SDag-Erling Smørgrav 876b7579f77SDag-Erling Smørgrav uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2) 877b7579f77SDag-Erling Smørgrav { 878b7579f77SDag-Erling Smørgrav int labs1, labs2, m; 879b7579f77SDag-Erling Smørgrav size_t len = LDNS_MAX_DOMAINLEN; 880b7579f77SDag-Erling Smørgrav labs1 = dname_count_labels(d1); 881b7579f77SDag-Erling Smørgrav labs2 = dname_count_labels(d2); 882b7579f77SDag-Erling Smørgrav (void)dname_lab_cmp(d1, labs1, d2, labs2, &m); 883b7579f77SDag-Erling Smørgrav dname_remove_labels(&d1, &len, labs1-m); 884b7579f77SDag-Erling Smørgrav return d1; 885b7579f77SDag-Erling Smørgrav } 886