xref: /freebsd/contrib/ldns/host2wire.c (revision 7b5038d71c5c74ab863c1ff3fec33de94bf35a57)
1*7b5038d7SDag-Erling Smørgrav /*
2*7b5038d7SDag-Erling Smørgrav  * host2wire.c
3*7b5038d7SDag-Erling Smørgrav  *
4*7b5038d7SDag-Erling Smørgrav  * conversion routines from the host to the wire format.
5*7b5038d7SDag-Erling Smørgrav  * This will usually just a re-ordering of the
6*7b5038d7SDag-Erling Smørgrav  * data (as we store it in network format)
7*7b5038d7SDag-Erling Smørgrav  *
8*7b5038d7SDag-Erling Smørgrav  * a Net::DNS like library for C
9*7b5038d7SDag-Erling Smørgrav  *
10*7b5038d7SDag-Erling Smørgrav  * (c) NLnet Labs, 2004-2006
11*7b5038d7SDag-Erling Smørgrav  *
12*7b5038d7SDag-Erling Smørgrav  * See the file LICENSE for the license
13*7b5038d7SDag-Erling Smørgrav  */
14*7b5038d7SDag-Erling Smørgrav 
15*7b5038d7SDag-Erling Smørgrav #include <ldns/config.h>
16*7b5038d7SDag-Erling Smørgrav 
17*7b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h>
18*7b5038d7SDag-Erling Smørgrav 
19*7b5038d7SDag-Erling Smørgrav /* TODO Jelte
20*7b5038d7SDag-Erling Smørgrav   add a pointer to a 'possiblecompression' structure
21*7b5038d7SDag-Erling Smørgrav   to all the needed functions?
22*7b5038d7SDag-Erling Smørgrav   something like an array of name, pointer values?
23*7b5038d7SDag-Erling Smørgrav   every dname part could be added to it
24*7b5038d7SDag-Erling Smørgrav */
25*7b5038d7SDag-Erling Smørgrav 
26*7b5038d7SDag-Erling Smørgrav ldns_status
27*7b5038d7SDag-Erling Smørgrav ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name)
28*7b5038d7SDag-Erling Smørgrav {
29*7b5038d7SDag-Erling Smørgrav 	if (ldns_buffer_reserve(buffer, ldns_rdf_size(name))) {
30*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_write(buffer, ldns_rdf_data(name), ldns_rdf_size(name));
31*7b5038d7SDag-Erling Smørgrav 	}
32*7b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
33*7b5038d7SDag-Erling Smørgrav }
34*7b5038d7SDag-Erling Smørgrav 
35*7b5038d7SDag-Erling Smørgrav ldns_status
36*7b5038d7SDag-Erling Smørgrav ldns_rdf2buffer_wire(ldns_buffer *buffer, const ldns_rdf *rdf)
37*7b5038d7SDag-Erling Smørgrav {
38*7b5038d7SDag-Erling Smørgrav 	if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
39*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf));
40*7b5038d7SDag-Erling Smørgrav 	}
41*7b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
42*7b5038d7SDag-Erling Smørgrav }
43*7b5038d7SDag-Erling Smørgrav 
44*7b5038d7SDag-Erling Smørgrav ldns_status
45*7b5038d7SDag-Erling Smørgrav ldns_rdf2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rdf *rdf)
46*7b5038d7SDag-Erling Smørgrav {
47*7b5038d7SDag-Erling Smørgrav 	size_t i;
48*7b5038d7SDag-Erling Smørgrav 	uint8_t *rdf_data;
49*7b5038d7SDag-Erling Smørgrav 
50*7b5038d7SDag-Erling Smørgrav 	if (ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME) {
51*7b5038d7SDag-Erling Smørgrav 		if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
52*7b5038d7SDag-Erling Smørgrav 			rdf_data = ldns_rdf_data(rdf);
53*7b5038d7SDag-Erling Smørgrav 			for (i = 0; i < ldns_rdf_size(rdf); i++) {
54*7b5038d7SDag-Erling Smørgrav 				ldns_buffer_write_u8(buffer,
55*7b5038d7SDag-Erling Smørgrav 				    (uint8_t) LDNS_DNAME_NORMALIZE((int)rdf_data[i]));
56*7b5038d7SDag-Erling Smørgrav 			}
57*7b5038d7SDag-Erling Smørgrav 		}
58*7b5038d7SDag-Erling Smørgrav 	} else {
59*7b5038d7SDag-Erling Smørgrav 		/* direct copy for all other types */
60*7b5038d7SDag-Erling Smørgrav 		if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
61*7b5038d7SDag-Erling Smørgrav 			ldns_buffer_write(buffer,
62*7b5038d7SDag-Erling Smørgrav 						   ldns_rdf_data(rdf),
63*7b5038d7SDag-Erling Smørgrav 						   ldns_rdf_size(rdf));
64*7b5038d7SDag-Erling Smørgrav 		}
65*7b5038d7SDag-Erling Smørgrav 	}
66*7b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
67*7b5038d7SDag-Erling Smørgrav }
68*7b5038d7SDag-Erling Smørgrav 
69*7b5038d7SDag-Erling Smørgrav /* convert a rr list to wireformat */
70*7b5038d7SDag-Erling Smørgrav ldns_status
71*7b5038d7SDag-Erling Smørgrav ldns_rr_list2buffer_wire(ldns_buffer *buffer,const ldns_rr_list *rr_list)
72*7b5038d7SDag-Erling Smørgrav {
73*7b5038d7SDag-Erling Smørgrav 	uint16_t rr_count;
74*7b5038d7SDag-Erling Smørgrav 	uint16_t i;
75*7b5038d7SDag-Erling Smørgrav 
76*7b5038d7SDag-Erling Smørgrav 	rr_count = ldns_rr_list_rr_count(rr_list);
77*7b5038d7SDag-Erling Smørgrav 	for(i = 0; i < rr_count; i++) {
78*7b5038d7SDag-Erling Smørgrav 		(void)ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i),
79*7b5038d7SDag-Erling Smørgrav 					  LDNS_SECTION_ANY);
80*7b5038d7SDag-Erling Smørgrav 	}
81*7b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
82*7b5038d7SDag-Erling Smørgrav }
83*7b5038d7SDag-Erling Smørgrav 
84*7b5038d7SDag-Erling Smørgrav ldns_status
85*7b5038d7SDag-Erling Smørgrav ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
86*7b5038d7SDag-Erling Smørgrav 						const ldns_rr *rr,
87*7b5038d7SDag-Erling Smørgrav 						int section)
88*7b5038d7SDag-Erling Smørgrav {
89*7b5038d7SDag-Erling Smørgrav 	uint16_t i;
90*7b5038d7SDag-Erling Smørgrav 	uint16_t rdl_pos = 0;
91*7b5038d7SDag-Erling Smørgrav 	bool pre_rfc3597 = false;
92*7b5038d7SDag-Erling Smørgrav 	switch (ldns_rr_get_type(rr)) {
93*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_NS:
94*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_MD:
95*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_MF:
96*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_CNAME:
97*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_SOA:
98*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_MB:
99*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_MG:
100*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_MR:
101*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_PTR:
102*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_HINFO:
103*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_MINFO:
104*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_MX:
105*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_RP:
106*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_AFSDB:
107*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_RT:
108*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_SIG:
109*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_PX:
110*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_NXT:
111*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_NAPTR:
112*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_KX:
113*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_SRV:
114*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_DNAME:
115*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_A6:
116*7b5038d7SDag-Erling Smørgrav 	case LDNS_RR_TYPE_RRSIG:
117*7b5038d7SDag-Erling Smørgrav 		pre_rfc3597 = true;
118*7b5038d7SDag-Erling Smørgrav 		break;
119*7b5038d7SDag-Erling Smørgrav 	default:
120*7b5038d7SDag-Erling Smørgrav 		break;
121*7b5038d7SDag-Erling Smørgrav 	}
122*7b5038d7SDag-Erling Smørgrav 
123*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_owner(rr)) {
124*7b5038d7SDag-Erling Smørgrav 		(void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr));
125*7b5038d7SDag-Erling Smørgrav 	}
126*7b5038d7SDag-Erling Smørgrav 
127*7b5038d7SDag-Erling Smørgrav 	if (ldns_buffer_reserve(buffer, 4)) {
128*7b5038d7SDag-Erling Smørgrav 		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
129*7b5038d7SDag-Erling Smørgrav 		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
130*7b5038d7SDag-Erling Smørgrav 	}
131*7b5038d7SDag-Erling Smørgrav 
132*7b5038d7SDag-Erling Smørgrav 	if (section != LDNS_SECTION_QUESTION) {
133*7b5038d7SDag-Erling Smørgrav 		if (ldns_buffer_reserve(buffer, 6)) {
134*7b5038d7SDag-Erling Smørgrav 			ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
135*7b5038d7SDag-Erling Smørgrav 			/* remember pos for later */
136*7b5038d7SDag-Erling Smørgrav 			rdl_pos = ldns_buffer_position(buffer);
137*7b5038d7SDag-Erling Smørgrav 			ldns_buffer_write_u16(buffer, 0);
138*7b5038d7SDag-Erling Smørgrav 		}
139*7b5038d7SDag-Erling Smørgrav 
140*7b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_rd_count(rr); i++) {
141*7b5038d7SDag-Erling Smørgrav 			if (pre_rfc3597) {
142*7b5038d7SDag-Erling Smørgrav 				(void) ldns_rdf2buffer_wire_canonical(
143*7b5038d7SDag-Erling Smørgrav 						buffer, ldns_rr_rdf(rr, i));
144*7b5038d7SDag-Erling Smørgrav 			} else {
145*7b5038d7SDag-Erling Smørgrav 				(void) ldns_rdf2buffer_wire(
146*7b5038d7SDag-Erling Smørgrav 						buffer, ldns_rr_rdf(rr, i));
147*7b5038d7SDag-Erling Smørgrav 			}
148*7b5038d7SDag-Erling Smørgrav 		}
149*7b5038d7SDag-Erling Smørgrav 
150*7b5038d7SDag-Erling Smørgrav 		if (rdl_pos != 0) {
151*7b5038d7SDag-Erling Smørgrav 			ldns_buffer_write_u16_at(buffer, rdl_pos,
152*7b5038d7SDag-Erling Smørgrav 			                         ldns_buffer_position(buffer)
153*7b5038d7SDag-Erling Smørgrav 		        	                   - rdl_pos - 2);
154*7b5038d7SDag-Erling Smørgrav 		}
155*7b5038d7SDag-Erling Smørgrav 	}
156*7b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
157*7b5038d7SDag-Erling Smørgrav }
158*7b5038d7SDag-Erling Smørgrav 
159*7b5038d7SDag-Erling Smørgrav ldns_status
160*7b5038d7SDag-Erling Smørgrav ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
161*7b5038d7SDag-Erling Smørgrav {
162*7b5038d7SDag-Erling Smørgrav 	uint16_t i;
163*7b5038d7SDag-Erling Smørgrav 	uint16_t rdl_pos = 0;
164*7b5038d7SDag-Erling Smørgrav 
165*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_owner(rr)) {
166*7b5038d7SDag-Erling Smørgrav 		(void) ldns_dname2buffer_wire(buffer, ldns_rr_owner(rr));
167*7b5038d7SDag-Erling Smørgrav 	}
168*7b5038d7SDag-Erling Smørgrav 
169*7b5038d7SDag-Erling Smørgrav 	if (ldns_buffer_reserve(buffer, 4)) {
170*7b5038d7SDag-Erling Smørgrav 		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
171*7b5038d7SDag-Erling Smørgrav 		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
172*7b5038d7SDag-Erling Smørgrav 	}
173*7b5038d7SDag-Erling Smørgrav 
174*7b5038d7SDag-Erling Smørgrav 	if (section != LDNS_SECTION_QUESTION) {
175*7b5038d7SDag-Erling Smørgrav 		if (ldns_buffer_reserve(buffer, 6)) {
176*7b5038d7SDag-Erling Smørgrav 			ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
177*7b5038d7SDag-Erling Smørgrav 			/* remember pos for later */
178*7b5038d7SDag-Erling Smørgrav 			rdl_pos = ldns_buffer_position(buffer);
179*7b5038d7SDag-Erling Smørgrav 			ldns_buffer_write_u16(buffer, 0);
180*7b5038d7SDag-Erling Smørgrav 		}
181*7b5038d7SDag-Erling Smørgrav 
182*7b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_rd_count(rr); i++) {
183*7b5038d7SDag-Erling Smørgrav 			(void) ldns_rdf2buffer_wire(
184*7b5038d7SDag-Erling Smørgrav 					buffer, ldns_rr_rdf(rr, i));
185*7b5038d7SDag-Erling Smørgrav 		}
186*7b5038d7SDag-Erling Smørgrav 
187*7b5038d7SDag-Erling Smørgrav 		if (rdl_pos != 0) {
188*7b5038d7SDag-Erling Smørgrav 			ldns_buffer_write_u16_at(buffer, rdl_pos,
189*7b5038d7SDag-Erling Smørgrav 			                         ldns_buffer_position(buffer)
190*7b5038d7SDag-Erling Smørgrav 		        	                   - rdl_pos - 2);
191*7b5038d7SDag-Erling Smørgrav 		}
192*7b5038d7SDag-Erling Smørgrav 	}
193*7b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
194*7b5038d7SDag-Erling Smørgrav }
195*7b5038d7SDag-Erling Smørgrav 
196*7b5038d7SDag-Erling Smørgrav ldns_status
197*7b5038d7SDag-Erling Smørgrav ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
198*7b5038d7SDag-Erling Smørgrav {
199*7b5038d7SDag-Erling Smørgrav 	uint16_t i;
200*7b5038d7SDag-Erling Smørgrav 
201*7b5038d7SDag-Erling Smørgrav 	/* it must be a sig RR */
202*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
203*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
204*7b5038d7SDag-Erling Smørgrav 	}
205*7b5038d7SDag-Erling Smørgrav 
206*7b5038d7SDag-Erling Smørgrav 	/* Convert all the rdfs, except the actual signature data
207*7b5038d7SDag-Erling Smørgrav 	 * rdf number 8  - the last, hence: -1 */
208*7b5038d7SDag-Erling Smørgrav 	for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) {
209*7b5038d7SDag-Erling Smørgrav 		(void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_rdf(rr, i));
210*7b5038d7SDag-Erling Smørgrav 	}
211*7b5038d7SDag-Erling Smørgrav 
212*7b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
213*7b5038d7SDag-Erling Smørgrav }
214*7b5038d7SDag-Erling Smørgrav 
215*7b5038d7SDag-Erling Smørgrav ldns_status
216*7b5038d7SDag-Erling Smørgrav ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
217*7b5038d7SDag-Erling Smørgrav {
218*7b5038d7SDag-Erling Smørgrav 	uint16_t i;
219*7b5038d7SDag-Erling Smørgrav 	/* convert all the rdf's */
220*7b5038d7SDag-Erling Smørgrav 	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
221*7b5038d7SDag-Erling Smørgrav 		(void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
222*7b5038d7SDag-Erling Smørgrav 	}
223*7b5038d7SDag-Erling Smørgrav 
224*7b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
225*7b5038d7SDag-Erling Smørgrav }
226*7b5038d7SDag-Erling Smørgrav 
227*7b5038d7SDag-Erling Smørgrav /*
228*7b5038d7SDag-Erling Smørgrav  * Copies the packet header data to the buffer in wire format
229*7b5038d7SDag-Erling Smørgrav  */
230*7b5038d7SDag-Erling Smørgrav static ldns_status
231*7b5038d7SDag-Erling Smørgrav ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
232*7b5038d7SDag-Erling Smørgrav {
233*7b5038d7SDag-Erling Smørgrav 	uint8_t flags;
234*7b5038d7SDag-Erling Smørgrav 	uint16_t arcount;
235*7b5038d7SDag-Erling Smørgrav 
236*7b5038d7SDag-Erling Smørgrav 	if (ldns_buffer_reserve(buffer, 12)) {
237*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_write_u16(buffer, ldns_pkt_id(packet));
238*7b5038d7SDag-Erling Smørgrav 
239*7b5038d7SDag-Erling Smørgrav 		flags = ldns_pkt_qr(packet) << 7
240*7b5038d7SDag-Erling Smørgrav 		        | ldns_pkt_get_opcode(packet) << 3
241*7b5038d7SDag-Erling Smørgrav 		        | ldns_pkt_aa(packet) << 2
242*7b5038d7SDag-Erling Smørgrav 		        | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet);
243*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_write_u8(buffer, flags);
244*7b5038d7SDag-Erling Smørgrav 
245*7b5038d7SDag-Erling Smørgrav 		flags = ldns_pkt_ra(packet) << 7
246*7b5038d7SDag-Erling Smørgrav 		        /*| ldns_pkt_z(packet) << 6*/
247*7b5038d7SDag-Erling Smørgrav 		        | ldns_pkt_ad(packet) << 5
248*7b5038d7SDag-Erling Smørgrav 		        | ldns_pkt_cd(packet) << 4 | ldns_pkt_get_rcode(packet);
249*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_write_u8(buffer, flags);
250*7b5038d7SDag-Erling Smørgrav 
251*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet));
252*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet));
253*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet));
254*7b5038d7SDag-Erling Smørgrav 		/* add EDNS0 and TSIG to additional if they are there */
255*7b5038d7SDag-Erling Smørgrav 		arcount = ldns_pkt_arcount(packet);
256*7b5038d7SDag-Erling Smørgrav 		if (ldns_pkt_tsig(packet)) {
257*7b5038d7SDag-Erling Smørgrav 			arcount++;
258*7b5038d7SDag-Erling Smørgrav 		}
259*7b5038d7SDag-Erling Smørgrav 		if (ldns_pkt_edns(packet)) {
260*7b5038d7SDag-Erling Smørgrav 			arcount++;
261*7b5038d7SDag-Erling Smørgrav 		}
262*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_write_u16(buffer, arcount);
263*7b5038d7SDag-Erling Smørgrav 	}
264*7b5038d7SDag-Erling Smørgrav 
265*7b5038d7SDag-Erling Smørgrav 	return ldns_buffer_status(buffer);
266*7b5038d7SDag-Erling Smørgrav }
267*7b5038d7SDag-Erling Smørgrav 
268*7b5038d7SDag-Erling Smørgrav ldns_status
269*7b5038d7SDag-Erling Smørgrav ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
270*7b5038d7SDag-Erling Smørgrav {
271*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *rr_list;
272*7b5038d7SDag-Erling Smørgrav 	uint16_t i;
273*7b5038d7SDag-Erling Smørgrav 
274*7b5038d7SDag-Erling Smørgrav 	/* edns tmp vars */
275*7b5038d7SDag-Erling Smørgrav 	ldns_rr *edns_rr;
276*7b5038d7SDag-Erling Smørgrav 	uint8_t edata[4];
277*7b5038d7SDag-Erling Smørgrav 
278*7b5038d7SDag-Erling Smørgrav 	(void) ldns_hdr2buffer_wire(buffer, packet);
279*7b5038d7SDag-Erling Smørgrav 
280*7b5038d7SDag-Erling Smørgrav 	rr_list = ldns_pkt_question(packet);
281*7b5038d7SDag-Erling Smørgrav 	if (rr_list) {
282*7b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
283*7b5038d7SDag-Erling Smørgrav 			(void) ldns_rr2buffer_wire(buffer,
284*7b5038d7SDag-Erling Smørgrav 			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION);
285*7b5038d7SDag-Erling Smørgrav 		}
286*7b5038d7SDag-Erling Smørgrav 	}
287*7b5038d7SDag-Erling Smørgrav 	rr_list = ldns_pkt_answer(packet);
288*7b5038d7SDag-Erling Smørgrav 	if (rr_list) {
289*7b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
290*7b5038d7SDag-Erling Smørgrav 			(void) ldns_rr2buffer_wire(buffer,
291*7b5038d7SDag-Erling Smørgrav 			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER);
292*7b5038d7SDag-Erling Smørgrav 		}
293*7b5038d7SDag-Erling Smørgrav 	}
294*7b5038d7SDag-Erling Smørgrav 	rr_list = ldns_pkt_authority(packet);
295*7b5038d7SDag-Erling Smørgrav 	if (rr_list) {
296*7b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
297*7b5038d7SDag-Erling Smørgrav 			(void) ldns_rr2buffer_wire(buffer,
298*7b5038d7SDag-Erling Smørgrav 			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY);
299*7b5038d7SDag-Erling Smørgrav 		}
300*7b5038d7SDag-Erling Smørgrav 	}
301*7b5038d7SDag-Erling Smørgrav 	rr_list = ldns_pkt_additional(packet);
302*7b5038d7SDag-Erling Smørgrav 	if (rr_list) {
303*7b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
304*7b5038d7SDag-Erling Smørgrav 			(void) ldns_rr2buffer_wire(buffer,
305*7b5038d7SDag-Erling Smørgrav 			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL);
306*7b5038d7SDag-Erling Smørgrav 		}
307*7b5038d7SDag-Erling Smørgrav 	}
308*7b5038d7SDag-Erling Smørgrav 
309*7b5038d7SDag-Erling Smørgrav 	/* add EDNS to additional if it is needed */
310*7b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_edns(packet)) {
311*7b5038d7SDag-Erling Smørgrav 		edns_rr = ldns_rr_new();
312*7b5038d7SDag-Erling Smørgrav 		if(!edns_rr) return LDNS_STATUS_MEM_ERR;
313*7b5038d7SDag-Erling Smørgrav 		ldns_rr_set_owner(edns_rr,
314*7b5038d7SDag-Erling Smørgrav 				ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "."));
315*7b5038d7SDag-Erling Smørgrav 		ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT);
316*7b5038d7SDag-Erling Smørgrav 		ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet));
317*7b5038d7SDag-Erling Smørgrav 		edata[0] = ldns_pkt_edns_extended_rcode(packet);
318*7b5038d7SDag-Erling Smørgrav 		edata[1] = ldns_pkt_edns_version(packet);
319*7b5038d7SDag-Erling Smørgrav 		ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet));
320*7b5038d7SDag-Erling Smørgrav 		ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata));
321*7b5038d7SDag-Erling Smørgrav 		/* don't forget to add the edns rdata (if any) */
322*7b5038d7SDag-Erling Smørgrav 		if (packet->_edns_data)
323*7b5038d7SDag-Erling Smørgrav 			ldns_rr_push_rdf (edns_rr, packet->_edns_data);
324*7b5038d7SDag-Erling Smørgrav 		(void)ldns_rr2buffer_wire(buffer, edns_rr, LDNS_SECTION_ADDITIONAL);
325*7b5038d7SDag-Erling Smørgrav 		/* take the edns rdata back out of the rr before we free rr */
326*7b5038d7SDag-Erling Smørgrav 		if (packet->_edns_data)
327*7b5038d7SDag-Erling Smørgrav 			(void)ldns_rr_pop_rdf (edns_rr);
328*7b5038d7SDag-Erling Smørgrav 		ldns_rr_free(edns_rr);
329*7b5038d7SDag-Erling Smørgrav 	}
330*7b5038d7SDag-Erling Smørgrav 
331*7b5038d7SDag-Erling Smørgrav 	/* add TSIG to additional if it is there */
332*7b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_tsig(packet)) {
333*7b5038d7SDag-Erling Smørgrav 		(void) ldns_rr2buffer_wire(buffer,
334*7b5038d7SDag-Erling Smørgrav 		                           ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL);
335*7b5038d7SDag-Erling Smørgrav 	}
336*7b5038d7SDag-Erling Smørgrav 
337*7b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
338*7b5038d7SDag-Erling Smørgrav }
339*7b5038d7SDag-Erling Smørgrav 
340*7b5038d7SDag-Erling Smørgrav ldns_status
341*7b5038d7SDag-Erling Smørgrav ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
342*7b5038d7SDag-Erling Smørgrav {
343*7b5038d7SDag-Erling Smørgrav 	ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
344*7b5038d7SDag-Erling Smørgrav 	uint8_t *result = NULL;
345*7b5038d7SDag-Erling Smørgrav 	ldns_status status;
346*7b5038d7SDag-Erling Smørgrav 	*result_size = 0;
347*7b5038d7SDag-Erling Smørgrav 	*dest = NULL;
348*7b5038d7SDag-Erling Smørgrav 	if(!buffer) return LDNS_STATUS_MEM_ERR;
349*7b5038d7SDag-Erling Smørgrav 
350*7b5038d7SDag-Erling Smørgrav 	status = ldns_rdf2buffer_wire(buffer, rdf);
351*7b5038d7SDag-Erling Smørgrav 	if (status == LDNS_STATUS_OK) {
352*7b5038d7SDag-Erling Smørgrav 		*result_size =  ldns_buffer_position(buffer);
353*7b5038d7SDag-Erling Smørgrav 		result = (uint8_t *) ldns_buffer_export(buffer);
354*7b5038d7SDag-Erling Smørgrav 	} else {
355*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(buffer);
356*7b5038d7SDag-Erling Smørgrav 		return status;
357*7b5038d7SDag-Erling Smørgrav 	}
358*7b5038d7SDag-Erling Smørgrav 
359*7b5038d7SDag-Erling Smørgrav 	if (result) {
360*7b5038d7SDag-Erling Smørgrav 		*dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer));
361*7b5038d7SDag-Erling Smørgrav 		if(!*dest) {
362*7b5038d7SDag-Erling Smørgrav 			ldns_buffer_free(buffer);
363*7b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_MEM_ERR;
364*7b5038d7SDag-Erling Smørgrav 		}
365*7b5038d7SDag-Erling Smørgrav 		memcpy(*dest, result, ldns_buffer_position(buffer));
366*7b5038d7SDag-Erling Smørgrav 	}
367*7b5038d7SDag-Erling Smørgrav 
368*7b5038d7SDag-Erling Smørgrav 	ldns_buffer_free(buffer);
369*7b5038d7SDag-Erling Smørgrav 	return status;
370*7b5038d7SDag-Erling Smørgrav }
371*7b5038d7SDag-Erling Smørgrav 
372*7b5038d7SDag-Erling Smørgrav ldns_status
373*7b5038d7SDag-Erling Smørgrav ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size)
374*7b5038d7SDag-Erling Smørgrav {
375*7b5038d7SDag-Erling Smørgrav 	ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
376*7b5038d7SDag-Erling Smørgrav 	uint8_t *result = NULL;
377*7b5038d7SDag-Erling Smørgrav 	ldns_status status;
378*7b5038d7SDag-Erling Smørgrav 	*result_size = 0;
379*7b5038d7SDag-Erling Smørgrav 	*dest = NULL;
380*7b5038d7SDag-Erling Smørgrav 	if(!buffer) return LDNS_STATUS_MEM_ERR;
381*7b5038d7SDag-Erling Smørgrav 
382*7b5038d7SDag-Erling Smørgrav 	status = ldns_rr2buffer_wire(buffer, rr, section);
383*7b5038d7SDag-Erling Smørgrav 	if (status == LDNS_STATUS_OK) {
384*7b5038d7SDag-Erling Smørgrav 		*result_size =  ldns_buffer_position(buffer);
385*7b5038d7SDag-Erling Smørgrav 		result = (uint8_t *) ldns_buffer_export(buffer);
386*7b5038d7SDag-Erling Smørgrav 	} else {
387*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(buffer);
388*7b5038d7SDag-Erling Smørgrav 		return status;
389*7b5038d7SDag-Erling Smørgrav 	}
390*7b5038d7SDag-Erling Smørgrav 
391*7b5038d7SDag-Erling Smørgrav 	if (result) {
392*7b5038d7SDag-Erling Smørgrav 		*dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer));
393*7b5038d7SDag-Erling Smørgrav 		if(!*dest) {
394*7b5038d7SDag-Erling Smørgrav 			ldns_buffer_free(buffer);
395*7b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_MEM_ERR;
396*7b5038d7SDag-Erling Smørgrav 		}
397*7b5038d7SDag-Erling Smørgrav 		memcpy(*dest, result, ldns_buffer_position(buffer));
398*7b5038d7SDag-Erling Smørgrav 	}
399*7b5038d7SDag-Erling Smørgrav 
400*7b5038d7SDag-Erling Smørgrav 	ldns_buffer_free(buffer);
401*7b5038d7SDag-Erling Smørgrav 	return status;
402*7b5038d7SDag-Erling Smørgrav }
403*7b5038d7SDag-Erling Smørgrav 
404*7b5038d7SDag-Erling Smørgrav ldns_status
405*7b5038d7SDag-Erling Smørgrav ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
406*7b5038d7SDag-Erling Smørgrav {
407*7b5038d7SDag-Erling Smørgrav 	ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
408*7b5038d7SDag-Erling Smørgrav 	uint8_t *result = NULL;
409*7b5038d7SDag-Erling Smørgrav 	ldns_status status;
410*7b5038d7SDag-Erling Smørgrav 	*result_size = 0;
411*7b5038d7SDag-Erling Smørgrav 	*dest = NULL;
412*7b5038d7SDag-Erling Smørgrav 	if(!buffer) return LDNS_STATUS_MEM_ERR;
413*7b5038d7SDag-Erling Smørgrav 
414*7b5038d7SDag-Erling Smørgrav 	status = ldns_pkt2buffer_wire(buffer, packet);
415*7b5038d7SDag-Erling Smørgrav 	if (status == LDNS_STATUS_OK) {
416*7b5038d7SDag-Erling Smørgrav 		*result_size =  ldns_buffer_position(buffer);
417*7b5038d7SDag-Erling Smørgrav 		result = (uint8_t *) ldns_buffer_export(buffer);
418*7b5038d7SDag-Erling Smørgrav 	} else {
419*7b5038d7SDag-Erling Smørgrav 		ldns_buffer_free(buffer);
420*7b5038d7SDag-Erling Smørgrav 		return status;
421*7b5038d7SDag-Erling Smørgrav 	}
422*7b5038d7SDag-Erling Smørgrav 
423*7b5038d7SDag-Erling Smørgrav 	if (result) {
424*7b5038d7SDag-Erling Smørgrav 		*dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer));
425*7b5038d7SDag-Erling Smørgrav 		if(!*dest) {
426*7b5038d7SDag-Erling Smørgrav 			ldns_buffer_free(buffer);
427*7b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_MEM_ERR;
428*7b5038d7SDag-Erling Smørgrav 		}
429*7b5038d7SDag-Erling Smørgrav 		memcpy(*dest, result, ldns_buffer_position(buffer));
430*7b5038d7SDag-Erling Smørgrav 	}
431*7b5038d7SDag-Erling Smørgrav 
432*7b5038d7SDag-Erling Smørgrav 	ldns_buffer_free(buffer);
433*7b5038d7SDag-Erling Smørgrav 	return status;
434*7b5038d7SDag-Erling Smørgrav }
435