1 /* 2 * host2wire.c 3 * 4 * conversion routines from the host to the wire format. 5 * This will usually just a re-ordering of the 6 * data (as we store it in network format) 7 * 8 * a Net::DNS like library for C 9 * 10 * (c) NLnet Labs, 2004-2006 11 * 12 * See the file LICENSE for the license 13 */ 14 15 #include <ldns/config.h> 16 17 #include <ldns/ldns.h> 18 19 ldns_status 20 ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name) 21 { 22 return ldns_dname2buffer_wire_compress(buffer, name, NULL); 23 } 24 25 ldns_status 26 ldns_dname2buffer_wire_compress(ldns_buffer *buffer, const ldns_rdf *name, ldns_rbtree_t *compression_data) 27 { 28 ldns_rbnode_t *node; 29 uint8_t *data; 30 size_t size; 31 ldns_rdf *label; 32 ldns_rdf *rest; 33 ldns_status s; 34 35 /* If no tree, just add the data */ 36 if(!compression_data) 37 { 38 if (ldns_buffer_reserve(buffer, ldns_rdf_size(name))) 39 { 40 ldns_buffer_write(buffer, ldns_rdf_data(name), ldns_rdf_size(name)); 41 } 42 return ldns_buffer_status(buffer); 43 } 44 45 /* No labels left, write final zero */ 46 if(ldns_dname_label_count(name)==0) 47 { 48 if(ldns_buffer_reserve(buffer,1)) 49 { 50 ldns_buffer_write_u8(buffer, 0); 51 } 52 return ldns_buffer_status(buffer); 53 } 54 55 /* Can we find the name in the tree? */ 56 if((node = ldns_rbtree_search(compression_data, name)) != NULL) 57 { 58 /* Found */ 59 uint16_t position = (uint16_t) (intptr_t) node->data | 0xC000; 60 if (ldns_buffer_reserve(buffer, 2)) 61 { 62 ldns_buffer_write_u16(buffer, position); 63 } 64 return ldns_buffer_status(buffer); 65 } 66 else 67 { 68 /* Not found. Write cache entry, take off first label, write it, */ 69 /* try again with the rest of the name. */ 70 if (ldns_buffer_position(buffer) < 16384) { 71 ldns_rdf *key; 72 73 node = LDNS_MALLOC(ldns_rbnode_t); 74 if(!node) 75 { 76 return LDNS_STATUS_MEM_ERR; 77 } 78 79 key = ldns_rdf_clone(name); 80 if (!key) { 81 LDNS_FREE(node); 82 return LDNS_STATUS_MEM_ERR; 83 } 84 node->key = key; 85 node->data = (void *) (intptr_t) ldns_buffer_position(buffer); 86 if(!ldns_rbtree_insert(compression_data,node)) 87 { 88 /* fprintf(stderr,"Name not found but now it's there?\n"); */ 89 ldns_rdf_deep_free(key); 90 LDNS_FREE(node); 91 } 92 } 93 label = ldns_dname_label(name, 0); 94 rest = ldns_dname_left_chop(name); 95 size = ldns_rdf_size(label) - 1; /* Don't want the final zero */ 96 data = ldns_rdf_data(label); 97 if(ldns_buffer_reserve(buffer, size)) 98 { 99 ldns_buffer_write(buffer, data, size); 100 } 101 ldns_rdf_deep_free(label); 102 s = ldns_dname2buffer_wire_compress(buffer, rest, compression_data); 103 ldns_rdf_deep_free(rest); 104 return s; 105 } 106 } 107 108 ldns_status 109 ldns_rdf2buffer_wire(ldns_buffer *buffer, const ldns_rdf *rdf) 110 { 111 return ldns_rdf2buffer_wire_compress(buffer, rdf, NULL); 112 } 113 114 ldns_status 115 ldns_rdf2buffer_wire_compress(ldns_buffer *buffer, const ldns_rdf *rdf, ldns_rbtree_t *compression_data) 116 { 117 /* If it's a DNAME, call that function to get compression */ 118 if(compression_data && ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME) 119 { 120 return ldns_dname2buffer_wire_compress(buffer,rdf,compression_data); 121 } 122 123 if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) { 124 ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf)); 125 } 126 return ldns_buffer_status(buffer); 127 } 128 129 ldns_status 130 ldns_rdf2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rdf *rdf) 131 { 132 size_t i; 133 uint8_t *rdf_data; 134 135 if (ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME) { 136 if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) { 137 rdf_data = ldns_rdf_data(rdf); 138 for (i = 0; i < ldns_rdf_size(rdf); i++) { 139 ldns_buffer_write_u8(buffer, 140 (uint8_t) LDNS_DNAME_NORMALIZE((int)rdf_data[i])); 141 } 142 } 143 } else { 144 /* direct copy for all other types */ 145 if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) { 146 ldns_buffer_write(buffer, 147 ldns_rdf_data(rdf), 148 ldns_rdf_size(rdf)); 149 } 150 } 151 return ldns_buffer_status(buffer); 152 } 153 154 /* convert a rr list to wireformat */ 155 ldns_status 156 ldns_rr_list2buffer_wire(ldns_buffer *buffer,const ldns_rr_list *rr_list) 157 { 158 uint16_t rr_count; 159 uint16_t i; 160 161 rr_count = ldns_rr_list_rr_count(rr_list); 162 for(i = 0; i < rr_count; i++) { 163 (void)ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), 164 LDNS_SECTION_ANY); 165 } 166 return ldns_buffer_status(buffer); 167 } 168 169 170 ldns_status 171 ldns_rr2buffer_wire_canonical(ldns_buffer *buffer, 172 const ldns_rr *rr, 173 int section) 174 { 175 uint16_t i; 176 uint16_t rdl_pos = 0; 177 bool pre_rfc3597 = false; 178 switch (ldns_rr_get_type(rr)) { 179 case LDNS_RR_TYPE_NS: 180 case LDNS_RR_TYPE_MD: 181 case LDNS_RR_TYPE_MF: 182 case LDNS_RR_TYPE_CNAME: 183 case LDNS_RR_TYPE_SOA: 184 case LDNS_RR_TYPE_MB: 185 case LDNS_RR_TYPE_MG: 186 case LDNS_RR_TYPE_MR: 187 case LDNS_RR_TYPE_PTR: 188 case LDNS_RR_TYPE_HINFO: 189 case LDNS_RR_TYPE_MINFO: 190 case LDNS_RR_TYPE_MX: 191 case LDNS_RR_TYPE_RP: 192 case LDNS_RR_TYPE_AFSDB: 193 case LDNS_RR_TYPE_RT: 194 case LDNS_RR_TYPE_SIG: 195 case LDNS_RR_TYPE_PX: 196 case LDNS_RR_TYPE_NXT: 197 case LDNS_RR_TYPE_NAPTR: 198 case LDNS_RR_TYPE_KX: 199 case LDNS_RR_TYPE_SRV: 200 case LDNS_RR_TYPE_DNAME: 201 case LDNS_RR_TYPE_A6: 202 case LDNS_RR_TYPE_RRSIG: 203 pre_rfc3597 = true; 204 break; 205 default: 206 break; 207 } 208 209 if (ldns_rr_owner(rr)) { 210 (void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr)); 211 } 212 213 if (ldns_buffer_reserve(buffer, 4)) { 214 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr)); 215 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr)); 216 } 217 218 if (section != LDNS_SECTION_QUESTION) { 219 if (ldns_buffer_reserve(buffer, 6)) { 220 ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr)); 221 /* remember pos for later */ 222 rdl_pos = ldns_buffer_position(buffer); 223 ldns_buffer_write_u16(buffer, 0); 224 } 225 for (i = 0; i < ldns_rr_rd_count(rr); i++) { 226 if (pre_rfc3597) { 227 (void) ldns_rdf2buffer_wire_canonical( 228 buffer, ldns_rr_rdf(rr, i)); 229 } else { 230 (void) ldns_rdf2buffer_wire( 231 buffer, ldns_rr_rdf(rr, i)); 232 } 233 } 234 if (rdl_pos != 0) { 235 ldns_buffer_write_u16_at(buffer, rdl_pos, 236 ldns_buffer_position(buffer) 237 - rdl_pos - 2); 238 } 239 } 240 return ldns_buffer_status(buffer); 241 } 242 243 ldns_status 244 ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section) 245 { 246 return ldns_rr2buffer_wire_compress(buffer,rr,section,NULL); 247 } 248 249 ldns_status 250 ldns_rr2buffer_wire_compress(ldns_buffer *buffer, const ldns_rr *rr, int section, ldns_rbtree_t *compression_data) 251 { 252 uint16_t i; 253 uint16_t rdl_pos = 0; 254 255 if (ldns_rr_owner(rr)) { 256 (void) ldns_dname2buffer_wire_compress(buffer, ldns_rr_owner(rr), compression_data); 257 } 258 259 if (ldns_buffer_reserve(buffer, 4)) { 260 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr)); 261 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr)); 262 } 263 264 if (section != LDNS_SECTION_QUESTION) { 265 if (ldns_buffer_reserve(buffer, 6)) { 266 ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr)); 267 /* remember pos for later */ 268 rdl_pos = ldns_buffer_position(buffer); 269 ldns_buffer_write_u16(buffer, 0); 270 } 271 if (LDNS_RR_COMPRESS == 272 ldns_rr_descript(ldns_rr_get_type(rr))->_compress) { 273 274 for (i = 0; i < ldns_rr_rd_count(rr); i++) { 275 (void) ldns_rdf2buffer_wire_compress(buffer, 276 ldns_rr_rdf(rr, i), compression_data); 277 } 278 } else { 279 for (i = 0; i < ldns_rr_rd_count(rr); i++) { 280 (void) ldns_rdf2buffer_wire( 281 buffer, ldns_rr_rdf(rr, i)); 282 } 283 } 284 if (rdl_pos != 0) { 285 ldns_buffer_write_u16_at(buffer, rdl_pos, 286 ldns_buffer_position(buffer) 287 - rdl_pos - 2); 288 } 289 } 290 return ldns_buffer_status(buffer); 291 } 292 293 ldns_status 294 ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr) 295 { 296 uint16_t i; 297 298 /* it must be a sig RR */ 299 if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) { 300 return LDNS_STATUS_ERR; 301 } 302 303 /* Convert all the rdfs, except the actual signature data 304 * rdf number 8 - the last, hence: -1 */ 305 for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) { 306 (void) ldns_rdf2buffer_wire_canonical(buffer, 307 ldns_rr_rdf(rr, i)); 308 } 309 310 return ldns_buffer_status(buffer); 311 } 312 313 ldns_status 314 ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr) 315 { 316 uint16_t i; 317 318 /* convert all the rdf's */ 319 for (i = 0; i < ldns_rr_rd_count(rr); i++) { 320 (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr,i)); 321 } 322 return ldns_buffer_status(buffer); 323 } 324 325 /* 326 * Copies the packet header data to the buffer in wire format 327 */ 328 static ldns_status 329 ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) 330 { 331 uint8_t flags; 332 uint16_t arcount; 333 334 if (ldns_buffer_reserve(buffer, 12)) { 335 ldns_buffer_write_u16(buffer, ldns_pkt_id(packet)); 336 337 flags = ldns_pkt_qr(packet) << 7 338 | ldns_pkt_get_opcode(packet) << 3 339 | ldns_pkt_aa(packet) << 2 340 | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet); 341 ldns_buffer_write_u8(buffer, flags); 342 343 flags = ldns_pkt_ra(packet) << 7 344 /*| ldns_pkt_z(packet) << 6*/ 345 | ldns_pkt_ad(packet) << 5 346 | ldns_pkt_cd(packet) << 4 347 | ldns_pkt_get_rcode(packet); 348 ldns_buffer_write_u8(buffer, flags); 349 350 ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet)); 351 ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet)); 352 ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet)); 353 /* add EDNS0 and TSIG to additional if they are there */ 354 arcount = ldns_pkt_arcount(packet); 355 if (ldns_pkt_tsig(packet)) { 356 arcount++; 357 } 358 if (ldns_pkt_edns(packet)) { 359 arcount++; 360 } 361 ldns_buffer_write_u16(buffer, arcount); 362 } 363 364 return ldns_buffer_status(buffer); 365 } 366 367 static void 368 compression_node_free(ldns_rbnode_t *node, void *arg) 369 { 370 (void)arg; /* Yes, dear compiler, it is used */ 371 ldns_rdf_deep_free((ldns_rdf *)node->key); 372 LDNS_FREE(node); 373 } 374 375 ldns_status 376 ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) 377 { 378 ldns_status status; 379 ldns_rbtree_t *compression_data = ldns_rbtree_create((int (*)(const void *, const void *))ldns_dname_compare); 380 381 status = ldns_pkt2buffer_wire_compress(buffer, packet, compression_data); 382 383 ldns_traverse_postorder(compression_data,compression_node_free,NULL); 384 ldns_rbtree_free(compression_data); 385 386 return status; 387 } 388 389 ldns_status 390 ldns_pkt2buffer_wire_compress(ldns_buffer *buffer, const ldns_pkt *packet, ldns_rbtree_t *compression_data) 391 { 392 ldns_rr_list *rr_list; 393 uint16_t i; 394 395 /* edns tmp vars */ 396 ldns_rr *edns_rr; 397 uint8_t edata[4]; 398 399 ldns_buffer *edns_buf = NULL; 400 ldns_rdf *edns_rdf = NULL; 401 402 (void) ldns_hdr2buffer_wire(buffer, packet); 403 404 rr_list = ldns_pkt_question(packet); 405 if (rr_list) { 406 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { 407 (void) ldns_rr2buffer_wire_compress(buffer, 408 ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION, compression_data); 409 } 410 } 411 rr_list = ldns_pkt_answer(packet); 412 if (rr_list) { 413 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { 414 (void) ldns_rr2buffer_wire_compress(buffer, 415 ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER, compression_data); 416 } 417 } 418 rr_list = ldns_pkt_authority(packet); 419 if (rr_list) { 420 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { 421 (void) ldns_rr2buffer_wire_compress(buffer, 422 ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY, compression_data); 423 } 424 } 425 rr_list = ldns_pkt_additional(packet); 426 if (rr_list) { 427 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { 428 (void) ldns_rr2buffer_wire_compress(buffer, 429 ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL, compression_data); 430 } 431 } 432 433 /* add EDNS to additional if it is needed */ 434 if (ldns_pkt_edns(packet)) { 435 edns_rr = ldns_rr_new(); 436 if(!edns_rr) return LDNS_STATUS_MEM_ERR; 437 ldns_rr_set_owner(edns_rr, 438 ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, ".")); 439 ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT); 440 ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet)); 441 edata[0] = ldns_pkt_edns_extended_rcode(packet); 442 edata[1] = ldns_pkt_edns_version(packet); 443 ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet)); 444 ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata)); 445 /* don't forget to add the edns rdata (if any) */ 446 if ((edns_buf = ldns_edns_option_list2wireformat_buffer(packet->_edns_list))) { 447 edns_rdf = ldns_rdf_new( LDNS_RDF_TYPE_UNKNOWN 448 , ldns_buffer_limit(edns_buf) 449 , ldns_buffer_export(edns_buf)); 450 ldns_buffer_free(edns_buf); 451 } 452 if (edns_rdf) 453 ldns_rr_push_rdf(edns_rr, edns_rdf); 454 else if (packet->_edns_data) 455 ldns_rr_push_rdf(edns_rr, packet->_edns_data); 456 (void)ldns_rr2buffer_wire_compress(buffer, edns_rr, LDNS_SECTION_ADDITIONAL, compression_data); 457 /* if the rdata of the OPT came from packet->_edns_data 458 * we need to take it back out of the edns_rr before we free it 459 * so packet->_edns_data doesn't get freed 460 */ 461 if (!edns_rdf && packet->_edns_data) 462 (void)ldns_rr_pop_rdf (edns_rr); 463 ldns_rr_free(edns_rr); 464 } 465 466 /* add TSIG to additional if it is there */ 467 if (ldns_pkt_tsig(packet)) { 468 (void) ldns_rr2buffer_wire_compress(buffer, 469 ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL, compression_data); 470 } 471 472 return LDNS_STATUS_OK; 473 } 474 475 ldns_status 476 ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size) 477 { 478 ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); 479 ldns_status status; 480 *result_size = 0; 481 *dest = NULL; 482 if(!buffer) return LDNS_STATUS_MEM_ERR; 483 484 status = ldns_rdf2buffer_wire(buffer, rdf); 485 if (status == LDNS_STATUS_OK) { 486 *result_size = ldns_buffer_position(buffer); 487 *dest = (uint8_t *) ldns_buffer_export(buffer); 488 } 489 ldns_buffer_free(buffer); 490 return status; 491 } 492 493 ldns_status 494 ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size) 495 { 496 ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); 497 ldns_status status; 498 *result_size = 0; 499 *dest = NULL; 500 if(!buffer) return LDNS_STATUS_MEM_ERR; 501 502 status = ldns_rr2buffer_wire(buffer, rr, section); 503 if (status == LDNS_STATUS_OK) { 504 *result_size = ldns_buffer_position(buffer); 505 *dest = (uint8_t *) ldns_buffer_export(buffer); 506 } 507 ldns_buffer_free(buffer); 508 return status; 509 } 510 511 ldns_status 512 ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size) 513 { 514 ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); 515 ldns_status status; 516 *result_size = 0; 517 *dest = NULL; 518 if(!buffer) return LDNS_STATUS_MEM_ERR; 519 520 status = ldns_pkt2buffer_wire(buffer, packet); 521 if (status == LDNS_STATUS_OK) { 522 *result_size = ldns_buffer_position(buffer); 523 *dest = (uint8_t *) ldns_buffer_export(buffer); 524 } 525 ldns_buffer_free(buffer); 526 return status; 527 } 528