1 /* 2 * packet.c -- low-level DNS packet encoding and decoding functions. 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 #include "config.h" 11 12 #include <string.h> 13 14 #include "packet.h" 15 #include "query.h" 16 #include "rdata.h" 17 #include "dns.h" 18 19 int round_robin = 0; 20 int minimal_responses = 0; 21 22 static void 23 encode_dname(query_type *q, domain_type *domain) 24 { 25 while (domain->parent && query_get_dname_offset(q, domain) == 0) { 26 query_put_dname_offset(q, domain, buffer_position(q->packet)); 27 DEBUG(DEBUG_NAME_COMPRESSION, 2, 28 (LOG_INFO, "dname: %s, number: %lu, offset: %u\n", 29 domain_to_string(domain), 30 (unsigned long) domain->number, 31 query_get_dname_offset(q, domain))); 32 buffer_write(q->packet, dname_name(domain_dname(domain)), 33 label_length(dname_name(domain_dname(domain))) + 1U); 34 domain = domain->parent; 35 } 36 if (domain->parent) { 37 DEBUG(DEBUG_NAME_COMPRESSION, 2, 38 (LOG_INFO, "dname: %s, number: %lu, pointer: %u\n", 39 domain_to_string(domain), 40 (unsigned long) domain->number, 41 query_get_dname_offset(q, domain))); 42 assert(query_get_dname_offset(q, domain) <= MAX_COMPRESSION_OFFSET); 43 buffer_write_u16(q->packet, 44 0xc000 | query_get_dname_offset(q, domain)); 45 } else { 46 buffer_write_u8(q->packet, 0); 47 } 48 } 49 50 int 51 packet_encode_rr(query_type *q, domain_type *owner, rr_type *rr, uint32_t ttl) 52 { 53 size_t truncation_mark; 54 uint16_t rdlength = 0; 55 size_t rdlength_pos; 56 const nsd_type_descriptor_type *descriptor = 57 nsd_type_descriptor(rr->type); 58 59 assert(q); 60 assert(owner); 61 assert(rr); 62 63 /* 64 * If the record does not in fit in the packet the packet size 65 * will be restored to the mark. 66 */ 67 truncation_mark = buffer_position(q->packet); 68 69 encode_dname(q, owner); 70 buffer_write_u16(q->packet, rr->type); 71 buffer_write_u16(q->packet, rr->klass); 72 buffer_write_u32(q->packet, ttl); 73 74 /* Reserve space for rdlength. */ 75 rdlength_pos = buffer_position(q->packet); 76 buffer_skip(q->packet, sizeof(rdlength)); 77 78 descriptor->write_rdata(q, rr); 79 80 if (!query_overflow(q)) { 81 rdlength = (buffer_position(q->packet) - rdlength_pos 82 - sizeof(rdlength)); 83 buffer_write_u16_at(q->packet, rdlength_pos, rdlength); 84 return 1; 85 } else { 86 buffer_set_position(q->packet, truncation_mark); 87 query_clear_dname_offsets(q, truncation_mark); 88 assert(!query_overflow(q)); 89 return 0; 90 } 91 } 92 93 int 94 packet_encode_rrset(query_type *query, 95 domain_type *owner, 96 rrset_type *rrset, 97 int section, 98 #ifdef MINIMAL_RESPONSES 99 size_t minimal_respsize, 100 int* done) 101 #else 102 size_t ATTR_UNUSED(minimal_respsize), 103 int* ATTR_UNUSED(done)) 104 #endif 105 { 106 uint16_t i; 107 size_t truncation_mark; 108 uint16_t added = 0; 109 int all_added = 1; 110 #ifdef MINIMAL_RESPONSES 111 int minimize_response = (section >= OPTIONAL_AUTHORITY_SECTION); 112 int truncate_rrset = (section == ANSWER_SECTION || 113 section == AUTHORITY_SECTION); 114 #else 115 int truncate_rrset = (section == ANSWER_SECTION || 116 section == AUTHORITY_SECTION || 117 section == OPTIONAL_AUTHORITY_SECTION); 118 #endif 119 static int round_robin_off = 0; 120 int do_robin = (round_robin && section == ANSWER_SECTION && 121 query->qtype != TYPE_AXFR && query->qtype != TYPE_IXFR); 122 uint16_t start; 123 rrset_type *rrsig; 124 125 assert(rrset->rr_count > 0); 126 127 truncation_mark = buffer_position(query->packet); 128 129 if(do_robin && rrset->rr_count) 130 start = (uint16_t)(round_robin_off++ % rrset->rr_count); 131 else start = 0; 132 for (i = start; i < rrset->rr_count; ++i) { 133 if (packet_encode_rr(query, owner, rrset->rrs[i], 134 rrset->rrs[i]->ttl)) { 135 ++added; 136 } else { 137 all_added = 0; 138 start = 0; 139 break; 140 } 141 } 142 for (i = 0; i < start; ++i) { 143 if (packet_encode_rr(query, owner, rrset->rrs[i], 144 rrset->rrs[i]->ttl)) { 145 ++added; 146 } else { 147 all_added = 0; 148 break; 149 } 150 } 151 152 if (all_added && 153 query->edns.dnssec_ok && 154 zone_is_secure(rrset->zone) && 155 rrset_rrtype(rrset) != TYPE_RRSIG && 156 (rrsig = domain_find_rrset(owner, rrset->zone, TYPE_RRSIG))) 157 { 158 for (i = 0; i < rrsig->rr_count; ++i) { 159 if (rr_rrsig_type_covered(rrsig->rrs[i]) 160 == rrset_rrtype(rrset)) 161 { 162 if (packet_encode_rr(query, owner, 163 rrsig->rrs[i], 164 rrset_rrtype(rrset)==TYPE_SOA?rrset->rrs[0]->ttl:rrsig->rrs[i]->ttl)) 165 { 166 ++added; 167 } else { 168 all_added = 0; 169 break; 170 } 171 } 172 } 173 } 174 175 #ifdef MINIMAL_RESPONSES 176 if ((!all_added || buffer_position(query->packet) > minimal_respsize) 177 && !query->tcp && minimize_response) { 178 /* Truncate entire RRset. */ 179 buffer_set_position(query->packet, truncation_mark); 180 query_clear_dname_offsets(query, truncation_mark); 181 added = 0; 182 *done = 1; 183 } 184 #endif 185 186 if (!all_added && truncate_rrset) { 187 /* Truncate entire RRset and set truncate flag. */ 188 buffer_set_position(query->packet, truncation_mark); 189 query_clear_dname_offsets(query, truncation_mark); 190 TC_SET(query->packet); 191 added = 0; 192 } 193 194 return added; 195 } 196 197 int 198 packet_skip_dname(buffer_type *packet) 199 { 200 while (1) { 201 uint8_t label_size; 202 if (!buffer_available(packet, 1)) 203 return 0; 204 205 label_size = buffer_read_u8(packet); 206 if (label_size == 0) { 207 return 1; 208 } else if ((label_size & 0xc0) != 0) { 209 if (!buffer_available(packet, 1)) 210 return 0; 211 buffer_skip(packet, 1); 212 return 1; 213 } else if (!buffer_available(packet, label_size)) { 214 return 0; 215 } else { 216 buffer_skip(packet, label_size); 217 } 218 } 219 } 220 221 int 222 packet_skip_rr(buffer_type *packet, int question_section) 223 { 224 if (!packet_skip_dname(packet)) 225 return 0; 226 227 if (question_section) { 228 if (!buffer_available(packet, 4)) 229 return 0; 230 buffer_skip(packet, 4); 231 } else { 232 uint16_t rdata_size; 233 if (!buffer_available(packet, 10)) 234 return 0; 235 buffer_skip(packet, 8); 236 rdata_size = buffer_read_u16(packet); 237 if (!buffer_available(packet, rdata_size)) 238 return 0; 239 buffer_skip(packet, rdata_size); 240 } 241 242 return 1; 243 } 244 245 rr_type * 246 packet_read_rr(region_type *region, domain_table_type *owners, 247 buffer_type *packet, int question_section) 248 { 249 const nsd_type_descriptor_type *descriptor; 250 const dname_type *owner; 251 struct domain* domain; 252 uint16_t type, class, rdlength; 253 uint32_t ttl; 254 struct rr *rr; 255 int32_t code; 256 257 owner = dname_make_from_packet(region, packet, 1, 1); 258 if (!owner || !buffer_available(packet, 2*sizeof(uint16_t))) { 259 return NULL; 260 } 261 262 domain = domain_table_insert(owners, owner); 263 type = buffer_read_u16(packet); 264 class = buffer_read_u16(packet); 265 266 if (question_section) { 267 rr_type *result = (rr_type *) region_alloc(region, 268 sizeof(rr_type)); 269 result->owner = domain; 270 result->type = type; 271 result->klass = class; 272 result->ttl = 0; 273 result->rdlength = 0; 274 return result; 275 } else if (!buffer_available(packet, sizeof(uint32_t) + sizeof(uint16_t))) { 276 return NULL; 277 } 278 279 ttl = buffer_read_u32(packet); 280 rdlength = buffer_read_u16(packet); 281 282 if (!buffer_available(packet, rdlength)) { 283 return NULL; 284 } 285 286 descriptor = nsd_type_descriptor(type); 287 code = descriptor->read_rdata(owners, rdlength, packet, &rr); 288 if(code < 0) { 289 return NULL; 290 } 291 rr->owner = domain; 292 rr->type = type; 293 rr->klass = class; 294 rr->ttl = ttl; 295 296 return rr; 297 } 298 299 int packet_read_query_section(buffer_type *packet, 300 uint8_t* dst, uint16_t* qtype, uint16_t* qclass) 301 { 302 uint8_t *query_name = buffer_current(packet); 303 uint8_t *src = query_name; 304 size_t len; 305 306 while (*src) { 307 /* 308 * If we are out of buffer limits or we have a pointer 309 * in question dname or the domain name is longer than 310 * MAXDOMAINLEN ... 311 */ 312 if ((*src & 0xc0) || 313 (src + *src + 2 > buffer_end(packet)) || 314 (src + *src + 2 > query_name + MAXDOMAINLEN)) 315 { 316 return 0; 317 } 318 memcpy(dst, src, *src + 1); 319 dst += *src + 1; 320 src += *src + 1; 321 } 322 *dst++ = *src++; 323 324 /* Make sure name is not too long or we have stripped packet... */ 325 len = src - query_name; 326 if (len > MAXDOMAINLEN || 327 (src + 2*sizeof(uint16_t) > buffer_end(packet))) 328 { 329 return 0; 330 } 331 buffer_set_position(packet, src - buffer_begin(packet)); 332 333 *qtype = buffer_read_u16(packet); 334 *qclass = buffer_read_u16(packet); 335 return 1; 336 } 337 338 int packet_find_notify_serial(buffer_type *packet, uint32_t* serial) 339 { 340 size_t saved_position = buffer_position(packet); 341 /* count of further RRs after question section */ 342 size_t rrcount = (size_t)ANCOUNT(packet) + (size_t)NSCOUNT(packet) + (size_t)ARCOUNT(packet); 343 size_t qcount = (size_t)QDCOUNT(packet); 344 size_t i; 345 buffer_set_position(packet, QHEADERSZ); 346 if(qcount > 64 || rrcount > 65530) { 347 /* query count 0 or 1 only, rr number limited by 64k packet, 348 * and should not be impossibly high, parse error */ 349 buffer_set_position(packet, saved_position); 350 return 0; 351 } 352 353 /* skip all question RRs */ 354 for (i = 0; i < qcount; ++i) { 355 if (!packet_skip_rr(packet, 1)) { 356 buffer_set_position(packet, saved_position); 357 return 0; 358 } 359 } 360 361 /* Find the SOA RR */ 362 for(i = 0; i < rrcount; i++) { 363 uint16_t rdata_size; 364 if (!packet_skip_dname(packet)) 365 break; 366 /* check length available for type,class,ttl,rdatalen */ 367 if (!buffer_available(packet, 10)) 368 break; 369 /* check type, class */ 370 if(buffer_read_u16(packet) == TYPE_SOA) { 371 if(buffer_read_u16(packet) != CLASS_IN) 372 break; 373 buffer_skip(packet, 4); /* skip ttl */ 374 rdata_size = buffer_read_u16(packet); 375 if (!buffer_available(packet, rdata_size)) 376 break; 377 /* skip two dnames, then serial */ 378 if (!packet_skip_dname(packet) || 379 !packet_skip_dname(packet)) 380 break; 381 if (!buffer_available(packet, 4)) 382 break; 383 *serial = buffer_read_u32(packet); 384 buffer_set_position(packet, saved_position); 385 return 1; 386 } 387 /* continue to next RR */ 388 buffer_skip(packet, 6); 389 rdata_size = buffer_read_u16(packet); 390 if (!buffer_available(packet, rdata_size)) 391 break; 392 buffer_skip(packet, rdata_size); 393 } 394 /* failed to find SOA */ 395 buffer_set_position(packet, saved_position); 396 return 0; 397 } 398