1*7b5038d7SDag-Erling Smørgrav /* 2*7b5038d7SDag-Erling Smørgrav * dname.c 3*7b5038d7SDag-Erling Smørgrav * 4*7b5038d7SDag-Erling Smørgrav * dname specific rdata implementations 5*7b5038d7SDag-Erling Smørgrav * A dname is a rdf structure with type LDNS_RDF_TYPE_DNAME 6*7b5038d7SDag-Erling Smørgrav * It is not a /real/ type! All function must therefor check 7*7b5038d7SDag-Erling Smørgrav * for LDNS_RDF_TYPE_DNAME. 8*7b5038d7SDag-Erling Smørgrav * 9*7b5038d7SDag-Erling Smørgrav * a Net::DNS like library for C 10*7b5038d7SDag-Erling Smørgrav * 11*7b5038d7SDag-Erling Smørgrav * (c) NLnet Labs, 2004-2006 12*7b5038d7SDag-Erling Smørgrav * 13*7b5038d7SDag-Erling Smørgrav * See the file LICENSE for the license 14*7b5038d7SDag-Erling Smørgrav */ 15*7b5038d7SDag-Erling Smørgrav 16*7b5038d7SDag-Erling Smørgrav #include <ldns/config.h> 17*7b5038d7SDag-Erling Smørgrav 18*7b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h> 19*7b5038d7SDag-Erling Smørgrav 20*7b5038d7SDag-Erling Smørgrav #ifdef HAVE_NETINET_IN_H 21*7b5038d7SDag-Erling Smørgrav #include <netinet/in.h> 22*7b5038d7SDag-Erling Smørgrav #endif 23*7b5038d7SDag-Erling Smørgrav #ifdef HAVE_SYS_SOCKET_H 24*7b5038d7SDag-Erling Smørgrav #include <sys/socket.h> 25*7b5038d7SDag-Erling Smørgrav #endif 26*7b5038d7SDag-Erling Smørgrav #ifdef HAVE_NETDB_H 27*7b5038d7SDag-Erling Smørgrav #include <netdb.h> 28*7b5038d7SDag-Erling Smørgrav #endif 29*7b5038d7SDag-Erling Smørgrav #ifdef HAVE_ARPA_INET_H 30*7b5038d7SDag-Erling Smørgrav #include <arpa/inet.h> 31*7b5038d7SDag-Erling Smørgrav #endif 32*7b5038d7SDag-Erling Smørgrav 33*7b5038d7SDag-Erling Smørgrav ldns_rdf * 34*7b5038d7SDag-Erling Smørgrav ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2) 35*7b5038d7SDag-Erling Smørgrav { 36*7b5038d7SDag-Erling Smørgrav ldns_rdf *new; 37*7b5038d7SDag-Erling Smørgrav uint16_t new_size; 38*7b5038d7SDag-Erling Smørgrav uint8_t *buf; 39*7b5038d7SDag-Erling Smørgrav uint16_t left_size; 40*7b5038d7SDag-Erling Smørgrav 41*7b5038d7SDag-Erling Smørgrav if (ldns_rdf_get_type(rd1) != LDNS_RDF_TYPE_DNAME || 42*7b5038d7SDag-Erling Smørgrav ldns_rdf_get_type(rd2) != LDNS_RDF_TYPE_DNAME) { 43*7b5038d7SDag-Erling Smørgrav return NULL; 44*7b5038d7SDag-Erling Smørgrav } 45*7b5038d7SDag-Erling Smørgrav 46*7b5038d7SDag-Erling Smørgrav /* remove root label if it is present at the end of the left 47*7b5038d7SDag-Erling Smørgrav * rd, by reducing the size with 1 48*7b5038d7SDag-Erling Smørgrav */ 49*7b5038d7SDag-Erling Smørgrav left_size = ldns_rdf_size(rd1); 50*7b5038d7SDag-Erling Smørgrav if (left_size > 0 &&ldns_rdf_data(rd1)[left_size - 1] == 0) { 51*7b5038d7SDag-Erling Smørgrav left_size--; 52*7b5038d7SDag-Erling Smørgrav } 53*7b5038d7SDag-Erling Smørgrav 54*7b5038d7SDag-Erling Smørgrav /* we overwrite the nullbyte of rd1 */ 55*7b5038d7SDag-Erling Smørgrav new_size = left_size + ldns_rdf_size(rd2); 56*7b5038d7SDag-Erling Smørgrav buf = LDNS_XMALLOC(uint8_t, new_size); 57*7b5038d7SDag-Erling Smørgrav if (!buf) { 58*7b5038d7SDag-Erling Smørgrav return NULL; 59*7b5038d7SDag-Erling Smørgrav } 60*7b5038d7SDag-Erling Smørgrav 61*7b5038d7SDag-Erling Smørgrav /* put the two dname's after each other */ 62*7b5038d7SDag-Erling Smørgrav memcpy(buf, ldns_rdf_data(rd1), left_size); 63*7b5038d7SDag-Erling Smørgrav memcpy(buf + left_size, ldns_rdf_data(rd2), ldns_rdf_size(rd2)); 64*7b5038d7SDag-Erling Smørgrav 65*7b5038d7SDag-Erling Smørgrav new = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, new_size, buf); 66*7b5038d7SDag-Erling Smørgrav 67*7b5038d7SDag-Erling Smørgrav LDNS_FREE(buf); 68*7b5038d7SDag-Erling Smørgrav return new; 69*7b5038d7SDag-Erling Smørgrav } 70*7b5038d7SDag-Erling Smørgrav 71*7b5038d7SDag-Erling Smørgrav ldns_status 72*7b5038d7SDag-Erling Smørgrav ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2) 73*7b5038d7SDag-Erling Smørgrav { 74*7b5038d7SDag-Erling Smørgrav uint16_t left_size; 75*7b5038d7SDag-Erling Smørgrav uint16_t size; 76*7b5038d7SDag-Erling Smørgrav uint8_t* newd; 77*7b5038d7SDag-Erling Smørgrav 78*7b5038d7SDag-Erling Smørgrav if (ldns_rdf_get_type(rd1) != LDNS_RDF_TYPE_DNAME || 79*7b5038d7SDag-Erling Smørgrav ldns_rdf_get_type(rd2) != LDNS_RDF_TYPE_DNAME) { 80*7b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 81*7b5038d7SDag-Erling Smørgrav } 82*7b5038d7SDag-Erling Smørgrav 83*7b5038d7SDag-Erling Smørgrav /* remove root label if it is present at the end of the left 84*7b5038d7SDag-Erling Smørgrav * rd, by reducing the size with 1 85*7b5038d7SDag-Erling Smørgrav */ 86*7b5038d7SDag-Erling Smørgrav left_size = ldns_rdf_size(rd1); 87*7b5038d7SDag-Erling Smørgrav if (left_size > 0 &&ldns_rdf_data(rd1)[left_size - 1] == 0) { 88*7b5038d7SDag-Erling Smørgrav left_size--; 89*7b5038d7SDag-Erling Smørgrav } 90*7b5038d7SDag-Erling Smørgrav 91*7b5038d7SDag-Erling Smørgrav size = left_size + ldns_rdf_size(rd2); 92*7b5038d7SDag-Erling Smørgrav newd = LDNS_XREALLOC(ldns_rdf_data(rd1), uint8_t, size); 93*7b5038d7SDag-Erling Smørgrav if(!newd) { 94*7b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 95*7b5038d7SDag-Erling Smørgrav } 96*7b5038d7SDag-Erling Smørgrav 97*7b5038d7SDag-Erling Smørgrav ldns_rdf_set_data(rd1, newd); 98*7b5038d7SDag-Erling Smørgrav memcpy(ldns_rdf_data(rd1) + left_size, ldns_rdf_data(rd2), 99*7b5038d7SDag-Erling Smørgrav ldns_rdf_size(rd2)); 100*7b5038d7SDag-Erling Smørgrav ldns_rdf_set_size(rd1, size); 101*7b5038d7SDag-Erling Smørgrav 102*7b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK; 103*7b5038d7SDag-Erling Smørgrav } 104*7b5038d7SDag-Erling Smørgrav 105*7b5038d7SDag-Erling Smørgrav ldns_rdf * 106*7b5038d7SDag-Erling Smørgrav ldns_dname_reverse(const ldns_rdf *d) 107*7b5038d7SDag-Erling Smørgrav { 108*7b5038d7SDag-Erling Smørgrav ldns_rdf *new; 109*7b5038d7SDag-Erling Smørgrav ldns_rdf *tmp; 110*7b5038d7SDag-Erling Smørgrav ldns_rdf *d_tmp; 111*7b5038d7SDag-Erling Smørgrav ldns_status status; 112*7b5038d7SDag-Erling Smørgrav 113*7b5038d7SDag-Erling Smørgrav d_tmp = ldns_rdf_clone(d); 114*7b5038d7SDag-Erling Smørgrav 115*7b5038d7SDag-Erling Smørgrav new = ldns_dname_new_frm_str("."); 116*7b5038d7SDag-Erling Smørgrav if(!new) 117*7b5038d7SDag-Erling Smørgrav return NULL; 118*7b5038d7SDag-Erling Smørgrav 119*7b5038d7SDag-Erling Smørgrav while(ldns_dname_label_count(d_tmp) > 0) { 120*7b5038d7SDag-Erling Smørgrav tmp = ldns_dname_label(d_tmp, 0); 121*7b5038d7SDag-Erling Smørgrav status = ldns_dname_cat(tmp, new); 122*7b5038d7SDag-Erling Smørgrav if(status != LDNS_STATUS_OK) { 123*7b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(new); 124*7b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(d_tmp); 125*7b5038d7SDag-Erling Smørgrav return NULL; 126*7b5038d7SDag-Erling Smørgrav } 127*7b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(new); 128*7b5038d7SDag-Erling Smørgrav new = tmp; 129*7b5038d7SDag-Erling Smørgrav tmp = ldns_dname_left_chop(d_tmp); 130*7b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(d_tmp); 131*7b5038d7SDag-Erling Smørgrav d_tmp = tmp; 132*7b5038d7SDag-Erling Smørgrav } 133*7b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(d_tmp); 134*7b5038d7SDag-Erling Smørgrav 135*7b5038d7SDag-Erling Smørgrav return new; 136*7b5038d7SDag-Erling Smørgrav } 137*7b5038d7SDag-Erling Smørgrav 138*7b5038d7SDag-Erling Smørgrav ldns_rdf * 139*7b5038d7SDag-Erling Smørgrav ldns_dname_clone_from(const ldns_rdf *d, uint16_t n) 140*7b5038d7SDag-Erling Smørgrav { 141*7b5038d7SDag-Erling Smørgrav uint8_t *data; 142*7b5038d7SDag-Erling Smørgrav uint8_t label_size; 143*7b5038d7SDag-Erling Smørgrav size_t data_size; 144*7b5038d7SDag-Erling Smørgrav 145*7b5038d7SDag-Erling Smørgrav if (!d || 146*7b5038d7SDag-Erling Smørgrav ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME || 147*7b5038d7SDag-Erling Smørgrav ldns_dname_label_count(d) < n) { 148*7b5038d7SDag-Erling Smørgrav return NULL; 149*7b5038d7SDag-Erling Smørgrav } 150*7b5038d7SDag-Erling Smørgrav 151*7b5038d7SDag-Erling Smørgrav data = ldns_rdf_data(d); 152*7b5038d7SDag-Erling Smørgrav data_size = ldns_rdf_size(d); 153*7b5038d7SDag-Erling Smørgrav while (n > 0) { 154*7b5038d7SDag-Erling Smørgrav label_size = data[0] + 1; 155*7b5038d7SDag-Erling Smørgrav data += label_size; 156*7b5038d7SDag-Erling Smørgrav if (data_size < label_size) { 157*7b5038d7SDag-Erling Smørgrav /* this label is very broken */ 158*7b5038d7SDag-Erling Smørgrav return NULL; 159*7b5038d7SDag-Erling Smørgrav } 160*7b5038d7SDag-Erling Smørgrav data_size -= label_size; 161*7b5038d7SDag-Erling Smørgrav n--; 162*7b5038d7SDag-Erling Smørgrav } 163*7b5038d7SDag-Erling Smørgrav 164*7b5038d7SDag-Erling Smørgrav return ldns_dname_new_frm_data(data_size, data); 165*7b5038d7SDag-Erling Smørgrav } 166*7b5038d7SDag-Erling Smørgrav 167*7b5038d7SDag-Erling Smørgrav ldns_rdf * 168*7b5038d7SDag-Erling Smørgrav ldns_dname_left_chop(const ldns_rdf *d) 169*7b5038d7SDag-Erling Smørgrav { 170*7b5038d7SDag-Erling Smørgrav uint8_t label_pos; 171*7b5038d7SDag-Erling Smørgrav ldns_rdf *chop; 172*7b5038d7SDag-Erling Smørgrav 173*7b5038d7SDag-Erling Smørgrav if (!d) { 174*7b5038d7SDag-Erling Smørgrav return NULL; 175*7b5038d7SDag-Erling Smørgrav } 176*7b5038d7SDag-Erling Smørgrav 177*7b5038d7SDag-Erling Smørgrav if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) { 178*7b5038d7SDag-Erling Smørgrav return NULL; 179*7b5038d7SDag-Erling Smørgrav } 180*7b5038d7SDag-Erling Smørgrav if (ldns_dname_label_count(d) == 0) { 181*7b5038d7SDag-Erling Smørgrav /* root label */ 182*7b5038d7SDag-Erling Smørgrav return NULL; 183*7b5038d7SDag-Erling Smørgrav } 184*7b5038d7SDag-Erling Smørgrav /* 05blaat02nl00 */ 185*7b5038d7SDag-Erling Smørgrav label_pos = ldns_rdf_data(d)[0]; 186*7b5038d7SDag-Erling Smørgrav 187*7b5038d7SDag-Erling Smørgrav chop = ldns_dname_new_frm_data(ldns_rdf_size(d) - label_pos - 1, 188*7b5038d7SDag-Erling Smørgrav ldns_rdf_data(d) + label_pos + 1); 189*7b5038d7SDag-Erling Smørgrav return chop; 190*7b5038d7SDag-Erling Smørgrav } 191*7b5038d7SDag-Erling Smørgrav 192*7b5038d7SDag-Erling Smørgrav uint8_t 193*7b5038d7SDag-Erling Smørgrav ldns_dname_label_count(const ldns_rdf *r) 194*7b5038d7SDag-Erling Smørgrav { 195*7b5038d7SDag-Erling Smørgrav uint16_t src_pos; 196*7b5038d7SDag-Erling Smørgrav uint16_t len; 197*7b5038d7SDag-Erling Smørgrav uint8_t i; 198*7b5038d7SDag-Erling Smørgrav size_t r_size; 199*7b5038d7SDag-Erling Smørgrav 200*7b5038d7SDag-Erling Smørgrav if (!r) { 201*7b5038d7SDag-Erling Smørgrav return 0; 202*7b5038d7SDag-Erling Smørgrav } 203*7b5038d7SDag-Erling Smørgrav 204*7b5038d7SDag-Erling Smørgrav i = 0; 205*7b5038d7SDag-Erling Smørgrav src_pos = 0; 206*7b5038d7SDag-Erling Smørgrav r_size = ldns_rdf_size(r); 207*7b5038d7SDag-Erling Smørgrav 208*7b5038d7SDag-Erling Smørgrav if (ldns_rdf_get_type(r) != LDNS_RDF_TYPE_DNAME) { 209*7b5038d7SDag-Erling Smørgrav return 0; 210*7b5038d7SDag-Erling Smørgrav } else { 211*7b5038d7SDag-Erling Smørgrav len = ldns_rdf_data(r)[src_pos]; /* start of the label */ 212*7b5038d7SDag-Erling Smørgrav 213*7b5038d7SDag-Erling Smørgrav /* single root label */ 214*7b5038d7SDag-Erling Smørgrav if (1 == r_size) { 215*7b5038d7SDag-Erling Smørgrav return 0; 216*7b5038d7SDag-Erling Smørgrav } else { 217*7b5038d7SDag-Erling Smørgrav while ((len > 0) && src_pos < r_size) { 218*7b5038d7SDag-Erling Smørgrav src_pos++; 219*7b5038d7SDag-Erling Smørgrav src_pos += len; 220*7b5038d7SDag-Erling Smørgrav len = ldns_rdf_data(r)[src_pos]; 221*7b5038d7SDag-Erling Smørgrav i++; 222*7b5038d7SDag-Erling Smørgrav } 223*7b5038d7SDag-Erling Smørgrav } 224*7b5038d7SDag-Erling Smørgrav } 225*7b5038d7SDag-Erling Smørgrav return i; 226*7b5038d7SDag-Erling Smørgrav } 227*7b5038d7SDag-Erling Smørgrav 228*7b5038d7SDag-Erling Smørgrav ldns_rdf * 229*7b5038d7SDag-Erling Smørgrav ldns_dname_new(uint16_t s, void *d) 230*7b5038d7SDag-Erling Smørgrav { 231*7b5038d7SDag-Erling Smørgrav ldns_rdf *rd; 232*7b5038d7SDag-Erling Smørgrav 233*7b5038d7SDag-Erling Smørgrav rd = LDNS_MALLOC(ldns_rdf); 234*7b5038d7SDag-Erling Smørgrav if (!rd) { 235*7b5038d7SDag-Erling Smørgrav return NULL; 236*7b5038d7SDag-Erling Smørgrav } 237*7b5038d7SDag-Erling Smørgrav ldns_rdf_set_size(rd, s); 238*7b5038d7SDag-Erling Smørgrav ldns_rdf_set_type(rd, LDNS_RDF_TYPE_DNAME); 239*7b5038d7SDag-Erling Smørgrav ldns_rdf_set_data(rd, d); 240*7b5038d7SDag-Erling Smørgrav return rd; 241*7b5038d7SDag-Erling Smørgrav } 242*7b5038d7SDag-Erling Smørgrav 243*7b5038d7SDag-Erling Smørgrav ldns_rdf * 244*7b5038d7SDag-Erling Smørgrav ldns_dname_new_frm_str(const char *str) 245*7b5038d7SDag-Erling Smørgrav { 246*7b5038d7SDag-Erling Smørgrav return ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, str); 247*7b5038d7SDag-Erling Smørgrav } 248*7b5038d7SDag-Erling Smørgrav 249*7b5038d7SDag-Erling Smørgrav ldns_rdf * 250*7b5038d7SDag-Erling Smørgrav ldns_dname_new_frm_data(uint16_t size, const void *data) 251*7b5038d7SDag-Erling Smørgrav { 252*7b5038d7SDag-Erling Smørgrav return ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, size, data); 253*7b5038d7SDag-Erling Smørgrav } 254*7b5038d7SDag-Erling Smørgrav 255*7b5038d7SDag-Erling Smørgrav void 256*7b5038d7SDag-Erling Smørgrav ldns_dname2canonical(const ldns_rdf *rd) 257*7b5038d7SDag-Erling Smørgrav { 258*7b5038d7SDag-Erling Smørgrav uint8_t *rdd; 259*7b5038d7SDag-Erling Smørgrav uint16_t i; 260*7b5038d7SDag-Erling Smørgrav 261*7b5038d7SDag-Erling Smørgrav if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_DNAME) { 262*7b5038d7SDag-Erling Smørgrav return; 263*7b5038d7SDag-Erling Smørgrav } 264*7b5038d7SDag-Erling Smørgrav 265*7b5038d7SDag-Erling Smørgrav rdd = (uint8_t*)ldns_rdf_data(rd); 266*7b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rdf_size(rd); i++, rdd++) { 267*7b5038d7SDag-Erling Smørgrav *rdd = (uint8_t)LDNS_DNAME_NORMALIZE((int)*rdd); 268*7b5038d7SDag-Erling Smørgrav } 269*7b5038d7SDag-Erling Smørgrav } 270*7b5038d7SDag-Erling Smørgrav 271*7b5038d7SDag-Erling Smørgrav bool 272*7b5038d7SDag-Erling Smørgrav ldns_dname_is_subdomain(const ldns_rdf *sub, const ldns_rdf *parent) 273*7b5038d7SDag-Erling Smørgrav { 274*7b5038d7SDag-Erling Smørgrav uint8_t sub_lab; 275*7b5038d7SDag-Erling Smørgrav uint8_t par_lab; 276*7b5038d7SDag-Erling Smørgrav int8_t i, j; 277*7b5038d7SDag-Erling Smørgrav ldns_rdf *tmp_sub = NULL; 278*7b5038d7SDag-Erling Smørgrav ldns_rdf *tmp_par = NULL; 279*7b5038d7SDag-Erling Smørgrav ldns_rdf *sub_clone; 280*7b5038d7SDag-Erling Smørgrav ldns_rdf *parent_clone; 281*7b5038d7SDag-Erling Smørgrav bool result = true; 282*7b5038d7SDag-Erling Smørgrav 283*7b5038d7SDag-Erling Smørgrav if (ldns_rdf_get_type(sub) != LDNS_RDF_TYPE_DNAME || 284*7b5038d7SDag-Erling Smørgrav ldns_rdf_get_type(parent) != LDNS_RDF_TYPE_DNAME || 285*7b5038d7SDag-Erling Smørgrav ldns_rdf_compare(sub, parent) == 0) { 286*7b5038d7SDag-Erling Smørgrav return false; 287*7b5038d7SDag-Erling Smørgrav } 288*7b5038d7SDag-Erling Smørgrav 289*7b5038d7SDag-Erling Smørgrav /* would be nicer if we do not have to clone... */ 290*7b5038d7SDag-Erling Smørgrav sub_clone = ldns_dname_clone_from(sub, 0); 291*7b5038d7SDag-Erling Smørgrav parent_clone = ldns_dname_clone_from(parent, 0); 292*7b5038d7SDag-Erling Smørgrav ldns_dname2canonical(sub_clone); 293*7b5038d7SDag-Erling Smørgrav ldns_dname2canonical(parent_clone); 294*7b5038d7SDag-Erling Smørgrav 295*7b5038d7SDag-Erling Smørgrav sub_lab = ldns_dname_label_count(sub_clone); 296*7b5038d7SDag-Erling Smørgrav par_lab = ldns_dname_label_count(parent_clone); 297*7b5038d7SDag-Erling Smørgrav 298*7b5038d7SDag-Erling Smørgrav /* if sub sits above parent, it cannot be a child/sub domain */ 299*7b5038d7SDag-Erling Smørgrav if (sub_lab < par_lab) { 300*7b5038d7SDag-Erling Smørgrav result = false; 301*7b5038d7SDag-Erling Smørgrav } else { 302*7b5038d7SDag-Erling Smørgrav /* check all labels the from the parent labels, from right to left. 303*7b5038d7SDag-Erling Smørgrav * When they /all/ match we have found a subdomain 304*7b5038d7SDag-Erling Smørgrav */ 305*7b5038d7SDag-Erling Smørgrav j = sub_lab - 1; /* we count from zero, thank you */ 306*7b5038d7SDag-Erling Smørgrav for (i = par_lab -1; i >= 0; i--) { 307*7b5038d7SDag-Erling Smørgrav tmp_sub = ldns_dname_label(sub_clone, j); 308*7b5038d7SDag-Erling Smørgrav tmp_par = ldns_dname_label(parent_clone, i); 309*7b5038d7SDag-Erling Smørgrav if (!tmp_sub || !tmp_par) { 310*7b5038d7SDag-Erling Smørgrav /* deep free does null check */ 311*7b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(tmp_sub); 312*7b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(tmp_par); 313*7b5038d7SDag-Erling Smørgrav result = false; 314*7b5038d7SDag-Erling Smørgrav break; 315*7b5038d7SDag-Erling Smørgrav } 316*7b5038d7SDag-Erling Smørgrav 317*7b5038d7SDag-Erling Smørgrav if (ldns_rdf_compare(tmp_sub, tmp_par) != 0) { 318*7b5038d7SDag-Erling Smørgrav /* they are not equal */ 319*7b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(tmp_sub); 320*7b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(tmp_par); 321*7b5038d7SDag-Erling Smørgrav result = false; 322*7b5038d7SDag-Erling Smørgrav break; 323*7b5038d7SDag-Erling Smørgrav } 324*7b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(tmp_sub); 325*7b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(tmp_par); 326*7b5038d7SDag-Erling Smørgrav j--; 327*7b5038d7SDag-Erling Smørgrav } 328*7b5038d7SDag-Erling Smørgrav } 329*7b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(sub_clone); 330*7b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(parent_clone); 331*7b5038d7SDag-Erling Smørgrav return result; 332*7b5038d7SDag-Erling Smørgrav } 333*7b5038d7SDag-Erling Smørgrav 334*7b5038d7SDag-Erling Smørgrav int 335*7b5038d7SDag-Erling Smørgrav ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2) 336*7b5038d7SDag-Erling Smørgrav { 337*7b5038d7SDag-Erling Smørgrav size_t lc1, lc2, lc1f, lc2f; 338*7b5038d7SDag-Erling Smørgrav size_t i; 339*7b5038d7SDag-Erling Smørgrav int result = 0; 340*7b5038d7SDag-Erling Smørgrav uint8_t *lp1, *lp2; 341*7b5038d7SDag-Erling Smørgrav 342*7b5038d7SDag-Erling Smørgrav /* see RFC4034 for this algorithm */ 343*7b5038d7SDag-Erling Smørgrav /* this algorithm assumes the names are normalized to case */ 344*7b5038d7SDag-Erling Smørgrav 345*7b5038d7SDag-Erling Smørgrav /* only when both are not NULL we can say anything about them */ 346*7b5038d7SDag-Erling Smørgrav if (!dname1 && !dname2) { 347*7b5038d7SDag-Erling Smørgrav return 0; 348*7b5038d7SDag-Erling Smørgrav } 349*7b5038d7SDag-Erling Smørgrav if (!dname1 || !dname2) { 350*7b5038d7SDag-Erling Smørgrav return -1; 351*7b5038d7SDag-Erling Smørgrav } 352*7b5038d7SDag-Erling Smørgrav /* asserts must happen later as we are looking in the 353*7b5038d7SDag-Erling Smørgrav * dname, which could be NULL. But this case is handled 354*7b5038d7SDag-Erling Smørgrav * above 355*7b5038d7SDag-Erling Smørgrav */ 356*7b5038d7SDag-Erling Smørgrav assert(ldns_rdf_get_type(dname1) == LDNS_RDF_TYPE_DNAME); 357*7b5038d7SDag-Erling Smørgrav assert(ldns_rdf_get_type(dname2) == LDNS_RDF_TYPE_DNAME); 358*7b5038d7SDag-Erling Smørgrav 359*7b5038d7SDag-Erling Smørgrav lc1 = ldns_dname_label_count(dname1); 360*7b5038d7SDag-Erling Smørgrav lc2 = ldns_dname_label_count(dname2); 361*7b5038d7SDag-Erling Smørgrav 362*7b5038d7SDag-Erling Smørgrav if (lc1 == 0 && lc2 == 0) { 363*7b5038d7SDag-Erling Smørgrav return 0; 364*7b5038d7SDag-Erling Smørgrav } 365*7b5038d7SDag-Erling Smørgrav if (lc1 == 0) { 366*7b5038d7SDag-Erling Smørgrav return -1; 367*7b5038d7SDag-Erling Smørgrav } 368*7b5038d7SDag-Erling Smørgrav if (lc2 == 0) { 369*7b5038d7SDag-Erling Smørgrav return 1; 370*7b5038d7SDag-Erling Smørgrav } 371*7b5038d7SDag-Erling Smørgrav lc1--; 372*7b5038d7SDag-Erling Smørgrav lc2--; 373*7b5038d7SDag-Erling Smørgrav /* we start at the last label */ 374*7b5038d7SDag-Erling Smørgrav while (true) { 375*7b5038d7SDag-Erling Smørgrav /* find the label first */ 376*7b5038d7SDag-Erling Smørgrav lc1f = lc1; 377*7b5038d7SDag-Erling Smørgrav lp1 = ldns_rdf_data(dname1); 378*7b5038d7SDag-Erling Smørgrav while (lc1f > 0) { 379*7b5038d7SDag-Erling Smørgrav lp1 += *lp1 + 1; 380*7b5038d7SDag-Erling Smørgrav lc1f--; 381*7b5038d7SDag-Erling Smørgrav } 382*7b5038d7SDag-Erling Smørgrav 383*7b5038d7SDag-Erling Smørgrav /* and find the other one */ 384*7b5038d7SDag-Erling Smørgrav lc2f = lc2; 385*7b5038d7SDag-Erling Smørgrav lp2 = ldns_rdf_data(dname2); 386*7b5038d7SDag-Erling Smørgrav while (lc2f > 0) { 387*7b5038d7SDag-Erling Smørgrav lp2 += *lp2 + 1; 388*7b5038d7SDag-Erling Smørgrav lc2f--; 389*7b5038d7SDag-Erling Smørgrav } 390*7b5038d7SDag-Erling Smørgrav 391*7b5038d7SDag-Erling Smørgrav /* now check the label character for character. */ 392*7b5038d7SDag-Erling Smørgrav for (i = 1; i < (size_t)(*lp1 + 1); i++) { 393*7b5038d7SDag-Erling Smørgrav if (i > *lp2) { 394*7b5038d7SDag-Erling Smørgrav /* apparently label 1 is larger */ 395*7b5038d7SDag-Erling Smørgrav result = 1; 396*7b5038d7SDag-Erling Smørgrav goto done; 397*7b5038d7SDag-Erling Smørgrav } 398*7b5038d7SDag-Erling Smørgrav if (LDNS_DNAME_NORMALIZE((int) *(lp1 + i)) < 399*7b5038d7SDag-Erling Smørgrav LDNS_DNAME_NORMALIZE((int) *(lp2 + i))) { 400*7b5038d7SDag-Erling Smørgrav result = -1; 401*7b5038d7SDag-Erling Smørgrav goto done; 402*7b5038d7SDag-Erling Smørgrav } else if (LDNS_DNAME_NORMALIZE((int) *(lp1 + i)) > 403*7b5038d7SDag-Erling Smørgrav LDNS_DNAME_NORMALIZE((int) *(lp2 + i))) { 404*7b5038d7SDag-Erling Smørgrav result = 1; 405*7b5038d7SDag-Erling Smørgrav goto done; 406*7b5038d7SDag-Erling Smørgrav } 407*7b5038d7SDag-Erling Smørgrav } 408*7b5038d7SDag-Erling Smørgrav if (*lp1 < *lp2) { 409*7b5038d7SDag-Erling Smørgrav /* apparently label 2 is larger */ 410*7b5038d7SDag-Erling Smørgrav result = -1; 411*7b5038d7SDag-Erling Smørgrav goto done; 412*7b5038d7SDag-Erling Smørgrav } 413*7b5038d7SDag-Erling Smørgrav if (lc1 == 0 && lc2 > 0) { 414*7b5038d7SDag-Erling Smørgrav result = -1; 415*7b5038d7SDag-Erling Smørgrav goto done; 416*7b5038d7SDag-Erling Smørgrav } else if (lc1 > 0 && lc2 == 0) { 417*7b5038d7SDag-Erling Smørgrav result = 1; 418*7b5038d7SDag-Erling Smørgrav goto done; 419*7b5038d7SDag-Erling Smørgrav } else if (lc1 == 0 && lc2 == 0) { 420*7b5038d7SDag-Erling Smørgrav result = 0; 421*7b5038d7SDag-Erling Smørgrav goto done; 422*7b5038d7SDag-Erling Smørgrav } 423*7b5038d7SDag-Erling Smørgrav lc1--; 424*7b5038d7SDag-Erling Smørgrav lc2--; 425*7b5038d7SDag-Erling Smørgrav } 426*7b5038d7SDag-Erling Smørgrav 427*7b5038d7SDag-Erling Smørgrav done: 428*7b5038d7SDag-Erling Smørgrav return result; 429*7b5038d7SDag-Erling Smørgrav } 430*7b5038d7SDag-Erling Smørgrav 431*7b5038d7SDag-Erling Smørgrav int 432*7b5038d7SDag-Erling Smørgrav ldns_dname_is_wildcard(const ldns_rdf* dname) 433*7b5038d7SDag-Erling Smørgrav { 434*7b5038d7SDag-Erling Smørgrav return ( ldns_dname_label_count(dname) > 0 && 435*7b5038d7SDag-Erling Smørgrav ldns_rdf_data(dname)[0] == 1 && 436*7b5038d7SDag-Erling Smørgrav ldns_rdf_data(dname)[1] == '*'); 437*7b5038d7SDag-Erling Smørgrav } 438*7b5038d7SDag-Erling Smørgrav 439*7b5038d7SDag-Erling Smørgrav int 440*7b5038d7SDag-Erling Smørgrav ldns_dname_match_wildcard(const ldns_rdf *dname, const ldns_rdf *wildcard) 441*7b5038d7SDag-Erling Smørgrav { 442*7b5038d7SDag-Erling Smørgrav ldns_rdf *wc_chopped; 443*7b5038d7SDag-Erling Smørgrav int result; 444*7b5038d7SDag-Erling Smørgrav /* check whether it really is a wildcard */ 445*7b5038d7SDag-Erling Smørgrav if (ldns_dname_is_wildcard(wildcard)) { 446*7b5038d7SDag-Erling Smørgrav /* ok, so the dname needs to be a subdomain of the wildcard 447*7b5038d7SDag-Erling Smørgrav * without the * 448*7b5038d7SDag-Erling Smørgrav */ 449*7b5038d7SDag-Erling Smørgrav wc_chopped = ldns_dname_left_chop(wildcard); 450*7b5038d7SDag-Erling Smørgrav result = (int) ldns_dname_is_subdomain(dname, wc_chopped); 451*7b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(wc_chopped); 452*7b5038d7SDag-Erling Smørgrav } else { 453*7b5038d7SDag-Erling Smørgrav result = (ldns_dname_compare(dname, wildcard) == 0); 454*7b5038d7SDag-Erling Smørgrav } 455*7b5038d7SDag-Erling Smørgrav return result; 456*7b5038d7SDag-Erling Smørgrav } 457*7b5038d7SDag-Erling Smørgrav 458*7b5038d7SDag-Erling Smørgrav /* nsec test: does prev <= middle < next 459*7b5038d7SDag-Erling Smørgrav * -1 = yes 460*7b5038d7SDag-Erling Smørgrav * 0 = error/can't tell 461*7b5038d7SDag-Erling Smørgrav * 1 = no 462*7b5038d7SDag-Erling Smørgrav */ 463*7b5038d7SDag-Erling Smørgrav int 464*7b5038d7SDag-Erling Smørgrav ldns_dname_interval(const ldns_rdf *prev, const ldns_rdf *middle, 465*7b5038d7SDag-Erling Smørgrav const ldns_rdf *next) 466*7b5038d7SDag-Erling Smørgrav { 467*7b5038d7SDag-Erling Smørgrav int prev_check, next_check; 468*7b5038d7SDag-Erling Smørgrav 469*7b5038d7SDag-Erling Smørgrav assert(ldns_rdf_get_type(prev) == LDNS_RDF_TYPE_DNAME); 470*7b5038d7SDag-Erling Smørgrav assert(ldns_rdf_get_type(middle) == LDNS_RDF_TYPE_DNAME); 471*7b5038d7SDag-Erling Smørgrav assert(ldns_rdf_get_type(next) == LDNS_RDF_TYPE_DNAME); 472*7b5038d7SDag-Erling Smørgrav 473*7b5038d7SDag-Erling Smørgrav prev_check = ldns_dname_compare(prev, middle); 474*7b5038d7SDag-Erling Smørgrav next_check = ldns_dname_compare(middle, next); 475*7b5038d7SDag-Erling Smørgrav /* <= next. This cannot be the case for nsec, because then we would 476*7b5038d7SDag-Erling Smørgrav * have gotten the nsec of next... 477*7b5038d7SDag-Erling Smørgrav */ 478*7b5038d7SDag-Erling Smørgrav if (next_check == 0) { 479*7b5038d7SDag-Erling Smørgrav return 0; 480*7b5038d7SDag-Erling Smørgrav } 481*7b5038d7SDag-Erling Smørgrav 482*7b5038d7SDag-Erling Smørgrav /* <= */ 483*7b5038d7SDag-Erling Smørgrav if ((prev_check == -1 || prev_check == 0) && 484*7b5038d7SDag-Erling Smørgrav /* < */ 485*7b5038d7SDag-Erling Smørgrav next_check == -1) { 486*7b5038d7SDag-Erling Smørgrav return -1; 487*7b5038d7SDag-Erling Smørgrav } else { 488*7b5038d7SDag-Erling Smørgrav return 1; 489*7b5038d7SDag-Erling Smørgrav } 490*7b5038d7SDag-Erling Smørgrav } 491*7b5038d7SDag-Erling Smørgrav 492*7b5038d7SDag-Erling Smørgrav 493*7b5038d7SDag-Erling Smørgrav bool 494*7b5038d7SDag-Erling Smørgrav ldns_dname_str_absolute(const char *dname_str) 495*7b5038d7SDag-Erling Smørgrav { 496*7b5038d7SDag-Erling Smørgrav const char* s; 497*7b5038d7SDag-Erling Smørgrav if(dname_str && strcmp(dname_str, ".") == 0) 498*7b5038d7SDag-Erling Smørgrav return 1; 499*7b5038d7SDag-Erling Smørgrav if(!dname_str || strlen(dname_str) < 2) 500*7b5038d7SDag-Erling Smørgrav return 0; 501*7b5038d7SDag-Erling Smørgrav if(dname_str[strlen(dname_str) - 1] != '.') 502*7b5038d7SDag-Erling Smørgrav return 0; 503*7b5038d7SDag-Erling Smørgrav if(dname_str[strlen(dname_str) - 2] != '\\') 504*7b5038d7SDag-Erling Smørgrav return 1; /* ends in . and no \ before it */ 505*7b5038d7SDag-Erling Smørgrav /* so we have the case of ends in . and there is \ before it */ 506*7b5038d7SDag-Erling Smørgrav for(s=dname_str; *s; s++) { 507*7b5038d7SDag-Erling Smørgrav if(*s == '\\') { 508*7b5038d7SDag-Erling Smørgrav if(s[1] && s[2] && s[3] /* check length */ 509*7b5038d7SDag-Erling Smørgrav && isdigit(s[1]) && isdigit(s[2]) && 510*7b5038d7SDag-Erling Smørgrav isdigit(s[3])) 511*7b5038d7SDag-Erling Smørgrav s += 3; 512*7b5038d7SDag-Erling Smørgrav else if(!s[1] || isdigit(s[1])) /* escape of nul,0-9 */ 513*7b5038d7SDag-Erling Smørgrav return 0; /* parse error */ 514*7b5038d7SDag-Erling Smørgrav else s++; /* another character escaped */ 515*7b5038d7SDag-Erling Smørgrav } 516*7b5038d7SDag-Erling Smørgrav else if(!*(s+1) && *s == '.') 517*7b5038d7SDag-Erling Smørgrav return 1; /* trailing dot, unescaped */ 518*7b5038d7SDag-Erling Smørgrav } 519*7b5038d7SDag-Erling Smørgrav return 0; 520*7b5038d7SDag-Erling Smørgrav } 521*7b5038d7SDag-Erling Smørgrav 522*7b5038d7SDag-Erling Smørgrav ldns_rdf * 523*7b5038d7SDag-Erling Smørgrav ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos) 524*7b5038d7SDag-Erling Smørgrav { 525*7b5038d7SDag-Erling Smørgrav uint8_t labelcnt; 526*7b5038d7SDag-Erling Smørgrav uint16_t src_pos; 527*7b5038d7SDag-Erling Smørgrav uint16_t len; 528*7b5038d7SDag-Erling Smørgrav ldns_rdf *tmpnew; 529*7b5038d7SDag-Erling Smørgrav size_t s; 530*7b5038d7SDag-Erling Smørgrav uint8_t *data; 531*7b5038d7SDag-Erling Smørgrav 532*7b5038d7SDag-Erling Smørgrav if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_DNAME) { 533*7b5038d7SDag-Erling Smørgrav return NULL; 534*7b5038d7SDag-Erling Smørgrav } 535*7b5038d7SDag-Erling Smørgrav 536*7b5038d7SDag-Erling Smørgrav labelcnt = 0; 537*7b5038d7SDag-Erling Smørgrav src_pos = 0; 538*7b5038d7SDag-Erling Smørgrav s = ldns_rdf_size(rdf); 539*7b5038d7SDag-Erling Smørgrav 540*7b5038d7SDag-Erling Smørgrav len = ldns_rdf_data(rdf)[src_pos]; /* label start */ 541*7b5038d7SDag-Erling Smørgrav while ((len > 0) && src_pos < s) { 542*7b5038d7SDag-Erling Smørgrav if (labelcnt == labelpos) { 543*7b5038d7SDag-Erling Smørgrav /* found our label */ 544*7b5038d7SDag-Erling Smørgrav data = LDNS_XMALLOC(uint8_t, len + 2); 545*7b5038d7SDag-Erling Smørgrav if (!data) { 546*7b5038d7SDag-Erling Smørgrav return NULL; 547*7b5038d7SDag-Erling Smørgrav } 548*7b5038d7SDag-Erling Smørgrav memcpy(data, ldns_rdf_data(rdf) + src_pos, len + 1); 549*7b5038d7SDag-Erling Smørgrav data[len + 2 - 1] = 0; 550*7b5038d7SDag-Erling Smørgrav 551*7b5038d7SDag-Erling Smørgrav tmpnew = ldns_rdf_new( LDNS_RDF_TYPE_DNAME 552*7b5038d7SDag-Erling Smørgrav , len + 2, data); 553*7b5038d7SDag-Erling Smørgrav if (!tmpnew) { 554*7b5038d7SDag-Erling Smørgrav LDNS_FREE(data); 555*7b5038d7SDag-Erling Smørgrav return NULL; 556*7b5038d7SDag-Erling Smørgrav } 557*7b5038d7SDag-Erling Smørgrav return tmpnew; 558*7b5038d7SDag-Erling Smørgrav } 559*7b5038d7SDag-Erling Smørgrav src_pos++; 560*7b5038d7SDag-Erling Smørgrav src_pos += len; 561*7b5038d7SDag-Erling Smørgrav len = ldns_rdf_data(rdf)[src_pos]; 562*7b5038d7SDag-Erling Smørgrav labelcnt++; 563*7b5038d7SDag-Erling Smørgrav } 564*7b5038d7SDag-Erling Smørgrav return NULL; 565*7b5038d7SDag-Erling Smørgrav } 566