summaryrefslogtreecommitdiff
path: root/src/libknot
diff options
context:
space:
mode:
Diffstat (limited to 'src/libknot')
-rw-r--r--src/libknot/hash/cuckoo-hash-table.c2
-rw-r--r--src/libknot/nameserver/name-server.c89
-rw-r--r--src/libknot/packet/packet.c21
-rw-r--r--src/libknot/packet/packet.h27
-rw-r--r--src/libknot/packet/response.c88
-rw-r--r--src/libknot/packet/response.h4
6 files changed, 220 insertions, 11 deletions
diff --git a/src/libknot/hash/cuckoo-hash-table.c b/src/libknot/hash/cuckoo-hash-table.c
index 50a7a0f..9db32bf 100644
--- a/src/libknot/hash/cuckoo-hash-table.c
+++ b/src/libknot/hash/cuckoo-hash-table.c
@@ -1037,6 +1037,7 @@ int ck_update_item(const ck_hash_table_t *table, const char *key, size_t length,
ck_hash_table_item_t **item = ck_find_item_nc(table, key, length);
if (item == NULL || (*item) == NULL) {
+ rcu_read_unlock();
return -1;
}
@@ -1060,6 +1061,7 @@ int ck_delete_item(const ck_hash_table_t *table, const char *key, size_t length,
ck_hash_table_item_t **place = ck_find_item_nc(table, key, length);
if (place == NULL) {
+ rcu_read_unlock();
return -1;
}
diff --git a/src/libknot/nameserver/name-server.c b/src/libknot/nameserver/name-server.c
index d938683..7a6bc4d 100644
--- a/src/libknot/nameserver/name-server.c
+++ b/src/libknot/nameserver/name-server.c
@@ -298,6 +298,14 @@ static void ns_follow_cname(const knot_node_t **node,
add_rrset_to_resp(resp, rrset, tc, 0, 0, 1);
ns_add_rrsigs(cname_rrset, resp, *qname,
add_rrset_to_resp, tc);
+
+ int ret = knot_response_add_wildcard_node(
+ resp, *node, *qname);
+
+ /*! \todo Fix when return values are handled! */
+ if (ret != KNOT_EOK) {
+ assert(0);
+ }
} else {
add_rrset_to_resp(resp, rrset, tc, 0, 0, 1);
ns_add_rrsigs(rrset, resp, *qname, add_rrset_to_resp,
@@ -1346,6 +1354,32 @@ static int ns_put_nsec_nsec3_wildcard_answer(const knot_node_t *node,
}
/*----------------------------------------------------------------------------*/
+
+static int ns_put_nsec_nsec3_wildcard_nodes(knot_packet_t *response,
+ const knot_zone_contents_t *zone)
+{
+ assert(response != NULL);
+ assert(zone != NULL);
+
+ int ret = 0;
+
+ for (int i = 0; i < response->wildcard_nodes.count; ++i) {
+ ret = ns_put_nsec_nsec3_wildcard_answer(
+ response->wildcard_nodes.nodes[i],
+ knot_node_parent(
+ response->wildcard_nodes.nodes[i]),
+ NULL, zone,
+ response->wildcard_nodes.snames[i],
+ response);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+ }
+
+ return KNOT_EOK;
+}
+
+/*----------------------------------------------------------------------------*/
/*!
* \brief Creates a referral response.
*
@@ -1470,7 +1504,7 @@ static inline int ns_referral(const knot_node_t *node,
}
if (ret == KNOT_EOK) {
- ns_put_additional(resp);
+// ns_put_additional(resp);
knot_response_set_rcode(resp, KNOT_RCODE_NOERROR);
}
return ret;
@@ -1536,14 +1570,35 @@ static int ns_answer_from_node(const knot_node_t *node,
} else { // else put authority NS
// if wildcard answer, add NSEC / NSEC3
dbg_ns("Adding NSEC/NSEC3 for wildcard answer.\n");
+
+// char *n = knot_dname_to_str(knot_node_owner(node));
+// char *ce = (closest_encloser)
+// ? knot_dname_to_str(knot_node_owner(closest_encloser))
+// : "(nil)";
+// char *prev = (previous)
+// ? knot_dname_to_str(knot_node_owner(previous))
+// : "(nil)";
+// printf("Node: %s, closest encloser: %s, previous: %s\n",
+// n, ce, prev);
+// free(n);
+// if (closest_encloser) {
+// free(ce);
+// }
+// if (previous) {
+// free(prev);
+// }
+ assert(previous == NULL);
+ assert(closest_encloser == knot_node_parent(node)
+ || !knot_dname_is_wildcard(knot_node_owner(node)));
+
ret = ns_put_nsec_nsec3_wildcard_answer(node, closest_encloser,
previous, zone, qname, resp);
ns_put_authority_ns(zone, resp);
}
- if (ret == KNOT_EOK) {
- ns_put_additional(resp);
- }
+// if (ret == KNOT_EOK) {
+// ns_put_additional(resp);
+// }
return ret;
}
@@ -1740,10 +1795,10 @@ dbg_ns_exec(
char *name;
if (node) {
name = knot_dname_to_str(node->owner);
- dbg_ns("zone_find_dname() returned node %s ", name);
+ dbg_ns("zone_find_dname() returned node %s \n", name);
free(name);
} else {
- dbg_ns("zone_find_dname() returned no node,");
+ dbg_ns("zone_find_dname() returned no node,\n");
}
if (closest_encloser != NULL) {
@@ -1806,14 +1861,15 @@ have_node:
// return NXDOMAIN
knot_response_set_rcode(resp,
KNOT_RCODE_NXDOMAIN);
- if (ns_put_nsec_nsec3_nxdomain(zone, previous,
- closest_encloser, qname, resp) != 0) {
- return NS_ERR_SERVFAIL;
- }
} else {
knot_response_set_rcode(resp,
KNOT_RCODE_NOERROR);
}
+
+ if (ns_put_nsec_nsec3_nxdomain(zone, previous,
+ closest_encloser, qname, resp) != 0) {
+ return NS_ERR_SERVFAIL;
+ }
knot_response_set_aa(resp);
goto finalize;
}
@@ -1896,6 +1952,13 @@ finalize:
ns_put_authority_soa(zone, resp);
}
+ // add all missing NSECs/NSEC3s for wildcard nodes
+ ret = ns_put_nsec_nsec3_wildcard_nodes(resp, zone);
+
+ if (ret == KNOT_EOK) {
+ ns_put_additional(resp);
+ }
+
return ret;
}
@@ -2468,6 +2531,8 @@ static int ns_ixfr_from_zone(knot_ns_xfr_t *xfr)
assert(xfr->response != NULL);
assert(knot_packet_authority_rrset_count(xfr->query) > 0);
assert(xfr->data != NULL);
+
+ rcu_read_lock();
knot_changesets_t *chgsets = (knot_changesets_t *)xfr->data;
knot_zone_contents_t *contents = knot_zone_get_contents(xfr->zone);
@@ -2487,6 +2552,7 @@ static int ns_ixfr_from_zone(knot_ns_xfr_t *xfr)
/*! \todo Probably rename the function. */
ns_xfr_send_and_clear(xfr, 1);
// socket_close(xfr->session); /*! \todo Remove for UDP.*/
+ rcu_read_unlock();
return res;
}
@@ -2495,6 +2561,7 @@ static int ns_ixfr_from_zone(knot_ns_xfr_t *xfr)
res = ns_ixfr_put_changeset(xfr, &chgsets->sets[i]);
if (res != KNOT_EOK) {
// answer is sent
+ rcu_read_unlock();
return res;
}
}
@@ -2510,6 +2577,8 @@ static int ns_ixfr_from_zone(knot_ns_xfr_t *xfr)
// return 1;
}
+ rcu_read_unlock();
+
return KNOT_EOK;
}
diff --git a/src/libknot/packet/packet.c b/src/libknot/packet/packet.c
index ed73afa..82b65c6 100644
--- a/src/libknot/packet/packet.c
+++ b/src/libknot/packet/packet.c
@@ -112,6 +112,18 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt)
pkt->compression.max = DEFAULT_DOMAINS_IN_RESPONSE;
pkt->compression.default_count = DEFAULT_DOMAINS_IN_RESPONSE;
+ // wildcard nodes and SNAMEs associated with them
+ pkt->wildcard_nodes.nodes = (const knot_node_t **)pos;
+ pos += DEFAULT_WILDCARD_NODES * sizeof(const knot_node_t *);
+ pkt->wildcard_nodes.snames = (const knot_dname_t **)pos;
+ pos += DEFAULT_WILDCARD_NODES * sizeof(knot_dname_t *);
+
+ dbg_packet("Wildcard nodes: %p\n", pkt->wildcard_nodes.nodes);
+ dbg_packet("Wildcard SNAMEs: %p\n", pkt->wildcard_nodes.snames);
+
+ pkt->wildcard_nodes.default_count = DEFAULT_WILDCARD_NODES;
+ pkt->wildcard_nodes.max = DEFAULT_WILDCARD_NODES;
+
pkt->tmp_rrsets = (const knot_rrset_t **)pos;
pos += DEFAULT_TMP_RRSETS * sizeof(const knot_rrset_t *);
@@ -639,6 +651,11 @@ static void knot_packet_free_allocated_space(knot_packet_t *pkt)
free(pkt->compression.offsets);
}
+ if (pkt->wildcard_nodes.max > pkt->wildcard_nodes.default_count) {
+ free(pkt->wildcard_nodes.nodes);
+ free(pkt->wildcard_nodes.snames);
+ }
+
if (pkt->tmp_rrsets_max > DEFAULT_RRSET_COUNT(TMP_RRSETS, pkt)) {
free(pkt->tmp_rrsets);
}
@@ -1460,6 +1477,10 @@ void knot_packet_free(knot_packet_t **packet)
dbg_packet("Freeing tmp RRSets...\n");
knot_packet_free_tmp_rrsets(*packet);
+ /*! \note The above code will free the domain names pointed to by
+ * the list of wildcard nodes. It should not matter, however.
+ */
+
// check if some additional space was allocated for the packet
dbg_packet("Freeing additional allocated space...\n");
knot_packet_free_allocated_space(*packet);
diff --git a/src/libknot/packet/packet.h b/src/libknot/packet/packet.h
index c798133..9e37c12 100644
--- a/src/libknot/packet/packet.h
+++ b/src/libknot/packet/packet.h
@@ -33,6 +33,7 @@
#include "dname.h"
#include "rrset.h"
#include "edns.h"
+#include "zone/node.h"
/*----------------------------------------------------------------------------*/
/*!
@@ -53,6 +54,16 @@ struct knot_compressed_dnames {
typedef struct knot_compressed_dnames knot_compressed_dnames_t;
+struct knot_wildcard_nodes {
+ const knot_node_t **nodes; /*!< Wildcard nodes from CNAME processing. */
+ const knot_dname_t **snames; /*!< SNAMEs related to the nodes. */
+ short count; /*!< Count of items in the previous arrays. */
+ short max; /*!< Capacity of the structure (allocated). */
+ short default_count;
+};
+
+typedef struct knot_wildcard_nodes knot_wildcard_nodes_t;
+
/*----------------------------------------------------------------------------*/
/*!
* \brief Structure representing the DNS packet header.
@@ -134,6 +145,9 @@ struct knot_packet {
/*! \brief Information needed for compressing domain names in packet. */
knot_compressed_dnames_t compression;
+ /*! \brief Wildcard nodes to be processed for NSEC/NSEC3. */
+ knot_wildcard_nodes_t wildcard_nodes;
+
/*! \brief RRSets to be destroyed with the packet structure. */
const knot_rrset_t **tmp_rrsets;
short tmp_rrsets_count; /*!< Count of temporary RRSets. */
@@ -172,6 +186,9 @@ enum {
/*! \brief Default count of temporary RRSets stored in response. */
DEFAULT_TMP_RRSETS = 5,
+ /*! \brief Default count of wildcard nodes saved for later processing.*/
+ DEFAULT_WILDCARD_NODES = 1,
+
/*! \brief Default count of temporary RRSets stored in query. */
DEFAULT_TMP_RRSETS_QUERY = 2,
@@ -179,7 +196,8 @@ enum {
STEP_NSCOUNT = 8, /*!< Step for increasing space for Authority RRSets.*/
STEP_ARCOUNT = 8,/*!< Step for increasing space for Additional RRSets.*/
STEP_DOMAINS = 10, /*!< Step for resizing compression table. */
- STEP_TMP_RRSETS = 5 /*!< Step for increasing temorary RRSets count. */
+ STEP_TMP_RRSETS = 5, /*!< Step for increasing temorary RRSets count. */
+ STEP_WILDCARD_NODES = 2
};
/*----------------------------------------------------------------------------*/
@@ -214,6 +232,12 @@ enum {
DEFAULT_DOMAINS_IN_RESPONSE * sizeof(size_t),
PREALLOC_COMPRESSION = PREALLOC_DOMAINS + PREALLOC_OFFSETS,
+ PREALLOC_WC_NODES =
+ DEFAULT_WILDCARD_NODES * sizeof(knot_node_t *),
+ PREALLOC_WC_SNAMES =
+ DEFAULT_WILDCARD_NODES * sizeof(knot_dname_t *),
+ PREALLOC_WC = PREALLOC_WC_NODES + PREALLOC_WC_SNAMES,
+
PREALLOC_QUERY = PREALLOC_PACKET
+ PREALLOC_QNAME
+ PREALLOC_RRSETS(DEFAULT_ANCOUNT_QUERY)
@@ -229,6 +253,7 @@ enum {
+ PREALLOC_RRSETS(DEFAULT_NSCOUNT)
+ PREALLOC_RRSETS(DEFAULT_ARCOUNT)
+ PREALLOC_COMPRESSION
+ + PREALLOC_WC
+ PREALLOC_RRSETS(DEFAULT_TMP_RRSETS)
};
diff --git a/src/libknot/packet/response.c b/src/libknot/packet/response.c
index d113cdf..9f6277c 100644
--- a/src/libknot/packet/response.c
+++ b/src/libknot/packet/response.c
@@ -814,6 +814,53 @@ static int knot_response_realloc_rrsets(const knot_rrset_t ***rrsets,
}
/*----------------------------------------------------------------------------*/
+/*!
+ * \brief Reallocate space for Wildcard nodes.
+ *
+ * \retval KNOT_EOK
+ * \retval KNOT_ENOMEM
+ */
+static int knot_response_realloc_wc_nodes(const knot_node_t ***nodes,
+ const knot_dname_t ***snames,
+ short *max_count,
+ short default_max_count, short step)
+{
+ dbg_packet("Max count: %d, default max count: %d\n",
+ *max_count, default_max_count);
+ int free_old = (*max_count) != default_max_count;
+
+ const knot_node_t **old_nodes = *nodes;
+ const knot_dname_t **old_snames = *snames;
+
+ short new_max_count = *max_count + step;
+
+ const knot_node_t **new_nodes = (const knot_node_t **)malloc(
+ new_max_count * sizeof(knot_node_t *));
+ CHECK_ALLOC_LOG(new_nodes, KNOT_ENOMEM);
+
+ const knot_dname_t **new_snames = (const knot_dname_t **)malloc(
+ new_max_count * sizeof(knot_dname_t *));
+ if (new_snames == NULL) {
+ free(new_nodes);
+ return KNOT_ENOMEM;
+ }
+
+ memcpy(new_nodes, *nodes, (*max_count) * sizeof(knot_node_t *));
+ memcpy(new_snames, *snames, (*max_count) * sizeof(knot_dname_t *));
+
+ *nodes = new_nodes;
+ *snames = new_snames;
+ *max_count = new_max_count;
+
+ if (free_old) {
+ free(old_nodes);
+ free(old_snames);
+ }
+
+ return KNOT_EOK;
+}
+
+/*----------------------------------------------------------------------------*/
/* API functions */
/*----------------------------------------------------------------------------*/
@@ -915,9 +962,20 @@ void knot_response_clear(knot_packet_t *resp, int clear_question)
resp->an_rrsets = 0;
resp->ns_rrsets = 0;
resp->ar_rrsets = 0;
+
resp->compression.count = 0;
+
+ /*! \todo Temporary RRSets are not deallocated, which may potentially
+ * lead to memory leaks should this function be used in other
+ * cases than with XFR-out.
+ */
knot_packet_free_tmp_rrsets(resp);
resp->tmp_rrsets_count = 0;
+
+ /*! \todo If this function is used in other cases than with XFR-out,
+ * the list of wildcard nodes should be cleared here.
+ */
+
resp->header.ancount = 0;
resp->header.nscount = 0;
resp->header.arcount = 0;
@@ -1201,3 +1259,33 @@ int knot_response_add_nsid(knot_packet_t *response, const uint8_t *data,
return knot_edns_add_option(&response->opt_rr,
EDNS_OPTION_NSID, length, data);
}
+
+/*----------------------------------------------------------------------------*/
+
+int knot_response_add_wildcard_node(knot_packet_t *response,
+ const knot_node_t *node,
+ const knot_dname_t *sname)
+{
+ if (response == NULL || node == NULL || sname == NULL) {
+ return KNOT_EBADARG;
+ }
+
+ if (response->wildcard_nodes.count == response->wildcard_nodes.max
+ && knot_response_realloc_wc_nodes(&response->wildcard_nodes.nodes,
+ &response->wildcard_nodes.snames,
+ &response->wildcard_nodes.max,
+ DEFAULT_WILDCARD_NODES,
+ STEP_WILDCARD_NODES) != KNOT_EOK) {
+ return KNOT_ENOMEM;
+ }
+
+ response->wildcard_nodes.nodes[response->wildcard_nodes.count] = node;
+ response->wildcard_nodes.snames[response->wildcard_nodes.count] = sname;
+ ++response->wildcard_nodes.count;
+
+ dbg_response("Current wildcard nodes count: %d, max count: %d\n",
+ response->wildcard_nodes.count,
+ response->wildcard_nodes.max);
+
+ return KNOT_EOK;
+}
diff --git a/src/libknot/packet/response.h b/src/libknot/packet/response.h
index d522f82..d3e66f3 100644
--- a/src/libknot/packet/response.h
+++ b/src/libknot/packet/response.h
@@ -197,6 +197,10 @@ void knot_response_set_tc(knot_packet_t *response);
int knot_response_add_nsid(knot_packet_t *response, const uint8_t *data,
uint16_t length);
+int knot_response_add_wildcard_node(knot_packet_t *response,
+ const knot_node_t *node,
+ const knot_dname_t *sname);
+
#endif /* _KNOT_response_H_ */
/*! @} */