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 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
27 ldns_dname2buffer_wire(ldns_buffer
*buffer
, const ldns_rdf
*name
)
29 if (ldns_buffer_reserve(buffer
, ldns_rdf_size(name
))) {
30 ldns_buffer_write(buffer
, ldns_rdf_data(name
), ldns_rdf_size(name
));
32 return ldns_buffer_status(buffer
);
36 ldns_rdf2buffer_wire(ldns_buffer
*buffer
, const ldns_rdf
*rdf
)
38 if (ldns_buffer_reserve(buffer
, ldns_rdf_size(rdf
))) {
39 ldns_buffer_write(buffer
, ldns_rdf_data(rdf
), ldns_rdf_size(rdf
));
41 return ldns_buffer_status(buffer
);
45 ldns_rdf2buffer_wire_canonical(ldns_buffer
*buffer
, const ldns_rdf
*rdf
)
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
]));
59 /* direct copy for all other types */
60 if (ldns_buffer_reserve(buffer
, ldns_rdf_size(rdf
))) {
61 ldns_buffer_write(buffer
,
66 return ldns_buffer_status(buffer
);
69 /* convert a rr list to wireformat */
71 ldns_rr_list2buffer_wire(ldns_buffer
*buffer
,const ldns_rr_list
*rr_list
)
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
),
81 return ldns_buffer_status(buffer
);
85 ldns_rr2buffer_wire_canonical(ldns_buffer
*buffer
,
91 bool pre_rfc3597
= false;
92 switch (ldns_rr_get_type(rr
)) {
96 case LDNS_RR_TYPE_CNAME
:
97 case LDNS_RR_TYPE_SOA
:
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 case LDNS_RR_TYPE_RRSIG
:
123 if (ldns_rr_owner(rr
)) {
124 (void) ldns_rdf2buffer_wire_canonical(buffer
, ldns_rr_owner(rr
));
127 if (ldns_buffer_reserve(buffer
, 4)) {
128 (void) ldns_buffer_write_u16(buffer
, ldns_rr_get_type(rr
));
129 (void) ldns_buffer_write_u16(buffer
, ldns_rr_get_class(rr
));
132 if (section
!= LDNS_SECTION_QUESTION
) {
133 if (ldns_buffer_reserve(buffer
, 6)) {
134 ldns_buffer_write_u32(buffer
, ldns_rr_ttl(rr
));
135 /* remember pos for later */
136 rdl_pos
= ldns_buffer_position(buffer
);
137 ldns_buffer_write_u16(buffer
, 0);
140 for (i
= 0; i
< ldns_rr_rd_count(rr
); i
++) {
142 (void) ldns_rdf2buffer_wire_canonical(
143 buffer
, ldns_rr_rdf(rr
, i
));
145 (void) ldns_rdf2buffer_wire(
146 buffer
, ldns_rr_rdf(rr
, i
));
151 ldns_buffer_write_u16_at(buffer
, rdl_pos
,
152 ldns_buffer_position(buffer
)
156 return ldns_buffer_status(buffer
);
160 ldns_rr2buffer_wire(ldns_buffer
*buffer
, const ldns_rr
*rr
, int section
)
163 uint16_t rdl_pos
= 0;
165 if (ldns_rr_owner(rr
)) {
166 (void) ldns_dname2buffer_wire(buffer
, ldns_rr_owner(rr
));
169 if (ldns_buffer_reserve(buffer
, 4)) {
170 (void) ldns_buffer_write_u16(buffer
, ldns_rr_get_type(rr
));
171 (void) ldns_buffer_write_u16(buffer
, ldns_rr_get_class(rr
));
174 if (section
!= LDNS_SECTION_QUESTION
) {
175 if (ldns_buffer_reserve(buffer
, 6)) {
176 ldns_buffer_write_u32(buffer
, ldns_rr_ttl(rr
));
177 /* remember pos for later */
178 rdl_pos
= ldns_buffer_position(buffer
);
179 ldns_buffer_write_u16(buffer
, 0);
182 for (i
= 0; i
< ldns_rr_rd_count(rr
); i
++) {
183 (void) ldns_rdf2buffer_wire(
184 buffer
, ldns_rr_rdf(rr
, i
));
188 ldns_buffer_write_u16_at(buffer
, rdl_pos
,
189 ldns_buffer_position(buffer
)
193 return ldns_buffer_status(buffer
);
197 ldns_rrsig2buffer_wire(ldns_buffer
*buffer
, const ldns_rr
*rr
)
201 /* it must be a sig RR */
202 if (ldns_rr_get_type(rr
) != LDNS_RR_TYPE_RRSIG
) {
203 return LDNS_STATUS_ERR
;
206 /* Convert all the rdfs, except the actual signature data
207 * rdf number 8 - the last, hence: -1 */
208 for (i
= 0; i
< ldns_rr_rd_count(rr
) - 1; i
++) {
209 (void) ldns_rdf2buffer_wire_canonical(buffer
, ldns_rr_rdf(rr
, i
));
212 return ldns_buffer_status(buffer
);
216 ldns_rr_rdata2buffer_wire(ldns_buffer
*buffer
, const ldns_rr
*rr
)
219 /* convert all the rdf's */
220 for (i
= 0; i
< ldns_rr_rd_count(rr
); i
++) {
221 (void) ldns_rdf2buffer_wire(buffer
, ldns_rr_rdf(rr
, i
));
224 return ldns_buffer_status(buffer
);
228 * Copies the packet header data to the buffer in wire format
231 ldns_hdr2buffer_wire(ldns_buffer
*buffer
, const ldns_pkt
*packet
)
236 if (ldns_buffer_reserve(buffer
, 12)) {
237 ldns_buffer_write_u16(buffer
, ldns_pkt_id(packet
));
239 flags
= ldns_pkt_qr(packet
) << 7
240 | ldns_pkt_get_opcode(packet
) << 3
241 | ldns_pkt_aa(packet
) << 2
242 | ldns_pkt_tc(packet
) << 1 | ldns_pkt_rd(packet
);
243 ldns_buffer_write_u8(buffer
, flags
);
245 flags
= ldns_pkt_ra(packet
) << 7
246 /*| ldns_pkt_z(packet) << 6*/
247 | ldns_pkt_ad(packet
) << 5
248 | ldns_pkt_cd(packet
) << 4 | ldns_pkt_get_rcode(packet
);
249 ldns_buffer_write_u8(buffer
, flags
);
251 ldns_buffer_write_u16(buffer
, ldns_pkt_qdcount(packet
));
252 ldns_buffer_write_u16(buffer
, ldns_pkt_ancount(packet
));
253 ldns_buffer_write_u16(buffer
, ldns_pkt_nscount(packet
));
254 /* add EDNS0 and TSIG to additional if they are there */
255 arcount
= ldns_pkt_arcount(packet
);
256 if (ldns_pkt_tsig(packet
)) {
259 if (ldns_pkt_edns(packet
)) {
262 ldns_buffer_write_u16(buffer
, arcount
);
265 return ldns_buffer_status(buffer
);
269 ldns_pkt2buffer_wire(ldns_buffer
*buffer
, const ldns_pkt
*packet
)
271 ldns_rr_list
*rr_list
;
278 (void) ldns_hdr2buffer_wire(buffer
, packet
);
280 rr_list
= ldns_pkt_question(packet
);
282 for (i
= 0; i
< ldns_rr_list_rr_count(rr_list
); i
++) {
283 (void) ldns_rr2buffer_wire(buffer
,
284 ldns_rr_list_rr(rr_list
, i
), LDNS_SECTION_QUESTION
);
287 rr_list
= ldns_pkt_answer(packet
);
289 for (i
= 0; i
< ldns_rr_list_rr_count(rr_list
); i
++) {
290 (void) ldns_rr2buffer_wire(buffer
,
291 ldns_rr_list_rr(rr_list
, i
), LDNS_SECTION_ANSWER
);
294 rr_list
= ldns_pkt_authority(packet
);
296 for (i
= 0; i
< ldns_rr_list_rr_count(rr_list
); i
++) {
297 (void) ldns_rr2buffer_wire(buffer
,
298 ldns_rr_list_rr(rr_list
, i
), LDNS_SECTION_AUTHORITY
);
301 rr_list
= ldns_pkt_additional(packet
);
303 for (i
= 0; i
< ldns_rr_list_rr_count(rr_list
); i
++) {
304 (void) ldns_rr2buffer_wire(buffer
,
305 ldns_rr_list_rr(rr_list
, i
), LDNS_SECTION_ADDITIONAL
);
309 /* add EDNS to additional if it is needed */
310 if (ldns_pkt_edns(packet
)) {
311 edns_rr
= ldns_rr_new();
312 if(!edns_rr
) return LDNS_STATUS_MEM_ERR
;
313 ldns_rr_set_owner(edns_rr
,
314 ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME
, "."));
315 ldns_rr_set_type(edns_rr
, LDNS_RR_TYPE_OPT
);
316 ldns_rr_set_class(edns_rr
, ldns_pkt_edns_udp_size(packet
));
317 edata
[0] = ldns_pkt_edns_extended_rcode(packet
);
318 edata
[1] = ldns_pkt_edns_version(packet
);
319 ldns_write_uint16(&edata
[2], ldns_pkt_edns_z(packet
));
320 ldns_rr_set_ttl(edns_rr
, ldns_read_uint32(edata
));
321 /* don't forget to add the edns rdata (if any) */
322 if (packet
->_edns_data
)
323 ldns_rr_push_rdf (edns_rr
, packet
->_edns_data
);
324 (void)ldns_rr2buffer_wire(buffer
, edns_rr
, LDNS_SECTION_ADDITIONAL
);
325 /* take the edns rdata back out of the rr before we free rr */
326 if (packet
->_edns_data
)
327 (void)ldns_rr_pop_rdf (edns_rr
);
328 ldns_rr_free(edns_rr
);
331 /* add TSIG to additional if it is there */
332 if (ldns_pkt_tsig(packet
)) {
333 (void) ldns_rr2buffer_wire(buffer
,
334 ldns_pkt_tsig(packet
), LDNS_SECTION_ADDITIONAL
);
337 return LDNS_STATUS_OK
;
341 ldns_rdf2wire(uint8_t **dest
, const ldns_rdf
*rdf
, size_t *result_size
)
343 ldns_buffer
*buffer
= ldns_buffer_new(LDNS_MAX_PACKETLEN
);
347 if(!buffer
) return LDNS_STATUS_MEM_ERR
;
349 status
= ldns_rdf2buffer_wire(buffer
, rdf
);
350 if (status
== LDNS_STATUS_OK
) {
351 *result_size
= ldns_buffer_position(buffer
);
352 *dest
= (uint8_t *) ldns_buffer_export(buffer
);
354 ldns_buffer_free(buffer
);
359 ldns_rr2wire(uint8_t **dest
, const ldns_rr
*rr
, int section
, size_t *result_size
)
361 ldns_buffer
*buffer
= ldns_buffer_new(LDNS_MAX_PACKETLEN
);
365 if(!buffer
) return LDNS_STATUS_MEM_ERR
;
367 status
= ldns_rr2buffer_wire(buffer
, rr
, section
);
368 if (status
== LDNS_STATUS_OK
) {
369 *result_size
= ldns_buffer_position(buffer
);
370 *dest
= (uint8_t *) ldns_buffer_export(buffer
);
372 ldns_buffer_free(buffer
);
377 ldns_pkt2wire(uint8_t **dest
, const ldns_pkt
*packet
, size_t *result_size
)
379 ldns_buffer
*buffer
= ldns_buffer_new(LDNS_MAX_PACKETLEN
);
383 if(!buffer
) return LDNS_STATUS_MEM_ERR
;
385 status
= ldns_pkt2buffer_wire(buffer
, packet
);
386 if (status
== LDNS_STATUS_OK
) {
387 *result_size
= ldns_buffer_position(buffer
);
388 *dest
= (uint8_t *) ldns_buffer_export(buffer
);
390 ldns_buffer_free(buffer
);