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