Commit f4226c28 authored by Jan Kadlec's avatar Jan Kadlec

Merge branch 'nsid_reload_fixed' of /git/repositories/knot

parents 04be826a 8314c2be
......@@ -2671,8 +2671,23 @@ int zones_ns_conf_hook(const struct conf_t *conf, void *data)
knot_nameserver_t *ns = (knot_nameserver_t *)data;
dbg_zones_verb("zones: reconfiguring name server.\n");
/* Set NSID. */
knot_ns_set_nsid(ns, conf->nsid, conf->nsid_len);
/* Create new OPT RR, old must be freed after RCU sync. */
knot_opt_rr_t *opt_rr_old = ns->opt_rr;
knot_opt_rr_t *opt_rr = knot_edns_new();
if (opt_rr == NULL) {
log_server_error("Couldn't create OPT RR, please restart.\n");
} else {
knot_edns_set_version(opt_rr, EDNS_VERSION);
knot_edns_set_payload(opt_rr, EDNS_MAX_UDP_PAYLOAD);
if (conf->nsid_len > 0) {
knot_edns_add_option(opt_rr, EDNS_OPTION_NSID,
conf->nsid_len,
(const uint8_t *)conf->nsid);
}
}
/* Swap pointers to OPT RR. */
ns->opt_rr = opt_rr;
/* Server identification, RFC 4892. */
ns->identity = conf->identity;
......@@ -2687,6 +2702,9 @@ int zones_ns_conf_hook(const struct conf_t *conf, void *data)
/* Wait until all readers finish with reading the zones. */
synchronize_rcu();
/* Remove old OPT RR. */
knot_edns_free(&opt_rr_old);
dbg_zones_verb("zones: nameserver's zone db: %p, old db: %p\n",
ns->zone_db, old_db);
......
......@@ -36,11 +36,10 @@ enum knot_edns_consts {
knot_opt_rr_t *knot_edns_new()
{
knot_opt_rr_t *opt_rr = (knot_opt_rr_t *)malloc(
sizeof(knot_opt_rr_t));
knot_opt_rr_t *opt_rr = (knot_opt_rr_t *)malloc(sizeof(knot_opt_rr_t));
CHECK_ALLOC_LOG(opt_rr, NULL);
memset(opt_rr, 0, sizeof(knot_opt_rr_t));
opt_rr->size = KNOT_EDNS_MIN_SIZE;
opt_rr->size = EDNS_MIN_SIZE;
opt_rr->option_count = 0;
opt_rr->options_max = 0;
......@@ -53,90 +52,7 @@ knot_opt_rr_t *knot_edns_new()
/*----------------------------------------------------------------------------*/
int knot_edns_new_from_wire(knot_opt_rr_t *opt_rr, const uint8_t *wire,
size_t max_size)
{
const uint8_t *pos = wire;
int parsed = 0;
if (pos == NULL || max_size == 0 || opt_rr == NULL) {
return KNOT_EINVAL;
}
if ((int)max_size < KNOT_EDNS_MIN_SIZE) {
dbg_edns("Not enough data to parse OPT RR header.\n");
return KNOT_EFEWDATA;
}
// owner of EDNS OPT RR must be root (0)
if (*pos != 0) {
dbg_edns("EDNS packet malformed (expected root "
"domain as owner).\n");
return KNOT_EMALF;
}
pos += 1;
// check the type of the record (must be OPT)
if (knot_wire_read_u16(pos) != KNOT_RRTYPE_OPT) {
dbg_edns("EDNS packet malformed (expected OPT type.\n");
return KNOT_EMALF;
}
pos += 2;
opt_rr->payload = knot_wire_read_u16(pos);
dbg_edns_verb("Parsed payload: %u\n", opt_rr->payload);
pos += 2;
opt_rr->ext_rcode = *(pos++);
opt_rr->version = *(pos++);
opt_rr->flags = knot_wire_read_u16(pos);
pos += 2;
parsed = KNOT_EDNS_MIN_SIZE;
// ignore RDATA, but move pos behind them
uint16_t rdlength = knot_wire_read_u16(pos);
pos += 2;
if (max_size - parsed < rdlength) {
dbg_edns("Not enough data to parse OPT RR.\n");
return KNOT_EFEWDATA;
}
while (parsed < rdlength + KNOT_EDNS_MIN_SIZE) {
if (max_size - parsed < 4) {
dbg_edns("Not enough data to parse OPT RR"
" OPTION header.\n");
return KNOT_EFEWDATA;
}
uint16_t code = knot_wire_read_u16(pos);
pos += 2;
uint16_t length = knot_wire_read_u16(pos);
pos += 2;
dbg_edns_verb("EDNS OPTION: Code: %u, Length: %u\n",
code, length);
if (max_size - parsed - 4 < length) {
dbg_edns("Not enough data to parse OPT RR"
" OPTION data.\n");
return KNOT_EFEWDATA;
}
int ret;
if ((ret =
knot_edns_add_option(opt_rr, code, length, pos)) != 0) {
dbg_edns("Error parsing OPT option field.\n");
return ret;
}
pos += length;
parsed += length + 4;
}
return parsed;
}
/*----------------------------------------------------------------------------*/
int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr,
const knot_rrset_t *rrset)
int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr, const knot_rrset_t *rrset)
{
if (opt_rr == NULL || rrset == NULL
|| knot_rrset_type(rrset) != KNOT_RRTYPE_OPT) {
......@@ -355,7 +271,7 @@ short knot_edns_to_wire(const knot_opt_rr_t *opt_rr, uint8_t *wire,
return KNOT_EINVAL;
}
assert(KNOT_EDNS_MIN_SIZE <= (int)max_size);
assert(EDNS_MIN_SIZE <= (int)max_size);
if ((int)max_size < opt_rr->size) {
dbg_edns("Not enough place for OPT RR wire format.\n");
......
......@@ -70,20 +70,16 @@ struct knot_opt_rr {
typedef struct knot_opt_rr knot_opt_rr_t;
/*----------------------------------------------------------------------------*/
/*! \brief Constants for supported versions of EDNS. */
enum knot_edns_versions {
EDNS_VERSION_0 = (uint8_t)0, /*!< EDNS version 0. */
EDNS_NOT_SUPPORTED = (uint8_t)255 /*!< EDNS not supported. */
/*! \brief Constants for EDNS. */
enum knot_edns_const {
EDNS_MAX_UDP_PAYLOAD = 4096, /*!< Maximum UDP payload with EDNS enabled. */
EDNS_VERSION = 0, /*!< Supported EDNS version. */
EDNS_NOT_SUPPORTED = 255, /*!< EDNS not supported. */
EDNS_OPTION_NSID = 3, /*!< NSID option code. */
EDNS_MIN_SIZE = 11 /*!< Minimum size of EDNS OPT RR in wire format. */
};
/*! \brief Constants for EDNS option codes. */
enum knot_edns_option_codes {
EDNS_OPTION_NSID = (uint16_t)3 /*!< NSID option code. */
};
/*! \brief Minimum size of EDNS OPT RR in wire format. */
static const short KNOT_EDNS_MIN_SIZE = 11;
/*----------------------------------------------------------------------------*/
/*!
* \brief Creates new empty OPT RR structure for holding EDNS parameters.
......@@ -93,24 +89,16 @@ static const short KNOT_EDNS_MIN_SIZE = 11;
knot_opt_rr_t *knot_edns_new();
/*!
* \brief Initializes OPT RR structure from given OPT RR in wire format.
* \brief Initializes OPT RR structure from given OPT RRSet.
*
* \param opt_rr OPT RR structure to initialize.
* \param wire Wire format of the OPT RR to parse.
* \param max_size Maximum size of the wire format in bytes (may be more
* than acutal size of the OPT RR).
* \param rrset OPT RRSet to parse.
*
* \return Size of the parserd OPT RR in bytes if successful (always > 0).
* \retval KNOT_EOK
* \retval KNOT_EINVAL
* \retval KNOT_EFEWDATA
* \retval KNOT_EMALF
* \retval KNOT_ENOMEM
*/
int knot_edns_new_from_wire(knot_opt_rr_t *opt_rr, const uint8_t *wire,
size_t max_size);
int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr,
const knot_rrset_t *rrset);
int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr, const knot_rrset_t *rrset);
/*!
* \brief Returns the UDP payload stored in the OPT RR.
......
......@@ -40,16 +40,8 @@
/*----------------------------------------------------------------------------*/
/*! \brief Maximum UDP payload with EDNS enabled. */
static const uint16_t MAX_UDP_PAYLOAD_EDNS = 4096;
/*! \brief Maximum UDP payload with EDNS disabled. */
static const uint16_t MAX_UDP_PAYLOAD = 504; // 512 - 8B header
/*! \brief Maximum size of one AXFR response packet. */
static const uint16_t MAX_AXFR_PAYLOAD = 65535;
/*! \brief Supported EDNS version. */
static const uint8_t EDNS_VERSION = 0;
/*! \brief Determines whether EDNS is enabled. */
static const int EDNS_ENABLED = 1;
/*! \brief TTL of a CNAME synthetized from a DNAME. */
static const uint32_t SYNTH_CNAME_TTL = 0;
......@@ -57,14 +49,6 @@ static const uint32_t SYNTH_CNAME_TTL = 0;
/*! \brief Determines whether DNSSEC is enabled. */
static const int DNSSEC_ENABLED = 1;
/*! \brief Determines whether NSID is enabled. */
static const int NSID_ENABLED = 1;
/*! \brief Length of NSID option data. */
static const uint16_t NSID_LENGTH = 6;
/*! \brief NSID option data. */
static const uint8_t NSID_DATA[6] = {0x46, 0x6f, 0x6f, 0x42, 0x61, 0x72};
/*! \brief Internal error code to propagate need for SERVFAIL response. */
static const int NS_ERR_SERVFAIL = -999;
......@@ -3134,21 +3118,7 @@ knot_nameserver_t *knot_ns_create()
knot_packet_free(&err);
if (EDNS_ENABLED) {
ns->opt_rr = knot_edns_new();
if (ns->opt_rr == NULL) {
dbg_ns("Error while preparing OPT RR of the"
" server.\n");
knot_packet_free(&err);
free(ns);
return NULL;
}
knot_edns_set_version(ns->opt_rr, EDNS_VERSION);
knot_edns_set_payload(ns->opt_rr, MAX_UDP_PAYLOAD_EDNS);
} else {
ns->opt_rr = NULL;
}
ns->opt_rr = NULL;
ns->identity = NULL;
ns->version = NULL;
......@@ -3159,72 +3129,6 @@ knot_nameserver_t *knot_ns_create()
/*----------------------------------------------------------------------------*/
static int knot_ns_replace_nsid(knot_opt_rr_t *opt_rr, const char *nsid,
size_t len)
{
assert(opt_rr != NULL);
if (nsid == NULL || len == 0) {
return KNOT_EOK;
}
int found = 0;
int i = 0;
while (i < opt_rr->option_count && !found) {
if (opt_rr->options[i].code == EDNS_OPTION_NSID) {
found = 1;
} else {
++i;
}
}
if (found) {
uint8_t *new_data = (uint8_t *)malloc(len);
if (new_data == NULL) {
return KNOT_ENOMEM;
}
memcpy(new_data, nsid, len);
uint8_t *old = opt_rr->options[i].data;
opt_rr->options[i].data = new_data;
opt_rr->options[i].length = len;
free(old);
return KNOT_EOK;
} else {
return knot_edns_add_option(opt_rr, EDNS_OPTION_NSID,
len, (const uint8_t *)nsid);
}
}
/*----------------------------------------------------------------------------*/
void knot_ns_set_nsid(knot_nameserver_t *nameserver, const char *nsid, size_t len)
{
if (nameserver == NULL) {
dbg_ns("NS: set_nsid: nameserver=NULL.\n");
return;
}
if (nsid == NULL) {
/* This is fine. */
return;
}
int ret = knot_ns_replace_nsid(nameserver->opt_rr, nsid, len);
if (ret != KNOT_EOK) {
dbg_ns("NS: set_nsid: could not add EDNS option.\n");
return;
}
dbg_ns_verb("NS: set_nsid: added successfully.\n");
}
/*----------------------------------------------------------------------------*/
int knot_ns_parse_packet(const uint8_t *query_wire, size_t qsize,
knot_packet_t *packet, knot_packet_type_t *type)
{
......
......@@ -190,10 +190,6 @@ typedef enum knot_ns_xfr_type_t {
*/
knot_nameserver_t *knot_ns_create();
/*! \todo Document me. */
void knot_ns_set_nsid(knot_nameserver_t *nameserver, const char *nsid,
size_t nsid_length);
/*!
* \brief Parses the given query into the response structure and recognizes
* type of the query.
......
......@@ -495,7 +495,7 @@ int knot_response_add_opt(knot_packet_t *resp,
}
resp->opt_rr.size = opt_rr->size;
} else {
resp->opt_rr.size = KNOT_EDNS_MIN_SIZE;
resp->opt_rr.size = EDNS_MIN_SIZE;
}
// if max size is set, it means there is some reason to be that way,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment