]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ldns/host2wire.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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                 (void)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
85 ldns_status
86 ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
87                                                 const ldns_rr *rr,
88                                                 int section)
89 {
90         uint16_t i;
91         uint16_t rdl_pos = 0;
92         bool pre_rfc3597 = false;
93         switch (ldns_rr_get_type(rr)) {
94         case LDNS_RR_TYPE_NS:
95         case LDNS_RR_TYPE_MD:
96         case LDNS_RR_TYPE_MF:
97         case LDNS_RR_TYPE_CNAME:
98         case LDNS_RR_TYPE_SOA:
99         case LDNS_RR_TYPE_MB:
100         case LDNS_RR_TYPE_MG:
101         case LDNS_RR_TYPE_MR:
102         case LDNS_RR_TYPE_PTR:
103         case LDNS_RR_TYPE_HINFO:
104         case LDNS_RR_TYPE_MINFO:
105         case LDNS_RR_TYPE_MX:
106         case LDNS_RR_TYPE_RP:
107         case LDNS_RR_TYPE_AFSDB:
108         case LDNS_RR_TYPE_RT:
109         case LDNS_RR_TYPE_SIG:
110         case LDNS_RR_TYPE_PX:
111         case LDNS_RR_TYPE_NXT:
112         case LDNS_RR_TYPE_NAPTR:
113         case LDNS_RR_TYPE_KX:
114         case LDNS_RR_TYPE_SRV:
115         case LDNS_RR_TYPE_DNAME:
116         case LDNS_RR_TYPE_A6:
117         case LDNS_RR_TYPE_RRSIG:
118                 pre_rfc3597 = true;
119                 break;
120         default:
121                 break;
122         }
123         
124         if (ldns_rr_owner(rr)) {
125                 (void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr));
126         }
127         
128         if (ldns_buffer_reserve(buffer, 4)) {
129                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
130                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
131         }
132
133         if (section != LDNS_SECTION_QUESTION) {
134                 if (ldns_buffer_reserve(buffer, 6)) {
135                         ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
136                         /* remember pos for later */
137                         rdl_pos = ldns_buffer_position(buffer);
138                         ldns_buffer_write_u16(buffer, 0);
139                 }       
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));
147                         }
148                 }
149                 if (rdl_pos != 0) {
150                         ldns_buffer_write_u16_at(buffer, rdl_pos,
151                                                  ldns_buffer_position(buffer)
152                                                    - rdl_pos - 2);
153                 }
154         }
155         return ldns_buffer_status(buffer);
156 }
157
158 ldns_status
159 ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
160 {
161         uint16_t i;
162         uint16_t rdl_pos = 0;
163         
164         if (ldns_rr_owner(rr)) {
165                 (void) ldns_dname2buffer_wire(buffer, ldns_rr_owner(rr));
166         }
167         
168         if (ldns_buffer_reserve(buffer, 4)) {
169                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
170                 (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
171         }
172
173         if (section != LDNS_SECTION_QUESTION) {
174                 if (ldns_buffer_reserve(buffer, 6)) {
175                         ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
176                         /* remember pos for later */
177                         rdl_pos = ldns_buffer_position(buffer);
178                         ldns_buffer_write_u16(buffer, 0);
179                 }
180                 for (i = 0; i < ldns_rr_rd_count(rr); i++) {
181                         (void) ldns_rdf2buffer_wire(
182                                         buffer, ldns_rr_rdf(rr, i));
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                 (void) ldns_rdf2buffer_wire_canonical(buffer, 
207                                 ldns_rr_rdf(rr, i));
208         }
209
210         return ldns_buffer_status(buffer);
211 }
212
213 ldns_status
214 ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
215 {
216         uint16_t i;
217         /* convert all the rdf's */
218         for (i = 0; i < ldns_rr_rd_count(rr); i++) {
219                 (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr,i));
220         }
221         return ldns_buffer_status(buffer);
222 }
223
224 /*
225  * Copies the packet header data to the buffer in wire format
226  */
227 static ldns_status
228 ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
229 {
230         uint8_t flags;
231         uint16_t arcount;
232         
233         if (ldns_buffer_reserve(buffer, 12)) {
234                 ldns_buffer_write_u16(buffer, ldns_pkt_id(packet));
235                 
236                 flags = ldns_pkt_qr(packet) << 7
237                         | ldns_pkt_get_opcode(packet) << 3
238                         | ldns_pkt_aa(packet) << 2
239                         | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet);
240                 ldns_buffer_write_u8(buffer, flags);
241                 
242                 flags = ldns_pkt_ra(packet) << 7
243                         /*| ldns_pkt_z(packet) << 6*/
244                         | ldns_pkt_ad(packet) << 5
245                         | ldns_pkt_cd(packet) << 4
246                         | ldns_pkt_get_rcode(packet);
247                 ldns_buffer_write_u8(buffer, flags);
248                 
249                 ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet));
250                 ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet));
251                 ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet));
252                 /* add EDNS0 and TSIG to additional if they are there */
253                 arcount = ldns_pkt_arcount(packet);
254                 if (ldns_pkt_tsig(packet)) {
255                         arcount++;
256                 }
257                 if (ldns_pkt_edns(packet)) {
258                         arcount++;
259                 }
260                 ldns_buffer_write_u16(buffer, arcount);
261         }
262         
263         return ldns_buffer_status(buffer);
264 }
265
266 ldns_status
267 ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
268 {
269         ldns_rr_list *rr_list;
270         uint16_t i;
271         
272         /* edns tmp vars */
273         ldns_rr *edns_rr;
274         uint8_t edata[4];
275         
276         (void) ldns_hdr2buffer_wire(buffer, packet);
277
278         rr_list = ldns_pkt_question(packet);
279         if (rr_list) {
280                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
281                         (void) ldns_rr2buffer_wire(buffer, 
282                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION);
283                 }
284         }
285         rr_list = ldns_pkt_answer(packet);
286         if (rr_list) {
287                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
288                         (void) ldns_rr2buffer_wire(buffer, 
289                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER);
290                 }
291         }
292         rr_list = ldns_pkt_authority(packet);
293         if (rr_list) {
294                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
295                         (void) ldns_rr2buffer_wire(buffer, 
296                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY);
297                 }
298         }
299         rr_list = ldns_pkt_additional(packet);
300         if (rr_list) {
301                 for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
302                         (void) ldns_rr2buffer_wire(buffer, 
303                                      ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL);
304                 }
305         }
306         
307         /* add EDNS to additional if it is needed */
308         if (ldns_pkt_edns(packet)) {
309                 edns_rr = ldns_rr_new();
310                 if(!edns_rr) return LDNS_STATUS_MEM_ERR;
311                 ldns_rr_set_owner(edns_rr,
312                                 ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "."));
313                 ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT);
314                 ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet));
315                 edata[0] = ldns_pkt_edns_extended_rcode(packet);
316                 edata[1] = ldns_pkt_edns_version(packet);
317                 ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet));
318                 ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata));
319                 /* don't forget to add the edns rdata (if any) */
320                 if (packet->_edns_data)
321                         ldns_rr_push_rdf (edns_rr, packet->_edns_data);
322                 (void)ldns_rr2buffer_wire(buffer, edns_rr, LDNS_SECTION_ADDITIONAL);
323                 /* take the edns rdata back out of the rr before we free rr */
324                 if (packet->_edns_data)
325                         (void)ldns_rr_pop_rdf (edns_rr);
326                 ldns_rr_free(edns_rr);
327         }
328         
329         /* add TSIG to additional if it is there */
330         if (ldns_pkt_tsig(packet)) {
331                 (void) ldns_rr2buffer_wire(buffer,
332                                            ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL);
333         }
334         
335         return LDNS_STATUS_OK;
336 }
337
338 ldns_status
339 ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
340 {
341         ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
342         ldns_status status;
343         *result_size = 0;
344         *dest = NULL;
345         if(!buffer) return LDNS_STATUS_MEM_ERR;
346         
347         status = ldns_rdf2buffer_wire(buffer, rdf);
348         if (status == LDNS_STATUS_OK) {
349                 *result_size =  ldns_buffer_position(buffer);
350                 *dest = (uint8_t *) ldns_buffer_export(buffer);
351         }
352         ldns_buffer_free(buffer);
353         return status;
354 }
355
356 ldns_status
357 ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size)
358 {
359         ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
360         ldns_status status;
361         *result_size = 0;
362         *dest = NULL;
363         if(!buffer) return LDNS_STATUS_MEM_ERR;
364         
365         status = ldns_rr2buffer_wire(buffer, rr, section);
366         if (status == LDNS_STATUS_OK) {
367                 *result_size =  ldns_buffer_position(buffer);
368                 *dest = (uint8_t *) ldns_buffer_export(buffer);
369         }
370         ldns_buffer_free(buffer);
371         return status;
372 }
373
374 ldns_status
375 ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
376 {
377         ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
378         ldns_status status;
379         *result_size = 0;
380         *dest = NULL;
381         if(!buffer) return LDNS_STATUS_MEM_ERR;
382         
383         status = ldns_pkt2buffer_wire(buffer, packet);
384         if (status == LDNS_STATUS_OK) {
385                 *result_size =  ldns_buffer_position(buffer);
386                 *dest = (uint8_t *) ldns_buffer_export(buffer);
387         }
388         ldns_buffer_free(buffer);
389         return status;
390 }