File Coverage

src/ldns/host2wire.c
Criterion Covered Total %
statement 189 226 83.6
branch 73 116 62.9
condition n/a
subroutine n/a
pod n/a
total 262 342 76.6


line stmt bran cond sub pod time code
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
16              
17             #include
18              
19             ldns_status
20 0           ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name)
21             {
22 0           return ldns_dname2buffer_wire_compress(buffer, name, NULL);
23             }
24              
25             ldns_status
26 125           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 125 100         if(!compression_data)
37             {
38 5 50         if (ldns_buffer_reserve(buffer, ldns_rdf_size(name)))
39             {
40 5           ldns_buffer_write(buffer, ldns_rdf_data(name), ldns_rdf_size(name));
41             }
42 5           return ldns_buffer_status(buffer);
43             }
44              
45             /* No labels left, write final zero */
46 120 100         if(ldns_dname_label_count(name)==0)
47             {
48 34 50         if(ldns_buffer_reserve(buffer,1))
49             {
50 34           ldns_buffer_write_u8(buffer, 0);
51             }
52 34           return ldns_buffer_status(buffer);
53             }
54              
55             /* Can we find the name in the tree? */
56 86 100         if((node = ldns_rbtree_search(compression_data, ldns_rdf_data(name))) != NULL)
57             {
58             /* Found */
59 6           uint16_t position = (uint16_t) (intptr_t) node->data | 0xC000;
60 6 50         if (ldns_buffer_reserve(buffer, 2))
61             {
62 6           ldns_buffer_write_u16(buffer, position);
63             }
64 6           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 80           ldns_rbnode_t *node = LDNS_MALLOC(ldns_rbnode_t);
71 80 50         if(!node)
72             {
73 0           return LDNS_STATUS_MEM_ERR;
74             }
75 80 50         if (ldns_buffer_position(buffer) < 16384) {
76 80           node->key = strdup((const char *)ldns_rdf_data(name));
77 80           node->data = (void *) (intptr_t) ldns_buffer_position(buffer);
78 80           if(!ldns_rbtree_insert(compression_data,node))
79             {
80             /* fprintf(stderr,"Name not found but now it's there?\n"); */
81             }
82             }
83 80           label = ldns_dname_label(name, 0);
84 80           rest = ldns_dname_left_chop(name);
85 80           size = ldns_rdf_size(label) - 1; /* Don't want the final zero */
86 80           data = ldns_rdf_data(label);
87 80 50         if(ldns_buffer_reserve(buffer, size))
88             {
89 80           ldns_buffer_write(buffer, data, size);
90             }
91 80           ldns_rdf_deep_free(label);
92 80           s = ldns_dname2buffer_wire_compress(buffer, rest, compression_data);
93 80           ldns_rdf_deep_free(rest);
94 80           return s;
95             }
96             }
97              
98             ldns_status
99 182           ldns_rdf2buffer_wire(ldns_buffer *buffer, const ldns_rdf *rdf)
100             {
101 182           return ldns_rdf2buffer_wire_compress(buffer, rdf, NULL);
102             }
103              
104             ldns_status
105 220           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 220 100         if(compression_data && ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME)
    50          
