]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ldns/host2wire.c
sysctl(9): Fix a few mandoc related issues
[FreeBSD/FreeBSD.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 ldns_status
20 ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name)
21 {
22         return ldns_dname2buffer_wire_compress(buffer, name, NULL);
23 }
24
25 ldns_status
26 ldns_dname2buffer_wire_compress(ldns_buffer *buffer, const ldns_rdf *name, ldns_rbtree_t *compression_data)
27 {
28         ldns_rbnode_t *node;
29         uint8_t *data;
30         size_t size;
31         ldns_rdf *label;
32         ldns_rdf *rest;
33         ldns_status s;
34
35         /* If no tree, just add the data */
36         if(!compression_data)
37         {
38                 if (ldns_buffer_reserve(buffer, ldns_rdf_size(name)))
39                 {
40                         ldns_buffer_write(buffer, ldns_rdf_data(name), ldns_rdf_size(name));
41                 }
42                 return ldns_buffer_status(buffer);
43         }
44
45         /* No labels left, write final zero */
46         if(ldns_dname_label_count(name)==0)
47         {
48                 if(ldns_buffer_reserve(buffer,1))
49                 {
50                         ldns_buffer_write_u8(buffer, 0);
51                 }
52                 return ldns_buffer_status(buffer);
53         }
54
55         /* Can we find the name in the tree? */
56         if((node = ldns_rbtree_search(compression_data, name)) != NULL)
57         {
58                 /* Found */
59                 uint16_t position = (uint16_t) (intptr_t) node->data | 0xC000;
60                 if (ldns_buffer_reserve(buffer, 2))
61                 {
62                         ldns_buffer_write_u16(buffer, position);
63                 }
64                 return ldns_buffer_status(buffer);
65         }
66         else
67         {
68                 /* Not found. Write cache entry, take off first label, write it, */
69                 /* try again with the rest of the name. */
70                 node = LDNS_MALLOC(ldns_rbnode_t);
71                 if(!node)
72                 {
73                         return LDNS_STATUS_MEM_ERR;
74                 }
75                 if (ldns_buffer_position(buffer) < 16384) {
76                         node->key = ldns_rdf_clone(name);
77                         node->data = (void *) (intptr_t) ldns_buffer_position(buffer);
78                         if(!ldns_rbtree_insert(compression_data,node))
79                         {
80                                 /* fprintf(stderr,"Name not found but now it's there?\n"); */
81                         }
82                 }
83                 label = ldns_dname_label(name, 0);
84                 rest = ldns_dname_left_chop(name);
85                 size = ldns_rdf_size(label) - 1; /* Don't want the final zero */
86                 data = ldns_rdf_data(label);
87                 if(ldns_buffer_reserve(buffer, size))
88                 {
89                         ldns_buffer_write(buffer, data, size);
90                 }
91                 ldns_rdf_deep_free(label);
92                 s = ldns_dname2buffer_wire_compress(buffer, rest, compression_data);
93                 ldns_rdf_deep_free(rest);
94                 return s;
95         }
96 }
97
98 ldns_status
99 ldns_rdf2buffer_wire(ldns_buffer *buffer, const ldns_rdf *rdf)
100 {
101         return ldns_rdf2buffer_wire_compress(buffer, rdf, NULL);
102 }
103
104 ldns_status
105 ldns_rdf2buffer_wire_compress(ldns_buffer *buffer, const ldns_rdf *rdf, ldns_rbtree_t *compression_data)
106 {
107         /* If it's a DNAME, call that function to get compression */
108         if(compression_data && ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME)
109         {
110                 return ldns_dname2buffer_wire_compress(buffer,rdf,compression_data);
111         }
112
113         if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
114                 ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf));
115         }
116         return ldns_buffer_status(buffer);
117 }
118
119 ldns_status
120 ldns_rdf2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rdf *rdf)
121 {
122         size_t i;
123         uint8_t *rdf_data;
124
125         if (ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME) {
126                 if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
127                         rdf_data = ldns_rdf_data(rdf);
128                         for (i = 0; i < ldns_rdf_size(rdf); i++) {
129                                 ldns_buffer_write_u8(buffer,
130                                     (uint8_t) LDNS_DNAME_NORMALIZE((int)rdf_data[i]));
131                         }
132                 }
133         } else {
134                 /* direct copy for all other types */
135                 if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
136                         ldns_buffer_write(buffer,
137                                                    ldns_rdf_data(rdf),
138                                                    ldns_rdf_size(rdf));
139                 }
140         }
141         return ldns_buffer_status(buffer);
142 }
143
144 /* convert a rr list to wireformat */
145 ldns_status
146 ldns_rr_list2buffer_wire(ldns_buffer *buffer,const ldns_rr_list *rr_list)
147 {
148         uint16_t rr_count;
149         uint16_t i;
150
151         rr_count = ldns_rr_list_rr_count(rr_list);
152         for(i = 0; i < rr_count; i++) {
153                 (void)ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), 
154                                           LDNS_SECTION_ANY);
155         }
156         return ldns_buffer_status(buffer);
157 }
158
159
160 ldns_status
161 ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
162                                                 const ldns_rr *rr,
163                                                 int section)
164 {
165         uint16_t i;
166         uint16_t rdl_pos = 0;
167         bool pre_rfc3597 = false;
168         switch (ldns_rr_get_type(rr)) {
169         case LDNS_RR_TYPE_NS:
170         case LDNS_RR_TYPE_MD:
171         case LDNS_RR_TYPE_MF:
172         case LDNS_RR_TYPE_CNAME:
173         case LDNS_RR_TYPE_SOA:
174         case LDNS_RR_TYPE_MB:
175         case LDNS_RR_TYPE_MG:
176         case LDNS_RR_TYPE_MR:
177         case LDNS_RR_TYPE_PTR:
178         case LDNS_RR_TYPE_HINFO:
179         case LDNS_RR_TYPE_MINFO:
180         case LDNS_RR_TYPE_MX:
181         case LDNS_RR_TYPE_RP:
182         case LDNS_RR_TYPE_AFSDB:
183         case LDNS_RR_TYPE_RT:
184         case LDNS_RR_TYPE_SIG:
185         case LDNS_RR_TYPE_PX:
186         case LDNS_RR_TYPE_NXT:
187         case LDNS_RR_TYPE_NAPTR:
188         case LDNS_RR_TYPE_KX:
189         case LDNS_RR_TYPE_SRV:
190         case LDNS_RR_TYPE_DNAME:
191         case LDNS_RR_TYPE_A6:
192         case LDNS_RR_TYPE_RRSIG:
193                 pre_rfc3597 = true;
194                 break;
195         default:
196                 break;
197         }
198         
199         if (ldns_rr_owner(rr)) {
200                 (void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr));
201         }
202         
203         if (ldns_buffer_reserve(buffer, 4)) {
204                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
205                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
206         }
207
208         if (section != LDNS_SECTION_QUESTION) {
209                 if (ldns_buffer_reserve(buffer, 6)) {
210                         ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
211                         /* remember pos for later */
212                         rdl_pos = ldns_buffer_position(buffer);
213                         ldns_buffer_write_u16(buffer, 0);
214                 }       
215                 for (i = 0; i < ldns_rr_rd_count(rr); i++) {
216                         if (pre_rfc3597) {
217                                 (void) ldns_rdf2buffer_wire_canonical(
218                                         buffer, ldns_rr_rdf(rr, i));
219                         } else {
220                                 (void) ldns_rdf2buffer_wire(
221                                         buffer, ldns_rr_rdf(rr, i));
222                         }
223                 }
224                 if (rdl_pos != 0) {
225                         ldns_buffer_write_u16_at(buffer, rdl_pos,
226                                                  ldns_buffer_position(buffer)
227                                                    - rdl_pos - 2);
228                 }
229         }
230         return ldns_buffer_status(buffer);
231 }
232
233 ldns_status
234 ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
235 {
236         return ldns_rr2buffer_wire_compress(buffer,rr,section,NULL);
237 }
238
239 ldns_status
240 ldns_rr2buffer_wire_compress(ldns_buffer *buffer, const ldns_rr *rr, int section, ldns_rbtree_t *compression_data)
241 {
242         uint16_t i;
243         uint16_t rdl_pos = 0;
244
245         if (ldns_rr_owner(rr)) {
246                 (void) ldns_dname2buffer_wire_compress(buffer, ldns_rr_owner(rr), compression_data);
247         }
248         
249         if (ldns_buffer_reserve(buffer, 4)) {
250                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
251                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
252         }
253
254         if (section != LDNS_SECTION_QUESTION) {
255                 if (ldns_buffer_reserve(buffer, 6)) {
256                         ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
257                         /* remember pos for later */
258                         rdl_pos = ldns_buffer_position(buffer);
259                         ldns_buffer_write_u16(buffer, 0);
260                 }
261                 if (LDNS_RR_COMPRESS ==
262                     ldns_rr_descript(ldns_rr_get_type(rr))->_compress) {
263
264                         for (i = 0; i < ldns_rr_rd_count(rr); i++) {
265                                 (void) ldns_rdf2buffer_wire_compress(buffer,
266                                     ldns_rr_rdf(rr, i), compression_data);
267                         }
268                 } else {
269                         for (i = 0; i < ldns_rr_rd_count(rr); i++) {
270                                 (void) ldns_rdf2buffer_wire(
271                                     buffer, ldns_rr_rdf(rr, i));
272                         }
273                 }
274                 if (rdl_pos != 0) {
275                         ldns_buffer_write_u16_at(buffer, rdl_pos,
276                                                  ldns_buffer_position(buffer)
277                                                    - rdl_pos - 2);
278                 }
279         }
280         return ldns_buffer_status(buffer);
281 }
282
283 ldns_status
284 ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
285 {
286         uint16_t i;
287
288         /* it must be a sig RR */
289         if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
290                 return LDNS_STATUS_ERR;
291         }
292         
293         /* Convert all the rdfs, except the actual signature data
294          * rdf number 8  - the last, hence: -1 */
295         for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) {
296                 (void) ldns_rdf2buffer_wire_canonical(buffer, 
297                                 ldns_rr_rdf(rr, i));
298         }
299
300         return ldns_buffer_status(buffer);
301 }
302
303 ldns_status
304 ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
305 {
306         uint16_t i;
307
308         /* convert all the rdf's */
309         for (i = 0; i < ldns_rr_rd_count(rr); i++) {
310                 (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr,i));
311         }
312         return ldns_buffer_status(buffer);
313 }
314
315 /*
316  * Copies the packet header data to the buffer in wire format
317  */
318 static ldns_status
319 ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
320 {
321         uint8_t flags;
322         uint16_t arcount;
323
324         if (ldns_buffer_reserve(buffer, 12)) {
325                 ldns_buffer_write_u16(buffer, ldns_pkt_id(packet));
326                 
327                 flags = ldns_pkt_qr(packet) << 7
328                         | ldns_pkt_get_opcode(packet) << 3
329                         | ldns_pkt_aa(packet) << 2
330                         | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet);
331                 ldns_buffer_write_u8(buffer, flags);
332                 
333                 flags = ldns_pkt_ra(packet) << 7
334                         /*| ldns_pkt_z(packet) << 6*/
335                         | ldns_pkt_ad(packet) << 5
336                         | ldns_pkt_cd(packet) << 4
337                         | ldns_pkt_get_rcode(packet);
338                 ldns_buffer_write_u8(buffer, flags);
339                 
340                 ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet));
341                 ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet));
342                 ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet));
343                 /* add EDNS0 and TSIG to additional if they are there */
344                 arcount = ldns_pkt_arcount(packet);
345                 if (ldns_pkt_tsig(packet)) {
346                         arcount++;
347                 }
348                 if (ldns_pkt_edns(packet)) {
349                         arcount++;
350                 }
351                 ldns_buffer_write_u16(buffer, arcount);
352         }
353         
354         return ldns_buffer_status(buffer);
355 }
356
357 static void
358 compression_node_free(ldns_rbnode_t *node, void *arg)
359 {
360         (void)arg; /* Yes, dear compiler, it is used */
361         ldns_rdf_deep_free((ldns_rdf *)node->key);
362         LDNS_FREE(node);
363 }
364
365 ldns_status
366 ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
367 {
368         ldns_rr_list *rr_list;
369         uint16_t i;
370
371         /* edns tmp vars */
372         ldns_rr *edns_rr;
373         uint8_t edata[4];
374
375         ldns_rbtree_t *compression_data = ldns_rbtree_create((int (*)(const void *, const void *))ldns_dname_compare);
376         
377         (void) ldns_hdr2buffer_wire(buffer, packet);
378
379         rr_list = ldns_pkt_question(packet);
380         if (rr_list) {
381                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
382                         (void) ldns_rr2buffer_wire_compress(buffer, 
383                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION, compression_data);
384                 }
385         }
386         rr_list = ldns_pkt_answer(packet);
387         if (rr_list) {
388                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
389                         (void) ldns_rr2buffer_wire_compress(buffer, 
390                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER, compression_data);
391                 }
392         }
393         rr_list = ldns_pkt_authority(packet);
394         if (rr_list) {
395                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
396                         (void) ldns_rr2buffer_wire_compress(buffer, 
397                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY, compression_data);
398                 }
399         }
400         rr_list = ldns_pkt_additional(packet);
401         if (rr_list) {
402                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
403                         (void) ldns_rr2buffer_wire_compress(buffer, 
404                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL, compression_data);
405                 }
406         }
407         
408         /* add EDNS to additional if it is needed */
409         if (ldns_pkt_edns(packet)) {
410                 edns_rr = ldns_rr_new();
411                 if(!edns_rr) return LDNS_STATUS_MEM_ERR;
412                 ldns_rr_set_owner(edns_rr,
413                                 ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "."));
414                 ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT);
415                 ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet));
416                 edata[0] = ldns_pkt_edns_extended_rcode(packet);
417                 edata[1] = ldns_pkt_edns_version(packet);
418                 ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet));
419                 ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata));
420                 /* don't forget to add the edns rdata (if any) */
421                 if (packet->_edns_data)
422                         ldns_rr_push_rdf (edns_rr, packet->_edns_data);
423                 (void)ldns_rr2buffer_wire_compress(buffer, edns_rr, LDNS_SECTION_ADDITIONAL, compression_data);
424                 /* take the edns rdata back out of the rr before we free rr */
425                 if (packet->_edns_data)
426                         (void)ldns_rr_pop_rdf (edns_rr);
427                 ldns_rr_free(edns_rr);
428         }
429         
430         /* add TSIG to additional if it is there */
431         if (ldns_pkt_tsig(packet)) {
432                 (void) ldns_rr2buffer_wire_compress(buffer,
433                                            ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL, compression_data);
434         }
435
436         ldns_traverse_postorder(compression_data,compression_node_free,NULL);
437         ldns_rbtree_free(compression_data);
438
439         return LDNS_STATUS_OK;
440 }
441
442 ldns_status
443 ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
444 {
445         ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
446         ldns_status status;
447         *result_size = 0;
448         *dest = NULL;
449         if(!buffer) return LDNS_STATUS_MEM_ERR;
450         
451         status = ldns_rdf2buffer_wire(buffer, rdf);
452         if (status == LDNS_STATUS_OK) {
453                 *result_size =  ldns_buffer_position(buffer);
454                 *dest = (uint8_t *) ldns_buffer_export(buffer);
455         }
456         ldns_buffer_free(buffer);
457         return status;
458 }
459
460 ldns_status
461 ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size)
462 {
463         ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
464         ldns_status status;
465         *result_size = 0;
466         *dest = NULL;
467         if(!buffer) return LDNS_STATUS_MEM_ERR;
468         
469         status = ldns_rr2buffer_wire(buffer, rr, section);
470         if (status == LDNS_STATUS_OK) {
471                 *result_size =  ldns_buffer_position(buffer);
472                 *dest = (uint8_t *) ldns_buffer_export(buffer);
473         }
474         ldns_buffer_free(buffer);
475         return status;
476 }
477
478 ldns_status
479 ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
480 {
481         ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
482         ldns_status status;
483         *result_size = 0;
484         *dest = NULL;
485         if(!buffer) return LDNS_STATUS_MEM_ERR;
486         
487         status = ldns_pkt2buffer_wire(buffer, packet);
488         if (status == LDNS_STATUS_OK) {
489                 *result_size =  ldns_buffer_position(buffer);
490                 *dest = (uint8_t *) ldns_buffer_export(buffer);
491         }
492         ldns_buffer_free(buffer);
493         return status;
494 }