1238104Sdes/* 2238104Sdes * packet.c 3238104Sdes * 4238104Sdes * dns packet implementation 5238104Sdes * 6238104Sdes * a Net::DNS like library for C 7238104Sdes * 8238104Sdes * (c) NLnet Labs, 2004-2006 9238104Sdes * 10238104Sdes * See the file LICENSE for the license 11238104Sdes */ 12238104Sdes 13238104Sdes#include <ldns/config.h> 14238104Sdes 15238104Sdes#include <ldns/ldns.h> 16238104Sdes 17238104Sdes#include <strings.h> 18238104Sdes#include <limits.h> 19238104Sdes 20238104Sdes#ifdef HAVE_SSL 21238104Sdes#include <openssl/rand.h> 22238104Sdes#endif 23238104Sdes 24238104Sdes/* Access functions 25238104Sdes * do this as functions to get type checking 26238104Sdes */ 27238104Sdes 28238104Sdes#define LDNS_EDNS_MASK_DO_BIT 0x8000 29238104Sdes 30238104Sdes/* TODO defines for 3600 */ 31238104Sdes/* convert to and from numerical flag values */ 32238104Sdesldns_lookup_table ldns_edns_flags[] = { 33238104Sdes { 3600, "do"}, 34238104Sdes { 0, NULL} 35238104Sdes}; 36238104Sdes 37238104Sdes/* read */ 38238104Sdesuint16_t 39238104Sdesldns_pkt_id(const ldns_pkt *packet) 40238104Sdes{ 41238104Sdes return packet->_header->_id; 42238104Sdes} 43238104Sdes 44238104Sdesbool 45238104Sdesldns_pkt_qr(const ldns_pkt *packet) 46238104Sdes{ 47238104Sdes return packet->_header->_qr; 48238104Sdes} 49238104Sdes 50238104Sdesbool 51238104Sdesldns_pkt_aa(const ldns_pkt *packet) 52238104Sdes{ 53238104Sdes return packet->_header->_aa; 54238104Sdes} 55238104Sdes 56238104Sdesbool 57238104Sdesldns_pkt_tc(const ldns_pkt *packet) 58238104Sdes{ 59238104Sdes return packet->_header->_tc; 60238104Sdes} 61238104Sdes 62238104Sdesbool 63238104Sdesldns_pkt_rd(const ldns_pkt *packet) 64238104Sdes{ 65238104Sdes return packet->_header->_rd; 66238104Sdes} 67238104Sdes 68238104Sdesbool 69238104Sdesldns_pkt_cd(const ldns_pkt *packet) 70238104Sdes{ 71238104Sdes return packet->_header->_cd; 72238104Sdes} 73238104Sdes 74238104Sdesbool 75238104Sdesldns_pkt_ra(const ldns_pkt *packet) 76238104Sdes{ 77238104Sdes return packet->_header->_ra; 78238104Sdes} 79238104Sdes 80238104Sdesbool 81238104Sdesldns_pkt_ad(const ldns_pkt *packet) 82238104Sdes{ 83238104Sdes return packet->_header->_ad; 84238104Sdes} 85238104Sdes 86238104Sdesldns_pkt_opcode 87238104Sdesldns_pkt_get_opcode(const ldns_pkt *packet) 88238104Sdes{ 89238104Sdes return packet->_header->_opcode; 90238104Sdes} 91238104Sdes 92238104Sdesldns_pkt_rcode 93238104Sdesldns_pkt_get_rcode(const ldns_pkt *packet) 94238104Sdes{ 95238104Sdes return packet->_header->_rcode; 96238104Sdes} 97238104Sdes 98238104Sdesuint16_t 99238104Sdesldns_pkt_qdcount(const ldns_pkt *packet) 100238104Sdes{ 101238104Sdes return packet->_header->_qdcount; 102238104Sdes} 103238104Sdes 104238104Sdesuint16_t 105238104Sdesldns_pkt_ancount(const ldns_pkt *packet) 106238104Sdes{ 107238104Sdes return packet->_header->_ancount; 108238104Sdes} 109238104Sdes 110238104Sdesuint16_t 111238104Sdesldns_pkt_nscount(const ldns_pkt *packet) 112238104Sdes{ 113238104Sdes return packet->_header->_nscount; 114238104Sdes} 115238104Sdes 116238104Sdesuint16_t 117238104Sdesldns_pkt_arcount(const ldns_pkt *packet) 118238104Sdes{ 119238104Sdes return packet->_header->_arcount; 120238104Sdes} 121238104Sdes 122238104Sdesldns_rr_list * 123238104Sdesldns_pkt_question(const ldns_pkt *packet) 124238104Sdes{ 125238104Sdes return packet->_question; 126238104Sdes} 127238104Sdes 128238104Sdesldns_rr_list * 129238104Sdesldns_pkt_answer(const ldns_pkt *packet) 130238104Sdes{ 131238104Sdes return packet->_answer; 132238104Sdes} 133238104Sdes 134238104Sdesldns_rr_list * 135238104Sdesldns_pkt_authority(const ldns_pkt *packet) 136238104Sdes{ 137238104Sdes return packet->_authority; 138238104Sdes} 139238104Sdes 140238104Sdesldns_rr_list * 141238104Sdesldns_pkt_additional(const ldns_pkt *packet) 142238104Sdes{ 143238104Sdes return packet->_additional; 144238104Sdes} 145238104Sdes 146238104Sdes/* return ALL section concatenated */ 147238104Sdesldns_rr_list * 148238104Sdesldns_pkt_all(const ldns_pkt *packet) 149238104Sdes{ 150238104Sdes ldns_rr_list *all, *prev_all; 151238104Sdes 152238104Sdes all = ldns_rr_list_cat_clone( 153238104Sdes ldns_pkt_question(packet), 154238104Sdes ldns_pkt_answer(packet)); 155238104Sdes prev_all = all; 156238104Sdes all = ldns_rr_list_cat_clone(all, 157238104Sdes ldns_pkt_authority(packet)); 158238104Sdes ldns_rr_list_deep_free(prev_all); 159238104Sdes prev_all = all; 160238104Sdes all = ldns_rr_list_cat_clone(all, 161238104Sdes ldns_pkt_additional(packet)); 162238104Sdes ldns_rr_list_deep_free(prev_all); 163238104Sdes return all; 164238104Sdes} 165238104Sdes 166238104Sdesldns_rr_list * 167238104Sdesldns_pkt_all_noquestion(const ldns_pkt *packet) 168238104Sdes{ 169238104Sdes ldns_rr_list *all, *all2; 170238104Sdes 171238104Sdes all = ldns_rr_list_cat_clone( 172238104Sdes ldns_pkt_answer(packet), 173238104Sdes ldns_pkt_authority(packet)); 174238104Sdes all2 = ldns_rr_list_cat_clone(all, 175238104Sdes ldns_pkt_additional(packet)); 176238104Sdes 177238104Sdes ldns_rr_list_deep_free(all); 178238104Sdes return all2; 179238104Sdes} 180238104Sdes 181238104Sdessize_t 182238104Sdesldns_pkt_size(const ldns_pkt *packet) 183238104Sdes{ 184238104Sdes return packet->_size; 185238104Sdes} 186238104Sdes 187238104Sdesuint32_t 188238104Sdesldns_pkt_querytime(const ldns_pkt *packet) 189238104Sdes{ 190238104Sdes return packet->_querytime; 191238104Sdes} 192238104Sdes 193238104Sdesldns_rdf * 194238104Sdesldns_pkt_answerfrom(const ldns_pkt *packet) 195238104Sdes{ 196238104Sdes return packet->_answerfrom; 197238104Sdes} 198238104Sdes 199238104Sdesstruct timeval 200238104Sdesldns_pkt_timestamp(const ldns_pkt *packet) 201238104Sdes{ 202238104Sdes return packet->timestamp; 203238104Sdes} 204238104Sdes 205238104Sdesuint16_t 206238104Sdesldns_pkt_edns_udp_size(const ldns_pkt *packet) 207238104Sdes{ 208238104Sdes return packet->_edns_udp_size; 209238104Sdes} 210238104Sdes 211238104Sdesuint8_t 212238104Sdesldns_pkt_edns_extended_rcode(const ldns_pkt *packet) 213238104Sdes{ 214238104Sdes return packet->_edns_extended_rcode; 215238104Sdes} 216238104Sdes 217238104Sdesuint8_t 218238104Sdesldns_pkt_edns_version(const ldns_pkt *packet) 219238104Sdes{ 220238104Sdes return packet->_edns_version; 221238104Sdes} 222238104Sdes 223238104Sdesuint16_t 224238104Sdesldns_pkt_edns_z(const ldns_pkt *packet) 225238104Sdes{ 226238104Sdes return packet->_edns_z; 227238104Sdes} 228238104Sdes 229238104Sdesbool 230238104Sdesldns_pkt_edns_do(const ldns_pkt *packet) 231238104Sdes{ 232238104Sdes return (packet->_edns_z & LDNS_EDNS_MASK_DO_BIT); 233238104Sdes} 234238104Sdes 235238104Sdesvoid 236238104Sdesldns_pkt_set_edns_do(ldns_pkt *packet, bool value) 237238104Sdes{ 238238104Sdes if (value) { 239238104Sdes packet->_edns_z = packet->_edns_z | LDNS_EDNS_MASK_DO_BIT; 240238104Sdes } else { 241238104Sdes packet->_edns_z = packet->_edns_z & ~LDNS_EDNS_MASK_DO_BIT; 242238104Sdes } 243238104Sdes} 244238104Sdes 245238104Sdesldns_rdf * 246238104Sdesldns_pkt_edns_data(const ldns_pkt *packet) 247238104Sdes{ 248238104Sdes return packet->_edns_data; 249238104Sdes} 250238104Sdes 251238104Sdes/* return only those rr that share the ownername */ 252238104Sdesldns_rr_list * 253238104Sdesldns_pkt_rr_list_by_name(ldns_pkt *packet, 254238104Sdes ldns_rdf *ownername, 255238104Sdes ldns_pkt_section sec) 256238104Sdes{ 257238104Sdes ldns_rr_list *rrs; 258238104Sdes ldns_rr_list *ret; 259238104Sdes uint16_t i; 260238104Sdes 261238104Sdes if (!packet) { 262238104Sdes return NULL; 263238104Sdes } 264238104Sdes 265238104Sdes rrs = ldns_pkt_get_section_clone(packet, sec); 266238104Sdes ret = NULL; 267238104Sdes 268238104Sdes for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) { 269269257Sdes if (ldns_dname_compare(ldns_rr_owner( 270238104Sdes ldns_rr_list_rr(rrs, i)), 271238104Sdes ownername) == 0) { 272238104Sdes /* owner names match */ 273246854Sdes if (ret == NULL) { 274246854Sdes ret = ldns_rr_list_new(); 275246854Sdes } 276246854Sdes ldns_rr_list_push_rr(ret, ldns_rr_list_rr(rrs, i)); 277238104Sdes } 278238104Sdes } 279238104Sdes return ret; 280238104Sdes} 281238104Sdes 282238104Sdes/* return only those rr that share a type */ 283238104Sdesldns_rr_list * 284238104Sdesldns_pkt_rr_list_by_type(const ldns_pkt *packet, 285238104Sdes ldns_rr_type type, 286238104Sdes ldns_pkt_section sec) 287238104Sdes{ 288238104Sdes ldns_rr_list *rrs; 289238104Sdes ldns_rr_list *new; 290238104Sdes uint16_t i; 291238104Sdes 292238104Sdes if(!packet) { 293238104Sdes return NULL; 294238104Sdes } 295238104Sdes 296238104Sdes rrs = ldns_pkt_get_section_clone(packet, sec); 297238104Sdes new = ldns_rr_list_new(); 298238104Sdes 299238104Sdes for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) { 300238104Sdes if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i))) { 301238104Sdes /* types match */ 302238104Sdes ldns_rr_list_push_rr(new, 303238104Sdes ldns_rr_clone( 304238104Sdes ldns_rr_list_rr(rrs, i)) 305238104Sdes ); 306238104Sdes } 307238104Sdes } 308238104Sdes ldns_rr_list_deep_free(rrs); 309238104Sdes 310238104Sdes if (ldns_rr_list_rr_count(new) == 0) { 311238104Sdes ldns_rr_list_free(new); 312238104Sdes return NULL; 313238104Sdes } else { 314238104Sdes return new; 315238104Sdes } 316238104Sdes} 317238104Sdes 318238104Sdes/* return only those rrs that share name and type */ 319238104Sdesldns_rr_list * 320238104Sdesldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet, 321238104Sdes const ldns_rdf *ownername, 322238104Sdes ldns_rr_type type, 323238104Sdes ldns_pkt_section sec) 324238104Sdes{ 325238104Sdes ldns_rr_list *rrs; 326238104Sdes ldns_rr_list *new; 327238104Sdes ldns_rr_list *ret; 328238104Sdes uint16_t i; 329238104Sdes 330238104Sdes if(!packet) { 331238104Sdes return NULL; 332238104Sdes } 333238104Sdes 334238104Sdes rrs = ldns_pkt_get_section_clone(packet, sec); 335238104Sdes new = ldns_rr_list_new(); 336238104Sdes ret = NULL; 337238104Sdes 338238104Sdes for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) { 339238104Sdes if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i)) && 340269257Sdes ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(rrs, i)), 341238104Sdes ownername 342238104Sdes ) == 0 343238104Sdes ) { 344238104Sdes /* types match */ 345238104Sdes ldns_rr_list_push_rr(new, ldns_rr_clone(ldns_rr_list_rr(rrs, i))); 346238104Sdes ret = new; 347238104Sdes } 348238104Sdes } 349238104Sdes ldns_rr_list_deep_free(rrs); 350238104Sdes if (!ret) { 351238104Sdes ldns_rr_list_free(new); 352238104Sdes } 353238104Sdes return ret; 354238104Sdes} 355238104Sdes 356238104Sdesbool 357238104Sdesldns_pkt_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr) 358238104Sdes{ 359238104Sdes bool result = false; 360238104Sdes 361238104Sdes switch (sec) { 362238104Sdes case LDNS_SECTION_QUESTION: 363238104Sdes return ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr); 364238104Sdes case LDNS_SECTION_ANSWER: 365238104Sdes return ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr); 366238104Sdes case LDNS_SECTION_AUTHORITY: 367238104Sdes return ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr); 368238104Sdes case LDNS_SECTION_ADDITIONAL: 369238104Sdes return ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr); 370238104Sdes case LDNS_SECTION_ANY: 371238104Sdes result = ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr); 372238104Sdes case LDNS_SECTION_ANY_NOQUESTION: 373238104Sdes result = result 374238104Sdes || ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr) 375238104Sdes || ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr) 376238104Sdes || ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr); 377238104Sdes } 378238104Sdes 379238104Sdes return result; 380238104Sdes} 381238104Sdes 382269257Sdesuint16_t 383238104Sdesldns_pkt_section_count(const ldns_pkt *packet, ldns_pkt_section s) 384238104Sdes{ 385238104Sdes switch(s) { 386238104Sdes case LDNS_SECTION_QUESTION: 387238104Sdes return ldns_pkt_qdcount(packet); 388238104Sdes case LDNS_SECTION_ANSWER: 389238104Sdes return ldns_pkt_ancount(packet); 390238104Sdes case LDNS_SECTION_AUTHORITY: 391238104Sdes return ldns_pkt_nscount(packet); 392238104Sdes case LDNS_SECTION_ADDITIONAL: 393238104Sdes return ldns_pkt_arcount(packet); 394238104Sdes case LDNS_SECTION_ANY: 395238104Sdes return ldns_pkt_qdcount(packet) + 396238104Sdes ldns_pkt_ancount(packet) + 397238104Sdes ldns_pkt_nscount(packet) + 398238104Sdes ldns_pkt_arcount(packet); 399238104Sdes case LDNS_SECTION_ANY_NOQUESTION: 400238104Sdes return ldns_pkt_ancount(packet) + 401238104Sdes ldns_pkt_nscount(packet) + 402238104Sdes ldns_pkt_arcount(packet); 403238104Sdes default: 404238104Sdes return 0; 405238104Sdes } 406238104Sdes} 407238104Sdes 408238104Sdesbool 409238104Sdesldns_pkt_empty(ldns_pkt *p) 410238104Sdes{ 411238104Sdes if (!p) { 412238104Sdes return true; /* NULL is empty? */ 413238104Sdes } 414238104Sdes if (ldns_pkt_section_count(p, LDNS_SECTION_ANY) > 0) { 415238104Sdes return false; 416238104Sdes } else { 417238104Sdes return true; 418238104Sdes } 419238104Sdes} 420238104Sdes 421238104Sdes 422238104Sdesldns_rr_list * 423238104Sdesldns_pkt_get_section_clone(const ldns_pkt *packet, ldns_pkt_section s) 424238104Sdes{ 425238104Sdes switch(s) { 426238104Sdes case LDNS_SECTION_QUESTION: 427238104Sdes return ldns_rr_list_clone(ldns_pkt_question(packet)); 428238104Sdes case LDNS_SECTION_ANSWER: 429238104Sdes return ldns_rr_list_clone(ldns_pkt_answer(packet)); 430238104Sdes case LDNS_SECTION_AUTHORITY: 431238104Sdes return ldns_rr_list_clone(ldns_pkt_authority(packet)); 432238104Sdes case LDNS_SECTION_ADDITIONAL: 433238104Sdes return ldns_rr_list_clone(ldns_pkt_additional(packet)); 434238104Sdes case LDNS_SECTION_ANY: 435238104Sdes /* these are already clones */ 436238104Sdes return ldns_pkt_all(packet); 437238104Sdes case LDNS_SECTION_ANY_NOQUESTION: 438238104Sdes return ldns_pkt_all_noquestion(packet); 439238104Sdes default: 440238104Sdes return NULL; 441238104Sdes } 442238104Sdes} 443238104Sdes 444238104Sdesldns_rr *ldns_pkt_tsig(const ldns_pkt *pkt) { 445238104Sdes return pkt->_tsig_rr; 446238104Sdes} 447238104Sdes 448238104Sdes/* write */ 449238104Sdesvoid 450238104Sdesldns_pkt_set_id(ldns_pkt *packet, uint16_t id) 451238104Sdes{ 452238104Sdes packet->_header->_id = id; 453238104Sdes} 454238104Sdes 455238104Sdesvoid 456238104Sdesldns_pkt_set_random_id(ldns_pkt *packet) 457238104Sdes{ 458238104Sdes uint16_t rid = ldns_get_random(); 459238104Sdes ldns_pkt_set_id(packet, rid); 460238104Sdes} 461238104Sdes 462238104Sdes 463238104Sdesvoid 464238104Sdesldns_pkt_set_qr(ldns_pkt *packet, bool qr) 465238104Sdes{ 466238104Sdes packet->_header->_qr = qr; 467238104Sdes} 468238104Sdes 469238104Sdesvoid 470238104Sdesldns_pkt_set_aa(ldns_pkt *packet, bool aa) 471238104Sdes{ 472238104Sdes packet->_header->_aa = aa; 473238104Sdes} 474238104Sdes 475238104Sdesvoid 476238104Sdesldns_pkt_set_tc(ldns_pkt *packet, bool tc) 477238104Sdes{ 478238104Sdes packet->_header->_tc = tc; 479238104Sdes} 480238104Sdes 481238104Sdesvoid 482238104Sdesldns_pkt_set_rd(ldns_pkt *packet, bool rd) 483238104Sdes{ 484238104Sdes packet->_header->_rd = rd; 485238104Sdes} 486238104Sdes 487238104Sdesvoid 488238104Sdesldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr) 489238104Sdes{ 490238104Sdes p->_additional = rr; 491238104Sdes} 492238104Sdes 493238104Sdesvoid 494238104Sdesldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr) 495238104Sdes{ 496238104Sdes p->_question = rr; 497238104Sdes} 498238104Sdes 499238104Sdesvoid 500238104Sdesldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr) 501238104Sdes{ 502238104Sdes p->_answer = rr; 503238104Sdes} 504238104Sdes 505238104Sdesvoid 506238104Sdesldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr) 507238104Sdes{ 508238104Sdes p->_authority = rr; 509238104Sdes} 510238104Sdes 511238104Sdesvoid 512238104Sdesldns_pkt_set_cd(ldns_pkt *packet, bool cd) 513238104Sdes{ 514238104Sdes packet->_header->_cd = cd; 515238104Sdes} 516238104Sdes 517238104Sdesvoid 518238104Sdesldns_pkt_set_ra(ldns_pkt *packet, bool ra) 519238104Sdes{ 520238104Sdes packet->_header->_ra = ra; 521238104Sdes} 522238104Sdes 523238104Sdesvoid 524238104Sdesldns_pkt_set_ad(ldns_pkt *packet, bool ad) 525238104Sdes{ 526238104Sdes packet->_header->_ad = ad; 527238104Sdes} 528238104Sdes 529238104Sdesvoid 530238104Sdesldns_pkt_set_opcode(ldns_pkt *packet, ldns_pkt_opcode opcode) 531238104Sdes{ 532238104Sdes packet->_header->_opcode = opcode; 533238104Sdes} 534238104Sdes 535238104Sdesvoid 536238104Sdesldns_pkt_set_rcode(ldns_pkt *packet, uint8_t rcode) 537238104Sdes{ 538238104Sdes packet->_header->_rcode = rcode; 539238104Sdes} 540238104Sdes 541238104Sdesvoid 542238104Sdesldns_pkt_set_qdcount(ldns_pkt *packet, uint16_t qdcount) 543238104Sdes{ 544238104Sdes packet->_header->_qdcount = qdcount; 545238104Sdes} 546238104Sdes 547238104Sdesvoid 548238104Sdesldns_pkt_set_ancount(ldns_pkt *packet, uint16_t ancount) 549238104Sdes{ 550238104Sdes packet->_header->_ancount = ancount; 551238104Sdes} 552238104Sdes 553238104Sdesvoid 554238104Sdesldns_pkt_set_nscount(ldns_pkt *packet, uint16_t nscount) 555238104Sdes{ 556238104Sdes packet->_header->_nscount = nscount; 557238104Sdes} 558238104Sdes 559238104Sdesvoid 560238104Sdesldns_pkt_set_arcount(ldns_pkt *packet, uint16_t arcount) 561238104Sdes{ 562238104Sdes packet->_header->_arcount = arcount; 563238104Sdes} 564238104Sdes 565238104Sdesvoid 566238104Sdesldns_pkt_set_querytime(ldns_pkt *packet, uint32_t time) 567238104Sdes{ 568238104Sdes packet->_querytime = time; 569238104Sdes} 570238104Sdes 571238104Sdesvoid 572238104Sdesldns_pkt_set_answerfrom(ldns_pkt *packet, ldns_rdf *answerfrom) 573238104Sdes{ 574238104Sdes packet->_answerfrom = answerfrom; 575238104Sdes} 576238104Sdes 577238104Sdesvoid 578238104Sdesldns_pkt_set_timestamp(ldns_pkt *packet, struct timeval timeval) 579238104Sdes{ 580238104Sdes packet->timestamp.tv_sec = timeval.tv_sec; 581238104Sdes packet->timestamp.tv_usec = timeval.tv_usec; 582238104Sdes} 583238104Sdes 584238104Sdesvoid 585238104Sdesldns_pkt_set_size(ldns_pkt *packet, size_t s) 586238104Sdes{ 587238104Sdes packet->_size = s; 588238104Sdes} 589238104Sdes 590238104Sdesvoid 591238104Sdesldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s) 592238104Sdes{ 593238104Sdes packet->_edns_udp_size = s; 594238104Sdes} 595238104Sdes 596238104Sdesvoid 597238104Sdesldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c) 598238104Sdes{ 599238104Sdes packet->_edns_extended_rcode = c; 600238104Sdes} 601238104Sdes 602238104Sdesvoid 603238104Sdesldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v) 604238104Sdes{ 605238104Sdes packet->_edns_version = v; 606238104Sdes} 607238104Sdes 608238104Sdesvoid 609238104Sdesldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z) 610238104Sdes{ 611238104Sdes packet->_edns_z = z; 612238104Sdes} 613238104Sdes 614238104Sdesvoid 615238104Sdesldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data) 616238104Sdes{ 617238104Sdes packet->_edns_data = data; 618238104Sdes} 619238104Sdes 620238104Sdesvoid 621238104Sdesldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count) 622238104Sdes{ 623238104Sdes switch(s) { 624238104Sdes case LDNS_SECTION_QUESTION: 625238104Sdes ldns_pkt_set_qdcount(packet, count); 626238104Sdes break; 627238104Sdes case LDNS_SECTION_ANSWER: 628238104Sdes ldns_pkt_set_ancount(packet, count); 629238104Sdes break; 630238104Sdes case LDNS_SECTION_AUTHORITY: 631238104Sdes ldns_pkt_set_nscount(packet, count); 632238104Sdes break; 633238104Sdes case LDNS_SECTION_ADDITIONAL: 634238104Sdes ldns_pkt_set_arcount(packet, count); 635238104Sdes break; 636238104Sdes case LDNS_SECTION_ANY: 637238104Sdes case LDNS_SECTION_ANY_NOQUESTION: 638238104Sdes break; 639238104Sdes } 640238104Sdes} 641238104Sdes 642238104Sdesvoid ldns_pkt_set_tsig(ldns_pkt *pkt, ldns_rr *rr) 643238104Sdes{ 644238104Sdes pkt->_tsig_rr = rr; 645238104Sdes} 646238104Sdes 647238104Sdesbool 648238104Sdesldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr) 649238104Sdes{ 650238104Sdes switch(section) { 651238104Sdes case LDNS_SECTION_QUESTION: 652246854Sdes if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) { 653246854Sdes return false; 654246854Sdes } 655238104Sdes ldns_pkt_set_qdcount(packet, ldns_pkt_qdcount(packet) + 1); 656238104Sdes break; 657238104Sdes case LDNS_SECTION_ANSWER: 658246854Sdes if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) { 659246854Sdes return false; 660246854Sdes } 661238104Sdes ldns_pkt_set_ancount(packet, ldns_pkt_ancount(packet) + 1); 662238104Sdes break; 663238104Sdes case LDNS_SECTION_AUTHORITY: 664246854Sdes if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) { 665246854Sdes return false; 666246854Sdes } 667238104Sdes ldns_pkt_set_nscount(packet, ldns_pkt_nscount(packet) + 1); 668238104Sdes break; 669238104Sdes case LDNS_SECTION_ADDITIONAL: 670246854Sdes if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) { 671246854Sdes return false; 672246854Sdes } 673238104Sdes ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + 1); 674238104Sdes break; 675238104Sdes case LDNS_SECTION_ANY: 676238104Sdes case LDNS_SECTION_ANY_NOQUESTION: 677238104Sdes /* shouldn't this error? */ 678238104Sdes break; 679238104Sdes } 680238104Sdes return true; 681238104Sdes} 682238104Sdes 683238104Sdesbool 684238104Sdesldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr) 685238104Sdes{ 686238104Sdes 687238104Sdes /* check to see if its there */ 688238104Sdes if (ldns_pkt_rr(pkt, sec, rr)) { 689238104Sdes /* already there */ 690238104Sdes return false; 691238104Sdes } 692238104Sdes return ldns_pkt_push_rr(pkt, sec, rr); 693238104Sdes} 694238104Sdes 695238104Sdesbool 696238104Sdesldns_pkt_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list) 697238104Sdes{ 698238104Sdes size_t i; 699238104Sdes for(i = 0; i < ldns_rr_list_rr_count(list); i++) { 700238104Sdes if (!ldns_pkt_push_rr(p, s, ldns_rr_list_rr(list, i))) { 701238104Sdes return false; 702238104Sdes } 703238104Sdes } 704238104Sdes return true; 705238104Sdes} 706238104Sdes 707238104Sdesbool 708238104Sdesldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list) 709238104Sdes{ 710238104Sdes size_t i; 711238104Sdes for(i = 0; i < ldns_rr_list_rr_count(list); i++) { 712238104Sdes if (!ldns_pkt_safe_push_rr(p, s, ldns_rr_list_rr(list, i))) { 713238104Sdes return false; 714238104Sdes } 715238104Sdes } 716238104Sdes return true; 717238104Sdes} 718238104Sdes 719238104Sdesbool 720238104Sdesldns_pkt_edns(const ldns_pkt *pkt) { 721238104Sdes return (ldns_pkt_edns_udp_size(pkt) > 0 || 722238104Sdes ldns_pkt_edns_extended_rcode(pkt) > 0 || 723238104Sdes ldns_pkt_edns_data(pkt) || 724238104Sdes ldns_pkt_edns_do(pkt) 725238104Sdes ); 726238104Sdes} 727238104Sdes 728238104Sdes 729238104Sdes/* Create/destroy/convert functions 730238104Sdes */ 731238104Sdesldns_pkt * 732246827Sdesldns_pkt_new(void) 733238104Sdes{ 734238104Sdes ldns_pkt *packet; 735238104Sdes packet = LDNS_MALLOC(ldns_pkt); 736238104Sdes if (!packet) { 737238104Sdes return NULL; 738238104Sdes } 739238104Sdes 740238104Sdes packet->_header = LDNS_MALLOC(ldns_hdr); 741238104Sdes if (!packet->_header) { 742238104Sdes LDNS_FREE(packet); 743238104Sdes return NULL; 744238104Sdes } 745238104Sdes 746238104Sdes packet->_question = ldns_rr_list_new(); 747238104Sdes packet->_answer = ldns_rr_list_new(); 748238104Sdes packet->_authority = ldns_rr_list_new(); 749238104Sdes packet->_additional = ldns_rr_list_new(); 750238104Sdes 751238104Sdes /* default everything to false */ 752238104Sdes ldns_pkt_set_qr(packet, false); 753238104Sdes ldns_pkt_set_aa(packet, false); 754238104Sdes ldns_pkt_set_tc(packet, false); 755238104Sdes ldns_pkt_set_rd(packet, false); 756238104Sdes ldns_pkt_set_ra(packet, false); 757238104Sdes ldns_pkt_set_ad(packet, false); 758238104Sdes ldns_pkt_set_cd(packet, false); 759238104Sdes 760238104Sdes ldns_pkt_set_opcode(packet, LDNS_PACKET_QUERY); 761238104Sdes ldns_pkt_set_rcode(packet, 0); 762238104Sdes ldns_pkt_set_id(packet, 0); 763238104Sdes ldns_pkt_set_size(packet, 0); 764238104Sdes ldns_pkt_set_querytime(packet, 0); 765238104Sdes memset(&packet->timestamp, 0, sizeof(packet->timestamp)); 766238104Sdes ldns_pkt_set_answerfrom(packet, NULL); 767238104Sdes ldns_pkt_set_section_count(packet, LDNS_SECTION_QUESTION, 0); 768238104Sdes ldns_pkt_set_section_count(packet, LDNS_SECTION_ANSWER, 0); 769238104Sdes ldns_pkt_set_section_count(packet, LDNS_SECTION_AUTHORITY, 0); 770238104Sdes ldns_pkt_set_section_count(packet, LDNS_SECTION_ADDITIONAL, 0); 771238104Sdes 772238104Sdes ldns_pkt_set_edns_udp_size(packet, 0); 773238104Sdes ldns_pkt_set_edns_extended_rcode(packet, 0); 774238104Sdes ldns_pkt_set_edns_version(packet, 0); 775238104Sdes ldns_pkt_set_edns_z(packet, 0); 776238104Sdes ldns_pkt_set_edns_data(packet, NULL); 777238104Sdes 778238104Sdes ldns_pkt_set_tsig(packet, NULL); 779238104Sdes 780238104Sdes return packet; 781238104Sdes} 782238104Sdes 783238104Sdesvoid 784238104Sdesldns_pkt_free(ldns_pkt *packet) 785238104Sdes{ 786238104Sdes if (packet) { 787238104Sdes LDNS_FREE(packet->_header); 788238104Sdes ldns_rr_list_deep_free(packet->_question); 789238104Sdes ldns_rr_list_deep_free(packet->_answer); 790238104Sdes ldns_rr_list_deep_free(packet->_authority); 791238104Sdes ldns_rr_list_deep_free(packet->_additional); 792238104Sdes ldns_rr_free(packet->_tsig_rr); 793238104Sdes ldns_rdf_deep_free(packet->_edns_data); 794246854Sdes ldns_rdf_deep_free(packet->_answerfrom); 795238104Sdes LDNS_FREE(packet); 796238104Sdes } 797238104Sdes} 798238104Sdes 799238104Sdesbool 800238104Sdesldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags) 801238104Sdes{ 802238104Sdes if (!packet) { 803238104Sdes return false; 804238104Sdes } 805238104Sdes if ((flags & LDNS_QR) == LDNS_QR) { 806238104Sdes ldns_pkt_set_qr(packet, true); 807238104Sdes } 808238104Sdes if ((flags & LDNS_AA) == LDNS_AA) { 809238104Sdes ldns_pkt_set_aa(packet, true); 810238104Sdes } 811238104Sdes if ((flags & LDNS_RD) == LDNS_RD) { 812238104Sdes ldns_pkt_set_rd(packet, true); 813238104Sdes } 814238104Sdes if ((flags & LDNS_TC) == LDNS_TC) { 815238104Sdes ldns_pkt_set_tc(packet, true); 816238104Sdes } 817238104Sdes if ((flags & LDNS_CD) == LDNS_CD) { 818238104Sdes ldns_pkt_set_cd(packet, true); 819238104Sdes } 820238104Sdes if ((flags & LDNS_RA) == LDNS_RA) { 821238104Sdes ldns_pkt_set_ra(packet, true); 822238104Sdes } 823238104Sdes if ((flags & LDNS_AD) == LDNS_AD) { 824238104Sdes ldns_pkt_set_ad(packet, true); 825238104Sdes } 826238104Sdes return true; 827238104Sdes} 828238104Sdes 829246854Sdes 830269257Sdesstatic ldns_rr* 831269257Sdesldns_pkt_authsoa(ldns_rdf* rr_name, ldns_rr_class rr_class) 832246854Sdes{ 833246854Sdes ldns_rr* soa_rr = ldns_rr_new(); 834246854Sdes ldns_rdf *owner_rdf; 835246854Sdes ldns_rdf *mname_rdf; 836246854Sdes ldns_rdf *rname_rdf; 837246854Sdes ldns_rdf *serial_rdf; 838246854Sdes ldns_rdf *refresh_rdf; 839246854Sdes ldns_rdf *retry_rdf; 840246854Sdes ldns_rdf *expire_rdf; 841246854Sdes ldns_rdf *minimum_rdf; 842246854Sdes 843246854Sdes if (!soa_rr) { 844269257Sdes return NULL; 845246854Sdes } 846246854Sdes owner_rdf = ldns_rdf_clone(rr_name); 847246854Sdes if (!owner_rdf) { 848246854Sdes ldns_rr_free(soa_rr); 849269257Sdes return NULL; 850246854Sdes } 851246854Sdes 852246854Sdes ldns_rr_set_owner(soa_rr, owner_rdf); 853246854Sdes ldns_rr_set_type(soa_rr, LDNS_RR_TYPE_SOA); 854246854Sdes ldns_rr_set_class(soa_rr, rr_class); 855246854Sdes ldns_rr_set_question(soa_rr, false); 856246854Sdes 857246854Sdes if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) { 858246854Sdes ldns_rr_free(soa_rr); 859269257Sdes return NULL; 860246854Sdes } else { 861246854Sdes ldns_rr_push_rdf(soa_rr, mname_rdf); 862246854Sdes } 863246854Sdes if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) { 864246854Sdes ldns_rr_free(soa_rr); 865269257Sdes return NULL; 866246854Sdes } else { 867246854Sdes ldns_rr_push_rdf(soa_rr, rname_rdf); 868246854Sdes } 869246854Sdes serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0); 870246854Sdes if (!serial_rdf) { 871246854Sdes ldns_rr_free(soa_rr); 872269257Sdes return NULL; 873246854Sdes } else { 874246854Sdes ldns_rr_push_rdf(soa_rr, serial_rdf); 875246854Sdes } 876246854Sdes refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0); 877246854Sdes if (!refresh_rdf) { 878246854Sdes ldns_rr_free(soa_rr); 879269257Sdes return NULL; 880246854Sdes } else { 881246854Sdes ldns_rr_push_rdf(soa_rr, refresh_rdf); 882246854Sdes } 883246854Sdes retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0); 884246854Sdes if (!retry_rdf) { 885246854Sdes ldns_rr_free(soa_rr); 886269257Sdes return NULL; 887246854Sdes } else { 888246854Sdes ldns_rr_push_rdf(soa_rr, retry_rdf); 889246854Sdes } 890246854Sdes expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0); 891246854Sdes if (!expire_rdf) { 892246854Sdes ldns_rr_free(soa_rr); 893269257Sdes return NULL; 894246854Sdes } else { 895246854Sdes ldns_rr_push_rdf(soa_rr, expire_rdf); 896246854Sdes } 897246854Sdes minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0); 898246854Sdes if (!minimum_rdf) { 899246854Sdes ldns_rr_free(soa_rr); 900269257Sdes return NULL; 901246854Sdes } else { 902246854Sdes ldns_rr_push_rdf(soa_rr, minimum_rdf); 903246854Sdes } 904269257Sdes return soa_rr; 905246854Sdes} 906246854Sdes 907246854Sdes 908269257Sdesstatic ldns_status 909269257Sdesldns_pkt_query_new_frm_str_internal(ldns_pkt **p, const char *name, 910269257Sdes ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags, 911269257Sdes ldns_rr* authsoa_rr) 912238104Sdes{ 913238104Sdes ldns_pkt *packet; 914238104Sdes ldns_rr *question_rr; 915238104Sdes ldns_rdf *name_rdf; 916238104Sdes 917238104Sdes packet = ldns_pkt_new(); 918238104Sdes if (!packet) { 919238104Sdes return LDNS_STATUS_MEM_ERR; 920238104Sdes } 921269257Sdes 922238104Sdes if (!ldns_pkt_set_flags(packet, flags)) { 923238104Sdes return LDNS_STATUS_ERR; 924238104Sdes } 925269257Sdes 926238104Sdes question_rr = ldns_rr_new(); 927238104Sdes if (!question_rr) { 928238104Sdes return LDNS_STATUS_MEM_ERR; 929238104Sdes } 930238104Sdes 931238104Sdes if (rr_type == 0) { 932238104Sdes rr_type = LDNS_RR_TYPE_A; 933238104Sdes } 934238104Sdes if (rr_class == 0) { 935238104Sdes rr_class = LDNS_RR_CLASS_IN; 936238104Sdes } 937238104Sdes 938238104Sdes if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) { 939238104Sdes ldns_rr_set_owner(question_rr, name_rdf); 940238104Sdes ldns_rr_set_type(question_rr, rr_type); 941238104Sdes ldns_rr_set_class(question_rr, rr_class); 942238104Sdes ldns_rr_set_question(question_rr, true); 943246854Sdes 944238104Sdes ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr); 945238104Sdes } else { 946238104Sdes ldns_rr_free(question_rr); 947238104Sdes ldns_pkt_free(packet); 948238104Sdes return LDNS_STATUS_ERR; 949238104Sdes } 950246854Sdes 951269257Sdes if (authsoa_rr) { 952269257Sdes ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr); 953246854Sdes } 954246854Sdes 955238104Sdes packet->_tsig_rr = NULL; 956238104Sdes ldns_pkt_set_answerfrom(packet, NULL); 957238104Sdes if (p) { 958238104Sdes *p = packet; 959238104Sdes return LDNS_STATUS_OK; 960238104Sdes } else { 961246854Sdes ldns_pkt_free(packet); 962238104Sdes return LDNS_STATUS_NULL; 963238104Sdes } 964238104Sdes} 965238104Sdes 966269257Sdesldns_status 967269257Sdesldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name, 968269257Sdes ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags) 969238104Sdes{ 970269257Sdes return ldns_pkt_query_new_frm_str_internal(p, name, rr_type, 971269257Sdes rr_class, flags, NULL); 972269257Sdes} 973269257Sdes 974269257Sdesldns_status 975269257Sdesldns_pkt_ixfr_request_new_frm_str(ldns_pkt **p, const char *name, 976269257Sdes ldns_rr_class rr_class, uint16_t flags, ldns_rr *soa) 977269257Sdes{ 978269257Sdes ldns_rr* authsoa_rr = soa; 979269257Sdes if (!authsoa_rr) { 980269257Sdes ldns_rdf *name_rdf; 981269257Sdes if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) { 982269257Sdes authsoa_rr = ldns_pkt_authsoa(name_rdf, rr_class); 983269257Sdes } 984269257Sdes ldns_rdf_free(name_rdf); 985269257Sdes } 986269257Sdes return ldns_pkt_query_new_frm_str_internal(p, name, LDNS_RR_TYPE_IXFR, 987269257Sdes rr_class, flags, authsoa_rr); 988269257Sdes} 989269257Sdes 990269257Sdesstatic ldns_pkt * 991269257Sdesldns_pkt_query_new_internal(ldns_rdf *rr_name, ldns_rr_type rr_type, 992269257Sdes ldns_rr_class rr_class, uint16_t flags, ldns_rr* authsoa_rr) 993269257Sdes{ 994238104Sdes ldns_pkt *packet; 995238104Sdes ldns_rr *question_rr; 996238104Sdes 997238104Sdes packet = ldns_pkt_new(); 998238104Sdes if (!packet) { 999238104Sdes return NULL; 1000238104Sdes } 1001238104Sdes 1002238104Sdes if (!ldns_pkt_set_flags(packet, flags)) { 1003238104Sdes return NULL; 1004238104Sdes } 1005269257Sdes 1006238104Sdes question_rr = ldns_rr_new(); 1007238104Sdes if (!question_rr) { 1008246854Sdes ldns_pkt_free(packet); 1009238104Sdes return NULL; 1010238104Sdes } 1011238104Sdes 1012238104Sdes if (rr_type == 0) { 1013238104Sdes rr_type = LDNS_RR_TYPE_A; 1014238104Sdes } 1015238104Sdes if (rr_class == 0) { 1016238104Sdes rr_class = LDNS_RR_CLASS_IN; 1017238104Sdes } 1018238104Sdes 1019238104Sdes ldns_rr_set_owner(question_rr, rr_name); 1020238104Sdes ldns_rr_set_type(question_rr, rr_type); 1021238104Sdes ldns_rr_set_class(question_rr, rr_class); 1022238104Sdes ldns_rr_set_question(question_rr, true); 1023238104Sdes ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr); 1024238104Sdes 1025269257Sdes if (authsoa_rr) { 1026269257Sdes ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr); 1027246854Sdes } 1028246854Sdes 1029246854Sdes packet->_tsig_rr = NULL; 1030238104Sdes return packet; 1031238104Sdes} 1032238104Sdes 1033269257Sdesldns_pkt * 1034269257Sdesldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type, 1035269257Sdes ldns_rr_class rr_class, uint16_t flags) 1036269257Sdes{ 1037269257Sdes return ldns_pkt_query_new_internal(rr_name, rr_type, 1038269257Sdes rr_class, flags, NULL); 1039269257Sdes} 1040269257Sdes 1041269257Sdesldns_pkt * 1042269257Sdesldns_pkt_ixfr_request_new(ldns_rdf *rr_name, ldns_rr_class rr_class, 1043269257Sdes uint16_t flags, ldns_rr* soa) 1044269257Sdes{ 1045269257Sdes ldns_rr* authsoa_rr = soa; 1046269257Sdes if (!authsoa_rr) { 1047269257Sdes authsoa_rr = ldns_pkt_authsoa(rr_name, rr_class); 1048269257Sdes } 1049269257Sdes return ldns_pkt_query_new_internal(rr_name, LDNS_RR_TYPE_IXFR, 1050269257Sdes rr_class, flags, authsoa_rr); 1051269257Sdes} 1052269257Sdes 1053238104Sdesldns_pkt_type 1054238104Sdesldns_pkt_reply_type(ldns_pkt *p) 1055238104Sdes{ 1056238104Sdes ldns_rr_list *tmp; 1057238104Sdes 1058238104Sdes if (!p) { 1059238104Sdes return LDNS_PACKET_UNKNOWN; 1060238104Sdes } 1061238104Sdes 1062238104Sdes if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NXDOMAIN) { 1063238104Sdes return LDNS_PACKET_NXDOMAIN; 1064238104Sdes } 1065238104Sdes 1066238104Sdes if (ldns_pkt_ancount(p) == 0 && ldns_pkt_arcount(p) == 0 1067238104Sdes && ldns_pkt_nscount(p) == 1) { 1068238104Sdes 1069238104Sdes /* check for SOA */ 1070238104Sdes tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_SOA, 1071238104Sdes LDNS_SECTION_AUTHORITY); 1072238104Sdes if (tmp) { 1073238104Sdes ldns_rr_list_deep_free(tmp); 1074238104Sdes return LDNS_PACKET_NODATA; 1075238104Sdes } else { 1076238104Sdes /* I have no idea ... */ 1077238104Sdes } 1078238104Sdes } 1079238104Sdes 1080238104Sdes if (ldns_pkt_ancount(p) == 0 && ldns_pkt_nscount(p) > 0) { 1081238104Sdes tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS, 1082238104Sdes LDNS_SECTION_AUTHORITY); 1083238104Sdes if (tmp) { 1084238104Sdes /* there are nameservers here */ 1085238104Sdes ldns_rr_list_deep_free(tmp); 1086238104Sdes return LDNS_PACKET_REFERRAL; 1087238104Sdes } else { 1088238104Sdes /* I have no idea */ 1089238104Sdes } 1090238104Sdes ldns_rr_list_deep_free(tmp); 1091238104Sdes } 1092238104Sdes 1093238104Sdes /* if we cannot determine the packet type, we say it's an 1094238104Sdes * answer... 1095238104Sdes */ 1096238104Sdes return LDNS_PACKET_ANSWER; 1097238104Sdes} 1098238104Sdes 1099238104Sdesldns_pkt * 1100238104Sdesldns_pkt_clone(ldns_pkt *pkt) 1101238104Sdes{ 1102238104Sdes ldns_pkt *new_pkt; 1103238104Sdes 1104238104Sdes if (!pkt) { 1105238104Sdes return NULL; 1106238104Sdes } 1107238104Sdes new_pkt = ldns_pkt_new(); 1108238104Sdes 1109238104Sdes ldns_pkt_set_id(new_pkt, ldns_pkt_id(pkt)); 1110238104Sdes ldns_pkt_set_qr(new_pkt, ldns_pkt_qr(pkt)); 1111238104Sdes ldns_pkt_set_aa(new_pkt, ldns_pkt_aa(pkt)); 1112238104Sdes ldns_pkt_set_tc(new_pkt, ldns_pkt_tc(pkt)); 1113238104Sdes ldns_pkt_set_rd(new_pkt, ldns_pkt_rd(pkt)); 1114238104Sdes ldns_pkt_set_cd(new_pkt, ldns_pkt_cd(pkt)); 1115238104Sdes ldns_pkt_set_ra(new_pkt, ldns_pkt_ra(pkt)); 1116238104Sdes ldns_pkt_set_ad(new_pkt, ldns_pkt_ad(pkt)); 1117238104Sdes ldns_pkt_set_opcode(new_pkt, ldns_pkt_get_opcode(pkt)); 1118238104Sdes ldns_pkt_set_rcode(new_pkt, ldns_pkt_get_rcode(pkt)); 1119238104Sdes ldns_pkt_set_qdcount(new_pkt, ldns_pkt_qdcount(pkt)); 1120238104Sdes ldns_pkt_set_ancount(new_pkt, ldns_pkt_ancount(pkt)); 1121238104Sdes ldns_pkt_set_nscount(new_pkt, ldns_pkt_nscount(pkt)); 1122238104Sdes ldns_pkt_set_arcount(new_pkt, ldns_pkt_arcount(pkt)); 1123246854Sdes if (ldns_pkt_answerfrom(pkt)) 1124246854Sdes ldns_pkt_set_answerfrom(new_pkt, 1125246854Sdes ldns_rdf_clone(ldns_pkt_answerfrom(pkt))); 1126238104Sdes ldns_pkt_set_querytime(new_pkt, ldns_pkt_querytime(pkt)); 1127238104Sdes ldns_pkt_set_size(new_pkt, ldns_pkt_size(pkt)); 1128238104Sdes ldns_pkt_set_tsig(new_pkt, ldns_rr_clone(ldns_pkt_tsig(pkt))); 1129238104Sdes 1130238104Sdes ldns_pkt_set_edns_udp_size(new_pkt, ldns_pkt_edns_udp_size(pkt)); 1131238104Sdes ldns_pkt_set_edns_extended_rcode(new_pkt, 1132238104Sdes ldns_pkt_edns_extended_rcode(pkt)); 1133238104Sdes ldns_pkt_set_edns_version(new_pkt, ldns_pkt_edns_version(pkt)); 1134238104Sdes ldns_pkt_set_edns_z(new_pkt, ldns_pkt_edns_z(pkt)); 1135238104Sdes if(ldns_pkt_edns_data(pkt)) 1136238104Sdes ldns_pkt_set_edns_data(new_pkt, 1137238104Sdes ldns_rdf_clone(ldns_pkt_edns_data(pkt))); 1138238104Sdes ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt)); 1139238104Sdes 1140238104Sdes ldns_rr_list_deep_free(new_pkt->_question); 1141238104Sdes ldns_rr_list_deep_free(new_pkt->_answer); 1142238104Sdes ldns_rr_list_deep_free(new_pkt->_authority); 1143238104Sdes ldns_rr_list_deep_free(new_pkt->_additional); 1144238104Sdes new_pkt->_question = ldns_rr_list_clone(ldns_pkt_question(pkt)); 1145238104Sdes new_pkt->_answer = ldns_rr_list_clone(ldns_pkt_answer(pkt)); 1146238104Sdes new_pkt->_authority = ldns_rr_list_clone(ldns_pkt_authority(pkt)); 1147238104Sdes new_pkt->_additional = ldns_rr_list_clone(ldns_pkt_additional(pkt)); 1148238104Sdes return new_pkt; 1149238104Sdes} 1150