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(ldns_pkt *packet,
254                         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_rdf_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, ldns_rr_list_rr(rrs, i));
277		}
278	}
279	return ret;
280}
281
282/* return only those rr that share a type */
283ldns_rr_list *
284ldns_pkt_rr_list_by_type(const ldns_pkt *packet,
285                         ldns_rr_type type,
286                         ldns_pkt_section sec)
287{
288	ldns_rr_list *rrs;
289	ldns_rr_list *new;
290	uint16_t i;
291
292	if(!packet) {
293		return NULL;
294	}
295
296	rrs = ldns_pkt_get_section_clone(packet, sec);
297	new = ldns_rr_list_new();
298
299	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
300		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i))) {
301			/* types match */
302			ldns_rr_list_push_rr(new,
303			                     ldns_rr_clone(
304			                     	ldns_rr_list_rr(rrs, i))
305					     );
306		}
307	}
308	ldns_rr_list_deep_free(rrs);
309
310	if (ldns_rr_list_rr_count(new) == 0) {
311		ldns_rr_list_free(new);
312		return NULL;
313	} else {
314		return new;
315	}
316}
317
318/* return only those rrs that share name and type */
319ldns_rr_list *
320ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet,
321                                  const ldns_rdf *ownername,
322                                  ldns_rr_type type,
323                                  ldns_pkt_section sec)
324{
325	ldns_rr_list *rrs;
326	ldns_rr_list *new;
327	ldns_rr_list *ret;
328	uint16_t i;
329
330	if(!packet) {
331		return NULL;
332	}
333
334	rrs = ldns_pkt_get_section_clone(packet, sec);
335	new = ldns_rr_list_new();
336	ret = NULL;
337
338	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
339		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i)) &&
340		    ldns_rdf_compare(ldns_rr_owner(ldns_rr_list_rr(rrs, i)),
341		                     ownername
342		                    ) == 0
343		   ) {
344			/* types match */
345			ldns_rr_list_push_rr(new, ldns_rr_clone(ldns_rr_list_rr(rrs, i)));
346			ret = new;
347		}
348	}
349	ldns_rr_list_deep_free(rrs);
350	if (!ret) {
351		ldns_rr_list_free(new);
352	}
353	return ret;
354}
355
356bool
357ldns_pkt_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
358{
359	bool result = false;
360
361	switch (sec) {
362	case LDNS_SECTION_QUESTION:
363		return ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
364	case LDNS_SECTION_ANSWER:
365		return ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr);
366	case LDNS_SECTION_AUTHORITY:
367		return ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr);
368	case LDNS_SECTION_ADDITIONAL:
369		return ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
370	case LDNS_SECTION_ANY:
371		result = ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
372	case LDNS_SECTION_ANY_NOQUESTION:
373		result = result
374		    || ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr)
375		    || ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr)
376		    || ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
377	}
378
379	return result;
380}
381
382static uint16_t
383ldns_pkt_section_count(const ldns_pkt *packet, ldns_pkt_section s)
384{
385	switch(s) {
386	case LDNS_SECTION_QUESTION:
387		return ldns_pkt_qdcount(packet);
388	case LDNS_SECTION_ANSWER:
389		return ldns_pkt_ancount(packet);
390	case LDNS_SECTION_AUTHORITY:
391		return ldns_pkt_nscount(packet);
392	case LDNS_SECTION_ADDITIONAL:
393		return ldns_pkt_arcount(packet);
394	case LDNS_SECTION_ANY:
395		return ldns_pkt_qdcount(packet) +
396			ldns_pkt_ancount(packet) +
397			ldns_pkt_nscount(packet) +
398			ldns_pkt_arcount(packet);
399	case LDNS_SECTION_ANY_NOQUESTION:
400		return ldns_pkt_ancount(packet) +
401			ldns_pkt_nscount(packet) +
402			ldns_pkt_arcount(packet);
403	default:
404		return 0;
405	}
406}
407
408bool
409ldns_pkt_empty(ldns_pkt *p)
410{
411	if (!p) {
412		return true; /* NULL is empty? */
413	}
414	if (ldns_pkt_section_count(p, LDNS_SECTION_ANY) > 0) {
415		return false;
416	} else {
417		return true;
418    }
419}
420
421
422ldns_rr_list *
423ldns_pkt_get_section_clone(const ldns_pkt *packet, ldns_pkt_section s)
424{
425	switch(s) {
426	case LDNS_SECTION_QUESTION:
427		return ldns_rr_list_clone(ldns_pkt_question(packet));
428	case LDNS_SECTION_ANSWER:
429		return ldns_rr_list_clone(ldns_pkt_answer(packet));
430	case LDNS_SECTION_AUTHORITY:
431		return ldns_rr_list_clone(ldns_pkt_authority(packet));
432	case LDNS_SECTION_ADDITIONAL:
433		return ldns_rr_list_clone(ldns_pkt_additional(packet));
434	case LDNS_SECTION_ANY:
435		/* these are already clones */
436		return ldns_pkt_all(packet);
437	case LDNS_SECTION_ANY_NOQUESTION:
438		return ldns_pkt_all_noquestion(packet);
439	default:
440		return NULL;
441	}
442}
443
444ldns_rr *ldns_pkt_tsig(const ldns_pkt *pkt) {
445	return pkt->_tsig_rr;
446}
447
448/* write */
449void
450ldns_pkt_set_id(ldns_pkt *packet, uint16_t id)
451{
452	packet->_header->_id = id;
453}
454
455void
456ldns_pkt_set_random_id(ldns_pkt *packet)
457{
458	uint16_t rid = ldns_get_random();
459	ldns_pkt_set_id(packet, rid);
460}
461
462
463void
464ldns_pkt_set_qr(ldns_pkt *packet, bool qr)
465{
466	packet->_header->_qr = qr;
467}
468
469void
470ldns_pkt_set_aa(ldns_pkt *packet, bool aa)
471{
472	packet->_header->_aa = aa;
473}
474
475void
476ldns_pkt_set_tc(ldns_pkt *packet, bool tc)
477{
478	packet->_header->_tc = tc;
479}
480
481void
482ldns_pkt_set_rd(ldns_pkt *packet, bool rd)
483{
484	packet->_header->_rd = rd;
485}
486
487void
488ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr)
489{
490	p->_additional = rr;
491}
492
493void
494ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr)
495{
496	p->_question = rr;
497}
498
499void
500ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr)
501{
502	p->_answer = rr;
503}
504
505void
506ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr)
507{
508	p->_authority = rr;
509}
510
511void
512ldns_pkt_set_cd(ldns_pkt *packet, bool cd)
513{
514	packet->_header->_cd = cd;
515}
516
517void
518ldns_pkt_set_ra(ldns_pkt *packet, bool ra)
519{
520	packet->_header->_ra = ra;
521}
522
523void
524ldns_pkt_set_ad(ldns_pkt *packet, bool ad)
525{
526	packet->_header->_ad = ad;
527}
528
529void
530ldns_pkt_set_opcode(ldns_pkt *packet, ldns_pkt_opcode opcode)
531{
532	packet->_header->_opcode = opcode;
533}
534
535void
536ldns_pkt_set_rcode(ldns_pkt *packet, uint8_t rcode)
537{
538	packet->_header->_rcode = rcode;
539}
540
541void
542ldns_pkt_set_qdcount(ldns_pkt *packet, uint16_t qdcount)
543{
544	packet->_header->_qdcount = qdcount;
545}
546
547void
548ldns_pkt_set_ancount(ldns_pkt *packet, uint16_t ancount)
549{
550	packet->_header->_ancount = ancount;
551}
552
553void
554ldns_pkt_set_nscount(ldns_pkt *packet, uint16_t nscount)
555{
556	packet->_header->_nscount = nscount;
557}
558
559void
560ldns_pkt_set_arcount(ldns_pkt *packet, uint16_t arcount)
561{
562	packet->_header->_arcount = arcount;
563}
564
565void
566ldns_pkt_set_querytime(ldns_pkt *packet, uint32_t time)
567{
568	packet->_querytime = time;
569}
570
571void
572ldns_pkt_set_answerfrom(ldns_pkt *packet, ldns_rdf *answerfrom)
573{
574	packet->_answerfrom = answerfrom;
575}
576
577void
578ldns_pkt_set_timestamp(ldns_pkt *packet, struct timeval timeval)
579{
580	packet->timestamp.tv_sec = timeval.tv_sec;
581	packet->timestamp.tv_usec = timeval.tv_usec;
582}
583
584void
585ldns_pkt_set_size(ldns_pkt *packet, size_t s)
586{
587	packet->_size = s;
588}
589
590void
591ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s)
592{
593	packet->_edns_udp_size = s;
594}
595
596void
597ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c)
598{
599	packet->_edns_extended_rcode = c;
600}
601
602void
603ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v)
604{
605	packet->_edns_version = v;
606}
607
608void
609ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z)
610{
611	packet->_edns_z = z;
612}
613
614void
615ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data)
616{
617	packet->_edns_data = data;
618}
619
620void
621ldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count)
622{
623	switch(s) {
624		case LDNS_SECTION_QUESTION:
625			ldns_pkt_set_qdcount(packet, count);
626			break;
627		case LDNS_SECTION_ANSWER:
628			ldns_pkt_set_ancount(packet, count);
629			break;
630		case LDNS_SECTION_AUTHORITY:
631			ldns_pkt_set_nscount(packet, count);
632			break;
633		case LDNS_SECTION_ADDITIONAL:
634			ldns_pkt_set_arcount(packet, count);
635			break;
636		case LDNS_SECTION_ANY:
637		case LDNS_SECTION_ANY_NOQUESTION:
638			break;
639	}
640}
641
642void ldns_pkt_set_tsig(ldns_pkt *pkt, ldns_rr *rr)
643{
644	pkt->_tsig_rr = rr;
645}
646
647bool
648ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr)
649{
650	switch(section) {
651		case LDNS_SECTION_QUESTION:
652			if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) {
653				return false;
654			}
655			ldns_pkt_set_qdcount(packet, ldns_pkt_qdcount(packet) + 1);
656			break;
657		case LDNS_SECTION_ANSWER:
658			if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) {
659				return false;
660			}
661			ldns_pkt_set_ancount(packet, ldns_pkt_ancount(packet) + 1);
662			break;
663		case LDNS_SECTION_AUTHORITY:
664			if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) {
665				return false;
666			}
667			ldns_pkt_set_nscount(packet, ldns_pkt_nscount(packet) + 1);
668			break;
669		case LDNS_SECTION_ADDITIONAL:
670			if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) {
671				return false;
672			}
673			ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + 1);
674			break;
675		case LDNS_SECTION_ANY:
676		case LDNS_SECTION_ANY_NOQUESTION:
677			/* shouldn't this error? */
678			break;
679	}
680	return true;
681}
682
683bool
684ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
685{
686
687	/* check to see if its there */
688	if (ldns_pkt_rr(pkt, sec, rr)) {
689		/* already there */
690		return false;
691	}
692	return ldns_pkt_push_rr(pkt, sec, rr);
693}
694
695bool
696ldns_pkt_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
697{
698	size_t i;
699	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
700		if (!ldns_pkt_push_rr(p, s, ldns_rr_list_rr(list, i))) {
701			return false;
702		}
703	}
704	return true;
705}
706
707bool
708ldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
709{
710	size_t i;
711	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
712		if (!ldns_pkt_safe_push_rr(p, s, ldns_rr_list_rr(list, i))) {
713			return false;
714		}
715	}
716	return true;
717}
718
719bool
720ldns_pkt_edns(const ldns_pkt *pkt) {
721	return (ldns_pkt_edns_udp_size(pkt) > 0 ||
722		ldns_pkt_edns_extended_rcode(pkt) > 0 ||
723		ldns_pkt_edns_data(pkt) ||
724		ldns_pkt_edns_do(pkt)
725	       );
726}
727
728
729/* Create/destroy/convert functions
730 */
731ldns_pkt *
732ldns_pkt_new(void)
733{
734	ldns_pkt *packet;
735	packet = LDNS_MALLOC(ldns_pkt);
736	if (!packet) {
737		return NULL;
738	}
739
740	packet->_header = LDNS_MALLOC(ldns_hdr);
741	if (!packet->_header) {
742		LDNS_FREE(packet);
743		return NULL;
744	}
745
746	packet->_question = ldns_rr_list_new();
747	packet->_answer = ldns_rr_list_new();
748	packet->_authority = ldns_rr_list_new();
749	packet->_additional = ldns_rr_list_new();
750
751	/* default everything to false */
752	ldns_pkt_set_qr(packet, false);
753	ldns_pkt_set_aa(packet, false);
754	ldns_pkt_set_tc(packet, false);
755	ldns_pkt_set_rd(packet, false);
756	ldns_pkt_set_ra(packet, false);
757	ldns_pkt_set_ad(packet, false);
758	ldns_pkt_set_cd(packet, false);
759
760	ldns_pkt_set_opcode(packet, LDNS_PACKET_QUERY);
761	ldns_pkt_set_rcode(packet, 0);
762	ldns_pkt_set_id(packet, 0);
763	ldns_pkt_set_size(packet, 0);
764	ldns_pkt_set_querytime(packet, 0);
765	memset(&packet->timestamp, 0, sizeof(packet->timestamp));
766	ldns_pkt_set_answerfrom(packet, NULL);
767	ldns_pkt_set_section_count(packet, LDNS_SECTION_QUESTION, 0);
768	ldns_pkt_set_section_count(packet, LDNS_SECTION_ANSWER, 0);
769	ldns_pkt_set_section_count(packet, LDNS_SECTION_AUTHORITY, 0);
770	ldns_pkt_set_section_count(packet, LDNS_SECTION_ADDITIONAL, 0);
771
772	ldns_pkt_set_edns_udp_size(packet, 0);
773	ldns_pkt_set_edns_extended_rcode(packet, 0);
774	ldns_pkt_set_edns_version(packet, 0);
775	ldns_pkt_set_edns_z(packet, 0);
776	ldns_pkt_set_edns_data(packet, NULL);
777
778	ldns_pkt_set_tsig(packet, NULL);
779
780	return packet;
781}
782
783void
784ldns_pkt_free(ldns_pkt *packet)
785{
786	if (packet) {
787		LDNS_FREE(packet->_header);
788		ldns_rr_list_deep_free(packet->_question);
789		ldns_rr_list_deep_free(packet->_answer);
790		ldns_rr_list_deep_free(packet->_authority);
791		ldns_rr_list_deep_free(packet->_additional);
792		ldns_rr_free(packet->_tsig_rr);
793		ldns_rdf_deep_free(packet->_edns_data);
794		ldns_rdf_deep_free(packet->_answerfrom);
795		LDNS_FREE(packet);
796	}
797}
798
799bool
800ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags)
801{
802	if (!packet) {
803		return false;
804	}
805	if ((flags & LDNS_QR) == LDNS_QR) {
806		ldns_pkt_set_qr(packet, true);
807	}
808	if ((flags & LDNS_AA) == LDNS_AA) {
809		ldns_pkt_set_aa(packet, true);
810	}
811	if ((flags & LDNS_RD) == LDNS_RD) {
812		ldns_pkt_set_rd(packet, true);
813	}
814	if ((flags & LDNS_TC) == LDNS_TC) {
815		ldns_pkt_set_tc(packet, true);
816	}
817	if ((flags & LDNS_CD) == LDNS_CD) {
818		ldns_pkt_set_cd(packet, true);
819	}
820	if ((flags & LDNS_RA) == LDNS_RA) {
821		ldns_pkt_set_ra(packet, true);
822	}
823	if ((flags & LDNS_AD) == LDNS_AD) {
824		ldns_pkt_set_ad(packet, true);
825	}
826	return true;
827}
828
829
830static ldns_status
831ldns_pkt_add_authsoa(ldns_pkt* packet, ldns_rdf* rr_name, ldns_rr_class rr_class)
832{
833	ldns_rr* soa_rr = ldns_rr_new();
834	ldns_rdf *owner_rdf;
835	ldns_rdf *mname_rdf;
836	ldns_rdf *rname_rdf;
837	ldns_rdf *serial_rdf;
838	ldns_rdf *refresh_rdf;
839	ldns_rdf *retry_rdf;
840	ldns_rdf *expire_rdf;
841	ldns_rdf *minimum_rdf;
842
843	if (!soa_rr) {
844		return LDNS_STATUS_MEM_ERR;
845	}
846	owner_rdf = ldns_rdf_clone(rr_name);
847	if (!owner_rdf) {
848		ldns_rr_free(soa_rr);
849		return LDNS_STATUS_MEM_ERR;
850	}
851
852	ldns_rr_set_owner(soa_rr, owner_rdf);
853	ldns_rr_set_type(soa_rr, LDNS_RR_TYPE_SOA);
854	ldns_rr_set_class(soa_rr, rr_class);
855	ldns_rr_set_question(soa_rr, false);
856
857	if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) {
858		ldns_rr_free(soa_rr);
859		return LDNS_STATUS_MEM_ERR;
860	} else {
861		ldns_rr_push_rdf(soa_rr, mname_rdf);
862	}
863	if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) {
864		ldns_rr_free(soa_rr);
865		return LDNS_STATUS_MEM_ERR;
866	} else {
867		ldns_rr_push_rdf(soa_rr, rname_rdf);
868	}
869	serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
870	if (!serial_rdf) {
871		ldns_rr_free(soa_rr);
872		return LDNS_STATUS_MEM_ERR;
873	} else {
874		ldns_rr_push_rdf(soa_rr, serial_rdf);
875	}
876	refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
877	if (!refresh_rdf) {
878		ldns_rr_free(soa_rr);
879		return LDNS_STATUS_MEM_ERR;
880	} else {
881		ldns_rr_push_rdf(soa_rr, refresh_rdf);
882	}
883	retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
884	if (!retry_rdf) {
885		ldns_rr_free(soa_rr);
886		return LDNS_STATUS_MEM_ERR;
887	} else {
888		ldns_rr_push_rdf(soa_rr, retry_rdf);
889	}
890	expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
891	if (!expire_rdf) {
892		ldns_rr_free(soa_rr);
893		return LDNS_STATUS_MEM_ERR;
894	} else {
895		ldns_rr_push_rdf(soa_rr, expire_rdf);
896	}
897	minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
898	if (!minimum_rdf) {
899		ldns_rr_free(soa_rr);
900		return LDNS_STATUS_MEM_ERR;
901	} else {
902		ldns_rr_push_rdf(soa_rr, minimum_rdf);
903	}
904	ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, soa_rr);
905	return LDNS_STATUS_OK;
906}
907
908
909ldns_status
910ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name, ldns_rr_type rr_type,
911		ldns_rr_class rr_class, uint16_t flags)
912{
913	ldns_pkt *packet;
914	ldns_rr *question_rr;
915	ldns_rdf *name_rdf;
916
917	packet = ldns_pkt_new();
918	if (!packet) {
919		return LDNS_STATUS_MEM_ERR;
920	}
921
922	if (!ldns_pkt_set_flags(packet, flags)) {
923		return LDNS_STATUS_ERR;
924	}
925
926	question_rr = ldns_rr_new();
927	if (!question_rr) {
928		return LDNS_STATUS_MEM_ERR;
929	}
930
931	if (rr_type == 0) {
932		rr_type = LDNS_RR_TYPE_A;
933	}
934	if (rr_class == 0) {
935		rr_class = LDNS_RR_CLASS_IN;
936	}
937
938	if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
939		ldns_rr_set_owner(question_rr, name_rdf);
940		ldns_rr_set_type(question_rr, rr_type);
941		ldns_rr_set_class(question_rr, rr_class);
942                ldns_rr_set_question(question_rr, true);
943
944		ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
945	} else {
946		ldns_rr_free(question_rr);
947		ldns_pkt_free(packet);
948		return LDNS_STATUS_ERR;
949	}
950
951	/** IXFR? */
952	if (rr_type == LDNS_RR_TYPE_IXFR) {
953		if (ldns_pkt_add_authsoa(packet, name_rdf, rr_class) != LDNS_STATUS_OK) {
954			ldns_pkt_free(packet);
955			return LDNS_STATUS_ERR;
956		}
957	}
958
959	packet->_tsig_rr = NULL;
960	ldns_pkt_set_answerfrom(packet, NULL);
961	if (p) {
962		*p = packet;
963		return LDNS_STATUS_OK;
964	} else {
965		ldns_pkt_free(packet);
966		return LDNS_STATUS_NULL;
967	}
968}
969
970ldns_pkt *
971ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class,
972		uint16_t flags)
973{
974	ldns_pkt *packet;
975	ldns_rr *question_rr;
976
977	packet = ldns_pkt_new();
978	if (!packet) {
979		return NULL;
980	}
981
982	if (!ldns_pkt_set_flags(packet, flags)) {
983		return NULL;
984	}
985
986	question_rr = ldns_rr_new();
987	if (!question_rr) {
988		ldns_pkt_free(packet);
989		return NULL;
990	}
991
992	if (rr_type == 0) {
993		rr_type = LDNS_RR_TYPE_A;
994	}
995	if (rr_class == 0) {
996		rr_class = LDNS_RR_CLASS_IN;
997	}
998
999	ldns_rr_set_owner(question_rr, rr_name);
1000	ldns_rr_set_type(question_rr, rr_type);
1001	ldns_rr_set_class(question_rr, rr_class);
1002        ldns_rr_set_question(question_rr, true);
1003	ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
1004
1005	/** IXFR? */
1006	if (rr_type == LDNS_RR_TYPE_IXFR) {
1007		if (ldns_pkt_add_authsoa(packet, rr_name, rr_class) != LDNS_STATUS_OK) {
1008			ldns_pkt_free(packet);
1009			return NULL;
1010		}
1011	}
1012
1013	packet->_tsig_rr = NULL;
1014	return packet;
1015}
1016
1017ldns_pkt_type
1018ldns_pkt_reply_type(ldns_pkt *p)
1019{
1020	ldns_rr_list *tmp;
1021
1022	if (!p) {
1023		return LDNS_PACKET_UNKNOWN;
1024	}
1025
1026	if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NXDOMAIN) {
1027		return LDNS_PACKET_NXDOMAIN;
1028	}
1029
1030	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_arcount(p) == 0
1031			&& ldns_pkt_nscount(p) == 1) {
1032
1033		/* check for SOA */
1034		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_SOA,
1035					LDNS_SECTION_AUTHORITY);
1036		if (tmp) {
1037			ldns_rr_list_deep_free(tmp);
1038			return LDNS_PACKET_NODATA;
1039		} else {
1040			/* I have no idea ... */
1041		}
1042	}
1043
1044	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_nscount(p) > 0) {
1045		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS,
1046		                               LDNS_SECTION_AUTHORITY);
1047		if (tmp) {
1048			/* there are nameservers here */
1049			ldns_rr_list_deep_free(tmp);
1050			return LDNS_PACKET_REFERRAL;
1051		} else {
1052			/* I have no idea */
1053		}
1054		ldns_rr_list_deep_free(tmp);
1055	}
1056
1057	/* if we cannot determine the packet type, we say it's an
1058	 * answer...
1059	 */
1060	return LDNS_PACKET_ANSWER;
1061}
1062
1063ldns_pkt *
1064ldns_pkt_clone(ldns_pkt *pkt)
1065{
1066	ldns_pkt *new_pkt;
1067
1068	if (!pkt) {
1069		return NULL;
1070	}
1071	new_pkt = ldns_pkt_new();
1072
1073	ldns_pkt_set_id(new_pkt, ldns_pkt_id(pkt));
1074	ldns_pkt_set_qr(new_pkt, ldns_pkt_qr(pkt));
1075	ldns_pkt_set_aa(new_pkt, ldns_pkt_aa(pkt));
1076	ldns_pkt_set_tc(new_pkt, ldns_pkt_tc(pkt));
1077	ldns_pkt_set_rd(new_pkt, ldns_pkt_rd(pkt));
1078	ldns_pkt_set_cd(new_pkt, ldns_pkt_cd(pkt));
1079	ldns_pkt_set_ra(new_pkt, ldns_pkt_ra(pkt));
1080	ldns_pkt_set_ad(new_pkt, ldns_pkt_ad(pkt));
1081	ldns_pkt_set_opcode(new_pkt, ldns_pkt_get_opcode(pkt));
1082	ldns_pkt_set_rcode(new_pkt, ldns_pkt_get_rcode(pkt));
1083	ldns_pkt_set_qdcount(new_pkt, ldns_pkt_qdcount(pkt));
1084	ldns_pkt_set_ancount(new_pkt, ldns_pkt_ancount(pkt));
1085	ldns_pkt_set_nscount(new_pkt, ldns_pkt_nscount(pkt));
1086	ldns_pkt_set_arcount(new_pkt, ldns_pkt_arcount(pkt));
1087	if (ldns_pkt_answerfrom(pkt))
1088		ldns_pkt_set_answerfrom(new_pkt,
1089			ldns_rdf_clone(ldns_pkt_answerfrom(pkt)));
1090	ldns_pkt_set_querytime(new_pkt, ldns_pkt_querytime(pkt));
1091	ldns_pkt_set_size(new_pkt, ldns_pkt_size(pkt));
1092	ldns_pkt_set_tsig(new_pkt, ldns_rr_clone(ldns_pkt_tsig(pkt)));
1093
1094	ldns_pkt_set_edns_udp_size(new_pkt, ldns_pkt_edns_udp_size(pkt));
1095	ldns_pkt_set_edns_extended_rcode(new_pkt,
1096		ldns_pkt_edns_extended_rcode(pkt));
1097	ldns_pkt_set_edns_version(new_pkt, ldns_pkt_edns_version(pkt));
1098	ldns_pkt_set_edns_z(new_pkt, ldns_pkt_edns_z(pkt));
1099	if(ldns_pkt_edns_data(pkt))
1100		ldns_pkt_set_edns_data(new_pkt,
1101			ldns_rdf_clone(ldns_pkt_edns_data(pkt)));
1102	ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt));
1103
1104	ldns_rr_list_deep_free(new_pkt->_question);
1105	ldns_rr_list_deep_free(new_pkt->_answer);
1106	ldns_rr_list_deep_free(new_pkt->_authority);
1107	ldns_rr_list_deep_free(new_pkt->_additional);
1108	new_pkt->_question = ldns_rr_list_clone(ldns_pkt_question(pkt));
1109	new_pkt->_answer = ldns_rr_list_clone(ldns_pkt_answer(pkt));
1110	new_pkt->_authority = ldns_rr_list_clone(ldns_pkt_authority(pkt));
1111	new_pkt->_additional = ldns_rr_list_clone(ldns_pkt_additional(pkt));
1112	return new_pkt;
1113}
1114