93b017df74f8039c040b778438b73a5a1aac572b
[dragonfly.git] / contrib / ldns / host2wire.c
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                 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(buffer,
142                                                                                            ldns_rr_rdf(rr, i));
143                         } else {
144                                 (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
145                         }
146                 }
147                 
148                 if (rdl_pos != 0) {
149                         ldns_buffer_write_u16_at(buffer, rdl_pos,
150                                                  ldns_buffer_position(buffer)
151                                                    - rdl_pos - 2);
152                 }
153         }
154         return ldns_buffer_status(buffer);
155 }
156
157 ldns_status
158 ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
159 {
160         uint16_t i;
161         uint16_t rdl_pos = 0;
162         
163         if (ldns_rr_owner(rr)) {
164                 (void) ldns_dname2buffer_wire(buffer, ldns_rr_owner(rr));
165         }
166         
167         if (ldns_buffer_reserve(buffer, 4)) {
168                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
169                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
170         }
171
172         if (section != LDNS_SECTION_QUESTION) {
173                 if (ldns_buffer_reserve(buffer, 6)) {
174                         ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
175                         /* remember pos for later */
176                         rdl_pos = ldns_buffer_position(buffer);
177                         ldns_buffer_write_u16(buffer, 0);
178                 }       
179
180                 for (i = 0; i < ldns_rr_rd_count(rr); i++) {
181                         (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
182                 }
183                 
184                 if (rdl_pos != 0) {
185                         ldns_buffer_write_u16_at(buffer, rdl_pos,
186                                                  ldns_buffer_position(buffer)
187                                                    - rdl_pos - 2);
188                 }
189         }
190         return ldns_buffer_status(buffer);
191 }
192
193 ldns_status
194 ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
195 {
196         uint16_t i;
197
198         /* it must be a sig RR */
199         if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
200                 return LDNS_STATUS_ERR;
201         }
202         
203         /* Convert all the rdfs, except the actual signature data
204          * rdf number 8  - the last, hence: -1 */
205         for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) {
206                 if (ldns_rr_rdf(rr, i)) {
207                         (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
208                 }
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                         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 }