usched: Allow process to change self cpu affinity
[dragonfly.git] / contrib / ldns / packet.c
blobb44c0add6450293a2d89c91ad487a2c18a0a69eb
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
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}
37 /* read */
38 uint16_t
39 ldns_pkt_id(const ldns_pkt *packet)
41 return packet->_header->_id;
44 bool
45 ldns_pkt_qr(const ldns_pkt *packet)
47 return packet->_header->_qr;
50 bool
51 ldns_pkt_aa(const ldns_pkt *packet)
53 return packet->_header->_aa;
56 bool
57 ldns_pkt_tc(const ldns_pkt *packet)
59 return packet->_header->_tc;
62 bool
63 ldns_pkt_rd(const ldns_pkt *packet)
65 return packet->_header->_rd;
68 bool
69 ldns_pkt_cd(const ldns_pkt *packet)
71 return packet->_header->_cd;
74 bool
75 ldns_pkt_ra(const ldns_pkt *packet)
77 return packet->_header->_ra;
80 bool
81 ldns_pkt_ad(const ldns_pkt *packet)
83 return packet->_header->_ad;
86 ldns_pkt_opcode
87 ldns_pkt_get_opcode(const ldns_pkt *packet)
89 return packet->_header->_opcode;
92 ldns_pkt_rcode
93 ldns_pkt_get_rcode(const ldns_pkt *packet)
95 return packet->_header->_rcode;
98 uint16_t
99 ldns_pkt_qdcount(const ldns_pkt *packet)
101 return packet->_header->_qdcount;
104 uint16_t
105 ldns_pkt_ancount(const ldns_pkt *packet)
107 return packet->_header->_ancount;
110 uint16_t
111 ldns_pkt_nscount(const ldns_pkt *packet)
113 return packet->_header->_nscount;
116 uint16_t
117 ldns_pkt_arcount(const ldns_pkt *packet)
119 return packet->_header->_arcount;
122 ldns_rr_list *
123 ldns_pkt_question(const ldns_pkt *packet)
125 return packet->_question;
128 ldns_rr_list *
129 ldns_pkt_answer(const ldns_pkt *packet)
131 return packet->_answer;
134 ldns_rr_list *
135 ldns_pkt_authority(const ldns_pkt *packet)
137 return packet->_authority;
140 ldns_rr_list *
141 ldns_pkt_additional(const ldns_pkt *packet)
143 return packet->_additional;
146 /* return ALL section concatenated */
147 ldns_rr_list *
148 ldns_pkt_all(const ldns_pkt *packet)
150 ldns_rr_list *all, *prev_all;
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;
166 ldns_rr_list *
167 ldns_pkt_all_noquestion(const ldns_pkt *packet)
169 ldns_rr_list *all, *all2;
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));
177 ldns_rr_list_deep_free(all);
178 return all2;
181 size_t
182 ldns_pkt_size(const ldns_pkt *packet)
184 return packet->_size;
187 uint32_t
188 ldns_pkt_querytime(const ldns_pkt *packet)
190 return packet->_querytime;
193 ldns_rdf *
194 ldns_pkt_answerfrom(const ldns_pkt *packet)
196 return packet->_answerfrom;
199 struct timeval
200 ldns_pkt_timestamp(const ldns_pkt *packet)
202 return packet->timestamp;
205 uint16_t
206 ldns_pkt_edns_udp_size(const ldns_pkt *packet)
208 return packet->_edns_udp_size;
211 uint8_t
212 ldns_pkt_edns_extended_rcode(const ldns_pkt *packet)
214 return packet->_edns_extended_rcode;
217 uint8_t
218 ldns_pkt_edns_version(const ldns_pkt *packet)
220 return packet->_edns_version;
223 uint16_t
224 ldns_pkt_edns_z(const ldns_pkt *packet)
226 return packet->_edns_z;
229 bool
230 ldns_pkt_edns_do(const ldns_pkt *packet)
232 return (packet->_edns_z & LDNS_EDNS_MASK_DO_BIT);
235 void
236 ldns_pkt_set_edns_do(ldns_pkt *packet, bool value)
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;
245 ldns_rdf *
246 ldns_pkt_edns_data(const ldns_pkt *packet)
248 return packet->_edns_data;
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)
257 ldns_rr_list *rrs;
258 ldns_rr_list *ret;
259 uint16_t i;
261 if (!packet) {
262 return NULL;
265 rrs = ldns_pkt_get_section_clone(packet, sec);
266 ret = NULL;
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();
276 ldns_rr_list_push_rr(ret, ldns_rr_list_rr(rrs, i));
279 return ret;
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)
288 ldns_rr_list *rrs;
289 ldns_rr_list *new;
290 uint16_t i;
292 if(!packet) {
293 return NULL;
296 rrs = ldns_pkt_get_section_clone(packet, sec);
297 new = ldns_rr_list_new();
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))
308 ldns_rr_list_deep_free(rrs);
310 if (ldns_rr_list_rr_count(new) == 0) {
311 ldns_rr_list_free(new);
312 return NULL;
313 } else {
314 return new;
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)
325 ldns_rr_list *rrs;
326 ldns_rr_list *new;
327 ldns_rr_list *ret;
328 uint16_t i;
330 if(!packet) {
331 return NULL;
334 rrs = ldns_pkt_get_section_clone(packet, sec);
335 new = ldns_rr_list_new();
336 ret = NULL;
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
344 /* types match */
345 ldns_rr_list_push_rr(new, ldns_rr_clone(ldns_rr_list_rr(rrs, i)));
346 ret = new;
349 ldns_rr_list_deep_free(rrs);
350 if (!ret) {
351 ldns_rr_list_free(new);
353 return ret;
356 bool
357 ldns_pkt_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
359 bool result = false;
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);
379 return result;
382 uint16_t
383 ldns_pkt_section_count(const ldns_pkt *packet, ldns_pkt_section s)
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;
408 bool
409 ldns_pkt_empty(ldns_pkt *p)
411 if (!p) {
412 return true; /* NULL is empty? */
414 if (ldns_pkt_section_count(p, LDNS_SECTION_ANY) > 0) {
415 return false;
416 } else {
417 return true;
422 ldns_rr_list *
423 ldns_pkt_get_section_clone(const ldns_pkt *packet, ldns_pkt_section s)
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;
444 ldns_rr *ldns_pkt_tsig(const ldns_pkt *pkt) {
445 return pkt->_tsig_rr;
448 /* write */
449 void
450 ldns_pkt_set_id(ldns_pkt *packet, uint16_t id)
452 packet->_header->_id = id;
455 void
456 ldns_pkt_set_random_id(ldns_pkt *packet)
458 uint16_t rid = ldns_get_random();
459 ldns_pkt_set_id(packet, rid);
463 void
464 ldns_pkt_set_qr(ldns_pkt *packet, bool qr)
466 packet->_header->_qr = qr;
469 void
470 ldns_pkt_set_aa(ldns_pkt *packet, bool aa)
472 packet->_header->_aa = aa;
475 void
476 ldns_pkt_set_tc(ldns_pkt *packet, bool tc)
478 packet->_header->_tc = tc;
481 void
482 ldns_pkt_set_rd(ldns_pkt *packet, bool rd)
484 packet->_header->_rd = rd;
487 void
488 ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr)
490 p->_additional = rr;
493 void
494 ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr)
496 p->_question = rr;
499 void
500 ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr)
502 p->_answer = rr;
505 void
506 ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr)
508 p->_authority = rr;
511 void
512 ldns_pkt_set_cd(ldns_pkt *packet, bool cd)
514 packet->_header->_cd = cd;
517 void
518 ldns_pkt_set_ra(ldns_pkt *packet, bool ra)
520 packet->_header->_ra = ra;
523 void
524 ldns_pkt_set_ad(ldns_pkt *packet, bool ad)
526 packet->_header->_ad = ad;
529 void
530 ldns_pkt_set_opcode(ldns_pkt *packet, ldns_pkt_opcode opcode)
532 packet->_header->_opcode = opcode;
535 void
536 ldns_pkt_set_rcode(ldns_pkt *packet, uint8_t rcode)
538 packet->_header->_rcode = rcode;
541 void
542 ldns_pkt_set_qdcount(ldns_pkt *packet, uint16_t qdcount)
544 packet->_header->_qdcount = qdcount;
547 void
548 ldns_pkt_set_ancount(ldns_pkt *packet, uint16_t ancount)
550 packet->_header->_ancount = ancount;
553 void
554 ldns_pkt_set_nscount(ldns_pkt *packet, uint16_t nscount)
556 packet->_header->_nscount = nscount;
559 void
560 ldns_pkt_set_arcount(ldns_pkt *packet, uint16_t arcount)
562 packet->_header->_arcount = arcount;
565 void
566 ldns_pkt_set_querytime(ldns_pkt *packet, uint32_t time)
568 packet->_querytime = time;
571 void
572 ldns_pkt_set_answerfrom(ldns_pkt *packet, ldns_rdf *answerfrom)
574 packet->_answerfrom = answerfrom;
577 void
578 ldns_pkt_set_timestamp(ldns_pkt *packet, struct timeval timeval)
580 packet->timestamp.tv_sec = timeval.tv_sec;
581 packet->timestamp.tv_usec = timeval.tv_usec;
584 void
585 ldns_pkt_set_size(ldns_pkt *packet, size_t s)
587 packet->_size = s;
590 void
591 ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s)
593 packet->_edns_udp_size = s;
596 void
597 ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c)
599 packet->_edns_extended_rcode = c;
602 void
603 ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v)
605 packet->_edns_version = v;
608 void
609 ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z)
611 packet->_edns_z = z;
614 void
615 ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data)
617 packet->_edns_data = data;
620 void
621 ldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count)
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;
642 void ldns_pkt_set_tsig(ldns_pkt *pkt, ldns_rr *rr)
644 pkt->_tsig_rr = rr;
647 bool
648 ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr)
650 switch(section) {
651 case LDNS_SECTION_QUESTION:
652 if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) {
653 return false;
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;
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;
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;
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;
680 return true;
683 bool
684 ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
687 /* check to see if its there */
688 if (ldns_pkt_rr(pkt, sec, rr)) {
689 /* already there */
690 return false;
692 return ldns_pkt_push_rr(pkt, sec, rr);
695 bool
696 ldns_pkt_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
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;
704 return true;
707 bool
708 ldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
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;
716 return true;
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)
729 /* Create/destroy/convert functions
731 ldns_pkt *
732 ldns_pkt_new()
734 ldns_pkt *packet;
735 packet = LDNS_MALLOC(ldns_pkt);
736 if (!packet) {
737 return NULL;
740 packet->_header = LDNS_MALLOC(ldns_hdr);
741 if (!packet->_header) {
742 LDNS_FREE(packet);
743 return NULL;
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();
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);
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);
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);
778 ldns_pkt_set_tsig(packet, NULL);
780 return packet;
783 void
784 ldns_pkt_free(ldns_pkt *packet)
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);
799 bool
800 ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags)
802 if (!packet) {
803 return false;
805 if ((flags & LDNS_QR) == LDNS_QR) {
806 ldns_pkt_set_qr(packet, true);
808 if ((flags & LDNS_AA) == LDNS_AA) {
809 ldns_pkt_set_aa(packet, true);
811 if ((flags & LDNS_RD) == LDNS_RD) {
812 ldns_pkt_set_rd(packet, true);
814 if ((flags & LDNS_TC) == LDNS_TC) {
815 ldns_pkt_set_tc(packet, true);
817 if ((flags & LDNS_CD) == LDNS_CD) {
818 ldns_pkt_set_cd(packet, true);
820 if ((flags & LDNS_RA) == LDNS_RA) {
821 ldns_pkt_set_ra(packet, true);
823 if ((flags & LDNS_AD) == LDNS_AD) {
824 ldns_pkt_set_ad(packet, true);
826 return true;
830 static ldns_status
831 ldns_pkt_add_authsoa(ldns_pkt* packet, ldns_rdf* rr_name, ldns_rr_class rr_class)
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;
843 if (!soa_rr) {
844 return LDNS_STATUS_MEM_ERR;
846 owner_rdf = ldns_rdf_clone(rr_name);
847 if (!owner_rdf) {
848 ldns_rr_free(soa_rr);
849 return LDNS_STATUS_MEM_ERR;
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);
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);
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);
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);
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);
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);
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);
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);
904 ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, soa_rr);
905 return LDNS_STATUS_OK;
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)
913 ldns_pkt *packet;
914 ldns_rr *question_rr;
915 ldns_rdf *name_rdf;
917 packet = ldns_pkt_new();
918 if (!packet) {
919 return LDNS_STATUS_MEM_ERR;
922 if (!ldns_pkt_set_flags(packet, flags)) {
923 return LDNS_STATUS_ERR;
926 question_rr = ldns_rr_new();
927 if (!question_rr) {
928 return LDNS_STATUS_MEM_ERR;
931 if (rr_type == 0) {
932 rr_type = LDNS_RR_TYPE_A;
934 if (rr_class == 0) {
935 rr_class = LDNS_RR_CLASS_IN;
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);
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;
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;
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;
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)
974 ldns_pkt *packet;
975 ldns_rr *question_rr;
977 packet = ldns_pkt_new();
978 if (!packet) {
979 return NULL;
982 if (!ldns_pkt_set_flags(packet, flags)) {
983 return NULL;
986 question_rr = ldns_rr_new();
987 if (!question_rr) {
988 ldns_pkt_free(packet);
989 return NULL;
992 if (rr_type == 0) {
993 rr_type = LDNS_RR_TYPE_A;
995 if (rr_class == 0) {
996 rr_class = LDNS_RR_CLASS_IN;
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);
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;
1013 packet->_tsig_rr = NULL;
1014 return packet;
1017 ldns_pkt_type
1018 ldns_pkt_reply_type(ldns_pkt *p)
1020 ldns_rr_list *tmp;
1022 if (!p) {
1023 return LDNS_PACKET_UNKNOWN;
1026 if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NXDOMAIN) {
1027 return LDNS_PACKET_NXDOMAIN;
1030 if (ldns_pkt_ancount(p) == 0 && ldns_pkt_arcount(p) == 0
1031 && ldns_pkt_nscount(p) == 1) {
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 ... */
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 */
1054 ldns_rr_list_deep_free(tmp);
1057 /* if we cannot determine the packet type, we say it's an
1058 * answer...
1060 return LDNS_PACKET_ANSWER;
1063 ldns_pkt *
1064 ldns_pkt_clone(ldns_pkt *pkt)
1066 ldns_pkt *new_pkt;
1068 if (!pkt) {
1069 return NULL;
1071 new_pkt = ldns_pkt_new();
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)));
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));
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;