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 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE 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 "util/config_file.h" 41 #include "util/data/msgparse.h" 42 #include "util/data/msgreply.h" 43 #include "util/data/dname.h" 44 #include "util/data/packed_rrset.h" 45 #include "util/netevent.h" 46 #include "util/storage/lookup3.h" 47 #include "util/regional.h" 48 #include "util/rfc_1982.h" 49 #include "util/edns.h" 50 #include "sldns/rrdef.h" 51 #include "sldns/sbuffer.h" 52 #include "sldns/parseutil.h" 53 #include "sldns/wire2str.h" 54 55 /** smart comparison of (compressed, valid) dnames from packet */ 56 static int 57 smart_compare(sldns_buffer* pkt, uint8_t* dnow, 58 uint8_t* dprfirst, uint8_t* dprlast) 59 { 60 if(LABEL_IS_PTR(*dnow)) { 61 /* ptr points to a previous dname */ 62 uint8_t* p; 63 if((size_t)PTR_OFFSET(dnow[0], dnow[1]) 64 >= sldns_buffer_limit(pkt)) 65 return -1; 66 p = sldns_buffer_at(pkt, PTR_OFFSET(dnow[0], dnow[1])); 67 if( p == dprfirst || p == dprlast ) 68 return 0; 69 /* prev dname is also a ptr, both ptrs are the same. */ 70 if(LABEL_IS_PTR(*dprlast) && 71 dprlast[0] == dnow[0] && dprlast[1] == dnow[1]) 72 return 0; 73 } 74 return dname_pkt_compare(pkt, dnow, dprlast); 75 } 76 77 /** 78 * Allocate new rrset in region, fill with data. 79 */ 80 static struct rrset_parse* 81 new_rrset(struct msg_parse* msg, uint8_t* dname, size_t dnamelen, 82 uint16_t type, uint16_t dclass, hashvalue_type hash, 83 uint32_t rrset_flags, sldns_pkt_section section, 84 struct regional* region) 85 { 86 struct rrset_parse* p = regional_alloc(region, sizeof(*p)); 87 if(!p) return NULL; 88 p->rrset_bucket_next = msg->hashtable[hash & (PARSE_TABLE_SIZE-1)]; 89 msg->hashtable[hash & (PARSE_TABLE_SIZE-1)] = p; 90 p->rrset_all_next = 0; 91 if(msg->rrset_last) 92 msg->rrset_last->rrset_all_next = p; 93 else msg->rrset_first = p; 94 msg->rrset_last = p; 95 p->hash = hash; 96 p->section = section; 97 p->dname = dname; 98 p->dname_len = dnamelen; 99 p->type = type; 100 p->rrset_class = dclass; 101 p->flags = rrset_flags; 102 p->rr_count = 0; 103 p->size = 0; 104 p->rr_first = 0; 105 p->rr_last = 0; 106 p->rrsig_count = 0; 107 p->rrsig_first = 0; 108 p->rrsig_last = 0; 109 return p; 110 } 111 112 /** See if next rrset is nsec at zone apex */ 113 static int 114 nsec_at_apex(sldns_buffer* pkt) 115 { 116 /* we are at ttl position in packet. */ 117 size_t pos = sldns_buffer_position(pkt); 118 uint16_t rdatalen; 119 if(sldns_buffer_remaining(pkt) < 7) /* ttl+len+root */ 120 return 0; /* eek! */ 121 sldns_buffer_skip(pkt, 4); /* ttl */; 122 rdatalen = sldns_buffer_read_u16(pkt); 123 if(sldns_buffer_remaining(pkt) < rdatalen) { 124 sldns_buffer_set_position(pkt, pos); 125 return 0; /* parse error happens later */ 126 } 127 /* must validate the nsec next domain name format */ 128 if(pkt_dname_len(pkt) == 0) { 129 sldns_buffer_set_position(pkt, pos); 130 return 0; /* parse error */ 131 } 132 133 /* see if SOA bit is set. */ 134 if(sldns_buffer_position(pkt) < pos+4+rdatalen) { 135 /* nsec type bitmap contains items */ 136 uint8_t win, blen, bits; 137 /* need: windownum, bitmap len, firstbyte */ 138 if(sldns_buffer_position(pkt)+3 > pos+4+rdatalen) { 139 sldns_buffer_set_position(pkt, pos); 140 return 0; /* malformed nsec */ 141 } 142 win = sldns_buffer_read_u8(pkt); 143 blen = sldns_buffer_read_u8(pkt); 144 bits = sldns_buffer_read_u8(pkt); 145 /* 0window always first window. bitlen >=1 or parse 146 error really. bit 0x2 is SOA. */ 147 if(win == 0 && blen >= 1 && (bits & 0x02)) { 148 sldns_buffer_set_position(pkt, pos); 149 return 1; 150 } 151 } 152 153 sldns_buffer_set_position(pkt, pos); 154 return 0; 155 } 156 157 /** Calculate rrset flags */ 158 static uint32_t 159 pkt_rrset_flags(sldns_buffer* pkt, uint16_t type, sldns_pkt_section sec) 160 { 161 uint32_t f = 0; 162 if(type == LDNS_RR_TYPE_NSEC && nsec_at_apex(pkt)) { 163 f |= PACKED_RRSET_NSEC_AT_APEX; 164 } else if(type == LDNS_RR_TYPE_SOA && sec == LDNS_SECTION_AUTHORITY) { 165 f |= PACKED_RRSET_SOA_NEG; 166 } 167 return f; 168 } 169 170 hashvalue_type 171 pkt_hash_rrset(sldns_buffer* pkt, uint8_t* dname, uint16_t type, 172 uint16_t dclass, uint32_t rrset_flags) 173 { 174 /* note this MUST be identical to rrset_key_hash in packed_rrset.c */ 175 /* this routine handles compressed names */ 176 hashvalue_type h = 0xab; 177 h = dname_pkt_hash(pkt, dname, h); 178 h = hashlittle(&type, sizeof(type), h); /* host order */ 179 h = hashlittle(&dclass, sizeof(dclass), h); /* netw order */ 180 h = hashlittle(&rrset_flags, sizeof(uint32_t), h); 181 return h; 182 } 183 184 /** create partial dname hash for rrset hash */ 185 static hashvalue_type 186 pkt_hash_rrset_first(sldns_buffer* pkt, uint8_t* dname) 187 { 188 /* works together with pkt_hash_rrset_rest */ 189 /* note this MUST be identical to rrset_key_hash in packed_rrset.c */ 190 /* this routine handles compressed names */ 191 hashvalue_type h = 0xab; 192 h = dname_pkt_hash(pkt, dname, h); 193 return h; 194 } 195 196 /** create a rrset hash from a partial dname hash */ 197 static hashvalue_type 198 pkt_hash_rrset_rest(hashvalue_type dname_h, uint16_t type, uint16_t dclass, 199 uint32_t rrset_flags) 200 { 201 /* works together with pkt_hash_rrset_first */ 202 /* note this MUST be identical to rrset_key_hash in packed_rrset.c */ 203 hashvalue_type h; 204 h = hashlittle(&type, sizeof(type), dname_h); /* host order */ 205 h = hashlittle(&dclass, sizeof(dclass), h); /* netw order */ 206 h = hashlittle(&rrset_flags, sizeof(uint32_t), h); 207 return h; 208 } 209 210 /** compare rrset_parse with data */ 211 static int 212 rrset_parse_equals(struct rrset_parse* p, sldns_buffer* pkt, hashvalue_type h, 213 uint32_t rrset_flags, uint8_t* dname, size_t dnamelen, 214 uint16_t type, uint16_t dclass) 215 { 216 if(p->hash == h && p->dname_len == dnamelen && p->type == type && 217 p->rrset_class == dclass && p->flags == rrset_flags && 218 dname_pkt_compare(pkt, dname, p->dname) == 0) 219 return 1; 220 return 0; 221 } 222 223 224 struct rrset_parse* 225 msgparse_hashtable_lookup(struct msg_parse* msg, sldns_buffer* pkt, 226 hashvalue_type h, uint32_t rrset_flags, uint8_t* dname, 227 size_t dnamelen, uint16_t type, uint16_t dclass) 228 { 229 struct rrset_parse* p = msg->hashtable[h & (PARSE_TABLE_SIZE-1)]; 230 while(p) { 231 if(rrset_parse_equals(p, pkt, h, rrset_flags, dname, dnamelen, 232 type, dclass)) 233 return p; 234 p = p->rrset_bucket_next; 235 } 236 return NULL; 237 } 238 239 /** return type networkformat that rrsig in packet covers */ 240 static int 241 pkt_rrsig_covered(sldns_buffer* pkt, uint8_t* here, uint16_t* type) 242 { 243 size_t pos = sldns_buffer_position(pkt); 244 sldns_buffer_set_position(pkt, (size_t)(here-sldns_buffer_begin(pkt))); 245 /* ttl + len + size of small rrsig(rootlabel, no signature) */ 246 if(sldns_buffer_remaining(pkt) < 4+2+19) 247 return 0; 248 sldns_buffer_skip(pkt, 4); /* ttl */ 249 if(sldns_buffer_read_u16(pkt) < 19) /* too short */ { 250 sldns_buffer_set_position(pkt, pos); 251 return 0; 252 } 253 *type = sldns_buffer_read_u16(pkt); 254 sldns_buffer_set_position(pkt, pos); 255 return 1; 256 } 257 258 /** true if covered type equals prevtype */ 259 static int 260 pkt_rrsig_covered_equals(sldns_buffer* pkt, uint8_t* here, uint16_t type) 261 { 262 uint16_t t; 263 if(pkt_rrsig_covered(pkt, here, &t) && t == type) 264 return 1; 265 return 0; 266 } 267 268 void 269 msgparse_bucket_remove(struct msg_parse* msg, struct rrset_parse* rrset) 270 { 271 struct rrset_parse** p; 272 p = &msg->hashtable[ rrset->hash & (PARSE_TABLE_SIZE-1) ]; 273 while(*p) { 274 if(*p == rrset) { 275 *p = rrset->rrset_bucket_next; 276 return; 277 } 278 p = &( (*p)->rrset_bucket_next ); 279 } 280 } 281 282 /** change section of rrset from previous to current section */ 283 static void 284 change_section(struct msg_parse* msg, struct rrset_parse* rrset, 285 sldns_pkt_section section) 286 { 287 struct rrset_parse *p, *prev; 288 /* remove from list */ 289 if(section == rrset->section) 290 return; 291 p = msg->rrset_first; 292 prev = 0; 293 while(p) { 294 if(p == rrset) { 295 if(prev) prev->rrset_all_next = p->rrset_all_next; 296 else msg->rrset_first = p->rrset_all_next; 297 if(msg->rrset_last == rrset) 298 msg->rrset_last = prev; 299 break; 300 } 301 prev = p; 302 p = p->rrset_all_next; 303 } 304 /* remove from count */ 305 switch(rrset->section) { 306 case LDNS_SECTION_ANSWER: msg->an_rrsets--; break; 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 /* insert at end of list */ 312 rrset->rrset_all_next = 0; 313 if(msg->rrset_last) 314 msg->rrset_last->rrset_all_next = rrset; 315 else msg->rrset_first = rrset; 316 msg->rrset_last = rrset; 317 /* up count of new section */ 318 switch(section) { 319 case LDNS_SECTION_AUTHORITY: msg->ns_rrsets++; break; 320 case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets++; break; 321 default: log_assert(0); 322 } 323 rrset->section = section; 324 } 325 326 /** see if rrset of type RRSIG contains sig over given type */ 327 static int 328 rrset_has_sigover(sldns_buffer* pkt, struct rrset_parse* rrset, uint16_t type, 329 int* hasother) 330 { 331 int res = 0; 332 struct rr_parse* rr = rrset->rr_first; 333 log_assert( rrset->type == LDNS_RR_TYPE_RRSIG ); 334 while(rr) { 335 if(pkt_rrsig_covered_equals(pkt, rr->ttl_data, type)) 336 res = 1; 337 else *hasother = 1; 338 rr = rr->next; 339 } 340 return res; 341 } 342 343 /** move rrsigs from sigset to dataset */ 344 static int 345 moveover_rrsigs(sldns_buffer* pkt, struct regional* region, 346 struct rrset_parse* sigset, struct rrset_parse* dataset, int duplicate) 347 { 348 struct rr_parse* sig = sigset->rr_first; 349 struct rr_parse* prev = NULL; 350 struct rr_parse* insert; 351 struct rr_parse* nextsig; 352 while(sig) { 353 nextsig = sig->next; 354 if(pkt_rrsig_covered_equals(pkt, sig->ttl_data, 355 dataset->type)) { 356 if(duplicate) { 357 /* new */ 358 insert = (struct rr_parse*)regional_alloc( 359 region, sizeof(struct rr_parse)); 360 if(!insert) return 0; 361 insert->outside_packet = 0; 362 insert->ttl_data = sig->ttl_data; 363 insert->size = sig->size; 364 /* prev not used */ 365 } else { 366 /* remove from sigset */ 367 if(prev) prev->next = sig->next; 368 else sigset->rr_first = sig->next; 369 if(sigset->rr_last == sig) 370 sigset->rr_last = prev; 371 sigset->rr_count--; 372 sigset->size -= sig->size; 373 insert = sig; 374 /* prev not changed */ 375 } 376 /* add to dataset */ 377 dataset->rrsig_count++; 378 insert->next = 0; 379 if(dataset->rrsig_last) 380 dataset->rrsig_last->next = insert; 381 else dataset->rrsig_first = insert; 382 dataset->rrsig_last = insert; 383 dataset->size += insert->size; 384 } else { 385 prev = sig; 386 } 387 sig = nextsig; 388 } 389 return 1; 390 } 391 392 /** change an rrsig rrset for use as data rrset */ 393 static struct rrset_parse* 394 change_rrsig_rrset(struct rrset_parse* sigset, struct msg_parse* msg, 395 sldns_buffer* pkt, uint16_t datatype, uint32_t rrset_flags, 396 int hasother, sldns_pkt_section section, struct regional* region) 397 { 398 struct rrset_parse* dataset = sigset; 399 hashvalue_type hash = pkt_hash_rrset(pkt, sigset->dname, datatype, 400 sigset->rrset_class, rrset_flags); 401 log_assert( sigset->type == LDNS_RR_TYPE_RRSIG ); 402 log_assert( datatype != LDNS_RR_TYPE_RRSIG ); 403 if(hasother) { 404 /* need to make new rrset to hold data type */ 405 dataset = new_rrset(msg, sigset->dname, sigset->dname_len, 406 datatype, sigset->rrset_class, hash, rrset_flags, 407 section, region); 408 if(!dataset) 409 return NULL; 410 switch(section) { 411 case LDNS_SECTION_ANSWER: msg->an_rrsets++; break; 412 case LDNS_SECTION_AUTHORITY: msg->ns_rrsets++; break; 413 case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets++; break; 414 default: log_assert(0); 415 } 416 if(!moveover_rrsigs(pkt, region, sigset, dataset, 417 msg->qtype == LDNS_RR_TYPE_RRSIG || 418 (msg->qtype == LDNS_RR_TYPE_ANY && 419 section != LDNS_SECTION_ANSWER) )) 420 return NULL; 421 return dataset; 422 } 423 /* changeover the type of the rrset to data set */ 424 msgparse_bucket_remove(msg, dataset); 425 /* insert into new hash bucket */ 426 dataset->rrset_bucket_next = msg->hashtable[hash&(PARSE_TABLE_SIZE-1)]; 427 msg->hashtable[hash&(PARSE_TABLE_SIZE-1)] = dataset; 428 dataset->hash = hash; 429 /* use section of data item for result */ 430 change_section(msg, dataset, section); 431 dataset->type = datatype; 432 dataset->flags = rrset_flags; 433 dataset->rrsig_count += dataset->rr_count; 434 dataset->rr_count = 0; 435 /* move sigs to end of siglist */ 436 if(dataset->rrsig_last) 437 dataset->rrsig_last->next = dataset->rr_first; 438 else dataset->rrsig_first = dataset->rr_first; 439 dataset->rrsig_last = dataset->rr_last; 440 dataset->rr_first = 0; 441 dataset->rr_last = 0; 442 return dataset; 443 } 444 445 /** Find rrset. If equal to previous it is fast. hash if not so. 446 * @param msg: the message with hash table. 447 * @param pkt: the packet in wireformat (needed for compression ptrs). 448 * @param dname: pointer to start of dname (compressed) in packet. 449 * @param dnamelen: uncompressed wirefmt length of dname. 450 * @param type: type of current rr. 451 * @param dclass: class of current rr. 452 * @param hash: hash value is returned if the rrset could not be found. 453 * @param rrset_flags: is returned if the rrset could not be found. 454 * @param prev_dname_first: dname of last seen RR. First seen dname. 455 * @param prev_dname_last: dname of last seen RR. Last seen dname. 456 * @param prev_dnamelen: dname len of last seen RR. 457 * @param prev_type: type of last seen RR. 458 * @param prev_dclass: class of last seen RR. 459 * @param rrset_prev: last seen RRset. 460 * @param section: the current section in the packet. 461 * @param region: used to allocate temporary parsing data. 462 * @return 0 on out of memory. 463 */ 464 static int 465 find_rrset(struct msg_parse* msg, sldns_buffer* pkt, uint8_t* dname, 466 size_t dnamelen, uint16_t type, uint16_t dclass, hashvalue_type* hash, 467 uint32_t* rrset_flags, 468 uint8_t** prev_dname_first, uint8_t** prev_dname_last, 469 size_t* prev_dnamelen, uint16_t* prev_type, 470 uint16_t* prev_dclass, struct rrset_parse** rrset_prev, 471 sldns_pkt_section section, struct regional* region) 472 { 473 hashvalue_type dname_h = pkt_hash_rrset_first(pkt, dname); 474 uint16_t covtype; 475 if(*rrset_prev) { 476 /* check if equal to previous item */ 477 if(type == *prev_type && dclass == *prev_dclass && 478 dnamelen == *prev_dnamelen && 479 smart_compare(pkt, dname, *prev_dname_first, 480 *prev_dname_last) == 0 && 481 type != LDNS_RR_TYPE_RRSIG) { 482 /* same as previous */ 483 *prev_dname_last = dname; 484 return 1; 485 } 486 /* check if rrsig over previous item */ 487 if(type == LDNS_RR_TYPE_RRSIG && dclass == *prev_dclass && 488 pkt_rrsig_covered_equals(pkt, sldns_buffer_current(pkt), 489 *prev_type) && 490 smart_compare(pkt, dname, *prev_dname_first, 491 *prev_dname_last) == 0) { 492 /* covers previous */ 493 *prev_dname_last = dname; 494 return 1; 495 } 496 } 497 /* find by hashing and lookup in hashtable */ 498 *rrset_flags = pkt_rrset_flags(pkt, type, section); 499 500 /* if rrsig - try to lookup matching data set first */ 501 if(type == LDNS_RR_TYPE_RRSIG && pkt_rrsig_covered(pkt, 502 sldns_buffer_current(pkt), &covtype)) { 503 *hash = pkt_hash_rrset_rest(dname_h, covtype, dclass, 504 *rrset_flags); 505 *rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, 506 *rrset_flags, dname, dnamelen, covtype, dclass); 507 if(!*rrset_prev && covtype == LDNS_RR_TYPE_NSEC) { 508 /* if NSEC try with NSEC apex bit twiddled */ 509 *rrset_flags ^= PACKED_RRSET_NSEC_AT_APEX; 510 *hash = pkt_hash_rrset_rest(dname_h, covtype, dclass, 511 *rrset_flags); 512 *rrset_prev = msgparse_hashtable_lookup(msg, pkt, 513 *hash, *rrset_flags, dname, dnamelen, covtype, 514 dclass); 515 if(!*rrset_prev) /* untwiddle if not found */ 516 *rrset_flags ^= PACKED_RRSET_NSEC_AT_APEX; 517 } 518 if(!*rrset_prev && covtype == LDNS_RR_TYPE_SOA) { 519 /* if SOA try with SOA neg flag twiddled */ 520 *rrset_flags ^= PACKED_RRSET_SOA_NEG; 521 *hash = pkt_hash_rrset_rest(dname_h, covtype, dclass, 522 *rrset_flags); 523 *rrset_prev = msgparse_hashtable_lookup(msg, pkt, 524 *hash, *rrset_flags, dname, dnamelen, covtype, 525 dclass); 526 if(!*rrset_prev) /* untwiddle if not found */ 527 *rrset_flags ^= PACKED_RRSET_SOA_NEG; 528 } 529 if(*rrset_prev) { 530 *prev_dname_first = (*rrset_prev)->dname; 531 *prev_dname_last = dname; 532 *prev_dnamelen = dnamelen; 533 *prev_type = covtype; 534 *prev_dclass = dclass; 535 return 1; 536 } 537 } 538 if(type != LDNS_RR_TYPE_RRSIG) { 539 int hasother = 0; 540 /* find matching rrsig */ 541 *hash = pkt_hash_rrset_rest(dname_h, LDNS_RR_TYPE_RRSIG, 542 dclass, 0); 543 *rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, 544 0, dname, dnamelen, LDNS_RR_TYPE_RRSIG, 545 dclass); 546 if(*rrset_prev && rrset_has_sigover(pkt, *rrset_prev, type, 547 &hasother)) { 548 /* yes! */ 549 *prev_dname_first = (*rrset_prev)->dname; 550 *prev_dname_last = dname; 551 *prev_dnamelen = dnamelen; 552 *prev_type = type; 553 *prev_dclass = dclass; 554 *rrset_prev = change_rrsig_rrset(*rrset_prev, msg, 555 pkt, type, *rrset_flags, hasother, section, 556 region); 557 if(!*rrset_prev) return 0; 558 return 1; 559 } 560 } 561 562 *hash = pkt_hash_rrset_rest(dname_h, type, dclass, *rrset_flags); 563 *rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, *rrset_flags, 564 dname, dnamelen, type, dclass); 565 if(*rrset_prev) 566 *prev_dname_first = (*rrset_prev)->dname; 567 else *prev_dname_first = dname; 568 *prev_dname_last = dname; 569 *prev_dnamelen = dnamelen; 570 *prev_type = type; 571 *prev_dclass = dclass; 572 return 1; 573 } 574 575 /** 576 * Parse query section. 577 * @param pkt: packet, position at call must be at start of query section. 578 * at end position is after query section. 579 * @param msg: store results here. 580 * @return: 0 if OK, or rcode on error. 581 */ 582 static int 583 parse_query_section(sldns_buffer* pkt, struct msg_parse* msg) 584 { 585 if(msg->qdcount == 0) 586 return 0; 587 if(msg->qdcount > 1) 588 return LDNS_RCODE_FORMERR; 589 log_assert(msg->qdcount == 1); 590 if(sldns_buffer_remaining(pkt) <= 0) 591 return LDNS_RCODE_FORMERR; 592 msg->qname = sldns_buffer_current(pkt); 593 if((msg->qname_len = pkt_dname_len(pkt)) == 0) 594 return LDNS_RCODE_FORMERR; 595 if(sldns_buffer_remaining(pkt) < sizeof(uint16_t)*2) 596 return LDNS_RCODE_FORMERR; 597 msg->qtype = sldns_buffer_read_u16(pkt); 598 msg->qclass = sldns_buffer_read_u16(pkt); 599 return 0; 600 } 601 602 size_t 603 get_rdf_size(sldns_rdf_type rdf) 604 { 605 switch(rdf) { 606 case LDNS_RDF_TYPE_CLASS: 607 case LDNS_RDF_TYPE_ALG: 608 case LDNS_RDF_TYPE_INT8: 609 return 1; 610 break; 611 case LDNS_RDF_TYPE_INT16: 612 case LDNS_RDF_TYPE_TYPE: 613 case LDNS_RDF_TYPE_CERT_ALG: 614 return 2; 615 break; 616 case LDNS_RDF_TYPE_INT32: 617 case LDNS_RDF_TYPE_TIME: 618 case LDNS_RDF_TYPE_A: 619 case LDNS_RDF_TYPE_PERIOD: 620 return 4; 621 break; 622 case LDNS_RDF_TYPE_TSIGTIME: 623 return 6; 624 break; 625 case LDNS_RDF_TYPE_AAAA: 626 return 16; 627 break; 628 default: 629 log_assert(0); /* add type above */ 630 /* only types that appear before a domain * 631 * name are needed. rest is simply copied. */ 632 } 633 return 0; 634 } 635 636 /** calculate the size of one rr */ 637 static int 638 calc_size(sldns_buffer* pkt, uint16_t type, struct rr_parse* rr) 639 { 640 const sldns_rr_descriptor* desc; 641 uint16_t pkt_len; /* length of rr inside the packet */ 642 rr->size = sizeof(uint16_t); /* the rdatalen */ 643 sldns_buffer_skip(pkt, 4); /* skip ttl */ 644 pkt_len = sldns_buffer_read_u16(pkt); 645 if(sldns_buffer_remaining(pkt) < pkt_len) 646 return 0; 647 desc = sldns_rr_descript(type); 648 if(pkt_len > 0 && desc && desc->_dname_count > 0) { 649 int count = (int)desc->_dname_count; 650 int rdf = 0; 651 size_t len; 652 size_t oldpos; 653 /* skip first part. */ 654 while(pkt_len > 0 && count) { 655 switch(desc->_wireformat[rdf]) { 656 case LDNS_RDF_TYPE_DNAME: 657 /* decompress every domain name */ 658 oldpos = sldns_buffer_position(pkt); 659 if((len = pkt_dname_len(pkt)) == 0) 660 return 0; /* malformed dname */ 661 if(sldns_buffer_position(pkt)-oldpos > pkt_len) 662 return 0; /* dname exceeds rdata */ 663 pkt_len -= sldns_buffer_position(pkt)-oldpos; 664 rr->size += len; 665 count--; 666 len = 0; 667 break; 668 case LDNS_RDF_TYPE_STR: 669 if(pkt_len < 1) { 670 /* NOTREACHED, due to 'while(>0)' */ 671 return 0; /* len byte exceeds rdata */ 672 } 673 len = sldns_buffer_current(pkt)[0] + 1; 674 break; 675 default: 676 len = get_rdf_size(desc->_wireformat[rdf]); 677 } 678 if(len) { 679 if(pkt_len < len) 680 return 0; /* exceeds rdata */ 681 pkt_len -= len; 682 sldns_buffer_skip(pkt, (ssize_t)len); 683 rr->size += len; 684 } 685 rdf++; 686 } 687 } 688 /* remaining rdata */ 689 rr->size += pkt_len; 690 sldns_buffer_skip(pkt, (ssize_t)pkt_len); 691 return 1; 692 } 693 694 /** skip rr ttl and rdata */ 695 static int 696 skip_ttl_rdata(sldns_buffer* pkt) 697 { 698 uint16_t rdatalen; 699 if(sldns_buffer_remaining(pkt) < 6) /* ttl + rdatalen */ 700 return 0; 701 sldns_buffer_skip(pkt, 4); /* ttl */ 702 rdatalen = sldns_buffer_read_u16(pkt); 703 if(sldns_buffer_remaining(pkt) < rdatalen) 704 return 0; 705 sldns_buffer_skip(pkt, (ssize_t)rdatalen); 706 return 1; 707 } 708 709 /** see if RRSIG is a duplicate of another */ 710 static int 711 sig_is_double(sldns_buffer* pkt, struct rrset_parse* rrset, uint8_t* ttldata) 712 { 713 uint16_t rlen, siglen; 714 size_t pos = sldns_buffer_position(pkt); 715 struct rr_parse* sig; 716 if(sldns_buffer_remaining(pkt) < 6) 717 return 0; 718 sldns_buffer_skip(pkt, 4); /* ttl */ 719 rlen = sldns_buffer_read_u16(pkt); 720 if(sldns_buffer_remaining(pkt) < rlen) { 721 sldns_buffer_set_position(pkt, pos); 722 return 0; 723 } 724 sldns_buffer_set_position(pkt, pos); 725 726 sig = rrset->rrsig_first; 727 while(sig) { 728 /* check if rdatalen is same */ 729 memmove(&siglen, sig->ttl_data+4, sizeof(siglen)); 730 siglen = ntohs(siglen); 731 /* checks if data in packet is exactly the same, this means 732 * also dname in rdata is the same, but rrsig is not allowed 733 * to have compressed dnames anyway. If it is compressed anyway 734 * it will lead to duplicate rrs for qtype=RRSIG. (or ANY). 735 * 736 * Cannot use sig->size because size of the other one is not 737 * calculated yet. 738 */ 739 if(siglen == rlen) { 740 if(siglen>0 && memcmp(sig->ttl_data+6, ttldata+6, 741 siglen) == 0) { 742 /* same! */ 743 return 1; 744 } 745 } 746 sig = sig->next; 747 } 748 return 0; 749 } 750 751 /** Add rr (from packet here) to rrset, skips rr */ 752 static int 753 add_rr_to_rrset(struct rrset_parse* rrset, sldns_buffer* pkt, 754 struct msg_parse* msg, struct regional* region, 755 sldns_pkt_section section, uint16_t type) 756 { 757 struct rr_parse* rr; 758 /* check section of rrset. */ 759 if(rrset->section != section && type != LDNS_RR_TYPE_RRSIG && 760 rrset->type != LDNS_RR_TYPE_RRSIG) { 761 /* silently drop it - we drop the last part, since 762 * trust in rr data depends on the section it is in. 763 * the less trustworthy part is discarded. 764 * also the last part is more likely to be incomplete. 765 * RFC 2181: must put RRset only once in response. */ 766 /* 767 verbose(VERB_QUERY, "Packet contains rrset data in " 768 "multiple sections, dropped last part."); 769 log_buf(VERB_QUERY, "packet was", pkt); 770 */ 771 /* forwards */ 772 if(!skip_ttl_rdata(pkt)) 773 return LDNS_RCODE_FORMERR; 774 return 0; 775 } 776 777 if( (msg->qtype == LDNS_RR_TYPE_RRSIG || 778 msg->qtype == LDNS_RR_TYPE_ANY) 779 && sig_is_double(pkt, rrset, sldns_buffer_current(pkt))) { 780 if(!skip_ttl_rdata(pkt)) 781 return LDNS_RCODE_FORMERR; 782 return 0; 783 } 784 785 /* create rr */ 786 if(!(rr = (struct rr_parse*)regional_alloc(region, sizeof(*rr)))) 787 return LDNS_RCODE_SERVFAIL; 788 rr->outside_packet = 0; 789 rr->ttl_data = sldns_buffer_current(pkt); 790 rr->next = 0; 791 if(type == LDNS_RR_TYPE_RRSIG && rrset->type != LDNS_RR_TYPE_RRSIG) { 792 if(rrset->rrsig_last) 793 rrset->rrsig_last->next = rr; 794 else rrset->rrsig_first = rr; 795 rrset->rrsig_last = rr; 796 rrset->rrsig_count++; 797 } else { 798 if(rrset->rr_last) 799 rrset->rr_last->next = rr; 800 else rrset->rr_first = rr; 801 rrset->rr_last = rr; 802 rrset->rr_count++; 803 } 804 805 /* calc decompressed size */ 806 if(!calc_size(pkt, type, rr)) 807 return LDNS_RCODE_FORMERR; 808 rrset->size += rr->size; 809 810 return 0; 811 } 812 813 /** 814 * Parse packet RR section, for answer, authority and additional sections. 815 * @param pkt: packet, position at call must be at start of section. 816 * at end position is after section. 817 * @param msg: store results here. 818 * @param region: how to alloc results. 819 * @param section: section enum. 820 * @param num_rrs: how many rrs are in the section. 821 * @param num_rrsets: returns number of rrsets in the section. 822 * @return: 0 if OK, or rcode on error. 823 */ 824 static int 825 parse_section(sldns_buffer* pkt, struct msg_parse* msg, 826 struct regional* region, sldns_pkt_section section, 827 uint16_t num_rrs, size_t* num_rrsets) 828 { 829 uint16_t i; 830 uint8_t* dname, *prev_dname_f = NULL, *prev_dname_l = NULL; 831 size_t dnamelen, prev_dnamelen = 0; 832 uint16_t type, prev_type = 0; 833 uint16_t dclass, prev_dclass = 0; 834 uint32_t rrset_flags = 0; 835 hashvalue_type hash = 0; 836 struct rrset_parse* rrset = NULL; 837 int r; 838 839 if(num_rrs == 0) 840 return 0; 841 if(sldns_buffer_remaining(pkt) <= 0) 842 return LDNS_RCODE_FORMERR; 843 for(i=0; i<num_rrs; i++) { 844 /* parse this RR. */ 845 dname = sldns_buffer_current(pkt); 846 if((dnamelen = pkt_dname_len(pkt)) == 0) 847 return LDNS_RCODE_FORMERR; 848 if(sldns_buffer_remaining(pkt) < 10) /* type, class, ttl, len */ 849 return LDNS_RCODE_FORMERR; 850 type = sldns_buffer_read_u16(pkt); 851 sldns_buffer_read(pkt, &dclass, sizeof(dclass)); 852 853 if(0) { /* debug show what is being parsed. */ 854 if(type == LDNS_RR_TYPE_RRSIG) { 855 uint16_t t; 856 if(pkt_rrsig_covered(pkt, 857 sldns_buffer_current(pkt), &t)) 858 fprintf(stderr, "parse of %s(%d) [%s(%d)]", 859 sldns_rr_descript(type)? 860 sldns_rr_descript(type)->_name: "??", 861 (int)type, 862 sldns_rr_descript(t)? 863 sldns_rr_descript(t)->_name: "??", 864 (int)t); 865 } else 866 fprintf(stderr, "parse of %s(%d)", 867 sldns_rr_descript(type)? 868 sldns_rr_descript(type)->_name: "??", 869 (int)type); 870 fprintf(stderr, " %s(%d) ", 871 sldns_lookup_by_id(sldns_rr_classes, 872 (int)ntohs(dclass))?sldns_lookup_by_id( 873 sldns_rr_classes, (int)ntohs(dclass))->name: 874 "??", (int)ntohs(dclass)); 875 dname_print(stderr, pkt, dname); 876 fprintf(stderr, "\n"); 877 } 878 879 /* see if it is part of an existing RR set */ 880 if(!find_rrset(msg, pkt, dname, dnamelen, type, dclass, &hash, 881 &rrset_flags, &prev_dname_f, &prev_dname_l, 882 &prev_dnamelen, &prev_type, &prev_dclass, &rrset, 883 section, region)) 884 return LDNS_RCODE_SERVFAIL; 885 if(!rrset) { 886 /* it is a new RR set. hash&flags already calculated.*/ 887 (*num_rrsets)++; 888 rrset = new_rrset(msg, dname, dnamelen, type, dclass, 889 hash, rrset_flags, section, region); 890 if(!rrset) 891 return LDNS_RCODE_SERVFAIL; 892 } 893 else if(0) { 894 fprintf(stderr, "is part of existing: "); 895 dname_print(stderr, pkt, rrset->dname); 896 fprintf(stderr, " type %s(%d)\n", 897 sldns_rr_descript(rrset->type)? 898 sldns_rr_descript(rrset->type)->_name: "??", 899 (int)rrset->type); 900 } 901 /* add to rrset. */ 902 if((r=add_rr_to_rrset(rrset, pkt, msg, region, section, 903 type)) != 0) 904 return r; 905 } 906 return 0; 907 } 908 909 int 910 parse_packet(sldns_buffer* pkt, struct msg_parse* msg, struct regional* region) 911 { 912 int ret; 913 if(sldns_buffer_remaining(pkt) < LDNS_HEADER_SIZE) 914 return LDNS_RCODE_FORMERR; 915 /* read the header */ 916 sldns_buffer_read(pkt, &msg->id, sizeof(uint16_t)); 917 msg->flags = sldns_buffer_read_u16(pkt); 918 msg->qdcount = sldns_buffer_read_u16(pkt); 919 msg->ancount = sldns_buffer_read_u16(pkt); 920 msg->nscount = sldns_buffer_read_u16(pkt); 921 msg->arcount = sldns_buffer_read_u16(pkt); 922 if(msg->qdcount > 1) 923 return LDNS_RCODE_FORMERR; 924 if((ret = parse_query_section(pkt, msg)) != 0) 925 return ret; 926 if((ret = parse_section(pkt, msg, region, LDNS_SECTION_ANSWER, 927 msg->ancount, &msg->an_rrsets)) != 0) 928 return ret; 929 if((ret = parse_section(pkt, msg, region, LDNS_SECTION_AUTHORITY, 930 msg->nscount, &msg->ns_rrsets)) != 0) 931 return ret; 932 if(sldns_buffer_remaining(pkt) == 0 && msg->arcount == 1) { 933 /* BIND accepts leniently that an EDNS record is missing. 934 * so, we do too. */ 935 } else if((ret = parse_section(pkt, msg, region, 936 LDNS_SECTION_ADDITIONAL, msg->arcount, &msg->ar_rrsets)) != 0) 937 return ret; 938 /* if(sldns_buffer_remaining(pkt) > 0) { */ 939 /* there is spurious data at end of packet. ignore */ 940 /* } */ 941 msg->rrset_count = msg->an_rrsets + msg->ns_rrsets + msg->ar_rrsets; 942 return 0; 943 } 944 945 /** parse EDNS options from EDNS wireformat rdata */ 946 static int 947 parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len, 948 struct edns_data* edns, struct config_file* cfg, struct comm_point* c, 949 struct comm_reply* repinfo, uint32_t now, struct regional* region) 950 { 951 /* To respond with a Keepalive option, the client connection must have 952 * received one message with a TCP Keepalive EDNS option, and that 953 * option must have 0 length data. Subsequent messages sent on that 954 * connection will have a TCP Keepalive option. 955 * 956 * In the if-statement below, the option is added unsolicited. This 957 * means that the client has sent an KEEPALIVE option earlier. We know 958 * here this is true, because c->tcp_keepalive is set. 959 */ 960 if (cfg && cfg->do_tcp_keepalive && c && c->type != comm_udp && c->tcp_keepalive) { 961 if(!edns_opt_list_append_keepalive(&edns->opt_list_out, 962 c->tcp_timeout_msec / 100, region)) { 963 log_err("out of memory"); 964 return LDNS_RCODE_SERVFAIL; 965 } 966 } 967 968 /* while still more options, and have code+len to read */ 969 /* ignores partial content (i.e. rdata len 3) */ 970 while(rdata_len >= 4) { 971 uint16_t opt_code = sldns_read_uint16(rdata_ptr); 972 uint16_t opt_len = sldns_read_uint16(rdata_ptr+2); 973 uint8_t server_cookie[40]; 974 enum edns_cookie_val_status cookie_val_status; 975 int cookie_is_v4 = 1; 976 977 rdata_ptr += 4; 978 rdata_len -= 4; 979 if(opt_len > rdata_len) 980 break; /* option code partial */ 981 982 /* handle parse time edns options here */ 983 switch(opt_code) { 984 case LDNS_EDNS_NSID: 985 if (!cfg || !cfg->nsid) 986 break; 987 if(!edns_opt_list_append(&edns->opt_list_out, 988 LDNS_EDNS_NSID, cfg->nsid_len, 989 cfg->nsid, region)) { 990 log_err("out of memory"); 991 return LDNS_RCODE_SERVFAIL; 992 } 993 break; 994 995 case LDNS_EDNS_KEEPALIVE: 996 /* To respond with a Keepalive option, the client 997 * connection must have received one message with a TCP 998 * Keepalive EDNS option, and that option must have 0 999 * length data. Subsequent messages sent on that 1000 * connection will have a TCP Keepalive option. 1001 * 1002 * This should be the first time the client sends this 1003 * option, so c->tcp_keepalive is not set. 1004 * Besides adding the reply KEEPALIVE option, 1005 * c->tcp_keepalive will be set so that the 1006 * option will be added unsolicited in subsequent 1007 * responses (see the comment above the if-statement 1008 * at the start of this function). 1009 */ 1010 if (!cfg || !cfg->do_tcp_keepalive || !c || 1011 c->type == comm_udp || c->tcp_keepalive) 1012 break; 1013 if(opt_len) { 1014 verbose(VERB_ALGO, "query with bad edns keepalive."); 1015 return LDNS_RCODE_FORMERR; 1016 } 1017 if(!edns_opt_list_append_keepalive(&edns->opt_list_out, 1018 c->tcp_timeout_msec / 100, 1019 region)) { 1020 log_err("out of memory"); 1021 return LDNS_RCODE_SERVFAIL; 1022 } 1023 c->tcp_keepalive = 1; 1024 break; 1025 1026 case LDNS_EDNS_PADDING: 1027 if(!cfg || !cfg->pad_responses || 1028 !c || c->type != comm_tcp ||!c->ssl) 1029 break; 1030 if(!edns_opt_list_append(&edns->opt_list_out, 1031 LDNS_EDNS_PADDING, 1032 0, NULL, region)) { 1033 log_err("out of memory"); 1034 return LDNS_RCODE_SERVFAIL; 1035 } 1036 edns->padding_block_size = cfg->pad_responses_block_size; 1037 break; 1038 1039 case LDNS_EDNS_COOKIE: 1040 if(!cfg || !cfg->do_answer_cookie || !repinfo) 1041 break; 1042 if(opt_len != 8 && (opt_len < 16 || opt_len > 40)) { 1043 verbose(VERB_ALGO, "worker request: " 1044 "badly formatted cookie"); 1045 return LDNS_RCODE_FORMERR; 1046 } 1047 edns->cookie_present = 1; 1048 1049 /* Copy client cookie, version and timestamp for 1050 * validation and creation purposes. 1051 */ 1052 if(opt_len >= 16) { 1053 memmove(server_cookie, rdata_ptr, 16); 1054 } else { 1055 memset(server_cookie, 0, 16); 1056 memmove(server_cookie, rdata_ptr, opt_len); 1057 } 1058 1059 /* Copy client ip for validation and creation 1060 * purposes. It will be overwritten if (re)creation 1061 * is needed. 1062 */ 1063 if(repinfo->remote_addr.ss_family == AF_INET) { 1064 memcpy(server_cookie + 16, 1065 &((struct sockaddr_in*)&repinfo->remote_addr)->sin_addr, 4); 1066 } else { 1067 cookie_is_v4 = 0; 1068 memcpy(server_cookie + 16, 1069 &((struct sockaddr_in6*)&repinfo->remote_addr)->sin6_addr, 16); 1070 } 1071 1072 cookie_val_status = edns_cookie_server_validate( 1073 rdata_ptr, opt_len, cfg->cookie_secret, 1074 cfg->cookie_secret_len, cookie_is_v4, 1075 server_cookie, now); 1076 switch(cookie_val_status) { 1077 case COOKIE_STATUS_VALID: 1078 case COOKIE_STATUS_VALID_RENEW: 1079 edns->cookie_valid = 1; 1080 /* Reuse cookie */ 1081 if(!edns_opt_list_append( 1082 &edns->opt_list_out, LDNS_EDNS_COOKIE, 1083 opt_len, rdata_ptr, region)) { 1084 log_err("out of memory"); 1085 return LDNS_RCODE_SERVFAIL; 1086 } 1087 /* Cookie to be reused added to outgoing 1088 * options. Done! 1089 */ 1090 break; 1091 case COOKIE_STATUS_CLIENT_ONLY: 1092 edns->cookie_client = 1; 1093 /* fallthrough */ 1094 case COOKIE_STATUS_FUTURE: 1095 case COOKIE_STATUS_EXPIRED: 1096 case COOKIE_STATUS_INVALID: 1097 default: 1098 edns_cookie_server_write(server_cookie, 1099 cfg->cookie_secret, cookie_is_v4, now); 1100 if(!edns_opt_list_append(&edns->opt_list_out, 1101 LDNS_EDNS_COOKIE, 24, server_cookie, 1102 region)) { 1103 log_err("out of memory"); 1104 return LDNS_RCODE_SERVFAIL; 1105 } 1106 break; 1107 } 1108 break; 1109 default: 1110 break; 1111 } 1112 if(!edns_opt_list_append(&edns->opt_list_in, 1113 opt_code, opt_len, rdata_ptr, region)) { 1114 log_err("out of memory"); 1115 return LDNS_RCODE_SERVFAIL; 1116 } 1117 rdata_ptr += opt_len; 1118 rdata_len -= opt_len; 1119 } 1120 return LDNS_RCODE_NOERROR; 1121 } 1122 1123 int 1124 parse_extract_edns_from_response_msg(struct msg_parse* msg, 1125 struct edns_data* edns, struct regional* region) 1126 { 1127 struct rrset_parse* rrset = msg->rrset_first; 1128 struct rrset_parse* prev = 0; 1129 struct rrset_parse* found = 0; 1130 struct rrset_parse* found_prev = 0; 1131 size_t rdata_len; 1132 uint8_t* rdata_ptr; 1133 /* since the class encodes the UDP size, we cannot use hash table to 1134 * find the EDNS OPT record. Scan the packet. */ 1135 while(rrset) { 1136 if(rrset->type == LDNS_RR_TYPE_OPT) { 1137 /* only one OPT RR allowed. */ 1138 if(found) return LDNS_RCODE_FORMERR; 1139 /* found it! */ 1140 found_prev = prev; 1141 found = rrset; 1142 } 1143 prev = rrset; 1144 rrset = rrset->rrset_all_next; 1145 } 1146 if(!found) { 1147 memset(edns, 0, sizeof(*edns)); 1148 edns->udp_size = 512; 1149 return 0; 1150 } 1151 /* check the found RRset */ 1152 /* most lenient check possible. ignore dname, use last opt */ 1153 if(found->section != LDNS_SECTION_ADDITIONAL) 1154 return LDNS_RCODE_FORMERR; 1155 if(found->rr_count == 0) 1156 return LDNS_RCODE_FORMERR; 1157 if(0) { /* strict checking of dname and RRcount */ 1158 if(found->dname_len != 1 || !found->dname 1159 || found->dname[0] != 0) return LDNS_RCODE_FORMERR; 1160 if(found->rr_count != 1) return LDNS_RCODE_FORMERR; 1161 } 1162 log_assert(found->rr_first && found->rr_last); 1163 1164 /* remove from packet */ 1165 if(found_prev) found_prev->rrset_all_next = found->rrset_all_next; 1166 else msg->rrset_first = found->rrset_all_next; 1167 if(found == msg->rrset_last) 1168 msg->rrset_last = found_prev; 1169 msg->arcount --; 1170 msg->ar_rrsets --; 1171 msg->rrset_count --; 1172 1173 /* take the data ! */ 1174 edns->edns_present = 1; 1175 edns->ext_rcode = found->rr_last->ttl_data[0]; 1176 edns->edns_version = found->rr_last->ttl_data[1]; 1177 edns->bits = sldns_read_uint16(&found->rr_last->ttl_data[2]); 1178 edns->udp_size = ntohs(found->rrset_class); 1179 edns->opt_list_in = NULL; 1180 edns->opt_list_out = NULL; 1181 edns->opt_list_inplace_cb_out = NULL; 1182 edns->padding_block_size = 0; 1183 edns->cookie_present = 0; 1184 edns->cookie_valid = 0; 1185 1186 /* take the options */ 1187 rdata_len = found->rr_first->size-2; 1188 rdata_ptr = found->rr_first->ttl_data+6; 1189 1190 /* while still more options, and have code+len to read */ 1191 /* ignores partial content (i.e. rdata len 3) */ 1192 while(rdata_len >= 4) { 1193 uint16_t opt_code = sldns_read_uint16(rdata_ptr); 1194 uint16_t opt_len = sldns_read_uint16(rdata_ptr+2); 1195 rdata_ptr += 4; 1196 rdata_len -= 4; 1197 if(opt_len > rdata_len) 1198 break; /* option code partial */ 1199 1200 if(!edns_opt_list_append(&edns->opt_list_in, 1201 opt_code, opt_len, rdata_ptr, region)) { 1202 log_err("out of memory"); 1203 break; 1204 } 1205 rdata_ptr += opt_len; 1206 rdata_len -= opt_len; 1207 } 1208 /* ignore rrsigs */ 1209 return LDNS_RCODE_NOERROR; 1210 } 1211 1212 /** skip RR in packet */ 1213 static int 1214 skip_pkt_rr(sldns_buffer* pkt) 1215 { 1216 if(sldns_buffer_remaining(pkt) < 1) return 0; 1217 if(!pkt_dname_len(pkt)) 1218 return 0; 1219 if(sldns_buffer_remaining(pkt) < 4) return 0; 1220 sldns_buffer_skip(pkt, 4); /* type and class */ 1221 if(!skip_ttl_rdata(pkt)) 1222 return 0; 1223 return 1; 1224 } 1225 1226 /** skip RRs from packet */ 1227 int 1228 skip_pkt_rrs(sldns_buffer* pkt, int num) 1229 { 1230 int i; 1231 for(i=0; i<num; i++) { 1232 if(!skip_pkt_rr(pkt)) 1233 return 0; 1234 } 1235 return 1; 1236 } 1237 1238 int 1239 parse_edns_from_query_pkt(sldns_buffer* pkt, struct edns_data* edns, 1240 struct config_file* cfg, struct comm_point* c, 1241 struct comm_reply* repinfo, time_t now, struct regional* region) 1242 { 1243 size_t rdata_len; 1244 uint8_t* rdata_ptr; 1245 log_assert(LDNS_QDCOUNT(sldns_buffer_begin(pkt)) == 1); 1246 memset(edns, 0, sizeof(*edns)); 1247 if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 0 || 1248 LDNS_NSCOUNT(sldns_buffer_begin(pkt)) != 0) { 1249 if(!skip_pkt_rrs(pkt, ((int)LDNS_ANCOUNT(sldns_buffer_begin(pkt)))+ 1250 ((int)LDNS_NSCOUNT(sldns_buffer_begin(pkt))))) 1251 return LDNS_RCODE_FORMERR; 1252 } 1253 /* check edns section is present */ 1254 if(LDNS_ARCOUNT(sldns_buffer_begin(pkt)) > 1) { 1255 return LDNS_RCODE_FORMERR; 1256 } 1257 if(LDNS_ARCOUNT(sldns_buffer_begin(pkt)) == 0) { 1258 edns->udp_size = 512; 1259 return 0; 1260 } 1261 /* domain name must be the root of length 1. */ 1262 if(pkt_dname_len(pkt) != 1) 1263 return LDNS_RCODE_FORMERR; 1264 if(sldns_buffer_remaining(pkt) < 10) /* type, class, ttl, rdatalen */ 1265 return LDNS_RCODE_FORMERR; 1266 if(sldns_buffer_read_u16(pkt) != LDNS_RR_TYPE_OPT) 1267 return LDNS_RCODE_FORMERR; 1268 edns->edns_present = 1; 1269 edns->udp_size = sldns_buffer_read_u16(pkt); /* class is udp size */ 1270 edns->ext_rcode = sldns_buffer_read_u8(pkt); /* ttl used for bits */ 1271 edns->edns_version = sldns_buffer_read_u8(pkt); 1272 edns->bits = sldns_buffer_read_u16(pkt); 1273 edns->opt_list_in = NULL; 1274 edns->opt_list_out = NULL; 1275 edns->opt_list_inplace_cb_out = NULL; 1276 edns->padding_block_size = 0; 1277 edns->cookie_present = 0; 1278 edns->cookie_valid = 0; 1279 1280 /* take the options */ 1281 rdata_len = sldns_buffer_read_u16(pkt); 1282 if(sldns_buffer_remaining(pkt) < rdata_len) 1283 return LDNS_RCODE_FORMERR; 1284 rdata_ptr = sldns_buffer_current(pkt); 1285 /* ignore rrsigs */ 1286 return parse_edns_options_from_query(rdata_ptr, rdata_len, edns, cfg, 1287 c, repinfo, now, region); 1288 } 1289 1290 void 1291 log_edns_opt_list(enum verbosity_value level, const char* info_str, 1292 struct edns_option* list) 1293 { 1294 if(verbosity >= level && list) { 1295 char str[128], *s; 1296 size_t slen; 1297 verbose(level, "%s", info_str); 1298 while(list) { 1299 s = str; 1300 slen = sizeof(str); 1301 (void)sldns_wire2str_edns_option_print(&s, &slen, list->opt_code, 1302 list->opt_data, list->opt_len); 1303 verbose(level, " %s", str); 1304 list = list->next; 1305 } 1306 } 1307 } 1308 1309