1*eaad808eSchristos /* 2*eaad808eSchristos * util/data/dname.h - domain name handling 3*eaad808eSchristos * 4*eaad808eSchristos * Copyright (c) 2007, NLnet Labs. All rights reserved. 5*eaad808eSchristos * 6*eaad808eSchristos * This software is open source. 7*eaad808eSchristos * 8*eaad808eSchristos * Redistribution and use in source and binary forms, with or without 9*eaad808eSchristos * modification, are permitted provided that the following conditions 10*eaad808eSchristos * are met: 11*eaad808eSchristos * 12*eaad808eSchristos * Redistributions of source code must retain the above copyright notice, 13*eaad808eSchristos * this list of conditions and the following disclaimer. 14*eaad808eSchristos * 15*eaad808eSchristos * Redistributions in binary form must reproduce the above copyright notice, 16*eaad808eSchristos * this list of conditions and the following disclaimer in the documentation 17*eaad808eSchristos * and/or other materials provided with the distribution. 18*eaad808eSchristos * 19*eaad808eSchristos * Neither the name of the NLNET LABS nor the names of its contributors may 20*eaad808eSchristos * be used to endorse or promote products derived from this software without 21*eaad808eSchristos * specific prior written permission. 22*eaad808eSchristos * 23*eaad808eSchristos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24*eaad808eSchristos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25*eaad808eSchristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26*eaad808eSchristos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27*eaad808eSchristos * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28*eaad808eSchristos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29*eaad808eSchristos * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30*eaad808eSchristos * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31*eaad808eSchristos * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32*eaad808eSchristos * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33*eaad808eSchristos * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34*eaad808eSchristos */ 35*eaad808eSchristos 36*eaad808eSchristos /** 37*eaad808eSchristos * \file 38*eaad808eSchristos * 39*eaad808eSchristos * This file contains domain name handling functions. 40*eaad808eSchristos */ 41*eaad808eSchristos 42*eaad808eSchristos #include "config.h" 43*eaad808eSchristos #include <ctype.h> 44*eaad808eSchristos #include "util/data/dname.h" 45*eaad808eSchristos #include "util/data/msgparse.h" 46*eaad808eSchristos #include "util/log.h" 47*eaad808eSchristos #include "util/storage/lookup3.h" 48*eaad808eSchristos #include "sldns/sbuffer.h" 49*eaad808eSchristos 50*eaad808eSchristos /* determine length of a dname in buffer, no compression pointers allowed */ 51*eaad808eSchristos size_t 52*eaad808eSchristos query_dname_len(sldns_buffer* query) 53*eaad808eSchristos { 54*eaad808eSchristos size_t len = 0; 55*eaad808eSchristos size_t labellen; 56*eaad808eSchristos while(1) { 57*eaad808eSchristos if(sldns_buffer_remaining(query) < 1) 58*eaad808eSchristos return 0; /* parse error, need label len */ 59*eaad808eSchristos labellen = sldns_buffer_read_u8(query); 60*eaad808eSchristos if(labellen&0xc0) 61*eaad808eSchristos return 0; /* no compression allowed in queries */ 62*eaad808eSchristos len += labellen + 1; 63*eaad808eSchristos if(len > LDNS_MAX_DOMAINLEN) 64*eaad808eSchristos return 0; /* too long */ 65*eaad808eSchristos if(labellen == 0) 66*eaad808eSchristos return len; 67*eaad808eSchristos if(sldns_buffer_remaining(query) < labellen) 68*eaad808eSchristos return 0; /* parse error, need content */ 69*eaad808eSchristos sldns_buffer_skip(query, (ssize_t)labellen); 70*eaad808eSchristos } 71*eaad808eSchristos } 72*eaad808eSchristos 73*eaad808eSchristos size_t 74*eaad808eSchristos dname_valid(uint8_t* dname, size_t maxlen) 75*eaad808eSchristos { 76*eaad808eSchristos size_t len = 0; 77*eaad808eSchristos size_t labellen; 78*eaad808eSchristos labellen = *dname++; 79*eaad808eSchristos while(labellen) { 80*eaad808eSchristos if(labellen&0xc0) 81*eaad808eSchristos return 0; /* no compression ptrs allowed */ 82*eaad808eSchristos len += labellen + 1; 83*eaad808eSchristos if(len >= LDNS_MAX_DOMAINLEN) 84*eaad808eSchristos return 0; /* too long */ 85*eaad808eSchristos if(len > maxlen) 86*eaad808eSchristos return 0; /* does not fit in memory allocation */ 87*eaad808eSchristos dname += labellen; 88*eaad808eSchristos labellen = *dname++; 89*eaad808eSchristos } 90*eaad808eSchristos len += 1; 91*eaad808eSchristos if(len > maxlen) 92*eaad808eSchristos return 0; /* does not fit in memory allocation */ 93*eaad808eSchristos return len; 94*eaad808eSchristos } 95*eaad808eSchristos 96*eaad808eSchristos /** compare uncompressed, noncanonical, registers are hints for speed */ 97*eaad808eSchristos int 98*eaad808eSchristos query_dname_compare(register uint8_t* d1, register uint8_t* d2) 99*eaad808eSchristos { 100*eaad808eSchristos register uint8_t lab1, lab2; 101*eaad808eSchristos log_assert(d1 && d2); 102*eaad808eSchristos lab1 = *d1++; 103*eaad808eSchristos lab2 = *d2++; 104*eaad808eSchristos while( lab1 != 0 || lab2 != 0 ) { 105*eaad808eSchristos /* compare label length */ 106*eaad808eSchristos /* if one dname ends, it has labellength 0 */ 107*eaad808eSchristos if(lab1 != lab2) { 108*eaad808eSchristos if(lab1 < lab2) 109*eaad808eSchristos return -1; 110*eaad808eSchristos return 1; 111*eaad808eSchristos } 112*eaad808eSchristos log_assert(lab1 == lab2 && lab1 != 0); 113*eaad808eSchristos /* compare lowercased labels. */ 114*eaad808eSchristos while(lab1--) { 115*eaad808eSchristos /* compare bytes first for speed */ 116*eaad808eSchristos if(*d1 != *d2 && 117*eaad808eSchristos tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) { 118*eaad808eSchristos if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2)) 119*eaad808eSchristos return -1; 120*eaad808eSchristos return 1; 121*eaad808eSchristos } 122*eaad808eSchristos d1++; 123*eaad808eSchristos d2++; 124*eaad808eSchristos } 125*eaad808eSchristos /* next pair of labels. */ 126*eaad808eSchristos lab1 = *d1++; 127*eaad808eSchristos lab2 = *d2++; 128*eaad808eSchristos } 129*eaad808eSchristos return 0; 130*eaad808eSchristos } 131*eaad808eSchristos 132*eaad808eSchristos void 133*eaad808eSchristos query_dname_tolower(uint8_t* dname) 134*eaad808eSchristos { 135*eaad808eSchristos /* the dname is stored uncompressed */ 136*eaad808eSchristos uint8_t labellen; 137*eaad808eSchristos labellen = *dname; 138*eaad808eSchristos while(labellen) { 139*eaad808eSchristos dname++; 140*eaad808eSchristos while(labellen--) { 141*eaad808eSchristos *dname = (uint8_t)tolower((unsigned char)*dname); 142*eaad808eSchristos dname++; 143*eaad808eSchristos } 144*eaad808eSchristos labellen = *dname; 145*eaad808eSchristos } 146*eaad808eSchristos } 147*eaad808eSchristos 148*eaad808eSchristos void 149*eaad808eSchristos pkt_dname_tolower(sldns_buffer* pkt, uint8_t* dname) 150*eaad808eSchristos { 151*eaad808eSchristos uint8_t lablen; 152*eaad808eSchristos int count = 0; 153*eaad808eSchristos if(dname >= sldns_buffer_end(pkt)) 154*eaad808eSchristos return; 155*eaad808eSchristos lablen = *dname++; 156*eaad808eSchristos while(lablen) { 157*eaad808eSchristos if(LABEL_IS_PTR(lablen)) { 158*eaad808eSchristos if((size_t)PTR_OFFSET(lablen, *dname) 159*eaad808eSchristos >= sldns_buffer_limit(pkt)) 160*eaad808eSchristos return; 161*eaad808eSchristos dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); 162*eaad808eSchristos lablen = *dname++; 163*eaad808eSchristos if(count++ > MAX_COMPRESS_PTRS) 164*eaad808eSchristos return; 165*eaad808eSchristos continue; 166*eaad808eSchristos } 167*eaad808eSchristos if(dname+lablen >= sldns_buffer_end(pkt)) 168*eaad808eSchristos return; 169*eaad808eSchristos while(lablen--) { 170*eaad808eSchristos *dname = (uint8_t)tolower((unsigned char)*dname); 171*eaad808eSchristos dname++; 172*eaad808eSchristos } 173*eaad808eSchristos if(dname >= sldns_buffer_end(pkt)) 174*eaad808eSchristos return; 175*eaad808eSchristos lablen = *dname++; 176*eaad808eSchristos } 177*eaad808eSchristos } 178*eaad808eSchristos 179*eaad808eSchristos 180*eaad808eSchristos size_t 181*eaad808eSchristos pkt_dname_len(sldns_buffer* pkt) 182*eaad808eSchristos { 183*eaad808eSchristos size_t len = 0; 184*eaad808eSchristos int ptrcount = 0; 185*eaad808eSchristos uint8_t labellen; 186*eaad808eSchristos size_t endpos = 0; 187*eaad808eSchristos 188*eaad808eSchristos /* read dname and determine length */ 189*eaad808eSchristos /* check compression pointers, loops, out of bounds */ 190*eaad808eSchristos while(1) { 191*eaad808eSchristos /* read next label */ 192*eaad808eSchristos if(sldns_buffer_remaining(pkt) < 1) 193*eaad808eSchristos return 0; 194*eaad808eSchristos labellen = sldns_buffer_read_u8(pkt); 195*eaad808eSchristos if(LABEL_IS_PTR(labellen)) { 196*eaad808eSchristos /* compression ptr */ 197*eaad808eSchristos uint16_t ptr; 198*eaad808eSchristos if(sldns_buffer_remaining(pkt) < 1) 199*eaad808eSchristos return 0; 200*eaad808eSchristos ptr = PTR_OFFSET(labellen, sldns_buffer_read_u8(pkt)); 201*eaad808eSchristos if(ptrcount++ > MAX_COMPRESS_PTRS) 202*eaad808eSchristos return 0; /* loop! */ 203*eaad808eSchristos if(sldns_buffer_limit(pkt) <= ptr) 204*eaad808eSchristos return 0; /* out of bounds! */ 205*eaad808eSchristos if(!endpos) 206*eaad808eSchristos endpos = sldns_buffer_position(pkt); 207*eaad808eSchristos sldns_buffer_set_position(pkt, ptr); 208*eaad808eSchristos } else { 209*eaad808eSchristos /* label contents */ 210*eaad808eSchristos if(labellen > 0x3f) 211*eaad808eSchristos return 0; /* label too long */ 212*eaad808eSchristos len += 1 + labellen; 213*eaad808eSchristos if(len > LDNS_MAX_DOMAINLEN) 214*eaad808eSchristos return 0; 215*eaad808eSchristos if(labellen == 0) { 216*eaad808eSchristos /* end of dname */ 217*eaad808eSchristos break; 218*eaad808eSchristos } 219*eaad808eSchristos if(sldns_buffer_remaining(pkt) < labellen) 220*eaad808eSchristos return 0; 221*eaad808eSchristos sldns_buffer_skip(pkt, (ssize_t)labellen); 222*eaad808eSchristos } 223*eaad808eSchristos } 224*eaad808eSchristos if(endpos) 225*eaad808eSchristos sldns_buffer_set_position(pkt, endpos); 226*eaad808eSchristos 227*eaad808eSchristos return len; 228*eaad808eSchristos } 229*eaad808eSchristos 230*eaad808eSchristos int 231*eaad808eSchristos dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2) 232*eaad808eSchristos { 233*eaad808eSchristos uint8_t len1, len2; 234*eaad808eSchristos log_assert(pkt && d1 && d2); 235*eaad808eSchristos len1 = *d1++; 236*eaad808eSchristos len2 = *d2++; 237*eaad808eSchristos while( len1 != 0 || len2 != 0 ) { 238*eaad808eSchristos /* resolve ptrs */ 239*eaad808eSchristos if(LABEL_IS_PTR(len1)) { 240*eaad808eSchristos d1 = sldns_buffer_at(pkt, PTR_OFFSET(len1, *d1)); 241*eaad808eSchristos len1 = *d1++; 242*eaad808eSchristos continue; 243*eaad808eSchristos } 244*eaad808eSchristos if(LABEL_IS_PTR(len2)) { 245*eaad808eSchristos d2 = sldns_buffer_at(pkt, PTR_OFFSET(len2, *d2)); 246*eaad808eSchristos len2 = *d2++; 247*eaad808eSchristos continue; 248*eaad808eSchristos } 249*eaad808eSchristos /* check label length */ 250*eaad808eSchristos log_assert(len1 <= LDNS_MAX_LABELLEN); 251*eaad808eSchristos log_assert(len2 <= LDNS_MAX_LABELLEN); 252*eaad808eSchristos if(len1 != len2) { 253*eaad808eSchristos if(len1 < len2) return -1; 254*eaad808eSchristos return 1; 255*eaad808eSchristos } 256*eaad808eSchristos log_assert(len1 == len2 && len1 != 0); 257*eaad808eSchristos /* compare labels */ 258*eaad808eSchristos while(len1--) { 259*eaad808eSchristos if(tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) { 260*eaad808eSchristos if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2)) 261*eaad808eSchristos return -1; 262*eaad808eSchristos return 1; 263*eaad808eSchristos } 264*eaad808eSchristos d1++; 265*eaad808eSchristos d2++; 266*eaad808eSchristos } 267*eaad808eSchristos len1 = *d1++; 268*eaad808eSchristos len2 = *d2++; 269*eaad808eSchristos } 270*eaad808eSchristos return 0; 271*eaad808eSchristos } 272*eaad808eSchristos 273*eaad808eSchristos hashvalue_t 274*eaad808eSchristos dname_query_hash(uint8_t* dname, hashvalue_t h) 275*eaad808eSchristos { 276*eaad808eSchristos uint8_t labuf[LDNS_MAX_LABELLEN+1]; 277*eaad808eSchristos uint8_t lablen; 278*eaad808eSchristos int i; 279*eaad808eSchristos 280*eaad808eSchristos /* preserve case of query, make hash label by label */ 281*eaad808eSchristos lablen = *dname++; 282*eaad808eSchristos while(lablen) { 283*eaad808eSchristos log_assert(lablen <= LDNS_MAX_LABELLEN); 284*eaad808eSchristos labuf[0] = lablen; 285*eaad808eSchristos i=0; 286*eaad808eSchristos while(lablen--) { 287*eaad808eSchristos labuf[++i] = (uint8_t)tolower((unsigned char)*dname); 288*eaad808eSchristos dname++; 289*eaad808eSchristos } 290*eaad808eSchristos h = hashlittle(labuf, labuf[0] + 1, h); 291*eaad808eSchristos lablen = *dname++; 292*eaad808eSchristos } 293*eaad808eSchristos 294*eaad808eSchristos return h; 295*eaad808eSchristos } 296*eaad808eSchristos 297*eaad808eSchristos hashvalue_t 298*eaad808eSchristos dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_t h) 299*eaad808eSchristos { 300*eaad808eSchristos uint8_t labuf[LDNS_MAX_LABELLEN+1]; 301*eaad808eSchristos uint8_t lablen; 302*eaad808eSchristos int i; 303*eaad808eSchristos 304*eaad808eSchristos /* preserve case of query, make hash label by label */ 305*eaad808eSchristos lablen = *dname++; 306*eaad808eSchristos while(lablen) { 307*eaad808eSchristos if(LABEL_IS_PTR(lablen)) { 308*eaad808eSchristos /* follow pointer */ 309*eaad808eSchristos dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); 310*eaad808eSchristos lablen = *dname++; 311*eaad808eSchristos continue; 312*eaad808eSchristos } 313*eaad808eSchristos log_assert(lablen <= LDNS_MAX_LABELLEN); 314*eaad808eSchristos labuf[0] = lablen; 315*eaad808eSchristos i=0; 316*eaad808eSchristos while(lablen--) { 317*eaad808eSchristos labuf[++i] = (uint8_t)tolower((unsigned char)*dname); 318*eaad808eSchristos dname++; 319*eaad808eSchristos } 320*eaad808eSchristos h = hashlittle(labuf, labuf[0] + 1, h); 321*eaad808eSchristos lablen = *dname++; 322*eaad808eSchristos } 323*eaad808eSchristos 324*eaad808eSchristos return h; 325*eaad808eSchristos } 326*eaad808eSchristos 327*eaad808eSchristos void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname) 328*eaad808eSchristos { 329*eaad808eSchristos /* copy over the dname and decompress it at the same time */ 330*eaad808eSchristos size_t len = 0; 331*eaad808eSchristos uint8_t lablen; 332*eaad808eSchristos lablen = *dname++; 333*eaad808eSchristos while(lablen) { 334*eaad808eSchristos if(LABEL_IS_PTR(lablen)) { 335*eaad808eSchristos /* follow pointer */ 336*eaad808eSchristos dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); 337*eaad808eSchristos lablen = *dname++; 338*eaad808eSchristos continue; 339*eaad808eSchristos } 340*eaad808eSchristos log_assert(lablen <= LDNS_MAX_LABELLEN); 341*eaad808eSchristos len += (size_t)lablen+1; 342*eaad808eSchristos if(len >= LDNS_MAX_DOMAINLEN) { 343*eaad808eSchristos *to = 0; /* end the result prematurely */ 344*eaad808eSchristos log_err("bad dname in dname_pkt_copy"); 345*eaad808eSchristos return; 346*eaad808eSchristos } 347*eaad808eSchristos *to++ = lablen; 348*eaad808eSchristos memmove(to, dname, lablen); 349*eaad808eSchristos dname += lablen; 350*eaad808eSchristos to += lablen; 351*eaad808eSchristos lablen = *dname++; 352*eaad808eSchristos } 353*eaad808eSchristos /* copy last \0 */ 354*eaad808eSchristos *to = 0; 355*eaad808eSchristos } 356*eaad808eSchristos 357*eaad808eSchristos void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname) 358*eaad808eSchristos { 359*eaad808eSchristos uint8_t lablen; 360*eaad808eSchristos if(!out) out = stdout; 361*eaad808eSchristos if(!dname) return; 362*eaad808eSchristos 363*eaad808eSchristos lablen = *dname++; 364*eaad808eSchristos if(!lablen) 365*eaad808eSchristos fputc('.', out); 366*eaad808eSchristos while(lablen) { 367*eaad808eSchristos if(LABEL_IS_PTR(lablen)) { 368*eaad808eSchristos /* follow pointer */ 369*eaad808eSchristos if(!pkt) { 370*eaad808eSchristos fputs("??compressionptr??", out); 371*eaad808eSchristos return; 372*eaad808eSchristos } 373*eaad808eSchristos dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); 374*eaad808eSchristos lablen = *dname++; 375*eaad808eSchristos continue; 376*eaad808eSchristos } 377*eaad808eSchristos if(lablen > LDNS_MAX_LABELLEN) { 378*eaad808eSchristos fputs("??extendedlabel??", out); 379*eaad808eSchristos return; 380*eaad808eSchristos } 381*eaad808eSchristos while(lablen--) 382*eaad808eSchristos fputc((int)*dname++, out); 383*eaad808eSchristos fputc('.', out); 384*eaad808eSchristos lablen = *dname++; 385*eaad808eSchristos } 386*eaad808eSchristos } 387*eaad808eSchristos 388*eaad808eSchristos int 389*eaad808eSchristos dname_count_labels(uint8_t* dname) 390*eaad808eSchristos { 391*eaad808eSchristos uint8_t lablen; 392*eaad808eSchristos int labs = 1; 393*eaad808eSchristos 394*eaad808eSchristos lablen = *dname++; 395*eaad808eSchristos while(lablen) { 396*eaad808eSchristos labs++; 397*eaad808eSchristos dname += lablen; 398*eaad808eSchristos lablen = *dname++; 399*eaad808eSchristos } 400*eaad808eSchristos return labs; 401*eaad808eSchristos } 402*eaad808eSchristos 403*eaad808eSchristos int 404*eaad808eSchristos dname_count_size_labels(uint8_t* dname, size_t* size) 405*eaad808eSchristos { 406*eaad808eSchristos uint8_t lablen; 407*eaad808eSchristos int labs = 1; 408*eaad808eSchristos size_t sz = 1; 409*eaad808eSchristos 410*eaad808eSchristos lablen = *dname++; 411*eaad808eSchristos while(lablen) { 412*eaad808eSchristos labs++; 413*eaad808eSchristos sz += lablen+1; 414*eaad808eSchristos dname += lablen; 415*eaad808eSchristos lablen = *dname++; 416*eaad808eSchristos } 417*eaad808eSchristos *size = sz; 418*eaad808eSchristos return labs; 419*eaad808eSchristos } 420*eaad808eSchristos 421*eaad808eSchristos /** 422*eaad808eSchristos * Compare labels in memory, lowercase while comparing. 423*eaad808eSchristos * @param p1: label 1 424*eaad808eSchristos * @param p2: label 2 425*eaad808eSchristos * @param len: number of bytes to compare. 426*eaad808eSchristos * @return: 0, -1, +1 comparison result. 427*eaad808eSchristos */ 428*eaad808eSchristos static int 429*eaad808eSchristos memlowercmp(uint8_t* p1, uint8_t* p2, uint8_t len) 430*eaad808eSchristos { 431*eaad808eSchristos while(len--) { 432*eaad808eSchristos if(*p1 != *p2 && tolower((unsigned char)*p1) != tolower((unsigned char)*p2)) { 433*eaad808eSchristos if(tolower((unsigned char)*p1) < tolower((unsigned char)*p2)) 434*eaad808eSchristos return -1; 435*eaad808eSchristos return 1; 436*eaad808eSchristos } 437*eaad808eSchristos p1++; 438*eaad808eSchristos p2++; 439*eaad808eSchristos } 440*eaad808eSchristos return 0; 441*eaad808eSchristos } 442*eaad808eSchristos 443*eaad808eSchristos int 444*eaad808eSchristos dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs) 445*eaad808eSchristos { 446*eaad808eSchristos uint8_t len1, len2; 447*eaad808eSchristos int atlabel = labs1; 448*eaad808eSchristos int lastmlabs; 449*eaad808eSchristos int lastdiff = 0; 450*eaad808eSchristos /* first skip so that we compare same label. */ 451*eaad808eSchristos if(labs1 > labs2) { 452*eaad808eSchristos while(atlabel > labs2) { 453*eaad808eSchristos len1 = *d1++; 454*eaad808eSchristos d1 += len1; 455*eaad808eSchristos atlabel--; 456*eaad808eSchristos } 457*eaad808eSchristos log_assert(atlabel == labs2); 458*eaad808eSchristos } else if(labs1 < labs2) { 459*eaad808eSchristos atlabel = labs2; 460*eaad808eSchristos while(atlabel > labs1) { 461*eaad808eSchristos len2 = *d2++; 462*eaad808eSchristos d2 += len2; 463*eaad808eSchristos atlabel--; 464*eaad808eSchristos } 465*eaad808eSchristos log_assert(atlabel == labs1); 466*eaad808eSchristos } 467*eaad808eSchristos lastmlabs = atlabel+1; 468*eaad808eSchristos /* now at same label in d1 and d2, atlabel */ 469*eaad808eSchristos /* www.example.com. */ 470*eaad808eSchristos /* 4 3 2 1 atlabel number */ 471*eaad808eSchristos /* repeat until at root label (which is always the same) */ 472*eaad808eSchristos while(atlabel > 1) { 473*eaad808eSchristos len1 = *d1++; 474*eaad808eSchristos len2 = *d2++; 475*eaad808eSchristos if(len1 != len2) { 476*eaad808eSchristos log_assert(len1 != 0 && len2 != 0); 477*eaad808eSchristos if(len1<len2) 478*eaad808eSchristos lastdiff = -1; 479*eaad808eSchristos else lastdiff = 1; 480*eaad808eSchristos lastmlabs = atlabel; 481*eaad808eSchristos d1 += len1; 482*eaad808eSchristos d2 += len2; 483*eaad808eSchristos } else { 484*eaad808eSchristos /* memlowercmp is inlined here; or just like 485*eaad808eSchristos * if((c=memlowercmp(d1, d2, len1)) != 0) { 486*eaad808eSchristos * lastdiff = c; 487*eaad808eSchristos * lastmlabs = atlabel; } apart from d1++,d2++ */ 488*eaad808eSchristos while(len1) { 489*eaad808eSchristos if(*d1 != *d2 && tolower((unsigned char)*d1) 490*eaad808eSchristos != tolower((unsigned char)*d2)) { 491*eaad808eSchristos if(tolower((unsigned char)*d1) < 492*eaad808eSchristos tolower((unsigned char)*d2)) { 493*eaad808eSchristos lastdiff = -1; 494*eaad808eSchristos lastmlabs = atlabel; 495*eaad808eSchristos d1 += len1; 496*eaad808eSchristos d2 += len1; 497*eaad808eSchristos break; 498*eaad808eSchristos } 499*eaad808eSchristos lastdiff = 1; 500*eaad808eSchristos lastmlabs = atlabel; 501*eaad808eSchristos d1 += len1; 502*eaad808eSchristos d2 += len1; 503*eaad808eSchristos break; /* out of memlowercmp */ 504*eaad808eSchristos } 505*eaad808eSchristos d1++; 506*eaad808eSchristos d2++; 507*eaad808eSchristos len1--; 508*eaad808eSchristos } 509*eaad808eSchristos } 510*eaad808eSchristos atlabel--; 511*eaad808eSchristos } 512*eaad808eSchristos /* last difference atlabel number, so number of labels matching, 513*eaad808eSchristos * at the right side, is one less. */ 514*eaad808eSchristos *mlabs = lastmlabs-1; 515*eaad808eSchristos if(lastdiff == 0) { 516*eaad808eSchristos /* all labels compared were equal, check if one has more 517*eaad808eSchristos * labels, so that example.com. > com. */ 518*eaad808eSchristos if(labs1 > labs2) 519*eaad808eSchristos return 1; 520*eaad808eSchristos else if(labs1 < labs2) 521*eaad808eSchristos return -1; 522*eaad808eSchristos } 523*eaad808eSchristos return lastdiff; 524*eaad808eSchristos } 525*eaad808eSchristos 526*eaad808eSchristos int 527*eaad808eSchristos dname_buffer_write(sldns_buffer* pkt, uint8_t* dname) 528*eaad808eSchristos { 529*eaad808eSchristos uint8_t lablen; 530*eaad808eSchristos 531*eaad808eSchristos if(sldns_buffer_remaining(pkt) < 1) 532*eaad808eSchristos return 0; 533*eaad808eSchristos lablen = *dname++; 534*eaad808eSchristos sldns_buffer_write_u8(pkt, lablen); 535*eaad808eSchristos while(lablen) { 536*eaad808eSchristos if(sldns_buffer_remaining(pkt) < (size_t)lablen+1) 537*eaad808eSchristos return 0; 538*eaad808eSchristos sldns_buffer_write(pkt, dname, lablen); 539*eaad808eSchristos dname += lablen; 540*eaad808eSchristos lablen = *dname++; 541*eaad808eSchristos sldns_buffer_write_u8(pkt, lablen); 542*eaad808eSchristos } 543*eaad808eSchristos return 1; 544*eaad808eSchristos } 545*eaad808eSchristos 546*eaad808eSchristos void dname_str(uint8_t* dname, char* str) 547*eaad808eSchristos { 548*eaad808eSchristos size_t len = 0; 549*eaad808eSchristos uint8_t lablen = 0; 550*eaad808eSchristos char* s = str; 551*eaad808eSchristos if(!dname || !*dname) { 552*eaad808eSchristos *s++ = '.'; 553*eaad808eSchristos *s = 0; 554*eaad808eSchristos return; 555*eaad808eSchristos } 556*eaad808eSchristos lablen = *dname++; 557*eaad808eSchristos while(lablen) { 558*eaad808eSchristos if(lablen > LDNS_MAX_LABELLEN) { 559*eaad808eSchristos *s++ = '#'; 560*eaad808eSchristos *s = 0; 561*eaad808eSchristos return; 562*eaad808eSchristos } 563*eaad808eSchristos len += lablen+1; 564*eaad808eSchristos if(len >= LDNS_MAX_DOMAINLEN-1) { 565*eaad808eSchristos *s++ = '&'; 566*eaad808eSchristos *s = 0; 567*eaad808eSchristos return; 568*eaad808eSchristos } 569*eaad808eSchristos while(lablen--) { 570*eaad808eSchristos if(isalnum((unsigned char)*dname) 571*eaad808eSchristos || *dname == '-' || *dname == '_' 572*eaad808eSchristos || *dname == '*') 573*eaad808eSchristos *s++ = *(char*)dname++; 574*eaad808eSchristos else { 575*eaad808eSchristos *s++ = '?'; 576*eaad808eSchristos dname++; 577*eaad808eSchristos } 578*eaad808eSchristos } 579*eaad808eSchristos *s++ = '.'; 580*eaad808eSchristos lablen = *dname++; 581*eaad808eSchristos } 582*eaad808eSchristos *s = 0; 583*eaad808eSchristos } 584*eaad808eSchristos 585*eaad808eSchristos int 586*eaad808eSchristos dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2) 587*eaad808eSchristos { 588*eaad808eSchristos int m; 589*eaad808eSchristos /* check subdomain: d1: www.example.com. and d2: example.com. */ 590*eaad808eSchristos if(labs2 >= labs1) 591*eaad808eSchristos return 0; 592*eaad808eSchristos if(dname_lab_cmp(d1, labs1, d2, labs2, &m) > 0) { 593*eaad808eSchristos /* subdomain if all labels match */ 594*eaad808eSchristos return (m == labs2); 595*eaad808eSchristos } 596*eaad808eSchristos return 0; 597*eaad808eSchristos } 598*eaad808eSchristos 599*eaad808eSchristos int 600*eaad808eSchristos dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2) 601*eaad808eSchristos { 602*eaad808eSchristos return dname_strict_subdomain(d1, dname_count_labels(d1), d2, 603*eaad808eSchristos dname_count_labels(d2)); 604*eaad808eSchristos } 605*eaad808eSchristos 606*eaad808eSchristos int 607*eaad808eSchristos dname_subdomain_c(uint8_t* d1, uint8_t* d2) 608*eaad808eSchristos { 609*eaad808eSchristos int m; 610*eaad808eSchristos /* check subdomain: d1: www.example.com. and d2: example.com. */ 611*eaad808eSchristos /* or d1: example.com. and d2: example.com. */ 612*eaad808eSchristos int labs1 = dname_count_labels(d1); 613*eaad808eSchristos int labs2 = dname_count_labels(d2); 614*eaad808eSchristos if(labs2 > labs1) 615*eaad808eSchristos return 0; 616*eaad808eSchristos if(dname_lab_cmp(d1, labs1, d2, labs2, &m) < 0) { 617*eaad808eSchristos /* must have been example.com , www.example.com - wrong */ 618*eaad808eSchristos /* or otherwise different dnames */ 619*eaad808eSchristos return 0; 620*eaad808eSchristos } 621*eaad808eSchristos return (m == labs2); 622*eaad808eSchristos } 623*eaad808eSchristos 624*eaad808eSchristos int 625*eaad808eSchristos dname_is_root(uint8_t* dname) 626*eaad808eSchristos { 627*eaad808eSchristos uint8_t len; 628*eaad808eSchristos log_assert(dname); 629*eaad808eSchristos len = dname[0]; 630*eaad808eSchristos log_assert(!LABEL_IS_PTR(len)); 631*eaad808eSchristos return (len == 0); 632*eaad808eSchristos } 633*eaad808eSchristos 634*eaad808eSchristos void 635*eaad808eSchristos dname_remove_label(uint8_t** dname, size_t* len) 636*eaad808eSchristos { 637*eaad808eSchristos size_t lablen; 638*eaad808eSchristos log_assert(dname && *dname && len); 639*eaad808eSchristos lablen = (*dname)[0]; 640*eaad808eSchristos log_assert(!LABEL_IS_PTR(lablen)); 641*eaad808eSchristos log_assert(*len > lablen); 642*eaad808eSchristos if(lablen == 0) 643*eaad808eSchristos return; /* do not modify root label */ 644*eaad808eSchristos *len -= lablen+1; 645*eaad808eSchristos *dname += lablen+1; 646*eaad808eSchristos } 647*eaad808eSchristos 648*eaad808eSchristos void 649*eaad808eSchristos dname_remove_labels(uint8_t** dname, size_t* len, int n) 650*eaad808eSchristos { 651*eaad808eSchristos int i; 652*eaad808eSchristos for(i=0; i<n; i++) 653*eaad808eSchristos dname_remove_label(dname, len); 654*eaad808eSchristos } 655*eaad808eSchristos 656*eaad808eSchristos int 657*eaad808eSchristos dname_signame_label_count(uint8_t* dname) 658*eaad808eSchristos { 659*eaad808eSchristos uint8_t lablen; 660*eaad808eSchristos int count = 0; 661*eaad808eSchristos if(!*dname) 662*eaad808eSchristos return 0; 663*eaad808eSchristos if(dname[0] == 1 && dname[1] == '*') 664*eaad808eSchristos dname += 2; 665*eaad808eSchristos lablen = dname[0]; 666*eaad808eSchristos while(lablen) { 667*eaad808eSchristos count++; 668*eaad808eSchristos dname += lablen; 669*eaad808eSchristos dname += 1; 670*eaad808eSchristos lablen = dname[0]; 671*eaad808eSchristos } 672*eaad808eSchristos return count; 673*eaad808eSchristos } 674*eaad808eSchristos 675*eaad808eSchristos int 676*eaad808eSchristos dname_is_wild(uint8_t* dname) 677*eaad808eSchristos { 678*eaad808eSchristos return (dname[0] == 1 && dname[1] == '*'); 679*eaad808eSchristos } 680*eaad808eSchristos 681*eaad808eSchristos /** 682*eaad808eSchristos * Compare labels in memory, lowercase while comparing. 683*eaad808eSchristos * Returns canonical order for labels. If all is equal, the 684*eaad808eSchristos * shortest is first. 685*eaad808eSchristos * 686*eaad808eSchristos * @param p1: label 1 687*eaad808eSchristos * @param len1: length of label 1. 688*eaad808eSchristos * @param p2: label 2 689*eaad808eSchristos * @param len2: length of label 2. 690*eaad808eSchristos * @return: 0, -1, +1 comparison result. 691*eaad808eSchristos */ 692*eaad808eSchristos static int 693*eaad808eSchristos memcanoncmp(uint8_t* p1, uint8_t len1, uint8_t* p2, uint8_t len2) 694*eaad808eSchristos { 695*eaad808eSchristos uint8_t min = (len1<len2)?len1:len2; 696*eaad808eSchristos int c = memlowercmp(p1, p2, min); 697*eaad808eSchristos if(c != 0) 698*eaad808eSchristos return c; 699*eaad808eSchristos /* equal, see who is shortest */ 700*eaad808eSchristos if(len1 < len2) 701*eaad808eSchristos return -1; 702*eaad808eSchristos if(len1 > len2) 703*eaad808eSchristos return 1; 704*eaad808eSchristos return 0; 705*eaad808eSchristos } 706*eaad808eSchristos 707*eaad808eSchristos 708*eaad808eSchristos int 709*eaad808eSchristos dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs) 710*eaad808eSchristos { 711*eaad808eSchristos /* like dname_lab_cmp, but with different label comparison, 712*eaad808eSchristos * empty character sorts before \000. 713*eaad808eSchristos * So ylyly is before z. */ 714*eaad808eSchristos uint8_t len1, len2; 715*eaad808eSchristos int atlabel = labs1; 716*eaad808eSchristos int lastmlabs; 717*eaad808eSchristos int lastdiff = 0; 718*eaad808eSchristos int c; 719*eaad808eSchristos /* first skip so that we compare same label. */ 720*eaad808eSchristos if(labs1 > labs2) { 721*eaad808eSchristos while(atlabel > labs2) { 722*eaad808eSchristos len1 = *d1++; 723*eaad808eSchristos d1 += len1; 724*eaad808eSchristos atlabel--; 725*eaad808eSchristos } 726*eaad808eSchristos log_assert(atlabel == labs2); 727*eaad808eSchristos } else if(labs1 < labs2) { 728*eaad808eSchristos atlabel = labs2; 729*eaad808eSchristos while(atlabel > labs1) { 730*eaad808eSchristos len2 = *d2++; 731*eaad808eSchristos d2 += len2; 732*eaad808eSchristos atlabel--; 733*eaad808eSchristos } 734*eaad808eSchristos log_assert(atlabel == labs1); 735*eaad808eSchristos } 736*eaad808eSchristos lastmlabs = atlabel+1; 737*eaad808eSchristos /* now at same label in d1 and d2, atlabel */ 738*eaad808eSchristos /* www.example.com. */ 739*eaad808eSchristos /* 4 3 2 1 atlabel number */ 740*eaad808eSchristos /* repeat until at root label (which is always the same) */ 741*eaad808eSchristos while(atlabel > 1) { 742*eaad808eSchristos len1 = *d1++; 743*eaad808eSchristos len2 = *d2++; 744*eaad808eSchristos 745*eaad808eSchristos if((c=memcanoncmp(d1, len1, d2, len2)) != 0) { 746*eaad808eSchristos if(c<0) 747*eaad808eSchristos lastdiff = -1; 748*eaad808eSchristos else lastdiff = 1; 749*eaad808eSchristos lastmlabs = atlabel; 750*eaad808eSchristos } 751*eaad808eSchristos 752*eaad808eSchristos d1 += len1; 753*eaad808eSchristos d2 += len2; 754*eaad808eSchristos atlabel--; 755*eaad808eSchristos } 756*eaad808eSchristos /* last difference atlabel number, so number of labels matching, 757*eaad808eSchristos * at the right side, is one less. */ 758*eaad808eSchristos *mlabs = lastmlabs-1; 759*eaad808eSchristos if(lastdiff == 0) { 760*eaad808eSchristos /* all labels compared were equal, check if one has more 761*eaad808eSchristos * labels, so that example.com. > com. */ 762*eaad808eSchristos if(labs1 > labs2) 763*eaad808eSchristos return 1; 764*eaad808eSchristos else if(labs1 < labs2) 765*eaad808eSchristos return -1; 766*eaad808eSchristos } 767*eaad808eSchristos return lastdiff; 768*eaad808eSchristos } 769*eaad808eSchristos 770*eaad808eSchristos int 771*eaad808eSchristos dname_canonical_compare(uint8_t* d1, uint8_t* d2) 772*eaad808eSchristos { 773*eaad808eSchristos int labs1, labs2, m; 774*eaad808eSchristos labs1 = dname_count_labels(d1); 775*eaad808eSchristos labs2 = dname_count_labels(d2); 776*eaad808eSchristos return dname_canon_lab_cmp(d1, labs1, d2, labs2, &m); 777*eaad808eSchristos } 778*eaad808eSchristos 779*eaad808eSchristos uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2) 780*eaad808eSchristos { 781*eaad808eSchristos int labs1, labs2, m; 782*eaad808eSchristos size_t len = LDNS_MAX_DOMAINLEN; 783*eaad808eSchristos labs1 = dname_count_labels(d1); 784*eaad808eSchristos labs2 = dname_count_labels(d2); 785*eaad808eSchristos (void)dname_lab_cmp(d1, labs1, d2, labs2, &m); 786*eaad808eSchristos dname_remove_labels(&d1, &len, labs1-m); 787*eaad808eSchristos return d1; 788*eaad808eSchristos } 789