Changeset View
Changeset View
Standalone View
Standalone View
contrib/ldns/packet.c
/* | /* | ||||
* packet.c | * packet.c | ||||
* | * | ||||
* dns packet implementation | * dns packet implementation | ||||
* | * | ||||
* a Net::DNS like library for C | * a Net::DNS like library for C | ||||
* | * | ||||
* (c) NLnet Labs, 2004-2006 | * (c) NLnet Labs, 2004-2006 | ||||
* | * | ||||
* See the file LICENSE for the license | * See the file LICENSE for the license | ||||
*/ | */ | ||||
#include <ldns/config.h> | #include <ldns/config.h> | ||||
#include <ldns/ldns.h> | #include <ldns/ldns.h> | ||||
#include <ldns/internal.h> | |||||
#include <strings.h> | #include <strings.h> | ||||
#include <limits.h> | #include <limits.h> | ||||
#ifdef HAVE_SSL | #ifdef HAVE_SSL | ||||
#include <openssl/rand.h> | #include <openssl/rand.h> | ||||
#endif | #endif | ||||
/* Access functions | /* Access functions | ||||
* do this as functions to get type checking | * do this as functions to get type checking | ||||
*/ | */ | ||||
#define LDNS_EDNS_MASK_DO_BIT 0x8000 | #define LDNS_EDNS_MASK_DO_BIT 0x8000 | ||||
#define LDNS_EDNS_MASK_UNASSIGNED (0xFFFF & ~LDNS_EDNS_MASK_DO_BIT) | |||||
/* TODO defines for 3600 */ | /* TODO defines for 3600 */ | ||||
/* convert to and from numerical flag values */ | /* convert to and from numerical flag values */ | ||||
ldns_lookup_table ldns_edns_flags[] = { | ldns_lookup_table ldns_edns_flags[] = { | ||||
{ 3600, "do"}, | { 3600, "do"}, | ||||
{ 0, NULL} | { 0, NULL} | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 200 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
if (value) { | if (value) { | ||||
packet->_edns_z = packet->_edns_z | LDNS_EDNS_MASK_DO_BIT; | packet->_edns_z = packet->_edns_z | LDNS_EDNS_MASK_DO_BIT; | ||||
} else { | } else { | ||||
packet->_edns_z = packet->_edns_z & ~LDNS_EDNS_MASK_DO_BIT; | packet->_edns_z = packet->_edns_z & ~LDNS_EDNS_MASK_DO_BIT; | ||||
} | } | ||||
} | } | ||||
uint16_t | |||||
ldns_pkt_edns_unassigned(const ldns_pkt *packet) | |||||
{ | |||||
return (packet->_edns_z & LDNS_EDNS_MASK_UNASSIGNED); | |||||
} | |||||
void | |||||
ldns_pkt_set_edns_unassigned(ldns_pkt *packet, uint16_t value) | |||||
{ | |||||
packet->_edns_z = (packet->_edns_z & ~LDNS_EDNS_MASK_UNASSIGNED) | |||||
| (value & LDNS_EDNS_MASK_UNASSIGNED); | |||||
} | |||||
ldns_rdf * | ldns_rdf * | ||||
ldns_pkt_edns_data(const ldns_pkt *packet) | ldns_pkt_edns_data(const ldns_pkt *packet) | ||||
{ | { | ||||
return packet->_edns_data; | return packet->_edns_data; | ||||
} | } | ||||
/* return only those rr that share the ownername */ | /* return only those rr that share the ownername */ | ||||
ldns_rr_list * | ldns_rr_list * | ||||
▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | ldns_pkt_rr(const ldns_pkt *pkt, ldns_pkt_section sec, const ldns_rr *rr) | ||||
case LDNS_SECTION_ANSWER: | case LDNS_SECTION_ANSWER: | ||||
return ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr); | return ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr); | ||||
case LDNS_SECTION_AUTHORITY: | case LDNS_SECTION_AUTHORITY: | ||||
return ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr); | return ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr); | ||||
case LDNS_SECTION_ADDITIONAL: | case LDNS_SECTION_ADDITIONAL: | ||||
return ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr); | return ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr); | ||||
case LDNS_SECTION_ANY: | case LDNS_SECTION_ANY: | ||||
result = ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr); | result = ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr); | ||||
/* fallthrough */ | |||||
case LDNS_SECTION_ANY_NOQUESTION: | case LDNS_SECTION_ANY_NOQUESTION: | ||||
result = result | result = result | ||||
|| ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr) | || ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr) | ||||
|| ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr) | || ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr) | ||||
|| ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr); | || ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr); | ||||
} | } | ||||
return result; | return result; | ||||
▲ Show 20 Lines • Show All 233 Lines • ▼ Show 20 Lines | |||||
void | void | ||||
ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data) | ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data) | ||||
{ | { | ||||
packet->_edns_data = data; | packet->_edns_data = data; | ||||
} | } | ||||
void | void | ||||
ldns_pkt_set_edns_option_list(ldns_pkt *packet, ldns_edns_option_list *list) | |||||
{ | |||||
if (packet->_edns_list) | |||||
ldns_edns_option_list_deep_free(packet->_edns_list); | |||||
packet->_edns_list = list; | |||||
} | |||||
void | |||||
ldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count) | ldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count) | ||||
{ | { | ||||
switch(s) { | switch(s) { | ||||
case LDNS_SECTION_QUESTION: | case LDNS_SECTION_QUESTION: | ||||
ldns_pkt_set_qdcount(packet, count); | ldns_pkt_set_qdcount(packet, count); | ||||
break; | break; | ||||
case LDNS_SECTION_ANSWER: | case LDNS_SECTION_ANSWER: | ||||
ldns_pkt_set_ancount(packet, count); | ldns_pkt_set_ancount(packet, count); | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | for(i = 0; i < ldns_rr_list_rr_count(list); i++) { | ||||
if (!ldns_pkt_safe_push_rr(p, s, ldns_rr_list_rr(list, i))) { | if (!ldns_pkt_safe_push_rr(p, s, ldns_rr_list_rr(list, i))) { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool | bool | ||||
ldns_pkt_edns(const ldns_pkt *pkt) { | ldns_pkt_edns(const ldns_pkt *pkt) | ||||
{ | |||||
return (ldns_pkt_edns_udp_size(pkt) > 0 || | return (ldns_pkt_edns_udp_size(pkt) > 0 || | ||||
ldns_pkt_edns_extended_rcode(pkt) > 0 || | ldns_pkt_edns_extended_rcode(pkt) > 0 || | ||||
ldns_pkt_edns_data(pkt) || | ldns_pkt_edns_data(pkt) || | ||||
ldns_pkt_edns_do(pkt) || | ldns_pkt_edns_do(pkt) || | ||||
pkt->_edns_list || | |||||
pkt->_edns_present | pkt->_edns_present | ||||
); | ); | ||||
} | } | ||||
ldns_edns_option_list* | |||||
pkt_edns_data2edns_option_list(const ldns_rdf *edns_data) | |||||
{ | |||||
size_t pos = 0; | |||||
ldns_edns_option_list* edns_list; | |||||
size_t max; | |||||
const uint8_t* wire; | |||||
if (!edns_data) | |||||
return NULL; | |||||
max = ldns_rdf_size(edns_data); | |||||
wire = ldns_rdf_data(edns_data); | |||||
if (!max) | |||||
return NULL; | |||||
if (!(edns_list = ldns_edns_option_list_new())) | |||||
return NULL; | |||||
while (pos < max) { | |||||
ldns_edns_option* edns; | |||||
uint8_t *data; | |||||
if (pos + 4 > max) { /* make sure the header is */ | |||||
ldns_edns_option_list_deep_free(edns_list); | |||||
return NULL; | |||||
} | |||||
ldns_edns_option_code code = ldns_read_uint16(&wire[pos]); | |||||
size_t size = ldns_read_uint16(&wire[pos+2]); | |||||
pos += 4; | |||||
if (pos + size > max) { /* make sure the size fits the data */ | |||||
ldns_edns_option_list_deep_free(edns_list); | |||||
return NULL; | |||||
} | |||||
data = LDNS_XMALLOC(uint8_t, size); | |||||
if (!data) { | |||||
ldns_edns_option_list_deep_free(edns_list); | |||||
return NULL; | |||||
} | |||||
memcpy(data, &wire[pos], size); | |||||
pos += size; | |||||
edns = ldns_edns_new(code, size, data); | |||||
if (!edns) { | |||||
ldns_edns_option_list_deep_free(edns_list); | |||||
return NULL; | |||||
} | |||||
if (!ldns_edns_option_list_push(edns_list, edns)) { | |||||
ldns_edns_option_list_deep_free(edns_list); | |||||
return NULL; | |||||
} | |||||
} | |||||
return edns_list; | |||||
} | |||||
ldns_edns_option_list* | |||||
ldns_pkt_edns_get_option_list(ldns_pkt *packet) | |||||
{ | |||||
/* return the list if it already exists */ | |||||
if (packet->_edns_list != NULL) | |||||
return packet->_edns_list; | |||||
/* if the list doesn't exists, we create it by parsing the | |||||
* packet->_edns_data | |||||
*/ | |||||
if (!ldns_pkt_edns_data(packet)) | |||||
return NULL; | |||||
return ( packet->_edns_list | |||||
= pkt_edns_data2edns_option_list(ldns_pkt_edns_data(packet))); | |||||
} | |||||
/* Create/destroy/convert functions | /* Create/destroy/convert functions | ||||
*/ | */ | ||||
ldns_pkt * | ldns_pkt * | ||||
ldns_pkt_new(void) | ldns_pkt_new(void) | ||||
{ | { | ||||
ldns_pkt *packet; | ldns_pkt *packet; | ||||
packet = LDNS_MALLOC(ldns_pkt); | packet = LDNS_MALLOC(ldns_pkt); | ||||
if (!packet) { | if (!packet) { | ||||
Show All 32 Lines | ldns_pkt_new(void) | ||||
ldns_pkt_set_section_count(packet, LDNS_SECTION_AUTHORITY, 0); | ldns_pkt_set_section_count(packet, LDNS_SECTION_AUTHORITY, 0); | ||||
ldns_pkt_set_section_count(packet, LDNS_SECTION_ADDITIONAL, 0); | ldns_pkt_set_section_count(packet, LDNS_SECTION_ADDITIONAL, 0); | ||||
ldns_pkt_set_edns_udp_size(packet, 0); | ldns_pkt_set_edns_udp_size(packet, 0); | ||||
ldns_pkt_set_edns_extended_rcode(packet, 0); | ldns_pkt_set_edns_extended_rcode(packet, 0); | ||||
ldns_pkt_set_edns_version(packet, 0); | ldns_pkt_set_edns_version(packet, 0); | ||||
ldns_pkt_set_edns_z(packet, 0); | ldns_pkt_set_edns_z(packet, 0); | ||||
ldns_pkt_set_edns_data(packet, NULL); | ldns_pkt_set_edns_data(packet, NULL); | ||||
packet->_edns_list = NULL; | |||||
packet->_edns_present = false; | packet->_edns_present = false; | ||||
ldns_pkt_set_tsig(packet, NULL); | ldns_pkt_set_tsig(packet, NULL); | ||||
return packet; | return packet; | ||||
} | } | ||||
void | void | ||||
ldns_pkt_free(ldns_pkt *packet) | ldns_pkt_free(ldns_pkt *packet) | ||||
{ | { | ||||
if (packet) { | if (packet) { | ||||
LDNS_FREE(packet->_header); | LDNS_FREE(packet->_header); | ||||
ldns_rr_list_deep_free(packet->_question); | ldns_rr_list_deep_free(packet->_question); | ||||
ldns_rr_list_deep_free(packet->_answer); | ldns_rr_list_deep_free(packet->_answer); | ||||
ldns_rr_list_deep_free(packet->_authority); | ldns_rr_list_deep_free(packet->_authority); | ||||
ldns_rr_list_deep_free(packet->_additional); | ldns_rr_list_deep_free(packet->_additional); | ||||
ldns_rr_free(packet->_tsig_rr); | ldns_rr_free(packet->_tsig_rr); | ||||
ldns_rdf_deep_free(packet->_edns_data); | ldns_rdf_deep_free(packet->_edns_data); | ||||
ldns_edns_option_list_deep_free(packet->_edns_list); | |||||
ldns_rdf_deep_free(packet->_answerfrom); | ldns_rdf_deep_free(packet->_answerfrom); | ||||
LDNS_FREE(packet); | LDNS_FREE(packet); | ||||
} | } | ||||
} | } | ||||
bool | bool | ||||
ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags) | ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | ldns_pkt_query_new_frm_str_internal(ldns_pkt **p, const char *name, | ||||
ldns_rdf *name_rdf; | ldns_rdf *name_rdf; | ||||
packet = ldns_pkt_new(); | packet = ldns_pkt_new(); | ||||
if (!packet) { | if (!packet) { | ||||
return LDNS_STATUS_MEM_ERR; | return LDNS_STATUS_MEM_ERR; | ||||
} | } | ||||
if (!ldns_pkt_set_flags(packet, flags)) { | if (!ldns_pkt_set_flags(packet, flags)) { | ||||
ldns_pkt_free(packet); | |||||
return LDNS_STATUS_ERR; | return LDNS_STATUS_ERR; | ||||
} | } | ||||
question_rr = ldns_rr_new(); | question_rr = ldns_rr_new(); | ||||
if (!question_rr) { | if (!question_rr) { | ||||
ldns_pkt_free(packet); | |||||
return LDNS_STATUS_MEM_ERR; | return LDNS_STATUS_MEM_ERR; | ||||
} | } | ||||
if (rr_type == 0) { | if (rr_type == 0) { | ||||
rr_type = LDNS_RR_TYPE_A; | rr_type = LDNS_RR_TYPE_A; | ||||
} | } | ||||
if (rr_class == 0) { | if (rr_class == 0) { | ||||
rr_class = LDNS_RR_CLASS_IN; | rr_class = LDNS_RR_CLASS_IN; | ||||
▲ Show 20 Lines • Show All 197 Lines • ▼ Show 20 Lines | ldns_pkt_set_edns_extended_rcode(new_pkt, | ||||
ldns_pkt_edns_extended_rcode(pkt)); | ldns_pkt_edns_extended_rcode(pkt)); | ||||
ldns_pkt_set_edns_version(new_pkt, ldns_pkt_edns_version(pkt)); | ldns_pkt_set_edns_version(new_pkt, ldns_pkt_edns_version(pkt)); | ||||
new_pkt->_edns_present = pkt->_edns_present; | new_pkt->_edns_present = pkt->_edns_present; | ||||
ldns_pkt_set_edns_z(new_pkt, ldns_pkt_edns_z(pkt)); | ldns_pkt_set_edns_z(new_pkt, ldns_pkt_edns_z(pkt)); | ||||
if(ldns_pkt_edns_data(pkt)) | if(ldns_pkt_edns_data(pkt)) | ||||
ldns_pkt_set_edns_data(new_pkt, | ldns_pkt_set_edns_data(new_pkt, | ||||
ldns_rdf_clone(ldns_pkt_edns_data(pkt))); | ldns_rdf_clone(ldns_pkt_edns_data(pkt))); | ||||
ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt)); | ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt)); | ||||
if (pkt->_edns_list) | |||||
ldns_pkt_set_edns_option_list(new_pkt, | |||||
ldns_edns_option_list_clone(pkt->_edns_list)); | |||||
ldns_rr_list_deep_free(new_pkt->_question); | ldns_rr_list_deep_free(new_pkt->_question); | ||||
ldns_rr_list_deep_free(new_pkt->_answer); | ldns_rr_list_deep_free(new_pkt->_answer); | ||||
ldns_rr_list_deep_free(new_pkt->_authority); | ldns_rr_list_deep_free(new_pkt->_authority); | ||||
ldns_rr_list_deep_free(new_pkt->_additional); | ldns_rr_list_deep_free(new_pkt->_additional); | ||||
new_pkt->_question = ldns_rr_list_clone(ldns_pkt_question(pkt)); | new_pkt->_question = ldns_rr_list_clone(ldns_pkt_question(pkt)); | ||||
new_pkt->_answer = ldns_rr_list_clone(ldns_pkt_answer(pkt)); | new_pkt->_answer = ldns_rr_list_clone(ldns_pkt_answer(pkt)); | ||||
new_pkt->_authority = ldns_rr_list_clone(ldns_pkt_authority(pkt)); | new_pkt->_authority = ldns_rr_list_clone(ldns_pkt_authority(pkt)); | ||||
new_pkt->_additional = ldns_rr_list_clone(ldns_pkt_additional(pkt)); | new_pkt->_additional = ldns_rr_list_clone(ldns_pkt_additional(pkt)); | ||||
return new_pkt; | return new_pkt; | ||||
} | } |