packet.c revision 238104
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 *new; 259238104Sdes ldns_rr_list *ret; 260238104Sdes uint16_t i; 261238104Sdes 262238104Sdes if (!packet) { 263238104Sdes return NULL; 264238104Sdes } 265238104Sdes 266238104Sdes rrs = ldns_pkt_get_section_clone(packet, sec); 267238104Sdes new = ldns_rr_list_new(); 268238104Sdes ret = NULL; 269238104Sdes 270238104Sdes for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) { 271238104Sdes if (ldns_rdf_compare(ldns_rr_owner( 272238104Sdes ldns_rr_list_rr(rrs, i)), 273238104Sdes ownername) == 0) { 274238104Sdes /* owner names match */ 275238104Sdes ldns_rr_list_push_rr(new, ldns_rr_list_rr(rrs, i)); 276238104Sdes ret = new; 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)) && 340238104Sdes ldns_rdf_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 382238104Sdesuint16_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: 652238104Sdes ldns_rr_list_push_rr(ldns_pkt_question(packet), rr); 653238104Sdes ldns_pkt_set_qdcount(packet, ldns_pkt_qdcount(packet) + 1); 654238104Sdes break; 655238104Sdes case LDNS_SECTION_ANSWER: 656238104Sdes ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr); 657238104Sdes ldns_pkt_set_ancount(packet, ldns_pkt_ancount(packet) + 1); 658238104Sdes break; 659238104Sdes case LDNS_SECTION_AUTHORITY: 660238104Sdes ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr); 661238104Sdes ldns_pkt_set_nscount(packet, ldns_pkt_nscount(packet) + 1); 662238104Sdes break; 663238104Sdes case LDNS_SECTION_ADDITIONAL: 664238104Sdes ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr); 665238104Sdes ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + 1); 666238104Sdes break; 667238104Sdes case LDNS_SECTION_ANY: 668238104Sdes case LDNS_SECTION_ANY_NOQUESTION: 669238104Sdes /* shouldn't this error? */ 670238104Sdes break; 671238104Sdes } 672238104Sdes return true; 673238104Sdes} 674238104Sdes 675238104Sdesbool 676238104Sdesldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr) 677238104Sdes{ 678238104Sdes 679238104Sdes /* check to see if its there */ 680238104Sdes if (ldns_pkt_rr(pkt, sec, rr)) { 681238104Sdes /* already there */ 682238104Sdes return false; 683238104Sdes } 684238104Sdes return ldns_pkt_push_rr(pkt, sec, rr); 685238104Sdes} 686238104Sdes 687238104Sdesbool 688238104Sdesldns_pkt_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list) 689238104Sdes{ 690238104Sdes size_t i; 691238104Sdes for(i = 0; i < ldns_rr_list_rr_count(list); i++) { 692238104Sdes if (!ldns_pkt_push_rr(p, s, ldns_rr_list_rr(list, i))) { 693238104Sdes return false; 694238104Sdes } 695238104Sdes } 696238104Sdes return true; 697238104Sdes} 698238104Sdes 699238104Sdesbool 700238104Sdesldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list) 701238104Sdes{ 702238104Sdes size_t i; 703238104Sdes for(i = 0; i < ldns_rr_list_rr_count(list); i++) { 704238104Sdes if (!ldns_pkt_safe_push_rr(p, s, ldns_rr_list_rr(list, i))) { 705238104Sdes return false; 706238104Sdes } 707238104Sdes } 708238104Sdes return true; 709238104Sdes} 710238104Sdes 711238104Sdesbool 712238104Sdesldns_pkt_edns(const ldns_pkt *pkt) { 713238104Sdes return (ldns_pkt_edns_udp_size(pkt) > 0 || 714238104Sdes ldns_pkt_edns_extended_rcode(pkt) > 0 || 715238104Sdes ldns_pkt_edns_data(pkt) || 716238104Sdes ldns_pkt_edns_do(pkt) 717238104Sdes ); 718238104Sdes} 719238104Sdes 720238104Sdes 721238104Sdes/* Create/destroy/convert functions 722238104Sdes */ 723238104Sdesldns_pkt * 724238104Sdesldns_pkt_new() 725238104Sdes{ 726238104Sdes ldns_pkt *packet; 727238104Sdes packet = LDNS_MALLOC(ldns_pkt); 728238104Sdes if (!packet) { 729238104Sdes return NULL; 730238104Sdes } 731238104Sdes 732238104Sdes packet->_header = LDNS_MALLOC(ldns_hdr); 733238104Sdes if (!packet->_header) { 734238104Sdes LDNS_FREE(packet); 735238104Sdes return NULL; 736238104Sdes } 737238104Sdes 738238104Sdes packet->_question = ldns_rr_list_new(); 739238104Sdes packet->_answer = ldns_rr_list_new(); 740238104Sdes packet->_authority = ldns_rr_list_new(); 741238104Sdes packet->_additional = ldns_rr_list_new(); 742238104Sdes 743238104Sdes /* default everything to false */ 744238104Sdes ldns_pkt_set_qr(packet, false); 745238104Sdes ldns_pkt_set_aa(packet, false); 746238104Sdes ldns_pkt_set_tc(packet, false); 747238104Sdes ldns_pkt_set_rd(packet, false); 748238104Sdes ldns_pkt_set_ra(packet, false); 749238104Sdes ldns_pkt_set_ad(packet, false); 750238104Sdes ldns_pkt_set_cd(packet, false); 751238104Sdes 752238104Sdes ldns_pkt_set_opcode(packet, LDNS_PACKET_QUERY); 753238104Sdes ldns_pkt_set_rcode(packet, 0); 754238104Sdes ldns_pkt_set_id(packet, 0); 755238104Sdes ldns_pkt_set_size(packet, 0); 756238104Sdes ldns_pkt_set_querytime(packet, 0); 757238104Sdes memset(&packet->timestamp, 0, sizeof(packet->timestamp)); 758238104Sdes ldns_pkt_set_answerfrom(packet, NULL); 759238104Sdes ldns_pkt_set_section_count(packet, LDNS_SECTION_QUESTION, 0); 760238104Sdes ldns_pkt_set_section_count(packet, LDNS_SECTION_ANSWER, 0); 761238104Sdes ldns_pkt_set_section_count(packet, LDNS_SECTION_AUTHORITY, 0); 762238104Sdes ldns_pkt_set_section_count(packet, LDNS_SECTION_ADDITIONAL, 0); 763238104Sdes 764238104Sdes ldns_pkt_set_edns_udp_size(packet, 0); 765238104Sdes ldns_pkt_set_edns_extended_rcode(packet, 0); 766238104Sdes ldns_pkt_set_edns_version(packet, 0); 767238104Sdes ldns_pkt_set_edns_z(packet, 0); 768238104Sdes ldns_pkt_set_edns_data(packet, NULL); 769238104Sdes 770238104Sdes ldns_pkt_set_tsig(packet, NULL); 771238104Sdes 772238104Sdes return packet; 773238104Sdes} 774238104Sdes 775238104Sdesvoid 776238104Sdesldns_pkt_free(ldns_pkt *packet) 777238104Sdes{ 778238104Sdes if (packet) { 779238104Sdes LDNS_FREE(packet->_header); 780238104Sdes ldns_rr_list_deep_free(packet->_question); 781238104Sdes ldns_rr_list_deep_free(packet->_answer); 782238104Sdes ldns_rr_list_deep_free(packet->_authority); 783238104Sdes ldns_rr_list_deep_free(packet->_additional); 784238104Sdes ldns_rr_free(packet->_tsig_rr); 785238104Sdes ldns_rdf_deep_free(packet->_edns_data); 786238104Sdes LDNS_FREE(packet); 787238104Sdes } 788238104Sdes} 789238104Sdes 790238104Sdesbool 791238104Sdesldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags) 792238104Sdes{ 793238104Sdes if (!packet) { 794238104Sdes return false; 795238104Sdes } 796238104Sdes if ((flags & LDNS_QR) == LDNS_QR) { 797238104Sdes ldns_pkt_set_qr(packet, true); 798238104Sdes } 799238104Sdes if ((flags & LDNS_AA) == LDNS_AA) { 800238104Sdes ldns_pkt_set_aa(packet, true); 801238104Sdes } 802238104Sdes if ((flags & LDNS_RD) == LDNS_RD) { 803238104Sdes ldns_pkt_set_rd(packet, true); 804238104Sdes } 805238104Sdes if ((flags & LDNS_TC) == LDNS_TC) { 806238104Sdes ldns_pkt_set_tc(packet, true); 807238104Sdes } 808238104Sdes if ((flags & LDNS_CD) == LDNS_CD) { 809238104Sdes ldns_pkt_set_cd(packet, true); 810238104Sdes } 811238104Sdes if ((flags & LDNS_RA) == LDNS_RA) { 812238104Sdes ldns_pkt_set_ra(packet, true); 813238104Sdes } 814238104Sdes if ((flags & LDNS_AD) == LDNS_AD) { 815238104Sdes ldns_pkt_set_ad(packet, true); 816238104Sdes } 817238104Sdes return true; 818238104Sdes} 819238104Sdes 820238104Sdesldns_status 821238104Sdesldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name, ldns_rr_type rr_type, 822238104Sdes ldns_rr_class rr_class, uint16_t flags) 823238104Sdes{ 824238104Sdes ldns_pkt *packet; 825238104Sdes ldns_rr *question_rr; 826238104Sdes ldns_rdf *name_rdf; 827238104Sdes 828238104Sdes packet = ldns_pkt_new(); 829238104Sdes if (!packet) { 830238104Sdes return LDNS_STATUS_MEM_ERR; 831238104Sdes } 832238104Sdes 833238104Sdes if (!ldns_pkt_set_flags(packet, flags)) { 834238104Sdes return LDNS_STATUS_ERR; 835238104Sdes } 836238104Sdes 837238104Sdes question_rr = ldns_rr_new(); 838238104Sdes if (!question_rr) { 839238104Sdes return LDNS_STATUS_MEM_ERR; 840238104Sdes } 841238104Sdes 842238104Sdes if (rr_type == 0) { 843238104Sdes rr_type = LDNS_RR_TYPE_A; 844238104Sdes } 845238104Sdes if (rr_class == 0) { 846238104Sdes rr_class = LDNS_RR_CLASS_IN; 847238104Sdes } 848238104Sdes 849238104Sdes if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) { 850238104Sdes ldns_rr_set_owner(question_rr, name_rdf); 851238104Sdes ldns_rr_set_type(question_rr, rr_type); 852238104Sdes ldns_rr_set_class(question_rr, rr_class); 853238104Sdes ldns_rr_set_question(question_rr, true); 854238104Sdes 855238104Sdes ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr); 856238104Sdes } else { 857238104Sdes ldns_rr_free(question_rr); 858238104Sdes ldns_pkt_free(packet); 859238104Sdes return LDNS_STATUS_ERR; 860238104Sdes } 861238104Sdes 862238104Sdes packet->_tsig_rr = NULL; 863238104Sdes 864238104Sdes ldns_pkt_set_answerfrom(packet, NULL); 865238104Sdes if (p) { 866238104Sdes *p = packet; 867238104Sdes return LDNS_STATUS_OK; 868238104Sdes } else { 869238104Sdes return LDNS_STATUS_NULL; 870238104Sdes } 871238104Sdes} 872238104Sdes 873238104Sdesldns_pkt * 874238104Sdesldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class, 875238104Sdes uint16_t flags) 876238104Sdes{ 877238104Sdes ldns_pkt *packet; 878238104Sdes ldns_rr *question_rr; 879238104Sdes 880238104Sdes packet = ldns_pkt_new(); 881238104Sdes if (!packet) { 882238104Sdes return NULL; 883238104Sdes } 884238104Sdes 885238104Sdes if (!ldns_pkt_set_flags(packet, flags)) { 886238104Sdes return NULL; 887238104Sdes } 888238104Sdes 889238104Sdes question_rr = ldns_rr_new(); 890238104Sdes if (!question_rr) { 891238104Sdes return NULL; 892238104Sdes } 893238104Sdes 894238104Sdes if (rr_type == 0) { 895238104Sdes rr_type = LDNS_RR_TYPE_A; 896238104Sdes } 897238104Sdes if (rr_class == 0) { 898238104Sdes rr_class = LDNS_RR_CLASS_IN; 899238104Sdes } 900238104Sdes 901238104Sdes ldns_rr_set_owner(question_rr, rr_name); 902238104Sdes ldns_rr_set_type(question_rr, rr_type); 903238104Sdes ldns_rr_set_class(question_rr, rr_class); 904238104Sdes ldns_rr_set_question(question_rr, true); 905238104Sdes 906238104Sdes packet->_tsig_rr = NULL; 907238104Sdes 908238104Sdes ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr); 909238104Sdes 910238104Sdes return packet; 911238104Sdes} 912238104Sdes 913238104Sdesldns_pkt_type 914238104Sdesldns_pkt_reply_type(ldns_pkt *p) 915238104Sdes{ 916238104Sdes ldns_rr_list *tmp; 917238104Sdes 918238104Sdes if (!p) { 919238104Sdes return LDNS_PACKET_UNKNOWN; 920238104Sdes } 921238104Sdes 922238104Sdes if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NXDOMAIN) { 923238104Sdes return LDNS_PACKET_NXDOMAIN; 924238104Sdes } 925238104Sdes 926238104Sdes if (ldns_pkt_ancount(p) == 0 && ldns_pkt_arcount(p) == 0 927238104Sdes && ldns_pkt_nscount(p) == 1) { 928238104Sdes 929238104Sdes /* check for SOA */ 930238104Sdes tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_SOA, 931238104Sdes LDNS_SECTION_AUTHORITY); 932238104Sdes if (tmp) { 933238104Sdes ldns_rr_list_deep_free(tmp); 934238104Sdes return LDNS_PACKET_NODATA; 935238104Sdes } else { 936238104Sdes /* I have no idea ... */ 937238104Sdes } 938238104Sdes } 939238104Sdes 940238104Sdes if (ldns_pkt_ancount(p) == 0 && ldns_pkt_nscount(p) > 0) { 941238104Sdes tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS, 942238104Sdes LDNS_SECTION_AUTHORITY); 943238104Sdes if (tmp) { 944238104Sdes /* there are nameservers here */ 945238104Sdes ldns_rr_list_deep_free(tmp); 946238104Sdes return LDNS_PACKET_REFERRAL; 947238104Sdes } else { 948238104Sdes /* I have no idea */ 949238104Sdes } 950238104Sdes ldns_rr_list_deep_free(tmp); 951238104Sdes } 952238104Sdes 953238104Sdes /* if we cannot determine the packet type, we say it's an 954238104Sdes * answer... 955238104Sdes */ 956238104Sdes return LDNS_PACKET_ANSWER; 957238104Sdes} 958238104Sdes 959238104Sdesldns_pkt * 960238104Sdesldns_pkt_clone(ldns_pkt *pkt) 961238104Sdes{ 962238104Sdes ldns_pkt *new_pkt; 963238104Sdes 964238104Sdes if (!pkt) { 965238104Sdes return NULL; 966238104Sdes } 967238104Sdes new_pkt = ldns_pkt_new(); 968238104Sdes 969238104Sdes ldns_pkt_set_id(new_pkt, ldns_pkt_id(pkt)); 970238104Sdes ldns_pkt_set_qr(new_pkt, ldns_pkt_qr(pkt)); 971238104Sdes ldns_pkt_set_aa(new_pkt, ldns_pkt_aa(pkt)); 972238104Sdes ldns_pkt_set_tc(new_pkt, ldns_pkt_tc(pkt)); 973238104Sdes ldns_pkt_set_rd(new_pkt, ldns_pkt_rd(pkt)); 974238104Sdes ldns_pkt_set_cd(new_pkt, ldns_pkt_cd(pkt)); 975238104Sdes ldns_pkt_set_ra(new_pkt, ldns_pkt_ra(pkt)); 976238104Sdes ldns_pkt_set_ad(new_pkt, ldns_pkt_ad(pkt)); 977238104Sdes ldns_pkt_set_opcode(new_pkt, ldns_pkt_get_opcode(pkt)); 978238104Sdes ldns_pkt_set_rcode(new_pkt, ldns_pkt_get_rcode(pkt)); 979238104Sdes ldns_pkt_set_qdcount(new_pkt, ldns_pkt_qdcount(pkt)); 980238104Sdes ldns_pkt_set_ancount(new_pkt, ldns_pkt_ancount(pkt)); 981238104Sdes ldns_pkt_set_nscount(new_pkt, ldns_pkt_nscount(pkt)); 982238104Sdes ldns_pkt_set_arcount(new_pkt, ldns_pkt_arcount(pkt)); 983238104Sdes ldns_pkt_set_answerfrom(new_pkt, ldns_pkt_answerfrom(pkt)); 984238104Sdes ldns_pkt_set_querytime(new_pkt, ldns_pkt_querytime(pkt)); 985238104Sdes ldns_pkt_set_size(new_pkt, ldns_pkt_size(pkt)); 986238104Sdes ldns_pkt_set_tsig(new_pkt, ldns_rr_clone(ldns_pkt_tsig(pkt))); 987238104Sdes 988238104Sdes ldns_pkt_set_edns_udp_size(new_pkt, ldns_pkt_edns_udp_size(pkt)); 989238104Sdes ldns_pkt_set_edns_extended_rcode(new_pkt, 990238104Sdes ldns_pkt_edns_extended_rcode(pkt)); 991238104Sdes ldns_pkt_set_edns_version(new_pkt, ldns_pkt_edns_version(pkt)); 992238104Sdes ldns_pkt_set_edns_z(new_pkt, ldns_pkt_edns_z(pkt)); 993238104Sdes if(ldns_pkt_edns_data(pkt)) 994238104Sdes ldns_pkt_set_edns_data(new_pkt, 995238104Sdes ldns_rdf_clone(ldns_pkt_edns_data(pkt))); 996238104Sdes ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt)); 997238104Sdes 998238104Sdes ldns_rr_list_deep_free(new_pkt->_question); 999238104Sdes ldns_rr_list_deep_free(new_pkt->_answer); 1000238104Sdes ldns_rr_list_deep_free(new_pkt->_authority); 1001238104Sdes ldns_rr_list_deep_free(new_pkt->_additional); 1002238104Sdes new_pkt->_question = ldns_rr_list_clone(ldns_pkt_question(pkt)); 1003238104Sdes new_pkt->_answer = ldns_rr_list_clone(ldns_pkt_answer(pkt)); 1004238104Sdes new_pkt->_authority = ldns_rr_list_clone(ldns_pkt_authority(pkt)); 1005238104Sdes new_pkt->_additional = ldns_rr_list_clone(ldns_pkt_additional(pkt)); 1006238104Sdes return new_pkt; 1007238104Sdes} 1008