1825eb42bSJan Lentfer /* 2825eb42bSJan Lentfer * dname.c 3825eb42bSJan Lentfer * 4825eb42bSJan Lentfer * dname specific rdata implementations 5825eb42bSJan Lentfer * A dname is a rdf structure with type LDNS_RDF_TYPE_DNAME 6825eb42bSJan Lentfer * It is not a /real/ type! All function must therefor check 7825eb42bSJan Lentfer * for LDNS_RDF_TYPE_DNAME. 8825eb42bSJan Lentfer * 9825eb42bSJan Lentfer * a Net::DNS like library for C 10825eb42bSJan Lentfer * 11825eb42bSJan Lentfer * (c) NLnet Labs, 2004-2006 12825eb42bSJan Lentfer * 13825eb42bSJan Lentfer * See the file LICENSE for the license 14825eb42bSJan Lentfer */ 15825eb42bSJan Lentfer 16825eb42bSJan Lentfer #include <ldns/config.h> 17825eb42bSJan Lentfer 18825eb42bSJan Lentfer #include <ldns/ldns.h> 19825eb42bSJan Lentfer 20825eb42bSJan Lentfer #ifdef HAVE_NETINET_IN_H 21825eb42bSJan Lentfer #include <netinet/in.h> 22825eb42bSJan Lentfer #endif 23825eb42bSJan Lentfer #ifdef HAVE_SYS_SOCKET_H 24825eb42bSJan Lentfer #include <sys/socket.h> 25825eb42bSJan Lentfer #endif 26825eb42bSJan Lentfer #ifdef HAVE_NETDB_H 27825eb42bSJan Lentfer #include <netdb.h> 28825eb42bSJan Lentfer #endif 29825eb42bSJan Lentfer #ifdef HAVE_ARPA_INET_H 30825eb42bSJan Lentfer #include <arpa/inet.h> 31825eb42bSJan Lentfer #endif 32825eb42bSJan Lentfer 33*d1b2b5caSJohn Marino /* Returns whether the last label in the name is a root label (a empty label). 34*d1b2b5caSJohn Marino * Note that it is not enough to just test the last character to be 0, 35*d1b2b5caSJohn Marino * because it may be part of the last label itself. 36*d1b2b5caSJohn Marino */ 37*d1b2b5caSJohn Marino static bool 38*d1b2b5caSJohn Marino ldns_dname_last_label_is_root_label(const ldns_rdf* dname) 39*d1b2b5caSJohn Marino { 40*d1b2b5caSJohn Marino size_t src_pos; 41*d1b2b5caSJohn Marino size_t len = 0; 42*d1b2b5caSJohn Marino 43*d1b2b5caSJohn Marino for (src_pos = 0; src_pos < ldns_rdf_size(dname); src_pos += len + 1) { 44*d1b2b5caSJohn Marino len = ldns_rdf_data(dname)[src_pos]; 45*d1b2b5caSJohn Marino } 46*d1b2b5caSJohn Marino assert(src_pos == ldns_rdf_size(dname)); 47*d1b2b5caSJohn Marino 48*d1b2b5caSJohn Marino return src_pos > 0 && len == 0; 49*d1b2b5caSJohn Marino } 50*d1b2b5caSJohn Marino 51825eb42bSJan Lentfer ldns_rdf * 52825eb42bSJan Lentfer ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2) 53825eb42bSJan Lentfer { 54825eb42bSJan Lentfer ldns_rdf *new; 55825eb42bSJan Lentfer uint16_t new_size; 56825eb42bSJan Lentfer uint8_t *buf; 57825eb42bSJan Lentfer uint16_t left_size; 58825eb42bSJan Lentfer 59825eb42bSJan Lentfer if (ldns_rdf_get_type(rd1) != LDNS_RDF_TYPE_DNAME || 60825eb42bSJan Lentfer ldns_rdf_get_type(rd2) != LDNS_RDF_TYPE_DNAME) { 61825eb42bSJan Lentfer return NULL; 62825eb42bSJan Lentfer } 63825eb42bSJan Lentfer 64825eb42bSJan Lentfer /* remove root label if it is present at the end of the left 65825eb42bSJan Lentfer * rd, by reducing the size with 1 66825eb42bSJan Lentfer */ 67825eb42bSJan Lentfer left_size = ldns_rdf_size(rd1); 68*d1b2b5caSJohn Marino if (ldns_dname_last_label_is_root_label(rd1)) { 69825eb42bSJan Lentfer left_size--; 70825eb42bSJan Lentfer } 71825eb42bSJan Lentfer 72825eb42bSJan Lentfer /* we overwrite the nullbyte of rd1 */ 73825eb42bSJan Lentfer new_size = left_size + ldns_rdf_size(rd2); 74825eb42bSJan Lentfer buf = LDNS_XMALLOC(uint8_t, new_size); 75825eb42bSJan Lentfer if (!buf) { 76825eb42bSJan Lentfer return NULL; 77825eb42bSJan Lentfer } 78825eb42bSJan Lentfer 79825eb42bSJan Lentfer /* put the two dname's after each other */ 80825eb42bSJan Lentfer memcpy(buf, ldns_rdf_data(rd1), left_size); 81825eb42bSJan Lentfer memcpy(buf + left_size, ldns_rdf_data(rd2), ldns_rdf_size(rd2)); 82825eb42bSJan Lentfer 83825eb42bSJan Lentfer new = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, new_size, buf); 84825eb42bSJan Lentfer 85825eb42bSJan Lentfer LDNS_FREE(buf); 86825eb42bSJan Lentfer return new; 87825eb42bSJan Lentfer } 88825eb42bSJan Lentfer 89825eb42bSJan Lentfer ldns_status 90825eb42bSJan Lentfer ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2) 91825eb42bSJan Lentfer { 92825eb42bSJan Lentfer uint16_t left_size; 93825eb42bSJan Lentfer uint16_t size; 94ac996e71SJan Lentfer uint8_t* newd; 95825eb42bSJan Lentfer 96825eb42bSJan Lentfer if (ldns_rdf_get_type(rd1) != LDNS_RDF_TYPE_DNAME || 97825eb42bSJan Lentfer ldns_rdf_get_type(rd2) != LDNS_RDF_TYPE_DNAME) { 98825eb42bSJan Lentfer return LDNS_STATUS_ERR; 99825eb42bSJan Lentfer } 100825eb42bSJan Lentfer 101825eb42bSJan Lentfer /* remove root label if it is present at the end of the left 102825eb42bSJan Lentfer * rd, by reducing the size with 1 103825eb42bSJan Lentfer */ 104825eb42bSJan Lentfer left_size = ldns_rdf_size(rd1); 105*d1b2b5caSJohn Marino if (ldns_dname_last_label_is_root_label(rd1)) { 106825eb42bSJan Lentfer left_size--; 107825eb42bSJan Lentfer } 108825eb42bSJan Lentfer 109825eb42bSJan Lentfer size = left_size + ldns_rdf_size(rd2); 110ac996e71SJan Lentfer newd = LDNS_XREALLOC(ldns_rdf_data(rd1), uint8_t, size); 111ac996e71SJan Lentfer if(!newd) { 112ac996e71SJan Lentfer return LDNS_STATUS_MEM_ERR; 113ac996e71SJan Lentfer } 114825eb42bSJan Lentfer 115ac996e71SJan Lentfer ldns_rdf_set_data(rd1, newd); 116825eb42bSJan Lentfer memcpy(ldns_rdf_data(rd1) + left_size, ldns_rdf_data(rd2), 117825eb42bSJan Lentfer ldns_rdf_size(rd2)); 118825eb42bSJan Lentfer ldns_rdf_set_size(rd1, size); 119825eb42bSJan Lentfer 120825eb42bSJan Lentfer return LDNS_STATUS_OK; 121825eb42bSJan Lentfer } 122825eb42bSJan Lentfer 123825eb42bSJan Lentfer ldns_rdf* 124*d1b2b5caSJohn Marino ldns_dname_reverse(const ldns_rdf *dname) 125825eb42bSJan Lentfer { 126*d1b2b5caSJohn Marino size_t rd_size; 127*d1b2b5caSJohn Marino uint8_t* buf; 128825eb42bSJan Lentfer ldns_rdf* new; 129*d1b2b5caSJohn Marino size_t src_pos; 130*d1b2b5caSJohn Marino size_t len ; 131825eb42bSJan Lentfer 132*d1b2b5caSJohn Marino assert(ldns_rdf_get_type(dname) == LDNS_RDF_TYPE_DNAME); 133825eb42bSJan Lentfer 134*d1b2b5caSJohn Marino rd_size = ldns_rdf_size(dname); 135*d1b2b5caSJohn Marino buf = LDNS_XMALLOC(uint8_t, rd_size); 136*d1b2b5caSJohn Marino if (! buf) { 137ac996e71SJan Lentfer return NULL; 138ac996e71SJan Lentfer } 139*d1b2b5caSJohn Marino new = ldns_rdf_new(LDNS_RDF_TYPE_DNAME, rd_size, buf); 140*d1b2b5caSJohn Marino if (! new) { 141*d1b2b5caSJohn Marino LDNS_FREE(buf); 142*d1b2b5caSJohn Marino return NULL; 143825eb42bSJan Lentfer } 144825eb42bSJan Lentfer 145*d1b2b5caSJohn Marino /* If dname ends in a root label, the reverse should too. 146*d1b2b5caSJohn Marino */ 147*d1b2b5caSJohn Marino if (ldns_dname_last_label_is_root_label(dname)) { 148*d1b2b5caSJohn Marino buf[rd_size - 1] = 0; 149*d1b2b5caSJohn Marino rd_size -= 1; 150*d1b2b5caSJohn Marino } 151*d1b2b5caSJohn Marino for (src_pos = 0; src_pos < rd_size; src_pos += len + 1) { 152*d1b2b5caSJohn Marino len = ldns_rdf_data(dname)[src_pos]; 153*d1b2b5caSJohn Marino memcpy(&buf[rd_size - src_pos - len - 1], 154*d1b2b5caSJohn Marino &ldns_rdf_data(dname)[src_pos], len + 1); 155*d1b2b5caSJohn Marino } 156825eb42bSJan Lentfer return new; 157825eb42bSJan Lentfer } 158825eb42bSJan Lentfer 159825eb42bSJan Lentfer ldns_rdf * 160825eb42bSJan Lentfer ldns_dname_clone_from(const ldns_rdf *d, uint16_t n) 161825eb42bSJan Lentfer { 162825eb42bSJan Lentfer uint8_t *data; 163825eb42bSJan Lentfer uint8_t label_size; 164825eb42bSJan Lentfer size_t data_size; 165825eb42bSJan Lentfer 166825eb42bSJan Lentfer if (!d || 167825eb42bSJan Lentfer ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME || 168825eb42bSJan Lentfer ldns_dname_label_count(d) < n) { 169825eb42bSJan Lentfer return NULL; 170825eb42bSJan Lentfer } 171825eb42bSJan Lentfer 172825eb42bSJan Lentfer data = ldns_rdf_data(d); 173825eb42bSJan Lentfer data_size = ldns_rdf_size(d); 174825eb42bSJan Lentfer while (n > 0) { 175825eb42bSJan Lentfer label_size = data[0] + 1; 176825eb42bSJan Lentfer data += label_size; 177825eb42bSJan Lentfer if (data_size < label_size) { 178825eb42bSJan Lentfer /* this label is very broken */ 179825eb42bSJan Lentfer return NULL; 180825eb42bSJan Lentfer } 181825eb42bSJan Lentfer data_size -= label_size; 182825eb42bSJan Lentfer n--; 183825eb42bSJan Lentfer } 184825eb42bSJan Lentfer 185825eb42bSJan Lentfer return ldns_dname_new_frm_data(data_size, data); 186825eb42bSJan Lentfer } 187825eb42bSJan Lentfer 188825eb42bSJan Lentfer ldns_rdf * 189825eb42bSJan Lentfer ldns_dname_left_chop(const ldns_rdf *d) 190825eb42bSJan Lentfer { 191825eb42bSJan Lentfer uint8_t label_pos; 192825eb42bSJan Lentfer ldns_rdf *chop; 193825eb42bSJan Lentfer 194825eb42bSJan Lentfer if (!d) { 195825eb42bSJan Lentfer return NULL; 196825eb42bSJan Lentfer } 197825eb42bSJan Lentfer 198825eb42bSJan Lentfer if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) { 199825eb42bSJan Lentfer return NULL; 200825eb42bSJan Lentfer } 201825eb42bSJan Lentfer if (ldns_dname_label_count(d) == 0) { 202825eb42bSJan Lentfer /* root label */ 203825eb42bSJan Lentfer return NULL; 204825eb42bSJan Lentfer } 205825eb42bSJan Lentfer /* 05blaat02nl00 */ 206825eb42bSJan Lentfer label_pos = ldns_rdf_data(d)[0]; 207825eb42bSJan Lentfer 208825eb42bSJan Lentfer chop = ldns_dname_new_frm_data(ldns_rdf_size(d) - label_pos - 1, 209825eb42bSJan Lentfer ldns_rdf_data(d) + label_pos + 1); 210825eb42bSJan Lentfer return chop; 211825eb42bSJan Lentfer } 212825eb42bSJan Lentfer 213825eb42bSJan Lentfer uint8_t 214825eb42bSJan Lentfer ldns_dname_label_count(const ldns_rdf *r) 215825eb42bSJan Lentfer { 216825eb42bSJan Lentfer uint16_t src_pos; 217825eb42bSJan Lentfer uint16_t len; 218825eb42bSJan Lentfer uint8_t i; 219825eb42bSJan Lentfer size_t r_size; 220825eb42bSJan Lentfer 221825eb42bSJan Lentfer if (!r) { 222825eb42bSJan Lentfer return 0; 223825eb42bSJan Lentfer } 224825eb42bSJan Lentfer 225825eb42bSJan Lentfer i = 0; 226825eb42bSJan Lentfer src_pos = 0; 227825eb42bSJan Lentfer r_size = ldns_rdf_size(r); 228825eb42bSJan Lentfer 229825eb42bSJan Lentfer if (ldns_rdf_get_type(r) != LDNS_RDF_TYPE_DNAME) { 230825eb42bSJan Lentfer return 0; 231825eb42bSJan Lentfer } else { 232825eb42bSJan Lentfer len = ldns_rdf_data(r)[src_pos]; /* start of the label */ 233825eb42bSJan Lentfer 234825eb42bSJan Lentfer /* single root label */ 235825eb42bSJan Lentfer if (1 == r_size) { 236825eb42bSJan Lentfer return 0; 237825eb42bSJan Lentfer } else { 238825eb42bSJan Lentfer while ((len > 0) && src_pos < r_size) { 239825eb42bSJan Lentfer src_pos++; 240825eb42bSJan Lentfer src_pos += len; 241825eb42bSJan Lentfer len = ldns_rdf_data(r)[src_pos]; 242825eb42bSJan Lentfer i++; 243825eb42bSJan Lentfer } 244825eb42bSJan Lentfer } 245825eb42bSJan Lentfer } 246825eb42bSJan Lentfer return i; 247825eb42bSJan Lentfer } 248825eb42bSJan Lentfer 249825eb42bSJan Lentfer ldns_rdf * 250825eb42bSJan Lentfer ldns_dname_new(uint16_t s, void *d) 251825eb42bSJan Lentfer { 252825eb42bSJan Lentfer ldns_rdf *rd; 253825eb42bSJan Lentfer 254825eb42bSJan Lentfer rd = LDNS_MALLOC(ldns_rdf); 255825eb42bSJan Lentfer if (!rd) { 256825eb42bSJan Lentfer return NULL; 257825eb42bSJan Lentfer } 258825eb42bSJan Lentfer ldns_rdf_set_size(rd, s); 259825eb42bSJan Lentfer ldns_rdf_set_type(rd, LDNS_RDF_TYPE_DNAME); 260825eb42bSJan Lentfer ldns_rdf_set_data(rd, d); 261825eb42bSJan Lentfer return rd; 262825eb42bSJan Lentfer } 263825eb42bSJan Lentfer 264825eb42bSJan Lentfer ldns_rdf * 265825eb42bSJan Lentfer ldns_dname_new_frm_str(const char *str) 266825eb42bSJan Lentfer { 267825eb42bSJan Lentfer return ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, str); 268825eb42bSJan Lentfer } 269825eb42bSJan Lentfer 270825eb42bSJan Lentfer ldns_rdf * 271825eb42bSJan Lentfer ldns_dname_new_frm_data(uint16_t size, const void *data) 272825eb42bSJan Lentfer { 273825eb42bSJan Lentfer return ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, size, data); 274825eb42bSJan Lentfer } 275825eb42bSJan Lentfer 276825eb42bSJan Lentfer void 277825eb42bSJan Lentfer ldns_dname2canonical(const ldns_rdf *rd) 278825eb42bSJan Lentfer { 279825eb42bSJan Lentfer uint8_t *rdd; 280825eb42bSJan Lentfer uint16_t i; 281825eb42bSJan Lentfer 282825eb42bSJan Lentfer if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_DNAME) { 283825eb42bSJan Lentfer return; 284825eb42bSJan Lentfer } 285825eb42bSJan Lentfer 286825eb42bSJan Lentfer rdd = (uint8_t*)ldns_rdf_data(rd); 287825eb42bSJan Lentfer for (i = 0; i < ldns_rdf_size(rd); i++, rdd++) { 288825eb42bSJan Lentfer *rdd = (uint8_t)LDNS_DNAME_NORMALIZE((int)*rdd); 289825eb42bSJan Lentfer } 290825eb42bSJan Lentfer } 291825eb42bSJan Lentfer 292825eb42bSJan Lentfer bool 293825eb42bSJan Lentfer ldns_dname_is_subdomain(const ldns_rdf *sub, const ldns_rdf *parent) 294825eb42bSJan Lentfer { 295825eb42bSJan Lentfer uint8_t sub_lab; 296825eb42bSJan Lentfer uint8_t par_lab; 297825eb42bSJan Lentfer int8_t i, j; 298825eb42bSJan Lentfer ldns_rdf *tmp_sub = NULL; 299825eb42bSJan Lentfer ldns_rdf *tmp_par = NULL; 300825eb42bSJan Lentfer ldns_rdf *sub_clone; 301825eb42bSJan Lentfer ldns_rdf *parent_clone; 302825eb42bSJan Lentfer bool result = true; 303825eb42bSJan Lentfer 304825eb42bSJan Lentfer if (ldns_rdf_get_type(sub) != LDNS_RDF_TYPE_DNAME || 305825eb42bSJan Lentfer ldns_rdf_get_type(parent) != LDNS_RDF_TYPE_DNAME || 306825eb42bSJan Lentfer ldns_rdf_compare(sub, parent) == 0) { 307825eb42bSJan Lentfer return false; 308825eb42bSJan Lentfer } 309825eb42bSJan Lentfer 310825eb42bSJan Lentfer /* would be nicer if we do not have to clone... */ 311825eb42bSJan Lentfer sub_clone = ldns_dname_clone_from(sub, 0); 312825eb42bSJan Lentfer parent_clone = ldns_dname_clone_from(parent, 0); 313825eb42bSJan Lentfer ldns_dname2canonical(sub_clone); 314825eb42bSJan Lentfer ldns_dname2canonical(parent_clone); 315825eb42bSJan Lentfer 316825eb42bSJan Lentfer sub_lab = ldns_dname_label_count(sub_clone); 317825eb42bSJan Lentfer par_lab = ldns_dname_label_count(parent_clone); 318825eb42bSJan Lentfer 319825eb42bSJan Lentfer /* if sub sits above parent, it cannot be a child/sub domain */ 320825eb42bSJan Lentfer if (sub_lab < par_lab) { 321825eb42bSJan Lentfer result = false; 322825eb42bSJan Lentfer } else { 323825eb42bSJan Lentfer /* check all labels the from the parent labels, from right to left. 324825eb42bSJan Lentfer * When they /all/ match we have found a subdomain 325825eb42bSJan Lentfer */ 326825eb42bSJan Lentfer j = sub_lab - 1; /* we count from zero, thank you */ 327825eb42bSJan Lentfer for (i = par_lab -1; i >= 0; i--) { 328825eb42bSJan Lentfer tmp_sub = ldns_dname_label(sub_clone, j); 329825eb42bSJan Lentfer tmp_par = ldns_dname_label(parent_clone, i); 330825eb42bSJan Lentfer if (!tmp_sub || !tmp_par) { 331825eb42bSJan Lentfer /* deep free does null check */ 332825eb42bSJan Lentfer ldns_rdf_deep_free(tmp_sub); 333825eb42bSJan Lentfer ldns_rdf_deep_free(tmp_par); 334825eb42bSJan Lentfer result = false; 335825eb42bSJan Lentfer break; 336825eb42bSJan Lentfer } 337825eb42bSJan Lentfer 338825eb42bSJan Lentfer if (ldns_rdf_compare(tmp_sub, tmp_par) != 0) { 339825eb42bSJan Lentfer /* they are not equal */ 340825eb42bSJan Lentfer ldns_rdf_deep_free(tmp_sub); 341825eb42bSJan Lentfer ldns_rdf_deep_free(tmp_par); 342825eb42bSJan Lentfer result = false; 343825eb42bSJan Lentfer break; 344825eb42bSJan Lentfer } 345825eb42bSJan Lentfer ldns_rdf_deep_free(tmp_sub); 346825eb42bSJan Lentfer ldns_rdf_deep_free(tmp_par); 347825eb42bSJan Lentfer j--; 348825eb42bSJan Lentfer } 349825eb42bSJan Lentfer } 350825eb42bSJan Lentfer ldns_rdf_deep_free(sub_clone); 351825eb42bSJan Lentfer ldns_rdf_deep_free(parent_clone); 352825eb42bSJan Lentfer return result; 353825eb42bSJan Lentfer } 354825eb42bSJan Lentfer 355825eb42bSJan Lentfer int 356825eb42bSJan Lentfer ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2) 357825eb42bSJan Lentfer { 358825eb42bSJan Lentfer size_t lc1, lc2, lc1f, lc2f; 359825eb42bSJan Lentfer size_t i; 360825eb42bSJan Lentfer int result = 0; 361825eb42bSJan Lentfer uint8_t *lp1, *lp2; 362825eb42bSJan Lentfer 363825eb42bSJan Lentfer /* see RFC4034 for this algorithm */ 364825eb42bSJan Lentfer /* this algorithm assumes the names are normalized to case */ 365825eb42bSJan Lentfer 366825eb42bSJan Lentfer /* only when both are not NULL we can say anything about them */ 367825eb42bSJan Lentfer if (!dname1 && !dname2) { 368825eb42bSJan Lentfer return 0; 369825eb42bSJan Lentfer } 370825eb42bSJan Lentfer if (!dname1 || !dname2) { 371825eb42bSJan Lentfer return -1; 372825eb42bSJan Lentfer } 373825eb42bSJan Lentfer /* asserts must happen later as we are looking in the 374825eb42bSJan Lentfer * dname, which could be NULL. But this case is handled 375825eb42bSJan Lentfer * above 376825eb42bSJan Lentfer */ 377825eb42bSJan Lentfer assert(ldns_rdf_get_type(dname1) == LDNS_RDF_TYPE_DNAME); 378825eb42bSJan Lentfer assert(ldns_rdf_get_type(dname2) == LDNS_RDF_TYPE_DNAME); 379825eb42bSJan Lentfer 380825eb42bSJan Lentfer lc1 = ldns_dname_label_count(dname1); 381825eb42bSJan Lentfer lc2 = ldns_dname_label_count(dname2); 382825eb42bSJan Lentfer 383825eb42bSJan Lentfer if (lc1 == 0 && lc2 == 0) { 384825eb42bSJan Lentfer return 0; 385825eb42bSJan Lentfer } 386825eb42bSJan Lentfer if (lc1 == 0) { 387825eb42bSJan Lentfer return -1; 388825eb42bSJan Lentfer } 389825eb42bSJan Lentfer if (lc2 == 0) { 390825eb42bSJan Lentfer return 1; 391825eb42bSJan Lentfer } 392825eb42bSJan Lentfer lc1--; 393825eb42bSJan Lentfer lc2--; 394825eb42bSJan Lentfer /* we start at the last label */ 395825eb42bSJan Lentfer while (true) { 396825eb42bSJan Lentfer /* find the label first */ 397825eb42bSJan Lentfer lc1f = lc1; 398825eb42bSJan Lentfer lp1 = ldns_rdf_data(dname1); 399825eb42bSJan Lentfer while (lc1f > 0) { 400825eb42bSJan Lentfer lp1 += *lp1 + 1; 401825eb42bSJan Lentfer lc1f--; 402825eb42bSJan Lentfer } 403825eb42bSJan Lentfer 404825eb42bSJan Lentfer /* and find the other one */ 405825eb42bSJan Lentfer lc2f = lc2; 406825eb42bSJan Lentfer lp2 = ldns_rdf_data(dname2); 407825eb42bSJan Lentfer while (lc2f > 0) { 408825eb42bSJan Lentfer lp2 += *lp2 + 1; 409825eb42bSJan Lentfer lc2f--; 410825eb42bSJan Lentfer } 411825eb42bSJan Lentfer 412825eb42bSJan Lentfer /* now check the label character for character. */ 413825eb42bSJan Lentfer for (i = 1; i < (size_t)(*lp1 + 1); i++) { 414825eb42bSJan Lentfer if (i > *lp2) { 415825eb42bSJan Lentfer /* apparently label 1 is larger */ 416825eb42bSJan Lentfer result = 1; 417825eb42bSJan Lentfer goto done; 418825eb42bSJan Lentfer } 419825eb42bSJan Lentfer if (LDNS_DNAME_NORMALIZE((int) *(lp1 + i)) < 420825eb42bSJan Lentfer LDNS_DNAME_NORMALIZE((int) *(lp2 + i))) { 421825eb42bSJan Lentfer result = -1; 422825eb42bSJan Lentfer goto done; 423825eb42bSJan Lentfer } else if (LDNS_DNAME_NORMALIZE((int) *(lp1 + i)) > 424825eb42bSJan Lentfer LDNS_DNAME_NORMALIZE((int) *(lp2 + i))) { 425825eb42bSJan Lentfer result = 1; 426825eb42bSJan Lentfer goto done; 427825eb42bSJan Lentfer } 428825eb42bSJan Lentfer } 429825eb42bSJan Lentfer if (*lp1 < *lp2) { 430825eb42bSJan Lentfer /* apparently label 2 is larger */ 431825eb42bSJan Lentfer result = -1; 432825eb42bSJan Lentfer goto done; 433825eb42bSJan Lentfer } 434825eb42bSJan Lentfer if (lc1 == 0 && lc2 > 0) { 435825eb42bSJan Lentfer result = -1; 436825eb42bSJan Lentfer goto done; 437825eb42bSJan Lentfer } else if (lc1 > 0 && lc2 == 0) { 438825eb42bSJan Lentfer result = 1; 439825eb42bSJan Lentfer goto done; 440825eb42bSJan Lentfer } else if (lc1 == 0 && lc2 == 0) { 441825eb42bSJan Lentfer result = 0; 442825eb42bSJan Lentfer goto done; 443825eb42bSJan Lentfer } 444825eb42bSJan Lentfer lc1--; 445825eb42bSJan Lentfer lc2--; 446825eb42bSJan Lentfer } 447825eb42bSJan Lentfer 448825eb42bSJan Lentfer done: 449825eb42bSJan Lentfer return result; 450825eb42bSJan Lentfer } 451825eb42bSJan Lentfer 452825eb42bSJan Lentfer int 453ac996e71SJan Lentfer ldns_dname_is_wildcard(const ldns_rdf* dname) 454ac996e71SJan Lentfer { 455ac996e71SJan Lentfer return ( ldns_dname_label_count(dname) > 0 && 456ac996e71SJan Lentfer ldns_rdf_data(dname)[0] == 1 && 457ac996e71SJan Lentfer ldns_rdf_data(dname)[1] == '*'); 458ac996e71SJan Lentfer } 459ac996e71SJan Lentfer 460ac996e71SJan Lentfer int 461825eb42bSJan Lentfer ldns_dname_match_wildcard(const ldns_rdf *dname, const ldns_rdf *wildcard) 462825eb42bSJan Lentfer { 463825eb42bSJan Lentfer ldns_rdf *wc_chopped; 464825eb42bSJan Lentfer int result; 465825eb42bSJan Lentfer /* check whether it really is a wildcard */ 466ac996e71SJan Lentfer if (ldns_dname_is_wildcard(wildcard)) { 467825eb42bSJan Lentfer /* ok, so the dname needs to be a subdomain of the wildcard 468825eb42bSJan Lentfer * without the * 469825eb42bSJan Lentfer */ 470825eb42bSJan Lentfer wc_chopped = ldns_dname_left_chop(wildcard); 471825eb42bSJan Lentfer result = (int) ldns_dname_is_subdomain(dname, wc_chopped); 472825eb42bSJan Lentfer ldns_rdf_deep_free(wc_chopped); 473825eb42bSJan Lentfer } else { 474825eb42bSJan Lentfer result = (ldns_dname_compare(dname, wildcard) == 0); 475825eb42bSJan Lentfer } 476825eb42bSJan Lentfer return result; 477825eb42bSJan Lentfer } 478825eb42bSJan Lentfer 479825eb42bSJan Lentfer /* nsec test: does prev <= middle < next 480825eb42bSJan Lentfer * -1 = yes 481825eb42bSJan Lentfer * 0 = error/can't tell 482825eb42bSJan Lentfer * 1 = no 483825eb42bSJan Lentfer */ 484825eb42bSJan Lentfer int 485825eb42bSJan Lentfer ldns_dname_interval(const ldns_rdf *prev, const ldns_rdf *middle, 486825eb42bSJan Lentfer const ldns_rdf *next) 487825eb42bSJan Lentfer { 488825eb42bSJan Lentfer int prev_check, next_check; 489825eb42bSJan Lentfer 490825eb42bSJan Lentfer assert(ldns_rdf_get_type(prev) == LDNS_RDF_TYPE_DNAME); 491825eb42bSJan Lentfer assert(ldns_rdf_get_type(middle) == LDNS_RDF_TYPE_DNAME); 492825eb42bSJan Lentfer assert(ldns_rdf_get_type(next) == LDNS_RDF_TYPE_DNAME); 493825eb42bSJan Lentfer 494825eb42bSJan Lentfer prev_check = ldns_dname_compare(prev, middle); 495825eb42bSJan Lentfer next_check = ldns_dname_compare(middle, next); 496825eb42bSJan Lentfer /* <= next. This cannot be the case for nsec, because then we would 497825eb42bSJan Lentfer * have gotten the nsec of next... 498825eb42bSJan Lentfer */ 499825eb42bSJan Lentfer if (next_check == 0) { 500825eb42bSJan Lentfer return 0; 501825eb42bSJan Lentfer } 502825eb42bSJan Lentfer 503825eb42bSJan Lentfer /* <= */ 504825eb42bSJan Lentfer if ((prev_check == -1 || prev_check == 0) && 505825eb42bSJan Lentfer /* < */ 506825eb42bSJan Lentfer next_check == -1) { 507825eb42bSJan Lentfer return -1; 508825eb42bSJan Lentfer } else { 509825eb42bSJan Lentfer return 1; 510825eb42bSJan Lentfer } 511825eb42bSJan Lentfer } 512825eb42bSJan Lentfer 513825eb42bSJan Lentfer 514825eb42bSJan Lentfer bool 515825eb42bSJan Lentfer ldns_dname_str_absolute(const char *dname_str) 516825eb42bSJan Lentfer { 517ac996e71SJan Lentfer const char* s; 518825eb42bSJan Lentfer if(dname_str && strcmp(dname_str, ".") == 0) 519825eb42bSJan Lentfer return 1; 520ac996e71SJan Lentfer if(!dname_str || strlen(dname_str) < 2) 521ac996e71SJan Lentfer return 0; 522ac996e71SJan Lentfer if(dname_str[strlen(dname_str) - 1] != '.') 523ac996e71SJan Lentfer return 0; 524ac996e71SJan Lentfer if(dname_str[strlen(dname_str) - 2] != '\\') 525ac996e71SJan Lentfer return 1; /* ends in . and no \ before it */ 526ac996e71SJan Lentfer /* so we have the case of ends in . and there is \ before it */ 527ac996e71SJan Lentfer for(s=dname_str; *s; s++) { 528ac996e71SJan Lentfer if(*s == '\\') { 529ac996e71SJan Lentfer if(s[1] && s[2] && s[3] /* check length */ 530ac996e71SJan Lentfer && isdigit(s[1]) && isdigit(s[2]) && 531ac996e71SJan Lentfer isdigit(s[3])) 532ac996e71SJan Lentfer s += 3; 533ac996e71SJan Lentfer else if(!s[1] || isdigit(s[1])) /* escape of nul,0-9 */ 534ac996e71SJan Lentfer return 0; /* parse error */ 535ac996e71SJan Lentfer else s++; /* another character escaped */ 536ac996e71SJan Lentfer } 537ac996e71SJan Lentfer else if(!*(s+1) && *s == '.') 538ac996e71SJan Lentfer return 1; /* trailing dot, unescaped */ 539ac996e71SJan Lentfer } 540ac996e71SJan Lentfer return 0; 541825eb42bSJan Lentfer } 542825eb42bSJan Lentfer 543*d1b2b5caSJohn Marino bool 544*d1b2b5caSJohn Marino ldns_dname_absolute(const ldns_rdf *rdf) 545*d1b2b5caSJohn Marino { 546*d1b2b5caSJohn Marino char *str = ldns_rdf2str(rdf); 547*d1b2b5caSJohn Marino if (str) { 548*d1b2b5caSJohn Marino bool r = ldns_dname_str_absolute(str); 549*d1b2b5caSJohn Marino LDNS_FREE(str); 550*d1b2b5caSJohn Marino return r; 551*d1b2b5caSJohn Marino } 552*d1b2b5caSJohn Marino return false; 553*d1b2b5caSJohn Marino } 554*d1b2b5caSJohn Marino 555825eb42bSJan Lentfer ldns_rdf * 556825eb42bSJan Lentfer ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos) 557825eb42bSJan Lentfer { 558825eb42bSJan Lentfer uint8_t labelcnt; 559825eb42bSJan Lentfer uint16_t src_pos; 560825eb42bSJan Lentfer uint16_t len; 561825eb42bSJan Lentfer ldns_rdf *tmpnew; 562825eb42bSJan Lentfer size_t s; 563*d1b2b5caSJohn Marino uint8_t *data; 564825eb42bSJan Lentfer 565825eb42bSJan Lentfer if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_DNAME) { 566825eb42bSJan Lentfer return NULL; 567825eb42bSJan Lentfer } 568825eb42bSJan Lentfer 569825eb42bSJan Lentfer labelcnt = 0; 570825eb42bSJan Lentfer src_pos = 0; 571825eb42bSJan Lentfer s = ldns_rdf_size(rdf); 572825eb42bSJan Lentfer 573825eb42bSJan Lentfer len = ldns_rdf_data(rdf)[src_pos]; /* label start */ 574825eb42bSJan Lentfer while ((len > 0) && src_pos < s) { 575825eb42bSJan Lentfer if (labelcnt == labelpos) { 576825eb42bSJan Lentfer /* found our label */ 577*d1b2b5caSJohn Marino data = LDNS_XMALLOC(uint8_t, len + 2); 578*d1b2b5caSJohn Marino if (!data) { 579*d1b2b5caSJohn Marino return NULL; 580*d1b2b5caSJohn Marino } 581*d1b2b5caSJohn Marino memcpy(data, ldns_rdf_data(rdf) + src_pos, len + 1); 582*d1b2b5caSJohn Marino data[len + 2 - 1] = 0; 583*d1b2b5caSJohn Marino 584*d1b2b5caSJohn Marino tmpnew = ldns_rdf_new( LDNS_RDF_TYPE_DNAME 585*d1b2b5caSJohn Marino , len + 2, data); 586825eb42bSJan Lentfer if (!tmpnew) { 587*d1b2b5caSJohn Marino LDNS_FREE(data); 588825eb42bSJan Lentfer return NULL; 589825eb42bSJan Lentfer } 590825eb42bSJan Lentfer return tmpnew; 591825eb42bSJan Lentfer } 592825eb42bSJan Lentfer src_pos++; 593825eb42bSJan Lentfer src_pos += len; 594825eb42bSJan Lentfer len = ldns_rdf_data(rdf)[src_pos]; 595825eb42bSJan Lentfer labelcnt++; 596825eb42bSJan Lentfer } 597825eb42bSJan Lentfer return NULL; 598825eb42bSJan Lentfer } 599