kernel - Fix lockup due to recentn pmap change
[dragonfly.git] / contrib / ldns / host2wire.c
blobde1e01e9ba3f074cf571496a6a9834117b4e30d2
1 /*
2 * host2wire.c
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>
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
26 ldns_status
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);
35 ldns_status
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);
44 ldns_status
45 ldns_rdf2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rdf *rdf)
47 size_t i;
48 uint8_t *rdf_data;
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]));
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));
66 return ldns_buffer_status(buffer);
69 /* convert a rr list to wireformat */
70 ldns_status
71 ldns_rr_list2buffer_wire(ldns_buffer *buffer,const ldns_rr_list *rr_list)
73 uint16_t rr_count;
74 uint16_t i;
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);
81 return ldns_buffer_status(buffer);
84 ldns_status
85 ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
86 const ldns_rr *rr,
87 int section)
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 case LDNS_RR_TYPE_RRSIG:
117 pre_rfc3597 = true;
118 break;
119 default:
120 break;
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++) {
141 if (pre_rfc3597) {
142 (void) ldns_rdf2buffer_wire_canonical(
143 buffer, ldns_rr_rdf(rr, i));
144 } else {
145 (void) ldns_rdf2buffer_wire(
146 buffer, ldns_rr_rdf(rr, i));
150 if (rdl_pos != 0) {
151 ldns_buffer_write_u16_at(buffer, rdl_pos,
152 ldns_buffer_position(buffer)
153 - rdl_pos - 2);
156 return ldns_buffer_status(buffer);
159 ldns_status
160 ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
162 uint16_t i;
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));
187 if (rdl_pos != 0) {
188 ldns_buffer_write_u16_at(buffer, rdl_pos,
189 ldns_buffer_position(buffer)
190 - rdl_pos - 2);
193 return ldns_buffer_status(buffer);
196 ldns_status
197 ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
199 uint16_t i;
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);
215 ldns_status
216 ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
218 uint16_t i;
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
230 static ldns_status
231 ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
233 uint8_t flags;
234 uint16_t arcount;
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)) {
257 arcount++;
259 if (ldns_pkt_edns(packet)) {
260 arcount++;
262 ldns_buffer_write_u16(buffer, arcount);
265 return ldns_buffer_status(buffer);
268 ldns_status
269 ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
271 ldns_rr_list *rr_list;
272 uint16_t i;
274 /* edns tmp vars */
275 ldns_rr *edns_rr;
276 uint8_t edata[4];
278 (void) ldns_hdr2buffer_wire(buffer, packet);
280 rr_list = ldns_pkt_question(packet);
281 if (rr_list) {
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);
288 if (rr_list) {
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);
295 if (rr_list) {
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);
302 if (rr_list) {
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;
340 ldns_status
341 ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
343 ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
344 ldns_status status;
345 *result_size = 0;
346 *dest = NULL;
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);
355 return status;
358 ldns_status
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);
362 ldns_status status;
363 *result_size = 0;
364 *dest = NULL;
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);
373 return status;
376 ldns_status
377 ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
379 ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
380 ldns_status status;
381 *result_size = 0;
382 *dest = NULL;
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);
391 return status;