aboutsummaryrefslogtreecommitdiff
path: root/packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'packet.c')
-rw-r--r--packet.c113
1 files changed, 111 insertions, 2 deletions
diff --git a/packet.c b/packet.c
index 95f8f3fe4d24..afa59005c3bd 100644
--- a/packet.c
+++ b/packet.c
@@ -26,6 +26,7 @@
*/
#define LDNS_EDNS_MASK_DO_BIT 0x8000
+#define LDNS_EDNS_MASK_UNASSIGNED (0xFFFF & ~LDNS_EDNS_MASK_DO_BIT)
/* TODO defines for 3600 */
/* convert to and from numerical flag values */
@@ -242,6 +243,19 @@ ldns_pkt_set_edns_do(ldns_pkt *packet, bool value)
}
}
+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_pkt_edns_data(const ldns_pkt *packet)
{
@@ -375,6 +389,7 @@ ldns_pkt_rr(const ldns_pkt *pkt, ldns_pkt_section sec, const ldns_rr *rr)
return ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
case LDNS_SECTION_ANY:
result = ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
+ /* fallthrough */
case LDNS_SECTION_ANY_NOQUESTION:
result = result
|| ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr)
@@ -624,6 +639,15 @@ ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data)
}
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)
{
switch(s) {
@@ -723,15 +747,93 @@ ldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
}
bool
-ldns_pkt_edns(const ldns_pkt *pkt) {
+ldns_pkt_edns(const ldns_pkt *pkt)
+{
return (ldns_pkt_edns_udp_size(pkt) > 0 ||
ldns_pkt_edns_extended_rcode(pkt) > 0 ||
ldns_pkt_edns_data(pkt) ||
ldns_pkt_edns_do(pkt) ||
+ pkt->_edns_list ||
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
*/
@@ -781,8 +883,9 @@ ldns_pkt_new(void)
ldns_pkt_set_edns_version(packet, 0);
ldns_pkt_set_edns_z(packet, 0);
ldns_pkt_set_edns_data(packet, NULL);
+ packet->_edns_list = NULL;
packet->_edns_present = false;
-
+
ldns_pkt_set_tsig(packet, NULL);
return packet;
@@ -799,6 +902,7 @@ ldns_pkt_free(ldns_pkt *packet)
ldns_rr_list_deep_free(packet->_additional);
ldns_rr_free(packet->_tsig_rr);
ldns_rdf_deep_free(packet->_edns_data);
+ ldns_edns_option_list_deep_free(packet->_edns_list);
ldns_rdf_deep_free(packet->_answerfrom);
LDNS_FREE(packet);
}
@@ -928,11 +1032,13 @@ ldns_pkt_query_new_frm_str_internal(ldns_pkt **p, const char *name,
}
if (!ldns_pkt_set_flags(packet, flags)) {
+ ldns_pkt_free(packet);
return LDNS_STATUS_ERR;
}
question_rr = ldns_rr_new();
if (!question_rr) {
+ ldns_pkt_free(packet);
return LDNS_STATUS_MEM_ERR;
}
@@ -1146,6 +1252,9 @@ ldns_pkt_clone(const ldns_pkt *pkt)
ldns_pkt_set_edns_data(new_pkt,
ldns_rdf_clone(ldns_pkt_edns_data(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->_answer);