Skip to content
Snippets Groups Projects
Commit 2ce2a64d authored by Daniel Salzman's avatar Daniel Salzman
Browse files

zone: add request EDNS option support

parent c4d6f771
No related branches found
No related tags found
No related merge requests found
......@@ -482,6 +482,7 @@ zone:
max\-journal\-size: SIZE
dnssec\-signing: BOOL
kasp\-db: STR
request\-edns\-option: INT:[HEXSTR]
serial\-policy: increment | unixtime
module: STR/STR ...
.ft P
......@@ -647,6 +648,12 @@ A KASP database path. Non absolute path is relative to
\fI\%storage\fP\&.
.sp
Default: \fI\%storage\fP/keys
.SS request\-edns\-option
.sp
An arbitrary EDNS0 option which is included into a server request (AXFR, IXFR,
SOA, or NOTIFY). The value is in the option_code:option_data format.
.sp
Default: empty
.SS serial\-policy
.sp
Specifies how the zone serial is updated after a dynamic update or
......
......@@ -562,6 +562,7 @@ Definition of zones served by the server.
max-journal-size: SIZE
dnssec-signing: BOOL
kasp-db: STR
request-edns-option: INT:[HEXSTR]
serial-policy: increment | unixtime
module: STR/STR ...
......@@ -759,6 +760,16 @@ A KASP database path. Non absolute path is relative to
Default: :ref:`storage<zone_storage>`/keys
.. _zone_request_edns_option:
request-edns-option
-------------------
An arbitrary EDNS0 option which is included into a server request (AXFR, IXFR,
SOA, or NOTIFY). The value is in the option_code:option_data format.
Default: empty
.. _zone_serial-policy:
serial-policy
......
......@@ -133,23 +133,24 @@ static const yp_item_t desc_remote[] = {
};
#define ZONE_ITEMS \
{ C_FILE, YP_TSTR, YP_VNONE }, \
{ C_STORAGE, YP_TSTR, YP_VSTR = { STORAGE_DIR } }, \
{ C_MASTER, YP_TREF, YP_VREF = { C_RMT }, YP_FMULTI, { check_ref } }, \
{ C_DDNS_MASTER, YP_TREF, YP_VREF = { C_RMT }, YP_FNONE, { check_ref } }, \
{ C_NOTIFY, YP_TREF, YP_VREF = { C_RMT }, YP_FMULTI, { check_ref } }, \
{ C_ACL, YP_TREF, YP_VREF = { C_ACL }, YP_FMULTI, { check_ref } }, \
{ C_SEM_CHECKS, YP_TBOOL, YP_VNONE }, \
{ C_DISABLE_ANY, YP_TBOOL, YP_VNONE }, \
{ C_ZONEFILE_SYNC, YP_TINT, YP_VINT = { -1, INT32_MAX, 0, YP_STIME } }, \
{ C_IXFR_DIFF, YP_TBOOL, YP_VNONE }, \
{ C_MAX_JOURNAL_SIZE, YP_TINT, YP_VINT = { 0, INT64_MAX, INT64_MAX, YP_SSIZE } }, \
{ C_DNSSEC_SIGNING, YP_TBOOL, YP_VNONE }, \
{ C_KASP_DB, YP_TSTR, YP_VSTR = { "keys" } }, \
{ C_SERIAL_POLICY, YP_TOPT, YP_VOPT = { serial_policies, SERIAL_POLICY_INCREMENT } }, \
{ C_MODULE, YP_TDATA, YP_VDATA = { 0, NULL, mod_id_to_bin, mod_id_to_txt }, \
YP_FMULTI, { check_modref } }, \
{ C_COMMENT, YP_TSTR, YP_VNONE },
{ C_FILE, YP_TSTR, YP_VNONE }, \
{ C_STORAGE, YP_TSTR, YP_VSTR = { STORAGE_DIR } }, \
{ C_MASTER, YP_TREF, YP_VREF = { C_RMT }, YP_FMULTI, { check_ref } }, \
{ C_DDNS_MASTER, YP_TREF, YP_VREF = { C_RMT }, YP_FNONE, { check_ref } }, \
{ C_NOTIFY, YP_TREF, YP_VREF = { C_RMT }, YP_FMULTI, { check_ref } }, \
{ C_ACL, YP_TREF, YP_VREF = { C_ACL }, YP_FMULTI, { check_ref } }, \
{ C_SEM_CHECKS, YP_TBOOL, YP_VNONE }, \
{ C_DISABLE_ANY, YP_TBOOL, YP_VNONE }, \
{ C_ZONEFILE_SYNC, YP_TINT, YP_VINT = { -1, INT32_MAX, 0, YP_STIME } }, \
{ C_IXFR_DIFF, YP_TBOOL, YP_VNONE }, \
{ C_MAX_JOURNAL_SIZE, YP_TINT, YP_VINT = { 0, INT64_MAX, INT64_MAX, YP_SSIZE } }, \
{ C_DNSSEC_SIGNING, YP_TBOOL, YP_VNONE }, \
{ C_KASP_DB, YP_TSTR, YP_VSTR = { "keys" } }, \
{ C_SERIAL_POLICY, YP_TOPT, YP_VOPT = { serial_policies, SERIAL_POLICY_INCREMENT } }, \
{ C_REQUEST_EDNS_OPTION, YP_TDATA, YP_VDATA = { 0, NULL, edns_opt_to_bin, edns_opt_to_txt } }, \
{ C_MODULE, YP_TDATA, YP_VDATA = { 0, NULL, mod_id_to_bin, mod_id_to_txt }, \
YP_FMULTI, { check_modref } }, \
{ C_COMMENT, YP_TSTR, YP_VNONE },
static const yp_item_t desc_template[] = {
{ C_ID, YP_TSTR, YP_VNONE },
......
......@@ -61,6 +61,7 @@
#define C_RATE_LIMIT "\x0A""rate-limit"
#define C_RATE_LIMIT_SLIP "\x0F""rate-limit-slip"
#define C_RATE_LIMIT_TBL_SIZE "\x15""rate-limit-table-size"
#define C_REQUEST_EDNS_OPTION "\x13""request-edns-option"
#define C_RMT "\x06""remote"
#define C_RUNDIR "\x06""rundir"
#define C_SECRET "\x06""secret"
......
......@@ -31,6 +31,7 @@
#include "knot/conf/confdb.h"
#include "knot/conf/scheme.h"
#include "libknot/errcode.h"
#include "libknot/internal/utils.h"
#include "libknot/yparser/yptrafo.h"
static int hex_to_num(char hex) {
......@@ -179,6 +180,74 @@ int mod_id_to_txt(
return KNOT_EOK;
}
int edns_opt_to_bin(
char const *txt,
size_t txt_len,
uint8_t *bin,
size_t *bin_len)
{
char *suffix = NULL;
unsigned long number = strtoul(txt, &suffix, 10);
// Check for "code:[value]" format.
if (suffix <= txt || *suffix != ':' || number > UINT16_MAX) {
return KNOT_EINVAL;
}
// Store the option code.
uint16_t code = number;
if (*bin_len < sizeof(code)) {
return KNOT_ESPACE;
}
wire_write_u16(bin, code);
bin += sizeof(code);
// Prepare suffix input (behind colon character).
size_t txt_suffix_len = txt_len - (suffix - txt) - 1;
size_t bin_suffix_len = *bin_len - sizeof(code);
suffix++;
// Convert suffix data.
int ret = hex_text_to_bin(suffix, txt_suffix_len, bin, &bin_suffix_len);
if (ret != KNOT_EOK) {
return ret;
}
// Set output data length.
*bin_len = sizeof(code) + bin_suffix_len;
return KNOT_EOK;
}
int edns_opt_to_txt(
uint8_t const *bin,
size_t bin_len,
char *txt,
size_t *txt_len)
{
uint16_t code = wire_read_u16(bin);
// Write option code part.
int code_len = snprintf(txt, *txt_len, "%u:", code);
if (code_len <= 0 || code_len >= *txt_len) {
return KNOT_ESPACE;
}
size_t data_len = *txt_len - code_len;
// Write possible option data part.
int ret = hex_text_to_txt(bin + sizeof(code), bin_len - sizeof(code),
txt + code_len, &data_len);
if (ret != KNOT_EOK) {
return ret;
}
// Set output text length.
*txt_len = code_len + data_len;
return KNOT_EOK;
}
int check_ref(
conf_check_t *args)
{
......
......@@ -79,6 +79,20 @@ int mod_id_to_txt(
size_t *txt_len
);
int edns_opt_to_bin(
char const *txt,
size_t txt_len,
uint8_t *bin,
size_t *bin_len
);
int edns_opt_to_txt(
uint8_t const *bin,
size_t bin_len,
char *txt,
size_t *txt_len
);
int check_ref(
conf_check_t *args
);
......
......@@ -89,6 +89,44 @@ static knot_pkt_t *zone_query(const zone_t *zone, uint16_t pkt_type, mm_ctx_t *m
return pkt;
}
/*! \brief Set EDNS section. */
static int prepare_edns(zone_t *zone, knot_pkt_t *pkt)
{
conf_val_t opt = conf_zone_get(conf(), C_REQUEST_EDNS_OPTION, zone->name);
/* Check if an extra EDNS option is configured. */
conf_data(&opt);
if (opt.data == NULL) {
return KNOT_EOK;
}
knot_rrset_t opt_rr;
conf_val_t udp_max = conf_get(conf(), C_SRV, C_MAX_UDP_PAYLOAD);
int ret = knot_edns_init(&opt_rr, conf_int(&udp_max), 0,
KNOT_EDNS_VERSION, &pkt->mm);
if (ret != KNOT_EOK) {
return ret;
}
ret = knot_edns_add_option(&opt_rr, wire_read_u16(opt.data),
opt.len - sizeof(uint16_t),
opt.data + sizeof(uint16_t), &pkt->mm);
if (ret != KNOT_EOK) {
knot_rrset_clear(&opt_rr, &pkt->mm);
return ret;
}
knot_pkt_begin(pkt, KNOT_ADDITIONAL);
ret = knot_pkt_put(pkt, KNOT_COMPR_HINT_NONE, &opt_rr, KNOT_PF_FREE);
if (ret != KNOT_EOK) {
knot_rrset_clear(&opt_rr, &pkt->mm);
return ret;
}
return KNOT_EOK;
}
/*!
* \brief Create a zone event query, send it, wait for the response and process it.
*
......@@ -119,6 +157,12 @@ static int zone_query_execute(zone_t *zone, uint16_t pkt_type, const conf_remote
knot_requestor_init(&re, &mm);
knot_requestor_overlay(&re, KNOT_STATE_ANSWER, &param);
/* Set EDNS section. */
ret = prepare_edns(zone, query);
if (ret != KNOT_EOK) {
goto fail;
}
const knot_tsig_key_t *key = remote->key.name != NULL ?
&remote->key : NULL;
tsig_init(&param.tsig_ctx, key);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment