Commit a878b903 authored by Filip Siroky's avatar Filip Siroky Committed by Daniel Salzman

conf: add ip family specific maximum UDP limits

parent beecc7ae
......@@ -110,8 +110,19 @@ void conf_refresh_hostname(
static void init_cache(
conf_t *conf)
{
conf_val_t val = conf_get(conf, C_SRV, C_MAX_IPV4_UDP_PAYLOAD);
if (val.code != KNOT_EOK) {
val = conf_get(conf, C_SRV, C_MAX_UDP_PAYLOAD);
}
conf->cache.srv_max_ipv4_udp_payload = conf_int(&val);
val = conf_get(conf, C_SRV, C_MAX_IPV6_UDP_PAYLOAD);
if (val.code != KNOT_EOK) {
val = conf_get(conf, C_SRV, C_MAX_UDP_PAYLOAD);
}
conf->cache.srv_max_ipv6_udp_payload = conf_int(&val);
conf->cache.srv_nsid = conf_get(conf, C_SRV, C_NSID);
conf->cache.srv_max_udp_payload = conf_get(conf, C_SRV, C_MAX_UDP_PAYLOAD);
conf->cache.srv_max_tcp_clients = conf_get(conf, C_SRV, C_MAX_TCP_CLIENTS);
conf->cache.srv_tcp_hshake_timeout = conf_get(conf, C_SRV, C_TCP_HSHAKE_TIMEOUT);
conf->cache.srv_tcp_idle_timeout = conf_get(conf, C_SRV, C_TCP_IDLE_TIMEOUT);
......
......@@ -91,8 +91,9 @@ typedef struct {
/*! Cached critical confdb items. */
struct {
int16_t srv_max_ipv4_udp_payload;
int16_t srv_max_ipv6_udp_payload;
conf_val_t srv_nsid;
conf_val_t srv_max_udp_payload;
conf_val_t srv_max_tcp_clients;
conf_val_t srv_tcp_hshake_timeout;
conf_val_t srv_tcp_idle_timeout;
......
......@@ -93,30 +93,36 @@ static const knot_lookup_t log_severities[] = {
};
static const yp_item_t desc_server[] = {
{ C_IDENT, YP_TSTR, YP_VNONE },
{ C_VERSION, YP_TSTR, YP_VNONE },
{ C_NSID, YP_THEX, YP_VNONE },
{ C_RUNDIR, YP_TSTR, YP_VSTR = { RUN_DIR } },
{ C_USER, YP_TSTR, YP_VNONE },
{ C_PIDFILE, YP_TSTR, YP_VSTR = { "knot.pid" } },
{ C_UDP_WORKERS, YP_TINT, YP_VINT = { 1, 255, YP_NIL } },
{ C_TCP_WORKERS, YP_TINT, YP_VINT = { 1, 255, YP_NIL } },
{ C_BG_WORKERS, YP_TINT, YP_VINT = { 1, 255, YP_NIL } },
{ C_ASYNC_START, YP_TBOOL, YP_VNONE },
{ C_TCP_HSHAKE_TIMEOUT, YP_TINT, YP_VINT = { 0, INT32_MAX, 5, YP_STIME } },
{ C_TCP_IDLE_TIMEOUT, YP_TINT, YP_VINT = { 0, INT32_MAX, 20, YP_STIME } },
{ C_TCP_REPLY_TIMEOUT, YP_TINT, YP_VINT = { 0, INT32_MAX, 10, YP_STIME } },
{ C_MAX_TCP_CLIENTS, YP_TINT, YP_VINT = { 0, INT32_MAX, 100 } },
{ C_MAX_UDP_PAYLOAD, YP_TINT, YP_VINT = { KNOT_EDNS_MIN_UDP_PAYLOAD,
KNOT_EDNS_MAX_UDP_PAYLOAD,
4096, YP_SSIZE } },
{ C_RATE_LIMIT, YP_TINT, YP_VINT = { 0, INT32_MAX, 0 } },
{ C_RATE_LIMIT_SLIP, YP_TINT, YP_VINT = { 0, RRL_SLIP_MAX, 1 } },
{ C_RATE_LIMIT_TBL_SIZE, YP_TINT, YP_VINT = { 1, INT32_MAX, 393241 } },
{ C_RATE_LIMIT_WHITELIST,YP_TDATA, YP_VDATA = { 0, NULL, addr_range_to_bin,
addr_range_to_txt }, YP_FMULTI },
{ C_LISTEN, YP_TADDR, YP_VADDR = { 53 }, YP_FMULTI },
{ C_COMMENT, YP_TSTR, YP_VNONE },
{ C_IDENT, YP_TSTR, YP_VNONE },
{ C_VERSION, YP_TSTR, YP_VNONE },
{ C_NSID, YP_THEX, YP_VNONE },
{ C_RUNDIR, YP_TSTR, YP_VSTR = { RUN_DIR } },
{ C_USER, YP_TSTR, YP_VNONE },
{ C_PIDFILE, YP_TSTR, YP_VSTR = { "knot.pid" } },
{ C_UDP_WORKERS, YP_TINT, YP_VINT = { 1, 255, YP_NIL } },
{ C_TCP_WORKERS, YP_TINT, YP_VINT = { 1, 255, YP_NIL } },
{ C_BG_WORKERS, YP_TINT, YP_VINT = { 1, 255, YP_NIL } },
{ C_ASYNC_START, YP_TBOOL, YP_VNONE },
{ C_TCP_HSHAKE_TIMEOUT, YP_TINT, YP_VINT = { 0, INT32_MAX, 5, YP_STIME } },
{ C_TCP_IDLE_TIMEOUT, YP_TINT, YP_VINT = { 0, INT32_MAX, 20, YP_STIME } },
{ C_TCP_REPLY_TIMEOUT, YP_TINT, YP_VINT = { 0, INT32_MAX, 10, YP_STIME } },
{ C_MAX_TCP_CLIENTS, YP_TINT, YP_VINT = { 0, INT32_MAX, 100 } },
{ C_MAX_UDP_PAYLOAD, YP_TINT, YP_VINT = { KNOT_EDNS_MIN_UDP_PAYLOAD,
KNOT_EDNS_MAX_UDP_PAYLOAD,
4096, YP_SSIZE } },
{ C_MAX_IPV4_UDP_PAYLOAD, YP_TINT, YP_VINT = { KNOT_EDNS_MIN_UDP_PAYLOAD,
KNOT_EDNS_MAX_UDP_PAYLOAD,
4096, YP_SSIZE } },
{ C_MAX_IPV6_UDP_PAYLOAD, YP_TINT, YP_VINT = { KNOT_EDNS_MIN_UDP_PAYLOAD,
KNOT_EDNS_MAX_UDP_PAYLOAD,
4096, YP_SSIZE } },
{ C_RATE_LIMIT, YP_TINT, YP_VINT = { 0, INT32_MAX, 0 } },
{ C_RATE_LIMIT_SLIP, YP_TINT, YP_VINT = { 0, RRL_SLIP_MAX, 1 } },
{ C_RATE_LIMIT_TBL_SIZE, YP_TINT, YP_VINT = { 1, INT32_MAX, 393241 } },
{ C_RATE_LIMIT_WHITELIST, YP_TDATA, YP_VDATA = { 0, NULL, addr_range_to_bin,
addr_range_to_txt }, YP_FMULTI },
{ C_LISTEN, YP_TADDR, YP_VADDR = { 53 }, YP_FMULTI },
{ C_COMMENT, YP_TSTR, YP_VNONE },
{ NULL }
};
......
......@@ -63,6 +63,8 @@
#define C_MAX_JOURNAL_SIZE "\x10""max-journal-size"
#define C_MAX_TCP_CLIENTS "\x0F""max-tcp-clients"
#define C_MAX_UDP_PAYLOAD "\x0F""max-udp-payload"
#define C_MAX_IPV4_UDP_PAYLOAD "\x14""max-ipv4-udp-payload"
#define C_MAX_IPV6_UDP_PAYLOAD "\x14""max-ipv6-udp-payload"
#define C_MODULE "\x06""module"
#define C_NOTIFY "\x06""notify"
#define C_NSEC3 "\x05""nsec3"
......
......@@ -229,9 +229,19 @@ static int answer_edns_init(const knot_pkt_t *query, knot_pkt_t *resp,
}
/* Initialize OPT record. */
conf_val_t *max_payload = &conf()->cache.srv_max_udp_payload;
int ret = knot_edns_init(&qdata->opt_rr, conf_int(max_payload), 0,
KNOT_EDNS_VERSION, qdata->mm);
int16_t max_payload;
switch (qdata->param->remote->ss_family) {
case AF_INET:
max_payload = conf()->cache.srv_max_ipv4_udp_payload;
break;
case AF_INET6:
max_payload = conf()->cache.srv_max_ipv6_udp_payload;
break;
default:
return KNOT_ERROR;
}
int ret = knot_edns_init(&qdata->opt_rr, max_payload, 0,
KNOT_EDNS_VERSION, qdata->mm);
if (ret != KNOT_EOK) {
return ret;
}
......@@ -341,9 +351,18 @@ static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, knot_layer_
if (has_limit) {
resp->max_size = KNOT_WIRE_MIN_PKTSIZE;
if (knot_pkt_has_edns(query)) {
conf_val_t *max_payload = &conf()->cache.srv_max_udp_payload;
uint16_t server;
switch (qdata->param->remote->ss_family) {
case AF_INET:
server = conf()->cache.srv_max_ipv4_udp_payload;
break;
case AF_INET6:
server = conf()->cache.srv_max_ipv6_udp_payload;
break;
default:
return KNOT_ERROR;
}
uint16_t client = knot_edns_get_payload(query->opt_rr);
uint16_t server = conf_int(max_payload);
uint16_t transfer = MIN(client, server);
resp->max_size = MAX(resp->max_size, transfer);
}
......
......@@ -222,7 +222,8 @@ static knot_pkt_t *zone_query(const zone_t *zone, uint16_t pkt_type, knot_mm_t *
}
/*! \brief Set EDNS section. */
static int prepare_edns(conf_t *conf, zone_t *zone, knot_pkt_t *pkt)
static int prepare_edns(conf_t *conf, zone_t *zone, knot_pkt_t *pkt,
const conf_remote_t *remote)
{
conf_val_t val = conf_zone_get(conf, C_REQUEST_EDNS_OPTION, zone->name);
......@@ -233,10 +234,21 @@ static int prepare_edns(conf_t *conf, zone_t *zone, knot_pkt_t *pkt)
return KNOT_EOK;
}
int16_t max_payload;
switch (remote->addr.ss_family) {
case AF_INET:
max_payload = conf->cache.srv_max_ipv4_udp_payload;
break;
case AF_INET6:
max_payload = conf->cache.srv_max_ipv6_udp_payload;
break;
default:
return KNOT_ERROR;
}
knot_rrset_t opt_rr;
conf_val_t *max_payload = &conf->cache.srv_max_udp_payload;
int ret = knot_edns_init(&opt_rr, conf_int(max_payload), 0,
KNOT_EDNS_VERSION, &pkt->mm);
int ret = knot_edns_init(&opt_rr, max_payload, 0, KNOT_EDNS_VERSION, &pkt->mm);
if (ret != KNOT_EOK) {
return ret;
}
......@@ -299,7 +311,8 @@ static int zone_query_request(knot_pkt_t *query, const conf_remote_t *remote,
* \note Everything in this function is executed synchronously, returns when
* the query processing is either complete or an error occurs.
*/
int zone_query_execute(conf_t *conf, zone_t *zone, uint16_t pkt_type, const conf_remote_t *remote)
int zone_query_execute(conf_t *conf, zone_t *zone, uint16_t pkt_type,
const conf_remote_t *remote)
{
/* Create a memory pool for this task. */
knot_mm_t mm;
......@@ -313,7 +326,7 @@ int zone_query_execute(conf_t *conf, zone_t *zone, uint16_t pkt_type, const conf
}
/* Set EDNS section. */
int ret = prepare_edns(conf, zone, query);
int ret = prepare_edns(conf, zone, query, remote);
if (ret != KNOT_EOK) {
knot_pkt_free(&query);
mp_delete(mm.ctx);
......
......@@ -73,10 +73,15 @@ int zone_load_check(conf_t *conf, zone_contents_t *contents)
/* Check minimum EDNS0 payload if signed. (RFC4035/sec. 3) */
if (zone_contents_is_signed(contents)) {
conf_val_t *max_payload = &conf->cache.srv_max_udp_payload;
if (conf_int(max_payload) < KNOT_EDNS_MIN_DNSSEC_PAYLOAD) {
if (conf->cache.srv_max_ipv4_udp_payload < KNOT_EDNS_MIN_DNSSEC_PAYLOAD) {
log_zone_error(contents->apex->owner, "EDNS payload size "
"is lower than %u bytes for DNSSEC zone",
"for IPv4 is lower than %u bytes for DNSSEC zone",
KNOT_EDNS_MIN_DNSSEC_PAYLOAD);
return KNOT_EPAYLOAD;
}
if (conf->cache.srv_max_ipv6_udp_payload < KNOT_EDNS_MIN_DNSSEC_PAYLOAD) {
log_zone_error(contents->apex->owner, "EDNS payload size "
"for IPv6 is lower than %u bytes for DNSSEC zone",
KNOT_EDNS_MIN_DNSSEC_PAYLOAD);
return KNOT_EPAYLOAD;
}
......
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