summaryrefslogtreecommitdiff
path: root/usr.sbin/unbound/util
diff options
context:
space:
mode:
authorStuart Henderson <sthen@cvs.openbsd.org>2020-08-24 09:41:54 +0000
committerStuart Henderson <sthen@cvs.openbsd.org>2020-08-24 09:41:54 +0000
commita8caf799285f804684b3911bad666569243617d4 (patch)
treeece123666035943a5d1491020b1d3ce78c96db32 /usr.sbin/unbound/util
parent3798bdfa99216b77c98f20ad898ec10a40ec30a1 (diff)
merge unbound 1.11.0
Diffstat (limited to 'usr.sbin/unbound/util')
-rw-r--r--usr.sbin/unbound/util/config_file.c43
-rw-r--r--usr.sbin/unbound/util/config_file.h25
-rw-r--r--usr.sbin/unbound/util/configlexer.lex76
-rw-r--r--usr.sbin/unbound/util/configparser.y155
-rw-r--r--usr.sbin/unbound/util/fptr_wlist.c57
-rw-r--r--usr.sbin/unbound/util/iana_ports.inc3
-rw-r--r--usr.sbin/unbound/util/log.h2
-rw-r--r--usr.sbin/unbound/util/mini_event.h2
-rw-r--r--usr.sbin/unbound/util/net_help.c159
-rw-r--r--usr.sbin/unbound/util/net_help.h38
-rw-r--r--usr.sbin/unbound/util/netevent.c45
-rw-r--r--usr.sbin/unbound/util/netevent.h18
-rw-r--r--usr.sbin/unbound/util/shm_side/shm_main.c4
-rw-r--r--usr.sbin/unbound/util/ub_event.c4
14 files changed, 550 insertions, 81 deletions
diff --git a/usr.sbin/unbound/util/config_file.c b/usr.sbin/unbound/util/config_file.c
index 5a8139d69c4..6139dfc2610 100644
--- a/usr.sbin/unbound/util/config_file.c
+++ b/usr.sbin/unbound/util/config_file.c
@@ -116,6 +116,7 @@ config_create(void)
cfg->ssl_upstream = 0;
cfg->tls_cert_bundle = NULL;
cfg->tls_win_cert = 0;
+ cfg->tls_use_sni = 1;
cfg->use_syslog = 1;
cfg->log_identity = NULL; /* changed later with argv[0] */
cfg->log_time_ascii = 0;
@@ -186,6 +187,7 @@ config_create(void)
cfg->so_reuseport = REUSEPORT_DEFAULT;
cfg->ip_transparent = 0;
cfg->ip_freebind = 0;
+ cfg->ip_dscp = 0;
cfg->num_ifs = 0;
cfg->ifs = NULL;
cfg->num_out_ifs = 0;
@@ -266,13 +268,14 @@ config_create(void)
cfg->unblock_lan_zones = 0;
cfg->insecure_lan_zones = 0;
cfg->python_script = NULL;
+ cfg->dynlib_file = NULL;
cfg->remote_control_enable = 0;
cfg->control_ifs.first = NULL;
cfg->control_ifs.last = NULL;
cfg->control_port = UNBOUND_CONTROL_PORT;
cfg->control_use_cert = 1;
cfg->minimal_responses = 1;
- cfg->rrset_roundrobin = 0;
+ cfg->rrset_roundrobin = 1;
cfg->unknown_server_time_limit = 376;
cfg->max_udp_size = 4096;
if(!(cfg->server_key_file = strdup(RUN_DIR"/unbound_server.key")))
@@ -295,6 +298,8 @@ config_create(void)
if(!(cfg->dnstap_socket_path = strdup(DNSTAP_SOCKET_PATH)))
goto error_exit;
#endif
+ cfg->dnstap_bidirectional = 1;
+ cfg->dnstap_tls = 1;
cfg->disable_dnssec_lame_check = 0;
cfg->ip_ratelimit = 0;
cfg->ratelimit = 0;
@@ -335,6 +340,7 @@ config_create(void)
if(!(cfg->redis_server_host = strdup("127.0.0.1"))) goto error_exit;
cfg->redis_timeout = 100;
cfg->redis_server_port = 6379;
+ cfg->redis_expire_records = 0;
#endif /* USE_REDIS */
#endif /* USE_CACHEDB */
#ifdef USE_IPSET
@@ -504,6 +510,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STRLIST_APPEND("tls-session-ticket-keys:", tls_session_ticket_keys)
else S_STR("tls-ciphers:", tls_ciphers)
else S_STR("tls-ciphersuites:", tls_ciphersuites)
+ else S_YNO("tls-use-sni:", tls_use_sni)
else S_YNO("interface-automatic:", if_automatic)
else S_YNO("use-systemd:", use_systemd)
else S_YNO("do-daemonize:", do_daemonize)
@@ -523,6 +530,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("so-reuseport:", so_reuseport)
else S_YNO("ip-transparent:", ip_transparent)
else S_YNO("ip-freebind:", ip_freebind)
+ else S_NUMBER_OR_ZERO("ip-dscp:", ip_dscp)
else S_MEMSIZE("rrset-cache-size:", rrset_cache_size)
else S_POW2("rrset-cache-slabs:", rrset_cache_slabs)
else S_YNO("prefetch:", prefetch)
@@ -622,6 +630,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STR("control-cert-file:", control_cert_file)
else S_STR("module-config:", module_conf)
else S_STRLIST("python-script:", python_script)
+ else S_STRLIST("dynlib-file:", dynlib_file)
else S_YNO("disable-dnssec-lame-check:", disable_dnssec_lame_check)
#ifdef CLIENT_SUBNET
/* Can't set max subnet prefix here, since that value is used when
@@ -631,7 +640,15 @@ int config_set_option(struct config_file* cfg, const char* opt,
#endif
#ifdef USE_DNSTAP
else S_YNO("dnstap-enable:", dnstap)
+ else S_YNO("dnstap-bidirectional:", dnstap_bidirectional)
else S_STR("dnstap-socket-path:", dnstap_socket_path)
+ else S_STR("dnstap-ip:", dnstap_ip)
+ else S_YNO("dnstap-tls:", dnstap_tls)
+ else S_STR("dnstap-tls-server-name:", dnstap_tls_server_name)
+ else S_STR("dnstap-tls-cert-bundle:", dnstap_tls_cert_bundle)
+ else S_STR("dnstap-tls-client-key-file:", dnstap_tls_client_key_file)
+ else S_STR("dnstap-tls-client-cert-file:",
+ dnstap_tls_client_cert_file)
else S_YNO("dnstap-send-identity:", dnstap_send_identity)
else S_YNO("dnstap-send-version:", dnstap_send_version)
else S_STR("dnstap-identity:", dnstap_identity)
@@ -915,6 +932,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "so-reuseport", so_reuseport)
else O_YNO(opt, "ip-transparent", ip_transparent)
else O_YNO(opt, "ip-freebind", ip_freebind)
+ else O_DEC(opt, "ip-dscp", ip_dscp)
else O_MEM(opt, "rrset-cache-size", rrset_cache_size)
else O_DEC(opt, "rrset-cache-slabs", rrset_cache_slabs)
else O_YNO(opt, "prefetch-key", prefetch_key)
@@ -949,6 +967,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_LST(opt, "tls-session-ticket-keys", tls_session_ticket_keys.first)
else O_STR(opt, "tls-ciphers", tls_ciphers)
else O_STR(opt, "tls-ciphersuites", tls_ciphersuites)
+ else O_YNO(opt, "tls-use-sni", tls_use_sni)
else O_YNO(opt, "use-systemd", use_systemd)
else O_YNO(opt, "do-daemonize", do_daemonize)
else O_STR(opt, "chroot", chrootdir)
@@ -1038,7 +1057,16 @@ config_get_option(struct config_file* cfg, const char* opt,
#endif
#ifdef USE_DNSTAP
else O_YNO(opt, "dnstap-enable", dnstap)
+ else O_YNO(opt, "dnstap-bidirectional", dnstap_bidirectional)
else O_STR(opt, "dnstap-socket-path", dnstap_socket_path)
+ else O_STR(opt, "dnstap-ip", dnstap_ip)
+ else O_YNO(opt, "dnstap-tls", dnstap_tls)
+ else O_STR(opt, "dnstap-tls-server-name", dnstap_tls_server_name)
+ else O_STR(opt, "dnstap-tls-cert-bundle", dnstap_tls_cert_bundle)
+ else O_STR(opt, "dnstap-tls-client-key-file",
+ dnstap_tls_client_key_file)
+ else O_STR(opt, "dnstap-tls-client-cert-file",
+ dnstap_tls_client_cert_file)
else O_YNO(opt, "dnstap-send-identity", dnstap_send_identity)
else O_YNO(opt, "dnstap-send-version", dnstap_send_version)
else O_STR(opt, "dnstap-identity", dnstap_identity)
@@ -1076,6 +1104,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "insecure-lan-zones", insecure_lan_zones)
else O_DEC(opt, "max-udp-size", max_udp_size)
else O_LST(opt, "python-script", python_script)
+ else O_LST(opt, "dynlib-file", dynlib_file)
else O_YNO(opt, "disable-dnssec-lame-check", disable_dnssec_lame_check)
else O_DEC(opt, "ip-ratelimit", ip_ratelimit)
else O_DEC(opt, "ratelimit", ratelimit)
@@ -1116,6 +1145,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_STR(opt, "redis-server-host", redis_server_host)
else O_DEC(opt, "redis-server-port", redis_server_port)
else O_DEC(opt, "redis-timeout", redis_timeout)
+ else O_YNO(opt, "redis-expire-records", redis_expire_records)
#endif /* USE_REDIS */
#endif /* USE_CACHEDB */
#ifdef USE_IPSET
@@ -1458,11 +1488,17 @@ config_delete(struct config_file* cfg)
free(cfg->dns64_prefix);
config_delstrlist(cfg->dns64_ignore_aaaa);
free(cfg->dnstap_socket_path);
+ free(cfg->dnstap_ip);
+ free(cfg->dnstap_tls_server_name);
+ free(cfg->dnstap_tls_cert_bundle);
+ free(cfg->dnstap_tls_client_key_file);
+ free(cfg->dnstap_tls_client_cert_file);
free(cfg->dnstap_identity);
free(cfg->dnstap_version);
config_deldblstrlist(cfg->ratelimit_for_domain);
config_deldblstrlist(cfg->ratelimit_below_domain);
config_delstrlist(cfg->python_script);
+ config_delstrlist(cfg->dynlib_file);
#ifdef USE_IPSECMOD
free(cfg->ipsecmod_hook);
config_delstrlist(cfg->ipsecmod_whitelist);
@@ -1509,6 +1545,11 @@ int
cfg_mark_ports(const char* str, int allow, int* avail, int num)
{
char* mid = strchr(str, '-');
+#ifdef DISABLE_EXPLICIT_PORT_RANDOMISATION
+ log_warn("Explicit port randomisation disabled, ignoring "
+ "outgoing-port-permit and outgoing-port-avoid configuration "
+ "options");
+#endif
if(!mid) {
int port = atoi(str);
if(port == 0 && strcmp(str, "0") != 0) {
diff --git a/usr.sbin/unbound/util/config_file.h b/usr.sbin/unbound/util/config_file.h
index 8739ca2ae1e..66e5025d05b 100644
--- a/usr.sbin/unbound/util/config_file.h
+++ b/usr.sbin/unbound/util/config_file.h
@@ -85,6 +85,8 @@ struct config_file {
int do_ip4;
/** do ip6 query support. */
int do_ip6;
+ /** prefer ip4 upstream queries. */
+ int prefer_ip4;
/** prefer ip6 upstream queries. */
int prefer_ip6;
/** do udp query support. */
@@ -126,6 +128,8 @@ struct config_file {
char* tls_ciphers;
/** TLS chiphersuites (TLSv1.3) */
char* tls_ciphersuites;
+ /** if SNI is to be used */
+ int tls_use_sni;
/** outgoing port range number of ports (per thread) */
int outgoing_num_ports;
@@ -186,6 +190,8 @@ struct config_file {
int ip_transparent;
/** IP_FREEBIND socket option request on port 53 sockets */
int ip_freebind;
+ /** IP_TOS socket option requested on port 53 sockets */
+ int ip_dscp;
/** number of interfaces to open. If 0 default all interfaces. */
int num_ifs;
@@ -444,6 +450,9 @@ struct config_file {
/** Python script file */
struct config_strlist* python_script;
+ /** Dynamic library file */
+ struct config_strlist* dynlib_file;
+
/** Use systemd socket activation. */
int use_systemd;
@@ -472,8 +481,22 @@ struct config_file {
/** true to enable dnstap support */
int dnstap;
+ /** using bidirectional frame streams if true */
+ int dnstap_bidirectional;
/** dnstap socket path */
char* dnstap_socket_path;
+ /** dnstap IP */
+ char* dnstap_ip;
+ /** dnstap TLS enable */
+ int dnstap_tls;
+ /** dnstap tls server authentication name */
+ char* dnstap_tls_server_name;
+ /** dnstap server cert bundle */
+ char* dnstap_tls_cert_bundle;
+ /** dnstap client key for client authentication */
+ char* dnstap_tls_client_key_file;
+ /** dnstap client cert for client authentication */
+ char* dnstap_tls_client_cert_file;
/** true to send "identity" via dnstap */
int dnstap_send_identity;
/** true to send "version" via dnstap */
@@ -582,6 +605,8 @@ struct config_file {
int redis_server_port;
/** timeout (in ms) for communication with the redis server */
int redis_timeout;
+ /** set timeout on redis records based on DNS response ttl */
+ int redis_expire_records;
#endif
#endif
diff --git a/usr.sbin/unbound/util/configlexer.lex b/usr.sbin/unbound/util/configlexer.lex
index deedffa58da..83cea4b992f 100644
--- a/usr.sbin/unbound/util/configlexer.lex
+++ b/usr.sbin/unbound/util/configlexer.lex
@@ -45,11 +45,13 @@ struct inc_state {
int line;
YY_BUFFER_STATE buffer;
struct inc_state* next;
+ int inc_toplevel;
};
static struct inc_state* config_include_stack = NULL;
static int inc_depth = 0;
static int inc_prev = 0;
static int num_args = 0;
+static int inc_toplevel = 0;
void init_cfg_parse(void)
{
@@ -57,14 +59,15 @@ void init_cfg_parse(void)
inc_depth = 0;
inc_prev = 0;
num_args = 0;
+ inc_toplevel = 0;
}
-static void config_start_include(const char* filename)
+static void config_start_include(const char* filename, int toplevel)
{
FILE *input;
struct inc_state* s;
char* nm;
- if(inc_depth++ > 100000) {
+ if(inc_depth+1 > 100000) {
ub_c_error_msg("too many include files");
return;
}
@@ -96,17 +99,20 @@ static void config_start_include(const char* filename)
return;
}
LEXOUT(("switch_to_include_file(%s)\n", filename));
+ inc_depth++;
s->filename = cfg_parser->filename;
s->line = cfg_parser->line;
s->buffer = YY_CURRENT_BUFFER;
+ s->inc_toplevel = inc_toplevel;
s->next = config_include_stack;
config_include_stack = s;
cfg_parser->filename = nm;
cfg_parser->line = 1;
+ inc_toplevel = toplevel;
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
}
-static void config_start_include_glob(const char* filename)
+static void config_start_include_glob(const char* filename, int toplevel)
{
/* check for wildcards */
@@ -139,19 +145,19 @@ static void config_start_include_glob(const char* filename)
globfree(&g);
if(r == GLOB_NOMATCH)
return; /* no matches for pattern */
- config_start_include(filename); /* let original deal with it */
+ config_start_include(filename, toplevel); /* let original deal with it */
return;
}
/* process files found, if any */
for(i=(int)g.gl_pathc-1; i>=0; i--) {
- config_start_include(g.gl_pathv[i]);
+ config_start_include(g.gl_pathv[i], toplevel);
}
globfree(&g);
return;
}
#endif /* HAVE_GLOB */
- config_start_include(filename);
+ config_start_include(filename, toplevel);
}
static void config_end_include(void)
@@ -165,6 +171,7 @@ static void config_end_include(void)
yy_delete_buffer(YY_CURRENT_BUFFER);
yy_switch_to_buffer(s->buffer);
config_include_stack = s->next;
+ inc_toplevel = s->inc_toplevel;
free(s);
}
@@ -199,7 +206,7 @@ COLON \:
DQANY [^\"\n\r\\]|\\.
SQANY [^\'\n\r\\]|\\.
-%x quotedstring singlequotedstr include include_quoted val
+%x quotedstring singlequotedstr include include_quoted val include_toplevel include_toplevel_quoted
%%
<INITIAL,val>{SPACE}* {
@@ -220,6 +227,7 @@ outgoing-num-tcp{COLON} { YDVAR(1, VAR_OUTGOING_NUM_TCP) }
incoming-num-tcp{COLON} { YDVAR(1, VAR_INCOMING_NUM_TCP) }
do-ip4{COLON} { YDVAR(1, VAR_DO_IP4) }
do-ip6{COLON} { YDVAR(1, VAR_DO_IP6) }
+prefer-ip4{COLON} { YDVAR(1, VAR_PREFER_IP4) }
prefer-ip6{COLON} { YDVAR(1, VAR_PREFER_IP6) }
do-udp{COLON} { YDVAR(1, VAR_DO_UDP) }
do-tcp{COLON} { YDVAR(1, VAR_DO_TCP) }
@@ -247,6 +255,7 @@ tls-additional-port{COLON} { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) }
tls-session-ticket-keys{COLON} { YDVAR(1, VAR_TLS_SESSION_TICKET_KEYS) }
tls-ciphers{COLON} { YDVAR(1, VAR_TLS_CIPHERS) }
tls-ciphersuites{COLON} { YDVAR(1, VAR_TLS_CIPHERSUITES) }
+tls-use-sni{COLON} { YDVAR(1, VAR_TLS_USE_SNI) }
use-systemd{COLON} { YDVAR(1, VAR_USE_SYSTEMD) }
do-daemonize{COLON} { YDVAR(1, VAR_DO_DAEMONIZE) }
interface{COLON} { YDVAR(1, VAR_INTERFACE) }
@@ -258,6 +267,7 @@ so-sndbuf{COLON} { YDVAR(1, VAR_SO_SNDBUF) }
so-reuseport{COLON} { YDVAR(1, VAR_SO_REUSEPORT) }
ip-transparent{COLON} { YDVAR(1, VAR_IP_TRANSPARENT) }
ip-freebind{COLON} { YDVAR(1, VAR_IP_FREEBIND) }
+ip-dscp{COLON} { YDVAR(1, VAR_IP_DSCP) }
chroot{COLON} { YDVAR(1, VAR_CHROOT) }
username{COLON} { YDVAR(1, VAR_USERNAME) }
directory{COLON} { YDVAR(1, VAR_DIRECTORY) }
@@ -412,6 +422,8 @@ control-key-file{COLON} { YDVAR(1, VAR_CONTROL_KEY_FILE) }
control-cert-file{COLON} { YDVAR(1, VAR_CONTROL_CERT_FILE) }
python-script{COLON} { YDVAR(1, VAR_PYTHON_SCRIPT) }
python{COLON} { YDVAR(0, VAR_PYTHON) }
+dynlib-file{COLON} { YDVAR(1, VAR_DYNLIB_FILE) }
+dynlib{COLON} { YDVAR(0, VAR_DYNLIB) }
domain-insecure{COLON} { YDVAR(1, VAR_DOMAIN_INSECURE) }
minimal-responses{COLON} { YDVAR(1, VAR_MINIMAL_RESPONSES) }
rrset-roundrobin{COLON} { YDVAR(1, VAR_RRSET_ROUNDROBIN) }
@@ -429,7 +441,16 @@ access-control-view{COLON} { YDVAR(2, VAR_ACCESS_CONTROL_VIEW) }
local-zone-override{COLON} { YDVAR(3, VAR_LOCAL_ZONE_OVERRIDE) }
dnstap{COLON} { YDVAR(0, VAR_DNSTAP) }
dnstap-enable{COLON} { YDVAR(1, VAR_DNSTAP_ENABLE) }
+dnstap-bidirectional{COLON} { YDVAR(1, VAR_DNSTAP_BIDIRECTIONAL) }
dnstap-socket-path{COLON} { YDVAR(1, VAR_DNSTAP_SOCKET_PATH) }
+dnstap-ip{COLON} { YDVAR(1, VAR_DNSTAP_IP) }
+dnstap-tls{COLON} { YDVAR(1, VAR_DNSTAP_TLS) }
+dnstap-tls-server-name{COLON} { YDVAR(1, VAR_DNSTAP_TLS_SERVER_NAME) }
+dnstap-tls-cert-bundle{COLON} { YDVAR(1, VAR_DNSTAP_TLS_CERT_BUNDLE) }
+dnstap-tls-client-key-file{COLON} {
+ YDVAR(1, VAR_DNSTAP_TLS_CLIENT_KEY_FILE) }
+dnstap-tls-client-cert-file{COLON} {
+ YDVAR(1, VAR_DNSTAP_TLS_CLIENT_CERT_FILE) }
dnstap-send-identity{COLON} { YDVAR(1, VAR_DNSTAP_SEND_IDENTITY) }
dnstap-send-version{COLON} { YDVAR(1, VAR_DNSTAP_SEND_VERSION) }
dnstap-identity{COLON} { YDVAR(1, VAR_DNSTAP_IDENTITY) }
@@ -490,6 +511,7 @@ secret-seed{COLON} { YDVAR(1, VAR_CACHEDB_SECRETSEED) }
redis-server-host{COLON} { YDVAR(1, VAR_CACHEDB_REDISHOST) }
redis-server-port{COLON} { YDVAR(1, VAR_CACHEDB_REDISPORT) }
redis-timeout{COLON} { YDVAR(1, VAR_CACHEDB_REDISTIMEOUT) }
+redis-expire-records{COLON} { YDVAR(1, VAR_CACHEDB_REDISEXPIRERECORDS) }
ipset{COLON} { YDVAR(0, VAR_IPSET) }
name-v4{COLON} { YDVAR(1, VAR_IPSET_NAME_V4) }
name-v6{COLON} { YDVAR(1, VAR_IPSET_NAME_V6) }
@@ -551,7 +573,7 @@ tcp-connection-limit{COLON} { YDVAR(2, VAR_TCP_CONNECTION_LIMIT) }
<include>\" { LEXOUT(("IQS ")); BEGIN(include_quoted); }
<include>{UNQUOTEDLETTER}* {
LEXOUT(("Iunquotedstr(%s) ", yytext));
- config_start_include_glob(yytext);
+ config_start_include_glob(yytext, 0);
BEGIN(inc_prev);
}
<include_quoted><<EOF>> {
@@ -564,7 +586,7 @@ tcp-connection-limit{COLON} { YDVAR(2, VAR_TCP_CONNECTION_LIMIT) }
<include_quoted>\" {
LEXOUT(("IQE "));
yytext[yyleng - 1] = '\0';
- config_start_include_glob(yytext);
+ config_start_include_glob(yytext, 0);
BEGIN(inc_prev);
}
<INITIAL,val><<EOF>> {
@@ -573,11 +595,47 @@ tcp-connection-limit{COLON} { YDVAR(2, VAR_TCP_CONNECTION_LIMIT) }
if (!config_include_stack) {
yyterminate();
} else {
+ int prev_toplevel = inc_toplevel;
fclose(yyin);
config_end_include();
+ if(prev_toplevel) return (VAR_FORCE_TOPLEVEL);
}
}
+ /* include-toplevel: directive */
+<INITIAL,val>include-toplevel{COLON} {
+ LEXOUT(("v(%s) ", yytext)); inc_prev = YYSTATE; BEGIN(include_toplevel);
+}
+<include_toplevel><<EOF>> {
+ yyerror("EOF inside include_toplevel directive");
+ BEGIN(inc_prev);
+}
+<include_toplevel>{SPACE}* { LEXOUT(("ITSP ")); /* ignore */ }
+<include_toplevel>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; }
+<include_toplevel>\" { LEXOUT(("ITQS ")); BEGIN(include_toplevel_quoted); }
+<include_toplevel>{UNQUOTEDLETTER}* {
+ LEXOUT(("ITunquotedstr(%s) ", yytext));
+ config_start_include_glob(yytext, 1);
+ BEGIN(inc_prev);
+ return (VAR_FORCE_TOPLEVEL);
+}
+<include_toplevel_quoted><<EOF>> {
+ yyerror("EOF inside quoted string");
+ BEGIN(inc_prev);
+}
+<include_toplevel_quoted>{DQANY}* { LEXOUT(("ITSTR(%s) ", yytext)); yymore(); }
+<include_toplevel_quoted>{NEWLINE} {
+ yyerror("newline before \" in include name");
+ cfg_parser->line++; BEGIN(inc_prev);
+}
+<include_toplevel_quoted>\" {
+ LEXOUT(("ITQE "));
+ yytext[yyleng - 1] = '\0';
+ config_start_include_glob(yytext, 1);
+ BEGIN(inc_prev);
+ return (VAR_FORCE_TOPLEVEL);
+}
+
<val>{UNQUOTEDLETTER}* { LEXOUT(("unquotedstr(%s) ", yytext));
if(--num_args == 0) { BEGIN(INITIAL); }
yylval.str = strdup(yytext); return STRING_ARG; }
diff --git a/usr.sbin/unbound/util/configparser.y b/usr.sbin/unbound/util/configparser.y
index 798f4a972fd..fe600a999d4 100644
--- a/usr.sbin/unbound/util/configparser.y
+++ b/usr.sbin/unbound/util/configparser.y
@@ -69,8 +69,9 @@ extern struct config_parser_state* cfg_parser;
%token SPACE LETTER NEWLINE COMMENT COLON ANY ZONESTR
%token <str> STRING_ARG
+%token VAR_FORCE_TOPLEVEL
%token VAR_SERVER VAR_VERBOSITY VAR_NUM_THREADS VAR_PORT
-%token VAR_OUTGOING_RANGE VAR_INTERFACE
+%token VAR_OUTGOING_RANGE VAR_INTERFACE VAR_PREFER_IP4
%token VAR_DO_IP4 VAR_DO_IP6 VAR_PREFER_IP6 VAR_DO_UDP VAR_DO_TCP
%token VAR_TCP_MSS VAR_OUTGOING_TCP_MSS VAR_TCP_IDLE_TIMEOUT
%token VAR_EDNS_TCP_KEEPALIVE VAR_EDNS_TCP_KEEPALIVE_TIMEOUT
@@ -116,8 +117,10 @@ extern struct config_parser_state* cfg_parser;
%token VAR_UNBLOCK_LAN_ZONES VAR_INSECURE_LAN_ZONES
%token VAR_INFRA_CACHE_MIN_RTT
%token VAR_DNS64_PREFIX VAR_DNS64_SYNTHALL VAR_DNS64_IGNORE_AAAA
-%token VAR_DNSTAP VAR_DNSTAP_ENABLE VAR_DNSTAP_SOCKET_PATH
-%token VAR_DNSTAP_SEND_IDENTITY VAR_DNSTAP_SEND_VERSION
+%token VAR_DNSTAP VAR_DNSTAP_ENABLE VAR_DNSTAP_SOCKET_PATH VAR_DNSTAP_IP
+%token VAR_DNSTAP_TLS VAR_DNSTAP_TLS_SERVER_NAME VAR_DNSTAP_TLS_CERT_BUNDLE
+%token VAR_DNSTAP_TLS_CLIENT_KEY_FILE VAR_DNSTAP_TLS_CLIENT_CERT_FILE
+%token VAR_DNSTAP_SEND_IDENTITY VAR_DNSTAP_SEND_VERSION VAR_DNSTAP_BIDIRECTIONAL
%token VAR_DNSTAP_IDENTITY VAR_DNSTAP_VERSION
%token VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES
%token VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES
@@ -127,6 +130,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES
%token VAR_RESPONSE_IP_TAG VAR_RESPONSE_IP VAR_RESPONSE_IP_DATA
%token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT
+%token VAR_IP_DSCP
%token VAR_DISABLE_DNSSEC_LAME_CHECK
%token VAR_IP_RATELIMIT VAR_IP_RATELIMIT_SLABS VAR_IP_RATELIMIT_SIZE
%token VAR_RATELIMIT VAR_RATELIMIT_SLABS VAR_RATELIMIT_SIZE
@@ -159,6 +163,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_IPSECMOD_MAX_TTL VAR_IPSECMOD_WHITELIST VAR_IPSECMOD_STRICT
%token VAR_CACHEDB VAR_CACHEDB_BACKEND VAR_CACHEDB_SECRETSEED
%token VAR_CACHEDB_REDISHOST VAR_CACHEDB_REDISPORT VAR_CACHEDB_REDISTIMEOUT
+%token VAR_CACHEDB_REDISEXPIRERECORDS
%token VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM VAR_FOR_UPSTREAM
%token VAR_AUTH_ZONE VAR_ZONEFILE VAR_MASTER VAR_URL VAR_FOR_DOWNSTREAM
%token VAR_FALLBACK_ENABLED VAR_TLS_ADDITIONAL_PORT VAR_LOW_RTT VAR_LOW_RTT_PERMIL
@@ -166,10 +171,11 @@ extern struct config_parser_state* cfg_parser;
%token VAR_ALLOW_NOTIFY VAR_TLS_WIN_CERT VAR_TCP_CONNECTION_LIMIT
%token VAR_FORWARD_NO_CACHE VAR_STUB_NO_CACHE VAR_LOG_SERVFAIL VAR_DENY_ANY
%token VAR_UNKNOWN_SERVER_TIME_LIMIT VAR_LOG_TAG_QUERYREPLY
-%token VAR_STREAM_WAIT_SIZE VAR_TLS_CIPHERS VAR_TLS_CIPHERSUITES
+%token VAR_STREAM_WAIT_SIZE VAR_TLS_CIPHERS VAR_TLS_CIPHERSUITES VAR_TLS_USE_SNI
%token VAR_IPSET VAR_IPSET_NAME_V4 VAR_IPSET_NAME_V6
%token VAR_TLS_SESSION_TICKET_KEYS VAR_RPZ VAR_TAGS VAR_RPZ_ACTION_OVERRIDE
%token VAR_RPZ_CNAME_OVERRIDE VAR_RPZ_LOG VAR_RPZ_LOG_NAME
+%token VAR_DYNLIB VAR_DYNLIB_FILE
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -178,20 +184,25 @@ toplevelvar: serverstart contents_server | stubstart contents_stub |
rcstart contents_rc | dtstart contents_dt | viewstart contents_view |
dnscstart contents_dnsc | cachedbstart contents_cachedb |
ipsetstart contents_ipset | authstart contents_auth |
- rpzstart contents_rpz
+ rpzstart contents_rpz | dynlibstart contents_dl |
+ force_toplevel
+ ;
+force_toplevel: VAR_FORCE_TOPLEVEL
+ {
+ OUTYY(("\nP(force-toplevel)\n"));
+ }
;
-
/* server: declaration */
serverstart: VAR_SERVER
{
- OUTYY(("\nP(server:)\n"));
+ OUTYY(("\nP(server:)\n"));
}
;
-contents_server: contents_server content_server
+contents_server: contents_server content_server
| ;
content_server: server_num_threads | server_verbosity | server_port |
server_outgoing_range | server_do_ip4 |
- server_do_ip6 | server_prefer_ip6 |
+ server_do_ip6 | server_prefer_ip4 | server_prefer_ip6 |
server_do_udp | server_do_tcp |
server_tcp_mss | server_outgoing_tcp_mss | server_tcp_idle_timeout |
server_tcp_keepalive | server_tcp_keepalive_timeout |
@@ -239,6 +250,7 @@ content_server: server_num_threads | server_verbosity | server_port |
server_dns64_prefix | server_dns64_synthall | server_dns64_ignore_aaaa |
server_infra_cache_min_rtt | server_harden_algo_downgrade |
server_ip_transparent | server_ip_ratelimit | server_ratelimit |
+ server_ip_dscp |
server_ip_ratelimit_slabs | server_ratelimit_slabs |
server_ip_ratelimit_size | server_ratelimit_size |
server_ratelimit_for_domain |
@@ -272,7 +284,8 @@ content_server: server_num_threads | server_verbosity | server_port |
server_tcp_connection_limit | server_log_servfail | server_deny_any |
server_unknown_server_time_limit | server_log_tag_queryreply |
server_stream_wait_size | server_tls_ciphers |
- server_tls_ciphersuites | server_tls_session_ticket_keys
+ server_tls_ciphersuites | server_tls_session_ticket_keys |
+ server_tls_use_sni
;
stubstart: VAR_STUB_ZONE
{
@@ -780,6 +793,15 @@ server_do_tcp: VAR_DO_TCP STRING_ARG
free($2);
}
;
+server_prefer_ip4: VAR_PREFER_IP4 STRING_ARG
+ {
+ OUTYY(("P(server_prefer_ip4:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->prefer_ip4 = (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
server_prefer_ip6: VAR_PREFER_IP6 STRING_ARG
{
OUTYY(("P(server_prefer_ip6:%s)\n", $2));
@@ -938,6 +960,15 @@ server_tls_session_ticket_keys: VAR_TLS_SESSION_TICKET_KEYS STRING_ARG
yyerror("out of memory");
}
;
+server_tls_use_sni: VAR_TLS_USE_SNI STRING_ARG
+ {
+ OUTYY(("P(server_tls_use_sni:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->tls_use_sni = (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
server_use_systemd: VAR_USE_SYSTEMD STRING_ARG
{
OUTYY(("P(server_use_systemd:%s)\n", $2));
@@ -1247,6 +1278,20 @@ server_ip_freebind: VAR_IP_FREEBIND STRING_ARG
free($2);
}
;
+server_ip_dscp: VAR_IP_DSCP STRING_ARG
+ {
+ OUTYY(("P(server_ip_dscp:%s)\n", $2));
+ if(atoi($2) == 0 && strcmp($2, "0") != 0)
+ yyerror("number expected");
+ else if (atoi($2) > 63)
+ yyerror("value too large (max 63)");
+ else if (atoi($2) < 0)
+ yyerror("value too small (min 0)");
+ else
+ cfg_parser->cfg->ip_dscp = atoi($2);
+ free($2);
+ }
+ ;
server_stream_wait_size: VAR_STREAM_WAIT_SIZE STRING_ARG
{
OUTYY(("P(server_stream_wait_size:%s)\n", $2));
@@ -2719,7 +2764,10 @@ dtstart: VAR_DNSTAP
;
contents_dt: contents_dt content_dt
| ;
-content_dt: dt_dnstap_enable | dt_dnstap_socket_path |
+content_dt: dt_dnstap_enable | dt_dnstap_socket_path | dt_dnstap_bidirectional |
+ dt_dnstap_ip | dt_dnstap_tls | dt_dnstap_tls_server_name |
+ dt_dnstap_tls_cert_bundle |
+ dt_dnstap_tls_client_key_file | dt_dnstap_tls_client_cert_file |
dt_dnstap_send_identity | dt_dnstap_send_version |
dt_dnstap_identity | dt_dnstap_version |
dt_dnstap_log_resolver_query_messages |
@@ -2738,6 +2786,16 @@ dt_dnstap_enable: VAR_DNSTAP_ENABLE STRING_ARG
free($2);
}
;
+dt_dnstap_bidirectional: VAR_DNSTAP_BIDIRECTIONAL STRING_ARG
+ {
+ OUTYY(("P(dt_dnstap_bidirectional:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->dnstap_bidirectional =
+ (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
dt_dnstap_socket_path: VAR_DNSTAP_SOCKET_PATH STRING_ARG
{
OUTYY(("P(dt_dnstap_socket_path:%s)\n", $2));
@@ -2745,6 +2803,50 @@ dt_dnstap_socket_path: VAR_DNSTAP_SOCKET_PATH STRING_ARG
cfg_parser->cfg->dnstap_socket_path = $2;
}
;
+dt_dnstap_ip: VAR_DNSTAP_IP STRING_ARG
+ {
+ OUTYY(("P(dt_dnstap_ip:%s)\n", $2));
+ free(cfg_parser->cfg->dnstap_ip);
+ cfg_parser->cfg->dnstap_ip = $2;
+ }
+ ;
+dt_dnstap_tls: VAR_DNSTAP_TLS STRING_ARG
+ {
+ OUTYY(("P(dt_dnstap_tls:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->dnstap_tls = (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
+dt_dnstap_tls_server_name: VAR_DNSTAP_TLS_SERVER_NAME STRING_ARG
+ {
+ OUTYY(("P(dt_dnstap_tls_server_name:%s)\n", $2));
+ free(cfg_parser->cfg->dnstap_tls_server_name);
+ cfg_parser->cfg->dnstap_tls_server_name = $2;
+ }
+ ;
+dt_dnstap_tls_cert_bundle: VAR_DNSTAP_TLS_CERT_BUNDLE STRING_ARG
+ {
+ OUTYY(("P(dt_dnstap_tls_cert_bundle:%s)\n", $2));
+ free(cfg_parser->cfg->dnstap_tls_cert_bundle);
+ cfg_parser->cfg->dnstap_tls_cert_bundle = $2;
+ }
+ ;
+dt_dnstap_tls_client_key_file: VAR_DNSTAP_TLS_CLIENT_KEY_FILE STRING_ARG
+ {
+ OUTYY(("P(dt_dnstap_tls_client_key_file:%s)\n", $2));
+ free(cfg_parser->cfg->dnstap_tls_client_key_file);
+ cfg_parser->cfg->dnstap_tls_client_key_file = $2;
+ }
+ ;
+dt_dnstap_tls_client_cert_file: VAR_DNSTAP_TLS_CLIENT_CERT_FILE STRING_ARG
+ {
+ OUTYY(("P(dt_dnstap_tls_client_cert_file:%s)\n", $2));
+ free(cfg_parser->cfg->dnstap_tls_client_cert_file);
+ cfg_parser->cfg->dnstap_tls_client_cert_file = $2;
+ }
+ ;
dt_dnstap_send_identity: VAR_DNSTAP_SEND_IDENTITY STRING_ARG
{
OUTYY(("P(dt_dnstap_send_identity:%s)\n", $2));
@@ -2852,6 +2954,21 @@ py_script: VAR_PYTHON_SCRIPT STRING_ARG
if(!cfg_strlist_append_ex(&cfg_parser->cfg->python_script, $2))
yyerror("out of memory");
}
+dynlibstart: VAR_DYNLIB
+ {
+ OUTYY(("\nP(dynlib:)\n"));
+ }
+ ;
+contents_dl: contents_dl content_dl
+ | ;
+content_dl: dl_file
+ ;
+dl_file: VAR_DYNLIB_FILE STRING_ARG
+ {
+ OUTYY(("P(dynlib-file:%s)\n", $2));
+ if(!cfg_strlist_append_ex(&cfg_parser->cfg->dynlib_file, $2))
+ yyerror("out of memory");
+ }
server_disable_dnssec_lame_check: VAR_DISABLE_DNSSEC_LAME_CHECK STRING_ARG
{
OUTYY(("P(disable_dnssec_lame_check:%s)\n", $2));
@@ -3003,7 +3120,8 @@ cachedbstart: VAR_CACHEDB
contents_cachedb: contents_cachedb content_cachedb
| ;
content_cachedb: cachedb_backend_name | cachedb_secret_seed |
- redis_server_host | redis_server_port | redis_timeout
+ redis_server_host | redis_server_port | redis_timeout |
+ redis_expire_records
;
cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG
{
@@ -3069,6 +3187,19 @@ redis_timeout: VAR_CACHEDB_REDISTIMEOUT STRING_ARG
free($2);
}
;
+redis_expire_records: VAR_CACHEDB_REDISEXPIRERECORDS STRING_ARG
+ {
+ #if defined(USE_CACHEDB) && defined(USE_REDIS)
+ OUTYY(("P(redis_expire_records:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->redis_expire_records = (strcmp($2, "yes")==0);
+ #else
+ OUTYY(("P(Compiled without cachedb or redis, ignoring)\n"));
+ #endif
+ free($2);
+ }
+ ;
server_tcp_connection_limit: VAR_TCP_CONNECTION_LIMIT STRING_ARG STRING_ARG
{
OUTYY(("P(server_tcp_connection_limit:%s %s)\n", $2, $3));
diff --git a/usr.sbin/unbound/util/fptr_wlist.c b/usr.sbin/unbound/util/fptr_wlist.c
index 84d41cc8464..aa275ed534b 100644
--- a/usr.sbin/unbound/util/fptr_wlist.c
+++ b/usr.sbin/unbound/util/fptr_wlist.c
@@ -81,6 +81,9 @@
#ifdef WITH_PYTHONMODULE
#include "pythonmod/pythonmod.h"
#endif
+#ifdef WITH_DYNLIBMODULE
+#include "dynlibmod/dynlibmod.h"
+#endif
#ifdef USE_CACHEDB
#include "cachedb/cachedb.h"
#endif
@@ -93,6 +96,9 @@
#ifdef USE_IPSET
#include "ipset/ipset.h"
#endif
+#ifdef USE_DNSTAP
+#include "dnstap/dtstream.h"
+#endif
int
fptr_whitelist_comm_point(comm_point_callback_type *fptr)
@@ -168,6 +174,15 @@ fptr_whitelist_event(void (*fptr)(int, short, void *))
else if(fptr == &tube_handle_signal) return 1;
else if(fptr == &comm_base_handle_slow_accept) return 1;
else if(fptr == &comm_point_http_handle_callback) return 1;
+#ifdef USE_DNSTAP
+ else if(fptr == &dtio_output_cb) return 1;
+ else if(fptr == &dtio_cmd_cb) return 1;
+ else if(fptr == &dtio_reconnect_timeout_cb) return 1;
+ else if(fptr == &dtio_stop_timer_cb) return 1;
+ else if(fptr == &dtio_stop_ev_cb) return 1;
+ else if(fptr == &dtio_tap_callback) return 1;
+ else if(fptr == &dtio_mainfdcallback) return 1;
+#endif
#ifdef UB_ON_WINDOWS
else if(fptr == &worker_win_stop_cb) return 1;
#endif
@@ -380,6 +395,9 @@ fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id))
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_init) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ else if(fptr == &dynlibmod_init) return 1;
+#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_init) return 1;
#endif
@@ -405,6 +423,9 @@ fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id))
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_deinit) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ else if(fptr == &dynlibmod_deinit) return 1;
+#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_deinit) return 1;
#endif
@@ -431,6 +452,9 @@ fptr_whitelist_mod_operate(void (*fptr)(struct module_qstate* qstate,
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_operate) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ else if(fptr == &dynlibmod_operate) return 1;
+#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_operate) return 1;
#endif
@@ -457,6 +481,9 @@ fptr_whitelist_mod_inform_super(void (*fptr)(
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_inform_super) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ else if(fptr == &dynlibmod_inform_super) return 1;
+#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_inform_super) return 1;
#endif
@@ -483,6 +510,9 @@ fptr_whitelist_mod_clear(void (*fptr)(struct module_qstate* qstate,
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_clear) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ else if(fptr == &dynlibmod_clear) return 1;
+#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_clear) return 1;
#endif
@@ -508,6 +538,9 @@ fptr_whitelist_mod_get_mem(size_t (*fptr)(struct module_env* env, int id))
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_get_mem) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ else if(fptr == &dynlibmod_get_mem) return 1;
+#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_get_mem) return 1;
#endif
@@ -566,18 +599,30 @@ int fptr_whitelist_inplace_cb_reply_generic(inplace_cb_reply_func_type* fptr,
#ifdef WITH_PYTHONMODULE
if(fptr == &python_inplace_cb_reply_generic) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ if(fptr == &dynlib_inplace_cb_reply_generic) return 1;
+#endif
} else if(type == inplace_cb_reply_cache) {
#ifdef WITH_PYTHONMODULE
if(fptr == &python_inplace_cb_reply_generic) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ if(fptr == &dynlib_inplace_cb_reply_generic) return 1;
+#endif
} else if(type == inplace_cb_reply_local) {
#ifdef WITH_PYTHONMODULE
if(fptr == &python_inplace_cb_reply_generic) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ if(fptr == &dynlib_inplace_cb_reply_generic) return 1;
+#endif
} else if(type == inplace_cb_reply_servfail) {
#ifdef WITH_PYTHONMODULE
if(fptr == &python_inplace_cb_reply_generic) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ if(fptr == &dynlib_inplace_cb_reply_generic) return 1;
+#endif
}
return 0;
}
@@ -592,6 +637,10 @@ int fptr_whitelist_inplace_cb_query(inplace_cb_query_func_type* fptr)
if(fptr == &python_inplace_cb_query_generic)
return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ if(fptr == &dynlib_inplace_cb_query_generic)
+ return 1;
+#endif
(void)fptr;
return 0;
}
@@ -605,6 +654,10 @@ int fptr_whitelist_inplace_cb_edns_back_parsed(
#else
(void)fptr;
#endif
+#ifdef WITH_DYNLIBMODULE
+ if(fptr == &dynlib_inplace_cb_edns_back_parsed)
+ return 1;
+#endif
return 0;
}
@@ -617,6 +670,10 @@ int fptr_whitelist_inplace_cb_query_response(
#else
(void)fptr;
#endif
+#ifdef WITH_DYNLIBMODULE
+ if(fptr == &dynlib_inplace_cb_query_response)
+ return 1;
+#endif
return 0;
}
diff --git a/usr.sbin/unbound/util/iana_ports.inc b/usr.sbin/unbound/util/iana_ports.inc
index 3b8afe54e82..79488f49a2c 100644
--- a/usr.sbin/unbound/util/iana_ports.inc
+++ b/usr.sbin/unbound/util/iana_ports.inc
@@ -3771,6 +3771,7 @@
4188,
4191,
4192,
+4195,
4197,
4199,
4300,
@@ -4539,6 +4540,7 @@
6850,
6868,
6888,
+6924,
6935,
6936,
6946,
@@ -5229,6 +5231,7 @@
18241,
18262,
18463,
+18516,
18634,
18635,
18668,
diff --git a/usr.sbin/unbound/util/log.h b/usr.sbin/unbound/util/log.h
index 098a850a559..29a1ba38009 100644
--- a/usr.sbin/unbound/util/log.h
+++ b/usr.sbin/unbound/util/log.h
@@ -121,7 +121,7 @@ void log_ident_set_default(const char* id);
/**
* Revert identity to print, back to the recorded default value.
*/
-void log_ident_revert_to_default();
+void log_ident_revert_to_default(void);
/**
* Set identity to print if there is an identity, otherwise
diff --git a/usr.sbin/unbound/util/mini_event.h b/usr.sbin/unbound/util/mini_event.h
index 204894d97af..1734ca574c6 100644
--- a/usr.sbin/unbound/util/mini_event.h
+++ b/usr.sbin/unbound/util/mini_event.h
@@ -54,6 +54,8 @@
#if defined(USE_MINI_EVENT) && !defined(USE_WINSOCK)
+#include <sys/time.h>
+
#ifndef HAVE_EVENT_BASE_FREE
#define HAVE_EVENT_BASE_FREE
#endif
diff --git a/usr.sbin/unbound/util/net_help.c b/usr.sbin/unbound/util/net_help.c
index 0869f91f954..f59a4d65370 100644
--- a/usr.sbin/unbound/util/net_help.c
+++ b/usr.sbin/unbound/util/net_help.c
@@ -55,6 +55,9 @@
#ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h>
#endif
+#ifdef HAVE_OPENSSL_CORE_NAMES_H
+#include <openssl/core_names.h>
+#endif
#ifdef USE_WINSOCK
#include <wincrypt.h>
#endif
@@ -67,8 +70,8 @@ uint16_t EDNS_ADVERTISED_SIZE = 4096;
/** minimal responses when positive answer: default is no */
int MINIMAL_RESPONSES = 0;
-/** rrset order roundrobin: default is no */
-int RRSET_ROUNDROBIN = 0;
+/** rrset order roundrobin: default is yes */
+int RRSET_ROUNDROBIN = 1;
/** log tag queries with name instead of 'info' for filtering */
int LOG_TAG_QUERYREPLY = 0;
@@ -79,6 +82,32 @@ static struct tls_session_ticket_key {
unsigned char *hmac_key;
} *ticket_keys;
+/**
+ * callback TLS session ticket encrypt and decrypt
+ * For use with SSL_CTX_set_tlsext_ticket_key_cb or
+ * SSL_CTX_set_tlsext_ticket_key_evp_cb
+ * @param s: the SSL_CTX to use (from connect_sslctx_create())
+ * @param key_name: secret name, 16 bytes
+ * @param iv: up to EVP_MAX_IV_LENGTH.
+ * @param evp_ctx: the evp cipher context, function sets this.
+ * @param hmac_ctx: the hmac context, function sets this.
+ * with ..key_cb it is of type HMAC_CTX*
+ * with ..key_evp_cb it is of type EVP_MAC_CTX*
+ * @param enc: 1 is encrypt, 0 is decrypt
+ * @return 0 on no ticket, 1 for okay, and 2 for okay but renew the ticket
+ * (the ticket is decrypt only). and <0 for failures.
+ */
+#ifdef HAVE_SSL
+int tls_session_ticket_key_cb(SSL *s, unsigned char* key_name,
+ unsigned char* iv, EVP_CIPHER_CTX *evp_ctx,
+#ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
+ EVP_MAC_CTX *hmac_ctx,
+#else
+ HMAC_CTX* hmac_ctx,
+#endif
+ int enc);
+#endif /* HAVE_SSL */
+
/* returns true is string addr is an ip6 specced address */
int
str_is_ip6(const char* str)
@@ -829,6 +858,32 @@ void log_crypto_err_code(const char* str, unsigned long err)
#endif /* HAVE_SSL */
}
+#ifdef HAVE_SSL
+/** log certificate details */
+void
+log_cert(unsigned level, const char* str, void* cert)
+{
+ BIO* bio;
+ char nul = 0;
+ char* pp = NULL;
+ long len;
+ if(verbosity < level) return;
+ bio = BIO_new(BIO_s_mem());
+ if(!bio) return;
+ X509_print_ex(bio, (X509*)cert, 0, (unsigned long)-1
+ ^(X509_FLAG_NO_SUBJECT
+ |X509_FLAG_NO_ISSUER|X509_FLAG_NO_VALIDITY
+ |X509_FLAG_NO_EXTENSIONS|X509_FLAG_NO_AUX
+ |X509_FLAG_NO_ATTRIBUTES));
+ BIO_write(bio, &nul, (int)sizeof(nul));
+ len = BIO_get_mem_data(bio, &pp);
+ if(len != 0 && pp) {
+ verbose(level, "%s: \n%s", str, pp);
+ }
+ BIO_free(bio);
+}
+#endif /* HAVE_SSL */
+
int
listen_sslctx_setup(void* ctxt)
{
@@ -970,7 +1025,7 @@ void* listen_sslctx_create(char* key, char* pem, char* verifypem)
}
SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(
verifypem));
- SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
}
return ctx;
#else
@@ -1191,6 +1246,60 @@ void* outgoing_ssl_fd(void* sslctx, int fd)
#endif
}
+int check_auth_name_for_ssl(char* auth_name)
+{
+ if(!auth_name) return 1;
+#if defined(HAVE_SSL) && !defined(HAVE_SSL_SET1_HOST) && !defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
+ log_err("the query has an auth_name %s, but libssl has no call to "
+ "perform TLS authentication. Remove that name from config "
+ "or upgrade the ssl crypto library.", auth_name);
+ return 0;
+#else
+ return 1;
+#endif
+}
+
+/** set the authname on an SSL structure, SSL* ssl */
+int set_auth_name_on_ssl(void* ssl, char* auth_name, int use_sni)
+{
+ if(!auth_name) return 1;
+#ifdef HAVE_SSL
+ if(use_sni) {
+ (void)SSL_set_tlsext_host_name(ssl, auth_name);
+ }
+#else
+ (void)ssl;
+ (void)use_sni;
+#endif
+#ifdef HAVE_SSL_SET1_HOST
+ SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
+ /* setting the hostname makes openssl verify the
+ * host name in the x509 certificate in the
+ * SSL connection*/
+ if(!SSL_set1_host(ssl, auth_name)) {
+ log_err("SSL_set1_host failed");
+ return 0;
+ }
+#elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
+ /* openssl 1.0.2 has this function that can be used for
+ * set1_host like verification */
+ if(auth_name) {
+ X509_VERIFY_PARAM* param = SSL_get0_param(ssl);
+# ifdef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
+ X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+# endif
+ if(!X509_VERIFY_PARAM_set1_host(param, auth_name, strlen(auth_name))) {
+ log_err("X509_VERIFY_PARAM_set1_host failed");
+ return 0;
+ }
+ SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
+ }
+#else
+ verbose(VERB_ALGO, "the query has an auth_name, but libssl has no call to perform TLS authentication");
+#endif /* HAVE_SSL_SET1_HOST */
+ return 1;
+}
+
#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
/** global lock list for openssl locks */
static lock_basic_type *ub_openssl_locks = NULL;
@@ -1285,7 +1394,7 @@ int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_ses
if(!data)
return 0;
- f = fopen(p->str, "r");
+ f = fopen(p->str, "rb");
if(!f) {
log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno));
free(data);
@@ -1308,10 +1417,17 @@ int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_ses
}
/* terminate array with NULL key name entry */
keys->key_name = NULL;
+# ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
+ if(SSL_CTX_set_tlsext_ticket_key_evp_cb(sslctx, tls_session_ticket_key_cb) == 0) {
+ log_err("no support for TLS session ticket");
+ return 0;
+ }
+# else
if(SSL_CTX_set_tlsext_ticket_key_cb(sslctx, tls_session_ticket_key_cb) == 0) {
log_err("no support for TLS session ticket");
return 0;
}
+# endif
return 1;
#else
(void)sslctx;
@@ -1321,13 +1437,27 @@ int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_ses
}
-int tls_session_ticket_key_cb(void *ATTR_UNUSED(sslctx), unsigned char* key_name, unsigned char* iv, void *evp_sctx, void *hmac_ctx, int enc)
+#ifdef HAVE_SSL
+int tls_session_ticket_key_cb(SSL *ATTR_UNUSED(sslctx), unsigned char* key_name,
+ unsigned char* iv, EVP_CIPHER_CTX *evp_sctx,
+#ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
+ EVP_MAC_CTX *hmac_ctx,
+#else
+ HMAC_CTX* hmac_ctx,
+#endif
+ int enc)
{
#ifdef HAVE_SSL
+# ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
+ OSSL_PARAM params[3];
+# else
const EVP_MD *digest;
+# endif
const EVP_CIPHER *cipher;
int evp_cipher_length;
+# ifndef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
digest = EVP_sha256();
+# endif
cipher = EVP_aes_256_cbc();
evp_cipher_length = EVP_CIPHER_iv_length(cipher);
if( enc == 1 ) {
@@ -1342,7 +1472,14 @@ int tls_session_ticket_key_cb(void *ATTR_UNUSED(sslctx), unsigned char* key_name
verbose(VERB_CLIENT, "EVP_EncryptInit_ex failed");
return -1;
}
-#ifndef HMAC_INIT_EX_RETURNS_VOID
+#ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
+ params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ ticket_keys->hmac_key, 32);
+ params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+ "sha256", 0);
+ params[2] = OSSL_PARAM_construct_end();
+ EVP_MAC_set_ctx_params(hmac_ctx, params);
+#elif !defined(HMAC_INIT_EX_RETURNS_VOID)
if (HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL) != 1) {
verbose(VERB_CLIENT, "HMAC_Init_ex failed");
return -1;
@@ -1366,7 +1503,14 @@ int tls_session_ticket_key_cb(void *ATTR_UNUSED(sslctx), unsigned char* key_name
return 0;
}
-#ifndef HMAC_INIT_EX_RETURNS_VOID
+#ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
+ params[0] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ key->hmac_key, 32);
+ params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+ "sha256", 0);
+ params[2] = OSSL_PARAM_construct_end();
+ EVP_MAC_set_ctx_params(hmac_ctx, params);
+#elif !defined(HMAC_INIT_EX_RETURNS_VOID)
if (HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL) != 1) {
verbose(VERB_CLIENT, "HMAC_Init_ex failed");
return -1;
@@ -1391,6 +1535,7 @@ int tls_session_ticket_key_cb(void *ATTR_UNUSED(sslctx), unsigned char* key_name
return 0;
#endif
}
+#endif /* HAVE_SSL */
void
listen_sslctx_delete_ticket_keys(void)
diff --git a/usr.sbin/unbound/util/net_help.h b/usr.sbin/unbound/util/net_help.h
index 7a33a72035d..29943ada090 100644
--- a/usr.sbin/unbound/util/net_help.h
+++ b/usr.sbin/unbound/util/net_help.h
@@ -386,6 +386,14 @@ void log_crypto_err(const char* str);
void log_crypto_err_code(const char* str, unsigned long err);
/**
+ * Log certificate details verbosity, string, of X509 cert
+ * @param level: verbosity level
+ * @param str: string to prefix on output
+ * @param cert: X509* structure.
+ */
+void log_cert(unsigned level, const char* str, void* cert);
+
+/**
* Set SSL_OP_NOxxx options on SSL context to disable bad crypto
* @param ctxt: SSL_CTX*
* @return false on failure.
@@ -435,6 +443,22 @@ void* incoming_ssl_fd(void* sslctx, int fd);
void* outgoing_ssl_fd(void* sslctx, int fd);
/**
+ * check if authname SSL functionality is available, false if not
+ * @param auth_name: the name for the remote server, used for error print.
+ * @return false if SSL functionality to check the SSL name is not available.
+ */
+int check_auth_name_for_ssl(char* auth_name);
+
+/**
+ * set auth name on SSL for verification
+ * @param ssl: SSL* to set
+ * @param auth_name: if NULL nothing happens, otherwise the name to check.
+ * @param use_sni: if SNI will be used.
+ * @return 1 on success or NULL auth_name, 0 on failure.
+ */
+int set_auth_name_on_ssl(void* ssl, char* auth_name, int use_sni);
+
+/**
* Initialize openssl locking for thread safety
* @return false on failure (alloc failure).
*/
@@ -454,20 +478,6 @@ void ub_openssl_lock_delete(void);
int listen_sslctx_setup_ticket_keys(void* sslctx,
struct config_strlist* tls_session_ticket_keys);
-/**
- * callback TLS session ticket encrypt and decrypt
- * For use with SSL_CTX_set_tlsext_ticket_key_cb
- * @param s: the SSL_CTX to use (from connect_sslctx_create())
- * @param key_name: secret name, 16 bytes
- * @param iv: up to EVP_MAX_IV_LENGTH.
- * @param evp_ctx: the evp cipher context, function sets this.
- * @param hmac_ctx: the hmax context, function sets this.
- * @param enc: 1 is encrypt, 0 is decrypt
- * @return 0 on no ticket, 1 for okay, and 2 for okay but renew the ticket
- * (the ticket is decrypt only). and <0 for failures.
- */
-int tls_session_ticket_key_cb(void *s, unsigned char* key_name,unsigned char* iv, void *evp_ctx, void *hmac_ctx, int enc);
-
/** Free memory used for TLS session ticket keys */
void listen_sslctx_delete_ticket_keys(void);
diff --git a/usr.sbin/unbound/util/netevent.c b/usr.sbin/unbound/util/netevent.c
index dbc9f4cd8f3..3e7a433e502 100644
--- a/usr.sbin/unbound/util/netevent.c
+++ b/usr.sbin/unbound/util/netevent.c
@@ -470,7 +470,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
msg.msg_iovlen = 1;
msg.msg_control = control.buf;
#ifndef S_SPLINT_S
- msg.msg_controllen = sizeof(control);
+ msg.msg_controllen = sizeof(control.buf);
#endif /* S_SPLINT_S */
msg.msg_flags = 0;
@@ -480,7 +480,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
#ifdef IP_PKTINFO
void* cmsg_data;
msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
- log_assert(msg.msg_controllen <= sizeof(control));
+ log_assert(msg.msg_controllen <= sizeof(control.buf));
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_PKTINFO;
memmove(CMSG_DATA(cmsg), &r->pktinfo.v4info,
@@ -491,7 +491,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
#elif defined(IP_SENDSRCADDR)
msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
- log_assert(msg.msg_controllen <= sizeof(control));
+ log_assert(msg.msg_controllen <= sizeof(control.buf));
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_SENDSRCADDR;
memmove(CMSG_DATA(cmsg), &r->pktinfo.v4addr,
@@ -504,7 +504,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
} else if(r->srctype == 6) {
void* cmsg_data;
msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
- log_assert(msg.msg_controllen <= sizeof(control));
+ log_assert(msg.msg_controllen <= sizeof(control.buf));
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_PKTINFO;
memmove(CMSG_DATA(cmsg), &r->pktinfo.v6info,
@@ -516,7 +516,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
} else {
/* try to pass all 0 to use default route */
msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
- log_assert(msg.msg_controllen <= sizeof(control));
+ log_assert(msg.msg_controllen <= sizeof(control.buf));
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_PKTINFO;
memset(CMSG_DATA(cmsg), 0, sizeof(struct in6_pktinfo));
@@ -616,7 +616,7 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
msg.msg_iovlen = 1;
msg.msg_control = ancil.buf;
#ifndef S_SPLINT_S
- msg.msg_controllen = sizeof(ancil);
+ msg.msg_controllen = sizeof(ancil.buf);
#endif /* S_SPLINT_S */
msg.msg_flags = 0;
rcv = recvmsg(fd, &msg, 0);
@@ -1033,34 +1033,8 @@ tcp_callback_reader(struct comm_point* c)
}
#ifdef HAVE_SSL
-/** log certificate details */
-static void
-log_cert(unsigned level, const char* str, X509* cert)
-{
- BIO* bio;
- char nul = 0;
- char* pp = NULL;
- long len;
- if(verbosity < level) return;
- bio = BIO_new(BIO_s_mem());
- if(!bio) return;
- X509_print_ex(bio, cert, 0, (unsigned long)-1
- ^(X509_FLAG_NO_SUBJECT
- |X509_FLAG_NO_ISSUER|X509_FLAG_NO_VALIDITY
- |X509_FLAG_NO_EXTENSIONS|X509_FLAG_NO_AUX
- |X509_FLAG_NO_ATTRIBUTES));
- BIO_write(bio, &nul, (int)sizeof(nul));
- len = BIO_get_mem_data(bio, &pp);
- if(len != 0 && pp) {
- verbose(level, "%s: \n%s", str, pp);
- }
- BIO_free(bio);
-}
-#endif /* HAVE_SSL */
-
-#ifdef HAVE_SSL
/** true if the ssl handshake error has to be squelched from the logs */
-static int
+int
squelch_err_ssl_handshake(unsigned long err)
{
if(verbosity >= VERB_QUERY)
@@ -3189,7 +3163,10 @@ comm_point_send_reply(struct comm_reply *repinfo)
if(repinfo->c->tcp_parent->dtenv != NULL &&
repinfo->c->tcp_parent->dtenv->log_client_response_messages)
dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv,
- &repinfo->addr, repinfo->c->type, repinfo->c->buffer);
+ &repinfo->addr, repinfo->c->type,
+ ( repinfo->c->tcp_req_info
+ ? repinfo->c->tcp_req_info->spool_buffer
+ : repinfo->c->buffer ));
#endif
if(repinfo->c->tcp_req_info) {
tcp_req_info_send_reply(repinfo->c->tcp_req_info);
diff --git a/usr.sbin/unbound/util/netevent.h b/usr.sbin/unbound/util/netevent.h
index d80c72b3343..bb2cd1e5373 100644
--- a/usr.sbin/unbound/util/netevent.h
+++ b/usr.sbin/unbound/util/netevent.h
@@ -783,7 +783,23 @@ void comm_base_handle_slow_accept(int fd, short event, void* arg);
void comm_point_tcp_win_bio_cb(struct comm_point* c, void* ssl);
#endif
-/** see if errno for tcp connect has to be logged or not. This uses errno */
+/**
+ * See if errno for tcp connect has to be logged or not. This uses errno
+ * @param addr: apart from checking errno, the addr is checked for ip4mapped
+ * and broadcast type, hence passed.
+ * @param addrlen: length of the addr parameter.
+ * @return true if it needs to be logged.
+ */
int tcp_connect_errno_needs_log(struct sockaddr* addr, socklen_t addrlen);
+#ifdef HAVE_SSL
+/**
+ * True if the ssl handshake error has to be squelched from the logs
+ * @param err: the error returned by the openssl routine, ERR_get_error.
+ * This is a packed structure with elements that are examined.
+ * @return true if the error is squelched (not logged).
+ */
+int squelch_err_ssl_handshake(unsigned long err);
+#endif
+
#endif /* NET_EVENT_H */
diff --git a/usr.sbin/unbound/util/shm_side/shm_main.c b/usr.sbin/unbound/util/shm_side/shm_main.c
index 46a71510fea..af8c5bcf370 100644
--- a/usr.sbin/unbound/util/shm_side/shm_main.c
+++ b/usr.sbin/unbound/util/shm_side/shm_main.c
@@ -285,6 +285,10 @@ void shm_main_run(struct worker *worker)
shm_stat->mem.ipsecmod = (long long)mod_get_mem(&worker->env,
"ipsecmod");
#endif
+#ifdef WITH_DYNLIBMODULE
+ shm_stat->mem.dynlib = (long long)mod_get_mem(&worker->env,
+ "dynlib");
+#endif
}
server_stats_add(stat_total, stat_info);
diff --git a/usr.sbin/unbound/util/ub_event.c b/usr.sbin/unbound/util/ub_event.c
index 9af476ad408..68f633bb0ef 100644
--- a/usr.sbin/unbound/util/ub_event.c
+++ b/usr.sbin/unbound/util/ub_event.c
@@ -148,7 +148,7 @@ const char* ub_event_get_version(void)
return event_get_version();
}
-#if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EVBACKEND_SELECT)
+#if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EV_FEATURE_BACKENDS)
static const char* ub_ev_backend2str(int b)
{
switch(b) {
@@ -184,7 +184,7 @@ ub_get_event_sys(struct ub_event_base* base, const char** n, const char** s,
*n = "libev";
if (!b)
b = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
-# ifdef EVBACKEND_SELECT
+# ifdef EV_FEATURE_BACKENDS
*m = ub_ev_backend2str(ev_backend((struct ev_loop*)b));
# else
*m = "not obtainable";