ldns: Update vendor branch from 1.6.11 to 1.6.16
[dragonfly.git] / contrib / ldns / packet.c
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 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()
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 }