summaryrefslogtreecommitdiff
path: root/usr.sbin/unbound/util
diff options
context:
space:
mode:
authorStuart Henderson <sthen@cvs.openbsd.org>2024-04-12 15:45:25 +0000
committerStuart Henderson <sthen@cvs.openbsd.org>2024-04-12 15:45:25 +0000
commit3602361106df8e297c23ee4ea6f39b63d995c36c (patch)
treee8fd4bbeb42338595df7e17342b2a5ef8dd2e8d9 /usr.sbin/unbound/util
parent4b11a11f25856354bcf490574c8194bc479951da (diff)
merge unbound update
Diffstat (limited to 'usr.sbin/unbound/util')
-rw-r--r--usr.sbin/unbound/util/config_file.c10
-rw-r--r--usr.sbin/unbound/util/config_file.h6
-rw-r--r--usr.sbin/unbound/util/configlexer.lex3
-rw-r--r--usr.sbin/unbound/util/configparser.y45
-rw-r--r--usr.sbin/unbound/util/data/msgencode.c4
-rw-r--r--usr.sbin/unbound/util/data/msgparse.c25
-rw-r--r--usr.sbin/unbound/util/data/msgparse.h18
-rw-r--r--usr.sbin/unbound/util/fptr_wlist.c2
-rw-r--r--usr.sbin/unbound/util/log.c2
-rw-r--r--usr.sbin/unbound/util/module.c18
-rw-r--r--usr.sbin/unbound/util/module.h10
-rw-r--r--usr.sbin/unbound/util/net_help.c105
-rw-r--r--usr.sbin/unbound/util/net_help.h18
-rw-r--r--usr.sbin/unbound/util/netevent.c102
14 files changed, 324 insertions, 44 deletions
diff --git a/usr.sbin/unbound/util/config_file.c b/usr.sbin/unbound/util/config_file.c
index b7aed66dc19..8d1fd552191 100644
--- a/usr.sbin/unbound/util/config_file.c
+++ b/usr.sbin/unbound/util/config_file.c
@@ -271,6 +271,7 @@ config_create(void)
cfg->val_permissive_mode = 0;
cfg->aggressive_nsec = 1;
cfg->ignore_cd = 0;
+ cfg->disable_edns_do = 0;
cfg->serve_expired = 0;
cfg->serve_expired_ttl = 0;
cfg->serve_expired_ttl_reset = 0;
@@ -381,6 +382,7 @@ config_create(void)
#ifdef USE_CACHEDB
if(!(cfg->cachedb_backend = strdup("testframe"))) goto error_exit;
if(!(cfg->cachedb_secret = strdup("default"))) goto error_exit;
+ cfg->cachedb_no_store = 0;
#ifdef USE_REDIS
if(!(cfg->redis_server_host = strdup("127.0.0.1"))) goto error_exit;
cfg->redis_server_path = NULL;
@@ -388,6 +390,7 @@ config_create(void)
cfg->redis_timeout = 100;
cfg->redis_server_port = 6379;
cfg->redis_expire_records = 0;
+ cfg->redis_logical_db = 0;
#endif /* USE_REDIS */
#endif /* USE_CACHEDB */
#ifdef USE_IPSET
@@ -690,6 +693,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("val-permissive-mode:", val_permissive_mode)
else S_YNO("aggressive-nsec:", aggressive_nsec)
else S_YNO("ignore-cd-flag:", ignore_cd)
+ else S_YNO("disable-edns-do:", disable_edns_do)
else if(strcmp(opt, "serve-expired:") == 0)
{ IS_YES_OR_NO; cfg->serve_expired = (strcmp(val, "yes") == 0);
SERVE_EXPIRED = cfg->serve_expired; }
@@ -819,6 +823,9 @@ int config_set_option(struct config_file* cfg, const char* opt,
{ IS_NUMBER_OR_ZERO; cfg->ipsecmod_max_ttl = atoi(val); }
else S_YNO("ipsecmod-strict:", ipsecmod_strict)
#endif
+#ifdef USE_CACHEDB
+ else S_YNO("cachedb-no-store:", cachedb_no_store)
+#endif /* USE_CACHEDB */
else if(strcmp(opt, "define-tag:") ==0) {
return config_add_tag(cfg, val);
/* val_sig_skew_min, max and val_max_restart are copied into val_env
@@ -1149,6 +1156,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "val-permissive-mode", val_permissive_mode)
else O_YNO(opt, "aggressive-nsec", aggressive_nsec)
else O_YNO(opt, "ignore-cd-flag", ignore_cd)
+ else O_YNO(opt, "disable-edns-do", disable_edns_do)
else O_YNO(opt, "serve-expired", serve_expired)
else O_DEC(opt, "serve-expired-ttl", serve_expired_ttl)
else O_YNO(opt, "serve-expired-ttl-reset", serve_expired_ttl_reset)
@@ -1306,6 +1314,7 @@ config_get_option(struct config_file* cfg, const char* opt,
#ifdef USE_CACHEDB
else O_STR(opt, "backend", cachedb_backend)
else O_STR(opt, "secret-seed", cachedb_secret)
+ else O_YNO(opt, "cachedb-no-store", cachedb_no_store)
#ifdef USE_REDIS
else O_STR(opt, "redis-server-host", redis_server_host)
else O_DEC(opt, "redis-server-port", redis_server_port)
@@ -1313,6 +1322,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_STR(opt, "redis-server-password", redis_server_password)
else O_DEC(opt, "redis-timeout", redis_timeout)
else O_YNO(opt, "redis-expire-records", redis_expire_records)
+ else O_DEC(opt, "redis-logical-db", redis_logical_db)
#endif /* USE_REDIS */
#endif /* USE_CACHEDB */
#ifdef USE_IPSET
diff --git a/usr.sbin/unbound/util/config_file.h b/usr.sbin/unbound/util/config_file.h
index 452f3c6a78f..ad22b8330e3 100644
--- a/usr.sbin/unbound/util/config_file.h
+++ b/usr.sbin/unbound/util/config_file.h
@@ -409,6 +409,8 @@ struct config_file {
int aggressive_nsec;
/** ignore the CD flag in incoming queries and refuse them bogus data */
int ignore_cd;
+ /** disable EDNS DO flag in outgoing requests */
+ int disable_edns_do;
/** serve expired entries and prefetch them */
int serve_expired;
/** serve expired entries until TTL after expiration */
@@ -699,6 +701,8 @@ struct config_file {
char* cachedb_backend;
/** secret seed for hash key calculation */
char* cachedb_secret;
+ /** cachedb that does not store, but only reads from database, if on */
+ int cachedb_no_store;
#ifdef USE_REDIS
/** redis server's IP address or host name */
char* redis_server_host;
@@ -712,6 +716,8 @@ struct config_file {
int redis_timeout;
/** set timeout on redis records based on DNS response ttl */
int redis_expire_records;
+ /** set the redis logical database upon connection */
+ int redis_logical_db;
#endif
#endif
/** Downstream DNS Cookies */
diff --git a/usr.sbin/unbound/util/configlexer.lex b/usr.sbin/unbound/util/configlexer.lex
index 3fcdfa62e03..fdc267434c7 100644
--- a/usr.sbin/unbound/util/configlexer.lex
+++ b/usr.sbin/unbound/util/configlexer.lex
@@ -403,6 +403,7 @@ val-clean-additional{COLON} { YDVAR(1, VAR_VAL_CLEAN_ADDITIONAL) }
val-permissive-mode{COLON} { YDVAR(1, VAR_VAL_PERMISSIVE_MODE) }
aggressive-nsec{COLON} { YDVAR(1, VAR_AGGRESSIVE_NSEC) }
ignore-cd-flag{COLON} { YDVAR(1, VAR_IGNORE_CD_FLAG) }
+disable-edns-do{COLON} { YDVAR(1, VAR_DISABLE_EDNS_DO) }
serve-expired{COLON} { YDVAR(1, VAR_SERVE_EXPIRED) }
serve-expired-ttl{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_TTL) }
serve-expired-ttl-reset{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_TTL_RESET) }
@@ -557,12 +558,14 @@ ipsecmod-strict{COLON} { YDVAR(1, VAR_IPSECMOD_STRICT) }
cachedb{COLON} { YDVAR(0, VAR_CACHEDB) }
backend{COLON} { YDVAR(1, VAR_CACHEDB_BACKEND) }
secret-seed{COLON} { YDVAR(1, VAR_CACHEDB_SECRETSEED) }
+cachedb-no-store{COLON} { YDVAR(1, VAR_CACHEDB_NO_STORE) }
redis-server-host{COLON} { YDVAR(1, VAR_CACHEDB_REDISHOST) }
redis-server-port{COLON} { YDVAR(1, VAR_CACHEDB_REDISPORT) }
redis-server-path{COLON} { YDVAR(1, VAR_CACHEDB_REDISPATH) }
redis-server-password{COLON} { YDVAR(1, VAR_CACHEDB_REDISPASSWORD) }
redis-timeout{COLON} { YDVAR(1, VAR_CACHEDB_REDISTIMEOUT) }
redis-expire-records{COLON} { YDVAR(1, VAR_CACHEDB_REDISEXPIRERECORDS) }
+redis-logical-db{COLON} { YDVAR(1, VAR_CACHEDB_REDISLOGICALDB) }
ipset{COLON} { YDVAR(0, VAR_IPSET) }
name-v4{COLON} { YDVAR(1, VAR_IPSET_NAME_V4) }
name-v6{COLON} { YDVAR(1, VAR_IPSET_NAME_V6) }
diff --git a/usr.sbin/unbound/util/configparser.y b/usr.sbin/unbound/util/configparser.y
index d8f25a67ebb..da5d6608f1d 100644
--- a/usr.sbin/unbound/util/configparser.y
+++ b/usr.sbin/unbound/util/configparser.y
@@ -179,6 +179,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_CACHEDB VAR_CACHEDB_BACKEND VAR_CACHEDB_SECRETSEED
%token VAR_CACHEDB_REDISHOST VAR_CACHEDB_REDISPORT VAR_CACHEDB_REDISTIMEOUT
%token VAR_CACHEDB_REDISEXPIRERECORDS VAR_CACHEDB_REDISPATH VAR_CACHEDB_REDISPASSWORD
+%token VAR_CACHEDB_REDISLOGICALDB
%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
@@ -198,7 +199,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_INTERFACE_ACTION VAR_INTERFACE_VIEW VAR_INTERFACE_TAG
%token VAR_INTERFACE_TAG_ACTION VAR_INTERFACE_TAG_DATA
%token VAR_PROXY_PROTOCOL_PORT VAR_STATISTICS_INHIBIT_ZERO
-%token VAR_HARDEN_UNKNOWN_ADDITIONAL
+%token VAR_HARDEN_UNKNOWN_ADDITIONAL VAR_DISABLE_EDNS_DO VAR_CACHEDB_NO_STORE
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -332,7 +333,7 @@ content_server: server_num_threads | server_verbosity | server_port |
server_tcp_reuse_timeout | server_tcp_auth_query_timeout |
server_interface_automatic_ports | server_ede |
server_proxy_protocol_port | server_statistics_inhibit_zero |
- server_harden_unknown_additional
+ server_harden_unknown_additional | server_disable_edns_do
;
stubstart: VAR_STUB_ZONE
{
@@ -2060,6 +2061,15 @@ server_ignore_cd_flag: VAR_IGNORE_CD_FLAG STRING_ARG
free($2);
}
;
+server_disable_edns_do: VAR_DISABLE_EDNS_DO STRING_ARG
+ {
+ OUTYY(("P(server_disable_edns_do:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->disable_edns_do = (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
server_serve_expired: VAR_SERVE_EXPIRED STRING_ARG
{
OUTYY(("P(server_serve_expired:%s)\n", $2));
@@ -3701,7 +3711,8 @@ contents_cachedb: contents_cachedb content_cachedb
| ;
content_cachedb: cachedb_backend_name | cachedb_secret_seed |
redis_server_host | redis_server_port | redis_timeout |
- redis_expire_records | redis_server_path | redis_server_password
+ redis_expire_records | redis_server_path | redis_server_password |
+ cachedb_no_store | redis_logical_db
;
cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG
{
@@ -3727,6 +3738,19 @@ cachedb_secret_seed: VAR_CACHEDB_SECRETSEED STRING_ARG
#endif
}
;
+cachedb_no_store: VAR_CACHEDB_NO_STORE STRING_ARG
+ {
+ #ifdef USE_CACHEDB
+ OUTYY(("P(cachedb_no_store:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->cachedb_no_store = (strcmp($2, "yes")==0);
+ #else
+ OUTYY(("P(Compiled without cachedb, ignoring)\n"));
+ #endif
+ free($2);
+ }
+ ;
redis_server_host: VAR_CACHEDB_REDISHOST STRING_ARG
{
#if defined(USE_CACHEDB) && defined(USE_REDIS)
@@ -3804,6 +3828,21 @@ redis_expire_records: VAR_CACHEDB_REDISEXPIRERECORDS STRING_ARG
free($2);
}
;
+redis_logical_db: VAR_CACHEDB_REDISLOGICALDB STRING_ARG
+ {
+ #if defined(USE_CACHEDB) && defined(USE_REDIS)
+ int db;
+ OUTYY(("P(redis_logical_db:%s)\n", $2));
+ db = atoi($2);
+ if((db == 0 && strcmp($2, "0") != 0) || db < 0)
+ yyerror("valid redis logical database index expected");
+ else cfg_parser->cfg->redis_logical_db = db;
+ #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/data/msgencode.c b/usr.sbin/unbound/util/data/msgencode.c
index 93423f985bd..898ff8412a4 100644
--- a/usr.sbin/unbound/util/data/msgencode.c
+++ b/usr.sbin/unbound/util/data/msgencode.c
@@ -1015,8 +1015,10 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
ede_size = calc_ede_option_size(edns, &ede_txt_size);
if(sldns_buffer_capacity(pkt) < udpsize)
udpsize = sldns_buffer_capacity(pkt);
+ if(!edns || !edns->edns_present) {
+ attach_edns = 0;
/* EDEs are optional, try to fit anything else before them */
- if(udpsize < LDNS_HEADER_SIZE + edns_field_size - ede_size) {
+ } else if(udpsize < LDNS_HEADER_SIZE + edns_field_size - ede_size) {
/* packet too small to contain edns, omit it. */
attach_edns = 0;
} else {
diff --git a/usr.sbin/unbound/util/data/msgparse.c b/usr.sbin/unbound/util/data/msgparse.c
index b5414c6d0a5..d06b7bb25e6 100644
--- a/usr.sbin/unbound/util/data/msgparse.c
+++ b/usr.sbin/unbound/util/data/msgparse.c
@@ -47,6 +47,7 @@
#include "util/regional.h"
#include "util/rfc_1982.h"
#include "util/edns.h"
+#include "util/net_help.h"
#include "sldns/rrdef.h"
#include "sldns/sbuffer.h"
#include "sldns/parseutil.h"
@@ -1306,3 +1307,27 @@ log_edns_opt_list(enum verbosity_value level, const char* info_str,
}
}
+/** remove RR from msgparse RRset, return true if rrset is entirely bad */
+int
+msgparse_rrset_remove_rr(const char* str, sldns_buffer* pkt, struct rrset_parse* rrset,
+ struct rr_parse* prev, struct rr_parse* rr, struct sockaddr_storage* addr, socklen_t addrlen)
+{
+ if(verbosity >= VERB_QUERY && rrset->dname_len <= LDNS_MAX_DOMAINLEN && str) {
+ uint8_t buf[LDNS_MAX_DOMAINLEN+1];
+ dname_pkt_copy(pkt, buf, rrset->dname);
+ if(addr)
+ log_name_addr(VERB_QUERY, str, buf, addr, addrlen);
+ else log_nametypeclass(VERB_QUERY, str, buf,
+ rrset->type, ntohs(rrset->rrset_class));
+ }
+ if(prev)
+ prev->next = rr->next;
+ else rrset->rr_first = rr->next;
+ if(rrset->rr_last == rr)
+ rrset->rr_last = prev;
+ rrset->rr_count --;
+ rrset->size -= rr->size;
+ /* rr struct still exists, but is unlinked, so that in the for loop
+ * the rr->next works fine to continue. */
+ return rrset->rr_count == 0;
+}
diff --git a/usr.sbin/unbound/util/data/msgparse.h b/usr.sbin/unbound/util/data/msgparse.h
index b7dc235d677..8e5c94a28cb 100644
--- a/usr.sbin/unbound/util/data/msgparse.h
+++ b/usr.sbin/unbound/util/data/msgparse.h
@@ -371,4 +371,22 @@ void msgparse_bucket_remove(struct msg_parse* msg, struct rrset_parse* rrset);
void log_edns_opt_list(enum verbosity_value level, const char* info_str,
struct edns_option* list);
+/**
+ * Remove RR from msgparse RRset.
+ * @param str: this string is used for logging if verbose. If NULL, there is
+ * no logging of the remove.
+ * @param pkt: packet in buffer that is removed from. Used to log the name
+ * of the item removed.
+ * @param rrset: RRset that the RR is removed from.
+ * @param prev: previous RR in list, or NULL.
+ * @param rr: RR that is removed.
+ * @param addr: address used for logging, if verbose, or NULL then it is not
+ * used.
+ * @param addrlen: length of addr, if that is not NULL.
+ * @return true if rrset is entirely bad, it would then need to be removed.
+ */
+int msgparse_rrset_remove_rr(const char* str, struct sldns_buffer* pkt,
+ struct rrset_parse* rrset, struct rr_parse* prev, struct rr_parse* rr,
+ struct sockaddr_storage* addr, socklen_t addrlen);
+
#endif /* UTIL_DATA_MSGPARSE_H */
diff --git a/usr.sbin/unbound/util/fptr_wlist.c b/usr.sbin/unbound/util/fptr_wlist.c
index 11cce1a2a04..a792a342954 100644
--- a/usr.sbin/unbound/util/fptr_wlist.c
+++ b/usr.sbin/unbound/util/fptr_wlist.c
@@ -169,7 +169,9 @@ int
fptr_whitelist_event(void (*fptr)(int, short, void *))
{
if(fptr == &comm_point_udp_callback) return 1;
+#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG)
else if(fptr == &comm_point_udp_ancil_callback) return 1;
+#endif
else if(fptr == &comm_point_tcp_accept_callback) return 1;
else if(fptr == &comm_point_tcp_handle_callback) return 1;
else if(fptr == &comm_timer_callback) return 1;
diff --git a/usr.sbin/unbound/util/log.c b/usr.sbin/unbound/util/log.c
index dfbb2334994..a15ee920c0f 100644
--- a/usr.sbin/unbound/util/log.c
+++ b/usr.sbin/unbound/util/log.c
@@ -187,7 +187,7 @@ void log_ident_set_default(const char* id)
default_ident = id;
}
-void log_ident_revert_to_default()
+void log_ident_revert_to_default(void)
{
ident = default_ident;
}
diff --git a/usr.sbin/unbound/util/module.c b/usr.sbin/unbound/util/module.c
index 773dab853d2..62e5de4a05b 100644
--- a/usr.sbin/unbound/util/module.c
+++ b/usr.sbin/unbound/util/module.c
@@ -194,6 +194,24 @@ char* errinf_to_str_servfail(struct module_qstate* qstate)
return p;
}
+char* errinf_to_str_misc(struct module_qstate* qstate)
+{
+ char buf[20480];
+ char* p = buf;
+ size_t left = sizeof(buf);
+ struct errinf_strlist* s;
+ if(!qstate->errinf)
+ snprintf(p, left, "misc failure");
+ else for(s=qstate->errinf; s; s=s->next) {
+ snprintf(p, left, "%s%s", (s==qstate->errinf?"":" "), s->str);
+ left -= strlen(p); p += strlen(p);
+ }
+ p = strdup(buf);
+ if(!p)
+ log_err("malloc failure in errinf_to_str");
+ return p;
+}
+
void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr)
{
char buf[1024];
diff --git a/usr.sbin/unbound/util/module.h b/usr.sbin/unbound/util/module.h
index 5b6fcc93cf1..8a9da3f931a 100644
--- a/usr.sbin/unbound/util/module.h
+++ b/usr.sbin/unbound/util/module.h
@@ -691,6 +691,8 @@ struct module_qstate {
struct respip_action_info* respip_action_info;
/** if the query is rpz passthru, no further rpz processing for it */
int rpz_passthru;
+ /* Flag tcp required. */
+ int tcp_required;
/** whether the reply should be dropped */
int is_drop;
@@ -843,6 +845,14 @@ sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate);
char* errinf_to_str_servfail(struct module_qstate* qstate);
/**
+ * Create error info in string. For misc failures that are not servfail.
+ * @param qstate: query state.
+ * @return string or NULL on malloc failure (already logged).
+ * This string is malloced and has to be freed by caller.
+ */
+char* errinf_to_str_misc(struct module_qstate* qstate);
+
+/**
* Initialize the edns known options by allocating the required space.
* @param env: the module environment.
* @return false on failure (no memory).
diff --git a/usr.sbin/unbound/util/net_help.c b/usr.sbin/unbound/util/net_help.c
index dec46da20e2..8970247926d 100644
--- a/usr.sbin/unbound/util/net_help.c
+++ b/usr.sbin/unbound/util/net_help.c
@@ -953,6 +953,111 @@ void log_crypto_err_code(const char* str, unsigned long err)
}
#ifdef HAVE_SSL
+/** Print crypt erro with SSL_get_error want code and err_get_error code */
+static void log_crypto_err_io_code_arg(const char* str, int r,
+ unsigned long err, int err_present)
+{
+ int print_errno = 0, print_crypto_err = 0;
+ const char* inf = NULL;
+
+ switch(r) {
+ case SSL_ERROR_NONE:
+ inf = "no error";
+ break;
+ case SSL_ERROR_ZERO_RETURN:
+ inf = "channel closed";
+ break;
+ case SSL_ERROR_WANT_READ:
+ inf = "want read";
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ inf = "want write";
+ break;
+ case SSL_ERROR_WANT_CONNECT:
+ inf = "want connect";
+ break;
+ case SSL_ERROR_WANT_ACCEPT:
+ inf = "want accept";
+ break;
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ inf = "want X509 lookup";
+ break;
+#ifdef SSL_ERROR_WANT_ASYNC
+ case SSL_ERROR_WANT_ASYNC:
+ inf = "want async";
+ break;
+#endif
+#ifdef SSL_ERROR_WANT_ASYNC_JOB
+ case SSL_ERROR_WANT_ASYNC_JOB:
+ inf = "want async job";
+ break;
+#endif
+#ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB
+ case SSL_ERROR_WANT_CLIENT_HELLO_CB:
+ inf = "want client hello cb";
+ break;
+#endif
+ case SSL_ERROR_SYSCALL:
+ print_errno = 1;
+ inf = "syscall";
+ break;
+ case SSL_ERROR_SSL:
+ print_crypto_err = 1;
+ inf = "SSL, usually protocol, error";
+ break;
+ default:
+ inf = "unknown SSL_get_error result code";
+ print_errno = 1;
+ print_crypto_err = 1;
+ }
+ if(print_crypto_err) {
+ if(print_errno) {
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "%s with errno %s",
+ str, strerror(errno));
+ if(err_present)
+ log_crypto_err_code(buf, err);
+ else log_crypto_err(buf);
+ } else {
+ if(err_present)
+ log_crypto_err_code(str, err);
+ else log_crypto_err(str);
+ }
+ } else {
+ if(print_errno) {
+ if(errno == 0)
+ log_err("str: syscall error with errno %s",
+ strerror(errno));
+ else log_err("str: %s", strerror(errno));
+ } else {
+ log_err("str: %s", inf);
+ }
+ }
+}
+#endif /* HAVE_SSL */
+
+void log_crypto_err_io(const char* str, int r)
+{
+#ifdef HAVE_SSL
+ log_crypto_err_io_code_arg(str, r, 0, 0);
+#else
+ (void)str;
+ (void)r;
+#endif /* HAVE_SSL */
+}
+
+void log_crypto_err_io_code(const char* str, int r, unsigned long err)
+{
+#ifdef HAVE_SSL
+ log_crypto_err_io_code_arg(str, r, err, 1);
+#else
+ (void)str;
+ (void)r;
+ (void)err;
+#endif /* HAVE_SSL */
+}
+
+#ifdef HAVE_SSL
/** log certificate details */
void
log_cert(unsigned level, const char* str, void* cert)
diff --git a/usr.sbin/unbound/util/net_help.h b/usr.sbin/unbound/util/net_help.h
index a9de910d546..edaea42353d 100644
--- a/usr.sbin/unbound/util/net_help.h
+++ b/usr.sbin/unbound/util/net_help.h
@@ -430,6 +430,24 @@ void log_crypto_err(const char* str);
void log_crypto_err_code(const char* str, unsigned long err);
/**
+ * Log an error from libcrypto that came from SSL_write and so on, with
+ * a value from SSL_get_error, calls log_err. If that fails it logs with
+ * log_crypto_err.
+ * @param str: what failed
+ * @param r: output of SSL_get_error on the I/O operation result.
+ */
+void log_crypto_err_io(const char* str, int r);
+
+/**
+ * Log an error from libcrypt that came from an I/O routine with the
+ * errcode from ERR_get_error. Calls log_err() and log_crypto_err_code.
+ * @param str: what failed
+ * @param r: output of SSL_get_error on the I/O operation result.
+ * @param err: error code from ERR_get_error
+ */
+void log_crypto_err_io_code(const char* str, int r, unsigned long err);
+
+/**
* Log certificate details verbosity, string, of X509 cert
* @param level: verbosity level
* @param str: string to prefix on output
diff --git a/usr.sbin/unbound/util/netevent.c b/usr.sbin/unbound/util/netevent.c
index b9395a8998b..141e48d48b3 100644
--- a/usr.sbin/unbound/util/netevent.c
+++ b/usr.sbin/unbound/util/netevent.c
@@ -892,15 +892,18 @@ static int udp_recv_needs_log(int err)
static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep,
int stream) {
size_t size;
- struct pp2_header *header = pp2_read_header(buf);
- if(header == NULL) return 0;
+ struct pp2_header *header;
+ int err = pp2_read_header(sldns_buffer_begin(buf),
+ sldns_buffer_remaining(buf));
+ if(err) return 0;
+ header = (struct pp2_header*)sldns_buffer_begin(buf);
size = PP2_HEADER_SIZE + ntohs(header->len);
if((header->ver_cmd & 0xF) == PP2_CMD_LOCAL) {
/* A connection from the proxy itself.
* No need to do anything with addresses. */
goto done;
}
- if(header->fam_prot == 0x00) {
+ if(header->fam_prot == PP2_UNSPEC_UNSPEC) {
/* Unspecified family and protocol. This could be used for
* health checks by proxies.
* No need to do anything with addresses. */
@@ -908,8 +911,8 @@ static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep,
}
/* Read the proxied address */
switch(header->fam_prot) {
- case 0x11: /* AF_INET|STREAM */
- case 0x12: /* AF_INET|DGRAM */
+ case PP2_INET_STREAM:
+ case PP2_INET_DGRAM:
{
struct sockaddr_in* addr =
(struct sockaddr_in*)&rep->client_addr;
@@ -920,8 +923,8 @@ static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep,
}
/* Ignore the destination address; it should be us. */
break;
- case 0x21: /* AF_INET6|STREAM */
- case 0x22: /* AF_INET6|DGRAM */
+ case PP2_INET6_STREAM:
+ case PP2_INET6_DGRAM:
{
struct sockaddr_in6* addr =
(struct sockaddr_in6*)&rep->client_addr;
@@ -934,6 +937,10 @@ static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep,
}
/* Ignore the destination address; it should be us. */
break;
+ default:
+ log_err("proxy_protocol: unsupported family and "
+ "protocol 0x%x", (int)header->fam_prot);
+ return 0;
}
rep->is_proxied = 1;
done:
@@ -948,10 +955,10 @@ done:
return 1;
}
+#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG)
void
comm_point_udp_ancil_callback(int fd, short event, void* arg)
{
-#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG)
struct comm_reply rep;
struct msghdr msg;
struct iovec iov[1];
@@ -1063,21 +1070,21 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
fptr_ok(fptr_whitelist_comm_point(rep.c->callback));
if((*rep.c->callback)(rep.c, rep.c->cb_arg, NETEVENT_NOERROR, &rep)) {
/* send back immediate reply */
- (void)comm_point_send_udp_msg_if(rep.c, rep.c->buffer,
+ struct sldns_buffer *buffer;
+#ifdef USE_DNSCRYPT
+ buffer = rep.c->dnscrypt_buffer;
+#else
+ buffer = rep.c->buffer;
+#endif
+ (void)comm_point_send_udp_msg_if(rep.c, buffer,
(struct sockaddr*)&rep.remote_addr,
rep.remote_addrlen, &rep);
}
if(!rep.c || rep.c->fd == -1) /* commpoint closed */
break;
}
-#else
- (void)fd;
- (void)event;
- (void)arg;
- fatal_exit("recvmsg: No support for IPV6_PKTINFO; IP_PKTINFO or IP_RECVDSTADDR. "
- "Please disable interface-automatic");
-#endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG */
}
+#endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG */
void
comm_point_udp_callback(int fd, short event, void* arg)
@@ -1665,7 +1672,8 @@ ssl_handshake(struct comm_point* c)
} else {
unsigned long err = ERR_get_error();
if(!squelch_err_ssl_handshake(err)) {
- log_crypto_err_code("ssl handshake failed", err);
+ log_crypto_err_io_code("ssl handshake failed",
+ want, err);
log_addr(VERB_OPS, "ssl handshake failed",
&c->repinfo.remote_addr,
c->repinfo.remote_addrlen);
@@ -1815,23 +1823,30 @@ ssl_handle_read(struct comm_point* c)
strerror(errno));
return 0;
}
- log_crypto_err("could not SSL_read");
+ log_crypto_err_io("could not SSL_read",
+ want);
return 0;
}
c->tcp_byte_count += r;
+ sldns_buffer_skip(c->buffer, r);
if(c->tcp_byte_count != current_read_size) return 1;
c->pp2_header_state = pp2_header_init;
}
}
if(c->pp2_header_state == pp2_header_init) {
- header = pp2_read_header(c->buffer);
- if(!header) {
+ int err;
+ err = pp2_read_header(
+ sldns_buffer_begin(c->buffer),
+ sldns_buffer_limit(c->buffer));
+ if(err) {
log_err("proxy_protocol: could not parse "
- "PROXYv2 header");
+ "PROXYv2 header (%s)",
+ pp_lookup_error(err));
return 0;
}
+ header = (struct pp2_header*)sldns_buffer_begin(c->buffer);
want_read_size = ntohs(header->len);
- if(sldns_buffer_remaining(c->buffer) <
+ if(sldns_buffer_limit(c->buffer) <
PP2_HEADER_SIZE + want_read_size) {
log_err_addr("proxy_protocol: not enough "
"buffer size to read PROXYv2 header", "",
@@ -1876,10 +1891,12 @@ ssl_handle_read(struct comm_point* c)
strerror(errno));
return 0;
}
- log_crypto_err("could not SSL_read");
+ log_crypto_err_io("could not SSL_read",
+ want);
return 0;
}
c->tcp_byte_count += r;
+ sldns_buffer_skip(c->buffer, r);
if(c->tcp_byte_count != current_read_size) return 1;
c->pp2_header_state = pp2_header_done;
}
@@ -1890,6 +1907,7 @@ ssl_handle_read(struct comm_point* c)
c->repinfo.remote_addrlen);
return 0;
}
+ sldns_buffer_flip(c->buffer);
if(!consume_pp2_header(c->buffer, &c->repinfo, 1)) {
log_err_addr("proxy_protocol: could not consume "
"PROXYv2 header", "", &c->repinfo.remote_addr,
@@ -1934,7 +1952,7 @@ ssl_handle_read(struct comm_point* c)
strerror(errno));
return 0;
}
- log_crypto_err("could not SSL_read");
+ log_crypto_err_io("could not SSL_read", want);
return 0;
}
c->tcp_byte_count += r;
@@ -1984,7 +2002,7 @@ ssl_handle_read(struct comm_point* c)
strerror(errno));
return 0;
}
- log_crypto_err("could not SSL_read");
+ log_crypto_err_io("could not SSL_read", want);
return 0;
}
sldns_buffer_skip(c->buffer, (ssize_t)r);
@@ -2075,7 +2093,7 @@ ssl_handle_write(struct comm_point* c)
strerror(errno));
return 0;
}
- log_crypto_err("could not SSL_write");
+ log_crypto_err_io("could not SSL_write", want);
return 0;
}
if(c->tcp_write_and_read) {
@@ -2127,7 +2145,7 @@ ssl_handle_write(struct comm_point* c)
strerror(errno));
return 0;
}
- log_crypto_err("could not SSL_write");
+ log_crypto_err_io("could not SSL_write", want);
return 0;
}
if(c->tcp_write_and_read) {
@@ -2211,19 +2229,25 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
goto recv_error_initial;
}
c->tcp_byte_count += r;
+ sldns_buffer_skip(c->buffer, r);
if(c->tcp_byte_count != current_read_size) return 1;
c->pp2_header_state = pp2_header_init;
}
}
if(c->pp2_header_state == pp2_header_init) {
- header = pp2_read_header(c->buffer);
- if(!header) {
+ int err;
+ err = pp2_read_header(
+ sldns_buffer_begin(c->buffer),
+ sldns_buffer_limit(c->buffer));
+ if(err) {
log_err("proxy_protocol: could not parse "
- "PROXYv2 header");
+ "PROXYv2 header (%s)",
+ pp_lookup_error(err));
return 0;
}
+ header = (struct pp2_header*)sldns_buffer_begin(c->buffer);
want_read_size = ntohs(header->len);
- if(sldns_buffer_remaining(c->buffer) <
+ if(sldns_buffer_limit(c->buffer) <
PP2_HEADER_SIZE + want_read_size) {
log_err_addr("proxy_protocol: not enough "
"buffer size to read PROXYv2 header", "",
@@ -2250,6 +2274,7 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
goto recv_error;
}
c->tcp_byte_count += r;
+ sldns_buffer_skip(c->buffer, r);
if(c->tcp_byte_count != current_read_size) return 1;
c->pp2_header_state = pp2_header_done;
}
@@ -2260,6 +2285,7 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
c->repinfo.remote_addrlen);
return 0;
}
+ sldns_buffer_flip(c->buffer);
if(!consume_pp2_header(c->buffer, &c->repinfo, 1)) {
log_err_addr("proxy_protocol: could not consume "
"PROXYv2 header", "", &c->repinfo.remote_addr,
@@ -2913,7 +2939,7 @@ ssl_http_read_more(struct comm_point* c)
strerror(errno));
return 0;
}
- log_crypto_err("could not SSL_read");
+ log_crypto_err_io("could not SSL_read", want);
return 0;
}
verbose(VERB_ALGO, "ssl http read more skip to %d + %d",
@@ -3364,7 +3390,7 @@ ssize_t http2_recv_cb(nghttp2_session* ATTR_UNUSED(session), uint8_t* buf,
strerror(errno));
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
- log_crypto_err("could not SSL_read");
+ log_crypto_err_io("could not SSL_read", want);
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
return r;
@@ -3619,7 +3645,7 @@ ssl_http_write_more(struct comm_point* c)
strerror(errno));
return 0;
}
- log_crypto_err("could not SSL_write");
+ log_crypto_err_io("could not SSL_write", want);
return 0;
}
sldns_buffer_skip(c->buffer, (ssize_t)r);
@@ -3692,7 +3718,7 @@ ssize_t http2_send_cb(nghttp2_session* ATTR_UNUSED(session), const uint8_t* buf,
strerror(errno));
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
- log_crypto_err("could not SSL_write");
+ log_crypto_err_io("could not SSL_write", want);
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
return r;
@@ -3958,11 +3984,7 @@ comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer,
evbits = UB_EV_READ | UB_EV_PERSIST;
/* ub_event stuff */
c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
-#ifdef USE_WINSOCK
comm_point_udp_callback, c);
-#else
- comm_point_udp_ancil_callback, c);
-#endif
if(c->ev->ev == NULL) {
log_err("could not baseset udp event");
comm_point_delete(c);
@@ -3977,6 +3999,7 @@ comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer,
return c;
}
+#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG)
struct comm_point*
comm_point_create_udp_ancil(struct comm_base *base, int fd,
sldns_buffer* buffer, int pp2_enabled,
@@ -4039,6 +4062,7 @@ comm_point_create_udp_ancil(struct comm_base *base, int fd,
c->event_added = 1;
return c;
}
+#endif
static struct comm_point*
comm_point_create_tcp_handler(struct comm_base *base,