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