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