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)
8 * a Net::DNS like library for C
10 * (c) NLnet Labs, 2004-2006
12 * See the file LICENSE for the license
15 #include <ldns/config.h>
17 #include <ldns/ldns.h>
20 ldns_dname2buffer_wire(ldns_buffer
*buffer
, const ldns_rdf
*name
)
22 return ldns_dname2buffer_wire_compress(buffer
, name
, NULL
);
26 ldns_dname2buffer_wire_compress(ldns_buffer
*buffer
, const ldns_rdf
*name
, ldns_rbtree_t
*compression_data
)
35 /* If no tree, just add the data */
38 if (ldns_buffer_reserve(buffer
, ldns_rdf_size(name
)))
40 ldns_buffer_write(buffer
, ldns_rdf_data(name
), ldns_rdf_size(name
));
42 return ldns_buffer_status(buffer
);
45 /* No labels left, write final zero */
46 if(ldns_dname_label_count(name
)==0)
48 if(ldns_buffer_reserve(buffer
,1))
50 ldns_buffer_write_u8(buffer
, 0);
52 return ldns_buffer_status(buffer
);
55 /* Can we find the name in the tree? */
56 if((node
= ldns_rbtree_search(compression_data
, name
)) != NULL
)
59 uint16_t position
= (uint16_t) (intptr_t) node
->data
| 0xC000;
60 if (ldns_buffer_reserve(buffer
, 2))
62 ldns_buffer_write_u16(buffer
, position
);
64 return ldns_buffer_status(buffer
);
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) {
73 node
= LDNS_MALLOC(ldns_rbnode_t
);
76 return LDNS_STATUS_MEM_ERR
;
79 key
= ldns_rdf_clone(name
);
82 return LDNS_STATUS_MEM_ERR
;
85 node
->data
= (void *) (intptr_t) ldns_buffer_position(buffer
);
86 if(!ldns_rbtree_insert(compression_data
,node
))
88 /* fprintf(stderr,"Name not found but now it's there?\n"); */
89 ldns_rdf_deep_free(key
);
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
))
99 ldns_buffer_write(buffer
, data
, size
);
101 ldns_rdf_deep_free(label
);
102 s
= ldns_dname2buffer_wire_compress(buffer
, rest
, compression_data
);
103 ldns_rdf_deep_free(rest
);
109 ldns_rdf2buffer_wire(ldns_buffer
*buffer
, const ldns_rdf
*rdf
)
111 return ldns_rdf2buffer_wire_compress(buffer
, rdf
, NULL
);
115 ldns_rdf2buffer_wire_compress(ldns_buffer
*buffer
, const ldns_rdf
*rdf
, ldns_rbtree_t
*compression_data
)
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
)
120 return ldns_dname2buffer_wire_compress(buffer
,rdf
,compression_data
);
123 if (ldns_buffer_reserve(buffer
, ldns_rdf_size(rdf
))) {
124 ldns_buffer_write(buffer
, ldns_rdf_data(rdf
), ldns_rdf_size(rdf
));
126 return ldns_buffer_status(buffer
);
130 ldns_rdf2buffer_wire_canonical(ldns_buffer
*buffer
, const ldns_rdf
*rdf
)
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
]));
144 /* direct copy for all other types */
145 if (ldns_buffer_reserve(buffer
, ldns_rdf_size(rdf
))) {
146 ldns_buffer_write(buffer
,
151 return ldns_buffer_status(buffer
);
154 /* convert a rr list to wireformat */
156 ldns_rr_list2buffer_wire(ldns_buffer
*buffer
,const ldns_rr_list
*rr_list
)
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
),
166 return ldns_buffer_status(buffer
);
171 ldns_rr2buffer_wire_canonical(ldns_buffer
*buffer
,
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
:
209 if (ldns_rr_owner(rr
)) {
210 (void) ldns_rdf2buffer_wire_canonical(buffer
, ldns_rr_owner(rr
));
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
));
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);
225 for (i
= 0; i
< ldns_rr_rd_count(rr
); i
++) {
227 (void) ldns_rdf2buffer_wire_canonical(
228 buffer
, ldns_rr_rdf(rr
, i
));
230 (void) ldns_rdf2buffer_wire(
231 buffer
, ldns_rr_rdf(rr
, i
));
235 ldns_buffer_write_u16_at(buffer
, rdl_pos
,
236 ldns_buffer_position(buffer
)
240 return ldns_buffer_status(buffer
);
244 ldns_rr2buffer_wire(ldns_buffer
*buffer
, const ldns_rr
*rr
, int section
)
246 return ldns_rr2buffer_wire_compress(buffer
,rr
,section
,NULL
);
250 ldns_rr2buffer_wire_compress(ldns_buffer
*buffer
, const ldns_rr
*rr
, int section
, ldns_rbtree_t
*compression_data
)
253 uint16_t rdl_pos
= 0;
255 if (ldns_rr_owner(rr
)) {
256 (void) ldns_dname2buffer_wire_compress(buffer
, ldns_rr_owner(rr
), compression_data
);
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
));
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);
271 if (LDNS_RR_COMPRESS
==
272 ldns_rr_descript(ldns_rr_get_type(rr
))->_compress
) {
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
);
279 for (i
= 0; i
< ldns_rr_rd_count(rr
); i
++) {
280 (void) ldns_rdf2buffer_wire(
281 buffer
, ldns_rr_rdf(rr
, i
));
285 ldns_buffer_write_u16_at(buffer
, rdl_pos
,
286 ldns_buffer_position(buffer
)
290 return ldns_buffer_status(buffer
);
294 ldns_rrsig2buffer_wire(ldns_buffer
*buffer
, const ldns_rr
*rr
)
298 /* it must be a sig RR */
299 if (ldns_rr_get_type(rr
) != LDNS_RR_TYPE_RRSIG
) {
300 return LDNS_STATUS_ERR
;
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
,
310 return ldns_buffer_status(buffer
);
314 ldns_rr_rdata2buffer_wire(ldns_buffer
*buffer
, const ldns_rr
*rr
)
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
));
322 return ldns_buffer_status(buffer
);
326 * Copies the packet header data to the buffer in wire format
329 ldns_hdr2buffer_wire(ldns_buffer
*buffer
, const ldns_pkt
*packet
)
334 if (ldns_buffer_reserve(buffer
, 12)) {
335 ldns_buffer_write_u16(buffer
, ldns_pkt_id(packet
));
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
);
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
);
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
)) {
358 if (ldns_pkt_edns(packet
)) {
361 ldns_buffer_write_u16(buffer
, arcount
);
364 return ldns_buffer_status(buffer
);
368 compression_node_free(ldns_rbnode_t
*node
, void *arg
)
370 (void)arg
; /* Yes, dear compiler, it is used */
371 ldns_rdf_deep_free((ldns_rdf
*)node
->key
);
376 ldns_pkt2buffer_wire(ldns_buffer
*buffer
, const ldns_pkt
*packet
)
379 ldns_rbtree_t
*compression_data
= ldns_rbtree_create((int (*)(const void *, const void *))ldns_dname_compare
);
381 status
= ldns_pkt2buffer_wire_compress(buffer
, packet
, compression_data
);
383 ldns_traverse_postorder(compression_data
,compression_node_free
,NULL
);
384 ldns_rbtree_free(compression_data
);
390 ldns_pkt2buffer_wire_compress(ldns_buffer
*buffer
, const ldns_pkt
*packet
, ldns_rbtree_t
*compression_data
)
392 ldns_rr_list
*rr_list
;
399 ldns_buffer
*edns_buf
= NULL
;
400 ldns_rdf
*edns_rdf
= NULL
;
402 (void) ldns_hdr2buffer_wire(buffer
, packet
);
404 rr_list
= ldns_pkt_question(packet
);
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
);
411 rr_list
= ldns_pkt_answer(packet
);
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
);
418 rr_list
= ldns_pkt_authority(packet
);
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
);
425 rr_list
= ldns_pkt_additional(packet
);
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
);
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
);
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
461 if (!edns_rdf
&& packet
->_edns_data
)
462 (void)ldns_rr_pop_rdf (edns_rr
);
463 ldns_rr_free(edns_rr
);
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
);
472 return LDNS_STATUS_OK
;
476 ldns_rdf2wire(uint8_t **dest
, const ldns_rdf
*rdf
, size_t *result_size
)
478 ldns_buffer
*buffer
= ldns_buffer_new(LDNS_MAX_PACKETLEN
);
482 if(!buffer
) return LDNS_STATUS_MEM_ERR
;
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
);
489 ldns_buffer_free(buffer
);
494 ldns_rr2wire(uint8_t **dest
, const ldns_rr
*rr
, int section
, size_t *result_size
)
496 ldns_buffer
*buffer
= ldns_buffer_new(LDNS_MAX_PACKETLEN
);
500 if(!buffer
) return LDNS_STATUS_MEM_ERR
;
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
);
507 ldns_buffer_free(buffer
);
512 ldns_pkt2wire(uint8_t **dest
, const ldns_pkt
*packet
, size_t *result_size
)
514 ldns_buffer
*buffer
= ldns_buffer_new(LDNS_MAX_PACKETLEN
);
518 if(!buffer
) return LDNS_STATUS_MEM_ERR
;
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
);
525 ldns_buffer_free(buffer
);