xref: /freebsd/contrib/ldns/packet.c (revision 8d20be1e22095c27faf8fe8b2f0d089739cc742e)
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 */
32 ldns_lookup_table ldns_edns_flags[] = {
33 	{ 3600, "do"},
34 	{ 0, NULL}
35 };
36 
37 /* read */
38 uint16_t
39 ldns_pkt_id(const ldns_pkt *packet)
40 {
41 	return packet->_header->_id;
42 }
43 
44 bool
45 ldns_pkt_qr(const ldns_pkt *packet)
46 {
47 	return packet->_header->_qr;
48 }
49 
50 bool
51 ldns_pkt_aa(const ldns_pkt *packet)
52 {
53 	return packet->_header->_aa;
54 }
55 
56 bool
57 ldns_pkt_tc(const ldns_pkt *packet)
58 {
59 	return packet->_header->_tc;
60 }
61 
62 bool
63 ldns_pkt_rd(const ldns_pkt *packet)
64 {
65 	return packet->_header->_rd;
66 }
67 
68 bool
69 ldns_pkt_cd(const ldns_pkt *packet)
70 {
71 	return packet->_header->_cd;
72 }
73 
74 bool
75 ldns_pkt_ra(const ldns_pkt *packet)
76 {
77 	return packet->_header->_ra;
78 }
79 
80 bool
81 ldns_pkt_ad(const ldns_pkt *packet)
82 {
83 	return packet->_header->_ad;
84 }
85 
86 ldns_pkt_opcode
87 ldns_pkt_get_opcode(const ldns_pkt *packet)
88 {
89 	return packet->_header->_opcode;
90 }
91 
92 ldns_pkt_rcode
93 ldns_pkt_get_rcode(const ldns_pkt *packet)
94 {
95 	return packet->_header->_rcode;
96 }
97 
98 uint16_t
99 ldns_pkt_qdcount(const ldns_pkt *packet)
100 {
101 	return packet->_header->_qdcount;
102 }
103 
104 uint16_t
105 ldns_pkt_ancount(const ldns_pkt *packet)
106 {
107 	return packet->_header->_ancount;
108 }
109 
110 uint16_t
111 ldns_pkt_nscount(const ldns_pkt *packet)
112 {
113 	return packet->_header->_nscount;
114 }
115 
116 uint16_t
117 ldns_pkt_arcount(const ldns_pkt *packet)
118 {
119 	return packet->_header->_arcount;
120 }
121 
122 ldns_rr_list *
123 ldns_pkt_question(const ldns_pkt *packet)
124 {
125 	return packet->_question;
126 }
127 
128 ldns_rr_list *
129 ldns_pkt_answer(const ldns_pkt *packet)
130 {
131 	return packet->_answer;
132 }
133 
134 ldns_rr_list *
135 ldns_pkt_authority(const ldns_pkt *packet)
136 {
137 	return packet->_authority;
138 }
139 
140 ldns_rr_list *
141 ldns_pkt_additional(const ldns_pkt *packet)
142 {
143 	return packet->_additional;
144 }
145 
146 /* return ALL section concatenated */
147 ldns_rr_list *
148 ldns_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 
166 ldns_rr_list *
167 ldns_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 
181 size_t
182 ldns_pkt_size(const ldns_pkt *packet)
183 {
184 	return packet->_size;
185 }
186 
187 uint32_t
188 ldns_pkt_querytime(const ldns_pkt *packet)
189 {
190 	return packet->_querytime;
191 }
192 
193 ldns_rdf *
194 ldns_pkt_answerfrom(const ldns_pkt *packet)
195 {
196 	return packet->_answerfrom;
197 }
198 
199 struct timeval
200 ldns_pkt_timestamp(const ldns_pkt *packet)
201 {
202 	return packet->timestamp;
203 }
204 
205 uint16_t
206 ldns_pkt_edns_udp_size(const ldns_pkt *packet)
207 {
208 	return packet->_edns_udp_size;
209 }
210 
211 uint8_t
212 ldns_pkt_edns_extended_rcode(const ldns_pkt *packet)
213 {
214 	return packet->_edns_extended_rcode;
215 }
216 
217 uint8_t
218 ldns_pkt_edns_version(const ldns_pkt *packet)
219 {
220 	return packet->_edns_version;
221 }
222 
223 uint16_t
224 ldns_pkt_edns_z(const ldns_pkt *packet)
225 {
226 	return packet->_edns_z;
227 }
228 
229 bool
230 ldns_pkt_edns_do(const ldns_pkt *packet)
231 {
232 	return (packet->_edns_z & LDNS_EDNS_MASK_DO_BIT);
233 }
234 
235 void
236 ldns_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 
245 ldns_rdf *
246 ldns_pkt_edns_data(const ldns_pkt *packet)
247 {
248 	return packet->_edns_data;
249 }
250 
251 /* return only those rr that share the ownername */
252 ldns_rr_list *
253 ldns_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 */
283 ldns_rr_list *
284 ldns_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 */
319 ldns_rr_list *
320 ldns_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 
356 bool
357 ldns_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 
382 static uint16_t
383 ldns_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 
408 bool
409 ldns_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 
422 ldns_rr_list *
423 ldns_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 
444 ldns_rr *ldns_pkt_tsig(const ldns_pkt *pkt) {
445 	return pkt->_tsig_rr;
446 }
447 
448 /* write */
449 void
450 ldns_pkt_set_id(ldns_pkt *packet, uint16_t id)
451 {
452 	packet->_header->_id = id;
453 }
454 
455 void
456 ldns_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 
463 void
464 ldns_pkt_set_qr(ldns_pkt *packet, bool qr)
465 {
466 	packet->_header->_qr = qr;
467 }
468 
469 void
470 ldns_pkt_set_aa(ldns_pkt *packet, bool aa)
471 {
472 	packet->_header->_aa = aa;
473 }
474 
475 void
476 ldns_pkt_set_tc(ldns_pkt *packet, bool tc)
477 {
478 	packet->_header->_tc = tc;
479 }
480 
481 void
482 ldns_pkt_set_rd(ldns_pkt *packet, bool rd)
483 {
484 	packet->_header->_rd = rd;
485 }
486 
487 void
488 ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr)
489 {
490 	p->_additional = rr;
491 }
492 
493 void
494 ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr)
495 {
496 	p->_question = rr;
497 }
498 
499 void
500 ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr)
501 {
502 	p->_answer = rr;
503 }
504 
505 void
506 ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr)
507 {
508 	p->_authority = rr;
509 }
510 
511 void
512 ldns_pkt_set_cd(ldns_pkt *packet, bool cd)
513 {
514 	packet->_header->_cd = cd;
515 }
516 
517 void
518 ldns_pkt_set_ra(ldns_pkt *packet, bool ra)
519 {
520 	packet->_header->_ra = ra;
521 }
522 
523 void
524 ldns_pkt_set_ad(ldns_pkt *packet, bool ad)
525 {
526 	packet->_header->_ad = ad;
527 }
528 
529 void
530 ldns_pkt_set_opcode(ldns_pkt *packet, ldns_pkt_opcode opcode)
531 {
532 	packet->_header->_opcode = opcode;
533 }
534 
535 void
536 ldns_pkt_set_rcode(ldns_pkt *packet, uint8_t rcode)
537 {
538 	packet->_header->_rcode = rcode;
539 }
540 
541 void
542 ldns_pkt_set_qdcount(ldns_pkt *packet, uint16_t qdcount)
543 {
544 	packet->_header->_qdcount = qdcount;
545 }
546 
547 void
548 ldns_pkt_set_ancount(ldns_pkt *packet, uint16_t ancount)
549 {
550 	packet->_header->_ancount = ancount;
551 }
552 
553 void
554 ldns_pkt_set_nscount(ldns_pkt *packet, uint16_t nscount)
555 {
556 	packet->_header->_nscount = nscount;
557 }
558 
559 void
560 ldns_pkt_set_arcount(ldns_pkt *packet, uint16_t arcount)
561 {
562 	packet->_header->_arcount = arcount;
563 }
564 
565 void
566 ldns_pkt_set_querytime(ldns_pkt *packet, uint32_t time)
567 {
568 	packet->_querytime = time;
569 }
570 
571 void
572 ldns_pkt_set_answerfrom(ldns_pkt *packet, ldns_rdf *answerfrom)
573 {
574 	packet->_answerfrom = answerfrom;
575 }
576 
577 void
578 ldns_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 
584 void
585 ldns_pkt_set_size(ldns_pkt *packet, size_t s)
586 {
587 	packet->_size = s;
588 }
589 
590 void
591 ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s)
592 {
593 	packet->_edns_udp_size = s;
594 }
595 
596 void
597 ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c)
598 {
599 	packet->_edns_extended_rcode = c;
600 }
601 
602 void
603 ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v)
604 {
605 	packet->_edns_version = v;
606 }
607 
608 void
609 ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z)
610 {
611 	packet->_edns_z = z;
612 }
613 
614 void
615 ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data)
616 {
617 	packet->_edns_data = data;
618 }
619 
620 void
621 ldns_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 
642 void ldns_pkt_set_tsig(ldns_pkt *pkt, ldns_rr *rr)
643 {
644 	pkt->_tsig_rr = rr;
645 }
646 
647 bool
648 ldns_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 
683 bool
684 ldns_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 
695 bool
696 ldns_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 
707 bool
708 ldns_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 
719 bool
720 ldns_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  */
731 ldns_pkt *
732 ldns_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 
783 void
784 ldns_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 
799 bool
800 ldns_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 
830 static ldns_status
831 ldns_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 
909 ldns_status
910 ldns_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 
970 ldns_pkt *
971 ldns_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 
1017 ldns_pkt_type
1018 ldns_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 
1063 ldns_pkt *
1064 ldns_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