xref: /freebsd/contrib/ldns/packet.c (revision 911f0260390e18cf85f3dbf2c719b593efdc1e3c)
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 */
34 ldns_lookup_table ldns_edns_flags[] = {
35 	{ 3600, "do"},
36 	{ 0, NULL}
37 };
38 
39 /* read */
40 uint16_t
41 ldns_pkt_id(const ldns_pkt *packet)
42 {
43 	return packet->_header->_id;
44 }
45 
46 bool
47 ldns_pkt_qr(const ldns_pkt *packet)
48 {
49 	return packet->_header->_qr;
50 }
51 
52 bool
53 ldns_pkt_aa(const ldns_pkt *packet)
54 {
55 	return packet->_header->_aa;
56 }
57 
58 bool
59 ldns_pkt_tc(const ldns_pkt *packet)
60 {
61 	return packet->_header->_tc;
62 }
63 
64 bool
65 ldns_pkt_rd(const ldns_pkt *packet)
66 {
67 	return packet->_header->_rd;
68 }
69 
70 bool
71 ldns_pkt_cd(const ldns_pkt *packet)
72 {
73 	return packet->_header->_cd;
74 }
75 
76 bool
77 ldns_pkt_ra(const ldns_pkt *packet)
78 {
79 	return packet->_header->_ra;
80 }
81 
82 bool
83 ldns_pkt_ad(const ldns_pkt *packet)
84 {
85 	return packet->_header->_ad;
86 }
87 
88 ldns_pkt_opcode
89 ldns_pkt_get_opcode(const ldns_pkt *packet)
90 {
91 	return packet->_header->_opcode;
92 }
93 
94 ldns_pkt_rcode
95 ldns_pkt_get_rcode(const ldns_pkt *packet)
96 {
97 	return packet->_header->_rcode;
98 }
99 
100 uint16_t
101 ldns_pkt_qdcount(const ldns_pkt *packet)
102 {
103 	return packet->_header->_qdcount;
104 }
105 
106 uint16_t
107 ldns_pkt_ancount(const ldns_pkt *packet)
108 {
109 	return packet->_header->_ancount;
110 }
111 
112 uint16_t
113 ldns_pkt_nscount(const ldns_pkt *packet)
114 {
115 	return packet->_header->_nscount;
116 }
117 
118 uint16_t
119 ldns_pkt_arcount(const ldns_pkt *packet)
120 {
121 	return packet->_header->_arcount;
122 }
123 
124 ldns_rr_list *
125 ldns_pkt_question(const ldns_pkt *packet)
126 {
127 	return packet->_question;
128 }
129 
130 ldns_rr_list *
131 ldns_pkt_answer(const ldns_pkt *packet)
132 {
133 	return packet->_answer;
134 }
135 
136 ldns_rr_list *
137 ldns_pkt_authority(const ldns_pkt *packet)
138 {
139 	return packet->_authority;
140 }
141 
142 ldns_rr_list *
143 ldns_pkt_additional(const ldns_pkt *packet)
144 {
145 	return packet->_additional;
146 }
147 
148 /* return ALL section concatenated */
149 ldns_rr_list *
150 ldns_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 
168 ldns_rr_list *
169 ldns_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 
183 size_t
184 ldns_pkt_size(const ldns_pkt *packet)
185 {
186 	return packet->_size;
187 }
188 
189 uint32_t
190 ldns_pkt_querytime(const ldns_pkt *packet)
191 {
192 	return packet->_querytime;
193 }
194 
195 ldns_rdf *
196 ldns_pkt_answerfrom(const ldns_pkt *packet)
197 {
198 	return packet->_answerfrom;
199 }
200 
201 struct timeval
202 ldns_pkt_timestamp(const ldns_pkt *packet)
203 {
204 	return packet->timestamp;
205 }
206 
207 uint16_t
208 ldns_pkt_edns_udp_size(const ldns_pkt *packet)
209 {
210 	return packet->_edns_udp_size;
211 }
212 
213 uint8_t
214 ldns_pkt_edns_extended_rcode(const ldns_pkt *packet)
215 {
216 	return packet->_edns_extended_rcode;
217 }
218 
219 uint8_t
220 ldns_pkt_edns_version(const ldns_pkt *packet)
221 {
222 	return packet->_edns_version;
223 }
224 
225 uint16_t
226 ldns_pkt_edns_z(const ldns_pkt *packet)
227 {
228 	return packet->_edns_z;
229 }
230 
231 bool
232 ldns_pkt_edns_do(const ldns_pkt *packet)
233 {
234 	return (packet->_edns_z & LDNS_EDNS_MASK_DO_BIT);
235 }
236 
237 void
238 ldns_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 
247 uint16_t
248 ldns_pkt_edns_unassigned(const ldns_pkt *packet)
249 {
250 	return (packet->_edns_z & LDNS_EDNS_MASK_UNASSIGNED);
251 }
252 
253 void
254 ldns_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 
260 ldns_rdf *
261 ldns_pkt_edns_data(const ldns_pkt *packet)
262 {
263 	return packet->_edns_data;
264 }
265 
266 /* return only those rr that share the ownername */
267 ldns_rr_list *
268 ldns_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 */
304 ldns_rr_list *
305 ldns_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 */
340 ldns_rr_list *
341 ldns_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 
377 bool
378 ldns_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 
404 uint16_t
405 ldns_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 
430 bool
431 ldns_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 
444 ldns_rr_list *
445 ldns_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 
466 ldns_rr *ldns_pkt_tsig(const ldns_pkt *pkt) {
467 	return pkt->_tsig_rr;
468 }
469 
470 /* write */
471 void
472 ldns_pkt_set_id(ldns_pkt *packet, uint16_t id)
473 {
474 	packet->_header->_id = id;
475 }
476 
477 void
478 ldns_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 
485 void
486 ldns_pkt_set_qr(ldns_pkt *packet, bool qr)
487 {
488 	packet->_header->_qr = qr;
489 }
490 
491 void
492 ldns_pkt_set_aa(ldns_pkt *packet, bool aa)
493 {
494 	packet->_header->_aa = aa;
495 }
496 
497 void
498 ldns_pkt_set_tc(ldns_pkt *packet, bool tc)
499 {
500 	packet->_header->_tc = tc;
501 }
502 
503 void
504 ldns_pkt_set_rd(ldns_pkt *packet, bool rd)
505 {
506 	packet->_header->_rd = rd;
507 }
508 
509 void
510 ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr)
511 {
512 	p->_additional = rr;
513 }
514 
515 void
516 ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr)
517 {
518 	p->_question = rr;
519 }
520 
521 void
522 ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr)
523 {
524 	p->_answer = rr;
525 }
526 
527 void
528 ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr)
529 {
530 	p->_authority = rr;
531 }
532 
533 void
534 ldns_pkt_set_cd(ldns_pkt *packet, bool cd)
535 {
536 	packet->_header->_cd = cd;
537 }
538 
539 void
540 ldns_pkt_set_ra(ldns_pkt *packet, bool ra)
541 {
542 	packet->_header->_ra = ra;
543 }
544 
545 void
546 ldns_pkt_set_ad(ldns_pkt *packet, bool ad)
547 {
548 	packet->_header->_ad = ad;
549 }
550 
551 void
552 ldns_pkt_set_opcode(ldns_pkt *packet, ldns_pkt_opcode opcode)
553 {
554 	packet->_header->_opcode = opcode;
555 }
556 
557 void
558 ldns_pkt_set_rcode(ldns_pkt *packet, uint8_t rcode)
559 {
560 	packet->_header->_rcode = rcode;
561 }
562 
563 void
564 ldns_pkt_set_qdcount(ldns_pkt *packet, uint16_t qdcount)
565 {
566 	packet->_header->_qdcount = qdcount;
567 }
568 
569 void
570 ldns_pkt_set_ancount(ldns_pkt *packet, uint16_t ancount)
571 {
572 	packet->_header->_ancount = ancount;
573 }
574 
575 void
576 ldns_pkt_set_nscount(ldns_pkt *packet, uint16_t nscount)
577 {
578 	packet->_header->_nscount = nscount;
579 }
580 
581 void
582 ldns_pkt_set_arcount(ldns_pkt *packet, uint16_t arcount)
583 {
584 	packet->_header->_arcount = arcount;
585 }
586 
587 void
588 ldns_pkt_set_querytime(ldns_pkt *packet, uint32_t time)
589 {
590 	packet->_querytime = time;
591 }
592 
593 void
594 ldns_pkt_set_answerfrom(ldns_pkt *packet, ldns_rdf *answerfrom)
595 {
596 	packet->_answerfrom = answerfrom;
597 }
598 
599 void
600 ldns_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 
606 void
607 ldns_pkt_set_size(ldns_pkt *packet, size_t s)
608 {
609 	packet->_size = s;
610 }
611 
612 void
613 ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s)
614 {
615 	packet->_edns_udp_size = s;
616 }
617 
618 void
619 ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c)
620 {
621 	packet->_edns_extended_rcode = c;
622 }
623 
624 void
625 ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v)
626 {
627 	packet->_edns_version = v;
628 }
629 
630 void
631 ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z)
632 {
633 	packet->_edns_z = z;
634 }
635 
636 void
637 ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data)
638 {
639 	packet->_edns_data = data;
640 }
641 
642 void
643 ldns_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 
651 void
652 ldns_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 
673 void ldns_pkt_set_tsig(ldns_pkt *pkt, ldns_rr *rr)
674 {
675 	pkt->_tsig_rr = rr;
676 }
677 
678 bool
679 ldns_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 
714 bool
715 ldns_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 
726 bool
727 ldns_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 
738 bool
739 ldns_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 
750 bool
751 ldns_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 
762 ldns_edns_option_list*
763 pkt_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 
821 ldns_edns_option_list*
822 ldns_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  */
841 ldns_pkt *
842 ldns_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 
895 void
896 ldns_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 
912 bool
913 ldns_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 
943 static ldns_rr*
944 ldns_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 
1021 static ldns_status
1022 ldns_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 
1081 ldns_status
1082 ldns_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 
1089 ldns_status
1090 ldns_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 
1105 static ldns_pkt *
1106 ldns_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 
1148 ldns_pkt *
1149 ldns_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 
1156 ldns_pkt *
1157 ldns_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 
1168 ldns_pkt_type
1169 ldns_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 
1214 ldns_pkt *
1215 ldns_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