packet.c
Go to the documentation of this file.
00001 /*
00002  * packet.c
00003  *
00004  * dns packet implementation
00005  *
00006  * a Net::DNS like library for C
00007  *
00008  * (c) NLnet Labs, 2004-2006
00009  *
00010  * See the file LICENSE for the license
00011  */
00012 
00013 #include <ldns/config.h>
00014 
00015 #include <ldns/ldns.h>
00016 
00017 #include <strings.h>
00018 #include <limits.h>
00019 
00020 #ifdef HAVE_SSL
00021 #include <openssl/rand.h>
00022 #endif
00023 
00024 /* Access functions 
00025  * do this as functions to get type checking
00026  */
00027 
00028 #define LDNS_EDNS_MASK_DO_BIT 0x8000
00029 
00030 /* TODO defines for 3600 */
00031 /* convert to and from numerical flag values */
00032 ldns_lookup_table ldns_edns_flags[] = {
00033         { 3600, "do"},
00034         { 0, NULL}
00035 };
00036 
00037 /* read */
00038 uint16_t
00039 ldns_pkt_id(const ldns_pkt *packet)
00040 {
00041         return packet->_header->_id;
00042 }
00043 
00044 bool
00045 ldns_pkt_qr(const ldns_pkt *packet)
00046 {
00047         return packet->_header->_qr;
00048 }
00049 
00050 bool
00051 ldns_pkt_aa(const ldns_pkt *packet)
00052 {
00053         return packet->_header->_aa;
00054 }
00055 
00056 bool
00057 ldns_pkt_tc(const ldns_pkt *packet)
00058 {
00059         return packet->_header->_tc;
00060 }
00061 
00062 bool
00063 ldns_pkt_rd(const ldns_pkt *packet)
00064 {
00065         return packet->_header->_rd;
00066 }
00067 
00068 bool
00069 ldns_pkt_cd(const ldns_pkt *packet)
00070 {
00071         return packet->_header->_cd;
00072 }
00073 
00074 bool
00075 ldns_pkt_ra(const ldns_pkt *packet)
00076 {
00077         return packet->_header->_ra;
00078 }
00079 
00080 bool
00081 ldns_pkt_ad(const ldns_pkt *packet)
00082 {
00083         return packet->_header->_ad;
00084 }
00085 
00086 ldns_pkt_opcode
00087 ldns_pkt_get_opcode(const ldns_pkt *packet)
00088 {
00089         return packet->_header->_opcode;
00090 }
00091 
00092 ldns_pkt_rcode
00093 ldns_pkt_get_rcode(const ldns_pkt *packet)
00094 {
00095         return packet->_header->_rcode;
00096 }
00097 
00098 uint16_t
00099 ldns_pkt_qdcount(const ldns_pkt *packet)
00100 {
00101         return packet->_header->_qdcount;
00102 }
00103 
00104 uint16_t
00105 ldns_pkt_ancount(const ldns_pkt *packet)
00106 {
00107         return packet->_header->_ancount;
00108 }
00109 
00110 uint16_t
00111 ldns_pkt_nscount(const ldns_pkt *packet)
00112 {
00113         return packet->_header->_nscount;
00114 }
00115 
00116 uint16_t
00117 ldns_pkt_arcount(const ldns_pkt *packet)
00118 {
00119         return packet->_header->_arcount;
00120 }
00121 
00122 ldns_rr_list *
00123 ldns_pkt_question(const ldns_pkt *packet)
00124 {
00125         return packet->_question;
00126 }
00127 
00128 ldns_rr_list *
00129 ldns_pkt_answer(const ldns_pkt *packet)
00130 {
00131         return packet->_answer;
00132 }
00133 
00134 ldns_rr_list *
00135 ldns_pkt_authority(const ldns_pkt *packet)
00136 {
00137         return packet->_authority;
00138 }
00139 
00140 ldns_rr_list *
00141 ldns_pkt_additional(const ldns_pkt *packet)
00142 {
00143         return packet->_additional;
00144 }
00145 
00146 /* return ALL section concatenated */
00147 ldns_rr_list *
00148 ldns_pkt_all(const ldns_pkt *packet)
00149 {
00150         ldns_rr_list *all, *prev_all;
00151 
00152         all = ldns_rr_list_cat_clone(
00153                         ldns_pkt_question(packet),
00154                         ldns_pkt_answer(packet));
00155         prev_all = all;
00156         all = ldns_rr_list_cat_clone(all,
00157                         ldns_pkt_authority(packet));
00158         ldns_rr_list_deep_free(prev_all);
00159         prev_all = all;
00160         all = ldns_rr_list_cat_clone(all,
00161                         ldns_pkt_additional(packet));
00162         ldns_rr_list_deep_free(prev_all);
00163         return all;
00164 }
00165 
00166 ldns_rr_list *
00167 ldns_pkt_all_noquestion(const ldns_pkt *packet)
00168 {
00169         ldns_rr_list *all, *all2;
00170 
00171         all = ldns_rr_list_cat_clone(
00172                         ldns_pkt_answer(packet),
00173                         ldns_pkt_authority(packet));
00174         all2 = ldns_rr_list_cat_clone(all,
00175                         ldns_pkt_additional(packet));
00176         
00177         ldns_rr_list_deep_free(all);
00178         return all2;
00179 }
00180 
00181 size_t
00182 ldns_pkt_size(const ldns_pkt *packet)
00183 {
00184         return packet->_size;
00185 }
00186 
00187 uint32_t 
00188 ldns_pkt_querytime(const ldns_pkt *packet)
00189 {
00190         return packet->_querytime;
00191 }
00192 
00193 ldns_rdf *
00194 ldns_pkt_answerfrom(const ldns_pkt *packet)
00195 {
00196         return packet->_answerfrom;
00197 }
00198 
00199 struct timeval
00200 ldns_pkt_timestamp(const ldns_pkt *packet)
00201 {
00202         return packet->timestamp;
00203 }
00204 
00205 uint16_t
00206 ldns_pkt_edns_udp_size(const ldns_pkt *packet)
00207 {
00208         return packet->_edns_udp_size;
00209 }
00210 
00211 uint8_t
00212 ldns_pkt_edns_extended_rcode(const ldns_pkt *packet)
00213 {
00214         return packet->_edns_extended_rcode;
00215 }
00216 
00217 uint8_t
00218 ldns_pkt_edns_version(const ldns_pkt *packet)
00219 {
00220         return packet->_edns_version;
00221 }
00222 
00223 uint16_t
00224 ldns_pkt_edns_z(const ldns_pkt *packet)
00225 {
00226         return packet->_edns_z;
00227 }
00228 
00229 bool
00230 ldns_pkt_edns_do(const ldns_pkt *packet)
00231 {
00232         return (packet->_edns_z & LDNS_EDNS_MASK_DO_BIT);
00233 }
00234 
00235 void
00236 ldns_pkt_set_edns_do(ldns_pkt *packet, bool value)
00237 {
00238         if (value) {
00239                 packet->_edns_z = packet->_edns_z | LDNS_EDNS_MASK_DO_BIT;
00240         } else {
00241                 packet->_edns_z = packet->_edns_z & ~LDNS_EDNS_MASK_DO_BIT;
00242         }
00243 }
00244 
00245 ldns_rdf *
00246 ldns_pkt_edns_data(const ldns_pkt *packet)
00247 {
00248         return packet->_edns_data;
00249 }
00250 
00251 /* return only those rr that share the ownername */
00252 ldns_rr_list *
00253 ldns_pkt_rr_list_by_name(ldns_pkt *packet,
00254                          ldns_rdf *ownername,
00255                          ldns_pkt_section sec)
00256 {
00257         ldns_rr_list *rrs;
00258         ldns_rr_list *ret;
00259         uint16_t i;
00260 
00261         if (!packet) {
00262                 return NULL;
00263         }
00264 
00265         rrs = ldns_pkt_get_section_clone(packet, sec);
00266         ret = NULL;
00267 
00268         for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
00269                 if (ldns_rdf_compare(ldns_rr_owner(
00270                                                 ldns_rr_list_rr(rrs, i)), 
00271                                         ownername) == 0) {
00272                         /* owner names match */
00273                         if (ret == NULL) {
00274                                 ret = ldns_rr_list_new();
00275                         }
00276                         ldns_rr_list_push_rr(ret, ldns_rr_list_rr(rrs, i));
00277                 }
00278         }
00279         return ret;
00280 }
00281 
00282 /* return only those rr that share a type */
00283 ldns_rr_list *
00284 ldns_pkt_rr_list_by_type(const ldns_pkt *packet,
00285                          ldns_rr_type type,
00286                          ldns_pkt_section sec)
00287 {
00288         ldns_rr_list *rrs;
00289         ldns_rr_list *new;
00290         uint16_t i;
00291 
00292         if(!packet) {
00293                 return NULL;
00294         }
00295         
00296         rrs = ldns_pkt_get_section_clone(packet, sec);
00297         new = ldns_rr_list_new();
00298         
00299         for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
00300                 if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i))) {
00301                         /* types match */
00302                         ldns_rr_list_push_rr(new, 
00303                                              ldns_rr_clone(
00304                                                 ldns_rr_list_rr(rrs, i))
00305                                              );
00306                 }
00307         }
00308         ldns_rr_list_deep_free(rrs);
00309 
00310         if (ldns_rr_list_rr_count(new) == 0) {
00311                 ldns_rr_list_free(new);
00312                 return NULL;
00313         } else {
00314                 return new;
00315         }
00316 }
00317 
00318 /* return only those rrs that share name and type */
00319 ldns_rr_list *
00320 ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet,
00321                                   const ldns_rdf *ownername,
00322                                   ldns_rr_type type,
00323                                   ldns_pkt_section sec)
00324 {
00325         ldns_rr_list *rrs;
00326         ldns_rr_list *new;
00327         ldns_rr_list *ret;
00328         uint16_t i;
00329 
00330         if(!packet) {
00331                 return NULL;
00332         }
00333         
00334         rrs = ldns_pkt_get_section_clone(packet, sec);
00335         new = ldns_rr_list_new();
00336         ret = NULL;
00337 
00338         for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
00339                 if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i)) &&
00340                     ldns_rdf_compare(ldns_rr_owner(ldns_rr_list_rr(rrs, i)),
00341                                      ownername
00342                                     ) == 0
00343                    ) {
00344                         /* types match */
00345                         ldns_rr_list_push_rr(new, ldns_rr_clone(ldns_rr_list_rr(rrs, i)));
00346                         ret = new;
00347                 }
00348         }
00349         ldns_rr_list_deep_free(rrs);
00350         if (!ret) {
00351                 ldns_rr_list_free(new);
00352         }
00353         return ret;
00354 }
00355 
00356 bool
00357 ldns_pkt_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
00358 {
00359         bool result = false;
00360 
00361         switch (sec) {
00362         case LDNS_SECTION_QUESTION:
00363                 return ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
00364         case LDNS_SECTION_ANSWER:
00365                 return ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr);
00366         case LDNS_SECTION_AUTHORITY:
00367                 return ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr);
00368         case LDNS_SECTION_ADDITIONAL:
00369                 return ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
00370         case LDNS_SECTION_ANY:
00371                 result = ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
00372         case LDNS_SECTION_ANY_NOQUESTION:
00373                 result = result
00374                     || ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr)
00375                     || ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr)
00376                     || ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
00377         }
00378 
00379         return result;
00380 }
00381 
00382 uint16_t
00383 ldns_pkt_section_count(const ldns_pkt *packet, ldns_pkt_section s)
00384 {
00385         switch(s) {
00386         case LDNS_SECTION_QUESTION:
00387                 return ldns_pkt_qdcount(packet);
00388         case LDNS_SECTION_ANSWER:
00389                 return ldns_pkt_ancount(packet);
00390         case LDNS_SECTION_AUTHORITY:
00391                 return ldns_pkt_nscount(packet);
00392         case LDNS_SECTION_ADDITIONAL:
00393                 return ldns_pkt_arcount(packet);
00394         case LDNS_SECTION_ANY:
00395                 return ldns_pkt_qdcount(packet) +
00396                         ldns_pkt_ancount(packet) +
00397                         ldns_pkt_nscount(packet) +
00398                         ldns_pkt_arcount(packet);
00399         case LDNS_SECTION_ANY_NOQUESTION:
00400                 return ldns_pkt_ancount(packet) +
00401                         ldns_pkt_nscount(packet) +
00402                         ldns_pkt_arcount(packet);
00403         default:
00404                 return 0;
00405         }
00406 }
00407 
00408 bool
00409 ldns_pkt_empty(ldns_pkt *p)
00410 {
00411         if (!p) {
00412                 return true; /* NULL is empty? */
00413         }
00414         if (ldns_pkt_section_count(p, LDNS_SECTION_ANY) > 0) {
00415                 return false;
00416         } else {
00417                 return true;
00418     }
00419 }
00420 
00421 
00422 ldns_rr_list *
00423 ldns_pkt_get_section_clone(const ldns_pkt *packet, ldns_pkt_section s)
00424 {
00425         switch(s) {
00426         case LDNS_SECTION_QUESTION:
00427                 return ldns_rr_list_clone(ldns_pkt_question(packet));
00428         case LDNS_SECTION_ANSWER:
00429                 return ldns_rr_list_clone(ldns_pkt_answer(packet));
00430         case LDNS_SECTION_AUTHORITY:
00431                 return ldns_rr_list_clone(ldns_pkt_authority(packet));
00432         case LDNS_SECTION_ADDITIONAL:
00433                 return ldns_rr_list_clone(ldns_pkt_additional(packet));
00434         case LDNS_SECTION_ANY:
00435                 /* these are already clones */
00436                 return ldns_pkt_all(packet);
00437         case LDNS_SECTION_ANY_NOQUESTION:
00438                 return ldns_pkt_all_noquestion(packet);
00439         default:
00440                 return NULL;
00441         }
00442 }
00443 
00444 ldns_rr *ldns_pkt_tsig(const ldns_pkt *pkt) {
00445         return pkt->_tsig_rr;
00446 }
00447 
00448 /* write */
00449 void
00450 ldns_pkt_set_id(ldns_pkt *packet, uint16_t id)
00451 {
00452         packet->_header->_id = id;
00453 }
00454 
00455 void
00456 ldns_pkt_set_random_id(ldns_pkt *packet)
00457 {
00458         uint16_t rid = ldns_get_random();
00459         ldns_pkt_set_id(packet, rid);
00460 }
00461 
00462 
00463 void
00464 ldns_pkt_set_qr(ldns_pkt *packet, bool qr)
00465 {
00466         packet->_header->_qr = qr;
00467 }
00468 
00469 void
00470 ldns_pkt_set_aa(ldns_pkt *packet, bool aa)
00471 {
00472         packet->_header->_aa = aa;
00473 }
00474 
00475 void
00476 ldns_pkt_set_tc(ldns_pkt *packet, bool tc)
00477 {
00478         packet->_header->_tc = tc;
00479 }
00480 
00481 void
00482 ldns_pkt_set_rd(ldns_pkt *packet, bool rd)
00483 {
00484         packet->_header->_rd = rd;
00485 }
00486 
00487 void
00488 ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr)
00489 {
00490         p->_additional = rr;
00491 }
00492 
00493 void
00494 ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr)
00495 {
00496         p->_question = rr;
00497 }
00498 
00499 void
00500 ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr)
00501 {
00502         p->_answer = rr;
00503 }
00504 
00505 void
00506 ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr)
00507 {
00508         p->_authority = rr;
00509 }
00510 
00511 void
00512 ldns_pkt_set_cd(ldns_pkt *packet, bool cd)
00513 {
00514         packet->_header->_cd = cd;
00515 }
00516 
00517 void
00518 ldns_pkt_set_ra(ldns_pkt *packet, bool ra)
00519 {
00520         packet->_header->_ra = ra;
00521 }
00522 
00523 void
00524 ldns_pkt_set_ad(ldns_pkt *packet, bool ad)
00525 {
00526         packet->_header->_ad = ad;
00527 }
00528 
00529 void
00530 ldns_pkt_set_opcode(ldns_pkt *packet, ldns_pkt_opcode opcode)
00531 {
00532         packet->_header->_opcode = opcode;
00533 }
00534 
00535 void
00536 ldns_pkt_set_rcode(ldns_pkt *packet, uint8_t rcode)
00537 {
00538         packet->_header->_rcode = rcode;
00539 }
00540 
00541 void
00542 ldns_pkt_set_qdcount(ldns_pkt *packet, uint16_t qdcount)
00543 {
00544         packet->_header->_qdcount = qdcount;
00545 }
00546 
00547 void
00548 ldns_pkt_set_ancount(ldns_pkt *packet, uint16_t ancount)
00549 {
00550         packet->_header->_ancount = ancount;
00551 }
00552 
00553 void
00554 ldns_pkt_set_nscount(ldns_pkt *packet, uint16_t nscount)
00555 {
00556         packet->_header->_nscount = nscount;
00557 }
00558 
00559 void
00560 ldns_pkt_set_arcount(ldns_pkt *packet, uint16_t arcount)
00561 {
00562         packet->_header->_arcount = arcount;
00563 }
00564 
00565 void
00566 ldns_pkt_set_querytime(ldns_pkt *packet, uint32_t time) 
00567 {
00568         packet->_querytime = time;
00569 }
00570 
00571 void
00572 ldns_pkt_set_answerfrom(ldns_pkt *packet, ldns_rdf *answerfrom)
00573 {
00574         packet->_answerfrom = answerfrom;
00575 }
00576 
00577 void
00578 ldns_pkt_set_timestamp(ldns_pkt *packet, struct timeval timeval)
00579 {
00580         packet->timestamp.tv_sec = timeval.tv_sec;
00581         packet->timestamp.tv_usec = timeval.tv_usec;
00582 }
00583 
00584 void
00585 ldns_pkt_set_size(ldns_pkt *packet, size_t s)
00586 {
00587         packet->_size = s;
00588 }
00589 
00590 void
00591 ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s)
00592 {
00593         packet->_edns_udp_size = s;
00594 }
00595 
00596 void
00597 ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c)
00598 {
00599         packet->_edns_extended_rcode = c;
00600 }
00601 
00602 void
00603 ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v)
00604 {
00605         packet->_edns_version = v;
00606 }
00607 
00608 void
00609 ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z)
00610 {
00611         packet->_edns_z = z;
00612 }
00613 
00614 void
00615 ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data)
00616 {
00617         packet->_edns_data = data;
00618 }
00619 
00620 void
00621 ldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count)
00622 {
00623         switch(s) {
00624                 case LDNS_SECTION_QUESTION:
00625                         ldns_pkt_set_qdcount(packet, count);
00626                         break;
00627                 case LDNS_SECTION_ANSWER:
00628                         ldns_pkt_set_ancount(packet, count);
00629                         break;
00630                 case LDNS_SECTION_AUTHORITY:
00631                         ldns_pkt_set_nscount(packet, count);
00632                         break;
00633                 case LDNS_SECTION_ADDITIONAL:
00634                         ldns_pkt_set_arcount(packet, count);
00635                         break;
00636                 case LDNS_SECTION_ANY:
00637                 case LDNS_SECTION_ANY_NOQUESTION:
00638                         break;
00639         }
00640 }
00641 
00642 void ldns_pkt_set_tsig(ldns_pkt *pkt, ldns_rr *rr)
00643 {
00644         pkt->_tsig_rr = rr;
00645 }
00646 
00647 bool
00648 ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr)
00649 {
00650         switch(section) {
00651                 case LDNS_SECTION_QUESTION:
00652                         if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) {
00653                                 return false;
00654                         }
00655                         ldns_pkt_set_qdcount(packet, ldns_pkt_qdcount(packet) + 1);
00656                         break;
00657                 case LDNS_SECTION_ANSWER:
00658                         if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) {
00659                                 return false;
00660                         }
00661                         ldns_pkt_set_ancount(packet, ldns_pkt_ancount(packet) + 1);
00662                         break;
00663                 case LDNS_SECTION_AUTHORITY:
00664                         if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) {
00665                                 return false;
00666                         }
00667                         ldns_pkt_set_nscount(packet, ldns_pkt_nscount(packet) + 1);
00668                         break;
00669                 case LDNS_SECTION_ADDITIONAL:
00670                         if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) {
00671                                 return false;
00672                         }
00673                         ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + 1);
00674                         break;
00675                 case LDNS_SECTION_ANY:
00676                 case LDNS_SECTION_ANY_NOQUESTION:
00677                         /* shouldn't this error? */
00678                         break;
00679         }
00680         return true;
00681 }
00682 
00683 bool
00684 ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
00685 {
00686 
00687         /* check to see if its there */
00688         if (ldns_pkt_rr(pkt, sec, rr)) {
00689                 /* already there */
00690                 return false;
00691         }
00692         return ldns_pkt_push_rr(pkt, sec, rr);
00693 }
00694 
00695 bool
00696 ldns_pkt_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
00697 {
00698         size_t i;
00699         for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
00700                 if (!ldns_pkt_push_rr(p, s, ldns_rr_list_rr(list, i))) {
00701                         return false;
00702                 }
00703         }
00704         return true;
00705 }
00706 
00707 bool
00708 ldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
00709 {
00710         size_t i;
00711         for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
00712                 if (!ldns_pkt_safe_push_rr(p, s, ldns_rr_list_rr(list, i))) {
00713                         return false;
00714                 }
00715         }
00716         return true;
00717 }
00718 
00719 bool
00720 ldns_pkt_edns(const ldns_pkt *pkt) {
00721         return (ldns_pkt_edns_udp_size(pkt) > 0 ||
00722                 ldns_pkt_edns_extended_rcode(pkt) > 0 ||
00723                 ldns_pkt_edns_data(pkt) ||
00724                 ldns_pkt_edns_do(pkt)
00725                );
00726 }
00727 
00728 
00729 /* Create/destroy/convert functions
00730  */
00731 ldns_pkt *
00732 ldns_pkt_new()
00733 {
00734         ldns_pkt *packet;
00735         packet = LDNS_MALLOC(ldns_pkt);
00736         if (!packet) {
00737                 return NULL;
00738         }
00739 
00740         packet->_header = LDNS_MALLOC(ldns_hdr);
00741         if (!packet->_header) {
00742                 LDNS_FREE(packet);
00743                 return NULL;
00744         }
00745 
00746         packet->_question = ldns_rr_list_new();
00747         packet->_answer = ldns_rr_list_new();
00748         packet->_authority = ldns_rr_list_new();
00749         packet->_additional = ldns_rr_list_new();
00750 
00751         /* default everything to false */
00752         ldns_pkt_set_qr(packet, false);
00753         ldns_pkt_set_aa(packet, false);
00754         ldns_pkt_set_tc(packet, false);
00755         ldns_pkt_set_rd(packet, false);
00756         ldns_pkt_set_ra(packet, false);
00757         ldns_pkt_set_ad(packet, false);
00758         ldns_pkt_set_cd(packet, false);
00759 
00760         ldns_pkt_set_opcode(packet, LDNS_PACKET_QUERY);
00761         ldns_pkt_set_rcode(packet, 0);
00762         ldns_pkt_set_id(packet, 0); 
00763         ldns_pkt_set_size(packet, 0);
00764         ldns_pkt_set_querytime(packet, 0);
00765         memset(&packet->timestamp, 0, sizeof(packet->timestamp));
00766         ldns_pkt_set_answerfrom(packet, NULL);
00767         ldns_pkt_set_section_count(packet, LDNS_SECTION_QUESTION, 0);
00768         ldns_pkt_set_section_count(packet, LDNS_SECTION_ANSWER, 0);
00769         ldns_pkt_set_section_count(packet, LDNS_SECTION_AUTHORITY, 0);
00770         ldns_pkt_set_section_count(packet, LDNS_SECTION_ADDITIONAL, 0);
00771         
00772         ldns_pkt_set_edns_udp_size(packet, 0);
00773         ldns_pkt_set_edns_extended_rcode(packet, 0);
00774         ldns_pkt_set_edns_version(packet, 0);
00775         ldns_pkt_set_edns_z(packet, 0);
00776         ldns_pkt_set_edns_data(packet, NULL);
00777         
00778         ldns_pkt_set_tsig(packet, NULL);
00779         
00780         return packet;
00781 }
00782 
00783 void
00784 ldns_pkt_free(ldns_pkt *packet)
00785 {
00786         if (packet) {
00787                 LDNS_FREE(packet->_header);
00788                 ldns_rr_list_deep_free(packet->_question);
00789                 ldns_rr_list_deep_free(packet->_answer);
00790                 ldns_rr_list_deep_free(packet->_authority);
00791                 ldns_rr_list_deep_free(packet->_additional);
00792                 ldns_rr_free(packet->_tsig_rr);
00793                 ldns_rdf_deep_free(packet->_edns_data);
00794                 ldns_rdf_deep_free(packet->_answerfrom);
00795                 LDNS_FREE(packet);
00796         }
00797 }
00798 
00799 bool
00800 ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags)
00801 {
00802         if (!packet) {
00803                 return false;
00804         }
00805         if ((flags & LDNS_QR) == LDNS_QR) {
00806                 ldns_pkt_set_qr(packet, true);
00807         }
00808         if ((flags & LDNS_AA) == LDNS_AA) {
00809                 ldns_pkt_set_aa(packet, true);
00810         }
00811         if ((flags & LDNS_RD) == LDNS_RD) {
00812                 ldns_pkt_set_rd(packet, true);
00813         }
00814         if ((flags & LDNS_TC) == LDNS_TC) {
00815                 ldns_pkt_set_tc(packet, true);
00816         }
00817         if ((flags & LDNS_CD) == LDNS_CD) {
00818                 ldns_pkt_set_cd(packet, true);
00819         }
00820         if ((flags & LDNS_RA) == LDNS_RA) {
00821                 ldns_pkt_set_ra(packet, true);
00822         }
00823         if ((flags & LDNS_AD) == LDNS_AD) {
00824                 ldns_pkt_set_ad(packet, true);
00825         }
00826         return true;
00827 }
00828 
00829 
00830 static ldns_status
00831 ldns_pkt_add_authsoa(ldns_pkt* packet, ldns_rdf* rr_name, ldns_rr_class rr_class)
00832 {
00833         ldns_rr* soa_rr = ldns_rr_new();
00834         ldns_rdf *owner_rdf;
00835         ldns_rdf *mname_rdf;
00836         ldns_rdf *rname_rdf;
00837         ldns_rdf *serial_rdf;
00838         ldns_rdf *refresh_rdf;
00839         ldns_rdf *retry_rdf;
00840         ldns_rdf *expire_rdf;
00841         ldns_rdf *minimum_rdf;
00842 
00843         if (!soa_rr) {
00844                 return LDNS_STATUS_MEM_ERR;
00845         }
00846         owner_rdf = ldns_rdf_clone(rr_name);
00847         if (!owner_rdf) {
00848                 ldns_rr_free(soa_rr);
00849                 return LDNS_STATUS_MEM_ERR;
00850         }
00851 
00852         ldns_rr_set_owner(soa_rr, owner_rdf);
00853         ldns_rr_set_type(soa_rr, LDNS_RR_TYPE_SOA);
00854         ldns_rr_set_class(soa_rr, rr_class);
00855         ldns_rr_set_question(soa_rr, false);
00856 
00857         if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) {
00858                 ldns_rr_free(soa_rr);
00859                 return LDNS_STATUS_MEM_ERR;
00860         } else {
00861                 ldns_rr_push_rdf(soa_rr, mname_rdf);
00862         }
00863         if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) {
00864                 ldns_rr_free(soa_rr);
00865                 return LDNS_STATUS_MEM_ERR;
00866         } else {
00867                 ldns_rr_push_rdf(soa_rr, rname_rdf);
00868         }
00869         serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
00870         if (!serial_rdf) {
00871                 ldns_rr_free(soa_rr);
00872                 return LDNS_STATUS_MEM_ERR;
00873         } else {
00874                 ldns_rr_push_rdf(soa_rr, serial_rdf);
00875         }
00876         refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
00877         if (!refresh_rdf) {
00878                 ldns_rr_free(soa_rr);
00879                 return LDNS_STATUS_MEM_ERR;
00880         } else {
00881                 ldns_rr_push_rdf(soa_rr, refresh_rdf);
00882         }
00883         retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
00884         if (!retry_rdf) {
00885                 ldns_rr_free(soa_rr);
00886                 return LDNS_STATUS_MEM_ERR;
00887         } else {
00888                 ldns_rr_push_rdf(soa_rr, retry_rdf);
00889         }
00890         expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
00891         if (!expire_rdf) {
00892                 ldns_rr_free(soa_rr);
00893                 return LDNS_STATUS_MEM_ERR;
00894         } else {
00895                 ldns_rr_push_rdf(soa_rr, expire_rdf);
00896         }
00897         minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
00898         if (!minimum_rdf) {
00899                 ldns_rr_free(soa_rr);
00900                 return LDNS_STATUS_MEM_ERR;
00901         } else {
00902                 ldns_rr_push_rdf(soa_rr, minimum_rdf);
00903         }
00904         ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, soa_rr);
00905         return LDNS_STATUS_OK;
00906 }
00907 
00908 
00909 ldns_status
00910 ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name, ldns_rr_type rr_type, 
00911                 ldns_rr_class rr_class, uint16_t flags)
00912 {
00913         ldns_pkt *packet;
00914         ldns_rr *question_rr;
00915         ldns_rdf *name_rdf;
00916 
00917         packet = ldns_pkt_new();
00918         if (!packet) {
00919                 return LDNS_STATUS_MEM_ERR;
00920         }
00921         
00922         if (!ldns_pkt_set_flags(packet, flags)) {
00923                 return LDNS_STATUS_ERR;
00924         }
00925         
00926         question_rr = ldns_rr_new();
00927         if (!question_rr) {
00928                 return LDNS_STATUS_MEM_ERR;
00929         }
00930 
00931         if (rr_type == 0) {
00932                 rr_type = LDNS_RR_TYPE_A;
00933         }
00934         if (rr_class == 0) {
00935                 rr_class = LDNS_RR_CLASS_IN;
00936         }
00937 
00938         if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
00939                 ldns_rr_set_owner(question_rr, name_rdf);
00940                 ldns_rr_set_type(question_rr, rr_type);
00941                 ldns_rr_set_class(question_rr, rr_class);
00942                 ldns_rr_set_question(question_rr, true);
00943 
00944                 ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
00945         } else {
00946                 ldns_rr_free(question_rr);
00947                 ldns_pkt_free(packet);
00948                 return LDNS_STATUS_ERR;
00949         }
00950 
00952         if (rr_type == LDNS_RR_TYPE_IXFR) {
00953                 if (ldns_pkt_add_authsoa(packet, name_rdf, rr_class) != LDNS_STATUS_OK) {
00954                         ldns_pkt_free(packet);
00955                         return LDNS_STATUS_ERR;
00956                 }
00957         }
00958 
00959         packet->_tsig_rr = NULL;
00960         ldns_pkt_set_answerfrom(packet, NULL);
00961         if (p) {
00962                 *p = packet;
00963                 return LDNS_STATUS_OK;
00964         } else {
00965                 ldns_pkt_free(packet);
00966                 return LDNS_STATUS_NULL;
00967         }
00968 }
00969 
00970 ldns_pkt *
00971 ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class,
00972                 uint16_t flags)
00973 {
00974         ldns_pkt *packet;
00975         ldns_rr *question_rr;
00976 
00977         packet = ldns_pkt_new();
00978         if (!packet) {
00979                 return NULL;
00980         }
00981 
00982         if (!ldns_pkt_set_flags(packet, flags)) {
00983                 return NULL;
00984         }
00985         
00986         question_rr = ldns_rr_new();
00987         if (!question_rr) {
00988                 ldns_pkt_free(packet);
00989                 return NULL;
00990         }
00991 
00992         if (rr_type == 0) {
00993                 rr_type = LDNS_RR_TYPE_A;
00994         }
00995         if (rr_class == 0) {
00996                 rr_class = LDNS_RR_CLASS_IN;
00997         }
00998 
00999         ldns_rr_set_owner(question_rr, rr_name);
01000         ldns_rr_set_type(question_rr, rr_type);
01001         ldns_rr_set_class(question_rr, rr_class);
01002         ldns_rr_set_question(question_rr, true);
01003         ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
01004 
01006         if (rr_type == LDNS_RR_TYPE_IXFR) {
01007                 if (ldns_pkt_add_authsoa(packet, rr_name, rr_class) != LDNS_STATUS_OK) {
01008                         ldns_pkt_free(packet);
01009                         return NULL;
01010                 }
01011         }
01012 
01013         packet->_tsig_rr = NULL;
01014         return packet;
01015 }
01016 
01017 ldns_pkt_type
01018 ldns_pkt_reply_type(ldns_pkt *p)
01019 {
01020         ldns_rr_list *tmp;
01021 
01022         if (!p) {
01023                 return LDNS_PACKET_UNKNOWN;
01024         }
01025 
01026         if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NXDOMAIN) {
01027                 return LDNS_PACKET_NXDOMAIN;
01028         }
01029 
01030         if (ldns_pkt_ancount(p) == 0 && ldns_pkt_arcount(p) == 0
01031                         && ldns_pkt_nscount(p) == 1) {
01032 
01033                 /* check for SOA */
01034                 tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_SOA, 
01035                                         LDNS_SECTION_AUTHORITY);
01036                 if (tmp) {
01037                         ldns_rr_list_deep_free(tmp);
01038                         return LDNS_PACKET_NODATA;
01039                 } else {
01040                         /* I have no idea ... */
01041                 }
01042         }
01043 
01044         if (ldns_pkt_ancount(p) == 0 && ldns_pkt_nscount(p) > 0) {
01045                 tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS,
01046                                                LDNS_SECTION_AUTHORITY);
01047                 if (tmp) {
01048                         /* there are nameservers here */
01049                         ldns_rr_list_deep_free(tmp);
01050                         return LDNS_PACKET_REFERRAL;
01051                 } else {
01052                         /* I have no idea */
01053                 }
01054                 ldns_rr_list_deep_free(tmp);
01055         }
01056         
01057         /* if we cannot determine the packet type, we say it's an 
01058          * answer...
01059          */
01060         return LDNS_PACKET_ANSWER;
01061 }
01062 
01063 ldns_pkt *
01064 ldns_pkt_clone(ldns_pkt *pkt)
01065 {
01066         ldns_pkt *new_pkt;
01067         
01068         if (!pkt) {
01069                 return NULL;
01070         }
01071         new_pkt = ldns_pkt_new();
01072 
01073         ldns_pkt_set_id(new_pkt, ldns_pkt_id(pkt));
01074         ldns_pkt_set_qr(new_pkt, ldns_pkt_qr(pkt));
01075         ldns_pkt_set_aa(new_pkt, ldns_pkt_aa(pkt));
01076         ldns_pkt_set_tc(new_pkt, ldns_pkt_tc(pkt));
01077         ldns_pkt_set_rd(new_pkt, ldns_pkt_rd(pkt));
01078         ldns_pkt_set_cd(new_pkt, ldns_pkt_cd(pkt));
01079         ldns_pkt_set_ra(new_pkt, ldns_pkt_ra(pkt));
01080         ldns_pkt_set_ad(new_pkt, ldns_pkt_ad(pkt));
01081         ldns_pkt_set_opcode(new_pkt, ldns_pkt_get_opcode(pkt));
01082         ldns_pkt_set_rcode(new_pkt, ldns_pkt_get_rcode(pkt));
01083         ldns_pkt_set_qdcount(new_pkt, ldns_pkt_qdcount(pkt));
01084         ldns_pkt_set_ancount(new_pkt, ldns_pkt_ancount(pkt));
01085         ldns_pkt_set_nscount(new_pkt, ldns_pkt_nscount(pkt));
01086         ldns_pkt_set_arcount(new_pkt, ldns_pkt_arcount(pkt));
01087         if (ldns_pkt_answerfrom(pkt))
01088                 ldns_pkt_set_answerfrom(new_pkt,
01089                         ldns_rdf_clone(ldns_pkt_answerfrom(pkt)));
01090         ldns_pkt_set_querytime(new_pkt, ldns_pkt_querytime(pkt));
01091         ldns_pkt_set_size(new_pkt, ldns_pkt_size(pkt));
01092         ldns_pkt_set_tsig(new_pkt, ldns_rr_clone(ldns_pkt_tsig(pkt)));
01093         
01094         ldns_pkt_set_edns_udp_size(new_pkt, ldns_pkt_edns_udp_size(pkt));
01095         ldns_pkt_set_edns_extended_rcode(new_pkt, 
01096                 ldns_pkt_edns_extended_rcode(pkt));
01097         ldns_pkt_set_edns_version(new_pkt, ldns_pkt_edns_version(pkt));
01098         ldns_pkt_set_edns_z(new_pkt, ldns_pkt_edns_z(pkt));
01099         if(ldns_pkt_edns_data(pkt))
01100                 ldns_pkt_set_edns_data(new_pkt, 
01101                         ldns_rdf_clone(ldns_pkt_edns_data(pkt)));
01102         ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt));
01103 
01104         ldns_rr_list_deep_free(new_pkt->_question);
01105         ldns_rr_list_deep_free(new_pkt->_answer);
01106         ldns_rr_list_deep_free(new_pkt->_authority);
01107         ldns_rr_list_deep_free(new_pkt->_additional);
01108         new_pkt->_question = ldns_rr_list_clone(ldns_pkt_question(pkt));
01109         new_pkt->_answer = ldns_rr_list_clone(ldns_pkt_answer(pkt));
01110         new_pkt->_authority = ldns_rr_list_clone(ldns_pkt_authority(pkt));
01111         new_pkt->_additional = ldns_rr_list_clone(ldns_pkt_additional(pkt));
01112         return new_pkt;
01113 }