rc.conf: Add and document the missing root_rw_mount=YES
[dragonfly.git] / contrib / ldns / packet.c
blobafa59005c3bda65e35a0d521327d648d427f5c16
1 /*
2 * packet.c
4 * dns packet implementation
6 * a Net::DNS like library for C
8 * (c) NLnet Labs, 2004-2006
10 * See the file LICENSE for the license
13 #include <ldns/config.h>
15 #include <ldns/ldns.h>
17 #include <strings.h>
18 #include <limits.h>
20 #ifdef HAVE_SSL
21 #include <openssl/rand.h>
22 #endif
24 /* Access functions
25 * do this as functions to get type checking
28 #define LDNS_EDNS_MASK_DO_BIT 0x8000
29 #define LDNS_EDNS_MASK_UNASSIGNED (0xFFFF & ~LDNS_EDNS_MASK_DO_BIT)
31 /* TODO defines for 3600 */
32 /* convert to and from numerical flag values */
33 ldns_lookup_table ldns_edns_flags[] = {
34 { 3600, "do"},
35 { 0, NULL}
38 /* read */
39 uint16_t
40 ldns_pkt_id(const ldns_pkt *packet)
42 return packet->_header->_id;
45 bool
46 ldns_pkt_qr(const ldns_pkt *packet)
48 return packet->_header->_qr;
51 bool
52 ldns_pkt_aa(const ldns_pkt *packet)
54 return packet->_header->_aa;
57 bool
58 ldns_pkt_tc(const ldns_pkt *packet)
60 return packet->_header->_tc;
63 bool
64 ldns_pkt_rd(const ldns_pkt *packet)
66 return packet->_header->_rd;
69 bool
70 ldns_pkt_cd(const ldns_pkt *packet)
72 return packet->_header->_cd;
75 bool
76 ldns_pkt_ra(const ldns_pkt *packet)
78 return packet->_header->_ra;
81 bool
82 ldns_pkt_ad(const ldns_pkt *packet)
84 return packet->_header->_ad;
87 ldns_pkt_opcode
88 ldns_pkt_get_opcode(const ldns_pkt *packet)
90 return packet->_header->_opcode;
93 ldns_pkt_rcode
94 ldns_pkt_get_rcode(const ldns_pkt *packet)
96 return packet->_header->_rcode;
99 uint16_t
100 ldns_pkt_qdcount(const ldns_pkt *packet)
102 return packet->_header->_qdcount;
105 uint16_t
106 ldns_pkt_ancount(const ldns_pkt *packet)
108 return packet->_header->_ancount;
111 uint16_t
112 ldns_pkt_nscount(const ldns_pkt *packet)
114 return packet->_header->_nscount;
117 uint16_t
118 ldns_pkt_arcount(const ldns_pkt *packet)
120 return packet->_header->_arcount;
123 ldns_rr_list *
124 ldns_pkt_question(const ldns_pkt *packet)
126 return packet->_question;
129 ldns_rr_list *
130 ldns_pkt_answer(const ldns_pkt *packet)
132 return packet->_answer;
135 ldns_rr_list *
136 ldns_pkt_authority(const ldns_pkt *packet)
138 return packet->_authority;
141 ldns_rr_list *
142 ldns_pkt_additional(const ldns_pkt *packet)
144 return packet->_additional;
147 /* return ALL section concatenated */
148 ldns_rr_list *
149 ldns_pkt_all(const ldns_pkt *packet)
151 ldns_rr_list *all, *prev_all;
153 all = ldns_rr_list_cat_clone(
154 ldns_pkt_question(packet),
155 ldns_pkt_answer(packet));
156 prev_all = all;
157 all = ldns_rr_list_cat_clone(all,
158 ldns_pkt_authority(packet));
159 ldns_rr_list_deep_free(prev_all);
160 prev_all = all;
161 all = ldns_rr_list_cat_clone(all,
162 ldns_pkt_additional(packet));
163 ldns_rr_list_deep_free(prev_all);
164 return all;
167 ldns_rr_list *
168 ldns_pkt_all_noquestion(const ldns_pkt *packet)
170 ldns_rr_list *all, *all2;
172 all = ldns_rr_list_cat_clone(
173 ldns_pkt_answer(packet),
174 ldns_pkt_authority(packet));
175 all2 = ldns_rr_list_cat_clone(all,
176 ldns_pkt_additional(packet));
178 ldns_rr_list_deep_free(all);
179 return all2;
182 size_t
183 ldns_pkt_size(const ldns_pkt *packet)
185 return packet->_size;
188 uint32_t
189 ldns_pkt_querytime(const ldns_pkt *packet)
191 return packet->_querytime;
194 ldns_rdf *
195 ldns_pkt_answerfrom(const ldns_pkt *packet)
197 return packet->_answerfrom;
200 struct timeval
201 ldns_pkt_timestamp(const ldns_pkt *packet)
203 return packet->timestamp;
206 uint16_t
207 ldns_pkt_edns_udp_size(const ldns_pkt *packet)
209 return packet->_edns_udp_size;
212 uint8_t
213 ldns_pkt_edns_extended_rcode(const ldns_pkt *packet)
215 return packet->_edns_extended_rcode;
218 uint8_t
219 ldns_pkt_edns_version(const ldns_pkt *packet)
221 return packet->_edns_version;
224 uint16_t
225 ldns_pkt_edns_z(const ldns_pkt *packet)
227 return packet->_edns_z;
230 bool
231 ldns_pkt_edns_do(const ldns_pkt *packet)
233 return (packet->_edns_z & LDNS_EDNS_MASK_DO_BIT);
236 void
237 ldns_pkt_set_edns_do(ldns_pkt *packet, bool value)
239 if (value) {
240 packet->_edns_z = packet->_edns_z | LDNS_EDNS_MASK_DO_BIT;
241 } else {
242 packet->_edns_z = packet->_edns_z & ~LDNS_EDNS_MASK_DO_BIT;
246 uint16_t
247 ldns_pkt_edns_unassigned(const ldns_pkt *packet)
249 return (packet->_edns_z & LDNS_EDNS_MASK_UNASSIGNED);
252 void
253 ldns_pkt_set_edns_unassigned(ldns_pkt *packet, uint16_t value)
255 packet->_edns_z = (packet->_edns_z & ~LDNS_EDNS_MASK_UNASSIGNED)
256 | (value & LDNS_EDNS_MASK_UNASSIGNED);
259 ldns_rdf *
260 ldns_pkt_edns_data(const ldns_pkt *packet)
262 return packet->_edns_data;
265 /* return only those rr that share the ownername */
266 ldns_rr_list *
267 ldns_pkt_rr_list_by_name(const ldns_pkt *packet,
268 const ldns_rdf *ownername,
269 ldns_pkt_section sec)
271 ldns_rr_list *rrs;
272 ldns_rr_list *ret;
273 uint16_t i;
275 if (!packet) {
276 return NULL;
279 rrs = ldns_pkt_get_section_clone(packet, sec);
280 ret = NULL;
282 for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
283 if (ldns_dname_compare(ldns_rr_owner(
284 ldns_rr_list_rr(rrs, i)),
285 ownername) == 0) {
286 /* owner names match */
287 if (ret == NULL) {
288 ret = ldns_rr_list_new();
290 ldns_rr_list_push_rr(ret,
291 ldns_rr_clone(
292 ldns_rr_list_rr(rrs, i))
297 ldns_rr_list_deep_free(rrs);
299 return ret;
302 /* return only those rr that share a type */
303 ldns_rr_list *
304 ldns_pkt_rr_list_by_type(const ldns_pkt *packet,
305 ldns_rr_type type,
306 ldns_pkt_section sec)
308 ldns_rr_list *rrs;
309 ldns_rr_list *new;
310 uint16_t i;
312 if(!packet) {
313 return NULL;
316 rrs = ldns_pkt_get_section_clone(packet, sec);
317 new = ldns_rr_list_new();
319 for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
320 if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i))) {
321 /* types match */
322 ldns_rr_list_push_rr(new,
323 ldns_rr_clone(
324 ldns_rr_list_rr(rrs, i))
328 ldns_rr_list_deep_free(rrs);
330 if (ldns_rr_list_rr_count(new) == 0) {
331 ldns_rr_list_free(new);
332 return NULL;
333 } else {
334 return new;
338 /* return only those rrs that share name and type */
339 ldns_rr_list *
340 ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet,
341 const ldns_rdf *ownername,
342 ldns_rr_type type,
343 ldns_pkt_section sec)
345 ldns_rr_list *rrs;
346 ldns_rr_list *new;
347 ldns_rr_list *ret;
348 uint16_t i;
350 if(!packet) {
351 return NULL;
354 rrs = ldns_pkt_get_section_clone(packet, sec);
355 new = ldns_rr_list_new();
356 ret = NULL;
358 for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
359 if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i)) &&
360 ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(rrs, i)),
361 ownername
362 ) == 0
364 /* types match */
365 ldns_rr_list_push_rr(new, ldns_rr_clone(ldns_rr_list_rr(rrs, i)));
366 ret = new;
369 ldns_rr_list_deep_free(rrs);
370 if (!ret) {
371 ldns_rr_list_free(new);
373 return ret;
376 bool
377 ldns_pkt_rr(const ldns_pkt *pkt, ldns_pkt_section sec, const ldns_rr *rr)
379 bool result = false;
381 switch (sec) {
382 case LDNS_SECTION_QUESTION:
383 return ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
384 case LDNS_SECTION_ANSWER:
385 return ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr);
386 case LDNS_SECTION_AUTHORITY:
387 return ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr);
388 case LDNS_SECTION_ADDITIONAL:
389 return ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
390 case LDNS_SECTION_ANY:
391 result = ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
392 /* fallthrough */
393 case LDNS_SECTION_ANY_NOQUESTION:
394 result = result
395 || ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr)
396 || ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr)
397 || ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
400 return result;
403 uint16_t
404 ldns_pkt_section_count(const ldns_pkt *packet, ldns_pkt_section s)
406 switch(s) {
407 case LDNS_SECTION_QUESTION:
408 return ldns_pkt_qdcount(packet);
409 case LDNS_SECTION_ANSWER:
410 return ldns_pkt_ancount(packet);
411 case LDNS_SECTION_AUTHORITY:
412 return ldns_pkt_nscount(packet);
413 case LDNS_SECTION_ADDITIONAL:
414 return ldns_pkt_arcount(packet);
415 case LDNS_SECTION_ANY:
416 return ldns_pkt_qdcount(packet) +
417 ldns_pkt_ancount(packet) +
418 ldns_pkt_nscount(packet) +
419 ldns_pkt_arcount(packet);
420 case LDNS_SECTION_ANY_NOQUESTION:
421 return ldns_pkt_ancount(packet) +
422 ldns_pkt_nscount(packet) +
423 ldns_pkt_arcount(packet);
424 default:
425 return 0;
429 bool
430 ldns_pkt_empty(ldns_pkt *p)
432 if (!p) {
433 return true; /* NULL is empty? */
435 if (ldns_pkt_section_count(p, LDNS_SECTION_ANY) > 0) {
436 return false;
437 } else {
438 return true;
443 ldns_rr_list *
444 ldns_pkt_get_section_clone(const ldns_pkt *packet, ldns_pkt_section s)
446 switch(s) {
447 case LDNS_SECTION_QUESTION:
448 return ldns_rr_list_clone(ldns_pkt_question(packet));
449 case LDNS_SECTION_ANSWER:
450 return ldns_rr_list_clone(ldns_pkt_answer(packet));
451 case LDNS_SECTION_AUTHORITY:
452 return ldns_rr_list_clone(ldns_pkt_authority(packet));
453 case LDNS_SECTION_ADDITIONAL:
454 return ldns_rr_list_clone(ldns_pkt_additional(packet));
455 case LDNS_SECTION_ANY:
456 /* these are already clones */
457 return ldns_pkt_all(packet);
458 case LDNS_SECTION_ANY_NOQUESTION:
459 return ldns_pkt_all_noquestion(packet);
460 default:
461 return NULL;
465 ldns_rr *ldns_pkt_tsig(const ldns_pkt *pkt) {
466 return pkt->_tsig_rr;
469 /* write */
470 void
471 ldns_pkt_set_id(ldns_pkt *packet, uint16_t id)
473 packet->_header->_id = id;
476 void
477 ldns_pkt_set_random_id(ldns_pkt *packet)
479 uint16_t rid = ldns_get_random();
480 ldns_pkt_set_id(packet, rid);
484 void
485 ldns_pkt_set_qr(ldns_pkt *packet, bool qr)
487 packet->_header->_qr = qr;
490 void
491 ldns_pkt_set_aa(ldns_pkt *packet, bool aa)
493 packet->_header->_aa = aa;
496 void
497 ldns_pkt_set_tc(ldns_pkt *packet, bool tc)
499 packet->_header->_tc = tc;
502 void
503 ldns_pkt_set_rd(ldns_pkt *packet, bool rd)
505 packet->_header->_rd = rd;
508 void
509 ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr)
511 p->_additional = rr;
514 void
515 ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr)
517 p->_question = rr;
520 void
521 ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr)
523 p->_answer = rr;
526 void
527 ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr)
529 p->_authority = rr;
532 void
533 ldns_pkt_set_cd(ldns_pkt *packet, bool cd)
535 packet->_header->_cd = cd;
538 void
539 ldns_pkt_set_ra(ldns_pkt *packet, bool ra)
541 packet->_header->_ra = ra;
544 void
545 ldns_pkt_set_ad(ldns_pkt *packet, bool ad)
547 packet->_header->_ad = ad;
550 void
551 ldns_pkt_set_opcode(ldns_pkt *packet, ldns_pkt_opcode opcode)
553 packet->_header->_opcode = opcode;
556 void
557 ldns_pkt_set_rcode(ldns_pkt *packet, uint8_t rcode)
559 packet->_header->_rcode = rcode;
562 void
563 ldns_pkt_set_qdcount(ldns_pkt *packet, uint16_t qdcount)
565 packet->_header->_qdcount = qdcount;
568 void
569 ldns_pkt_set_ancount(ldns_pkt *packet, uint16_t ancount)
571 packet->_header->_ancount = ancount;
574 void
575 ldns_pkt_set_nscount(ldns_pkt *packet, uint16_t nscount)
577 packet->_header->_nscount = nscount;
580 void
581 ldns_pkt_set_arcount(ldns_pkt *packet, uint16_t arcount)
583 packet->_header->_arcount = arcount;
586 void
587 ldns_pkt_set_querytime(ldns_pkt *packet, uint32_t time)
589 packet->_querytime = time;
592 void
593 ldns_pkt_set_answerfrom(ldns_pkt *packet, ldns_rdf *answerfrom)
595 packet->_answerfrom = answerfrom;
598 void
599 ldns_pkt_set_timestamp(ldns_pkt *packet, struct timeval timeval)
601 packet->timestamp.tv_sec = timeval.tv_sec;
602 packet->timestamp.tv_usec = timeval.tv_usec;
605 void
606 ldns_pkt_set_size(ldns_pkt *packet, size_t s)
608 packet->_size = s;
611 void
612 ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s)
614 packet->_edns_udp_size = s;
617 void
618 ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c)
620 packet->_edns_extended_rcode = c;
623 void
624 ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v)
626 packet->_edns_version = v;
629 void
630 ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z)
632 packet->_edns_z = z;
635 void
636 ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data)
638 packet->_edns_data = data;
641 void
642 ldns_pkt_set_edns_option_list(ldns_pkt *packet, ldns_edns_option_list *list)
644 if (packet->_edns_list)
645 ldns_edns_option_list_deep_free(packet->_edns_list);
646 packet->_edns_list = list;
650 void
651 ldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count)
653 switch(s) {
654 case LDNS_SECTION_QUESTION:
655 ldns_pkt_set_qdcount(packet, count);
656 break;
657 case LDNS_SECTION_ANSWER:
658 ldns_pkt_set_ancount(packet, count);
659 break;
660 case LDNS_SECTION_AUTHORITY:
661 ldns_pkt_set_nscount(packet, count);
662 break;
663 case LDNS_SECTION_ADDITIONAL:
664 ldns_pkt_set_arcount(packet, count);
665 break;
666 case LDNS_SECTION_ANY:
667 case LDNS_SECTION_ANY_NOQUESTION:
668 break;
672 void ldns_pkt_set_tsig(ldns_pkt *pkt, ldns_rr *rr)
674 pkt->_tsig_rr = rr;
677 bool
678 ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr)
680 switch(section) {
681 case LDNS_SECTION_QUESTION:
682 if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) {
683 return false;
685 ldns_pkt_set_qdcount(packet, ldns_pkt_qdcount(packet) + 1);
686 break;
687 case LDNS_SECTION_ANSWER:
688 if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) {
689 return false;
691 ldns_pkt_set_ancount(packet, ldns_pkt_ancount(packet) + 1);
692 break;
693 case LDNS_SECTION_AUTHORITY:
694 if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) {
695 return false;
697 ldns_pkt_set_nscount(packet, ldns_pkt_nscount(packet) + 1);
698 break;
699 case LDNS_SECTION_ADDITIONAL:
700 if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) {
701 return false;
703 ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + 1);
704 break;
705 case LDNS_SECTION_ANY:
706 case LDNS_SECTION_ANY_NOQUESTION:
707 /* shouldn't this error? */
708 break;
710 return true;
713 bool
714 ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
717 /* check to see if its there */
718 if (ldns_pkt_rr(pkt, sec, rr)) {
719 /* already there */
720 return false;
722 return ldns_pkt_push_rr(pkt, sec, rr);
725 bool
726 ldns_pkt_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
728 size_t i;
729 for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
730 if (!ldns_pkt_push_rr(p, s, ldns_rr_list_rr(list, i))) {
731 return false;
734 return true;
737 bool
738 ldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
740 size_t i;
741 for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
742 if (!ldns_pkt_safe_push_rr(p, s, ldns_rr_list_rr(list, i))) {
743 return false;
746 return true;
749 bool
750 ldns_pkt_edns(const ldns_pkt *pkt)
752 return (ldns_pkt_edns_udp_size(pkt) > 0 ||
753 ldns_pkt_edns_extended_rcode(pkt) > 0 ||
754 ldns_pkt_edns_data(pkt) ||
755 ldns_pkt_edns_do(pkt) ||
756 pkt->_edns_list ||
757 pkt->_edns_present
761 ldns_edns_option_list*
762 pkt_edns_data2edns_option_list(const ldns_rdf *edns_data)
764 size_t pos = 0;
765 ldns_edns_option_list* edns_list;
766 size_t max;
767 const uint8_t* wire;
769 if (!edns_data)
770 return NULL;
772 max = ldns_rdf_size(edns_data);
773 wire = ldns_rdf_data(edns_data);
774 if (!max)
775 return NULL;
777 if (!(edns_list = ldns_edns_option_list_new()))
778 return NULL;
780 while (pos < max) {
781 ldns_edns_option* edns;
782 uint8_t *data;
784 if (pos + 4 > max) { /* make sure the header is */
785 ldns_edns_option_list_deep_free(edns_list);
786 return NULL;
788 ldns_edns_option_code code = ldns_read_uint16(&wire[pos]);
789 size_t size = ldns_read_uint16(&wire[pos+2]);
790 pos += 4;
792 if (pos + size > max) { /* make sure the size fits the data */
793 ldns_edns_option_list_deep_free(edns_list);
794 return NULL;
796 data = LDNS_XMALLOC(uint8_t, size);
798 if (!data) {
799 ldns_edns_option_list_deep_free(edns_list);
800 return NULL;
802 memcpy(data, &wire[pos], size);
803 pos += size;
805 edns = ldns_edns_new(code, size, data);
807 if (!edns) {
808 ldns_edns_option_list_deep_free(edns_list);
809 return NULL;
811 if (!ldns_edns_option_list_push(edns_list, edns)) {
812 ldns_edns_option_list_deep_free(edns_list);
813 return NULL;
816 return edns_list;
820 ldns_edns_option_list*
821 ldns_pkt_edns_get_option_list(ldns_pkt *packet)
823 /* return the list if it already exists */
824 if (packet->_edns_list != NULL)
825 return packet->_edns_list;
827 /* if the list doesn't exists, we create it by parsing the
828 * packet->_edns_data
830 if (!ldns_pkt_edns_data(packet))
831 return NULL;
833 return ( packet->_edns_list
834 = pkt_edns_data2edns_option_list(ldns_pkt_edns_data(packet)));
838 /* Create/destroy/convert functions
840 ldns_pkt *
841 ldns_pkt_new(void)
843 ldns_pkt *packet;
844 packet = LDNS_MALLOC(ldns_pkt);
845 if (!packet) {
846 return NULL;
849 packet->_header = LDNS_MALLOC(ldns_hdr);
850 if (!packet->_header) {
851 LDNS_FREE(packet);
852 return NULL;
855 packet->_question = ldns_rr_list_new();
856 packet->_answer = ldns_rr_list_new();
857 packet->_authority = ldns_rr_list_new();
858 packet->_additional = ldns_rr_list_new();
860 /* default everything to false */
861 ldns_pkt_set_qr(packet, false);
862 ldns_pkt_set_aa(packet, false);
863 ldns_pkt_set_tc(packet, false);
864 ldns_pkt_set_rd(packet, false);
865 ldns_pkt_set_ra(packet, false);
866 ldns_pkt_set_ad(packet, false);
867 ldns_pkt_set_cd(packet, false);
869 ldns_pkt_set_opcode(packet, LDNS_PACKET_QUERY);
870 ldns_pkt_set_rcode(packet, 0);
871 ldns_pkt_set_id(packet, 0);
872 ldns_pkt_set_size(packet, 0);
873 ldns_pkt_set_querytime(packet, 0);
874 memset(&packet->timestamp, 0, sizeof(packet->timestamp));
875 ldns_pkt_set_answerfrom(packet, NULL);
876 ldns_pkt_set_section_count(packet, LDNS_SECTION_QUESTION, 0);
877 ldns_pkt_set_section_count(packet, LDNS_SECTION_ANSWER, 0);
878 ldns_pkt_set_section_count(packet, LDNS_SECTION_AUTHORITY, 0);
879 ldns_pkt_set_section_count(packet, LDNS_SECTION_ADDITIONAL, 0);
881 ldns_pkt_set_edns_udp_size(packet, 0);
882 ldns_pkt_set_edns_extended_rcode(packet, 0);
883 ldns_pkt_set_edns_version(packet, 0);
884 ldns_pkt_set_edns_z(packet, 0);
885 ldns_pkt_set_edns_data(packet, NULL);
886 packet->_edns_list = NULL;
887 packet->_edns_present = false;
889 ldns_pkt_set_tsig(packet, NULL);
891 return packet;
894 void
895 ldns_pkt_free(ldns_pkt *packet)
897 if (packet) {
898 LDNS_FREE(packet->_header);
899 ldns_rr_list_deep_free(packet->_question);
900 ldns_rr_list_deep_free(packet->_answer);
901 ldns_rr_list_deep_free(packet->_authority);
902 ldns_rr_list_deep_free(packet->_additional);
903 ldns_rr_free(packet->_tsig_rr);
904 ldns_rdf_deep_free(packet->_edns_data);
905 ldns_edns_option_list_deep_free(packet->_edns_list);
906 ldns_rdf_deep_free(packet->_answerfrom);
907 LDNS_FREE(packet);
911 bool
912 ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags)
914 if (!packet) {
915 return false;
917 if ((flags & LDNS_QR) == LDNS_QR) {
918 ldns_pkt_set_qr(packet, true);
920 if ((flags & LDNS_AA) == LDNS_AA) {
921 ldns_pkt_set_aa(packet, true);
923 if ((flags & LDNS_RD) == LDNS_RD) {
924 ldns_pkt_set_rd(packet, true);
926 if ((flags & LDNS_TC) == LDNS_TC) {
927 ldns_pkt_set_tc(packet, true);
929 if ((flags & LDNS_CD) == LDNS_CD) {
930 ldns_pkt_set_cd(packet, true);
932 if ((flags & LDNS_RA) == LDNS_RA) {
933 ldns_pkt_set_ra(packet, true);
935 if ((flags & LDNS_AD) == LDNS_AD) {
936 ldns_pkt_set_ad(packet, true);
938 return true;
942 static ldns_rr*
943 ldns_pkt_authsoa(const ldns_rdf* rr_name, ldns_rr_class rr_class)
945 ldns_rr* soa_rr = ldns_rr_new();
946 ldns_rdf *owner_rdf;
947 ldns_rdf *mname_rdf;
948 ldns_rdf *rname_rdf;
949 ldns_rdf *serial_rdf;
950 ldns_rdf *refresh_rdf;
951 ldns_rdf *retry_rdf;
952 ldns_rdf *expire_rdf;
953 ldns_rdf *minimum_rdf;
955 if (!soa_rr) {
956 return NULL;
958 owner_rdf = ldns_rdf_clone(rr_name);
959 if (!owner_rdf) {
960 ldns_rr_free(soa_rr);
961 return NULL;
964 ldns_rr_set_owner(soa_rr, owner_rdf);
965 ldns_rr_set_type(soa_rr, LDNS_RR_TYPE_SOA);
966 ldns_rr_set_class(soa_rr, rr_class);
967 ldns_rr_set_question(soa_rr, false);
969 if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) {
970 ldns_rr_free(soa_rr);
971 return NULL;
972 } else {
973 ldns_rr_push_rdf(soa_rr, mname_rdf);
975 if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) {
976 ldns_rr_free(soa_rr);
977 return NULL;
978 } else {
979 ldns_rr_push_rdf(soa_rr, rname_rdf);
981 serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
982 if (!serial_rdf) {
983 ldns_rr_free(soa_rr);
984 return NULL;
985 } else {
986 ldns_rr_push_rdf(soa_rr, serial_rdf);
988 refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
989 if (!refresh_rdf) {
990 ldns_rr_free(soa_rr);
991 return NULL;
992 } else {
993 ldns_rr_push_rdf(soa_rr, refresh_rdf);
995 retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
996 if (!retry_rdf) {
997 ldns_rr_free(soa_rr);
998 return NULL;
999 } else {
1000 ldns_rr_push_rdf(soa_rr, retry_rdf);
1002 expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1003 if (!expire_rdf) {
1004 ldns_rr_free(soa_rr);
1005 return NULL;
1006 } else {
1007 ldns_rr_push_rdf(soa_rr, expire_rdf);
1009 minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
1010 if (!minimum_rdf) {
1011 ldns_rr_free(soa_rr);
1012 return NULL;
1013 } else {
1014 ldns_rr_push_rdf(soa_rr, minimum_rdf);
1016 return soa_rr;
1020 static ldns_status
1021 ldns_pkt_query_new_frm_str_internal(ldns_pkt **p, const char *name,
1022 ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags,
1023 ldns_rr* authsoa_rr)
1025 ldns_pkt *packet;
1026 ldns_rr *question_rr;
1027 ldns_rdf *name_rdf;
1029 packet = ldns_pkt_new();
1030 if (!packet) {
1031 return LDNS_STATUS_MEM_ERR;
1034 if (!ldns_pkt_set_flags(packet, flags)) {
1035 ldns_pkt_free(packet);
1036 return LDNS_STATUS_ERR;
1039 question_rr = ldns_rr_new();
1040 if (!question_rr) {
1041 ldns_pkt_free(packet);
1042 return LDNS_STATUS_MEM_ERR;
1045 if (rr_type == 0) {
1046 rr_type = LDNS_RR_TYPE_A;
1048 if (rr_class == 0) {
1049 rr_class = LDNS_RR_CLASS_IN;
1052 if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
1053 ldns_rr_set_owner(question_rr, name_rdf);
1054 ldns_rr_set_type(question_rr, rr_type);
1055 ldns_rr_set_class(question_rr, rr_class);
1056 ldns_rr_set_question(question_rr, true);
1058 ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
1059 } else {
1060 ldns_rr_free(question_rr);
1061 ldns_pkt_free(packet);
1062 return LDNS_STATUS_ERR;
1065 if (authsoa_rr) {
1066 ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr);
1069 packet->_tsig_rr = NULL;
1070 ldns_pkt_set_answerfrom(packet, NULL);
1071 if (p) {
1072 *p = packet;
1073 return LDNS_STATUS_OK;
1074 } else {
1075 ldns_pkt_free(packet);
1076 return LDNS_STATUS_NULL;
1080 ldns_status
1081 ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name,
1082 ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags)
1084 return ldns_pkt_query_new_frm_str_internal(p, name, rr_type,
1085 rr_class, flags, NULL);
1088 ldns_status
1089 ldns_pkt_ixfr_request_new_frm_str(ldns_pkt **p, const char *name,
1090 ldns_rr_class rr_class, uint16_t flags, ldns_rr *soa)
1092 ldns_rr* authsoa_rr = soa;
1093 if (!authsoa_rr) {
1094 ldns_rdf *name_rdf;
1095 if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
1096 authsoa_rr = ldns_pkt_authsoa(name_rdf, rr_class);
1098 ldns_rdf_free(name_rdf);
1100 return ldns_pkt_query_new_frm_str_internal(p, name, LDNS_RR_TYPE_IXFR,
1101 rr_class, flags, authsoa_rr);
1104 static ldns_pkt *
1105 ldns_pkt_query_new_internal(ldns_rdf *rr_name, ldns_rr_type rr_type,
1106 ldns_rr_class rr_class, uint16_t flags, ldns_rr* authsoa_rr)
1108 ldns_pkt *packet;
1109 ldns_rr *question_rr;
1111 packet = ldns_pkt_new();
1112 if (!packet) {
1113 return NULL;
1116 if (!ldns_pkt_set_flags(packet, flags)) {
1117 return NULL;
1120 question_rr = ldns_rr_new();
1121 if (!question_rr) {
1122 ldns_pkt_free(packet);
1123 return NULL;
1126 if (rr_type == 0) {
1127 rr_type = LDNS_RR_TYPE_A;
1129 if (rr_class == 0) {
1130 rr_class = LDNS_RR_CLASS_IN;
1133 ldns_rr_set_owner(question_rr, rr_name);
1134 ldns_rr_set_type(question_rr, rr_type);
1135 ldns_rr_set_class(question_rr, rr_class);
1136 ldns_rr_set_question(question_rr, true);
1137 ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
1139 if (authsoa_rr) {
1140 ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr);
1143 packet->_tsig_rr = NULL;
1144 return packet;
1147 ldns_pkt *
1148 ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type,
1149 ldns_rr_class rr_class, uint16_t flags)
1151 return ldns_pkt_query_new_internal(rr_name, rr_type,
1152 rr_class, flags, NULL);
1155 ldns_pkt *
1156 ldns_pkt_ixfr_request_new(ldns_rdf *rr_name, ldns_rr_class rr_class,
1157 uint16_t flags, ldns_rr* soa)
1159 ldns_rr* authsoa_rr = soa;
1160 if (!authsoa_rr) {
1161 authsoa_rr = ldns_pkt_authsoa(rr_name, rr_class);
1163 return ldns_pkt_query_new_internal(rr_name, LDNS_RR_TYPE_IXFR,
1164 rr_class, flags, authsoa_rr);
1167 ldns_pkt_type
1168 ldns_pkt_reply_type(const ldns_pkt *p)
1170 ldns_rr_list *tmp;
1172 if (!p) {
1173 return LDNS_PACKET_UNKNOWN;
1176 if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NXDOMAIN) {
1177 return LDNS_PACKET_NXDOMAIN;
1180 if (ldns_pkt_ancount(p) == 0 && ldns_pkt_arcount(p) == 0
1181 && ldns_pkt_nscount(p) == 1) {
1183 /* check for SOA */
1184 tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_SOA,
1185 LDNS_SECTION_AUTHORITY);
1186 if (tmp) {
1187 ldns_rr_list_deep_free(tmp);
1188 return LDNS_PACKET_NODATA;
1189 } else {
1190 /* I have no idea ... */
1194 if (ldns_pkt_ancount(p) == 0 && ldns_pkt_nscount(p) > 0) {
1195 tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS,
1196 LDNS_SECTION_AUTHORITY);
1197 if (tmp) {
1198 /* there are nameservers here */
1199 ldns_rr_list_deep_free(tmp);
1200 return LDNS_PACKET_REFERRAL;
1201 } else {
1202 /* I have no idea */
1204 ldns_rr_list_deep_free(tmp);
1207 /* if we cannot determine the packet type, we say it's an
1208 * answer...
1210 return LDNS_PACKET_ANSWER;
1213 ldns_pkt *
1214 ldns_pkt_clone(const ldns_pkt *pkt)
1216 ldns_pkt *new_pkt;
1218 if (!pkt) {
1219 return NULL;
1221 new_pkt = ldns_pkt_new();
1223 ldns_pkt_set_id(new_pkt, ldns_pkt_id(pkt));
1224 ldns_pkt_set_qr(new_pkt, ldns_pkt_qr(pkt));
1225 ldns_pkt_set_aa(new_pkt, ldns_pkt_aa(pkt));
1226 ldns_pkt_set_tc(new_pkt, ldns_pkt_tc(pkt));
1227 ldns_pkt_set_rd(new_pkt, ldns_pkt_rd(pkt));
1228 ldns_pkt_set_cd(new_pkt, ldns_pkt_cd(pkt));
1229 ldns_pkt_set_ra(new_pkt, ldns_pkt_ra(pkt));
1230 ldns_pkt_set_ad(new_pkt, ldns_pkt_ad(pkt));
1231 ldns_pkt_set_opcode(new_pkt, ldns_pkt_get_opcode(pkt));
1232 ldns_pkt_set_rcode(new_pkt, ldns_pkt_get_rcode(pkt));
1233 ldns_pkt_set_qdcount(new_pkt, ldns_pkt_qdcount(pkt));
1234 ldns_pkt_set_ancount(new_pkt, ldns_pkt_ancount(pkt));
1235 ldns_pkt_set_nscount(new_pkt, ldns_pkt_nscount(pkt));
1236 ldns_pkt_set_arcount(new_pkt, ldns_pkt_arcount(pkt));
1237 if (ldns_pkt_answerfrom(pkt))
1238 ldns_pkt_set_answerfrom(new_pkt,
1239 ldns_rdf_clone(ldns_pkt_answerfrom(pkt)));
1240 ldns_pkt_set_timestamp(new_pkt, ldns_pkt_timestamp(pkt));
1241 ldns_pkt_set_querytime(new_pkt, ldns_pkt_querytime(pkt));
1242 ldns_pkt_set_size(new_pkt, ldns_pkt_size(pkt));
1243 ldns_pkt_set_tsig(new_pkt, ldns_rr_clone(ldns_pkt_tsig(pkt)));
1245 ldns_pkt_set_edns_udp_size(new_pkt, ldns_pkt_edns_udp_size(pkt));
1246 ldns_pkt_set_edns_extended_rcode(new_pkt,
1247 ldns_pkt_edns_extended_rcode(pkt));
1248 ldns_pkt_set_edns_version(new_pkt, ldns_pkt_edns_version(pkt));
1249 new_pkt->_edns_present = pkt->_edns_present;
1250 ldns_pkt_set_edns_z(new_pkt, ldns_pkt_edns_z(pkt));
1251 if(ldns_pkt_edns_data(pkt))
1252 ldns_pkt_set_edns_data(new_pkt,
1253 ldns_rdf_clone(ldns_pkt_edns_data(pkt)));
1254 ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt));
1255 if (pkt->_edns_list)
1256 ldns_pkt_set_edns_option_list(new_pkt,
1257 ldns_edns_option_list_clone(pkt->_edns_list));
1259 ldns_rr_list_deep_free(new_pkt->_question);
1260 ldns_rr_list_deep_free(new_pkt->_answer);
1261 ldns_rr_list_deep_free(new_pkt->_authority);
1262 ldns_rr_list_deep_free(new_pkt->_additional);
1263 new_pkt->_question = ldns_rr_list_clone(ldns_pkt_question(pkt));
1264 new_pkt->_answer = ldns_rr_list_clone(ldns_pkt_answer(pkt));
1265 new_pkt->_authority = ldns_rr_list_clone(ldns_pkt_authority(pkt));
1266 new_pkt->_additional = ldns_rr_list_clone(ldns_pkt_additional(pkt));
1267 return new_pkt;