109             {
110 3           return ldns_dname2buffer_wire_compress(buffer,rdf,compression_data);
111             }
112              
113 217 50         if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
114 217           ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf));
115             }
116 217           return ldns_buffer_status(buffer);
117             }
118              
119             ldns_status
120 76           ldns_rdf2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rdf *rdf)
121             {
122             size_t i;
123             uint8_t *rdf_data;
124              
125 76 100         if (ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME) {
126 31 50         if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
127 31           rdf_data = ldns_rdf_data(rdf);
128 347 100         for (i = 0; i < ldns_rdf_size(rdf); i++) {
129 316           ldns_buffer_write_u8(buffer,
130 316           (uint8_t) LDNS_DNAME_NORMALIZE((int)rdf_data[i]));
131             }
132             }
133             } else {
134             /* direct copy for all other types */
135 45 50         if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
136 90           ldns_buffer_write(buffer,
137 45           ldns_rdf_data(rdf),
138             ldns_rdf_size(rdf));
139             }
140             }
141 76           return ldns_buffer_status(buffer);
142             }
143              
144             /* convert a rr list to wireformat */
145             ldns_status
146 5           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 5           rr_count = ldns_rr_list_rr_count(rr_list);
152 10 100         for(i = 0; i < rr_count; i++) {
153 5           (void)ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i),
154             LDNS_SECTION_ANY);
155             }
156 5           return ldns_buffer_status(buffer);
157             }
158              
159              
160             ldns_status
161 18           ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
162             const ldns_rr *rr,
163             int section)
164             {
165             uint16_t i;
166 18           uint16_t rdl_pos = 0;
167 18           bool pre_rfc3597 = false;
168 18 100         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 6           pre_rfc3597 = true;
194 6           break;
195             default:
196 12           break;
197             }
198            
199 18 50         if (ldns_rr_owner(rr)) {
200 18           (void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr));
201             }
202            
203 18 50         if (ldns_buffer_reserve(buffer, 4)) {
204 18           (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
205 18           (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
206             }
207              
208 18 50         if (section != LDNS_SECTION_QUESTION) {
209 18 50         if (ldns_buffer_reserve(buffer, 6)) {
210 18           ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
211             /* remember pos for later */
212 18           rdl_pos = ldns_buffer_position(buffer);
213 18           ldns_buffer_write_u16(buffer, 0);
214             }
215 84 100         for (i = 0; i < ldns_rr_rd_count(rr); i++) {
216 66 100         if (pre_rfc3597) {
217 18           (void) ldns_rdf2buffer_wire_canonical(
218 18           buffer, ldns_rr_rdf(rr, i));
219             } else {
220 48           (void) ldns_rdf2buffer_wire(
221 48           buffer, ldns_rr_rdf(rr, i));
222             }
223             }
224 18 50         if (rdl_pos != 0) {
225 18           ldns_buffer_write_u16_at(buffer, rdl_pos,
226 18           ldns_buffer_position(buffer)
227             - rdl_pos - 2);
228             }
229             }
230 18           return ldns_buffer_status(buffer);
231             }
232              
233             ldns_status
234 5           ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
235             {
236 5           return ldns_rr2buffer_wire_compress(buffer,rr,section,NULL);
237             }
238              
239             ldns_status
240 42           ldns_rr2buffer_wire_compress(ldns_buffer *buffer, const ldns_rr *rr, int section, ldns_rbtree_t *compression_data)
241             {
242             uint16_t i;
243 42           uint16_t rdl_pos = 0;
244              
245 42 50         if (ldns_rr_owner(rr)) {
246 42           (void) ldns_dname2buffer_wire_compress(buffer, ldns_rr_owner(rr), compression_data);
247             }
248            
249 42 50         if (ldns_buffer_reserve(buffer, 4)) {
250 42           (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
251 42           (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
252             }
253              
254 42 100         if (section != LDNS_SECTION_QUESTION) {
255 11 50         if (ldns_buffer_reserve(buffer, 6)) {
256 11           ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
257             /* remember pos for later */
258 11           rdl_pos = ldns_buffer_position(buffer);
259 11           ldns_buffer_write_u16(buffer, 0);
260             }
261 11 100         if (LDNS_RR_COMPRESS ==
262 11           ldns_rr_descript(ldns_rr_get_type(rr))->_compress) {
263              
264 46 100         for (i = 0; i < ldns_rr_rd_count(rr); i++) {
265 38           (void) ldns_rdf2buffer_wire_compress(buffer,
266 38           ldns_rr_rdf(rr, i), compression_data);
267             }
268             } else {
269 3 50         for (i = 0; i < ldns_rr_rd_count(rr); i++) {
270 0           (void) ldns_rdf2buffer_wire(
271 0           buffer, ldns_rr_rdf(rr, i));
272             }
273             }
274 11 50         if (rdl_pos != 0) {
275 11           ldns_buffer_write_u16_at(buffer, rdl_pos,
276 11           ldns_buffer_position(buffer)
277             - rdl_pos - 2);
278             }
279             }
280 42           return ldns_buffer_status(buffer);
281             }
282              
283             ldns_status
284 5           ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
285             {
286             uint16_t i;
287              
288             /* it must be a sig RR */
289 5 50         if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
290 0           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 45 100         for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) {
296 40           (void) ldns_rdf2buffer_wire_canonical(buffer,
297 40           ldns_rr_rdf(rr, i));
298             }
299              
300 5           return ldns_buffer_status(buffer);
301             }
302              
303             ldns_status
304 29           ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
305             {
306             uint16_t i;
307              
308             /* convert all the rdf's */
309 145 100         for (i = 0; i < ldns_rr_rd_count(rr); i++) {
310 116           (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr,i));
311             }
312 29           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 31           ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
320             {
321             uint8_t flags;
322             uint16_t arcount;
323              
324 31 50         if (ldns_buffer_reserve(buffer, 12)) {
325 31           ldns_buffer_write_u16(buffer, ldns_pkt_id(packet));
326            
327 31           flags = ldns_pkt_qr(packet) << 7
328 31           | ldns_pkt_get_opcode(packet) << 3
329 31           | ldns_pkt_aa(packet) << 2
330 31           | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet);
331 31           ldns_buffer_write_u8(buffer, flags);
332            
333 31           flags = ldns_pkt_ra(packet) << 7
334             /*| ldns_pkt_z(packet) << 6*/
335 31           | ldns_pkt_ad(packet) << 5
336 31           | ldns_pkt_cd(packet) << 4
337 31           | ldns_pkt_get_rcode(packet);
338 31           ldns_buffer_write_u8(buffer, flags);
339            
340 31           ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet));
341 31           ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet));
342 31           ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet));
343             /* add EDNS0 and TSIG to additional if they are there */
344 31           arcount = ldns_pkt_arcount(packet);
345 31 50         if (ldns_pkt_tsig(packet)) {
346 0           arcount++;
347             }
348 31 100         if (ldns_pkt_edns(packet)) {
349 3           arcount++;
350             }
351 31           ldns_buffer_write_u16(buffer, arcount);
352             }
353            
354 31           return ldns_buffer_status(buffer);
355             }
356              
357             void
358 80           compression_node_free(ldns_rbnode_t *node, void *arg)
359             {
360             (void)arg; /* Yes, dear compiler, it is used */
361 80           free((void *)node->key);
362 80           LDNS_FREE(node);
363 80           }
364              
365             ldns_status
366 31           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 31           ldns_rbtree_t *compression_data = ldns_rbtree_create((int (*)(const void *, const void *))strcasecmp);
376            
377 31           (void) ldns_hdr2buffer_wire(buffer, packet);
378              
379 31           rr_list = ldns_pkt_question(packet);
380 31 50         if (rr_list) {
381 62 100         for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
382 31           (void) ldns_rr2buffer_wire_compress(buffer,
383 31           ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION, compression_data);
384             }
385             }
386 31           rr_list = ldns_pkt_answer(packet);
387 31 50         if (rr_list) {
388 34 100         for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
389 3           (void) ldns_rr2buffer_wire_compress(buffer,
390 3           ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER, compression_data);
391             }
392             }
393 31           rr_list = ldns_pkt_authority(packet);
394 31 50         if (rr_list) {
395 31 50         for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
396 0           (void) ldns_rr2buffer_wire_compress(buffer,
397 0           ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY, compression_data);
398             }
399             }
400 31           rr_list = ldns_pkt_additional(packet);
401 31 50         if (rr_list) {
402 31 50         for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
403 0           (void) ldns_rr2buffer_wire_compress(buffer,
404 0           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 31 100         if (ldns_pkt_edns(packet)) {
410 3           edns_rr = ldns_rr_new();
411 3 50         if(!edns_rr) return LDNS_STATUS_MEM_ERR;
412 3           ldns_rr_set_owner(edns_rr,
413             ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "."));
414 3           ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT);
415 3           ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet));
416 3           edata[0] = ldns_pkt_edns_extended_rcode(packet);
417 3           edata[1] = ldns_pkt_edns_version(packet);
418 3           ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet));
419 3           ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata));
420             /* don't forget to add the edns rdata (if any) */
421 3 50         if (packet->_edns_data)
422 0           ldns_rr_push_rdf (edns_rr, packet->_edns_data);
423 3           (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 3 50         if (packet->_edns_data)
426 0           (void)ldns_rr_pop_rdf (edns_rr);
427 3           ldns_rr_free(edns_rr);
428             }
429            
430             /* add TSIG to additional if it is there */
431 31 50         if (ldns_pkt_tsig(packet)) {
432 0           (void) ldns_rr2buffer_wire_compress(buffer,
433 0           ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL, compression_data);
434             }
435              
436 31           ldns_traverse_postorder(compression_data,compression_node_free,NULL);
437 31           ldns_rbtree_free(compression_data);
438              
439 31           return LDNS_STATUS_OK;
440             }
441              
442             ldns_status
443 0           ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
444             {
445 0           ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
446             ldns_status status;
447 0           *result_size = 0;
448 0           *dest = NULL;
449 0 0         if(!buffer) return LDNS_STATUS_MEM_ERR;
450            
451 0           status = ldns_rdf2buffer_wire(buffer, rdf);
452 0 0         if (status == LDNS_STATUS_OK) {
453 0           *result_size = ldns_buffer_position(buffer);
454 0           *dest = (uint8_t *) ldns_buffer_export(buffer);
455             }
456 0           ldns_buffer_free(buffer);
457 0           return status;
458             }
459              
460             ldns_status
461 0           ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size)
462             {
463 0           ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
464             ldns_status status;
465 0           *result_size = 0;
466 0           *dest = NULL;
467 0 0         if(!buffer) return LDNS_STATUS_MEM_ERR;
468            
469 0           status = ldns_rr2buffer_wire(buffer, rr, section);
470 0 0         if (status == LDNS_STATUS_OK) {
471 0           *result_size = ldns_buffer_position(buffer);
472 0           *dest = (uint8_t *) ldns_buffer_export(buffer);
473             }
474 0           ldns_buffer_free(buffer);
475 0           return status;
476             }
477              
478             ldns_status
479 3           ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
480             {
481 3           ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
482             ldns_status status;
483 3           *result_size = 0;
484 3           *dest = NULL;
485 3 50         if(!buffer) return LDNS_STATUS_MEM_ERR;
486            
487 3           status = ldns_pkt2buffer_wire(buffer, packet);
488 3 50         if (status == LDNS_STATUS_OK) {
489 3           *result_size = ldns_buffer_position(buffer);
490 3           *dest = (uint8_t *) ldns_buffer_export(buffer);
491             }
492 3           ldns_buffer_free(buffer);
493 3           return status;
494             }