xref: /dflybsd-src/contrib/ldns/packet.c (revision 7733acb50455a11cc2ee36edd926ff0fa3361e9a)
1825eb42bSJan Lentfer /*
2825eb42bSJan Lentfer  * packet.c
3825eb42bSJan Lentfer  *
4825eb42bSJan Lentfer  * dns packet implementation
5825eb42bSJan Lentfer  *
6825eb42bSJan Lentfer  * a Net::DNS like library for C
7825eb42bSJan Lentfer  *
8825eb42bSJan Lentfer  * (c) NLnet Labs, 2004-2006
9825eb42bSJan Lentfer  *
10825eb42bSJan Lentfer  * See the file LICENSE for the license
11825eb42bSJan Lentfer  */
12825eb42bSJan Lentfer 
13825eb42bSJan Lentfer #include <ldns/config.h>
14825eb42bSJan Lentfer 
15825eb42bSJan Lentfer #include <ldns/ldns.h>
16825eb42bSJan Lentfer 
17825eb42bSJan Lentfer #include <strings.h>
18825eb42bSJan Lentfer #include <limits.h>
19825eb42bSJan Lentfer 
20825eb42bSJan Lentfer #ifdef HAVE_SSL
21825eb42bSJan Lentfer #include <openssl/rand.h>
22825eb42bSJan Lentfer #endif
23825eb42bSJan Lentfer 
24825eb42bSJan Lentfer /* Access functions
25825eb42bSJan Lentfer  * do this as functions to get type checking
26825eb42bSJan Lentfer  */
27825eb42bSJan Lentfer 
28825eb42bSJan Lentfer #define LDNS_EDNS_MASK_DO_BIT 0x8000
29819dec71SDaniel Fojt #define LDNS_EDNS_MASK_UNASSIGNED (0xFFFF & ~LDNS_EDNS_MASK_DO_BIT)
30825eb42bSJan Lentfer 
31825eb42bSJan Lentfer /* TODO defines for 3600 */
32825eb42bSJan Lentfer /* convert to and from numerical flag values */
33825eb42bSJan Lentfer ldns_lookup_table ldns_edns_flags[] = {
34825eb42bSJan Lentfer 	{ 3600, "do"},
35825eb42bSJan Lentfer 	{ 0, NULL}
36825eb42bSJan Lentfer };
37825eb42bSJan Lentfer 
38825eb42bSJan Lentfer /* read */
39825eb42bSJan Lentfer uint16_t
ldns_pkt_id(const ldns_pkt * packet)40825eb42bSJan Lentfer ldns_pkt_id(const ldns_pkt *packet)
41825eb42bSJan Lentfer {
42825eb42bSJan Lentfer 	return packet->_header->_id;
43825eb42bSJan Lentfer }
44825eb42bSJan Lentfer 
45825eb42bSJan Lentfer bool
ldns_pkt_qr(const ldns_pkt * packet)46825eb42bSJan Lentfer ldns_pkt_qr(const ldns_pkt *packet)
47825eb42bSJan Lentfer {
48825eb42bSJan Lentfer 	return packet->_header->_qr;
49825eb42bSJan Lentfer }
50825eb42bSJan Lentfer 
51825eb42bSJan Lentfer bool
ldns_pkt_aa(const ldns_pkt * packet)52825eb42bSJan Lentfer ldns_pkt_aa(const ldns_pkt *packet)
53825eb42bSJan Lentfer {
54825eb42bSJan Lentfer 	return packet->_header->_aa;
55825eb42bSJan Lentfer }
56825eb42bSJan Lentfer 
57825eb42bSJan Lentfer bool
ldns_pkt_tc(const ldns_pkt * packet)58825eb42bSJan Lentfer ldns_pkt_tc(const ldns_pkt *packet)
59825eb42bSJan Lentfer {
60825eb42bSJan Lentfer 	return packet->_header->_tc;
61825eb42bSJan Lentfer }
62825eb42bSJan Lentfer 
63825eb42bSJan Lentfer bool
ldns_pkt_rd(const ldns_pkt * packet)64825eb42bSJan Lentfer ldns_pkt_rd(const ldns_pkt *packet)
65825eb42bSJan Lentfer {
66825eb42bSJan Lentfer 	return packet->_header->_rd;
67825eb42bSJan Lentfer }
68825eb42bSJan Lentfer 
69825eb42bSJan Lentfer bool
ldns_pkt_cd(const ldns_pkt * packet)70825eb42bSJan Lentfer ldns_pkt_cd(const ldns_pkt *packet)
71825eb42bSJan Lentfer {
72825eb42bSJan Lentfer 	return packet->_header->_cd;
73825eb42bSJan Lentfer }
74825eb42bSJan Lentfer 
75825eb42bSJan Lentfer bool
ldns_pkt_ra(const ldns_pkt * packet)76825eb42bSJan Lentfer ldns_pkt_ra(const ldns_pkt *packet)
77825eb42bSJan Lentfer {
78825eb42bSJan Lentfer 	return packet->_header->_ra;
79825eb42bSJan Lentfer }
80825eb42bSJan Lentfer 
81825eb42bSJan Lentfer bool
ldns_pkt_ad(const ldns_pkt * packet)82825eb42bSJan Lentfer ldns_pkt_ad(const ldns_pkt *packet)
83825eb42bSJan Lentfer {
84825eb42bSJan Lentfer 	return packet->_header->_ad;
85825eb42bSJan Lentfer }
86825eb42bSJan Lentfer 
87825eb42bSJan Lentfer ldns_pkt_opcode
ldns_pkt_get_opcode(const ldns_pkt * packet)88825eb42bSJan Lentfer ldns_pkt_get_opcode(const ldns_pkt *packet)
89825eb42bSJan Lentfer {
90825eb42bSJan Lentfer 	return packet->_header->_opcode;
91825eb42bSJan Lentfer }
92825eb42bSJan Lentfer 
93825eb42bSJan Lentfer ldns_pkt_rcode
ldns_pkt_get_rcode(const ldns_pkt * packet)94825eb42bSJan Lentfer ldns_pkt_get_rcode(const ldns_pkt *packet)
95825eb42bSJan Lentfer {
96825eb42bSJan Lentfer 	return packet->_header->_rcode;
97825eb42bSJan Lentfer }
98825eb42bSJan Lentfer 
99825eb42bSJan Lentfer uint16_t
ldns_pkt_qdcount(const ldns_pkt * packet)100825eb42bSJan Lentfer ldns_pkt_qdcount(const ldns_pkt *packet)
101825eb42bSJan Lentfer {
102825eb42bSJan Lentfer 	return packet->_header->_qdcount;
103825eb42bSJan Lentfer }
104825eb42bSJan Lentfer 
105825eb42bSJan Lentfer uint16_t
ldns_pkt_ancount(const ldns_pkt * packet)106825eb42bSJan Lentfer ldns_pkt_ancount(const ldns_pkt *packet)
107825eb42bSJan Lentfer {
108825eb42bSJan Lentfer 	return packet->_header->_ancount;
109825eb42bSJan Lentfer }
110825eb42bSJan Lentfer 
111825eb42bSJan Lentfer uint16_t
ldns_pkt_nscount(const ldns_pkt * packet)112825eb42bSJan Lentfer ldns_pkt_nscount(const ldns_pkt *packet)
113825eb42bSJan Lentfer {
114825eb42bSJan Lentfer 	return packet->_header->_nscount;
115825eb42bSJan Lentfer }
116825eb42bSJan Lentfer 
117825eb42bSJan Lentfer uint16_t
ldns_pkt_arcount(const ldns_pkt * packet)118825eb42bSJan Lentfer ldns_pkt_arcount(const ldns_pkt *packet)
119825eb42bSJan Lentfer {
120825eb42bSJan Lentfer 	return packet->_header->_arcount;
121825eb42bSJan Lentfer }
122825eb42bSJan Lentfer 
123825eb42bSJan Lentfer ldns_rr_list *
ldns_pkt_question(const ldns_pkt * packet)124825eb42bSJan Lentfer ldns_pkt_question(const ldns_pkt *packet)
125825eb42bSJan Lentfer {
126825eb42bSJan Lentfer 	return packet->_question;
127825eb42bSJan Lentfer }
128825eb42bSJan Lentfer 
129825eb42bSJan Lentfer ldns_rr_list *
ldns_pkt_answer(const ldns_pkt * packet)130825eb42bSJan Lentfer ldns_pkt_answer(const ldns_pkt *packet)
131825eb42bSJan Lentfer {
132825eb42bSJan Lentfer 	return packet->_answer;
133825eb42bSJan Lentfer }
134825eb42bSJan Lentfer 
135825eb42bSJan Lentfer ldns_rr_list *
ldns_pkt_authority(const ldns_pkt * packet)136825eb42bSJan Lentfer ldns_pkt_authority(const ldns_pkt *packet)
137825eb42bSJan Lentfer {
138825eb42bSJan Lentfer 	return packet->_authority;
139825eb42bSJan Lentfer }
140825eb42bSJan Lentfer 
141825eb42bSJan Lentfer ldns_rr_list *
ldns_pkt_additional(const ldns_pkt * packet)142825eb42bSJan Lentfer ldns_pkt_additional(const ldns_pkt *packet)
143825eb42bSJan Lentfer {
144825eb42bSJan Lentfer 	return packet->_additional;
145825eb42bSJan Lentfer }
146825eb42bSJan Lentfer 
147825eb42bSJan Lentfer /* return ALL section concatenated */
148825eb42bSJan Lentfer ldns_rr_list *
ldns_pkt_all(const ldns_pkt * packet)149825eb42bSJan Lentfer ldns_pkt_all(const ldns_pkt *packet)
150825eb42bSJan Lentfer {
151825eb42bSJan Lentfer 	ldns_rr_list *all, *prev_all;
152825eb42bSJan Lentfer 
153825eb42bSJan Lentfer 	all = ldns_rr_list_cat_clone(
154825eb42bSJan Lentfer 			ldns_pkt_question(packet),
155825eb42bSJan Lentfer 			ldns_pkt_answer(packet));
156825eb42bSJan Lentfer 	prev_all = all;
157825eb42bSJan Lentfer 	all = ldns_rr_list_cat_clone(all,
158825eb42bSJan Lentfer 			ldns_pkt_authority(packet));
159825eb42bSJan Lentfer 	ldns_rr_list_deep_free(prev_all);
160825eb42bSJan Lentfer 	prev_all = all;
161825eb42bSJan Lentfer 	all = ldns_rr_list_cat_clone(all,
162825eb42bSJan Lentfer 			ldns_pkt_additional(packet));
163825eb42bSJan Lentfer 	ldns_rr_list_deep_free(prev_all);
164825eb42bSJan Lentfer 	return all;
165825eb42bSJan Lentfer }
166825eb42bSJan Lentfer 
167825eb42bSJan Lentfer ldns_rr_list *
ldns_pkt_all_noquestion(const ldns_pkt * packet)168825eb42bSJan Lentfer ldns_pkt_all_noquestion(const ldns_pkt *packet)
169825eb42bSJan Lentfer {
170825eb42bSJan Lentfer 	ldns_rr_list *all, *all2;
171825eb42bSJan Lentfer 
172825eb42bSJan Lentfer 	all = ldns_rr_list_cat_clone(
173825eb42bSJan Lentfer 			ldns_pkt_answer(packet),
174825eb42bSJan Lentfer 			ldns_pkt_authority(packet));
175825eb42bSJan Lentfer 	all2 = ldns_rr_list_cat_clone(all,
176825eb42bSJan Lentfer 			ldns_pkt_additional(packet));
177825eb42bSJan Lentfer 
178825eb42bSJan Lentfer 	ldns_rr_list_deep_free(all);
179825eb42bSJan Lentfer 	return all2;
180825eb42bSJan Lentfer }
181825eb42bSJan Lentfer 
182825eb42bSJan Lentfer size_t
ldns_pkt_size(const ldns_pkt * packet)183825eb42bSJan Lentfer ldns_pkt_size(const ldns_pkt *packet)
184825eb42bSJan Lentfer {
185825eb42bSJan Lentfer 	return packet->_size;
186825eb42bSJan Lentfer }
187825eb42bSJan Lentfer 
188825eb42bSJan Lentfer uint32_t
ldns_pkt_querytime(const ldns_pkt * packet)189825eb42bSJan Lentfer ldns_pkt_querytime(const ldns_pkt *packet)
190825eb42bSJan Lentfer {
191825eb42bSJan Lentfer 	return packet->_querytime;
192825eb42bSJan Lentfer }
193825eb42bSJan Lentfer 
194825eb42bSJan Lentfer ldns_rdf *
ldns_pkt_answerfrom(const ldns_pkt * packet)195825eb42bSJan Lentfer ldns_pkt_answerfrom(const ldns_pkt *packet)
196825eb42bSJan Lentfer {
197825eb42bSJan Lentfer 	return packet->_answerfrom;
198825eb42bSJan Lentfer }
199825eb42bSJan Lentfer 
200825eb42bSJan Lentfer struct timeval
ldns_pkt_timestamp(const ldns_pkt * packet)201825eb42bSJan Lentfer ldns_pkt_timestamp(const ldns_pkt *packet)
202825eb42bSJan Lentfer {
203825eb42bSJan Lentfer 	return packet->timestamp;
204825eb42bSJan Lentfer }
205825eb42bSJan Lentfer 
206825eb42bSJan Lentfer uint16_t
ldns_pkt_edns_udp_size(const ldns_pkt * packet)207825eb42bSJan Lentfer ldns_pkt_edns_udp_size(const ldns_pkt *packet)
208825eb42bSJan Lentfer {
209825eb42bSJan Lentfer 	return packet->_edns_udp_size;
210825eb42bSJan Lentfer }
211825eb42bSJan Lentfer 
212825eb42bSJan Lentfer uint8_t
ldns_pkt_edns_extended_rcode(const ldns_pkt * packet)213825eb42bSJan Lentfer ldns_pkt_edns_extended_rcode(const ldns_pkt *packet)
214825eb42bSJan Lentfer {
215825eb42bSJan Lentfer 	return packet->_edns_extended_rcode;
216825eb42bSJan Lentfer }
217825eb42bSJan Lentfer 
218825eb42bSJan Lentfer uint8_t
ldns_pkt_edns_version(const ldns_pkt * packet)219825eb42bSJan Lentfer ldns_pkt_edns_version(const ldns_pkt *packet)
220825eb42bSJan Lentfer {
221825eb42bSJan Lentfer 	return packet->_edns_version;
222825eb42bSJan Lentfer }
223825eb42bSJan Lentfer 
224825eb42bSJan Lentfer uint16_t
ldns_pkt_edns_z(const ldns_pkt * packet)225825eb42bSJan Lentfer ldns_pkt_edns_z(const ldns_pkt *packet)
226825eb42bSJan Lentfer {
227825eb42bSJan Lentfer 	return packet->_edns_z;
228825eb42bSJan Lentfer }
229825eb42bSJan Lentfer 
230825eb42bSJan Lentfer bool
ldns_pkt_edns_do(const ldns_pkt * packet)231825eb42bSJan Lentfer ldns_pkt_edns_do(const ldns_pkt *packet)
232825eb42bSJan Lentfer {
233825eb42bSJan Lentfer 	return (packet->_edns_z & LDNS_EDNS_MASK_DO_BIT);
234825eb42bSJan Lentfer }
235825eb42bSJan Lentfer 
236825eb42bSJan Lentfer void
ldns_pkt_set_edns_do(ldns_pkt * packet,bool value)237825eb42bSJan Lentfer ldns_pkt_set_edns_do(ldns_pkt *packet, bool value)
238825eb42bSJan Lentfer {
239825eb42bSJan Lentfer 	if (value) {
240825eb42bSJan Lentfer 		packet->_edns_z = packet->_edns_z | LDNS_EDNS_MASK_DO_BIT;
241825eb42bSJan Lentfer 	} else {
242825eb42bSJan Lentfer 		packet->_edns_z = packet->_edns_z & ~LDNS_EDNS_MASK_DO_BIT;
243825eb42bSJan Lentfer 	}
244825eb42bSJan Lentfer }
245825eb42bSJan Lentfer 
246819dec71SDaniel Fojt uint16_t
ldns_pkt_edns_unassigned(const ldns_pkt * packet)247819dec71SDaniel Fojt ldns_pkt_edns_unassigned(const ldns_pkt *packet)
248819dec71SDaniel Fojt {
249819dec71SDaniel Fojt 	return (packet->_edns_z & LDNS_EDNS_MASK_UNASSIGNED);
250819dec71SDaniel Fojt }
251819dec71SDaniel Fojt 
252819dec71SDaniel Fojt void
ldns_pkt_set_edns_unassigned(ldns_pkt * packet,uint16_t value)253819dec71SDaniel Fojt ldns_pkt_set_edns_unassigned(ldns_pkt *packet, uint16_t value)
254819dec71SDaniel Fojt {
255819dec71SDaniel Fojt 	packet->_edns_z = (packet->_edns_z & ~LDNS_EDNS_MASK_UNASSIGNED)
256819dec71SDaniel Fojt 			| (value & LDNS_EDNS_MASK_UNASSIGNED);
257819dec71SDaniel Fojt }
258819dec71SDaniel Fojt 
259825eb42bSJan Lentfer ldns_rdf *
ldns_pkt_edns_data(const ldns_pkt * packet)260825eb42bSJan Lentfer ldns_pkt_edns_data(const ldns_pkt *packet)
261825eb42bSJan Lentfer {
262825eb42bSJan Lentfer 	return packet->_edns_data;
263825eb42bSJan Lentfer }
264825eb42bSJan Lentfer 
265825eb42bSJan Lentfer /* return only those rr that share the ownername */
266825eb42bSJan Lentfer ldns_rr_list *
ldns_pkt_rr_list_by_name(const ldns_pkt * packet,const ldns_rdf * ownername,ldns_pkt_section sec)2675340022aSzrj ldns_pkt_rr_list_by_name(const ldns_pkt *packet,
2685340022aSzrj                          const ldns_rdf *ownername,
269825eb42bSJan Lentfer                          ldns_pkt_section sec)
270825eb42bSJan Lentfer {
271825eb42bSJan Lentfer 	ldns_rr_list *rrs;
272825eb42bSJan Lentfer 	ldns_rr_list *ret;
273825eb42bSJan Lentfer 	uint16_t i;
274825eb42bSJan Lentfer 
275825eb42bSJan Lentfer 	if (!packet) {
276825eb42bSJan Lentfer 		return NULL;
277825eb42bSJan Lentfer 	}
278825eb42bSJan Lentfer 
279825eb42bSJan Lentfer 	rrs = ldns_pkt_get_section_clone(packet, sec);
280825eb42bSJan Lentfer 	ret = NULL;
281825eb42bSJan Lentfer 
282825eb42bSJan Lentfer 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
2835340022aSzrj 		if (ldns_dname_compare(ldns_rr_owner(
284825eb42bSJan Lentfer 						ldns_rr_list_rr(rrs, i)),
285825eb42bSJan Lentfer 					ownername) == 0) {
286825eb42bSJan Lentfer 			/* owner names match */
287d1b2b5caSJohn Marino 			if (ret == NULL) {
288d1b2b5caSJohn Marino 				ret = ldns_rr_list_new();
289d1b2b5caSJohn Marino 			}
2905340022aSzrj 			ldns_rr_list_push_rr(ret,
2915340022aSzrj 					     ldns_rr_clone(
2925340022aSzrj 						ldns_rr_list_rr(rrs, i))
2935340022aSzrj 					    );
294825eb42bSJan Lentfer 		}
295825eb42bSJan Lentfer 	}
2965340022aSzrj 
2975340022aSzrj 	ldns_rr_list_deep_free(rrs);
2985340022aSzrj 
299825eb42bSJan Lentfer 	return ret;
300825eb42bSJan Lentfer }
301825eb42bSJan Lentfer 
302825eb42bSJan Lentfer /* return only those rr that share a type */
303825eb42bSJan Lentfer ldns_rr_list *
ldns_pkt_rr_list_by_type(const ldns_pkt * packet,ldns_rr_type type,ldns_pkt_section sec)304825eb42bSJan Lentfer ldns_pkt_rr_list_by_type(const ldns_pkt *packet,
305825eb42bSJan Lentfer                          ldns_rr_type type,
306825eb42bSJan Lentfer                          ldns_pkt_section sec)
307825eb42bSJan Lentfer {
308825eb42bSJan Lentfer 	ldns_rr_list *rrs;
309825eb42bSJan Lentfer 	ldns_rr_list *new;
310825eb42bSJan Lentfer 	uint16_t i;
311825eb42bSJan Lentfer 
312825eb42bSJan Lentfer 	if(!packet) {
313825eb42bSJan Lentfer 		return NULL;
314825eb42bSJan Lentfer 	}
315825eb42bSJan Lentfer 
316825eb42bSJan Lentfer 	rrs = ldns_pkt_get_section_clone(packet, sec);
317825eb42bSJan Lentfer 	new = ldns_rr_list_new();
318825eb42bSJan Lentfer 
319825eb42bSJan Lentfer 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
320825eb42bSJan Lentfer 		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i))) {
321825eb42bSJan Lentfer 			/* types match */
322825eb42bSJan Lentfer 			ldns_rr_list_push_rr(new,
323825eb42bSJan Lentfer 			                     ldns_rr_clone(
324825eb42bSJan Lentfer 			                     	ldns_rr_list_rr(rrs, i))
325825eb42bSJan Lentfer 					     );
326825eb42bSJan Lentfer 		}
327825eb42bSJan Lentfer 	}
328825eb42bSJan Lentfer 	ldns_rr_list_deep_free(rrs);
329825eb42bSJan Lentfer 
330825eb42bSJan Lentfer 	if (ldns_rr_list_rr_count(new) == 0) {
331825eb42bSJan Lentfer 		ldns_rr_list_free(new);
332825eb42bSJan Lentfer 		return NULL;
333825eb42bSJan Lentfer 	} else {
334825eb42bSJan Lentfer 		return new;
335825eb42bSJan Lentfer 	}
336825eb42bSJan Lentfer }
337825eb42bSJan Lentfer 
338825eb42bSJan Lentfer /* return only those rrs that share name and type */
339825eb42bSJan Lentfer ldns_rr_list *
ldns_pkt_rr_list_by_name_and_type(const ldns_pkt * packet,const ldns_rdf * ownername,ldns_rr_type type,ldns_pkt_section sec)340825eb42bSJan Lentfer ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet,
341825eb42bSJan Lentfer                                   const ldns_rdf *ownername,
342825eb42bSJan Lentfer                                   ldns_rr_type type,
343825eb42bSJan Lentfer                                   ldns_pkt_section sec)
344825eb42bSJan Lentfer {
345825eb42bSJan Lentfer 	ldns_rr_list *rrs;
346825eb42bSJan Lentfer 	ldns_rr_list *new;
347825eb42bSJan Lentfer 	ldns_rr_list *ret;
348825eb42bSJan Lentfer 	uint16_t i;
349825eb42bSJan Lentfer 
350825eb42bSJan Lentfer 	if(!packet) {
351825eb42bSJan Lentfer 		return NULL;
352825eb42bSJan Lentfer 	}
353825eb42bSJan Lentfer 
354825eb42bSJan Lentfer 	rrs = ldns_pkt_get_section_clone(packet, sec);
355825eb42bSJan Lentfer 	new = ldns_rr_list_new();
356825eb42bSJan Lentfer 	ret = NULL;
357825eb42bSJan Lentfer 
358825eb42bSJan Lentfer 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
359825eb42bSJan Lentfer 		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i)) &&
3605340022aSzrj 		    ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(rrs, i)),
361825eb42bSJan Lentfer 		                     ownername
362825eb42bSJan Lentfer 		                    ) == 0
363825eb42bSJan Lentfer 		   ) {
364825eb42bSJan Lentfer 			/* types match */
365825eb42bSJan Lentfer 			ldns_rr_list_push_rr(new, ldns_rr_clone(ldns_rr_list_rr(rrs, i)));
366825eb42bSJan Lentfer 			ret = new;
367825eb42bSJan Lentfer 		}
368825eb42bSJan Lentfer 	}
369825eb42bSJan Lentfer 	ldns_rr_list_deep_free(rrs);
370825eb42bSJan Lentfer 	if (!ret) {
371825eb42bSJan Lentfer 		ldns_rr_list_free(new);
372825eb42bSJan Lentfer 	}
373825eb42bSJan Lentfer 	return ret;
374825eb42bSJan Lentfer }
375825eb42bSJan Lentfer 
376825eb42bSJan Lentfer bool
ldns_pkt_rr(const ldns_pkt * pkt,ldns_pkt_section sec,const ldns_rr * rr)3775340022aSzrj ldns_pkt_rr(const ldns_pkt *pkt, ldns_pkt_section sec, const ldns_rr *rr)
378825eb42bSJan Lentfer {
379825eb42bSJan Lentfer 	bool result = false;
380825eb42bSJan Lentfer 
381825eb42bSJan Lentfer 	switch (sec) {
382825eb42bSJan Lentfer 	case LDNS_SECTION_QUESTION:
383825eb42bSJan Lentfer 		return ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
384825eb42bSJan Lentfer 	case LDNS_SECTION_ANSWER:
385825eb42bSJan Lentfer 		return ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr);
386825eb42bSJan Lentfer 	case LDNS_SECTION_AUTHORITY:
387825eb42bSJan Lentfer 		return ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr);
388825eb42bSJan Lentfer 	case LDNS_SECTION_ADDITIONAL:
389825eb42bSJan Lentfer 		return ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
390825eb42bSJan Lentfer 	case LDNS_SECTION_ANY:
391825eb42bSJan Lentfer 		result = ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
392819dec71SDaniel Fojt 		/* fallthrough */
393825eb42bSJan Lentfer 	case LDNS_SECTION_ANY_NOQUESTION:
394825eb42bSJan Lentfer 		result = result
395825eb42bSJan Lentfer 		    || ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr)
396825eb42bSJan Lentfer 		    || ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr)
397825eb42bSJan Lentfer 		    || ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
398825eb42bSJan Lentfer 	}
399825eb42bSJan Lentfer 
400825eb42bSJan Lentfer 	return result;
401825eb42bSJan Lentfer }
402825eb42bSJan Lentfer 
403825eb42bSJan Lentfer uint16_t
ldns_pkt_section_count(const ldns_pkt * packet,ldns_pkt_section s)404825eb42bSJan Lentfer ldns_pkt_section_count(const ldns_pkt *packet, ldns_pkt_section s)
405825eb42bSJan Lentfer {
406825eb42bSJan Lentfer 	switch(s) {
407825eb42bSJan Lentfer 	case LDNS_SECTION_QUESTION:
408825eb42bSJan Lentfer 		return ldns_pkt_qdcount(packet);
409825eb42bSJan Lentfer 	case LDNS_SECTION_ANSWER:
410825eb42bSJan Lentfer 		return ldns_pkt_ancount(packet);
411825eb42bSJan Lentfer 	case LDNS_SECTION_AUTHORITY:
412825eb42bSJan Lentfer 		return ldns_pkt_nscount(packet);
413825eb42bSJan Lentfer 	case LDNS_SECTION_ADDITIONAL:
414825eb42bSJan Lentfer 		return ldns_pkt_arcount(packet);
415825eb42bSJan Lentfer 	case LDNS_SECTION_ANY:
416825eb42bSJan Lentfer 		return ldns_pkt_qdcount(packet) +
417825eb42bSJan Lentfer 			ldns_pkt_ancount(packet) +
418825eb42bSJan Lentfer 			ldns_pkt_nscount(packet) +
419825eb42bSJan Lentfer 			ldns_pkt_arcount(packet);
420825eb42bSJan Lentfer 	case LDNS_SECTION_ANY_NOQUESTION:
421825eb42bSJan Lentfer 		return ldns_pkt_ancount(packet) +
422825eb42bSJan Lentfer 			ldns_pkt_nscount(packet) +
423825eb42bSJan Lentfer 			ldns_pkt_arcount(packet);
424825eb42bSJan Lentfer 	default:
425825eb42bSJan Lentfer 		return 0;
426825eb42bSJan Lentfer 	}
427825eb42bSJan Lentfer }
428825eb42bSJan Lentfer 
429825eb42bSJan Lentfer bool
ldns_pkt_empty(ldns_pkt * p)430825eb42bSJan Lentfer ldns_pkt_empty(ldns_pkt *p)
431825eb42bSJan Lentfer {
432825eb42bSJan Lentfer 	if (!p) {
433825eb42bSJan Lentfer 		return true; /* NULL is empty? */
434825eb42bSJan Lentfer 	}
435825eb42bSJan Lentfer 	if (ldns_pkt_section_count(p, LDNS_SECTION_ANY) > 0) {
436825eb42bSJan Lentfer 		return false;
437ac996e71SJan Lentfer 	} else {
438ac996e71SJan Lentfer 		return true;
439ac996e71SJan Lentfer     }
440825eb42bSJan Lentfer }
441825eb42bSJan Lentfer 
442825eb42bSJan Lentfer 
443825eb42bSJan Lentfer ldns_rr_list *
ldns_pkt_get_section_clone(const ldns_pkt * packet,ldns_pkt_section s)444825eb42bSJan Lentfer ldns_pkt_get_section_clone(const ldns_pkt *packet, ldns_pkt_section s)
445825eb42bSJan Lentfer {
446825eb42bSJan Lentfer 	switch(s) {
447825eb42bSJan Lentfer 	case LDNS_SECTION_QUESTION:
448825eb42bSJan Lentfer 		return ldns_rr_list_clone(ldns_pkt_question(packet));
449825eb42bSJan Lentfer 	case LDNS_SECTION_ANSWER:
450825eb42bSJan Lentfer 		return ldns_rr_list_clone(ldns_pkt_answer(packet));
451825eb42bSJan Lentfer 	case LDNS_SECTION_AUTHORITY:
452825eb42bSJan Lentfer 		return ldns_rr_list_clone(ldns_pkt_authority(packet));
453825eb42bSJan Lentfer 	case LDNS_SECTION_ADDITIONAL:
454825eb42bSJan Lentfer 		return ldns_rr_list_clone(ldns_pkt_additional(packet));
455825eb42bSJan Lentfer 	case LDNS_SECTION_ANY:
456825eb42bSJan Lentfer 		/* these are already clones */
457825eb42bSJan Lentfer 		return ldns_pkt_all(packet);
458825eb42bSJan Lentfer 	case LDNS_SECTION_ANY_NOQUESTION:
459825eb42bSJan Lentfer 		return ldns_pkt_all_noquestion(packet);
460825eb42bSJan Lentfer 	default:
461825eb42bSJan Lentfer 		return NULL;
462825eb42bSJan Lentfer 	}
463825eb42bSJan Lentfer }
464825eb42bSJan Lentfer 
ldns_pkt_tsig(const ldns_pkt * pkt)465825eb42bSJan Lentfer ldns_rr *ldns_pkt_tsig(const ldns_pkt *pkt) {
466825eb42bSJan Lentfer 	return pkt->_tsig_rr;
467825eb42bSJan Lentfer }
468825eb42bSJan Lentfer 
469825eb42bSJan Lentfer /* write */
470825eb42bSJan Lentfer void
ldns_pkt_set_id(ldns_pkt * packet,uint16_t id)471825eb42bSJan Lentfer ldns_pkt_set_id(ldns_pkt *packet, uint16_t id)
472825eb42bSJan Lentfer {
473825eb42bSJan Lentfer 	packet->_header->_id = id;
474825eb42bSJan Lentfer }
475825eb42bSJan Lentfer 
476825eb42bSJan Lentfer void
ldns_pkt_set_random_id(ldns_pkt * packet)477825eb42bSJan Lentfer ldns_pkt_set_random_id(ldns_pkt *packet)
478825eb42bSJan Lentfer {
479ac996e71SJan Lentfer 	uint16_t rid = ldns_get_random();
480825eb42bSJan Lentfer 	ldns_pkt_set_id(packet, rid);
481825eb42bSJan Lentfer }
482825eb42bSJan Lentfer 
483825eb42bSJan Lentfer 
484825eb42bSJan Lentfer void
ldns_pkt_set_qr(ldns_pkt * packet,bool qr)485825eb42bSJan Lentfer ldns_pkt_set_qr(ldns_pkt *packet, bool qr)
486825eb42bSJan Lentfer {
487825eb42bSJan Lentfer 	packet->_header->_qr = qr;
488825eb42bSJan Lentfer }
489825eb42bSJan Lentfer 
490825eb42bSJan Lentfer void
ldns_pkt_set_aa(ldns_pkt * packet,bool aa)491825eb42bSJan Lentfer ldns_pkt_set_aa(ldns_pkt *packet, bool aa)
492825eb42bSJan Lentfer {
493825eb42bSJan Lentfer 	packet->_header->_aa = aa;
494825eb42bSJan Lentfer }
495825eb42bSJan Lentfer 
496825eb42bSJan Lentfer void
ldns_pkt_set_tc(ldns_pkt * packet,bool tc)497825eb42bSJan Lentfer ldns_pkt_set_tc(ldns_pkt *packet, bool tc)
498825eb42bSJan Lentfer {
499825eb42bSJan Lentfer 	packet->_header->_tc = tc;
500825eb42bSJan Lentfer }
501825eb42bSJan Lentfer 
502825eb42bSJan Lentfer void
ldns_pkt_set_rd(ldns_pkt * packet,bool rd)503825eb42bSJan Lentfer ldns_pkt_set_rd(ldns_pkt *packet, bool rd)
504825eb42bSJan Lentfer {
505825eb42bSJan Lentfer 	packet->_header->_rd = rd;
506825eb42bSJan Lentfer }
507825eb42bSJan Lentfer 
508825eb42bSJan Lentfer void
ldns_pkt_set_additional(ldns_pkt * p,ldns_rr_list * rr)509825eb42bSJan Lentfer ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr)
510825eb42bSJan Lentfer {
511825eb42bSJan Lentfer 	p->_additional = rr;
512825eb42bSJan Lentfer }
513825eb42bSJan Lentfer 
514825eb42bSJan Lentfer void
ldns_pkt_set_question(ldns_pkt * p,ldns_rr_list * rr)515825eb42bSJan Lentfer ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr)
516825eb42bSJan Lentfer {
517825eb42bSJan Lentfer 	p->_question = rr;
518825eb42bSJan Lentfer }
519825eb42bSJan Lentfer 
520825eb42bSJan Lentfer void
ldns_pkt_set_answer(ldns_pkt * p,ldns_rr_list * rr)521825eb42bSJan Lentfer ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr)
522825eb42bSJan Lentfer {
523825eb42bSJan Lentfer 	p->_answer = rr;
524825eb42bSJan Lentfer }
525825eb42bSJan Lentfer 
526825eb42bSJan Lentfer void
ldns_pkt_set_authority(ldns_pkt * p,ldns_rr_list * rr)527825eb42bSJan Lentfer ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr)
528825eb42bSJan Lentfer {
529825eb42bSJan Lentfer 	p->_authority = rr;
530825eb42bSJan Lentfer }
531825eb42bSJan Lentfer 
532825eb42bSJan Lentfer void
ldns_pkt_set_cd(ldns_pkt * packet,bool cd)533825eb42bSJan Lentfer ldns_pkt_set_cd(ldns_pkt *packet, bool cd)
534825eb42bSJan Lentfer {
535825eb42bSJan Lentfer 	packet->_header->_cd = cd;
536825eb42bSJan Lentfer }
537825eb42bSJan Lentfer 
538825eb42bSJan Lentfer void
ldns_pkt_set_ra(ldns_pkt * packet,bool ra)539825eb42bSJan Lentfer ldns_pkt_set_ra(ldns_pkt *packet, bool ra)
540825eb42bSJan Lentfer {
541825eb42bSJan Lentfer 	packet->_header->_ra = ra;
542825eb42bSJan Lentfer }
543825eb42bSJan Lentfer 
544825eb42bSJan Lentfer void
ldns_pkt_set_ad(ldns_pkt * packet,bool ad)545825eb42bSJan Lentfer ldns_pkt_set_ad(ldns_pkt *packet, bool ad)
546825eb42bSJan Lentfer {
547825eb42bSJan Lentfer 	packet->_header->_ad = ad;
548825eb42bSJan Lentfer }
549825eb42bSJan Lentfer 
550825eb42bSJan Lentfer void
ldns_pkt_set_opcode(ldns_pkt * packet,ldns_pkt_opcode opcode)551825eb42bSJan Lentfer ldns_pkt_set_opcode(ldns_pkt *packet, ldns_pkt_opcode opcode)
552825eb42bSJan Lentfer {
553825eb42bSJan Lentfer 	packet->_header->_opcode = opcode;
554825eb42bSJan Lentfer }
555825eb42bSJan Lentfer 
556825eb42bSJan Lentfer void
ldns_pkt_set_rcode(ldns_pkt * packet,uint8_t rcode)557825eb42bSJan Lentfer ldns_pkt_set_rcode(ldns_pkt *packet, uint8_t rcode)
558825eb42bSJan Lentfer {
559825eb42bSJan Lentfer 	packet->_header->_rcode = rcode;
560825eb42bSJan Lentfer }
561825eb42bSJan Lentfer 
562825eb42bSJan Lentfer void
ldns_pkt_set_qdcount(ldns_pkt * packet,uint16_t qdcount)563825eb42bSJan Lentfer ldns_pkt_set_qdcount(ldns_pkt *packet, uint16_t qdcount)
564825eb42bSJan Lentfer {
565825eb42bSJan Lentfer 	packet->_header->_qdcount = qdcount;
566825eb42bSJan Lentfer }
567825eb42bSJan Lentfer 
568825eb42bSJan Lentfer void
ldns_pkt_set_ancount(ldns_pkt * packet,uint16_t ancount)569825eb42bSJan Lentfer ldns_pkt_set_ancount(ldns_pkt *packet, uint16_t ancount)
570825eb42bSJan Lentfer {
571825eb42bSJan Lentfer 	packet->_header->_ancount = ancount;
572825eb42bSJan Lentfer }
573825eb42bSJan Lentfer 
574825eb42bSJan Lentfer void
ldns_pkt_set_nscount(ldns_pkt * packet,uint16_t nscount)575825eb42bSJan Lentfer ldns_pkt_set_nscount(ldns_pkt *packet, uint16_t nscount)
576825eb42bSJan Lentfer {
577825eb42bSJan Lentfer 	packet->_header->_nscount = nscount;
578825eb42bSJan Lentfer }
579825eb42bSJan Lentfer 
580825eb42bSJan Lentfer void
ldns_pkt_set_arcount(ldns_pkt * packet,uint16_t arcount)581825eb42bSJan Lentfer ldns_pkt_set_arcount(ldns_pkt *packet, uint16_t arcount)
582825eb42bSJan Lentfer {
583825eb42bSJan Lentfer 	packet->_header->_arcount = arcount;
584825eb42bSJan Lentfer }
585825eb42bSJan Lentfer 
586825eb42bSJan Lentfer void
ldns_pkt_set_querytime(ldns_pkt * packet,uint32_t time)587825eb42bSJan Lentfer ldns_pkt_set_querytime(ldns_pkt *packet, uint32_t time)
588825eb42bSJan Lentfer {
589825eb42bSJan Lentfer 	packet->_querytime = time;
590825eb42bSJan Lentfer }
591825eb42bSJan Lentfer 
592825eb42bSJan Lentfer void
ldns_pkt_set_answerfrom(ldns_pkt * packet,ldns_rdf * answerfrom)593825eb42bSJan Lentfer ldns_pkt_set_answerfrom(ldns_pkt *packet, ldns_rdf *answerfrom)
594825eb42bSJan Lentfer {
595825eb42bSJan Lentfer 	packet->_answerfrom = answerfrom;
596825eb42bSJan Lentfer }
597825eb42bSJan Lentfer 
598825eb42bSJan Lentfer void
ldns_pkt_set_timestamp(ldns_pkt * packet,struct timeval timeval)599825eb42bSJan Lentfer ldns_pkt_set_timestamp(ldns_pkt *packet, struct timeval timeval)
600825eb42bSJan Lentfer {
601825eb42bSJan Lentfer 	packet->timestamp.tv_sec = timeval.tv_sec;
602825eb42bSJan Lentfer 	packet->timestamp.tv_usec = timeval.tv_usec;
603825eb42bSJan Lentfer }
604825eb42bSJan Lentfer 
605825eb42bSJan Lentfer void
ldns_pkt_set_size(ldns_pkt * packet,size_t s)606825eb42bSJan Lentfer ldns_pkt_set_size(ldns_pkt *packet, size_t s)
607825eb42bSJan Lentfer {
608825eb42bSJan Lentfer 	packet->_size = s;
609825eb42bSJan Lentfer }
610825eb42bSJan Lentfer 
611825eb42bSJan Lentfer void
ldns_pkt_set_edns_udp_size(ldns_pkt * packet,uint16_t s)612825eb42bSJan Lentfer ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s)
613825eb42bSJan Lentfer {
614825eb42bSJan Lentfer 	packet->_edns_udp_size = s;
615825eb42bSJan Lentfer }
616825eb42bSJan Lentfer 
617825eb42bSJan Lentfer void
ldns_pkt_set_edns_extended_rcode(ldns_pkt * packet,uint8_t c)618825eb42bSJan Lentfer ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c)
619825eb42bSJan Lentfer {
620825eb42bSJan Lentfer 	packet->_edns_extended_rcode = c;
621825eb42bSJan Lentfer }
622825eb42bSJan Lentfer 
623825eb42bSJan Lentfer void
ldns_pkt_set_edns_version(ldns_pkt * packet,uint8_t v)624825eb42bSJan Lentfer ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v)
625825eb42bSJan Lentfer {
626825eb42bSJan Lentfer 	packet->_edns_version = v;
627825eb42bSJan Lentfer }
628825eb42bSJan Lentfer 
629825eb42bSJan Lentfer void
ldns_pkt_set_edns_z(ldns_pkt * packet,uint16_t z)630825eb42bSJan Lentfer ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z)
631825eb42bSJan Lentfer {
632825eb42bSJan Lentfer 	packet->_edns_z = z;
633825eb42bSJan Lentfer }
634825eb42bSJan Lentfer 
635825eb42bSJan Lentfer void
ldns_pkt_set_edns_data(ldns_pkt * packet,ldns_rdf * data)636825eb42bSJan Lentfer ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data)
637825eb42bSJan Lentfer {
638825eb42bSJan Lentfer 	packet->_edns_data = data;
639825eb42bSJan Lentfer }
640825eb42bSJan Lentfer 
641825eb42bSJan Lentfer void
ldns_pkt_set_edns_option_list(ldns_pkt * packet,ldns_edns_option_list * list)642*ee791febSAntonio Huete Jimenez ldns_pkt_set_edns_option_list(ldns_pkt *packet, ldns_edns_option_list *list)
643*ee791febSAntonio Huete Jimenez {
644*ee791febSAntonio Huete Jimenez 	if (packet->_edns_list)
645*ee791febSAntonio Huete Jimenez 		ldns_edns_option_list_deep_free(packet->_edns_list);
646*ee791febSAntonio Huete Jimenez 	packet->_edns_list = list;
647*ee791febSAntonio Huete Jimenez }
648*ee791febSAntonio Huete Jimenez 
649*ee791febSAntonio Huete Jimenez 
650*ee791febSAntonio Huete Jimenez void
ldns_pkt_set_section_count(ldns_pkt * packet,ldns_pkt_section s,uint16_t count)651825eb42bSJan Lentfer ldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count)
652825eb42bSJan Lentfer {
653825eb42bSJan Lentfer 	switch(s) {
654825eb42bSJan Lentfer 		case LDNS_SECTION_QUESTION:
655825eb42bSJan Lentfer 			ldns_pkt_set_qdcount(packet, count);
656825eb42bSJan Lentfer 			break;
657825eb42bSJan Lentfer 		case LDNS_SECTION_ANSWER:
658825eb42bSJan Lentfer 			ldns_pkt_set_ancount(packet, count);
659825eb42bSJan Lentfer 			break;
660825eb42bSJan Lentfer 		case LDNS_SECTION_AUTHORITY:
661825eb42bSJan Lentfer 			ldns_pkt_set_nscount(packet, count);
662825eb42bSJan Lentfer 			break;
663825eb42bSJan Lentfer 		case LDNS_SECTION_ADDITIONAL:
664825eb42bSJan Lentfer 			ldns_pkt_set_arcount(packet, count);
665825eb42bSJan Lentfer 			break;
666825eb42bSJan Lentfer 		case LDNS_SECTION_ANY:
667825eb42bSJan Lentfer 		case LDNS_SECTION_ANY_NOQUESTION:
668825eb42bSJan Lentfer 			break;
669825eb42bSJan Lentfer 	}
670825eb42bSJan Lentfer }
671825eb42bSJan Lentfer 
ldns_pkt_set_tsig(ldns_pkt * pkt,ldns_rr * rr)672825eb42bSJan Lentfer void ldns_pkt_set_tsig(ldns_pkt *pkt, ldns_rr *rr)
673825eb42bSJan Lentfer {
674825eb42bSJan Lentfer 	pkt->_tsig_rr = rr;
675825eb42bSJan Lentfer }
676825eb42bSJan Lentfer 
677825eb42bSJan Lentfer bool
ldns_pkt_push_rr(ldns_pkt * packet,ldns_pkt_section section,ldns_rr * rr)678825eb42bSJan Lentfer ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr)
679825eb42bSJan Lentfer {
680825eb42bSJan Lentfer 	switch(section) {
681825eb42bSJan Lentfer 		case LDNS_SECTION_QUESTION:
682d1b2b5caSJohn Marino 			if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) {
683d1b2b5caSJohn Marino 				return false;
684d1b2b5caSJohn Marino 			}
685825eb42bSJan Lentfer 			ldns_pkt_set_qdcount(packet, ldns_pkt_qdcount(packet) + 1);
686825eb42bSJan Lentfer 			break;
687825eb42bSJan Lentfer 		case LDNS_SECTION_ANSWER:
688d1b2b5caSJohn Marino 			if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) {
689d1b2b5caSJohn Marino 				return false;
690d1b2b5caSJohn Marino 			}
691825eb42bSJan Lentfer 			ldns_pkt_set_ancount(packet, ldns_pkt_ancount(packet) + 1);
692825eb42bSJan Lentfer 			break;
693825eb42bSJan Lentfer 		case LDNS_SECTION_AUTHORITY:
694d1b2b5caSJohn Marino 			if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) {
695d1b2b5caSJohn Marino 				return false;
696d1b2b5caSJohn Marino 			}
697825eb42bSJan Lentfer 			ldns_pkt_set_nscount(packet, ldns_pkt_nscount(packet) + 1);
698825eb42bSJan Lentfer 			break;
699825eb42bSJan Lentfer 		case LDNS_SECTION_ADDITIONAL:
700d1b2b5caSJohn Marino 			if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) {
701d1b2b5caSJohn Marino 				return false;
702d1b2b5caSJohn Marino 			}
703825eb42bSJan Lentfer 			ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + 1);
704825eb42bSJan Lentfer 			break;
705825eb42bSJan Lentfer 		case LDNS_SECTION_ANY:
706825eb42bSJan Lentfer 		case LDNS_SECTION_ANY_NOQUESTION:
707825eb42bSJan Lentfer 			/* shouldn't this error? */
708825eb42bSJan Lentfer 			break;
709825eb42bSJan Lentfer 	}
710825eb42bSJan Lentfer 	return true;
711825eb42bSJan Lentfer }
712825eb42bSJan Lentfer 
713825eb42bSJan Lentfer bool
ldns_pkt_safe_push_rr(ldns_pkt * pkt,ldns_pkt_section sec,ldns_rr * rr)714825eb42bSJan Lentfer ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
715825eb42bSJan Lentfer {
716825eb42bSJan Lentfer 
717825eb42bSJan Lentfer 	/* check to see if its there */
718825eb42bSJan Lentfer 	if (ldns_pkt_rr(pkt, sec, rr)) {
719825eb42bSJan Lentfer 		/* already there */
720825eb42bSJan Lentfer 		return false;
721825eb42bSJan Lentfer 	}
722825eb42bSJan Lentfer 	return ldns_pkt_push_rr(pkt, sec, rr);
723825eb42bSJan Lentfer }
724825eb42bSJan Lentfer 
725825eb42bSJan Lentfer bool
ldns_pkt_push_rr_list(ldns_pkt * p,ldns_pkt_section s,ldns_rr_list * list)726825eb42bSJan Lentfer ldns_pkt_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
727825eb42bSJan Lentfer {
728825eb42bSJan Lentfer 	size_t i;
729825eb42bSJan Lentfer 	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
730825eb42bSJan Lentfer 		if (!ldns_pkt_push_rr(p, s, ldns_rr_list_rr(list, i))) {
731825eb42bSJan Lentfer 			return false;
732825eb42bSJan Lentfer 		}
733825eb42bSJan Lentfer 	}
734825eb42bSJan Lentfer 	return true;
735825eb42bSJan Lentfer }
736825eb42bSJan Lentfer 
737825eb42bSJan Lentfer bool
ldns_pkt_safe_push_rr_list(ldns_pkt * p,ldns_pkt_section s,ldns_rr_list * list)738825eb42bSJan Lentfer ldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
739825eb42bSJan Lentfer {
740825eb42bSJan Lentfer 	size_t i;
741825eb42bSJan Lentfer 	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
742825eb42bSJan Lentfer 		if (!ldns_pkt_safe_push_rr(p, s, ldns_rr_list_rr(list, i))) {
743825eb42bSJan Lentfer 			return false;
744825eb42bSJan Lentfer 		}
745825eb42bSJan Lentfer 	}
746825eb42bSJan Lentfer 	return true;
747825eb42bSJan Lentfer }
748825eb42bSJan Lentfer 
749825eb42bSJan Lentfer bool
ldns_pkt_edns(const ldns_pkt * pkt)750*ee791febSAntonio Huete Jimenez ldns_pkt_edns(const ldns_pkt *pkt)
751*ee791febSAntonio Huete Jimenez {
752825eb42bSJan Lentfer 	return (ldns_pkt_edns_udp_size(pkt) > 0 ||
753825eb42bSJan Lentfer 		ldns_pkt_edns_extended_rcode(pkt) > 0 ||
754825eb42bSJan Lentfer 		ldns_pkt_edns_data(pkt) ||
7555340022aSzrj 		ldns_pkt_edns_do(pkt) ||
756*ee791febSAntonio Huete Jimenez 		pkt->_edns_list ||
7575340022aSzrj                 pkt->_edns_present
758825eb42bSJan Lentfer 	       );
759825eb42bSJan Lentfer }
760825eb42bSJan Lentfer 
761*ee791febSAntonio Huete Jimenez ldns_edns_option_list*
pkt_edns_data2edns_option_list(const ldns_rdf * edns_data)762*ee791febSAntonio Huete Jimenez pkt_edns_data2edns_option_list(const ldns_rdf *edns_data)
763*ee791febSAntonio Huete Jimenez {
764*ee791febSAntonio Huete Jimenez 	size_t pos = 0;
765*ee791febSAntonio Huete Jimenez 	ldns_edns_option_list* edns_list;
766*ee791febSAntonio Huete Jimenez 	size_t max;
767*ee791febSAntonio Huete Jimenez 	const uint8_t* wire;
768*ee791febSAntonio Huete Jimenez 
769*ee791febSAntonio Huete Jimenez 	if (!edns_data)
770*ee791febSAntonio Huete Jimenez 		return NULL;
771*ee791febSAntonio Huete Jimenez 
772*ee791febSAntonio Huete Jimenez 	max = ldns_rdf_size(edns_data);
773*ee791febSAntonio Huete Jimenez 	wire = ldns_rdf_data(edns_data);
774*ee791febSAntonio Huete Jimenez 	if (!max)
775*ee791febSAntonio Huete Jimenez 		return NULL;
776*ee791febSAntonio Huete Jimenez 
777*ee791febSAntonio Huete Jimenez 	if (!(edns_list = ldns_edns_option_list_new()))
778*ee791febSAntonio Huete Jimenez 		return NULL;
779*ee791febSAntonio Huete Jimenez 
780*ee791febSAntonio Huete Jimenez 	while (pos < max) {
781*ee791febSAntonio Huete Jimenez 		ldns_edns_option* edns;
782*ee791febSAntonio Huete Jimenez 		uint8_t *data;
783*ee791febSAntonio Huete Jimenez 
784*ee791febSAntonio Huete Jimenez 		if (pos + 4 > max) { /* make sure the header is  */
785*ee791febSAntonio Huete Jimenez 			ldns_edns_option_list_deep_free(edns_list);
786*ee791febSAntonio Huete Jimenez 			return NULL;
787*ee791febSAntonio Huete Jimenez 		}
788*ee791febSAntonio Huete Jimenez 		ldns_edns_option_code code = ldns_read_uint16(&wire[pos]);
789*ee791febSAntonio Huete Jimenez 		size_t size = ldns_read_uint16(&wire[pos+2]);
790*ee791febSAntonio Huete Jimenez 		pos += 4;
791*ee791febSAntonio Huete Jimenez 
792*ee791febSAntonio Huete Jimenez 		if (pos + size > max) { /* make sure the size fits the data */
793*ee791febSAntonio Huete Jimenez 			ldns_edns_option_list_deep_free(edns_list);
794*ee791febSAntonio Huete Jimenez 			return NULL;
795*ee791febSAntonio Huete Jimenez 		}
796*ee791febSAntonio Huete Jimenez 		data = LDNS_XMALLOC(uint8_t, size);
797*ee791febSAntonio Huete Jimenez 
798*ee791febSAntonio Huete Jimenez 		if (!data) {
799*ee791febSAntonio Huete Jimenez 			ldns_edns_option_list_deep_free(edns_list);
800*ee791febSAntonio Huete Jimenez 			return NULL;
801*ee791febSAntonio Huete Jimenez 		}
802*ee791febSAntonio Huete Jimenez 		memcpy(data, &wire[pos], size);
803*ee791febSAntonio Huete Jimenez 		pos += size;
804*ee791febSAntonio Huete Jimenez 
805*ee791febSAntonio Huete Jimenez 		edns = ldns_edns_new(code, size, data);
806*ee791febSAntonio Huete Jimenez 
807*ee791febSAntonio Huete Jimenez 		if (!edns) {
808*ee791febSAntonio Huete Jimenez 			ldns_edns_option_list_deep_free(edns_list);
809*ee791febSAntonio Huete Jimenez 			return NULL;
810*ee791febSAntonio Huete Jimenez 		}
811*ee791febSAntonio Huete Jimenez 		if (!ldns_edns_option_list_push(edns_list, edns)) {
812*ee791febSAntonio Huete Jimenez 			ldns_edns_option_list_deep_free(edns_list);
813*ee791febSAntonio Huete Jimenez 			return NULL;
814*ee791febSAntonio Huete Jimenez 		}
815*ee791febSAntonio Huete Jimenez 	}
816*ee791febSAntonio Huete Jimenez 	return edns_list;
817*ee791febSAntonio Huete Jimenez 
818*ee791febSAntonio Huete Jimenez }
819*ee791febSAntonio Huete Jimenez 
820*ee791febSAntonio Huete Jimenez ldns_edns_option_list*
ldns_pkt_edns_get_option_list(ldns_pkt * packet)821*ee791febSAntonio Huete Jimenez ldns_pkt_edns_get_option_list(ldns_pkt *packet)
822*ee791febSAntonio Huete Jimenez {
823*ee791febSAntonio Huete Jimenez 	/* return the list if it already exists */
824*ee791febSAntonio Huete Jimenez 	if (packet->_edns_list != NULL)
825*ee791febSAntonio Huete Jimenez 		return packet->_edns_list;
826*ee791febSAntonio Huete Jimenez 
827*ee791febSAntonio Huete Jimenez 	/* if the list doesn't exists, we create it by parsing the
828*ee791febSAntonio Huete Jimenez 	 * packet->_edns_data
829*ee791febSAntonio Huete Jimenez 	 */
830*ee791febSAntonio Huete Jimenez 	if (!ldns_pkt_edns_data(packet))
831*ee791febSAntonio Huete Jimenez 		return NULL;
832*ee791febSAntonio Huete Jimenez 
833*ee791febSAntonio Huete Jimenez 	return ( packet->_edns_list
834*ee791febSAntonio Huete Jimenez 	       = pkt_edns_data2edns_option_list(ldns_pkt_edns_data(packet)));
835*ee791febSAntonio Huete Jimenez }
836*ee791febSAntonio Huete Jimenez 
837825eb42bSJan Lentfer 
838825eb42bSJan Lentfer /* Create/destroy/convert functions
839825eb42bSJan Lentfer  */
840825eb42bSJan Lentfer ldns_pkt *
ldns_pkt_new(void)8415340022aSzrj ldns_pkt_new(void)
842825eb42bSJan Lentfer {
843825eb42bSJan Lentfer 	ldns_pkt *packet;
844825eb42bSJan Lentfer 	packet = LDNS_MALLOC(ldns_pkt);
845825eb42bSJan Lentfer 	if (!packet) {
846825eb42bSJan Lentfer 		return NULL;
847825eb42bSJan Lentfer 	}
848825eb42bSJan Lentfer 
849825eb42bSJan Lentfer 	packet->_header = LDNS_MALLOC(ldns_hdr);
850825eb42bSJan Lentfer 	if (!packet->_header) {
851825eb42bSJan Lentfer 		LDNS_FREE(packet);
852825eb42bSJan Lentfer 		return NULL;
853825eb42bSJan Lentfer 	}
854825eb42bSJan Lentfer 
855825eb42bSJan Lentfer 	packet->_question = ldns_rr_list_new();
856825eb42bSJan Lentfer 	packet->_answer = ldns_rr_list_new();
857825eb42bSJan Lentfer 	packet->_authority = ldns_rr_list_new();
858825eb42bSJan Lentfer 	packet->_additional = ldns_rr_list_new();
859825eb42bSJan Lentfer 
860825eb42bSJan Lentfer 	/* default everything to false */
861825eb42bSJan Lentfer 	ldns_pkt_set_qr(packet, false);
862825eb42bSJan Lentfer 	ldns_pkt_set_aa(packet, false);
863825eb42bSJan Lentfer 	ldns_pkt_set_tc(packet, false);
864825eb42bSJan Lentfer 	ldns_pkt_set_rd(packet, false);
865825eb42bSJan Lentfer 	ldns_pkt_set_ra(packet, false);
866825eb42bSJan Lentfer 	ldns_pkt_set_ad(packet, false);
867825eb42bSJan Lentfer 	ldns_pkt_set_cd(packet, false);
868825eb42bSJan Lentfer 
869825eb42bSJan Lentfer 	ldns_pkt_set_opcode(packet, LDNS_PACKET_QUERY);
870825eb42bSJan Lentfer 	ldns_pkt_set_rcode(packet, 0);
871825eb42bSJan Lentfer 	ldns_pkt_set_id(packet, 0);
872825eb42bSJan Lentfer 	ldns_pkt_set_size(packet, 0);
873825eb42bSJan Lentfer 	ldns_pkt_set_querytime(packet, 0);
874825eb42bSJan Lentfer 	memset(&packet->timestamp, 0, sizeof(packet->timestamp));
875825eb42bSJan Lentfer 	ldns_pkt_set_answerfrom(packet, NULL);
876825eb42bSJan Lentfer 	ldns_pkt_set_section_count(packet, LDNS_SECTION_QUESTION, 0);
877825eb42bSJan Lentfer 	ldns_pkt_set_section_count(packet, LDNS_SECTION_ANSWER, 0);
878825eb42bSJan Lentfer 	ldns_pkt_set_section_count(packet, LDNS_SECTION_AUTHORITY, 0);
879825eb42bSJan Lentfer 	ldns_pkt_set_section_count(packet, LDNS_SECTION_ADDITIONAL, 0);
880825eb42bSJan Lentfer 
881825eb42bSJan Lentfer 	ldns_pkt_set_edns_udp_size(packet, 0);
882825eb42bSJan Lentfer 	ldns_pkt_set_edns_extended_rcode(packet, 0);
883825eb42bSJan Lentfer 	ldns_pkt_set_edns_version(packet, 0);
884825eb42bSJan Lentfer 	ldns_pkt_set_edns_z(packet, 0);
885825eb42bSJan Lentfer 	ldns_pkt_set_edns_data(packet, NULL);
886*ee791febSAntonio Huete Jimenez 	packet->_edns_list = NULL;
8875340022aSzrj 	packet->_edns_present = false;
888825eb42bSJan Lentfer 
889825eb42bSJan Lentfer 	ldns_pkt_set_tsig(packet, NULL);
890825eb42bSJan Lentfer 
891825eb42bSJan Lentfer 	return packet;
892825eb42bSJan Lentfer }
893825eb42bSJan Lentfer 
894825eb42bSJan Lentfer void
ldns_pkt_free(ldns_pkt * packet)895825eb42bSJan Lentfer ldns_pkt_free(ldns_pkt *packet)
896825eb42bSJan Lentfer {
897825eb42bSJan Lentfer 	if (packet) {
898825eb42bSJan Lentfer 		LDNS_FREE(packet->_header);
899825eb42bSJan Lentfer 		ldns_rr_list_deep_free(packet->_question);
900825eb42bSJan Lentfer 		ldns_rr_list_deep_free(packet->_answer);
901825eb42bSJan Lentfer 		ldns_rr_list_deep_free(packet->_authority);
902825eb42bSJan Lentfer 		ldns_rr_list_deep_free(packet->_additional);
903825eb42bSJan Lentfer 		ldns_rr_free(packet->_tsig_rr);
904825eb42bSJan Lentfer 		ldns_rdf_deep_free(packet->_edns_data);
905*ee791febSAntonio Huete Jimenez 		ldns_edns_option_list_deep_free(packet->_edns_list);
906d1b2b5caSJohn Marino 		ldns_rdf_deep_free(packet->_answerfrom);
907825eb42bSJan Lentfer 		LDNS_FREE(packet);
908825eb42bSJan Lentfer 	}
909825eb42bSJan Lentfer }
910825eb42bSJan Lentfer 
911825eb42bSJan Lentfer bool
ldns_pkt_set_flags(ldns_pkt * packet,uint16_t flags)912825eb42bSJan Lentfer ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags)
913825eb42bSJan Lentfer {
914825eb42bSJan Lentfer 	if (!packet) {
915825eb42bSJan Lentfer 		return false;
916825eb42bSJan Lentfer 	}
917825eb42bSJan Lentfer 	if ((flags & LDNS_QR) == LDNS_QR) {
918825eb42bSJan Lentfer 		ldns_pkt_set_qr(packet, true);
919825eb42bSJan Lentfer 	}
920825eb42bSJan Lentfer 	if ((flags & LDNS_AA) == LDNS_AA) {
921825eb42bSJan Lentfer 		ldns_pkt_set_aa(packet, true);
922825eb42bSJan Lentfer 	}
923825eb42bSJan Lentfer 	if ((flags & LDNS_RD) == LDNS_RD) {
924825eb42bSJan Lentfer 		ldns_pkt_set_rd(packet, true);
925825eb42bSJan Lentfer 	}
926825eb42bSJan Lentfer 	if ((flags & LDNS_TC) == LDNS_TC) {
927825eb42bSJan Lentfer 		ldns_pkt_set_tc(packet, true);
928825eb42bSJan Lentfer 	}
929825eb42bSJan Lentfer 	if ((flags & LDNS_CD) == LDNS_CD) {
930825eb42bSJan Lentfer 		ldns_pkt_set_cd(packet, true);
931825eb42bSJan Lentfer 	}
932825eb42bSJan Lentfer 	if ((flags & LDNS_RA) == LDNS_RA) {
933825eb42bSJan Lentfer 		ldns_pkt_set_ra(packet, true);
934825eb42bSJan Lentfer 	}
935825eb42bSJan Lentfer 	if ((flags & LDNS_AD) == LDNS_AD) {
936825eb42bSJan Lentfer 		ldns_pkt_set_ad(packet, true);
937825eb42bSJan Lentfer 	}
938825eb42bSJan Lentfer 	return true;
939825eb42bSJan Lentfer }
940825eb42bSJan Lentfer 
941d1b2b5caSJohn Marino 
9425340022aSzrj static ldns_rr*
ldns_pkt_authsoa(const ldns_rdf * rr_name,ldns_rr_class rr_class)9435340022aSzrj ldns_pkt_authsoa(const ldns_rdf* rr_name, ldns_rr_class rr_class)
944d1b2b5caSJohn Marino {
945d1b2b5caSJohn Marino 	ldns_rr* soa_rr = ldns_rr_new();
946d1b2b5caSJohn Marino 	ldns_rdf *owner_rdf;
947d1b2b5caSJohn Marino 	ldns_rdf *mname_rdf;
948d1b2b5caSJohn Marino 	ldns_rdf *rname_rdf;
949d1b2b5caSJohn Marino 	ldns_rdf *serial_rdf;
950d1b2b5caSJohn Marino 	ldns_rdf *refresh_rdf;
951d1b2b5caSJohn Marino 	ldns_rdf *retry_rdf;
952d1b2b5caSJohn Marino 	ldns_rdf *expire_rdf;
953d1b2b5caSJohn Marino 	ldns_rdf *minimum_rdf;
954d1b2b5caSJohn Marino 
955d1b2b5caSJohn Marino 	if (!soa_rr) {
9565340022aSzrj 		return NULL;
957d1b2b5caSJohn Marino 	}
958d1b2b5caSJohn Marino 	owner_rdf = ldns_rdf_clone(rr_name);
959d1b2b5caSJohn Marino 	if (!owner_rdf) {
960d1b2b5caSJohn Marino 		ldns_rr_free(soa_rr);
9615340022aSzrj 		return NULL;
962d1b2b5caSJohn Marino 	}
963d1b2b5caSJohn Marino 
964d1b2b5caSJohn Marino 	ldns_rr_set_owner(soa_rr, owner_rdf);
965d1b2b5caSJohn Marino 	ldns_rr_set_type(soa_rr, LDNS_RR_TYPE_SOA);
966d1b2b5caSJohn Marino 	ldns_rr_set_class(soa_rr, rr_class);
967d1b2b5caSJohn Marino 	ldns_rr_set_question(soa_rr, false);
968d1b2b5caSJohn Marino 
969d1b2b5caSJohn Marino 	if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) {
970d1b2b5caSJohn Marino 		ldns_rr_free(soa_rr);
9715340022aSzrj 		return NULL;
972d1b2b5caSJohn Marino 	} else {
973d1b2b5caSJohn Marino 		ldns_rr_push_rdf(soa_rr, mname_rdf);
974d1b2b5caSJohn Marino 	}
975d1b2b5caSJohn Marino 	if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) {
976d1b2b5caSJohn Marino 		ldns_rr_free(soa_rr);
9775340022aSzrj 		return NULL;
978d1b2b5caSJohn Marino 	} else {
979d1b2b5caSJohn Marino 		ldns_rr_push_rdf(soa_rr, rname_rdf);
980d1b2b5caSJohn Marino 	}
981d1b2b5caSJohn Marino 	serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
982d1b2b5caSJohn Marino 	if (!serial_rdf) {
983d1b2b5caSJohn Marino 		ldns_rr_free(soa_rr);
9845340022aSzrj 		return NULL;
985d1b2b5caSJohn Marino 	} else {
986d1b2b5caSJohn Marino 		ldns_rr_push_rdf(soa_rr, serial_rdf);
987d1b2b5caSJohn Marino 	}
988d1b2b5caSJohn Marino 	refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
989d1b2b5caSJohn Marino 	if (!refresh_rdf) {
990d1b2b5caSJohn Marino 		ldns_rr_free(soa_rr);
9915340022aSzrj 		return NULL;
992d1b2b5caSJohn Marino 	} else {
993d1b2b5caSJohn Marino 		ldns_rr_push_rdf(soa_rr, refresh_rdf);
994d1b2b5caSJohn Marino 	}
995d1b2b5caSJohn Marino 	retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
996d1b2b5caSJohn Marino 	if (!retry_rdf) {
997d1b2b5caSJohn Marino 		ldns_rr_free(soa_rr);
9985340022aSzrj 		return NULL;
999d1b2b5caSJohn Marino 	} else {
1000d1b2b5caSJohn Marino 		ldns_rr_push_rdf(soa_rr, retry_rdf);
1001d1b2b5caSJohn Marino 	}
1002d1b2b5caSJohn Marino 	expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1003d1b2b5caSJohn Marino 	if (!expire_rdf) {
1004d1b2b5caSJohn Marino 		ldns_rr_free(soa_rr);
10055340022aSzrj 		return NULL;
1006d1b2b5caSJohn Marino 	} else {
1007d1b2b5caSJohn Marino 		ldns_rr_push_rdf(soa_rr, expire_rdf);
1008d1b2b5caSJohn Marino 	}
1009d1b2b5caSJohn Marino 	minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1010d1b2b5caSJohn Marino 	if (!minimum_rdf) {
1011d1b2b5caSJohn Marino 		ldns_rr_free(soa_rr);
10125340022aSzrj 		return NULL;
1013d1b2b5caSJohn Marino 	} else {
1014d1b2b5caSJohn Marino 		ldns_rr_push_rdf(soa_rr, minimum_rdf);
1015d1b2b5caSJohn Marino 	}
10165340022aSzrj 	return soa_rr;
1017d1b2b5caSJohn Marino }
1018d1b2b5caSJohn Marino 
1019d1b2b5caSJohn Marino 
10205340022aSzrj static ldns_status
ldns_pkt_query_new_frm_str_internal(ldns_pkt ** p,const char * name,ldns_rr_type rr_type,ldns_rr_class rr_class,uint16_t flags,ldns_rr * authsoa_rr)10215340022aSzrj ldns_pkt_query_new_frm_str_internal(ldns_pkt **p, const char *name,
10225340022aSzrj 	ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags,
10235340022aSzrj 	ldns_rr* authsoa_rr)
1024825eb42bSJan Lentfer {
1025825eb42bSJan Lentfer 	ldns_pkt *packet;
1026825eb42bSJan Lentfer 	ldns_rr *question_rr;
1027825eb42bSJan Lentfer 	ldns_rdf *name_rdf;
1028825eb42bSJan Lentfer 
1029825eb42bSJan Lentfer 	packet = ldns_pkt_new();
1030825eb42bSJan Lentfer 	if (!packet) {
1031825eb42bSJan Lentfer 		return LDNS_STATUS_MEM_ERR;
1032825eb42bSJan Lentfer 	}
1033825eb42bSJan Lentfer 
1034825eb42bSJan Lentfer 	if (!ldns_pkt_set_flags(packet, flags)) {
1035819dec71SDaniel Fojt 		ldns_pkt_free(packet);
1036825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
1037825eb42bSJan Lentfer 	}
1038825eb42bSJan Lentfer 
1039825eb42bSJan Lentfer 	question_rr = ldns_rr_new();
1040825eb42bSJan Lentfer 	if (!question_rr) {
1041819dec71SDaniel Fojt 		ldns_pkt_free(packet);
1042825eb42bSJan Lentfer 		return LDNS_STATUS_MEM_ERR;
1043825eb42bSJan Lentfer 	}
1044825eb42bSJan Lentfer 
1045825eb42bSJan Lentfer 	if (rr_type == 0) {
1046825eb42bSJan Lentfer 		rr_type = LDNS_RR_TYPE_A;
1047825eb42bSJan Lentfer 	}
1048825eb42bSJan Lentfer 	if (rr_class == 0) {
1049825eb42bSJan Lentfer 		rr_class = LDNS_RR_CLASS_IN;
1050825eb42bSJan Lentfer 	}
1051825eb42bSJan Lentfer 
1052825eb42bSJan Lentfer 	if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
1053825eb42bSJan Lentfer 		ldns_rr_set_owner(question_rr, name_rdf);
1054825eb42bSJan Lentfer 		ldns_rr_set_type(question_rr, rr_type);
1055825eb42bSJan Lentfer 		ldns_rr_set_class(question_rr, rr_class);
1056825eb42bSJan Lentfer                 ldns_rr_set_question(question_rr, true);
1057825eb42bSJan Lentfer 
1058825eb42bSJan Lentfer 		ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
1059825eb42bSJan Lentfer 	} else {
1060825eb42bSJan Lentfer 		ldns_rr_free(question_rr);
1061825eb42bSJan Lentfer 		ldns_pkt_free(packet);
1062825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
1063825eb42bSJan Lentfer 	}
1064825eb42bSJan Lentfer 
10655340022aSzrj 	if (authsoa_rr) {
10665340022aSzrj 		ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr);
1067d1b2b5caSJohn Marino 	}
1068825eb42bSJan Lentfer 
1069d1b2b5caSJohn Marino 	packet->_tsig_rr = NULL;
1070825eb42bSJan Lentfer 	ldns_pkt_set_answerfrom(packet, NULL);
1071825eb42bSJan Lentfer 	if (p) {
1072825eb42bSJan Lentfer 		*p = packet;
1073825eb42bSJan Lentfer 		return LDNS_STATUS_OK;
1074825eb42bSJan Lentfer 	} else {
1075d1b2b5caSJohn Marino 		ldns_pkt_free(packet);
1076825eb42bSJan Lentfer 		return LDNS_STATUS_NULL;
1077825eb42bSJan Lentfer 	}
1078825eb42bSJan Lentfer }
1079825eb42bSJan Lentfer 
10805340022aSzrj ldns_status
ldns_pkt_query_new_frm_str(ldns_pkt ** p,const char * name,ldns_rr_type rr_type,ldns_rr_class rr_class,uint16_t flags)10815340022aSzrj ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name,
10825340022aSzrj 	ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags)
10835340022aSzrj {
10845340022aSzrj 	return ldns_pkt_query_new_frm_str_internal(p, name, rr_type,
10855340022aSzrj 		rr_class, flags, NULL);
10865340022aSzrj }
10875340022aSzrj 
10885340022aSzrj ldns_status
ldns_pkt_ixfr_request_new_frm_str(ldns_pkt ** p,const char * name,ldns_rr_class rr_class,uint16_t flags,ldns_rr * soa)10895340022aSzrj ldns_pkt_ixfr_request_new_frm_str(ldns_pkt **p, const char *name,
10905340022aSzrj 	ldns_rr_class rr_class, uint16_t flags, ldns_rr *soa)
10915340022aSzrj {
10925340022aSzrj 	ldns_rr* authsoa_rr = soa;
10935340022aSzrj 	if (!authsoa_rr) {
10945340022aSzrj 		ldns_rdf *name_rdf;
10955340022aSzrj 		if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
10965340022aSzrj 			authsoa_rr = ldns_pkt_authsoa(name_rdf, rr_class);
10975340022aSzrj 		}
10985340022aSzrj 		ldns_rdf_free(name_rdf);
10995340022aSzrj 	}
11005340022aSzrj 	return ldns_pkt_query_new_frm_str_internal(p, name, LDNS_RR_TYPE_IXFR,
11015340022aSzrj 		rr_class, flags, authsoa_rr);
11025340022aSzrj }
11035340022aSzrj 
11045340022aSzrj static ldns_pkt *
ldns_pkt_query_new_internal(ldns_rdf * rr_name,ldns_rr_type rr_type,ldns_rr_class rr_class,uint16_t flags,ldns_rr * authsoa_rr)11055340022aSzrj ldns_pkt_query_new_internal(ldns_rdf *rr_name, ldns_rr_type rr_type,
11065340022aSzrj 	ldns_rr_class rr_class,	uint16_t flags, ldns_rr* authsoa_rr)
1107825eb42bSJan Lentfer {
1108825eb42bSJan Lentfer 	ldns_pkt *packet;
1109825eb42bSJan Lentfer 	ldns_rr *question_rr;
1110825eb42bSJan Lentfer 
1111825eb42bSJan Lentfer 	packet = ldns_pkt_new();
1112825eb42bSJan Lentfer 	if (!packet) {
1113825eb42bSJan Lentfer 		return NULL;
1114825eb42bSJan Lentfer 	}
1115825eb42bSJan Lentfer 
1116825eb42bSJan Lentfer 	if (!ldns_pkt_set_flags(packet, flags)) {
1117825eb42bSJan Lentfer 		return NULL;
1118825eb42bSJan Lentfer 	}
1119825eb42bSJan Lentfer 
1120825eb42bSJan Lentfer 	question_rr = ldns_rr_new();
1121825eb42bSJan Lentfer 	if (!question_rr) {
1122d1b2b5caSJohn Marino 		ldns_pkt_free(packet);
1123825eb42bSJan Lentfer 		return NULL;
1124825eb42bSJan Lentfer 	}
1125825eb42bSJan Lentfer 
1126825eb42bSJan Lentfer 	if (rr_type == 0) {
1127825eb42bSJan Lentfer 		rr_type = LDNS_RR_TYPE_A;
1128825eb42bSJan Lentfer 	}
1129825eb42bSJan Lentfer 	if (rr_class == 0) {
1130825eb42bSJan Lentfer 		rr_class = LDNS_RR_CLASS_IN;
1131825eb42bSJan Lentfer 	}
1132825eb42bSJan Lentfer 
1133825eb42bSJan Lentfer 	ldns_rr_set_owner(question_rr, rr_name);
1134825eb42bSJan Lentfer 	ldns_rr_set_type(question_rr, rr_type);
1135825eb42bSJan Lentfer 	ldns_rr_set_class(question_rr, rr_class);
1136825eb42bSJan Lentfer         ldns_rr_set_question(question_rr, true);
1137825eb42bSJan Lentfer 	ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
1138825eb42bSJan Lentfer 
11395340022aSzrj 	if (authsoa_rr) {
11405340022aSzrj 		ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr);
1141d1b2b5caSJohn Marino 	}
1142d1b2b5caSJohn Marino 
1143d1b2b5caSJohn Marino 	packet->_tsig_rr = NULL;
1144825eb42bSJan Lentfer 	return packet;
1145825eb42bSJan Lentfer }
1146825eb42bSJan Lentfer 
11475340022aSzrj ldns_pkt *
ldns_pkt_query_new(ldns_rdf * rr_name,ldns_rr_type rr_type,ldns_rr_class rr_class,uint16_t flags)11485340022aSzrj ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type,
11495340022aSzrj 	ldns_rr_class rr_class,	uint16_t flags)
11505340022aSzrj {
11515340022aSzrj 	return ldns_pkt_query_new_internal(rr_name, rr_type,
11525340022aSzrj 		rr_class, flags, NULL);
11535340022aSzrj }
11545340022aSzrj 
11555340022aSzrj ldns_pkt *
ldns_pkt_ixfr_request_new(ldns_rdf * rr_name,ldns_rr_class rr_class,uint16_t flags,ldns_rr * soa)11565340022aSzrj ldns_pkt_ixfr_request_new(ldns_rdf *rr_name, ldns_rr_class rr_class,
11575340022aSzrj 	uint16_t flags, ldns_rr* soa)
11585340022aSzrj {
11595340022aSzrj 	ldns_rr* authsoa_rr = soa;
11605340022aSzrj 	if (!authsoa_rr) {
11615340022aSzrj 		authsoa_rr = ldns_pkt_authsoa(rr_name, rr_class);
11625340022aSzrj 	}
11635340022aSzrj 	return ldns_pkt_query_new_internal(rr_name, LDNS_RR_TYPE_IXFR,
11645340022aSzrj 		rr_class, flags, authsoa_rr);
11655340022aSzrj }
11665340022aSzrj 
1167825eb42bSJan Lentfer ldns_pkt_type
ldns_pkt_reply_type(const ldns_pkt * p)11685340022aSzrj ldns_pkt_reply_type(const ldns_pkt *p)
1169825eb42bSJan Lentfer {
1170825eb42bSJan Lentfer 	ldns_rr_list *tmp;
1171825eb42bSJan Lentfer 
1172825eb42bSJan Lentfer 	if (!p) {
1173825eb42bSJan Lentfer 		return LDNS_PACKET_UNKNOWN;
1174825eb42bSJan Lentfer 	}
1175825eb42bSJan Lentfer 
1176825eb42bSJan Lentfer 	if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NXDOMAIN) {
1177825eb42bSJan Lentfer 		return LDNS_PACKET_NXDOMAIN;
1178825eb42bSJan Lentfer 	}
1179825eb42bSJan Lentfer 
1180825eb42bSJan Lentfer 	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_arcount(p) == 0
1181825eb42bSJan Lentfer 			&& ldns_pkt_nscount(p) == 1) {
1182825eb42bSJan Lentfer 
1183825eb42bSJan Lentfer 		/* check for SOA */
1184825eb42bSJan Lentfer 		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_SOA,
1185825eb42bSJan Lentfer 					LDNS_SECTION_AUTHORITY);
1186825eb42bSJan Lentfer 		if (tmp) {
1187825eb42bSJan Lentfer 			ldns_rr_list_deep_free(tmp);
1188825eb42bSJan Lentfer 			return LDNS_PACKET_NODATA;
1189825eb42bSJan Lentfer 		} else {
1190825eb42bSJan Lentfer 			/* I have no idea ... */
1191825eb42bSJan Lentfer 		}
1192825eb42bSJan Lentfer 	}
1193825eb42bSJan Lentfer 
1194825eb42bSJan Lentfer 	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_nscount(p) > 0) {
1195825eb42bSJan Lentfer 		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS,
1196825eb42bSJan Lentfer 		                               LDNS_SECTION_AUTHORITY);
1197825eb42bSJan Lentfer 		if (tmp) {
1198825eb42bSJan Lentfer 			/* there are nameservers here */
1199825eb42bSJan Lentfer 			ldns_rr_list_deep_free(tmp);
1200825eb42bSJan Lentfer 			return LDNS_PACKET_REFERRAL;
1201825eb42bSJan Lentfer 		} else {
1202825eb42bSJan Lentfer 			/* I have no idea */
1203825eb42bSJan Lentfer 		}
1204825eb42bSJan Lentfer 		ldns_rr_list_deep_free(tmp);
1205825eb42bSJan Lentfer 	}
1206825eb42bSJan Lentfer 
1207825eb42bSJan Lentfer 	/* if we cannot determine the packet type, we say it's an
1208825eb42bSJan Lentfer 	 * answer...
1209825eb42bSJan Lentfer 	 */
1210825eb42bSJan Lentfer 	return LDNS_PACKET_ANSWER;
1211825eb42bSJan Lentfer }
1212825eb42bSJan Lentfer 
1213825eb42bSJan Lentfer ldns_pkt *
ldns_pkt_clone(const ldns_pkt * pkt)12145340022aSzrj ldns_pkt_clone(const ldns_pkt *pkt)
1215825eb42bSJan Lentfer {
1216825eb42bSJan Lentfer 	ldns_pkt *new_pkt;
1217825eb42bSJan Lentfer 
1218825eb42bSJan Lentfer 	if (!pkt) {
1219825eb42bSJan Lentfer 		return NULL;
1220825eb42bSJan Lentfer 	}
1221825eb42bSJan Lentfer 	new_pkt = ldns_pkt_new();
1222825eb42bSJan Lentfer 
1223825eb42bSJan Lentfer 	ldns_pkt_set_id(new_pkt, ldns_pkt_id(pkt));
1224825eb42bSJan Lentfer 	ldns_pkt_set_qr(new_pkt, ldns_pkt_qr(pkt));
1225825eb42bSJan Lentfer 	ldns_pkt_set_aa(new_pkt, ldns_pkt_aa(pkt));
1226825eb42bSJan Lentfer 	ldns_pkt_set_tc(new_pkt, ldns_pkt_tc(pkt));
1227825eb42bSJan Lentfer 	ldns_pkt_set_rd(new_pkt, ldns_pkt_rd(pkt));
1228825eb42bSJan Lentfer 	ldns_pkt_set_cd(new_pkt, ldns_pkt_cd(pkt));
1229825eb42bSJan Lentfer 	ldns_pkt_set_ra(new_pkt, ldns_pkt_ra(pkt));
1230825eb42bSJan Lentfer 	ldns_pkt_set_ad(new_pkt, ldns_pkt_ad(pkt));
1231825eb42bSJan Lentfer 	ldns_pkt_set_opcode(new_pkt, ldns_pkt_get_opcode(pkt));
1232825eb42bSJan Lentfer 	ldns_pkt_set_rcode(new_pkt, ldns_pkt_get_rcode(pkt));
1233825eb42bSJan Lentfer 	ldns_pkt_set_qdcount(new_pkt, ldns_pkt_qdcount(pkt));
1234825eb42bSJan Lentfer 	ldns_pkt_set_ancount(new_pkt, ldns_pkt_ancount(pkt));
1235825eb42bSJan Lentfer 	ldns_pkt_set_nscount(new_pkt, ldns_pkt_nscount(pkt));
1236825eb42bSJan Lentfer 	ldns_pkt_set_arcount(new_pkt, ldns_pkt_arcount(pkt));
1237d1b2b5caSJohn Marino 	if (ldns_pkt_answerfrom(pkt))
1238d1b2b5caSJohn Marino 		ldns_pkt_set_answerfrom(new_pkt,
1239d1b2b5caSJohn Marino 			ldns_rdf_clone(ldns_pkt_answerfrom(pkt)));
12405340022aSzrj 	ldns_pkt_set_timestamp(new_pkt, ldns_pkt_timestamp(pkt));
1241825eb42bSJan Lentfer 	ldns_pkt_set_querytime(new_pkt, ldns_pkt_querytime(pkt));
1242825eb42bSJan Lentfer 	ldns_pkt_set_size(new_pkt, ldns_pkt_size(pkt));
1243ac996e71SJan Lentfer 	ldns_pkt_set_tsig(new_pkt, ldns_rr_clone(ldns_pkt_tsig(pkt)));
1244825eb42bSJan Lentfer 
1245825eb42bSJan Lentfer 	ldns_pkt_set_edns_udp_size(new_pkt, ldns_pkt_edns_udp_size(pkt));
1246825eb42bSJan Lentfer 	ldns_pkt_set_edns_extended_rcode(new_pkt,
1247825eb42bSJan Lentfer 		ldns_pkt_edns_extended_rcode(pkt));
1248825eb42bSJan Lentfer 	ldns_pkt_set_edns_version(new_pkt, ldns_pkt_edns_version(pkt));
12495340022aSzrj 	new_pkt->_edns_present = pkt->_edns_present;
1250825eb42bSJan Lentfer 	ldns_pkt_set_edns_z(new_pkt, ldns_pkt_edns_z(pkt));
1251825eb42bSJan Lentfer 	if(ldns_pkt_edns_data(pkt))
1252825eb42bSJan Lentfer 		ldns_pkt_set_edns_data(new_pkt,
1253825eb42bSJan Lentfer 			ldns_rdf_clone(ldns_pkt_edns_data(pkt)));
1254825eb42bSJan Lentfer 	ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt));
1255*ee791febSAntonio Huete Jimenez 	if (pkt->_edns_list)
1256*ee791febSAntonio Huete Jimenez 		ldns_pkt_set_edns_option_list(new_pkt,
1257*ee791febSAntonio Huete Jimenez 			ldns_edns_option_list_clone(pkt->_edns_list));
1258825eb42bSJan Lentfer 
1259825eb42bSJan Lentfer 	ldns_rr_list_deep_free(new_pkt->_question);
1260825eb42bSJan Lentfer 	ldns_rr_list_deep_free(new_pkt->_answer);
1261825eb42bSJan Lentfer 	ldns_rr_list_deep_free(new_pkt->_authority);
1262825eb42bSJan Lentfer 	ldns_rr_list_deep_free(new_pkt->_additional);
1263825eb42bSJan Lentfer 	new_pkt->_question = ldns_rr_list_clone(ldns_pkt_question(pkt));
1264825eb42bSJan Lentfer 	new_pkt->_answer = ldns_rr_list_clone(ldns_pkt_answer(pkt));
1265825eb42bSJan Lentfer 	new_pkt->_authority = ldns_rr_list_clone(ldns_pkt_authority(pkt));
1266825eb42bSJan Lentfer 	new_pkt->_additional = ldns_rr_list_clone(ldns_pkt_additional(pkt));
1267825eb42bSJan Lentfer 	return new_pkt;
1268825eb42bSJan Lentfer }
1269