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 /* TODO Jelte 20 add a pointer to a 'possiblecompression' structure 21 to all the needed functions? 22 something like an array of name, pointer values? 23 every dname part could be added to it 24 */ 25 26 ldns_status 27 ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name) 28 { 29 if (ldns_buffer_reserve(buffer, ldns_rdf_size(name))) { 30 ldns_buffer_write(buffer, ldns_rdf_data(name), ldns_rdf_size(name)); 31 } 32 return ldns_buffer_status(buffer); 33 } 34 35 ldns_status 36 ldns_rdf2buffer_wire(ldns_buffer *buffer, const ldns_rdf *rdf) 37 { 38 if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) { 39 ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf)); 40 } 41 return ldns_buffer_status(buffer); 42 } 43 44 ldns_status 45 ldns_rdf2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rdf *rdf) 46 { 47 size_t i; 48 uint8_t *rdf_data; 49 50 if (ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME) { 51 if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) { 52 rdf_data = ldns_rdf_data(rdf); 53 for (i = 0; i < ldns_rdf_size(rdf); i++) { 54 ldns_buffer_write_u8(buffer, 55 (uint8_t) LDNS_DNAME_NORMALIZE((int)rdf_data[i])); 56 } 57 } 58 } else { 59 /* direct copy for all other types */ 60 if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) { 61 ldns_buffer_write(buffer, 62 ldns_rdf_data(rdf), 63 ldns_rdf_size(rdf)); 64 } 65 } 66 return ldns_buffer_status(buffer); 67 } 68 69 /* convert a rr list to wireformat */ 70 ldns_status 71 ldns_rr_list2buffer_wire(ldns_buffer *buffer,const ldns_rr_list *rr_list) 72 { 73 uint16_t rr_count; 74 uint16_t i; 75 76 rr_count = ldns_rr_list_rr_count(rr_list); 77 for(i = 0; i < rr_count; i++) { 78 (void)ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), 79 LDNS_SECTION_ANY); 80 } 81 return ldns_buffer_status(buffer); 82 } 83 84 ldns_status 85 ldns_rr2buffer_wire_canonical(ldns_buffer *buffer, 86 const ldns_rr *rr, 87 int section) 88 { 89 uint16_t i; 90 uint16_t rdl_pos = 0; 91 bool pre_rfc3597 = false; 92 switch (ldns_rr_get_type(rr)) { 93 case LDNS_RR_TYPE_NS: 94 case LDNS_RR_TYPE_MD: 95 case LDNS_RR_TYPE_MF: 96 case LDNS_RR_TYPE_CNAME: 97 case LDNS_RR_TYPE_SOA: 98 case LDNS_RR_TYPE_MB: 99 case LDNS_RR_TYPE_MG: 100 case LDNS_RR_TYPE_MR: 101 case LDNS_RR_TYPE_PTR: 102 case LDNS_RR_TYPE_HINFO: 103 case LDNS_RR_TYPE_MINFO: 104 case LDNS_RR_TYPE_MX: 105 case LDNS_RR_TYPE_RP: 106 case LDNS_RR_TYPE_AFSDB: 107 case LDNS_RR_TYPE_RT: 108 case LDNS_RR_TYPE_SIG: 109 case LDNS_RR_TYPE_PX: 110 case LDNS_RR_TYPE_NXT: 111 case LDNS_RR_TYPE_NAPTR: 112 case LDNS_RR_TYPE_KX: 113 case LDNS_RR_TYPE_SRV: 114 case LDNS_RR_TYPE_DNAME: 115 case LDNS_RR_TYPE_A6: 116 pre_rfc3597 = true; 117 break; 118 default: 119 break; 120 } 121 122 if (ldns_rr_owner(rr)) { 123 (void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr)); 124 } 125 126 if (ldns_buffer_reserve(buffer, 4)) { 127 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr)); 128 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr)); 129 } 130 131 if (section != LDNS_SECTION_QUESTION) { 132 if (ldns_buffer_reserve(buffer, 6)) { 133 ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr)); 134 /* remember pos for later */ 135 rdl_pos = ldns_buffer_position(buffer); 136 ldns_buffer_write_u16(buffer, 0); 137 } 138 139 for (i = 0; i < ldns_rr_rd_count(rr); i++) { 140 if (pre_rfc3597) { 141 (void) ldns_rdf2buffer_wire_canonical( 142 buffer, ldns_rr_rdf(rr, i)); 143 } else { 144 (void) ldns_rdf2buffer_wire( 145 buffer, ldns_rr_rdf(rr, i)); 146 } 147 } 148 149 if (rdl_pos != 0) { 150 ldns_buffer_write_u16_at(buffer, rdl_pos, 151 ldns_buffer_position(buffer) 152 - rdl_pos - 2); 153 } 154 } 155 return ldns_buffer_status(buffer); 156 } 157 158 ldns_status 159 ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section) 160 { 161 uint16_t i; 162 uint16_t rdl_pos = 0; 163 164 if (ldns_rr_owner(rr)) { 165 (void) ldns_dname2buffer_wire(buffer, ldns_rr_owner(rr)); 166 } 167 168 if (ldns_buffer_reserve(buffer, 4)) { 169 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr)); 170 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr)); 171 } 172 173 if (section != LDNS_SECTION_QUESTION) { 174 if (ldns_buffer_reserve(buffer, 6)) { 175 ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr)); 176 /* remember pos for later */ 177 rdl_pos = ldns_buffer_position(buffer); 178 ldns_buffer_write_u16(buffer, 0); 179 } 180 181 for (i = 0; i < ldns_rr_rd_count(rr); i++) { 182 (void) ldns_rdf2buffer_wire( 183 buffer, ldns_rr_rdf(rr, i)); 184 } 185 186 if (rdl_pos != 0) { 187 ldns_buffer_write_u16_at(buffer, rdl_pos, 188 ldns_buffer_position(buffer) 189 - rdl_pos - 2); 190 } 191 } 192 return ldns_buffer_status(buffer); 193 } 194 195 ldns_status 196 ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr) 197 { 198 uint16_t i; 199 200 /* it must be a sig RR */ 201 if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) { 202 return LDNS_STATUS_ERR; 203 } 204 205 /* Convert all the rdfs, except the actual signature data 206 * rdf number 8 - the last, hence: -1 */ 207 for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) { 208 (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i)); 209 } 210 211 return ldns_buffer_status(buffer); 212 } 213 214 ldns_status 215 ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr) 216 { 217 uint16_t i; 218 /* convert all the rdf's */ 219 for (i = 0; i < ldns_rr_rd_count(rr); i++) { 220 (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i)); 221 } 222 223 return ldns_buffer_status(buffer); 224 } 225 226 /* 227 * Copies the packet header data to the buffer in wire format 228 */ 229 static ldns_status 230 ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) 231 { 232 uint8_t flags; 233 uint16_t arcount; 234 235 if (ldns_buffer_reserve(buffer, 12)) { 236 ldns_buffer_write_u16(buffer, ldns_pkt_id(packet)); 237 238 flags = ldns_pkt_qr(packet) << 7 239 | ldns_pkt_get_opcode(packet) << 3 240 | ldns_pkt_aa(packet) << 2 241 | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet); 242 ldns_buffer_write_u8(buffer, flags); 243 244 flags = ldns_pkt_ra(packet) << 7 245 /*| ldns_pkt_z(packet) << 6*/ 246 | ldns_pkt_ad(packet) << 5 247 | ldns_pkt_cd(packet) << 4 | ldns_pkt_get_rcode(packet); 248 ldns_buffer_write_u8(buffer, flags); 249 250 ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet)); 251 ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet)); 252 ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet)); 253 /* add EDNS0 and TSIG to additional if they are there */ 254 arcount = ldns_pkt_arcount(packet); 255 if (ldns_pkt_tsig(packet)) { 256 arcount++; 257 } 258 if (ldns_pkt_edns(packet)) { 259 arcount++; 260 } 261 ldns_buffer_write_u16(buffer, arcount); 262 } 263 264 return ldns_buffer_status(buffer); 265 } 266 267 ldns_status 268 ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) 269 { 270 ldns_rr_list *rr_list; 271 uint16_t i; 272 273 /* edns tmp vars */ 274 ldns_rr *edns_rr; 275 uint8_t edata[4]; 276 277 (void) ldns_hdr2buffer_wire(buffer, packet); 278 279 rr_list = ldns_pkt_question(packet); 280 if (rr_list) { 281 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { 282 (void) ldns_rr2buffer_wire(buffer, 283 ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION); 284 } 285 } 286 rr_list = ldns_pkt_answer(packet); 287 if (rr_list) { 288 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { 289 (void) ldns_rr2buffer_wire(buffer, 290 ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER); 291 } 292 } 293 rr_list = ldns_pkt_authority(packet); 294 if (rr_list) { 295 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { 296 (void) ldns_rr2buffer_wire(buffer, 297 ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY); 298 } 299 } 300 rr_list = ldns_pkt_additional(packet); 301 if (rr_list) { 302 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { 303 (void) ldns_rr2buffer_wire(buffer, 304 ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL); 305 } 306 } 307 308 /* add EDNS to additional if it is needed */ 309 if (ldns_pkt_edns(packet)) { 310 edns_rr = ldns_rr_new(); 311 if(!edns_rr) return LDNS_STATUS_MEM_ERR; 312 ldns_rr_set_owner(edns_rr, 313 ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, ".")); 314 ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT); 315 ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet)); 316 edata[0] = ldns_pkt_edns_extended_rcode(packet); 317 edata[1] = ldns_pkt_edns_version(packet); 318 ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet)); 319 ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata)); 320 /* don't forget to add the edns rdata (if any) */ 321 if (packet->_edns_data) 322 ldns_rr_push_rdf (edns_rr, packet->_edns_data); 323 (void)ldns_rr2buffer_wire(buffer, edns_rr, LDNS_SECTION_ADDITIONAL); 324 /* take the edns rdata back out of the rr before we free rr */ 325 if (packet->_edns_data) 326 (void)ldns_rr_pop_rdf (edns_rr); 327 ldns_rr_free(edns_rr); 328 } 329 330 /* add TSIG to additional if it is there */ 331 if (ldns_pkt_tsig(packet)) { 332 (void) ldns_rr2buffer_wire(buffer, 333 ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL); 334 } 335 336 return LDNS_STATUS_OK; 337 } 338 339 ldns_status 340 ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size) 341 { 342 ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); 343 uint8_t *result = NULL; 344 ldns_status status; 345 *result_size = 0; 346 *dest = NULL; 347 if(!buffer) return LDNS_STATUS_MEM_ERR; 348 349 status = ldns_rdf2buffer_wire(buffer, rdf); 350 if (status == LDNS_STATUS_OK) { 351 *result_size = ldns_buffer_position(buffer); 352 result = (uint8_t *) ldns_buffer_export(buffer); 353 } else { 354 ldns_buffer_free(buffer); 355 return status; 356 } 357 358 if (result) { 359 *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer)); 360 if(!*dest) { 361 ldns_buffer_free(buffer); 362 return LDNS_STATUS_MEM_ERR; 363 } 364 memcpy(*dest, result, ldns_buffer_position(buffer)); 365 } 366 367 ldns_buffer_free(buffer); 368 return status; 369 } 370 371 ldns_status 372 ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size) 373 { 374 ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); 375 uint8_t *result = NULL; 376 ldns_status status; 377 *result_size = 0; 378 *dest = NULL; 379 if(!buffer) return LDNS_STATUS_MEM_ERR; 380 381 status = ldns_rr2buffer_wire(buffer, rr, section); 382 if (status == LDNS_STATUS_OK) { 383 *result_size = ldns_buffer_position(buffer); 384 result = (uint8_t *) ldns_buffer_export(buffer); 385 } else { 386 ldns_buffer_free(buffer); 387 return status; 388 } 389 390 if (result) { 391 *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer)); 392 if(!*dest) { 393 ldns_buffer_free(buffer); 394 return LDNS_STATUS_MEM_ERR; 395 } 396 memcpy(*dest, result, ldns_buffer_position(buffer)); 397 } 398 399 ldns_buffer_free(buffer); 400 return status; 401 } 402 403 ldns_status 404 ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size) 405 { 406 ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); 407 uint8_t *result = NULL; 408 ldns_status status; 409 *result_size = 0; 410 *dest = NULL; 411 if(!buffer) return LDNS_STATUS_MEM_ERR; 412 413 status = ldns_pkt2buffer_wire(buffer, packet); 414 if (status == LDNS_STATUS_OK) { 415 *result_size = ldns_buffer_position(buffer); 416 result = (uint8_t *) ldns_buffer_export(buffer); 417 } else { 418 ldns_buffer_free(buffer); 419 return status; 420 } 421 422 if (result) { 423 *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer)); 424 if(!*dest) { 425 ldns_buffer_free(buffer); 426 return LDNS_STATUS_MEM_ERR; 427 } 428 memcpy(*dest, result, ldns_buffer_position(buffer)); 429 } 430 431 ldns_buffer_free(buffer); 432 return status; 433 } 434