1 /* 2 * util/data/msgparse.c - parse wireformat DNS messages. 3 * 4 * Copyright (c) 2007, NLnet Labs. All rights reserved. 5 * 6 * This software is open source. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 19 * Neither the name of the NLNET LABS nor the names of its contributors may 20 * be used to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 * POSSIBILITY OF SUCH DAMAGE. 34 */ 35 /** 36 * \file 37 * Routines for message parsing a packet buffer to a descriptive structure. 38 */ 39 #include "config.h" 40 #include <ldns/ldns.h> 41 #include "util/data/msgparse.h" 42 #include "util/data/dname.h" 43 #include "util/data/packed_rrset.h" 44 #include "util/storage/lookup3.h" 45 #include "util/regional.h" 46 47 /** smart comparison of (compressed, valid) dnames from packet */ 48 static int 49 smart_compare(ldns_buffer* pkt, uint8_t* dnow, 50 uint8_t* dprfirst, uint8_t* dprlast) 51 { 52 if(LABEL_IS_PTR(*dnow)) { 53 /* ptr points to a previous dname */ 54 uint8_t* p = ldns_buffer_at(pkt, PTR_OFFSET(dnow[0], dnow[1])); 55 if( p == dprfirst || p == dprlast ) 56 return 0; 57 /* prev dname is also a ptr, both ptrs are the same. */ 58 if(LABEL_IS_PTR(*dprlast) && 59 dprlast[0] == dnow[0] && dprlast[1] == dnow[1]) 60 return 0; 61 } 62 return dname_pkt_compare(pkt, dnow, dprlast); 63 } 64 65 /** 66 * Allocate new rrset in region, fill with data. 67 */ 68 static struct rrset_parse* 69 new_rrset(struct msg_parse* msg, uint8_t* dname, size_t dnamelen, 70 uint16_t type, uint16_t dclass, hashvalue_t hash, 71 uint32_t rrset_flags, ldns_pkt_section section, 72 struct regional* region) 73 { 74 struct rrset_parse* p = regional_alloc(region, sizeof(*p)); 75 if(!p) return NULL; 76 p->rrset_bucket_next = msg->hashtable[hash & (PARSE_TABLE_SIZE-1)]; 77 msg->hashtable[hash & (PARSE_TABLE_SIZE-1)] = p; 78 p->rrset_all_next = 0; 79 if(msg->rrset_last) 80 msg->rrset_last->rrset_all_next = p; 81 else msg->rrset_first = p; 82 msg->rrset_last = p; 83 p->hash = hash; 84 p->section = section; 85 p->dname = dname; 86 p->dname_len = dnamelen; 87 p->type = type; 88 p->rrset_class = dclass; 89 p->flags = rrset_flags; 90 p->rr_count = 0; 91 p->size = 0; 92 p->rr_first = 0; 93 p->rr_last = 0; 94 p->rrsig_count = 0; 95 p->rrsig_first = 0; 96 p->rrsig_last = 0; 97 return p; 98 } 99 100 /** See if next rrset is nsec at zone apex */ 101 static int 102 nsec_at_apex(ldns_buffer* pkt) 103 { 104 /* we are at ttl position in packet. */ 105 size_t pos = ldns_buffer_position(pkt); 106 uint16_t rdatalen; 107 if(ldns_buffer_remaining(pkt) < 7) /* ttl+len+root */ 108 return 0; /* eek! */ 109 ldns_buffer_skip(pkt, 4); /* ttl */; 110 rdatalen = ldns_buffer_read_u16(pkt); 111 if(ldns_buffer_remaining(pkt) < rdatalen) { 112 ldns_buffer_set_position(pkt, pos); 113 return 0; /* parse error happens later */ 114 } 115 /* must validate the nsec next domain name format */ 116 if(pkt_dname_len(pkt) == 0) { 117 ldns_buffer_set_position(pkt, pos); 118 return 0; /* parse error */ 119 } 120 121 /* see if SOA bit is set. */ 122 if(ldns_buffer_position(pkt) < pos+4+rdatalen) { 123 /* nsec type bitmap contains items */ 124 uint8_t win, blen, bits; 125 /* need: windownum, bitmap len, firstbyte */ 126 if(ldns_buffer_position(pkt)+3 > pos+4+rdatalen) { 127 ldns_buffer_set_position(pkt, pos); 128 return 0; /* malformed nsec */ 129 } 130 win = ldns_buffer_read_u8(pkt); 131 blen = ldns_buffer_read_u8(pkt); 132 bits = ldns_buffer_read_u8(pkt); 133 /* 0window always first window. bitlen >=1 or parse 134 error really. bit 0x2 is SOA. */ 135 if(win == 0 && blen >= 1 && (bits & 0x02)) { 136 ldns_buffer_set_position(pkt, pos); 137 return 1; 138 } 139 } 140 141 ldns_buffer_set_position(pkt, pos); 142 return 0; 143 } 144 145 /** Calculate rrset flags */ 146 static uint32_t 147 pkt_rrset_flags(ldns_buffer* pkt, uint16_t type, ldns_pkt_section sec) 148 { 149 uint32_t f = 0; 150 if(type == LDNS_RR_TYPE_NSEC && nsec_at_apex(pkt)) { 151 f |= PACKED_RRSET_NSEC_AT_APEX; 152 } else if(type == LDNS_RR_TYPE_SOA && sec == LDNS_SECTION_AUTHORITY) { 153 f |= PACKED_RRSET_SOA_NEG; 154 } 155 return f; 156 } 157 158 hashvalue_t 159 pkt_hash_rrset(ldns_buffer* pkt, uint8_t* dname, uint16_t type, 160 uint16_t dclass, uint32_t rrset_flags) 161 { 162 /* note this MUST be identical to rrset_key_hash in packed_rrset.c */ 163 /* this routine handles compressed names */ 164 hashvalue_t h = 0xab; 165 h = dname_pkt_hash(pkt, dname, h); 166 h = hashlittle(&type, sizeof(type), h); /* host order */ 167 h = hashlittle(&dclass, sizeof(dclass), h); /* netw order */ 168 h = hashlittle(&rrset_flags, sizeof(uint32_t), h); 169 return h; 170 } 171 172 /** create partial dname hash for rrset hash */ 173 static hashvalue_t 174 pkt_hash_rrset_first(ldns_buffer* pkt, uint8_t* dname) 175 { 176 /* works together with pkt_hash_rrset_rest */ 177 /* note this MUST be identical to rrset_key_hash in packed_rrset.c */ 178 /* this routine handles compressed names */ 179 hashvalue_t h = 0xab; 180 h = dname_pkt_hash(pkt, dname, h); 181 return h; 182 } 183 184 /** create a rrset hash from a partial dname hash */ 185 static hashvalue_t 186 pkt_hash_rrset_rest(hashvalue_t dname_h, uint16_t type, uint16_t dclass, 187 uint32_t rrset_flags) 188 { 189 /* works together with pkt_hash_rrset_first */ 190 /* note this MUST be identical to rrset_key_hash in packed_rrset.c */ 191 hashvalue_t h; 192 h = hashlittle(&type, sizeof(type), dname_h); /* host order */ 193 h = hashlittle(&dclass, sizeof(dclass), h); /* netw order */ 194 h = hashlittle(&rrset_flags, sizeof(uint32_t), h); 195 return h; 196 } 197 198 /** compare rrset_parse with data */ 199 static int 200 rrset_parse_equals(struct rrset_parse* p, ldns_buffer* pkt, hashvalue_t h, 201 uint32_t rrset_flags, uint8_t* dname, size_t dnamelen, 202 uint16_t type, uint16_t dclass) 203 { 204 if(p->hash == h && p->dname_len == dnamelen && p->type == type && 205 p->rrset_class == dclass && p->flags == rrset_flags && 206 dname_pkt_compare(pkt, dname, p->dname) == 0) 207 return 1; 208 return 0; 209 } 210 211 212 struct rrset_parse* 213 msgparse_hashtable_lookup(struct msg_parse* msg, ldns_buffer* pkt, 214 hashvalue_t h, uint32_t rrset_flags, uint8_t* dname, size_t dnamelen, 215 uint16_t type, uint16_t dclass) 216 { 217 struct rrset_parse* p = msg->hashtable[h & (PARSE_TABLE_SIZE-1)]; 218 while(p) { 219 if(rrset_parse_equals(p, pkt, h, rrset_flags, dname, dnamelen, 220 type, dclass)) 221 return p; 222 p = p->rrset_bucket_next; 223 } 224 return NULL; 225 } 226 227 /** return type networkformat that rrsig in packet covers */ 228 static int 229 pkt_rrsig_covered(ldns_buffer* pkt, uint8_t* here, uint16_t* type) 230 { 231 size_t pos = ldns_buffer_position(pkt); 232 ldns_buffer_set_position(pkt, (size_t)(here-ldns_buffer_begin(pkt))); 233 /* ttl + len + size of small rrsig(rootlabel, no signature) */ 234 if(ldns_buffer_remaining(pkt) < 4+2+19) 235 return 0; 236 ldns_buffer_skip(pkt, 4); /* ttl */ 237 if(ldns_buffer_read_u16(pkt) < 19) /* too short */ { 238 ldns_buffer_set_position(pkt, pos); 239 return 0; 240 } 241 *type = ldns_buffer_read_u16(pkt); 242 ldns_buffer_set_position(pkt, pos); 243 return 1; 244 } 245 246 /** true if covered type equals prevtype */ 247 static int 248 pkt_rrsig_covered_equals(ldns_buffer* pkt, uint8_t* here, uint16_t type) 249 { 250 uint16_t t; 251 if(pkt_rrsig_covered(pkt, here, &t) && t == type) 252 return 1; 253 return 0; 254 } 255 256 void 257 msgparse_bucket_remove(struct msg_parse* msg, struct rrset_parse* rrset) 258 { 259 struct rrset_parse** p; 260 p = &msg->hashtable[ rrset->hash & (PARSE_TABLE_SIZE-1) ]; 261 while(*p) { 262 if(*p == rrset) { 263 *p = rrset->rrset_bucket_next; 264 return; 265 } 266 p = &( (*p)->rrset_bucket_next ); 267 } 268 } 269 270 /** change section of rrset from previous to current section */ 271 static void 272 change_section(struct msg_parse* msg, struct rrset_parse* rrset, 273 ldns_pkt_section section) 274 { 275 struct rrset_parse *p, *prev; 276 /* remove from list */ 277 if(section == rrset->section) 278 return; 279 p = msg->rrset_first; 280 prev = 0; 281 while(p) { 282 if(p == rrset) { 283 if(prev) prev->rrset_all_next = p->rrset_all_next; 284 else msg->rrset_first = p->rrset_all_next; 285 if(msg->rrset_last == rrset) 286 msg->rrset_last = prev; 287 break; 288 } 289 prev = p; 290 p = p->rrset_all_next; 291 } 292 /* remove from count */ 293 switch(rrset->section) { 294 case LDNS_SECTION_ANSWER: msg->an_rrsets--; break; 295 case LDNS_SECTION_AUTHORITY: msg->ns_rrsets--; break; 296 case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets--; break; 297 default: log_assert(0); 298 } 299 /* insert at end of list */ 300 rrset->rrset_all_next = 0; 301 if(msg->rrset_last) 302 msg->rrset_last->rrset_all_next = rrset; 303 else msg->rrset_first = rrset; 304 msg->rrset_last = rrset; 305 /* up count of new section */ 306 switch(section) { 307 case LDNS_SECTION_AUTHORITY: msg->ns_rrsets++; break; 308 case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets++; break; 309 default: log_assert(0); 310 } 311 rrset->section = section; 312 } 313 314 /** see if rrset of type RRSIG contains sig over given type */ 315 static int 316 rrset_has_sigover(ldns_buffer* pkt, struct rrset_parse* rrset, uint16_t type, 317 int* hasother) 318 { 319 int res = 0; 320 struct rr_parse* rr = rrset->rr_first; 321 log_assert( rrset->type == LDNS_RR_TYPE_RRSIG ); 322 while(rr) { 323 if(pkt_rrsig_covered_equals(pkt, rr->ttl_data, type)) 324 res = 1; 325 else *hasother = 1; 326 rr = rr->next; 327 } 328 return res; 329 } 330 331 /** move rrsigs from sigset to dataset */ 332 static int 333 moveover_rrsigs(ldns_buffer* pkt, struct regional* region, 334 struct rrset_parse* sigset, struct rrset_parse* dataset, int duplicate) 335 { 336 struct rr_parse* sig = sigset->rr_first; 337 struct rr_parse* prev = NULL; 338 struct rr_parse* insert; 339 struct rr_parse* nextsig; 340 while(sig) { 341 nextsig = sig->next; 342 if(pkt_rrsig_covered_equals(pkt, sig->ttl_data, 343 dataset->type)) { 344 if(duplicate) { 345 /* new */ 346 insert = (struct rr_parse*)regional_alloc( 347 region, sizeof(struct rr_parse)); 348 if(!insert) return 0; 349 insert->outside_packet = 0; 350 insert->ttl_data = sig->ttl_data; 351 insert->size = sig->size; 352 /* prev not used */ 353 } else { 354 /* remove from sigset */ 355 if(prev) prev->next = sig->next; 356 else sigset->rr_first = sig->next; 357 if(sigset->rr_last == sig) 358 sigset->rr_last = prev; 359 sigset->rr_count--; 360 sigset->size -= sig->size; 361 insert = sig; 362 /* prev not changed */ 363 } 364 /* add to dataset */ 365 dataset->rrsig_count++; 366 insert->next = 0; 367 if(dataset->rrsig_last) 368 dataset->rrsig_last->next = insert; 369 else dataset->rrsig_first = insert; 370 dataset->rrsig_last = insert; 371 dataset->size += insert->size; 372 } else { 373 prev = sig; 374 } 375 sig = nextsig; 376 } 377 return 1; 378 } 379 380 /** change an rrsig rrset for use as data rrset */ 381 static struct rrset_parse* 382 change_rrsig_rrset(struct rrset_parse* sigset, struct msg_parse* msg, 383 ldns_buffer* pkt, uint16_t datatype, uint32_t rrset_flags, 384 int hasother, ldns_pkt_section section, struct regional* region) 385 { 386 struct rrset_parse* dataset = sigset; 387 hashvalue_t hash = pkt_hash_rrset(pkt, sigset->dname, datatype, 388 sigset->rrset_class, rrset_flags); 389 log_assert( sigset->type == LDNS_RR_TYPE_RRSIG ); 390 log_assert( datatype != LDNS_RR_TYPE_RRSIG ); 391 if(hasother) { 392 /* need to make new rrset to hold data type */ 393 dataset = new_rrset(msg, sigset->dname, sigset->dname_len, 394 datatype, sigset->rrset_class, hash, rrset_flags, 395 section, region); 396 if(!dataset) 397 return NULL; 398 switch(section) { 399 case LDNS_SECTION_ANSWER: msg->an_rrsets++; break; 400 case LDNS_SECTION_AUTHORITY: msg->ns_rrsets++; break; 401 case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets++; break; 402 default: log_assert(0); 403 } 404 if(!moveover_rrsigs(pkt, region, sigset, dataset, 405 msg->qtype == LDNS_RR_TYPE_RRSIG || 406 (msg->qtype == LDNS_RR_TYPE_ANY && 407 section != LDNS_SECTION_ANSWER) )) 408 return NULL; 409 return dataset; 410 } 411 /* changeover the type of the rrset to data set */ 412 msgparse_bucket_remove(msg, dataset); 413 /* insert into new hash bucket */ 414 dataset->rrset_bucket_next = msg->hashtable[hash&(PARSE_TABLE_SIZE-1)]; 415 msg->hashtable[hash&(PARSE_TABLE_SIZE-1)] = dataset; 416 dataset->hash = hash; 417 /* use section of data item for result */ 418 change_section(msg, dataset, section); 419 dataset->type = datatype; 420 dataset->flags = rrset_flags; 421 dataset->rrsig_count += dataset->rr_count; 422 dataset->rr_count = 0; 423 /* move sigs to end of siglist */ 424 if(dataset->rrsig_last) 425 dataset->rrsig_last->next = dataset->rr_first; 426 else dataset->rrsig_first = dataset->rr_first; 427 dataset->rrsig_last = dataset->rr_last; 428 dataset->rr_first = 0; 429 dataset->rr_last = 0; 430 return dataset; 431 } 432 433 /** Find rrset. If equal to previous it is fast. hash if not so. 434 * @param msg: the message with hash table. 435 * @param pkt: the packet in wireformat (needed for compression ptrs). 436 * @param dname: pointer to start of dname (compressed) in packet. 437 * @param dnamelen: uncompressed wirefmt length of dname. 438 * @param type: type of current rr. 439 * @param dclass: class of current rr. 440 * @param hash: hash value is returned if the rrset could not be found. 441 * @param rrset_flags: is returned if the rrset could not be found. 442 * @param prev_dname_first: dname of last seen RR. First seen dname. 443 * @param prev_dname_last: dname of last seen RR. Last seen dname. 444 * @param prev_dnamelen: dname len of last seen RR. 445 * @param prev_type: type of last seen RR. 446 * @param prev_dclass: class of last seen RR. 447 * @param rrset_prev: last seen RRset. 448 * @param section: the current section in the packet. 449 * @param region: used to allocate temporary parsing data. 450 * @return 0 on out of memory. 451 */ 452 static int 453 find_rrset(struct msg_parse* msg, ldns_buffer* pkt, uint8_t* dname, 454 size_t dnamelen, uint16_t type, uint16_t dclass, hashvalue_t* hash, 455 uint32_t* rrset_flags, 456 uint8_t** prev_dname_first, uint8_t** prev_dname_last, 457 size_t* prev_dnamelen, uint16_t* prev_type, 458 uint16_t* prev_dclass, struct rrset_parse** rrset_prev, 459 ldns_pkt_section section, struct regional* region) 460 { 461 hashvalue_t dname_h = pkt_hash_rrset_first(pkt, dname); 462 uint16_t covtype; 463 if(*rrset_prev) { 464 /* check if equal to previous item */ 465 if(type == *prev_type && dclass == *prev_dclass && 466 dnamelen == *prev_dnamelen && 467 smart_compare(pkt, dname, *prev_dname_first, 468 *prev_dname_last) == 0 && 469 type != LDNS_RR_TYPE_RRSIG) { 470 /* same as previous */ 471 *prev_dname_last = dname; 472 return 1; 473 } 474 /* check if rrsig over previous item */ 475 if(type == LDNS_RR_TYPE_RRSIG && dclass == *prev_dclass && 476 pkt_rrsig_covered_equals(pkt, ldns_buffer_current(pkt), 477 *prev_type) && 478 smart_compare(pkt, dname, *prev_dname_first, 479 *prev_dname_last) == 0) { 480 /* covers previous */ 481 *prev_dname_last = dname; 482 return 1; 483 } 484 } 485 /* find by hashing and lookup in hashtable */ 486 *rrset_flags = pkt_rrset_flags(pkt, type, section); 487 488 /* if rrsig - try to lookup matching data set first */ 489 if(type == LDNS_RR_TYPE_RRSIG && pkt_rrsig_covered(pkt, 490 ldns_buffer_current(pkt), &covtype)) { 491 *hash = pkt_hash_rrset_rest(dname_h, covtype, dclass, 492 *rrset_flags); 493 *rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, 494 *rrset_flags, dname, dnamelen, covtype, dclass); 495 if(!*rrset_prev && covtype == LDNS_RR_TYPE_NSEC) { 496 /* if NSEC try with NSEC apex bit twiddled */ 497 *rrset_flags ^= PACKED_RRSET_NSEC_AT_APEX; 498 *hash = pkt_hash_rrset_rest(dname_h, covtype, dclass, 499 *rrset_flags); 500 *rrset_prev = msgparse_hashtable_lookup(msg, pkt, 501 *hash, *rrset_flags, dname, dnamelen, covtype, 502 dclass); 503 if(!*rrset_prev) /* untwiddle if not found */ 504 *rrset_flags ^= PACKED_RRSET_NSEC_AT_APEX; 505 } 506 if(!*rrset_prev && covtype == LDNS_RR_TYPE_SOA) { 507 /* if SOA try with SOA neg flag twiddled */ 508 *rrset_flags ^= PACKED_RRSET_SOA_NEG; 509 *hash = pkt_hash_rrset_rest(dname_h, covtype, dclass, 510 *rrset_flags); 511 *rrset_prev = msgparse_hashtable_lookup(msg, pkt, 512 *hash, *rrset_flags, dname, dnamelen, covtype, 513 dclass); 514 if(!*rrset_prev) /* untwiddle if not found */ 515 *rrset_flags ^= PACKED_RRSET_SOA_NEG; 516 } 517 if(*rrset_prev) { 518 *prev_dname_first = (*rrset_prev)->dname; 519 *prev_dname_last = dname; 520 *prev_dnamelen = dnamelen; 521 *prev_type = covtype; 522 *prev_dclass = dclass; 523 return 1; 524 } 525 } 526 if(type != LDNS_RR_TYPE_RRSIG) { 527 int hasother = 0; 528 /* find matching rrsig */ 529 *hash = pkt_hash_rrset_rest(dname_h, LDNS_RR_TYPE_RRSIG, 530 dclass, 0); 531 *rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, 532 0, dname, dnamelen, LDNS_RR_TYPE_RRSIG, 533 dclass); 534 if(*rrset_prev && rrset_has_sigover(pkt, *rrset_prev, type, 535 &hasother)) { 536 /* yes! */ 537 *prev_dname_first = (*rrset_prev)->dname; 538 *prev_dname_last = dname; 539 *prev_dnamelen = dnamelen; 540 *prev_type = type; 541 *prev_dclass = dclass; 542 *rrset_prev = change_rrsig_rrset(*rrset_prev, msg, 543 pkt, type, *rrset_flags, hasother, section, 544 region); 545 if(!*rrset_prev) return 0; 546 return 1; 547 } 548 } 549 550 *hash = pkt_hash_rrset_rest(dname_h, type, dclass, *rrset_flags); 551 *rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, *rrset_flags, 552 dname, dnamelen, type, dclass); 553 if(*rrset_prev) 554 *prev_dname_first = (*rrset_prev)->dname; 555 else *prev_dname_first = dname; 556 *prev_dname_last = dname; 557 *prev_dnamelen = dnamelen; 558 *prev_type = type; 559 *prev_dclass = dclass; 560 return 1; 561 } 562 563 /** 564 * Parse query section. 565 * @param pkt: packet, position at call must be at start of query section. 566 * at end position is after query section. 567 * @param msg: store results here. 568 * @return: 0 if OK, or rcode on error. 569 */ 570 static int 571 parse_query_section(ldns_buffer* pkt, struct msg_parse* msg) 572 { 573 if(msg->qdcount == 0) 574 return 0; 575 if(msg->qdcount > 1) 576 return LDNS_RCODE_FORMERR; 577 log_assert(msg->qdcount == 1); 578 if(ldns_buffer_remaining(pkt) <= 0) 579 return LDNS_RCODE_FORMERR; 580 msg->qname = ldns_buffer_current(pkt); 581 if((msg->qname_len = pkt_dname_len(pkt)) == 0) 582 return LDNS_RCODE_FORMERR; 583 if(ldns_buffer_remaining(pkt) < sizeof(uint16_t)*2) 584 return LDNS_RCODE_FORMERR; 585 msg->qtype = ldns_buffer_read_u16(pkt); 586 msg->qclass = ldns_buffer_read_u16(pkt); 587 return 0; 588 } 589 590 size_t 591 get_rdf_size(ldns_rdf_type rdf) 592 { 593 switch(rdf) { 594 case LDNS_RDF_TYPE_CLASS: 595 case LDNS_RDF_TYPE_ALG: 596 case LDNS_RDF_TYPE_INT8: 597 return 1; 598 break; 599 case LDNS_RDF_TYPE_INT16: 600 case LDNS_RDF_TYPE_TYPE: 601 case LDNS_RDF_TYPE_CERT_ALG: 602 return 2; 603 break; 604 case LDNS_RDF_TYPE_INT32: 605 case LDNS_RDF_TYPE_TIME: 606 case LDNS_RDF_TYPE_A: 607 case LDNS_RDF_TYPE_PERIOD: 608 return 4; 609 break; 610 case LDNS_RDF_TYPE_TSIGTIME: 611 return 6; 612 break; 613 case LDNS_RDF_TYPE_AAAA: 614 return 16; 615 break; 616 default: 617 log_assert(false); /* add type above */ 618 /* only types that appear before a domain * 619 * name are needed. rest is simply copied. */ 620 } 621 return 0; 622 } 623 624 /** calculate the size of one rr */ 625 static int 626 calc_size(ldns_buffer* pkt, uint16_t type, struct rr_parse* rr) 627 { 628 const ldns_rr_descriptor* desc; 629 uint16_t pkt_len; /* length of rr inside the packet */ 630 rr->size = sizeof(uint16_t); /* the rdatalen */ 631 ldns_buffer_skip(pkt, 4); /* skip ttl */ 632 pkt_len = ldns_buffer_read_u16(pkt); 633 if(ldns_buffer_remaining(pkt) < pkt_len) 634 return 0; 635 desc = ldns_rr_descript(type); 636 if(pkt_len > 0 && desc && desc->_dname_count > 0) { 637 int count = (int)desc->_dname_count; 638 int rdf = 0; 639 size_t len; 640 size_t oldpos; 641 /* skip first part. */ 642 while(pkt_len > 0 && count) { 643 switch(desc->_wireformat[rdf]) { 644 case LDNS_RDF_TYPE_DNAME: 645 /* decompress every domain name */ 646 oldpos = ldns_buffer_position(pkt); 647 if((len = pkt_dname_len(pkt)) == 0) 648 return 0; /* malformed dname */ 649 if(ldns_buffer_position(pkt)-oldpos > pkt_len) 650 return 0; /* dname exceeds rdata */ 651 pkt_len -= ldns_buffer_position(pkt)-oldpos; 652 rr->size += len; 653 count--; 654 len = 0; 655 break; 656 case LDNS_RDF_TYPE_STR: 657 if(pkt_len < 1) { 658 /* NOTREACHED, due to 'while(>0)' */ 659 return 0; /* len byte exceeds rdata */ 660 } 661 len = ldns_buffer_current(pkt)[0] + 1; 662 break; 663 default: 664 len = get_rdf_size(desc->_wireformat[rdf]); 665 } 666 if(len) { 667 if(pkt_len < len) 668 return 0; /* exceeds rdata */ 669 pkt_len -= len; 670 ldns_buffer_skip(pkt, (ssize_t)len); 671 rr->size += len; 672 } 673 rdf++; 674 } 675 } 676 /* remaining rdata */ 677 rr->size += pkt_len; 678 ldns_buffer_skip(pkt, (ssize_t)pkt_len); 679 return 1; 680 } 681 682 /** skip rr ttl and rdata */ 683 static int 684 skip_ttl_rdata(ldns_buffer* pkt) 685 { 686 uint16_t rdatalen; 687 if(ldns_buffer_remaining(pkt) < 6) /* ttl + rdatalen */ 688 return 0; 689 ldns_buffer_skip(pkt, 4); /* ttl */ 690 rdatalen = ldns_buffer_read_u16(pkt); 691 if(ldns_buffer_remaining(pkt) < rdatalen) 692 return 0; 693 ldns_buffer_skip(pkt, (ssize_t)rdatalen); 694 return 1; 695 } 696 697 /** see if RRSIG is a duplicate of another */ 698 static int 699 sig_is_double(ldns_buffer* pkt, struct rrset_parse* rrset, uint8_t* ttldata) 700 { 701 uint16_t rlen, siglen; 702 size_t pos = ldns_buffer_position(pkt); 703 struct rr_parse* sig; 704 if(ldns_buffer_remaining(pkt) < 6) 705 return 0; 706 ldns_buffer_skip(pkt, 4); /* ttl */ 707 rlen = ldns_buffer_read_u16(pkt); 708 if(ldns_buffer_remaining(pkt) < rlen) { 709 ldns_buffer_set_position(pkt, pos); 710 return 0; 711 } 712 ldns_buffer_set_position(pkt, pos); 713 714 sig = rrset->rrsig_first; 715 while(sig) { 716 /* check if rdatalen is same */ 717 memmove(&siglen, sig->ttl_data+4, sizeof(siglen)); 718 siglen = ntohs(siglen); 719 /* checks if data in packet is exactly the same, this means 720 * also dname in rdata is the same, but rrsig is not allowed 721 * to have compressed dnames anyway. If it is compressed anyway 722 * it will lead to duplicate rrs for qtype=RRSIG. (or ANY). 723 * 724 * Cannot use sig->size because size of the other one is not 725 * calculated yet. 726 */ 727 if(siglen == rlen) { 728 if(siglen>0 && memcmp(sig->ttl_data+6, ttldata+6, 729 siglen) == 0) { 730 /* same! */ 731 return 1; 732 } 733 } 734 sig = sig->next; 735 } 736 return 0; 737 } 738 739 /** Add rr (from packet here) to rrset, skips rr */ 740 static int 741 add_rr_to_rrset(struct rrset_parse* rrset, ldns_buffer* pkt, 742 struct msg_parse* msg, struct regional* region, 743 ldns_pkt_section section, uint16_t type) 744 { 745 struct rr_parse* rr; 746 /* check section of rrset. */ 747 if(rrset->section != section && type != LDNS_RR_TYPE_RRSIG && 748 rrset->type != LDNS_RR_TYPE_RRSIG) { 749 /* silently drop it - we drop the last part, since 750 * trust in rr data depends on the section it is in. 751 * the less trustworthy part is discarded. 752 * also the last part is more likely to be incomplete. 753 * RFC 2181: must put RRset only once in response. */ 754 /* 755 verbose(VERB_QUERY, "Packet contains rrset data in " 756 "multiple sections, dropped last part."); 757 log_buf(VERB_QUERY, "packet was", pkt); 758 */ 759 /* forwards */ 760 if(!skip_ttl_rdata(pkt)) 761 return LDNS_RCODE_FORMERR; 762 return 0; 763 } 764 765 if( (msg->qtype == LDNS_RR_TYPE_RRSIG || 766 msg->qtype == LDNS_RR_TYPE_ANY) 767 && sig_is_double(pkt, rrset, ldns_buffer_current(pkt))) { 768 if(!skip_ttl_rdata(pkt)) 769 return LDNS_RCODE_FORMERR; 770 return 0; 771 } 772 773 /* create rr */ 774 if(!(rr = (struct rr_parse*)regional_alloc(region, sizeof(*rr)))) 775 return LDNS_RCODE_SERVFAIL; 776 rr->outside_packet = 0; 777 rr->ttl_data = ldns_buffer_current(pkt); 778 rr->next = 0; 779 if(type == LDNS_RR_TYPE_RRSIG && rrset->type != LDNS_RR_TYPE_RRSIG) { 780 if(rrset->rrsig_last) 781 rrset->rrsig_last->next = rr; 782 else rrset->rrsig_first = rr; 783 rrset->rrsig_last = rr; 784 rrset->rrsig_count++; 785 } else { 786 if(rrset->rr_last) 787 rrset->rr_last->next = rr; 788 else rrset->rr_first = rr; 789 rrset->rr_last = rr; 790 rrset->rr_count++; 791 } 792 793 /* calc decompressed size */ 794 if(!calc_size(pkt, type, rr)) 795 return LDNS_RCODE_FORMERR; 796 rrset->size += rr->size; 797 798 return 0; 799 } 800 801 /** 802 * Parse packet RR section, for answer, authority and additional sections. 803 * @param pkt: packet, position at call must be at start of section. 804 * at end position is after section. 805 * @param msg: store results here. 806 * @param region: how to alloc results. 807 * @param section: section enum. 808 * @param num_rrs: how many rrs are in the section. 809 * @param num_rrsets: returns number of rrsets in the section. 810 * @return: 0 if OK, or rcode on error. 811 */ 812 static int 813 parse_section(ldns_buffer* pkt, struct msg_parse* msg, 814 struct regional* region, ldns_pkt_section section, 815 uint16_t num_rrs, size_t* num_rrsets) 816 { 817 uint16_t i; 818 uint8_t* dname, *prev_dname_f = NULL, *prev_dname_l = NULL; 819 size_t dnamelen, prev_dnamelen = 0; 820 uint16_t type, prev_type = 0; 821 uint16_t dclass, prev_dclass = 0; 822 uint32_t rrset_flags = 0; 823 hashvalue_t hash = 0; 824 struct rrset_parse* rrset = NULL; 825 int r; 826 827 if(num_rrs == 0) 828 return 0; 829 if(ldns_buffer_remaining(pkt) <= 0) 830 return LDNS_RCODE_FORMERR; 831 for(i=0; i<num_rrs; i++) { 832 /* parse this RR. */ 833 dname = ldns_buffer_current(pkt); 834 if((dnamelen = pkt_dname_len(pkt)) == 0) 835 return LDNS_RCODE_FORMERR; 836 if(ldns_buffer_remaining(pkt) < 10) /* type, class, ttl, len */ 837 return LDNS_RCODE_FORMERR; 838 type = ldns_buffer_read_u16(pkt); 839 ldns_buffer_read(pkt, &dclass, sizeof(dclass)); 840 841 if(0) { /* debug show what is being parsed. */ 842 if(type == LDNS_RR_TYPE_RRSIG) { 843 uint16_t t; 844 if(pkt_rrsig_covered(pkt, 845 ldns_buffer_current(pkt), &t)) 846 fprintf(stderr, "parse of %s(%d) [%s(%d)]", 847 ldns_rr_descript(type)? 848 ldns_rr_descript(type)->_name: "??", 849 (int)type, 850 ldns_rr_descript(t)? 851 ldns_rr_descript(t)->_name: "??", 852 (int)t); 853 } else 854 fprintf(stderr, "parse of %s(%d)", 855 ldns_rr_descript(type)? 856 ldns_rr_descript(type)->_name: "??", 857 (int)type); 858 fprintf(stderr, " %s(%d) ", 859 ldns_lookup_by_id(ldns_rr_classes, 860 (int)ntohs(dclass))?ldns_lookup_by_id( 861 ldns_rr_classes, (int)ntohs(dclass))->name: 862 "??", (int)ntohs(dclass)); 863 dname_print(stderr, pkt, dname); 864 fprintf(stderr, "\n"); 865 } 866 867 /* see if it is part of an existing RR set */ 868 if(!find_rrset(msg, pkt, dname, dnamelen, type, dclass, &hash, 869 &rrset_flags, &prev_dname_f, &prev_dname_l, 870 &prev_dnamelen, &prev_type, &prev_dclass, &rrset, 871 section, region)) 872 return LDNS_RCODE_SERVFAIL; 873 if(!rrset) { 874 /* it is a new RR set. hash&flags already calculated.*/ 875 (*num_rrsets)++; 876 rrset = new_rrset(msg, dname, dnamelen, type, dclass, 877 hash, rrset_flags, section, region); 878 if(!rrset) 879 return LDNS_RCODE_SERVFAIL; 880 } 881 else if(0) { 882 fprintf(stderr, "is part of existing: "); 883 dname_print(stderr, pkt, rrset->dname); 884 fprintf(stderr, " type %s(%d)\n", 885 ldns_rr_descript(rrset->type)? 886 ldns_rr_descript(rrset->type)->_name: "??", 887 (int)rrset->type); 888 } 889 /* add to rrset. */ 890 if((r=add_rr_to_rrset(rrset, pkt, msg, region, section, 891 type)) != 0) 892 return r; 893 } 894 return 0; 895 } 896 897 int 898 parse_packet(ldns_buffer* pkt, struct msg_parse* msg, struct regional* region) 899 { 900 int ret; 901 if(ldns_buffer_remaining(pkt) < LDNS_HEADER_SIZE) 902 return LDNS_RCODE_FORMERR; 903 /* read the header */ 904 ldns_buffer_read(pkt, &msg->id, sizeof(uint16_t)); 905 msg->flags = ldns_buffer_read_u16(pkt); 906 msg->qdcount = ldns_buffer_read_u16(pkt); 907 msg->ancount = ldns_buffer_read_u16(pkt); 908 msg->nscount = ldns_buffer_read_u16(pkt); 909 msg->arcount = ldns_buffer_read_u16(pkt); 910 if(msg->qdcount > 1) 911 return LDNS_RCODE_FORMERR; 912 if((ret = parse_query_section(pkt, msg)) != 0) 913 return ret; 914 if((ret = parse_section(pkt, msg, region, LDNS_SECTION_ANSWER, 915 msg->ancount, &msg->an_rrsets)) != 0) 916 return ret; 917 if((ret = parse_section(pkt, msg, region, LDNS_SECTION_AUTHORITY, 918 msg->nscount, &msg->ns_rrsets)) != 0) 919 return ret; 920 if(ldns_buffer_remaining(pkt) == 0 && msg->arcount == 1) { 921 /* BIND accepts leniently that an EDNS record is missing. 922 * so, we do too. */ 923 } else if((ret = parse_section(pkt, msg, region, 924 LDNS_SECTION_ADDITIONAL, msg->arcount, &msg->ar_rrsets)) != 0) 925 return ret; 926 /* if(ldns_buffer_remaining(pkt) > 0) { */ 927 /* there is spurious data at end of packet. ignore */ 928 /* } */ 929 msg->rrset_count = msg->an_rrsets + msg->ns_rrsets + msg->ar_rrsets; 930 return 0; 931 } 932 933 int 934 parse_extract_edns(struct msg_parse* msg, struct edns_data* edns) 935 { 936 struct rrset_parse* rrset = msg->rrset_first; 937 struct rrset_parse* prev = 0; 938 struct rrset_parse* found = 0; 939 struct rrset_parse* found_prev = 0; 940 /* since the class encodes the UDP size, we cannot use hash table to 941 * find the EDNS OPT record. Scan the packet. */ 942 while(rrset) { 943 if(rrset->type == LDNS_RR_TYPE_OPT) { 944 /* only one OPT RR allowed. */ 945 if(found) return LDNS_RCODE_FORMERR; 946 /* found it! */ 947 found_prev = prev; 948 found = rrset; 949 } 950 prev = rrset; 951 rrset = rrset->rrset_all_next; 952 } 953 if(!found) { 954 memset(edns, 0, sizeof(*edns)); 955 edns->udp_size = 512; 956 return 0; 957 } 958 /* check the found RRset */ 959 /* most lenient check possible. ignore dname, use last opt */ 960 if(found->section != LDNS_SECTION_ADDITIONAL) 961 return LDNS_RCODE_FORMERR; 962 if(found->rr_count == 0) 963 return LDNS_RCODE_FORMERR; 964 if(0) { /* strict checking of dname and RRcount */ 965 if(found->dname_len != 1 || !found->dname 966 || found->dname[0] != 0) return LDNS_RCODE_FORMERR; 967 if(found->rr_count != 1) return LDNS_RCODE_FORMERR; 968 } 969 log_assert(found->rr_first && found->rr_last); 970 971 /* remove from packet */ 972 if(found_prev) found_prev->rrset_all_next = found->rrset_all_next; 973 else msg->rrset_first = found->rrset_all_next; 974 if(found == msg->rrset_last) 975 msg->rrset_last = found_prev; 976 msg->arcount --; 977 msg->ar_rrsets --; 978 msg->rrset_count --; 979 980 /* take the data ! */ 981 edns->edns_present = 1; 982 edns->ext_rcode = found->rr_last->ttl_data[0]; 983 edns->edns_version = found->rr_last->ttl_data[1]; 984 edns->bits = ldns_read_uint16(&found->rr_last->ttl_data[2]); 985 edns->udp_size = ntohs(found->rrset_class); 986 /* ignore rdata and rrsigs */ 987 return 0; 988 } 989 990 int 991 parse_edns_from_pkt(ldns_buffer* pkt, struct edns_data* edns) 992 { 993 log_assert(LDNS_QDCOUNT(ldns_buffer_begin(pkt)) == 1); 994 log_assert(LDNS_ANCOUNT(ldns_buffer_begin(pkt)) == 0); 995 log_assert(LDNS_NSCOUNT(ldns_buffer_begin(pkt)) == 0); 996 /* check edns section is present */ 997 if(LDNS_ARCOUNT(ldns_buffer_begin(pkt)) > 1) { 998 return LDNS_RCODE_FORMERR; 999 } 1000 if(LDNS_ARCOUNT(ldns_buffer_begin(pkt)) == 0) { 1001 memset(edns, 0, sizeof(*edns)); 1002 edns->udp_size = 512; 1003 return 0; 1004 } 1005 /* domain name must be the root of length 1. */ 1006 if(pkt_dname_len(pkt) != 1) 1007 return LDNS_RCODE_FORMERR; 1008 if(ldns_buffer_remaining(pkt) < 10) /* type, class, ttl, rdatalen */ 1009 return LDNS_RCODE_FORMERR; 1010 if(ldns_buffer_read_u16(pkt) != LDNS_RR_TYPE_OPT) 1011 return LDNS_RCODE_FORMERR; 1012 edns->edns_present = 1; 1013 edns->udp_size = ldns_buffer_read_u16(pkt); /* class is udp size */ 1014 edns->ext_rcode = ldns_buffer_read_u8(pkt); /* ttl used for bits */ 1015 edns->edns_version = ldns_buffer_read_u8(pkt); 1016 edns->bits = ldns_buffer_read_u16(pkt); 1017 /* ignore rdata and rrsigs */ 1018 return 0; 1019 } 1020