xref: /freebsd/contrib/ldns/packet.c (revision 7b5038d71c5c74ab863c1ff3fec33de94bf35a57)
1*7b5038d7SDag-Erling Smørgrav /*
2*7b5038d7SDag-Erling Smørgrav  * packet.c
3*7b5038d7SDag-Erling Smørgrav  *
4*7b5038d7SDag-Erling Smørgrav  * dns packet implementation
5*7b5038d7SDag-Erling Smørgrav  *
6*7b5038d7SDag-Erling Smørgrav  * a Net::DNS like library for C
7*7b5038d7SDag-Erling Smørgrav  *
8*7b5038d7SDag-Erling Smørgrav  * (c) NLnet Labs, 2004-2006
9*7b5038d7SDag-Erling Smørgrav  *
10*7b5038d7SDag-Erling Smørgrav  * See the file LICENSE for the license
11*7b5038d7SDag-Erling Smørgrav  */
12*7b5038d7SDag-Erling Smørgrav 
13*7b5038d7SDag-Erling Smørgrav #include <ldns/config.h>
14*7b5038d7SDag-Erling Smørgrav 
15*7b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h>
16*7b5038d7SDag-Erling Smørgrav 
17*7b5038d7SDag-Erling Smørgrav #include <strings.h>
18*7b5038d7SDag-Erling Smørgrav #include <limits.h>
19*7b5038d7SDag-Erling Smørgrav 
20*7b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
21*7b5038d7SDag-Erling Smørgrav #include <openssl/rand.h>
22*7b5038d7SDag-Erling Smørgrav #endif
23*7b5038d7SDag-Erling Smørgrav 
24*7b5038d7SDag-Erling Smørgrav /* Access functions
25*7b5038d7SDag-Erling Smørgrav  * do this as functions to get type checking
26*7b5038d7SDag-Erling Smørgrav  */
27*7b5038d7SDag-Erling Smørgrav 
28*7b5038d7SDag-Erling Smørgrav #define LDNS_EDNS_MASK_DO_BIT 0x8000
29*7b5038d7SDag-Erling Smørgrav 
30*7b5038d7SDag-Erling Smørgrav /* TODO defines for 3600 */
31*7b5038d7SDag-Erling Smørgrav /* convert to and from numerical flag values */
32*7b5038d7SDag-Erling Smørgrav ldns_lookup_table ldns_edns_flags[] = {
33*7b5038d7SDag-Erling Smørgrav 	{ 3600, "do"},
34*7b5038d7SDag-Erling Smørgrav 	{ 0, NULL}
35*7b5038d7SDag-Erling Smørgrav };
36*7b5038d7SDag-Erling Smørgrav 
37*7b5038d7SDag-Erling Smørgrav /* read */
38*7b5038d7SDag-Erling Smørgrav uint16_t
39*7b5038d7SDag-Erling Smørgrav ldns_pkt_id(const ldns_pkt *packet)
40*7b5038d7SDag-Erling Smørgrav {
41*7b5038d7SDag-Erling Smørgrav 	return packet->_header->_id;
42*7b5038d7SDag-Erling Smørgrav }
43*7b5038d7SDag-Erling Smørgrav 
44*7b5038d7SDag-Erling Smørgrav bool
45*7b5038d7SDag-Erling Smørgrav ldns_pkt_qr(const ldns_pkt *packet)
46*7b5038d7SDag-Erling Smørgrav {
47*7b5038d7SDag-Erling Smørgrav 	return packet->_header->_qr;
48*7b5038d7SDag-Erling Smørgrav }
49*7b5038d7SDag-Erling Smørgrav 
50*7b5038d7SDag-Erling Smørgrav bool
51*7b5038d7SDag-Erling Smørgrav ldns_pkt_aa(const ldns_pkt *packet)
52*7b5038d7SDag-Erling Smørgrav {
53*7b5038d7SDag-Erling Smørgrav 	return packet->_header->_aa;
54*7b5038d7SDag-Erling Smørgrav }
55*7b5038d7SDag-Erling Smørgrav 
56*7b5038d7SDag-Erling Smørgrav bool
57*7b5038d7SDag-Erling Smørgrav ldns_pkt_tc(const ldns_pkt *packet)
58*7b5038d7SDag-Erling Smørgrav {
59*7b5038d7SDag-Erling Smørgrav 	return packet->_header->_tc;
60*7b5038d7SDag-Erling Smørgrav }
61*7b5038d7SDag-Erling Smørgrav 
62*7b5038d7SDag-Erling Smørgrav bool
63*7b5038d7SDag-Erling Smørgrav ldns_pkt_rd(const ldns_pkt *packet)
64*7b5038d7SDag-Erling Smørgrav {
65*7b5038d7SDag-Erling Smørgrav 	return packet->_header->_rd;
66*7b5038d7SDag-Erling Smørgrav }
67*7b5038d7SDag-Erling Smørgrav 
68*7b5038d7SDag-Erling Smørgrav bool
69*7b5038d7SDag-Erling Smørgrav ldns_pkt_cd(const ldns_pkt *packet)
70*7b5038d7SDag-Erling Smørgrav {
71*7b5038d7SDag-Erling Smørgrav 	return packet->_header->_cd;
72*7b5038d7SDag-Erling Smørgrav }
73*7b5038d7SDag-Erling Smørgrav 
74*7b5038d7SDag-Erling Smørgrav bool
75*7b5038d7SDag-Erling Smørgrav ldns_pkt_ra(const ldns_pkt *packet)
76*7b5038d7SDag-Erling Smørgrav {
77*7b5038d7SDag-Erling Smørgrav 	return packet->_header->_ra;
78*7b5038d7SDag-Erling Smørgrav }
79*7b5038d7SDag-Erling Smørgrav 
80*7b5038d7SDag-Erling Smørgrav bool
81*7b5038d7SDag-Erling Smørgrav ldns_pkt_ad(const ldns_pkt *packet)
82*7b5038d7SDag-Erling Smørgrav {
83*7b5038d7SDag-Erling Smørgrav 	return packet->_header->_ad;
84*7b5038d7SDag-Erling Smørgrav }
85*7b5038d7SDag-Erling Smørgrav 
86*7b5038d7SDag-Erling Smørgrav ldns_pkt_opcode
87*7b5038d7SDag-Erling Smørgrav ldns_pkt_get_opcode(const ldns_pkt *packet)
88*7b5038d7SDag-Erling Smørgrav {
89*7b5038d7SDag-Erling Smørgrav 	return packet->_header->_opcode;
90*7b5038d7SDag-Erling Smørgrav }
91*7b5038d7SDag-Erling Smørgrav 
92*7b5038d7SDag-Erling Smørgrav ldns_pkt_rcode
93*7b5038d7SDag-Erling Smørgrav ldns_pkt_get_rcode(const ldns_pkt *packet)
94*7b5038d7SDag-Erling Smørgrav {
95*7b5038d7SDag-Erling Smørgrav 	return packet->_header->_rcode;
96*7b5038d7SDag-Erling Smørgrav }
97*7b5038d7SDag-Erling Smørgrav 
98*7b5038d7SDag-Erling Smørgrav uint16_t
99*7b5038d7SDag-Erling Smørgrav ldns_pkt_qdcount(const ldns_pkt *packet)
100*7b5038d7SDag-Erling Smørgrav {
101*7b5038d7SDag-Erling Smørgrav 	return packet->_header->_qdcount;
102*7b5038d7SDag-Erling Smørgrav }
103*7b5038d7SDag-Erling Smørgrav 
104*7b5038d7SDag-Erling Smørgrav uint16_t
105*7b5038d7SDag-Erling Smørgrav ldns_pkt_ancount(const ldns_pkt *packet)
106*7b5038d7SDag-Erling Smørgrav {
107*7b5038d7SDag-Erling Smørgrav 	return packet->_header->_ancount;
108*7b5038d7SDag-Erling Smørgrav }
109*7b5038d7SDag-Erling Smørgrav 
110*7b5038d7SDag-Erling Smørgrav uint16_t
111*7b5038d7SDag-Erling Smørgrav ldns_pkt_nscount(const ldns_pkt *packet)
112*7b5038d7SDag-Erling Smørgrav {
113*7b5038d7SDag-Erling Smørgrav 	return packet->_header->_nscount;
114*7b5038d7SDag-Erling Smørgrav }
115*7b5038d7SDag-Erling Smørgrav 
116*7b5038d7SDag-Erling Smørgrav uint16_t
117*7b5038d7SDag-Erling Smørgrav ldns_pkt_arcount(const ldns_pkt *packet)
118*7b5038d7SDag-Erling Smørgrav {
119*7b5038d7SDag-Erling Smørgrav 	return packet->_header->_arcount;
120*7b5038d7SDag-Erling Smørgrav }
121*7b5038d7SDag-Erling Smørgrav 
122*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
123*7b5038d7SDag-Erling Smørgrav ldns_pkt_question(const ldns_pkt *packet)
124*7b5038d7SDag-Erling Smørgrav {
125*7b5038d7SDag-Erling Smørgrav 	return packet->_question;
126*7b5038d7SDag-Erling Smørgrav }
127*7b5038d7SDag-Erling Smørgrav 
128*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
129*7b5038d7SDag-Erling Smørgrav ldns_pkt_answer(const ldns_pkt *packet)
130*7b5038d7SDag-Erling Smørgrav {
131*7b5038d7SDag-Erling Smørgrav 	return packet->_answer;
132*7b5038d7SDag-Erling Smørgrav }
133*7b5038d7SDag-Erling Smørgrav 
134*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
135*7b5038d7SDag-Erling Smørgrav ldns_pkt_authority(const ldns_pkt *packet)
136*7b5038d7SDag-Erling Smørgrav {
137*7b5038d7SDag-Erling Smørgrav 	return packet->_authority;
138*7b5038d7SDag-Erling Smørgrav }
139*7b5038d7SDag-Erling Smørgrav 
140*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
141*7b5038d7SDag-Erling Smørgrav ldns_pkt_additional(const ldns_pkt *packet)
142*7b5038d7SDag-Erling Smørgrav {
143*7b5038d7SDag-Erling Smørgrav 	return packet->_additional;
144*7b5038d7SDag-Erling Smørgrav }
145*7b5038d7SDag-Erling Smørgrav 
146*7b5038d7SDag-Erling Smørgrav /* return ALL section concatenated */
147*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
148*7b5038d7SDag-Erling Smørgrav ldns_pkt_all(const ldns_pkt *packet)
149*7b5038d7SDag-Erling Smørgrav {
150*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *all, *prev_all;
151*7b5038d7SDag-Erling Smørgrav 
152*7b5038d7SDag-Erling Smørgrav 	all = ldns_rr_list_cat_clone(
153*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_question(packet),
154*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_answer(packet));
155*7b5038d7SDag-Erling Smørgrav 	prev_all = all;
156*7b5038d7SDag-Erling Smørgrav 	all = ldns_rr_list_cat_clone(all,
157*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_authority(packet));
158*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(prev_all);
159*7b5038d7SDag-Erling Smørgrav 	prev_all = all;
160*7b5038d7SDag-Erling Smørgrav 	all = ldns_rr_list_cat_clone(all,
161*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_additional(packet));
162*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(prev_all);
163*7b5038d7SDag-Erling Smørgrav 	return all;
164*7b5038d7SDag-Erling Smørgrav }
165*7b5038d7SDag-Erling Smørgrav 
166*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
167*7b5038d7SDag-Erling Smørgrav ldns_pkt_all_noquestion(const ldns_pkt *packet)
168*7b5038d7SDag-Erling Smørgrav {
169*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *all, *all2;
170*7b5038d7SDag-Erling Smørgrav 
171*7b5038d7SDag-Erling Smørgrav 	all = ldns_rr_list_cat_clone(
172*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_answer(packet),
173*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_authority(packet));
174*7b5038d7SDag-Erling Smørgrav 	all2 = ldns_rr_list_cat_clone(all,
175*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_additional(packet));
176*7b5038d7SDag-Erling Smørgrav 
177*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(all);
178*7b5038d7SDag-Erling Smørgrav 	return all2;
179*7b5038d7SDag-Erling Smørgrav }
180*7b5038d7SDag-Erling Smørgrav 
181*7b5038d7SDag-Erling Smørgrav size_t
182*7b5038d7SDag-Erling Smørgrav ldns_pkt_size(const ldns_pkt *packet)
183*7b5038d7SDag-Erling Smørgrav {
184*7b5038d7SDag-Erling Smørgrav 	return packet->_size;
185*7b5038d7SDag-Erling Smørgrav }
186*7b5038d7SDag-Erling Smørgrav 
187*7b5038d7SDag-Erling Smørgrav uint32_t
188*7b5038d7SDag-Erling Smørgrav ldns_pkt_querytime(const ldns_pkt *packet)
189*7b5038d7SDag-Erling Smørgrav {
190*7b5038d7SDag-Erling Smørgrav 	return packet->_querytime;
191*7b5038d7SDag-Erling Smørgrav }
192*7b5038d7SDag-Erling Smørgrav 
193*7b5038d7SDag-Erling Smørgrav ldns_rdf *
194*7b5038d7SDag-Erling Smørgrav ldns_pkt_answerfrom(const ldns_pkt *packet)
195*7b5038d7SDag-Erling Smørgrav {
196*7b5038d7SDag-Erling Smørgrav 	return packet->_answerfrom;
197*7b5038d7SDag-Erling Smørgrav }
198*7b5038d7SDag-Erling Smørgrav 
199*7b5038d7SDag-Erling Smørgrav struct timeval
200*7b5038d7SDag-Erling Smørgrav ldns_pkt_timestamp(const ldns_pkt *packet)
201*7b5038d7SDag-Erling Smørgrav {
202*7b5038d7SDag-Erling Smørgrav 	return packet->timestamp;
203*7b5038d7SDag-Erling Smørgrav }
204*7b5038d7SDag-Erling Smørgrav 
205*7b5038d7SDag-Erling Smørgrav uint16_t
206*7b5038d7SDag-Erling Smørgrav ldns_pkt_edns_udp_size(const ldns_pkt *packet)
207*7b5038d7SDag-Erling Smørgrav {
208*7b5038d7SDag-Erling Smørgrav 	return packet->_edns_udp_size;
209*7b5038d7SDag-Erling Smørgrav }
210*7b5038d7SDag-Erling Smørgrav 
211*7b5038d7SDag-Erling Smørgrav uint8_t
212*7b5038d7SDag-Erling Smørgrav ldns_pkt_edns_extended_rcode(const ldns_pkt *packet)
213*7b5038d7SDag-Erling Smørgrav {
214*7b5038d7SDag-Erling Smørgrav 	return packet->_edns_extended_rcode;
215*7b5038d7SDag-Erling Smørgrav }
216*7b5038d7SDag-Erling Smørgrav 
217*7b5038d7SDag-Erling Smørgrav uint8_t
218*7b5038d7SDag-Erling Smørgrav ldns_pkt_edns_version(const ldns_pkt *packet)
219*7b5038d7SDag-Erling Smørgrav {
220*7b5038d7SDag-Erling Smørgrav 	return packet->_edns_version;
221*7b5038d7SDag-Erling Smørgrav }
222*7b5038d7SDag-Erling Smørgrav 
223*7b5038d7SDag-Erling Smørgrav uint16_t
224*7b5038d7SDag-Erling Smørgrav ldns_pkt_edns_z(const ldns_pkt *packet)
225*7b5038d7SDag-Erling Smørgrav {
226*7b5038d7SDag-Erling Smørgrav 	return packet->_edns_z;
227*7b5038d7SDag-Erling Smørgrav }
228*7b5038d7SDag-Erling Smørgrav 
229*7b5038d7SDag-Erling Smørgrav bool
230*7b5038d7SDag-Erling Smørgrav ldns_pkt_edns_do(const ldns_pkt *packet)
231*7b5038d7SDag-Erling Smørgrav {
232*7b5038d7SDag-Erling Smørgrav 	return (packet->_edns_z & LDNS_EDNS_MASK_DO_BIT);
233*7b5038d7SDag-Erling Smørgrav }
234*7b5038d7SDag-Erling Smørgrav 
235*7b5038d7SDag-Erling Smørgrav void
236*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_do(ldns_pkt *packet, bool value)
237*7b5038d7SDag-Erling Smørgrav {
238*7b5038d7SDag-Erling Smørgrav 	if (value) {
239*7b5038d7SDag-Erling Smørgrav 		packet->_edns_z = packet->_edns_z | LDNS_EDNS_MASK_DO_BIT;
240*7b5038d7SDag-Erling Smørgrav 	} else {
241*7b5038d7SDag-Erling Smørgrav 		packet->_edns_z = packet->_edns_z & ~LDNS_EDNS_MASK_DO_BIT;
242*7b5038d7SDag-Erling Smørgrav 	}
243*7b5038d7SDag-Erling Smørgrav }
244*7b5038d7SDag-Erling Smørgrav 
245*7b5038d7SDag-Erling Smørgrav ldns_rdf *
246*7b5038d7SDag-Erling Smørgrav ldns_pkt_edns_data(const ldns_pkt *packet)
247*7b5038d7SDag-Erling Smørgrav {
248*7b5038d7SDag-Erling Smørgrav 	return packet->_edns_data;
249*7b5038d7SDag-Erling Smørgrav }
250*7b5038d7SDag-Erling Smørgrav 
251*7b5038d7SDag-Erling Smørgrav /* return only those rr that share the ownername */
252*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
253*7b5038d7SDag-Erling Smørgrav ldns_pkt_rr_list_by_name(ldns_pkt *packet,
254*7b5038d7SDag-Erling Smørgrav                          ldns_rdf *ownername,
255*7b5038d7SDag-Erling Smørgrav                          ldns_pkt_section sec)
256*7b5038d7SDag-Erling Smørgrav {
257*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *rrs;
258*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *new;
259*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *ret;
260*7b5038d7SDag-Erling Smørgrav 	uint16_t i;
261*7b5038d7SDag-Erling Smørgrav 
262*7b5038d7SDag-Erling Smørgrav 	if (!packet) {
263*7b5038d7SDag-Erling Smørgrav 		return NULL;
264*7b5038d7SDag-Erling Smørgrav 	}
265*7b5038d7SDag-Erling Smørgrav 
266*7b5038d7SDag-Erling Smørgrav 	rrs = ldns_pkt_get_section_clone(packet, sec);
267*7b5038d7SDag-Erling Smørgrav 	new = ldns_rr_list_new();
268*7b5038d7SDag-Erling Smørgrav 	ret = NULL;
269*7b5038d7SDag-Erling Smørgrav 
270*7b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
271*7b5038d7SDag-Erling Smørgrav 		if (ldns_rdf_compare(ldns_rr_owner(
272*7b5038d7SDag-Erling Smørgrav 						ldns_rr_list_rr(rrs, i)),
273*7b5038d7SDag-Erling Smørgrav 					ownername) == 0) {
274*7b5038d7SDag-Erling Smørgrav 			/* owner names match */
275*7b5038d7SDag-Erling Smørgrav 			ldns_rr_list_push_rr(new, ldns_rr_list_rr(rrs, i));
276*7b5038d7SDag-Erling Smørgrav 			ret = new;
277*7b5038d7SDag-Erling Smørgrav 		}
278*7b5038d7SDag-Erling Smørgrav 	}
279*7b5038d7SDag-Erling Smørgrav 	return ret;
280*7b5038d7SDag-Erling Smørgrav }
281*7b5038d7SDag-Erling Smørgrav 
282*7b5038d7SDag-Erling Smørgrav /* return only those rr that share a type */
283*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
284*7b5038d7SDag-Erling Smørgrav ldns_pkt_rr_list_by_type(const ldns_pkt *packet,
285*7b5038d7SDag-Erling Smørgrav                          ldns_rr_type type,
286*7b5038d7SDag-Erling Smørgrav                          ldns_pkt_section sec)
287*7b5038d7SDag-Erling Smørgrav {
288*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *rrs;
289*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *new;
290*7b5038d7SDag-Erling Smørgrav 	uint16_t i;
291*7b5038d7SDag-Erling Smørgrav 
292*7b5038d7SDag-Erling Smørgrav 	if(!packet) {
293*7b5038d7SDag-Erling Smørgrav 		return NULL;
294*7b5038d7SDag-Erling Smørgrav 	}
295*7b5038d7SDag-Erling Smørgrav 
296*7b5038d7SDag-Erling Smørgrav 	rrs = ldns_pkt_get_section_clone(packet, sec);
297*7b5038d7SDag-Erling Smørgrav 	new = ldns_rr_list_new();
298*7b5038d7SDag-Erling Smørgrav 
299*7b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
300*7b5038d7SDag-Erling Smørgrav 		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i))) {
301*7b5038d7SDag-Erling Smørgrav 			/* types match */
302*7b5038d7SDag-Erling Smørgrav 			ldns_rr_list_push_rr(new,
303*7b5038d7SDag-Erling Smørgrav 			                     ldns_rr_clone(
304*7b5038d7SDag-Erling Smørgrav 			                     	ldns_rr_list_rr(rrs, i))
305*7b5038d7SDag-Erling Smørgrav 					     );
306*7b5038d7SDag-Erling Smørgrav 		}
307*7b5038d7SDag-Erling Smørgrav 	}
308*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(rrs);
309*7b5038d7SDag-Erling Smørgrav 
310*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(new) == 0) {
311*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(new);
312*7b5038d7SDag-Erling Smørgrav 		return NULL;
313*7b5038d7SDag-Erling Smørgrav 	} else {
314*7b5038d7SDag-Erling Smørgrav 		return new;
315*7b5038d7SDag-Erling Smørgrav 	}
316*7b5038d7SDag-Erling Smørgrav }
317*7b5038d7SDag-Erling Smørgrav 
318*7b5038d7SDag-Erling Smørgrav /* return only those rrs that share name and type */
319*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
320*7b5038d7SDag-Erling Smørgrav ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet,
321*7b5038d7SDag-Erling Smørgrav                                   const ldns_rdf *ownername,
322*7b5038d7SDag-Erling Smørgrav                                   ldns_rr_type type,
323*7b5038d7SDag-Erling Smørgrav                                   ldns_pkt_section sec)
324*7b5038d7SDag-Erling Smørgrav {
325*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *rrs;
326*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *new;
327*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *ret;
328*7b5038d7SDag-Erling Smørgrav 	uint16_t i;
329*7b5038d7SDag-Erling Smørgrav 
330*7b5038d7SDag-Erling Smørgrav 	if(!packet) {
331*7b5038d7SDag-Erling Smørgrav 		return NULL;
332*7b5038d7SDag-Erling Smørgrav 	}
333*7b5038d7SDag-Erling Smørgrav 
334*7b5038d7SDag-Erling Smørgrav 	rrs = ldns_pkt_get_section_clone(packet, sec);
335*7b5038d7SDag-Erling Smørgrav 	new = ldns_rr_list_new();
336*7b5038d7SDag-Erling Smørgrav 	ret = NULL;
337*7b5038d7SDag-Erling Smørgrav 
338*7b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
339*7b5038d7SDag-Erling Smørgrav 		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i)) &&
340*7b5038d7SDag-Erling Smørgrav 		    ldns_rdf_compare(ldns_rr_owner(ldns_rr_list_rr(rrs, i)),
341*7b5038d7SDag-Erling Smørgrav 		                     ownername
342*7b5038d7SDag-Erling Smørgrav 		                    ) == 0
343*7b5038d7SDag-Erling Smørgrav 		   ) {
344*7b5038d7SDag-Erling Smørgrav 			/* types match */
345*7b5038d7SDag-Erling Smørgrav 			ldns_rr_list_push_rr(new, ldns_rr_clone(ldns_rr_list_rr(rrs, i)));
346*7b5038d7SDag-Erling Smørgrav 			ret = new;
347*7b5038d7SDag-Erling Smørgrav 		}
348*7b5038d7SDag-Erling Smørgrav 	}
349*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(rrs);
350*7b5038d7SDag-Erling Smørgrav 	if (!ret) {
351*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(new);
352*7b5038d7SDag-Erling Smørgrav 	}
353*7b5038d7SDag-Erling Smørgrav 	return ret;
354*7b5038d7SDag-Erling Smørgrav }
355*7b5038d7SDag-Erling Smørgrav 
356*7b5038d7SDag-Erling Smørgrav bool
357*7b5038d7SDag-Erling Smørgrav ldns_pkt_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
358*7b5038d7SDag-Erling Smørgrav {
359*7b5038d7SDag-Erling Smørgrav 	bool result = false;
360*7b5038d7SDag-Erling Smørgrav 
361*7b5038d7SDag-Erling Smørgrav 	switch (sec) {
362*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_QUESTION:
363*7b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
364*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANSWER:
365*7b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr);
366*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_AUTHORITY:
367*7b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr);
368*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ADDITIONAL:
369*7b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
370*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY:
371*7b5038d7SDag-Erling Smørgrav 		result = ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
372*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY_NOQUESTION:
373*7b5038d7SDag-Erling Smørgrav 		result = result
374*7b5038d7SDag-Erling Smørgrav 		    || ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr)
375*7b5038d7SDag-Erling Smørgrav 		    || ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr)
376*7b5038d7SDag-Erling Smørgrav 		    || ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
377*7b5038d7SDag-Erling Smørgrav 	}
378*7b5038d7SDag-Erling Smørgrav 
379*7b5038d7SDag-Erling Smørgrav 	return result;
380*7b5038d7SDag-Erling Smørgrav }
381*7b5038d7SDag-Erling Smørgrav 
382*7b5038d7SDag-Erling Smørgrav static uint16_t
383*7b5038d7SDag-Erling Smørgrav ldns_pkt_section_count(const ldns_pkt *packet, ldns_pkt_section s)
384*7b5038d7SDag-Erling Smørgrav {
385*7b5038d7SDag-Erling Smørgrav 	switch(s) {
386*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_QUESTION:
387*7b5038d7SDag-Erling Smørgrav 		return ldns_pkt_qdcount(packet);
388*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANSWER:
389*7b5038d7SDag-Erling Smørgrav 		return ldns_pkt_ancount(packet);
390*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_AUTHORITY:
391*7b5038d7SDag-Erling Smørgrav 		return ldns_pkt_nscount(packet);
392*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ADDITIONAL:
393*7b5038d7SDag-Erling Smørgrav 		return ldns_pkt_arcount(packet);
394*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY:
395*7b5038d7SDag-Erling Smørgrav 		return ldns_pkt_qdcount(packet) +
396*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_ancount(packet) +
397*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_nscount(packet) +
398*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_arcount(packet);
399*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY_NOQUESTION:
400*7b5038d7SDag-Erling Smørgrav 		return ldns_pkt_ancount(packet) +
401*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_nscount(packet) +
402*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_arcount(packet);
403*7b5038d7SDag-Erling Smørgrav 	default:
404*7b5038d7SDag-Erling Smørgrav 		return 0;
405*7b5038d7SDag-Erling Smørgrav 	}
406*7b5038d7SDag-Erling Smørgrav }
407*7b5038d7SDag-Erling Smørgrav 
408*7b5038d7SDag-Erling Smørgrav bool
409*7b5038d7SDag-Erling Smørgrav ldns_pkt_empty(ldns_pkt *p)
410*7b5038d7SDag-Erling Smørgrav {
411*7b5038d7SDag-Erling Smørgrav 	if (!p) {
412*7b5038d7SDag-Erling Smørgrav 		return true; /* NULL is empty? */
413*7b5038d7SDag-Erling Smørgrav 	}
414*7b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_section_count(p, LDNS_SECTION_ANY) > 0) {
415*7b5038d7SDag-Erling Smørgrav 		return false;
416*7b5038d7SDag-Erling Smørgrav 	} else {
417*7b5038d7SDag-Erling Smørgrav 		return true;
418*7b5038d7SDag-Erling Smørgrav     }
419*7b5038d7SDag-Erling Smørgrav }
420*7b5038d7SDag-Erling Smørgrav 
421*7b5038d7SDag-Erling Smørgrav 
422*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
423*7b5038d7SDag-Erling Smørgrav ldns_pkt_get_section_clone(const ldns_pkt *packet, ldns_pkt_section s)
424*7b5038d7SDag-Erling Smørgrav {
425*7b5038d7SDag-Erling Smørgrav 	switch(s) {
426*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_QUESTION:
427*7b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_clone(ldns_pkt_question(packet));
428*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANSWER:
429*7b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_clone(ldns_pkt_answer(packet));
430*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_AUTHORITY:
431*7b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_clone(ldns_pkt_authority(packet));
432*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ADDITIONAL:
433*7b5038d7SDag-Erling Smørgrav 		return ldns_rr_list_clone(ldns_pkt_additional(packet));
434*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY:
435*7b5038d7SDag-Erling Smørgrav 		/* these are already clones */
436*7b5038d7SDag-Erling Smørgrav 		return ldns_pkt_all(packet);
437*7b5038d7SDag-Erling Smørgrav 	case LDNS_SECTION_ANY_NOQUESTION:
438*7b5038d7SDag-Erling Smørgrav 		return ldns_pkt_all_noquestion(packet);
439*7b5038d7SDag-Erling Smørgrav 	default:
440*7b5038d7SDag-Erling Smørgrav 		return NULL;
441*7b5038d7SDag-Erling Smørgrav 	}
442*7b5038d7SDag-Erling Smørgrav }
443*7b5038d7SDag-Erling Smørgrav 
444*7b5038d7SDag-Erling Smørgrav ldns_rr *ldns_pkt_tsig(const ldns_pkt *pkt) {
445*7b5038d7SDag-Erling Smørgrav 	return pkt->_tsig_rr;
446*7b5038d7SDag-Erling Smørgrav }
447*7b5038d7SDag-Erling Smørgrav 
448*7b5038d7SDag-Erling Smørgrav /* write */
449*7b5038d7SDag-Erling Smørgrav void
450*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_id(ldns_pkt *packet, uint16_t id)
451*7b5038d7SDag-Erling Smørgrav {
452*7b5038d7SDag-Erling Smørgrav 	packet->_header->_id = id;
453*7b5038d7SDag-Erling Smørgrav }
454*7b5038d7SDag-Erling Smørgrav 
455*7b5038d7SDag-Erling Smørgrav void
456*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_random_id(ldns_pkt *packet)
457*7b5038d7SDag-Erling Smørgrav {
458*7b5038d7SDag-Erling Smørgrav 	uint16_t rid = ldns_get_random();
459*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_id(packet, rid);
460*7b5038d7SDag-Erling Smørgrav }
461*7b5038d7SDag-Erling Smørgrav 
462*7b5038d7SDag-Erling Smørgrav 
463*7b5038d7SDag-Erling Smørgrav void
464*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_qr(ldns_pkt *packet, bool qr)
465*7b5038d7SDag-Erling Smørgrav {
466*7b5038d7SDag-Erling Smørgrav 	packet->_header->_qr = qr;
467*7b5038d7SDag-Erling Smørgrav }
468*7b5038d7SDag-Erling Smørgrav 
469*7b5038d7SDag-Erling Smørgrav void
470*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_aa(ldns_pkt *packet, bool aa)
471*7b5038d7SDag-Erling Smørgrav {
472*7b5038d7SDag-Erling Smørgrav 	packet->_header->_aa = aa;
473*7b5038d7SDag-Erling Smørgrav }
474*7b5038d7SDag-Erling Smørgrav 
475*7b5038d7SDag-Erling Smørgrav void
476*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_tc(ldns_pkt *packet, bool tc)
477*7b5038d7SDag-Erling Smørgrav {
478*7b5038d7SDag-Erling Smørgrav 	packet->_header->_tc = tc;
479*7b5038d7SDag-Erling Smørgrav }
480*7b5038d7SDag-Erling Smørgrav 
481*7b5038d7SDag-Erling Smørgrav void
482*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_rd(ldns_pkt *packet, bool rd)
483*7b5038d7SDag-Erling Smørgrav {
484*7b5038d7SDag-Erling Smørgrav 	packet->_header->_rd = rd;
485*7b5038d7SDag-Erling Smørgrav }
486*7b5038d7SDag-Erling Smørgrav 
487*7b5038d7SDag-Erling Smørgrav void
488*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr)
489*7b5038d7SDag-Erling Smørgrav {
490*7b5038d7SDag-Erling Smørgrav 	p->_additional = rr;
491*7b5038d7SDag-Erling Smørgrav }
492*7b5038d7SDag-Erling Smørgrav 
493*7b5038d7SDag-Erling Smørgrav void
494*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr)
495*7b5038d7SDag-Erling Smørgrav {
496*7b5038d7SDag-Erling Smørgrav 	p->_question = rr;
497*7b5038d7SDag-Erling Smørgrav }
498*7b5038d7SDag-Erling Smørgrav 
499*7b5038d7SDag-Erling Smørgrav void
500*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr)
501*7b5038d7SDag-Erling Smørgrav {
502*7b5038d7SDag-Erling Smørgrav 	p->_answer = rr;
503*7b5038d7SDag-Erling Smørgrav }
504*7b5038d7SDag-Erling Smørgrav 
505*7b5038d7SDag-Erling Smørgrav void
506*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr)
507*7b5038d7SDag-Erling Smørgrav {
508*7b5038d7SDag-Erling Smørgrav 	p->_authority = rr;
509*7b5038d7SDag-Erling Smørgrav }
510*7b5038d7SDag-Erling Smørgrav 
511*7b5038d7SDag-Erling Smørgrav void
512*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_cd(ldns_pkt *packet, bool cd)
513*7b5038d7SDag-Erling Smørgrav {
514*7b5038d7SDag-Erling Smørgrav 	packet->_header->_cd = cd;
515*7b5038d7SDag-Erling Smørgrav }
516*7b5038d7SDag-Erling Smørgrav 
517*7b5038d7SDag-Erling Smørgrav void
518*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_ra(ldns_pkt *packet, bool ra)
519*7b5038d7SDag-Erling Smørgrav {
520*7b5038d7SDag-Erling Smørgrav 	packet->_header->_ra = ra;
521*7b5038d7SDag-Erling Smørgrav }
522*7b5038d7SDag-Erling Smørgrav 
523*7b5038d7SDag-Erling Smørgrav void
524*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_ad(ldns_pkt *packet, bool ad)
525*7b5038d7SDag-Erling Smørgrav {
526*7b5038d7SDag-Erling Smørgrav 	packet->_header->_ad = ad;
527*7b5038d7SDag-Erling Smørgrav }
528*7b5038d7SDag-Erling Smørgrav 
529*7b5038d7SDag-Erling Smørgrav void
530*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_opcode(ldns_pkt *packet, ldns_pkt_opcode opcode)
531*7b5038d7SDag-Erling Smørgrav {
532*7b5038d7SDag-Erling Smørgrav 	packet->_header->_opcode = opcode;
533*7b5038d7SDag-Erling Smørgrav }
534*7b5038d7SDag-Erling Smørgrav 
535*7b5038d7SDag-Erling Smørgrav void
536*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_rcode(ldns_pkt *packet, uint8_t rcode)
537*7b5038d7SDag-Erling Smørgrav {
538*7b5038d7SDag-Erling Smørgrav 	packet->_header->_rcode = rcode;
539*7b5038d7SDag-Erling Smørgrav }
540*7b5038d7SDag-Erling Smørgrav 
541*7b5038d7SDag-Erling Smørgrav void
542*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_qdcount(ldns_pkt *packet, uint16_t qdcount)
543*7b5038d7SDag-Erling Smørgrav {
544*7b5038d7SDag-Erling Smørgrav 	packet->_header->_qdcount = qdcount;
545*7b5038d7SDag-Erling Smørgrav }
546*7b5038d7SDag-Erling Smørgrav 
547*7b5038d7SDag-Erling Smørgrav void
548*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_ancount(ldns_pkt *packet, uint16_t ancount)
549*7b5038d7SDag-Erling Smørgrav {
550*7b5038d7SDag-Erling Smørgrav 	packet->_header->_ancount = ancount;
551*7b5038d7SDag-Erling Smørgrav }
552*7b5038d7SDag-Erling Smørgrav 
553*7b5038d7SDag-Erling Smørgrav void
554*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_nscount(ldns_pkt *packet, uint16_t nscount)
555*7b5038d7SDag-Erling Smørgrav {
556*7b5038d7SDag-Erling Smørgrav 	packet->_header->_nscount = nscount;
557*7b5038d7SDag-Erling Smørgrav }
558*7b5038d7SDag-Erling Smørgrav 
559*7b5038d7SDag-Erling Smørgrav void
560*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_arcount(ldns_pkt *packet, uint16_t arcount)
561*7b5038d7SDag-Erling Smørgrav {
562*7b5038d7SDag-Erling Smørgrav 	packet->_header->_arcount = arcount;
563*7b5038d7SDag-Erling Smørgrav }
564*7b5038d7SDag-Erling Smørgrav 
565*7b5038d7SDag-Erling Smørgrav void
566*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_querytime(ldns_pkt *packet, uint32_t time)
567*7b5038d7SDag-Erling Smørgrav {
568*7b5038d7SDag-Erling Smørgrav 	packet->_querytime = time;
569*7b5038d7SDag-Erling Smørgrav }
570*7b5038d7SDag-Erling Smørgrav 
571*7b5038d7SDag-Erling Smørgrav void
572*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_answerfrom(ldns_pkt *packet, ldns_rdf *answerfrom)
573*7b5038d7SDag-Erling Smørgrav {
574*7b5038d7SDag-Erling Smørgrav 	packet->_answerfrom = answerfrom;
575*7b5038d7SDag-Erling Smørgrav }
576*7b5038d7SDag-Erling Smørgrav 
577*7b5038d7SDag-Erling Smørgrav void
578*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_timestamp(ldns_pkt *packet, struct timeval timeval)
579*7b5038d7SDag-Erling Smørgrav {
580*7b5038d7SDag-Erling Smørgrav 	packet->timestamp.tv_sec = timeval.tv_sec;
581*7b5038d7SDag-Erling Smørgrav 	packet->timestamp.tv_usec = timeval.tv_usec;
582*7b5038d7SDag-Erling Smørgrav }
583*7b5038d7SDag-Erling Smørgrav 
584*7b5038d7SDag-Erling Smørgrav void
585*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_size(ldns_pkt *packet, size_t s)
586*7b5038d7SDag-Erling Smørgrav {
587*7b5038d7SDag-Erling Smørgrav 	packet->_size = s;
588*7b5038d7SDag-Erling Smørgrav }
589*7b5038d7SDag-Erling Smørgrav 
590*7b5038d7SDag-Erling Smørgrav void
591*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s)
592*7b5038d7SDag-Erling Smørgrav {
593*7b5038d7SDag-Erling Smørgrav 	packet->_edns_udp_size = s;
594*7b5038d7SDag-Erling Smørgrav }
595*7b5038d7SDag-Erling Smørgrav 
596*7b5038d7SDag-Erling Smørgrav void
597*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c)
598*7b5038d7SDag-Erling Smørgrav {
599*7b5038d7SDag-Erling Smørgrav 	packet->_edns_extended_rcode = c;
600*7b5038d7SDag-Erling Smørgrav }
601*7b5038d7SDag-Erling Smørgrav 
602*7b5038d7SDag-Erling Smørgrav void
603*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v)
604*7b5038d7SDag-Erling Smørgrav {
605*7b5038d7SDag-Erling Smørgrav 	packet->_edns_version = v;
606*7b5038d7SDag-Erling Smørgrav }
607*7b5038d7SDag-Erling Smørgrav 
608*7b5038d7SDag-Erling Smørgrav void
609*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z)
610*7b5038d7SDag-Erling Smørgrav {
611*7b5038d7SDag-Erling Smørgrav 	packet->_edns_z = z;
612*7b5038d7SDag-Erling Smørgrav }
613*7b5038d7SDag-Erling Smørgrav 
614*7b5038d7SDag-Erling Smørgrav void
615*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data)
616*7b5038d7SDag-Erling Smørgrav {
617*7b5038d7SDag-Erling Smørgrav 	packet->_edns_data = data;
618*7b5038d7SDag-Erling Smørgrav }
619*7b5038d7SDag-Erling Smørgrav 
620*7b5038d7SDag-Erling Smørgrav void
621*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count)
622*7b5038d7SDag-Erling Smørgrav {
623*7b5038d7SDag-Erling Smørgrav 	switch(s) {
624*7b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_QUESTION:
625*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_qdcount(packet, count);
626*7b5038d7SDag-Erling Smørgrav 			break;
627*7b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANSWER:
628*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_ancount(packet, count);
629*7b5038d7SDag-Erling Smørgrav 			break;
630*7b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_AUTHORITY:
631*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_nscount(packet, count);
632*7b5038d7SDag-Erling Smørgrav 			break;
633*7b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ADDITIONAL:
634*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_arcount(packet, count);
635*7b5038d7SDag-Erling Smørgrav 			break;
636*7b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANY:
637*7b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANY_NOQUESTION:
638*7b5038d7SDag-Erling Smørgrav 			break;
639*7b5038d7SDag-Erling Smørgrav 	}
640*7b5038d7SDag-Erling Smørgrav }
641*7b5038d7SDag-Erling Smørgrav 
642*7b5038d7SDag-Erling Smørgrav void ldns_pkt_set_tsig(ldns_pkt *pkt, ldns_rr *rr)
643*7b5038d7SDag-Erling Smørgrav {
644*7b5038d7SDag-Erling Smørgrav 	pkt->_tsig_rr = rr;
645*7b5038d7SDag-Erling Smørgrav }
646*7b5038d7SDag-Erling Smørgrav 
647*7b5038d7SDag-Erling Smørgrav bool
648*7b5038d7SDag-Erling Smørgrav ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr)
649*7b5038d7SDag-Erling Smørgrav {
650*7b5038d7SDag-Erling Smørgrav 	switch(section) {
651*7b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_QUESTION:
652*7b5038d7SDag-Erling Smørgrav 			ldns_rr_list_push_rr(ldns_pkt_question(packet), rr);
653*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_qdcount(packet, ldns_pkt_qdcount(packet) + 1);
654*7b5038d7SDag-Erling Smørgrav 			break;
655*7b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANSWER:
656*7b5038d7SDag-Erling Smørgrav 			ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr);
657*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_ancount(packet, ldns_pkt_ancount(packet) + 1);
658*7b5038d7SDag-Erling Smørgrav 			break;
659*7b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_AUTHORITY:
660*7b5038d7SDag-Erling Smørgrav 			ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr);
661*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_nscount(packet, ldns_pkt_nscount(packet) + 1);
662*7b5038d7SDag-Erling Smørgrav 			break;
663*7b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ADDITIONAL:
664*7b5038d7SDag-Erling Smørgrav 			ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr);
665*7b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + 1);
666*7b5038d7SDag-Erling Smørgrav 			break;
667*7b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANY:
668*7b5038d7SDag-Erling Smørgrav 		case LDNS_SECTION_ANY_NOQUESTION:
669*7b5038d7SDag-Erling Smørgrav 			/* shouldn't this error? */
670*7b5038d7SDag-Erling Smørgrav 			break;
671*7b5038d7SDag-Erling Smørgrav 	}
672*7b5038d7SDag-Erling Smørgrav 	return true;
673*7b5038d7SDag-Erling Smørgrav }
674*7b5038d7SDag-Erling Smørgrav 
675*7b5038d7SDag-Erling Smørgrav bool
676*7b5038d7SDag-Erling Smørgrav ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
677*7b5038d7SDag-Erling Smørgrav {
678*7b5038d7SDag-Erling Smørgrav 
679*7b5038d7SDag-Erling Smørgrav 	/* check to see if its there */
680*7b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_rr(pkt, sec, rr)) {
681*7b5038d7SDag-Erling Smørgrav 		/* already there */
682*7b5038d7SDag-Erling Smørgrav 		return false;
683*7b5038d7SDag-Erling Smørgrav 	}
684*7b5038d7SDag-Erling Smørgrav 	return ldns_pkt_push_rr(pkt, sec, rr);
685*7b5038d7SDag-Erling Smørgrav }
686*7b5038d7SDag-Erling Smørgrav 
687*7b5038d7SDag-Erling Smørgrav bool
688*7b5038d7SDag-Erling Smørgrav ldns_pkt_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
689*7b5038d7SDag-Erling Smørgrav {
690*7b5038d7SDag-Erling Smørgrav 	size_t i;
691*7b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
692*7b5038d7SDag-Erling Smørgrav 		if (!ldns_pkt_push_rr(p, s, ldns_rr_list_rr(list, i))) {
693*7b5038d7SDag-Erling Smørgrav 			return false;
694*7b5038d7SDag-Erling Smørgrav 		}
695*7b5038d7SDag-Erling Smørgrav 	}
696*7b5038d7SDag-Erling Smørgrav 	return true;
697*7b5038d7SDag-Erling Smørgrav }
698*7b5038d7SDag-Erling Smørgrav 
699*7b5038d7SDag-Erling Smørgrav bool
700*7b5038d7SDag-Erling Smørgrav ldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
701*7b5038d7SDag-Erling Smørgrav {
702*7b5038d7SDag-Erling Smørgrav 	size_t i;
703*7b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
704*7b5038d7SDag-Erling Smørgrav 		if (!ldns_pkt_safe_push_rr(p, s, ldns_rr_list_rr(list, i))) {
705*7b5038d7SDag-Erling Smørgrav 			return false;
706*7b5038d7SDag-Erling Smørgrav 		}
707*7b5038d7SDag-Erling Smørgrav 	}
708*7b5038d7SDag-Erling Smørgrav 	return true;
709*7b5038d7SDag-Erling Smørgrav }
710*7b5038d7SDag-Erling Smørgrav 
711*7b5038d7SDag-Erling Smørgrav bool
712*7b5038d7SDag-Erling Smørgrav ldns_pkt_edns(const ldns_pkt *pkt) {
713*7b5038d7SDag-Erling Smørgrav 	return (ldns_pkt_edns_udp_size(pkt) > 0 ||
714*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_edns_extended_rcode(pkt) > 0 ||
715*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_edns_data(pkt) ||
716*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_edns_do(pkt)
717*7b5038d7SDag-Erling Smørgrav 	       );
718*7b5038d7SDag-Erling Smørgrav }
719*7b5038d7SDag-Erling Smørgrav 
720*7b5038d7SDag-Erling Smørgrav 
721*7b5038d7SDag-Erling Smørgrav /* Create/destroy/convert functions
722*7b5038d7SDag-Erling Smørgrav  */
723*7b5038d7SDag-Erling Smørgrav ldns_pkt *
724*7b5038d7SDag-Erling Smørgrav ldns_pkt_new(void)
725*7b5038d7SDag-Erling Smørgrav {
726*7b5038d7SDag-Erling Smørgrav 	ldns_pkt *packet;
727*7b5038d7SDag-Erling Smørgrav 	packet = LDNS_MALLOC(ldns_pkt);
728*7b5038d7SDag-Erling Smørgrav 	if (!packet) {
729*7b5038d7SDag-Erling Smørgrav 		return NULL;
730*7b5038d7SDag-Erling Smørgrav 	}
731*7b5038d7SDag-Erling Smørgrav 
732*7b5038d7SDag-Erling Smørgrav 	packet->_header = LDNS_MALLOC(ldns_hdr);
733*7b5038d7SDag-Erling Smørgrav 	if (!packet->_header) {
734*7b5038d7SDag-Erling Smørgrav 		LDNS_FREE(packet);
735*7b5038d7SDag-Erling Smørgrav 		return NULL;
736*7b5038d7SDag-Erling Smørgrav 	}
737*7b5038d7SDag-Erling Smørgrav 
738*7b5038d7SDag-Erling Smørgrav 	packet->_question = ldns_rr_list_new();
739*7b5038d7SDag-Erling Smørgrav 	packet->_answer = ldns_rr_list_new();
740*7b5038d7SDag-Erling Smørgrav 	packet->_authority = ldns_rr_list_new();
741*7b5038d7SDag-Erling Smørgrav 	packet->_additional = ldns_rr_list_new();
742*7b5038d7SDag-Erling Smørgrav 
743*7b5038d7SDag-Erling Smørgrav 	/* default everything to false */
744*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_qr(packet, false);
745*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_aa(packet, false);
746*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_tc(packet, false);
747*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_rd(packet, false);
748*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_ra(packet, false);
749*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_ad(packet, false);
750*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_cd(packet, false);
751*7b5038d7SDag-Erling Smørgrav 
752*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_opcode(packet, LDNS_PACKET_QUERY);
753*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_rcode(packet, 0);
754*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_id(packet, 0);
755*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_size(packet, 0);
756*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_querytime(packet, 0);
757*7b5038d7SDag-Erling Smørgrav 	memset(&packet->timestamp, 0, sizeof(packet->timestamp));
758*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_answerfrom(packet, NULL);
759*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_section_count(packet, LDNS_SECTION_QUESTION, 0);
760*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_section_count(packet, LDNS_SECTION_ANSWER, 0);
761*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_section_count(packet, LDNS_SECTION_AUTHORITY, 0);
762*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_section_count(packet, LDNS_SECTION_ADDITIONAL, 0);
763*7b5038d7SDag-Erling Smørgrav 
764*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_udp_size(packet, 0);
765*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_extended_rcode(packet, 0);
766*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_version(packet, 0);
767*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_z(packet, 0);
768*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_data(packet, NULL);
769*7b5038d7SDag-Erling Smørgrav 
770*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_tsig(packet, NULL);
771*7b5038d7SDag-Erling Smørgrav 
772*7b5038d7SDag-Erling Smørgrav 	return packet;
773*7b5038d7SDag-Erling Smørgrav }
774*7b5038d7SDag-Erling Smørgrav 
775*7b5038d7SDag-Erling Smørgrav void
776*7b5038d7SDag-Erling Smørgrav ldns_pkt_free(ldns_pkt *packet)
777*7b5038d7SDag-Erling Smørgrav {
778*7b5038d7SDag-Erling Smørgrav 	if (packet) {
779*7b5038d7SDag-Erling Smørgrav 		LDNS_FREE(packet->_header);
780*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(packet->_question);
781*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(packet->_answer);
782*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(packet->_authority);
783*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(packet->_additional);
784*7b5038d7SDag-Erling Smørgrav 		ldns_rr_free(packet->_tsig_rr);
785*7b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(packet->_edns_data);
786*7b5038d7SDag-Erling Smørgrav 		LDNS_FREE(packet);
787*7b5038d7SDag-Erling Smørgrav 	}
788*7b5038d7SDag-Erling Smørgrav }
789*7b5038d7SDag-Erling Smørgrav 
790*7b5038d7SDag-Erling Smørgrav bool
791*7b5038d7SDag-Erling Smørgrav ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags)
792*7b5038d7SDag-Erling Smørgrav {
793*7b5038d7SDag-Erling Smørgrav 	if (!packet) {
794*7b5038d7SDag-Erling Smørgrav 		return false;
795*7b5038d7SDag-Erling Smørgrav 	}
796*7b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_QR) == LDNS_QR) {
797*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_qr(packet, true);
798*7b5038d7SDag-Erling Smørgrav 	}
799*7b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_AA) == LDNS_AA) {
800*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_aa(packet, true);
801*7b5038d7SDag-Erling Smørgrav 	}
802*7b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_RD) == LDNS_RD) {
803*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_rd(packet, true);
804*7b5038d7SDag-Erling Smørgrav 	}
805*7b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_TC) == LDNS_TC) {
806*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_tc(packet, true);
807*7b5038d7SDag-Erling Smørgrav 	}
808*7b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_CD) == LDNS_CD) {
809*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_cd(packet, true);
810*7b5038d7SDag-Erling Smørgrav 	}
811*7b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_RA) == LDNS_RA) {
812*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_ra(packet, true);
813*7b5038d7SDag-Erling Smørgrav 	}
814*7b5038d7SDag-Erling Smørgrav 	if ((flags & LDNS_AD) == LDNS_AD) {
815*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_ad(packet, true);
816*7b5038d7SDag-Erling Smørgrav 	}
817*7b5038d7SDag-Erling Smørgrav 	return true;
818*7b5038d7SDag-Erling Smørgrav }
819*7b5038d7SDag-Erling Smørgrav 
820*7b5038d7SDag-Erling Smørgrav ldns_status
821*7b5038d7SDag-Erling Smørgrav ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name, ldns_rr_type rr_type,
822*7b5038d7SDag-Erling Smørgrav 		ldns_rr_class rr_class, uint16_t flags)
823*7b5038d7SDag-Erling Smørgrav {
824*7b5038d7SDag-Erling Smørgrav 	ldns_pkt *packet;
825*7b5038d7SDag-Erling Smørgrav 	ldns_rr *question_rr;
826*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *name_rdf;
827*7b5038d7SDag-Erling Smørgrav 
828*7b5038d7SDag-Erling Smørgrav 	packet = ldns_pkt_new();
829*7b5038d7SDag-Erling Smørgrav 	if (!packet) {
830*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_MEM_ERR;
831*7b5038d7SDag-Erling Smørgrav 	}
832*7b5038d7SDag-Erling Smørgrav 
833*7b5038d7SDag-Erling Smørgrav 	if (!ldns_pkt_set_flags(packet, flags)) {
834*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
835*7b5038d7SDag-Erling Smørgrav 	}
836*7b5038d7SDag-Erling Smørgrav 
837*7b5038d7SDag-Erling Smørgrav 	question_rr = ldns_rr_new();
838*7b5038d7SDag-Erling Smørgrav 	if (!question_rr) {
839*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_MEM_ERR;
840*7b5038d7SDag-Erling Smørgrav 	}
841*7b5038d7SDag-Erling Smørgrav 
842*7b5038d7SDag-Erling Smørgrav 	if (rr_type == 0) {
843*7b5038d7SDag-Erling Smørgrav 		rr_type = LDNS_RR_TYPE_A;
844*7b5038d7SDag-Erling Smørgrav 	}
845*7b5038d7SDag-Erling Smørgrav 	if (rr_class == 0) {
846*7b5038d7SDag-Erling Smørgrav 		rr_class = LDNS_RR_CLASS_IN;
847*7b5038d7SDag-Erling Smørgrav 	}
848*7b5038d7SDag-Erling Smørgrav 
849*7b5038d7SDag-Erling Smørgrav 	if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
850*7b5038d7SDag-Erling Smørgrav 		ldns_rr_set_owner(question_rr, name_rdf);
851*7b5038d7SDag-Erling Smørgrav 		ldns_rr_set_type(question_rr, rr_type);
852*7b5038d7SDag-Erling Smørgrav 		ldns_rr_set_class(question_rr, rr_class);
853*7b5038d7SDag-Erling Smørgrav                 ldns_rr_set_question(question_rr, true);
854*7b5038d7SDag-Erling Smørgrav 
855*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
856*7b5038d7SDag-Erling Smørgrav 	} else {
857*7b5038d7SDag-Erling Smørgrav 		ldns_rr_free(question_rr);
858*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_free(packet);
859*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
860*7b5038d7SDag-Erling Smørgrav 	}
861*7b5038d7SDag-Erling Smørgrav 
862*7b5038d7SDag-Erling Smørgrav 	packet->_tsig_rr = NULL;
863*7b5038d7SDag-Erling Smørgrav 
864*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_answerfrom(packet, NULL);
865*7b5038d7SDag-Erling Smørgrav 	if (p) {
866*7b5038d7SDag-Erling Smørgrav 		*p = packet;
867*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_OK;
868*7b5038d7SDag-Erling Smørgrav 	} else {
869*7b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_NULL;
870*7b5038d7SDag-Erling Smørgrav 	}
871*7b5038d7SDag-Erling Smørgrav }
872*7b5038d7SDag-Erling Smørgrav 
873*7b5038d7SDag-Erling Smørgrav ldns_pkt *
874*7b5038d7SDag-Erling Smørgrav ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class,
875*7b5038d7SDag-Erling Smørgrav 		uint16_t flags)
876*7b5038d7SDag-Erling Smørgrav {
877*7b5038d7SDag-Erling Smørgrav 	ldns_pkt *packet;
878*7b5038d7SDag-Erling Smørgrav 	ldns_rr *question_rr;
879*7b5038d7SDag-Erling Smørgrav 
880*7b5038d7SDag-Erling Smørgrav 	packet = ldns_pkt_new();
881*7b5038d7SDag-Erling Smørgrav 	if (!packet) {
882*7b5038d7SDag-Erling Smørgrav 		return NULL;
883*7b5038d7SDag-Erling Smørgrav 	}
884*7b5038d7SDag-Erling Smørgrav 
885*7b5038d7SDag-Erling Smørgrav 	if (!ldns_pkt_set_flags(packet, flags)) {
886*7b5038d7SDag-Erling Smørgrav 		return NULL;
887*7b5038d7SDag-Erling Smørgrav 	}
888*7b5038d7SDag-Erling Smørgrav 
889*7b5038d7SDag-Erling Smørgrav 	question_rr = ldns_rr_new();
890*7b5038d7SDag-Erling Smørgrav 	if (!question_rr) {
891*7b5038d7SDag-Erling Smørgrav 		return NULL;
892*7b5038d7SDag-Erling Smørgrav 	}
893*7b5038d7SDag-Erling Smørgrav 
894*7b5038d7SDag-Erling Smørgrav 	if (rr_type == 0) {
895*7b5038d7SDag-Erling Smørgrav 		rr_type = LDNS_RR_TYPE_A;
896*7b5038d7SDag-Erling Smørgrav 	}
897*7b5038d7SDag-Erling Smørgrav 	if (rr_class == 0) {
898*7b5038d7SDag-Erling Smørgrav 		rr_class = LDNS_RR_CLASS_IN;
899*7b5038d7SDag-Erling Smørgrav 	}
900*7b5038d7SDag-Erling Smørgrav 
901*7b5038d7SDag-Erling Smørgrav 	ldns_rr_set_owner(question_rr, rr_name);
902*7b5038d7SDag-Erling Smørgrav 	ldns_rr_set_type(question_rr, rr_type);
903*7b5038d7SDag-Erling Smørgrav 	ldns_rr_set_class(question_rr, rr_class);
904*7b5038d7SDag-Erling Smørgrav         ldns_rr_set_question(question_rr, true);
905*7b5038d7SDag-Erling Smørgrav 
906*7b5038d7SDag-Erling Smørgrav 	packet->_tsig_rr = NULL;
907*7b5038d7SDag-Erling Smørgrav 
908*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
909*7b5038d7SDag-Erling Smørgrav 
910*7b5038d7SDag-Erling Smørgrav 	return packet;
911*7b5038d7SDag-Erling Smørgrav }
912*7b5038d7SDag-Erling Smørgrav 
913*7b5038d7SDag-Erling Smørgrav ldns_pkt_type
914*7b5038d7SDag-Erling Smørgrav ldns_pkt_reply_type(ldns_pkt *p)
915*7b5038d7SDag-Erling Smørgrav {
916*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *tmp;
917*7b5038d7SDag-Erling Smørgrav 
918*7b5038d7SDag-Erling Smørgrav 	if (!p) {
919*7b5038d7SDag-Erling Smørgrav 		return LDNS_PACKET_UNKNOWN;
920*7b5038d7SDag-Erling Smørgrav 	}
921*7b5038d7SDag-Erling Smørgrav 
922*7b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NXDOMAIN) {
923*7b5038d7SDag-Erling Smørgrav 		return LDNS_PACKET_NXDOMAIN;
924*7b5038d7SDag-Erling Smørgrav 	}
925*7b5038d7SDag-Erling Smørgrav 
926*7b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_arcount(p) == 0
927*7b5038d7SDag-Erling Smørgrav 			&& ldns_pkt_nscount(p) == 1) {
928*7b5038d7SDag-Erling Smørgrav 
929*7b5038d7SDag-Erling Smørgrav 		/* check for SOA */
930*7b5038d7SDag-Erling Smørgrav 		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_SOA,
931*7b5038d7SDag-Erling Smørgrav 					LDNS_SECTION_AUTHORITY);
932*7b5038d7SDag-Erling Smørgrav 		if (tmp) {
933*7b5038d7SDag-Erling Smørgrav 			ldns_rr_list_deep_free(tmp);
934*7b5038d7SDag-Erling Smørgrav 			return LDNS_PACKET_NODATA;
935*7b5038d7SDag-Erling Smørgrav 		} else {
936*7b5038d7SDag-Erling Smørgrav 			/* I have no idea ... */
937*7b5038d7SDag-Erling Smørgrav 		}
938*7b5038d7SDag-Erling Smørgrav 	}
939*7b5038d7SDag-Erling Smørgrav 
940*7b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_nscount(p) > 0) {
941*7b5038d7SDag-Erling Smørgrav 		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS,
942*7b5038d7SDag-Erling Smørgrav 		                               LDNS_SECTION_AUTHORITY);
943*7b5038d7SDag-Erling Smørgrav 		if (tmp) {
944*7b5038d7SDag-Erling Smørgrav 			/* there are nameservers here */
945*7b5038d7SDag-Erling Smørgrav 			ldns_rr_list_deep_free(tmp);
946*7b5038d7SDag-Erling Smørgrav 			return LDNS_PACKET_REFERRAL;
947*7b5038d7SDag-Erling Smørgrav 		} else {
948*7b5038d7SDag-Erling Smørgrav 			/* I have no idea */
949*7b5038d7SDag-Erling Smørgrav 		}
950*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_deep_free(tmp);
951*7b5038d7SDag-Erling Smørgrav 	}
952*7b5038d7SDag-Erling Smørgrav 
953*7b5038d7SDag-Erling Smørgrav 	/* if we cannot determine the packet type, we say it's an
954*7b5038d7SDag-Erling Smørgrav 	 * answer...
955*7b5038d7SDag-Erling Smørgrav 	 */
956*7b5038d7SDag-Erling Smørgrav 	return LDNS_PACKET_ANSWER;
957*7b5038d7SDag-Erling Smørgrav }
958*7b5038d7SDag-Erling Smørgrav 
959*7b5038d7SDag-Erling Smørgrav ldns_pkt *
960*7b5038d7SDag-Erling Smørgrav ldns_pkt_clone(ldns_pkt *pkt)
961*7b5038d7SDag-Erling Smørgrav {
962*7b5038d7SDag-Erling Smørgrav 	ldns_pkt *new_pkt;
963*7b5038d7SDag-Erling Smørgrav 
964*7b5038d7SDag-Erling Smørgrav 	if (!pkt) {
965*7b5038d7SDag-Erling Smørgrav 		return NULL;
966*7b5038d7SDag-Erling Smørgrav 	}
967*7b5038d7SDag-Erling Smørgrav 	new_pkt = ldns_pkt_new();
968*7b5038d7SDag-Erling Smørgrav 
969*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_id(new_pkt, ldns_pkt_id(pkt));
970*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_qr(new_pkt, ldns_pkt_qr(pkt));
971*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_aa(new_pkt, ldns_pkt_aa(pkt));
972*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_tc(new_pkt, ldns_pkt_tc(pkt));
973*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_rd(new_pkt, ldns_pkt_rd(pkt));
974*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_cd(new_pkt, ldns_pkt_cd(pkt));
975*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_ra(new_pkt, ldns_pkt_ra(pkt));
976*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_ad(new_pkt, ldns_pkt_ad(pkt));
977*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_opcode(new_pkt, ldns_pkt_get_opcode(pkt));
978*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_rcode(new_pkt, ldns_pkt_get_rcode(pkt));
979*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_qdcount(new_pkt, ldns_pkt_qdcount(pkt));
980*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_ancount(new_pkt, ldns_pkt_ancount(pkt));
981*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_nscount(new_pkt, ldns_pkt_nscount(pkt));
982*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_arcount(new_pkt, ldns_pkt_arcount(pkt));
983*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_answerfrom(new_pkt, ldns_pkt_answerfrom(pkt));
984*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_querytime(new_pkt, ldns_pkt_querytime(pkt));
985*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_size(new_pkt, ldns_pkt_size(pkt));
986*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_tsig(new_pkt, ldns_rr_clone(ldns_pkt_tsig(pkt)));
987*7b5038d7SDag-Erling Smørgrav 
988*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_udp_size(new_pkt, ldns_pkt_edns_udp_size(pkt));
989*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_extended_rcode(new_pkt,
990*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_edns_extended_rcode(pkt));
991*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_version(new_pkt, ldns_pkt_edns_version(pkt));
992*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_z(new_pkt, ldns_pkt_edns_z(pkt));
993*7b5038d7SDag-Erling Smørgrav 	if(ldns_pkt_edns_data(pkt))
994*7b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_edns_data(new_pkt,
995*7b5038d7SDag-Erling Smørgrav 			ldns_rdf_clone(ldns_pkt_edns_data(pkt)));
996*7b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt));
997*7b5038d7SDag-Erling Smørgrav 
998*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(new_pkt->_question);
999*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(new_pkt->_answer);
1000*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(new_pkt->_authority);
1001*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(new_pkt->_additional);
1002*7b5038d7SDag-Erling Smørgrav 	new_pkt->_question = ldns_rr_list_clone(ldns_pkt_question(pkt));
1003*7b5038d7SDag-Erling Smørgrav 	new_pkt->_answer = ldns_rr_list_clone(ldns_pkt_answer(pkt));
1004*7b5038d7SDag-Erling Smørgrav 	new_pkt->_authority = ldns_rr_list_clone(ldns_pkt_authority(pkt));
1005*7b5038d7SDag-Erling Smørgrav 	new_pkt->_additional = ldns_rr_list_clone(ldns_pkt_additional(pkt));
1006*7b5038d7SDag-Erling Smørgrav 	return new_pkt;
1007*7b5038d7SDag-Erling Smørgrav }
1008