aboutsummaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2020-08-21 22:56:05 +0000
committerCy Schubert <cy@FreeBSD.org>2020-08-21 22:56:05 +0000
commit7973006f41cdaf144441d1a39f9f075053435e2f (patch)
tree157d55b04796bb6f041656c0e84dd5106f4bc4be /services
parent6a53c00e64c4cf911eb00846733d9e6a47b2e7f4 (diff)
downloadsrc-7973006f41cdaf144441d1a39f9f075053435e2f.tar.gz
src-7973006f41cdaf144441d1a39f9f075053435e2f.zip
Vendor import of Unbound 1.11.0.vendor/unbound/1.11.0
Notes
Notes: svn path=/vendor/unbound/dist/; revision=364468 svn path=/vendor/unbound/1.11.0/; revision=364470; tag=vendor/unbound/1.11.0
Diffstat (limited to 'services')
-rw-r--r--services/authzone.c63
-rw-r--r--services/authzone.h9
-rw-r--r--services/listen_dnsport.c90
-rw-r--r--services/listen_dnsport.h9
-rw-r--r--services/localzone.c2
-rw-r--r--services/mesh.c107
-rw-r--r--services/modstack.c9
-rw-r--r--services/outside_network.c121
-rw-r--r--services/outside_network.h14
-rw-r--r--services/rpz.c33
-rw-r--r--services/rpz.h8
11 files changed, 315 insertions, 150 deletions
diff --git a/services/authzone.c b/services/authzone.c
index 34170abaf4a2..a26d1003abe2 100644
--- a/services/authzone.c
+++ b/services/authzone.c
@@ -392,12 +392,12 @@ auth_zone_delete(struct auth_zone* z, struct auth_zones* az)
if(az && z->rpz) {
/* keep RPZ linked list intact */
lock_rw_wrlock(&az->rpz_lock);
- if(z->rpz->prev)
- z->rpz->prev->next = z->rpz->next;
+ if(z->rpz_az_prev)
+ z->rpz_az_prev->rpz_az_next = z->rpz_az_next;
else
- az->rpz_first = z->rpz->next;
- if(z->rpz->next)
- z->rpz->next->prev = z->rpz->prev;
+ az->rpz_first = z->rpz_az_next;
+ if(z->rpz_az_next)
+ z->rpz_az_next->rpz_az_prev = z->rpz_az_prev;
lock_rw_unlock(&az->rpz_lock);
}
if(z->rpz)
@@ -426,9 +426,11 @@ auth_zone_create(struct auth_zones* az, uint8_t* nm, size_t nmlen,
}
rbtree_init(&z->data, &auth_data_cmp);
lock_rw_init(&z->lock);
- lock_protect(&z->lock, &z->name, sizeof(*z)-sizeof(rbnode_type));
+ lock_protect(&z->lock, &z->name, sizeof(*z)-sizeof(rbnode_type)-
+ sizeof(&z->rpz_az_next)-sizeof(&z->rpz_az_prev));
lock_rw_wrlock(&z->lock);
- /* z lock protects all, except rbtree itself, which is az->lock */
+ /* z lock protects all, except rbtree itself and the rpz linked list
+ * pointers, which are protected using az->lock */
if(!rbtree_insert(&az->ztree, &z->node)) {
lock_rw_unlock(&z->lock);
auth_zone_delete(z, NULL);
@@ -1178,9 +1180,9 @@ az_insert_rr(struct auth_zone* z, uint8_t* rr, size_t rr_len,
return 0;
}
if(z->rpz) {
- if(!(rpz_insert_rr(z->rpz, z->namelen, dname, dname_len,
- rr_type, rr_class, rr_ttl, rdata, rdatalen, rr,
- rr_len)))
+ if(!(rpz_insert_rr(z->rpz, z->name, z->namelen, dname,
+ dname_len, rr_type, rr_class, rr_ttl, rdata, rdatalen,
+ rr, rr_len)))
return 0;
}
return 1;
@@ -1864,15 +1866,26 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
struct auth_xfer* x = NULL;
/* create zone */
+ if(c->isrpz) {
+ /* if the rpz lock is needed, grab it before the other
+ * locks to avoid a lock dependency cycle */
+ lock_rw_wrlock(&az->rpz_lock);
+ }
lock_rw_wrlock(&az->lock);
if(!(z=auth_zones_find_or_add_zone(az, c->name))) {
lock_rw_unlock(&az->lock);
+ if(c->isrpz) {
+ lock_rw_unlock(&az->rpz_lock);
+ }
return 0;
}
if(c->masters || c->urls) {
if(!(x=auth_zones_find_or_add_xfer(az, z))) {
lock_rw_unlock(&az->lock);
lock_rw_unlock(&z->lock);
+ if(c->isrpz) {
+ lock_rw_unlock(&az->rpz_lock);
+ }
return 0;
}
}
@@ -1887,6 +1900,9 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
lock_basic_unlock(&x->lock);
}
lock_rw_unlock(&z->lock);
+ if(c->isrpz) {
+ lock_rw_unlock(&az->rpz_lock);
+ }
return 0;
}
z->for_downstream = c->for_downstream;
@@ -1897,11 +1913,14 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
fatal_exit("Could not setup RPZ zones");
return 0;
}
- lock_rw_wrlock(&az->rpz_lock);
- z->rpz->next = az->rpz_first;
+ lock_protect(&z->lock, &z->rpz->local_zones, sizeof(*z->rpz));
+ /* the az->rpz_lock is locked above */
+ z->rpz_az_next = az->rpz_first;
if(az->rpz_first)
- az->rpz_first->prev = z->rpz;
- az->rpz_first = z->rpz;
+ az->rpz_first->rpz_az_prev = z;
+ az->rpz_first = z;
+ }
+ if(c->isrpz) {
lock_rw_unlock(&az->rpz_lock);
}
@@ -5331,7 +5350,7 @@ void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
log_assert(xfr->task_transfer);
lock_basic_lock(&xfr->lock);
env = xfr->task_transfer->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return; /* stop on quit */
}
@@ -5770,7 +5789,7 @@ auth_xfer_transfer_timer_callback(void* arg)
log_assert(xfr->task_transfer);
lock_basic_lock(&xfr->lock);
env = xfr->task_transfer->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return; /* stop on quit */
}
@@ -5812,7 +5831,7 @@ auth_xfer_transfer_tcp_callback(struct comm_point* c, void* arg, int err,
log_assert(xfr->task_transfer);
lock_basic_lock(&xfr->lock);
env = xfr->task_transfer->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return 0; /* stop on quit */
}
@@ -5893,7 +5912,7 @@ auth_xfer_transfer_http_callback(struct comm_point* c, void* arg, int err,
log_assert(xfr->task_transfer);
lock_basic_lock(&xfr->lock);
env = xfr->task_transfer->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return 0; /* stop on quit */
}
@@ -6107,7 +6126,7 @@ auth_xfer_probe_timer_callback(void* arg)
log_assert(xfr->task_probe);
lock_basic_lock(&xfr->lock);
env = xfr->task_probe->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return; /* stop on quit */
}
@@ -6143,7 +6162,7 @@ auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
log_assert(xfr->task_probe);
lock_basic_lock(&xfr->lock);
env = xfr->task_probe->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return 0; /* stop on quit */
}
@@ -6388,7 +6407,7 @@ void auth_xfer_probe_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
log_assert(xfr->task_probe);
lock_basic_lock(&xfr->lock);
env = xfr->task_probe->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return; /* stop on quit */
}
@@ -6465,7 +6484,7 @@ auth_xfer_timer(void* arg)
log_assert(xfr->task_nextprobe);
lock_basic_lock(&xfr->lock);
env = xfr->task_nextprobe->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return; /* stop on quit */
}
diff --git a/services/authzone.h b/services/authzone.h
index 9bb131ad8b39..3d94f30d6202 100644
--- a/services/authzone.h
+++ b/services/authzone.h
@@ -82,8 +82,8 @@ struct auth_zones {
size_t num_query_up;
/** number of queries downstream */
size_t num_query_down;
- /** first rpz item in linked list */
- struct rpz* rpz_first;
+ /** first auth zone containing rpz item in linked list */
+ struct auth_zone* rpz_first;
/** rw lock for rpz linked list, needed when iterating or editing linked
* list. */
lock_rw_type rpz_lock;
@@ -138,6 +138,11 @@ struct auth_zone {
int zone_deleted;
/** deletelist pointer, unused normally except during delete */
struct auth_zone* delete_next;
+ /* not protected by auth_zone lock, must be last items in struct */
+ /** next auth zone containing RPZ data, or NULL */
+ struct auth_zone* rpz_az_next;
+ /** previous auth zone containing RPZ data, or NULL */
+ struct auth_zone* rpz_az_prev;
};
/**
diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c
index 7e2afd843be8..cc56d3fd3167 100644
--- a/services/listen_dnsport.c
+++ b/services/listen_dnsport.c
@@ -179,9 +179,10 @@ int
create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t addrlen, int v6only, int* inuse, int* noproto,
int rcv, int snd, int listen, int* reuseport, int transparent,
- int freebind, int use_systemd)
+ int freebind, int use_systemd, int dscp)
{
int s;
+ char* err;
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND) || defined (SO_BINDANY)
int on=1;
#endif
@@ -451,6 +452,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
# endif
#endif /* SO_SNDBUF */
}
+ err = set_ip_dscp(s, family, dscp);
+ if(err != NULL)
+ log_warn("error setting IP DiffServ codepoint %d on UDP socket: %s", dscp, err);
if(family == AF_INET6) {
# if defined(IPV6_V6ONLY)
if(v6only) {
@@ -638,9 +642,10 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
int
create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
- int* reuseport, int transparent, int mss, int freebind, int use_systemd)
+ int* reuseport, int transparent, int mss, int freebind, int use_systemd, int dscp)
{
int s;
+ char* err;
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND) || defined(SO_BINDANY)
int on = 1;
#endif
@@ -793,6 +798,9 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
strerror(errno));
}
#endif /* IP_TRANSPARENT || IP_BINDANY || SO_BINDANY */
+ err = set_ip_dscp(s, addr->ai_family, dscp);
+ if(err != NULL)
+ log_warn("error setting IP DiffServ codepoint %d on TCP socket: %s", dscp, err);
if(
#ifdef HAVE_SYSTEMD
!got_fd_from_systemd &&
@@ -866,6 +874,55 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
return s;
}
+char*
+set_ip_dscp(int socket, int addrfamily, int dscp)
+{
+ int ds;
+
+ if(dscp == 0)
+ return NULL;
+ ds = dscp << 2;
+ switch(addrfamily) {
+ case AF_INET6:
+ if(setsockopt(socket, IPPROTO_IPV6, IPV6_TCLASS, (void*)&ds, sizeof(ds)) < 0)
+ return sock_strerror(errno);
+ break;
+ default:
+ if(setsockopt(socket, IPPROTO_IP, IP_TOS, (void*)&ds, sizeof(ds)) < 0)
+ return sock_strerror(errno);
+ break;
+ }
+ return NULL;
+}
+
+# ifndef USE_WINSOCK
+char*
+sock_strerror(int errn)
+{
+ return strerror(errn);
+}
+
+void
+sock_close(int socket)
+{
+ close(socket);
+}
+
+# else
+char*
+sock_strerror(int ATTR_UNUSED(errn))
+{
+ return wsa_strerror(WSAGetLastError());
+}
+
+void
+sock_close(int socket)
+{
+ closesocket(socket);
+}
+
+# endif /* USE_WINSOCK */
+
int
create_local_accept_sock(const char *path, int* noproto, int use_systemd)
{
@@ -952,7 +1009,7 @@ err:
static int
make_sock(int stype, const char* ifname, const char* port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
- int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd)
+ int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd, int dscp)
{
struct addrinfo *res = NULL;
int r, s, inuse, noproto;
@@ -980,7 +1037,7 @@ make_sock(int stype, const char* ifname, const char* port,
s = create_udp_sock(res->ai_family, res->ai_socktype,
(struct sockaddr*)res->ai_addr, res->ai_addrlen,
v6only, &inuse, &noproto, (int)rcv, (int)snd, 1,
- reuseport, transparent, freebind, use_systemd);
+ reuseport, transparent, freebind, use_systemd, dscp);
if(s == -1 && inuse) {
log_err("bind: address already in use");
} else if(s == -1 && noproto && hints->ai_family == AF_INET6){
@@ -988,7 +1045,7 @@ make_sock(int stype, const char* ifname, const char* port,
}
} else {
s = create_tcp_accept_sock(res, v6only, &noproto, reuseport,
- transparent, tcp_mss, freebind, use_systemd);
+ transparent, tcp_mss, freebind, use_systemd, dscp);
if(s == -1 && noproto && hints->ai_family == AF_INET6){
*noip6 = 1;
}
@@ -1001,7 +1058,7 @@ make_sock(int stype, const char* ifname, const char* port,
static int
make_sock_port(int stype, const char* ifname, const char* port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
- int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd)
+ int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd, int dscp)
{
char* s = strchr(ifname, '@');
if(s) {
@@ -1023,10 +1080,10 @@ make_sock_port(int stype, const char* ifname, const char* port,
(void)strlcpy(p, s+1, sizeof(p));
p[strlen(s+1)]=0;
return make_sock(stype, newif, p, hints, v6only, noip6,
- rcv, snd, reuseport, transparent, tcp_mss, freebind, use_systemd);
+ rcv, snd, reuseport, transparent, tcp_mss, freebind, use_systemd, dscp);
}
return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd,
- reuseport, transparent, tcp_mss, freebind, use_systemd);
+ reuseport, transparent, tcp_mss, freebind, use_systemd, dscp);
}
/**
@@ -1146,6 +1203,7 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
* @param freebind: set IP_FREEBIND socket option.
* @param use_systemd: if true, fetch sockets from systemd.
* @param dnscrypt_port: dnscrypt service port number
+ * @param dscp: DSCP to use.
* @return: returns false on error.
*/
static int
@@ -1154,7 +1212,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
size_t rcv, size_t snd, int ssl_port,
struct config_strlist* tls_additional_port, int* reuseport,
int transparent, int tcp_mss, int freebind, int use_systemd,
- int dnscrypt_port)
+ int dnscrypt_port, int dscp)
{
int s, noip6=0;
#ifdef USE_DNSCRYPT
@@ -1171,7 +1229,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if(do_auto) {
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
- tcp_mss, freebind, use_systemd)) == -1) {
+ tcp_mss, freebind, use_systemd, dscp)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
@@ -1200,7 +1258,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
/* regular udp socket */
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
- tcp_mss, freebind, use_systemd)) == -1) {
+ tcp_mss, freebind, use_systemd, dscp)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
@@ -1222,7 +1280,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
tls_additional_port);
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
&noip6, 0, 0, reuseport, transparent, tcp_mss,
- freebind, use_systemd)) == -1) {
+ freebind, use_systemd, dscp)) == -1) {
if(noip6) {
/*log_warn("IPv6 protocol not available");*/
return 1;
@@ -1421,7 +1479,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->ssl_port, cfg->tls_additional_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
- cfg->dnscrypt_port)) {
+ cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
@@ -1435,7 +1493,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->ssl_port, cfg->tls_additional_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
- cfg->dnscrypt_port)) {
+ cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
@@ -1451,7 +1509,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->ssl_port, cfg->tls_additional_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
- cfg->dnscrypt_port)) {
+ cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
@@ -1465,7 +1523,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->ssl_port, cfg->tls_additional_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
- cfg->dnscrypt_port)) {
+ cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
diff --git a/services/listen_dnsport.h b/services/listen_dnsport.h
index ad84d8322643..ddd1b63a4d95 100644
--- a/services/listen_dnsport.h
+++ b/services/listen_dnsport.h
@@ -205,11 +205,12 @@ void listen_start_accept(struct listen_dnsport* listen);
* @param transparent: set IP_TRANSPARENT socket option.
* @param freebind: set IP_FREEBIND socket option.
* @param use_systemd: if true, fetch sockets from systemd.
+ * @param dscp: DSCP to use.
* @return: the socket. -1 on error.
*/
int create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t addrlen, int v6only, int* inuse, int* noproto, int rcv,
- int snd, int listen, int* reuseport, int transparent, int freebind, int use_systemd);
+ int snd, int listen, int* reuseport, int transparent, int freebind, int use_systemd, int dscp);
/**
* Create and bind TCP listening socket
@@ -222,10 +223,11 @@ int create_udp_sock(int family, int socktype, struct sockaddr* addr,
* @param mss: maximum segment size of the socket. if zero, leaves the default.
* @param freebind: set IP_FREEBIND socket option.
* @param use_systemd: if true, fetch sockets from systemd.
+ * @param dscp: DSCP to use.
* @return: the socket. -1 on error.
*/
int create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
- int* reuseport, int transparent, int mss, int freebind, int use_systemd);
+ int* reuseport, int transparent, int mss, int freebind, int use_systemd, int dscp);
/**
* Create and bind local listening socket
@@ -367,4 +369,7 @@ int tcp_req_info_handle_read_close(struct tcp_req_info* req);
/** get the size of currently used tcp stream wait buffers (in bytes) */
size_t tcp_req_info_get_stream_buffer_size(void);
+char* set_ip_dscp(int socket, int addrfamily, int ds);
+char* sock_strerror(int errn);
+
#endif /* LISTEN_DNSPORT_H */
diff --git a/services/localzone.c b/services/localzone.c
index 18407832ff41..6aaf0c05518c 100644
--- a/services/localzone.c
+++ b/services/localzone.c
@@ -518,7 +518,7 @@ local_zone_enter_rr(struct local_zone* z, uint8_t* nm, size_t nmlen,
}
/** enter data RR into auth zone */
-int
+static int
lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr)
{
uint8_t* nm;
diff --git a/services/mesh.c b/services/mesh.c
index 9114ef4c4e2d..4b0c5db418f7 100644
--- a/services/mesh.c
+++ b/services/mesh.c
@@ -159,16 +159,28 @@ client_info_compare(const struct respip_client_info* ci_a,
return 1;
if(ci_a->taglen != ci_b->taglen)
return (ci_a->taglen < ci_b->taglen) ? -1 : 1;
- cmp = memcmp(ci_a->taglist, ci_b->taglist, ci_a->taglen);
- if(cmp != 0)
- return cmp;
+ if(ci_a->taglist && !ci_b->taglist)
+ return -1;
+ if(!ci_a->taglist && ci_b->taglist)
+ return 1;
+ if(ci_a->taglist && ci_b->taglist) {
+ cmp = memcmp(ci_a->taglist, ci_b->taglist, ci_a->taglen);
+ if(cmp != 0)
+ return cmp;
+ }
if(ci_a->tag_actions_size != ci_b->tag_actions_size)
return (ci_a->tag_actions_size < ci_b->tag_actions_size) ?
-1 : 1;
- cmp = memcmp(ci_a->tag_actions, ci_b->tag_actions,
- ci_a->tag_actions_size);
- if(cmp != 0)
- return cmp;
+ if(ci_a->tag_actions && !ci_b->tag_actions)
+ return -1;
+ if(!ci_a->tag_actions && ci_b->tag_actions)
+ return 1;
+ if(ci_a->tag_actions && ci_b->tag_actions) {
+ cmp = memcmp(ci_a->tag_actions, ci_b->tag_actions,
+ ci_a->tag_actions_size);
+ if(cmp != 0)
+ return cmp;
+ }
if(ci_a->tag_datas != ci_b->tag_datas)
return ci_a->tag_datas < ci_b->tag_datas ? -1 : 1;
if(ci_a->view != ci_b->view)
@@ -1284,7 +1296,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
void mesh_query_done(struct mesh_state* mstate)
{
- struct mesh_reply* r, *reply_list = NULL;
+ struct mesh_reply* r;
struct mesh_reply* prev = NULL;
struct sldns_buffer* prev_buffer = NULL;
struct mesh_cb* c;
@@ -1308,27 +1320,7 @@ void mesh_query_done(struct mesh_state* mstate)
free(err);
}
}
- if(mstate->reply_list) {
- /* set the reply_list to NULL during the mesh_query_done
- * processing, so that calls back into the mesh from
- * tcp_req_info (deciding to drop the reply and thus
- * unregister the mesh_reply from the mstate) are stopped
- * because the list is empty.
- * The mstate is then likely not a reply_state, and maybe
- * also a detached_state.
- */
- reply_list = mstate->reply_list;
- mstate->reply_list = NULL;
- if(!mstate->reply_list && !mstate->cb_list) {
- /* was a reply state, not anymore */
- log_assert(mstate->s.env->mesh->num_reply_states > 0);
- mstate->s.env->mesh->num_reply_states--;
- }
- if(!mstate->reply_list && !mstate->cb_list &&
- mstate->super_set.count == 0)
- mstate->s.env->mesh->num_detached_states++;
- }
- for(r = reply_list; r; r = r->next) {
+ for(r = mstate->reply_list; r; r = r->next) {
/* if a response-ip address block has been stored the
* information should be logged for each client. */
if(mstate->s.respip_action_info &&
@@ -1352,15 +1344,31 @@ void mesh_query_done(struct mesh_state* mstate)
/* if this query is determined to be dropped during the
* mesh processing, this is the point to take that action. */
if(mstate->s.is_drop) {
+ /* briefly set the reply_list to NULL, so that the
+ * tcp req info cleanup routine that calls the mesh
+ * to deregister the meshstate for it is not done
+ * because the list is NULL and also accounting is not
+ * done there, but instead we do that here. */
+ struct mesh_reply* reply_list = mstate->reply_list;
+ mstate->reply_list = NULL;
comm_point_drop_reply(&r->query_reply);
+ mstate->reply_list = reply_list;
} else {
struct sldns_buffer* r_buffer = r->query_reply.c->buffer;
+ struct mesh_reply* rlist = mstate->reply_list;
if(r->query_reply.c->tcp_req_info) {
r_buffer = r->query_reply.c->tcp_req_info->spool_buffer;
prev_buffer = NULL;
}
+ /* briefly set the replylist to null in case the
+ * meshsendreply calls tcpreqinfo sendreply that
+ * comm_point_drops because of size, and then the
+ * null stops the mesh state remove and thus
+ * reply_list modification and accounting */
+ mstate->reply_list = NULL;
mesh_send_reply(mstate, mstate->s.return_rcode, rep,
r, r_buffer, prev, prev_buffer);
+ mstate->reply_list = rlist;
if(r->query_reply.c->tcp_req_info) {
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
r_buffer = NULL;
@@ -1369,6 +1377,17 @@ void mesh_query_done(struct mesh_state* mstate)
prev_buffer = r_buffer;
}
}
+ if(mstate->reply_list) {
+ mstate->reply_list = NULL;
+ if(!mstate->reply_list && !mstate->cb_list) {
+ /* was a reply state, not anymore */
+ log_assert(mstate->s.env->mesh->num_reply_states > 0);
+ mstate->s.env->mesh->num_reply_states--;
+ }
+ if(!mstate->reply_list && !mstate->cb_list &&
+ mstate->super_set.count == 0)
+ mstate->s.env->mesh->num_detached_states++;
+ }
mstate->replies_sent = 1;
while((c = mstate->cb_list) != NULL) {
/* take this cb off the list; so that the list can be
@@ -1863,7 +1882,7 @@ mesh_serve_expired_callback(void* arg)
{
struct mesh_state* mstate = (struct mesh_state*) arg;
struct module_qstate* qstate = &mstate->s;
- struct mesh_reply* r;
+ struct mesh_reply* r, *rlist;
struct mesh_area* mesh = qstate->env->mesh;
struct dns_msg* msg;
struct mesh_cb* c;
@@ -1946,16 +1965,7 @@ mesh_serve_expired_callback(void* arg)
if(verbosity >= VERB_ALGO)
log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep);
- r = mstate->reply_list;
- mstate->reply_list = NULL;
- if(!mstate->reply_list && !mstate->cb_list) {
- log_assert(mesh->num_reply_states > 0);
- mesh->num_reply_states--;
- if(mstate->super_set.count == 0) {
- mesh->num_detached_states++;
- }
- }
- for(; r; r = r->next) {
+ for(r = mstate->reply_list; r; r = r->next) {
/* If address info is returned, it means the action should be an
* 'inform' variant and the information should be logged. */
if(actinfo.addrinfo) {
@@ -1977,8 +1987,15 @@ mesh_serve_expired_callback(void* arg)
r_buffer = r->query_reply.c->buffer;
if(r->query_reply.c->tcp_req_info)
r_buffer = r->query_reply.c->tcp_req_info->spool_buffer;
+ /* briefly set the replylist to null in case the meshsendreply
+ * calls tcpreqinfo sendreply that comm_point_drops because
+ * of size, and then the null stops the mesh state remove and
+ * thus reply_list modification and accounting */
+ rlist = mstate->reply_list;
+ mstate->reply_list = NULL;
mesh_send_reply(mstate, LDNS_RCODE_NOERROR, msg->rep,
r, r_buffer, prev, prev_buffer);
+ mstate->reply_list = rlist;
if(r->query_reply.c->tcp_req_info)
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
prev = r;
@@ -1988,6 +2005,16 @@ mesh_serve_expired_callback(void* arg)
mesh->ans_expired++;
}
+ if(mstate->reply_list) {
+ mstate->reply_list = NULL;
+ if(!mstate->reply_list && !mstate->cb_list) {
+ log_assert(mesh->num_reply_states > 0);
+ mesh->num_reply_states--;
+ if(mstate->super_set.count == 0) {
+ mesh->num_detached_states++;
+ }
+ }
+ }
while((c = mstate->cb_list) != NULL) {
/* take this cb off the list; so that the list can be
* changed, eg. by adds from the callback routine */
diff --git a/services/modstack.c b/services/modstack.c
index 68e5928146dd..a600549b16c3 100644
--- a/services/modstack.c
+++ b/services/modstack.c
@@ -51,6 +51,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
@@ -140,6 +143,9 @@ module_list_avail(void)
#ifdef WITH_PYTHONMODULE
"python",
#endif
+#ifdef WITH_DYNLIBMODULE
+ "dynlib",
+#endif
#ifdef USE_CACHEDB
"cachedb",
#endif
@@ -171,6 +177,9 @@ module_funcs_avail(void)
#ifdef WITH_PYTHONMODULE
&pythonmod_get_funcblock,
#endif
+#ifdef WITH_DYNLIBMODULE
+ &dynlibmod_get_funcblock,
+#endif
#ifdef USE_CACHEDB
&cachedb_get_funcblock,
#endif
diff --git a/services/outside_network.c b/services/outside_network.c
index 80b1f12454d6..44e01d7450cb 100644
--- a/services/outside_network.c
+++ b/services/outside_network.c
@@ -205,18 +205,25 @@ pick_outgoing_tcp(struct waiting_tcp* w, int s)
/** get TCP file descriptor for address, returns -1 on failure,
* tcp_mss is 0 or maxseg size to set for TCP packets. */
int
-outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss)
+outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss, int dscp)
{
int s;
+ int af;
+ char* err;
#ifdef SO_REUSEADDR
int on = 1;
#endif
#ifdef INET6
- if(addr_is_ip6(addr, addrlen))
+ if(addr_is_ip6(addr, addrlen)){
s = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
- else
+ af = AF_INET6;
+ } else {
+#else
+ {
#endif
+ af = AF_INET;
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ }
if(s == -1) {
#ifndef USE_WINSOCK
log_err_addr("outgoing tcp: socket", strerror(errno),
@@ -236,6 +243,12 @@ outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss)
}
#endif
+ err = set_ip_dscp(s, af, dscp);
+ if(err != NULL) {
+ verbose(VERB_ALGO, "outgoing tcp:"
+ "error setting IP DiffServ codepoint on socket");
+ }
+
if(tcp_mss > 0) {
#if defined(IPPROTO_TCP) && defined(TCP_MAXSEG)
if(setsockopt(s, IPPROTO_TCP, TCP_MAXSEG,
@@ -291,7 +304,7 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
log_assert(pkt);
log_assert(w->addrlen > 0);
/* open socket */
- s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss);
+ s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss, w->outnet->ip_dscp);
if(s == -1)
return 0;
@@ -373,45 +386,16 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
comm_point_tcp_win_bio_cb(pend->c, pend->c->ssl);
#endif
pend->c->ssl_shake_state = comm_ssl_shake_write;
- if(w->tls_auth_name) {
+ if(!set_auth_name_on_ssl(pend->c->ssl, w->tls_auth_name,
+ w->outnet->tls_use_sni)) {
+ pend->c->fd = s;
#ifdef HAVE_SSL
- (void)SSL_set_tlsext_host_name(pend->c->ssl, w->tls_auth_name);
+ SSL_free(pend->c->ssl);
#endif
+ pend->c->ssl = NULL;
+ comm_point_close(pend->c);
+ return 0;
}
-#ifdef HAVE_SSL_SET1_HOST
- if(w->tls_auth_name) {
- SSL_set_verify(pend->c->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(pend->c->ssl, w->tls_auth_name)) {
- log_err("SSL_set1_host failed");
- pend->c->fd = s;
- SSL_free(pend->c->ssl);
- pend->c->ssl = NULL;
- comm_point_close(pend->c);
- 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(w->tls_auth_name) {
- X509_VERIFY_PARAM* param = SSL_get0_param(pend->c->ssl);
- X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
- if(!X509_VERIFY_PARAM_set1_host(param, w->tls_auth_name, strlen(w->tls_auth_name))) {
- log_err("X509_VERIFY_PARAM_set1_host failed");
- pend->c->fd = s;
- SSL_free(pend->c->ssl);
- pend->c->ssl = NULL;
- comm_point_close(pend->c);
- return 0;
- }
- SSL_set_verify(pend->c->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 */
}
w->pkt = NULL;
w->next_waiting = (void*)pend;
@@ -512,7 +496,9 @@ portcomm_loweruse(struct outside_network* outnet, struct port_comm* pc)
comm_point_close(pc->cp);
pif = pc->pif;
log_assert(pif->inuse > 0);
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
pif->avail_ports[pif->avail_total - pif->inuse] = pc->number;
+#endif
pif->inuse--;
pif->out[pc->index] = pif->out[pif->inuse];
pif->out[pc->index]->index = pc->index;
@@ -725,10 +711,12 @@ create_pending_tcp(struct outside_network* outnet, size_t bufsize)
static int setup_if(struct port_if* pif, const char* addrstr,
int* avail, int numavail, size_t numfd)
{
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
pif->avail_total = numavail;
pif->avail_ports = (int*)memdup(avail, (size_t)numavail*sizeof(int));
if(!pif->avail_ports)
return 0;
+#endif
if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen) &&
!netblockstrtoaddr(addrstr, UNBOUND_DNS_PORT,
&pif->addr, &pif->addrlen, &pif->pfxlen))
@@ -745,11 +733,11 @@ static int setup_if(struct port_if* pif, const char* addrstr,
struct outside_network*
outside_network_create(struct comm_base *base, size_t bufsize,
size_t num_ports, char** ifs, int num_ifs, int do_ip4,
- int do_ip6, size_t num_tcp, struct infra_cache* infra,
+ int do_ip6, size_t num_tcp, int dscp, struct infra_cache* infra,
struct ub_randstate* rnd, int use_caps_for_id, int* availports,
int numavailports, size_t unwanted_threshold, int tcp_mss,
void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
- void* sslctx, int delayclose, struct dt_env* dtenv)
+ void* sslctx, int delayclose, int tls_use_sni, struct dt_env* dtenv)
{
struct outside_network* outnet = (struct outside_network*)
calloc(1, sizeof(struct outside_network));
@@ -765,6 +753,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
outnet->infra = infra;
outnet->rnd = rnd;
outnet->sslctx = sslctx;
+ outnet->tls_use_sni = tls_use_sni;
#ifdef USE_DNSTAP
outnet->dtenv = dtenv;
#else
@@ -778,6 +767,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
outnet->use_caps_for_id = use_caps_for_id;
outnet->do_udp = do_udp;
outnet->tcp_mss = tcp_mss;
+ outnet->ip_dscp = dscp;
#ifndef S_SPLINT_S
if(delayclose) {
outnet->delayclose = 1;
@@ -955,7 +945,9 @@ outside_network_delete(struct outside_network* outnet)
comm_point_delete(pc->cp);
free(pc);
}
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
free(outnet->ip4_ifs[i].avail_ports);
+#endif
free(outnet->ip4_ifs[i].out);
}
free(outnet->ip4_ifs);
@@ -969,7 +961,9 @@ outside_network_delete(struct outside_network* outnet)
comm_point_delete(pc->cp);
free(pc);
}
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
free(outnet->ip6_ifs[i].avail_ports);
+#endif
free(outnet->ip6_ifs[i].out);
}
free(outnet->ip6_ifs);
@@ -1059,11 +1053,12 @@ sai6_putrandom(struct sockaddr_in6 *sa, int pfxlen, struct ub_randstate *rnd)
* @param port: port override for addr.
* @param inuse: if -1 is returned, this bool means the port was in use.
* @param rnd: random state (for address randomisation).
+ * @param dscp: DSCP to use.
* @return fd or -1
*/
static int
udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen,
- int port, int* inuse, struct ub_randstate* rnd)
+ int port, int* inuse, struct ub_randstate* rnd, int dscp)
{
int fd, noproto;
if(addr_is_ip6(addr, addrlen)) {
@@ -1078,13 +1073,13 @@ udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen,
}
fd = create_udp_sock(AF_INET6, SOCK_DGRAM,
(struct sockaddr*)&sa, addrlen, 1, inuse, &noproto,
- 0, 0, 0, NULL, 0, freebind, 0);
+ 0, 0, 0, NULL, 0, freebind, 0, dscp);
} else {
struct sockaddr_in* sa = (struct sockaddr_in*)addr;
sa->sin_port = (in_port_t)htons((uint16_t)port);
fd = create_udp_sock(AF_INET, SOCK_DGRAM,
(struct sockaddr*)addr, addrlen, 1, inuse, &noproto,
- 0, 0, 0, NULL, 0, 0, 0);
+ 0, 0, 0, NULL, 0, 0, 0, dscp);
}
return fd;
}
@@ -1133,6 +1128,7 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
while(1) {
my_if = ub_random_max(outnet->rnd, num_if);
pif = &ifs[my_if];
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
my_port = ub_random_max(outnet->rnd, pif->avail_total);
if(my_port < pif->inuse) {
/* port already open */
@@ -1144,8 +1140,11 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
/* try to open new port, if fails, loop to try again */
log_assert(pif->inuse < pif->maxout);
portno = pif->avail_ports[my_port - pif->inuse];
+#else
+ my_port = portno = 0;
+#endif
fd = udp_sockport(&pif->addr, pif->addrlen, pif->pfxlen,
- portno, &inuse, outnet->rnd);
+ portno, &inuse, outnet->rnd, outnet->ip_dscp);
if(fd == -1 && !inuse) {
/* nonrecoverable error making socket */
return 0;
@@ -1167,8 +1166,10 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
/* grab port in interface */
pif->out[pif->inuse] = pend->pc;
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
pif->avail_ports[my_port - pif->inuse] =
pif->avail_ports[pif->avail_total-pif->inuse-1];
+#endif
pif->inuse++;
break;
}
@@ -2192,10 +2193,11 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
{
struct sockaddr_storage* addr;
socklen_t addrlen;
- int i, try, pnum;
+ int i, try, pnum, dscp;
struct port_if* pif;
/* create fd */
+ dscp = outnet->ip_dscp;
for(try = 0; try<1000; try++) {
int port = 0;
int freebind = 0;
@@ -2225,6 +2227,7 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
}
addr = &pif->addr;
addrlen = pif->addrlen;
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
pnum = ub_random_max(outnet->rnd, pif->avail_total);
if(pnum < pif->inuse) {
/* port already open */
@@ -2233,19 +2236,21 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
/* unused ports in start part of array */
port = pif->avail_ports[pnum - pif->inuse];
}
-
+#else
+ pnum = port = 0;
+#endif
if(addr_is_ip6(to_addr, to_addrlen)) {
struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
sa.sin6_port = (in_port_t)htons((uint16_t)port);
fd = create_udp_sock(AF_INET6, SOCK_DGRAM,
(struct sockaddr*)&sa, addrlen, 1, &inuse, &noproto,
- 0, 0, 0, NULL, 0, freebind, 0);
+ 0, 0, 0, NULL, 0, freebind, 0, dscp);
} else {
struct sockaddr_in* sa = (struct sockaddr_in*)addr;
sa->sin_port = (in_port_t)htons((uint16_t)port);
fd = create_udp_sock(AF_INET, SOCK_DGRAM,
(struct sockaddr*)addr, addrlen, 1, &inuse, &noproto,
- 0, 0, 0, NULL, 0, freebind, 0);
+ 0, 0, 0, NULL, 0, freebind, 0, dscp);
}
if(fd != -1) {
return fd;
@@ -2294,6 +2299,11 @@ setup_comm_ssl(struct comm_point* cp, struct outside_network* outnet,
#endif
cp->ssl_shake_state = comm_ssl_shake_write;
/* https verification */
+#ifdef HAVE_SSL
+ if(outnet->tls_use_sni) {
+ (void)SSL_set_tlsext_host_name(cp->ssl, host);
+ }
+#endif
#ifdef HAVE_SSL_SET1_HOST
if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
/* because we set SSL_VERIFY_PEER, in netevent in
@@ -2316,7 +2326,9 @@ setup_comm_ssl(struct comm_point* cp, struct outside_network* outnet,
* set1_host like verification */
if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
X509_VERIFY_PARAM* param = SSL_get0_param(cp->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, host, strlen(host))) {
log_err("X509_VERIFY_PARAM_set1_host failed");
return 0;
@@ -2335,7 +2347,7 @@ outnet_comm_point_for_tcp(struct outside_network* outnet,
sldns_buffer* query, int timeout, int ssl, char* host)
{
struct comm_point* cp;
- int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss);
+ int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp);
if(fd == -1) {
return 0;
}
@@ -2397,7 +2409,7 @@ outnet_comm_point_for_http(struct outside_network* outnet,
{
/* cp calls cb with err=NETEVENT_DONE when transfer is done */
struct comm_point* cp;
- int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss);
+ int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp);
if(fd == -1) {
return 0;
}
@@ -2455,7 +2467,10 @@ if_get_mem(struct port_if* pif)
{
size_t s;
int i;
- s = sizeof(*pif) + sizeof(int)*pif->avail_total +
+ s = sizeof(*pif) +
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
+ sizeof(int)*pif->avail_total +
+#endif
sizeof(struct port_comm*)*pif->maxout;
for(i=0; i<pif->inuse; i++)
s += sizeof(*pif->out[i]) +
diff --git a/services/outside_network.h b/services/outside_network.h
index 3456a3da38b0..c8f6d5724a87 100644
--- a/services/outside_network.h
+++ b/services/outside_network.h
@@ -132,12 +132,16 @@ struct outside_network {
struct ub_randstate* rnd;
/** ssl context to create ssl wrapped TCP with DNS connections */
void* sslctx;
+ /** if SNI will be used for TLS connections */
+ int tls_use_sni;
#ifdef USE_DNSTAP
/** dnstap environment */
struct dt_env* dtenv;
#endif
/** maximum segment size of tcp socket */
int tcp_mss;
+ /** IP_TOS socket option requested on the sockets */
+ int ip_dscp;
/**
* Array of tcp pending used for outgoing TCP connections.
@@ -172,11 +176,13 @@ struct port_if {
* if 0, no randomisation. */
int pfxlen;
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
/** the available ports array. These are unused.
* Only the first total-inuse part is filled. */
int* avail_ports;
/** the total number of available ports (size of the array) */
int avail_total;
+#endif
/** array of the commpoints currently in use.
* allocated for max number of fds, first part in use. */
@@ -399,6 +405,7 @@ struct serviced_query {
* @param do_ip4: service IP4.
* @param do_ip6: service IP6.
* @param num_tcp: number of outgoing tcp buffers to preallocate.
+ * @param dscp: DSCP to use.
* @param infra: pointer to infra cached used for serviced queries.
* @param rnd: stored to create random numbers for serviced queries.
* @param use_caps_for_id: enable to use 0x20 bits to encode id randomness.
@@ -412,16 +419,17 @@ struct serviced_query {
* @param sslctx: context to create outgoing connections with (if enabled).
* @param delayclose: if not 0, udp sockets are delayed before timeout closure.
* msec to wait on timeouted udp sockets.
+ * @param tls_use_sni: if SNI is used for TLS connections.
* @param dtenv: environment to send dnstap events with (if enabled).
* @return: the new structure (with no pending answers) or NULL on error.
*/
struct outside_network* outside_network_create(struct comm_base* base,
size_t bufsize, size_t num_ports, char** ifs, int num_ifs,
- int do_ip4, int do_ip6, size_t num_tcp, struct infra_cache* infra,
+ int do_ip4, int do_ip6, size_t num_tcp, int dscp, struct infra_cache* infra,
struct ub_randstate* rnd, int use_caps_for_id, int* availports,
int numavailports, size_t unwanted_threshold, int tcp_mss,
void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
- void* sslctx, int delayclose, struct dt_env *dtenv);
+ void* sslctx, int delayclose, int tls_use_sni, struct dt_env *dtenv);
/**
* Delete outside_network structure.
@@ -540,7 +548,7 @@ size_t serviced_get_mem(struct serviced_query* sq);
/** get TCP file descriptor for address, returns -1 on failure,
* tcp_mss is 0 or maxseg size to set for TCP packets. */
-int outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss);
+int outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss, int dscp);
/**
* Create udp commpoint suitable for sending packets to the destination.
diff --git a/services/rpz.c b/services/rpz.c
index 643b20c91d20..105f238d0a6d 100644
--- a/services/rpz.c
+++ b/services/rpz.c
@@ -586,7 +586,7 @@ rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
}
int
-rpz_insert_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
+rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl,
uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len)
{
@@ -596,9 +596,17 @@ rpz_insert_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
enum rpz_action a;
uint8_t* policydname;
+ if(!dname_subdomain_c(dname, azname)) {
+ log_err("RPZ: name of record to insert into RPZ is not a "
+ "subdomain of the configured name of the RPZ zone");
+ return 0;
+ }
+
log_assert(dnamelen >= aznamelen);
- if(!(policydname = calloc(1, (dnamelen-aznamelen)+1)))
+ if(!(policydname = calloc(1, (dnamelen-aznamelen)+1))) {
+ log_err("malloc error while inserting RPZ RR");
return 0;
+ }
a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
@@ -826,6 +834,8 @@ rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
delete_zone = rpz_data_delete_rr(z, dname,
dnamelen, rr_type, rdatawl, rdatalen);
else if(a != localzone_type_to_rpz_action(z->type)) {
+ lock_rw_unlock(&z->lock);
+ lock_rw_unlock(&r->local_zones->lock);
return;
}
lock_rw_unlock(&z->lock);
@@ -931,13 +941,16 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
struct regional* temp, struct comm_reply* repinfo,
uint8_t* taglist, size_t taglen, struct ub_server_stats* stats)
{
- struct rpz* r;
+ struct rpz* r = NULL;
+ struct auth_zone* a;
int ret;
enum localzone_type lzt;
struct local_zone* z = NULL;
struct local_data* ld = NULL;
lock_rw_rdlock(&az->rpz_lock);
- for(r = az->rpz_first; r; r = r->next) {
+ for(a = az->rpz_first; a; a = a->rpz_az_next) {
+ lock_rw_rdlock(&a->lock);
+ r = a->rpz;
if(!r->taglist || taglist_intersect(r->taglist,
r->taglistlen, taglist, taglen)) {
z = rpz_find_zone(r, qinfo->qname, qinfo->qname_len,
@@ -955,13 +968,14 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
}
if(z)
break;
- }
+ }
+ lock_rw_unlock(&a->lock); /* not found in this auth_zone */
}
lock_rw_unlock(&az->rpz_lock);
if(!z)
- return 0;
+ return 0; /* not holding auth_zone.lock anymore */
-
+ log_assert(r);
if(r->action_override == RPZ_NO_OVERRIDE_ACTION)
lzt = z->type;
else
@@ -972,6 +986,7 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
regional_alloc_zero(temp, sizeof(struct local_rrset));
if(!qinfo->local_alias) {
lock_rw_unlock(&z->lock);
+ lock_rw_unlock(&a->lock);
return 0; /* out of memory */
}
qinfo->local_alias->rrset =
@@ -979,6 +994,7 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
sizeof(*r->cname_override));
if(!qinfo->local_alias->rrset) {
lock_rw_unlock(&z->lock);
+ lock_rw_unlock(&a->lock);
return 0; /* out of memory */
}
qinfo->local_alias->rrset->rk.dname = qinfo->qname;
@@ -988,6 +1004,7 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
qinfo, repinfo, r->log_name);
stats->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
lock_rw_unlock(&z->lock);
+ lock_rw_unlock(&a->lock);
return 0;
}
@@ -1000,6 +1017,7 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
repinfo, r->log_name);
stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
lock_rw_unlock(&z->lock);
+ lock_rw_unlock(&a->lock);
return !qinfo->local_alias;
}
@@ -1010,6 +1028,7 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
qinfo, repinfo, r->log_name);
stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
lock_rw_unlock(&z->lock);
+ lock_rw_unlock(&a->lock);
return ret;
}
diff --git a/services/rpz.h b/services/rpz.h
index 676a4f2a8406..77a2db55ced4 100644
--- a/services/rpz.h
+++ b/services/rpz.h
@@ -86,7 +86,8 @@ enum rpz_action {
/**
* RPZ containing policies. Pointed to from corresponding auth-zone. Part of a
* linked list to keep configuration order. Iterating or changing the linked
- * list requires the rpz_lock from struct auth_zones.
+ * list requires the rpz_lock from struct auth_zones. Changing items in this
+ * struct require the lock from struct auth_zone.
*/
struct rpz {
struct local_zones* local_zones;
@@ -97,14 +98,13 @@ struct rpz {
struct ub_packed_rrset_key* cname_override;
int log;
char* log_name;
- struct rpz* next;
- struct rpz* prev;
struct regional* region;
};
/**
* Create policy from RR and add to this RPZ.
* @param r: the rpz to add the policy to.
+ * @param azname: dname of the auth-zone
* @param aznamelen: the length of the auth-zone name
* @param dname: dname of the RR
* @param dnamelen: length of the dname
@@ -117,7 +117,7 @@ struct rpz {
* @param rr_len: the length of the complete RR
* @return: 0 on error
*/
-int rpz_insert_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
+int rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl,
uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len);