aboutsummaryrefslogtreecommitdiff
path: root/contrib/unbound/services/listen_dnsport.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/unbound/services/listen_dnsport.c')
-rw-r--r--contrib/unbound/services/listen_dnsport.c293
1 files changed, 190 insertions, 103 deletions
diff --git a/contrib/unbound/services/listen_dnsport.c b/contrib/unbound/services/listen_dnsport.c
index 1c7c177a007e..753550978a07 100644
--- a/contrib/unbound/services/listen_dnsport.c
+++ b/contrib/unbound/services/listen_dnsport.c
@@ -4,22 +4,22 @@
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
- *
+ *
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- *
+ *
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -79,9 +79,11 @@
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
-
+#ifdef HAVE_LINUX_NET_TSTAMP_H
+#include <linux/net_tstamp.h>
+#endif
/** number of queued TCP connections for listen() */
-#define TCP_BACKLOG 256
+#define TCP_BACKLOG 256
#ifndef THREADS_DISABLED
/** lock on the counter of stream buffer memory */
@@ -124,12 +126,12 @@ verbose_print_addr(struct addrinfo *addr)
(void)strlcpy(buf, "(null)", sizeof(buf));
}
buf[sizeof(buf)-1] = 0;
- verbose(VERB_ALGO, "creating %s%s socket %s %d",
+ verbose(VERB_ALGO, "creating %s%s socket %s %d",
addr->ai_socktype==SOCK_DGRAM?"udp":
addr->ai_socktype==SOCK_STREAM?"tcp":"otherproto",
addr->ai_family==AF_INET?"4":
addr->ai_family==AF_INET6?"6":
- "_otherfam", buf,
+ "_otherfam", buf,
ntohs(((struct sockaddr_in*)addr->ai_addr)->sin_port));
}
}
@@ -140,7 +142,9 @@ verbose_print_unbound_socket(struct unbound_socket* ub_sock)
if(verbosity >= VERB_ALGO) {
log_info("listing of unbound_socket structure:");
verbose_print_addr(ub_sock->addr);
- log_info("s is: %d, fam is: %s", ub_sock->s, ub_sock->fam == AF_INET?"AF_INET":"AF_INET6");
+ log_info("s is: %d, fam is: %s, acl: %s", ub_sock->s,
+ ub_sock->fam == AF_INET?"AF_INET":"AF_INET6",
+ ub_sock->acl?"yes":"no");
}
}
@@ -185,7 +189,7 @@ systemd_get_activated(int family, int socktype, int listen,
log_err("systemd sd_listen_fds(): %s", strerror(-r));
return -1;
}
-
+
for(i = 0; i < r; i++) {
if(sd_is_socket(SD_LISTEN_FDS_START + i, family, socktype, listen)) {
s = SD_LISTEN_FDS_START + i;
@@ -251,7 +255,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
return -1;
}
#else
- if(WSAGetLastError() == WSAEAFNOSUPPORT ||
+ if(WSAGetLastError() == WSAEAFNOSUPPORT ||
WSAGetLastError() == WSAEPROTONOSUPPORT) {
*noproto = 1;
return -1;
@@ -268,7 +272,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
#endif
if(listen) {
#ifdef SO_REUSEADDR
- if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
+ if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
(socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
sock_strerror(errno));
@@ -366,9 +370,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t slen = (socklen_t)sizeof(got);
# ifdef SO_RCVBUFFORCE
/* Linux specific: try to use root permission to override
- * system limits on rcvbuf. The limit is stored in
+ * system limits on rcvbuf. The limit is stored in
* /proc/sys/net/core/rmem_max or sysctl net.core.rmem_max */
- if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv,
+ if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv,
(socklen_t)sizeof(rcv)) < 0) {
if(errno != EPERM) {
log_err("setsockopt(..., SO_RCVBUFFORCE, "
@@ -379,7 +383,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
return -1;
}
# endif /* SO_RCVBUFFORCE */
- if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv,
+ if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv,
(socklen_t)sizeof(rcv)) < 0) {
log_err("setsockopt(..., SO_RCVBUF, "
"...) failed: %s", sock_strerror(errno));
@@ -390,7 +394,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
}
/* check if we got the right thing or if system
* reduced to some system max. Warn if so */
- if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&got,
+ if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&got,
&slen) >= 0 && got < rcv/2) {
log_warn("so-rcvbuf %u was not granted. "
"Got %u. To fix: start with "
@@ -411,9 +415,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t slen = (socklen_t)sizeof(got);
# ifdef SO_SNDBUFFORCE
/* Linux specific: try to use root permission to override
- * system limits on sndbuf. The limit is stored in
+ * system limits on sndbuf. The limit is stored in
* /proc/sys/net/core/wmem_max or sysctl net.core.wmem_max */
- if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd,
+ if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd,
(socklen_t)sizeof(snd)) < 0) {
if(errno != EPERM) {
log_err("setsockopt(..., SO_SNDBUFFORCE, "
@@ -424,7 +428,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
return -1;
}
# endif /* SO_SNDBUFFORCE */
- if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd,
+ if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd,
(socklen_t)sizeof(snd)) < 0) {
log_err("setsockopt(..., SO_SNDBUF, "
"...) failed: %s", sock_strerror(errno));
@@ -435,7 +439,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
}
/* check if we got the right thing or if system
* reduced to some system max. Warn if so */
- if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got,
+ if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got,
&slen) >= 0 && got < snd/2) {
log_warn("so-sndbuf %u was not granted. "
"Got %u. To fix: start with "
@@ -458,9 +462,16 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
int action;
# endif
# if defined(IPV6_V6ONLY)
- if(v6only) {
+ if(v6only
+# ifdef HAVE_SYSTEMD
+ /* Systemd wants to control if the socket is v6 only
+ * or both, with BindIPv6Only=default, ipv6-only or
+ * both in systemd.socket, so it is not set here. */
+ && !got_fd_from_systemd
+# endif
+ ) {
int val=(v6only==2)?0:1;
- if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
(void*)&val, (socklen_t)sizeof(val)) < 0) {
log_err("setsockopt(..., IPV6_V6ONLY"
", ...) failed: %s", sock_strerror(errno));
@@ -511,12 +522,14 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
* instead which is writable; IPV6_MTU is readonly there. */
if (setsockopt(s, IPPROTO_IPV6, IPV6_USER_MTU,
(void*)&mtu, (socklen_t)sizeof(mtu)) < 0) {
- log_err("setsockopt(..., IPV6_USER_MTU, ...) failed: %s",
- wsa_strerror(WSAGetLastError()));
- sock_close(s);
- *noproto = 0;
- *inuse = 0;
- return -1;
+ if (WSAGetLastError() != WSAENOPROTOOPT) {
+ log_err("setsockopt(..., IPV6_USER_MTU, ...) failed: %s",
+ wsa_strerror(WSAGetLastError()));
+ sock_close(s);
+ *noproto = 0;
+ *inuse = 0;
+ return -1;
+ }
}
# endif /* USE_WINSOCK */
# endif /* IPv6 MTU */
@@ -565,7 +578,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
int action;
# if defined(IP_PMTUDISC_OMIT)
action = IP_PMTUDISC_OMIT;
- if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER,
+ if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER,
&action, (socklen_t)sizeof(action)) < 0) {
if (errno != EINVAL) {
@@ -598,7 +611,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
/* the IP_DONTFRAG option if defined in the 11.0 OSX headers,
* but does not work on that version, so we exclude it */
int off = 0;
- if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG,
+ if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG,
&off, (socklen_t)sizeof(off)) < 0) {
log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
strerror(errno));
@@ -636,7 +649,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
if(WSAGetLastError() != WSAEADDRINUSE &&
WSAGetLastError() != WSAEADDRNOTAVAIL &&
!(WSAGetLastError() == WSAEACCES && verbosity < 4 && !listen)) {
- log_err_addr("can't bind socket",
+ log_err_addr("can't bind socket",
wsa_strerror(WSAGetLastError()),
(struct sockaddr_storage*)addr, addrlen);
}
@@ -738,7 +751,7 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
}
#endif
#ifdef SO_REUSEADDR
- if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
+ if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
(socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
sock_strerror(errno));
@@ -774,8 +787,15 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
(void)reuseport;
#endif /* defined(SO_REUSEPORT) */
#if defined(IPV6_V6ONLY)
- if(addr->ai_family == AF_INET6 && v6only) {
- if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+ if(addr->ai_family == AF_INET6 && v6only
+# ifdef HAVE_SYSTEMD
+ /* Systemd wants to control if the socket is v6 only
+ * or both, with BindIPv6Only=default, ipv6-only or
+ * both in systemd.socket, so it is not set here. */
+ && !got_fd_from_systemd
+# endif
+ ) {
+ if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
(void*)&on, (socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
sock_strerror(errno));
@@ -827,7 +847,7 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
addr->ai_addrlen);
}
#else
- log_err_addr("can't bind socket",
+ log_err_addr("can't bind socket",
wsa_strerror(WSAGetLastError()),
(struct sockaddr_storage*)addr->ai_addr,
addr->ai_addrlen);
@@ -855,7 +875,7 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
/* 5 is recommended on linux */
qlen = 5;
#endif
- if ((setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &qlen,
+ if ((setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &qlen,
sizeof(qlen))) == -1 ) {
#ifdef ENOPROTOOPT
/* squelch ENOPROTOOPT: freebsd server mode with kernel support
@@ -981,7 +1001,7 @@ err:
* Create socket from getaddrinfo results
*/
static int
-make_sock(int stype, const char* ifname, const char* port,
+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 nodelay, int freebind,
int use_systemd, int dscp, struct unbound_socket* ub_sock)
@@ -997,10 +1017,10 @@ make_sock(int stype, const char* ifname, const char* port,
return -1;
}
#endif
- log_err("node %s:%s getaddrinfo: %s %s",
+ log_err("node %s:%s getaddrinfo: %s %s",
ifname?ifname:"default", port, gai_strerror(r),
#ifdef EAI_SYSTEM
- r==EAI_SYSTEM?(char*)strerror(errno):""
+ (r==EAI_SYSTEM?(char*)strerror(errno):"")
#else
""
#endif
@@ -1030,13 +1050,14 @@ make_sock(int stype, const char* ifname, const char* port,
ub_sock->addr = res;
ub_sock->s = s;
ub_sock->fam = hints->ai_family;
+ ub_sock->acl = NULL;
return s;
}
/** make socket and first see if ifname contains port override info */
static int
-make_sock_port(int stype, const char* ifname, const char* port,
+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 nodelay, int freebind,
int use_systemd, int dscp, struct unbound_socket* ub_sock)
@@ -1074,11 +1095,13 @@ make_sock_port(int stype, const char* ifname, const char* port,
* @param list: list head. changed.
* @param s: fd.
* @param ftype: if fd is UDP.
+ * @param pp2_enabled: if PROXYv2 is enabled for this port.
* @param ub_sock: socket with address.
* @return false on failure. list in unchanged then.
*/
static int
-port_insert(struct listen_port** list, int s, enum listen_type ftype, struct unbound_socket* ub_sock)
+port_insert(struct listen_port** list, int s, enum listen_type ftype,
+ int pp2_enabled, struct unbound_socket* ub_sock)
{
struct listen_port* item = (struct listen_port*)malloc(
sizeof(struct listen_port));
@@ -1087,14 +1110,34 @@ port_insert(struct listen_port** list, int s, enum listen_type ftype, struct unb
item->next = *list;
item->fd = s;
item->ftype = ftype;
+ item->pp2_enabled = pp2_enabled;
item->socket = ub_sock;
*list = item;
return 1;
}
+/** set fd to receive software timestamps */
+static int
+set_recvtimestamp(int s)
+{
+#ifdef HAVE_LINUX_NET_TSTAMP_H
+ int opt = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
+ if (setsockopt(s, SOL_SOCKET, SO_TIMESTAMPNS, (void*)&opt, (socklen_t)sizeof(opt)) < 0) {
+ log_err("setsockopt(..., SO_TIMESTAMPNS, ...) failed: %s",
+ strerror(errno));
+ return 0;
+ }
+ return 1;
+#else
+ log_err("packets timestamping is not supported on this platform");
+ (void)s;
+ return 0;
+#endif
+}
+
/** set fd to receive source address packet info */
static int
-set_recvpktinfo(int s, int family)
+set_recvpktinfo(int s, int family)
{
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)) || defined(IP_PKTINFO)
int on = 1;
@@ -1182,6 +1225,7 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
* @param ssl_port: ssl service port number
* @param tls_additional_port: list of additional ssl service port numbers.
* @param https_port: DoH service port number
+ * @param proxy_protocol_port: list of PROXYv2 port numbers.
* @param reuseport: try to set SO_REUSEPORT if nonNULL and true.
* set to false on exit if reuseport failed due to no kernel support.
* @param transparent: set IP_TRANSPARENT socket option.
@@ -1191,40 +1235,50 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
* @param use_systemd: if true, fetch sockets from systemd.
* @param dnscrypt_port: dnscrypt service port number
* @param dscp: DSCP to use.
+ * @param sock_queue_timeout: the sock_queue_timeout from config. Seconds to
+ * wait to discard if UDP packets have waited for long in the socket
+ * buffer.
* @return: returns false on error.
*/
static int
-ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
+ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
struct addrinfo *hints, const char* port, struct listen_port** list,
size_t rcv, size_t snd, int ssl_port,
struct config_strlist* tls_additional_port, int https_port,
+ struct config_strlist* proxy_protocol_port,
int* reuseport, int transparent, int tcp_mss, int freebind,
- int http2_nodelay, int use_systemd, int dnscrypt_port, int dscp)
+ int http2_nodelay, int use_systemd, int dnscrypt_port, int dscp,
+ int sock_queue_timeout)
{
int s, noip6=0;
int is_https = if_is_https(ifname, port, https_port);
+ int is_dnscrypt = if_is_dnscrypt(ifname, port, dnscrypt_port);
+ int is_pp2 = if_is_pp2(ifname, port, proxy_protocol_port);
int nodelay = is_https && http2_nodelay;
struct unbound_socket* ub_sock;
-#ifdef USE_DNSCRYPT
- int is_dnscrypt = ((strchr(ifname, '@') &&
- atoi(strchr(ifname, '@')+1) == dnscrypt_port) ||
- (!strchr(ifname, '@') && atoi(port) == dnscrypt_port));
-#else
- int is_dnscrypt = 0;
- (void)dnscrypt_port;
-#endif
if(!do_udp && !do_tcp)
return 0;
+ if(is_pp2) {
+ if(is_dnscrypt) {
+ fatal_exit("PROXYv2 and DNSCrypt combination not "
+ "supported!");
+ } else if(is_https) {
+ fatal_exit("PROXYv2 and DoH combination not "
+ "supported!");
+ }
+ }
+
if(do_auto) {
ub_sock = calloc(1, sizeof(struct unbound_socket));
if(!ub_sock)
return 0;
- if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
+ if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) {
- freeaddrinfo(ub_sock->addr);
+ if(ub_sock->addr)
+ freeaddrinfo(ub_sock->addr);
free(ub_sock);
if(noip6) {
log_warn("IPv6 protocol not available");
@@ -1235,14 +1289,20 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
/* getting source addr packet info is highly non-portable */
if(!set_recvpktinfo(s, hints->ai_family)) {
sock_close(s);
- freeaddrinfo(ub_sock->addr);
+ if(ub_sock->addr)
+ freeaddrinfo(ub_sock->addr);
free(ub_sock);
return 0;
}
- if(!port_insert(list, s,
- is_dnscrypt?listen_type_udpancil_dnscrypt:listen_type_udpancil, ub_sock)) {
+ if (sock_queue_timeout && !set_recvtimestamp(s)) {
+ log_warn("socket timestamping is not available");
+ }
+ if(!port_insert(list, s, is_dnscrypt
+ ?listen_type_udpancil_dnscrypt:listen_type_udpancil,
+ is_pp2, ub_sock)) {
sock_close(s);
- freeaddrinfo(ub_sock->addr);
+ if(ub_sock->addr)
+ freeaddrinfo(ub_sock->addr);
free(ub_sock);
return 0;
}
@@ -1251,10 +1311,11 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if(!ub_sock)
return 0;
/* regular udp socket */
- if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
+ if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) {
- freeaddrinfo(ub_sock->addr);
+ if(ub_sock->addr)
+ freeaddrinfo(ub_sock->addr);
free(ub_sock);
if(noip6) {
log_warn("IPv6 protocol not available");
@@ -1262,10 +1323,17 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
}
return 0;
}
- if(!port_insert(list, s,
- is_dnscrypt?listen_type_udp_dnscrypt:listen_type_udp, ub_sock)) {
+ if (sock_queue_timeout && !set_recvtimestamp(s)) {
+ log_warn("socket timestamping is not available");
+ }
+ if(!port_insert(list, s, is_dnscrypt
+ ?listen_type_udp_dnscrypt :
+ (sock_queue_timeout ?
+ listen_type_udpancil:listen_type_udp),
+ is_pp2, ub_sock)) {
sock_close(s);
- freeaddrinfo(ub_sock->addr);
+ if(ub_sock->addr)
+ freeaddrinfo(ub_sock->addr);
free(ub_sock);
return 0;
}
@@ -1285,10 +1353,11 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
port_type = listen_type_tcp_dnscrypt;
else
port_type = listen_type_tcp;
- if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
+ if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
&noip6, 0, 0, reuseport, transparent, tcp_mss, nodelay,
freebind, use_systemd, dscp, ub_sock)) == -1) {
- freeaddrinfo(ub_sock->addr);
+ if(ub_sock->addr)
+ freeaddrinfo(ub_sock->addr);
free(ub_sock);
if(noip6) {
/*log_warn("IPv6 protocol not available");*/
@@ -1298,9 +1367,10 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
}
if(is_ssl)
verbose(VERB_ALGO, "setup TCP for SSL service");
- if(!port_insert(list, s, port_type, ub_sock)) {
+ if(!port_insert(list, s, port_type, is_pp2, ub_sock)) {
sock_close(s);
- freeaddrinfo(ub_sock->addr);
+ if(ub_sock->addr)
+ freeaddrinfo(ub_sock->addr);
free(ub_sock);
return 0;
}
@@ -1308,7 +1378,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
return 1;
}
-/**
+/**
* Add items to commpoint list in front.
* @param c: commpoint to add.
* @param front: listen struct.
@@ -1359,7 +1429,7 @@ void listen_desetup_locks(void)
}
}
-struct listen_dnsport*
+struct listen_dnsport*
listen_create(struct comm_base* base, struct listen_port* ports,
size_t bufsize, int tcp_accept_count, int tcp_idle_timeout,
int harden_large_queries, uint32_t http_max_streams,
@@ -1387,14 +1457,16 @@ listen_create(struct comm_base* base, struct listen_port* ports,
if(ports->ftype == listen_type_udp ||
ports->ftype == listen_type_udp_dnscrypt) {
cp = comm_point_create_udp(base, ports->fd,
- front->udp_buff, cb, cb_arg, ports->socket);
+ front->udp_buff, ports->pp2_enabled, cb,
+ cb_arg, ports->socket);
} else if(ports->ftype == listen_type_tcp ||
ports->ftype == listen_type_tcp_dnscrypt) {
cp = comm_point_create_tcp(base, ports->fd,
tcp_accept_count, tcp_idle_timeout,
harden_large_queries, 0, NULL,
tcp_conn_limit, bufsize, front->udp_buff,
- ports->ftype, cb, cb_arg, ports->socket);
+ ports->ftype, ports->pp2_enabled, cb, cb_arg,
+ ports->socket);
} else if(ports->ftype == listen_type_ssl ||
ports->ftype == listen_type_http) {
cp = comm_point_create_tcp(base, ports->fd,
@@ -1402,7 +1474,8 @@ listen_create(struct comm_base* base, struct listen_port* ports,
harden_large_queries,
http_max_streams, http_endpoint,
tcp_conn_limit, bufsize, front->udp_buff,
- ports->ftype, cb, cb_arg, ports->socket);
+ ports->ftype, ports->pp2_enabled, cb, cb_arg,
+ ports->socket);
if(ports->ftype == listen_type_http) {
if(!sslctx && !http_notls) {
log_warn("HTTPS port configured, but "
@@ -1427,8 +1500,13 @@ listen_create(struct comm_base* base, struct listen_port* ports,
}
} else if(ports->ftype == listen_type_udpancil ||
ports->ftype == listen_type_udpancil_dnscrypt) {
+#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG)
cp = comm_point_create_udp_ancil(base, ports->fd,
- front->udp_buff, cb, cb_arg, ports->socket);
+ front->udp_buff, ports->pp2_enabled, cb,
+ cb_arg, ports->socket);
+#else
+ log_warn("This system does not support UDP ancilliary data.");
+#endif
}
if(!cp) {
log_err("can't create commpoint");
@@ -1491,10 +1569,10 @@ listen_list_delete(struct listen_list* list)
}
}
-void
+void
listen_delete(struct listen_dnsport* front)
{
- if(!front)
+ if(!front)
return;
listen_list_delete(front->cps);
#ifdef USE_DNSCRYPT
@@ -1700,7 +1778,7 @@ int resolve_interface_names(char** ifs, int num_ifs,
#endif /* HAVE_GETIFADDRS */
}
-struct listen_port*
+struct listen_port*
listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
int* reuseport)
{
@@ -1763,10 +1841,12 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
- cfg->https_port, reuseport, cfg->ip_transparent,
+ cfg->https_port,
+ cfg->proxy_protocol_port,
+ reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
- cfg->dnscrypt_port, cfg->ip_dscp)) {
+ cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
listening_ports_free(list);
return NULL;
}
@@ -1778,10 +1858,12 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
- cfg->https_port, reuseport, cfg->ip_transparent,
+ cfg->https_port,
+ cfg->proxy_protocol_port,
+ reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
- cfg->dnscrypt_port, cfg->ip_dscp)) {
+ cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
listening_ports_free(list);
return NULL;
}
@@ -1791,30 +1873,32 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
}
if(do_ip6) {
hints.ai_family = AF_INET6;
- if(!ports_create_if(do_auto?"::0":"::1",
- do_auto, cfg->do_udp, do_tcp,
+ if(!ports_create_if(do_auto?"::0":"::1",
+ do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
- cfg->https_port, reuseport, cfg->ip_transparent,
+ cfg->https_port, cfg->proxy_protocol_port,
+ reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
- cfg->dnscrypt_port, cfg->ip_dscp)) {
+ cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
listening_ports_free(list);
return NULL;
}
}
if(do_ip4) {
hints.ai_family = AF_INET;
- if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1",
- do_auto, cfg->do_udp, do_tcp,
+ if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1",
+ do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
- cfg->https_port, reuseport, cfg->ip_transparent,
+ cfg->https_port, cfg->proxy_protocol_port,
+ reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
- cfg->dnscrypt_port, cfg->ip_dscp)) {
+ cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
listening_ports_free(list);
return NULL;
}
@@ -1825,13 +1909,14 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
continue;
hints.ai_family = AF_INET6;
if(!ports_create_if(ifs[i], 0, cfg->do_udp,
- do_tcp, &hints, portbuf, &list,
+ do_tcp, &hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
- cfg->https_port, reuseport, cfg->ip_transparent,
+ cfg->https_port, cfg->proxy_protocol_port,
+ reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
- cfg->dnscrypt_port, cfg->ip_dscp)) {
+ cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
listening_ports_free(list);
return NULL;
}
@@ -1840,13 +1925,14 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
continue;
hints.ai_family = AF_INET;
if(!ports_create_if(ifs[i], 0, cfg->do_udp,
- do_tcp, &hints, portbuf, &list,
+ do_tcp, &hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
- cfg->https_port, reuseport, cfg->ip_transparent,
+ cfg->https_port, cfg->proxy_protocol_port,
+ reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
- cfg->dnscrypt_port, cfg->ip_dscp)) {
+ cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
listening_ports_free(list);
return NULL;
}
@@ -1866,7 +1952,8 @@ void listening_ports_free(struct listen_port* list)
}
/* rc_ports don't have ub_socket */
if(list->socket) {
- freeaddrinfo(list->socket->addr);
+ if(list->socket->addr)
+ freeaddrinfo(list->socket->addr);
free(list->socket);
}
free(list);
@@ -1877,8 +1964,8 @@ void listening_ports_free(struct listen_port* list)
size_t listen_get_mem(struct listen_dnsport* listen)
{
struct listen_list* p;
- size_t s = sizeof(*listen) + sizeof(*listen->base) +
- sizeof(*listen->udp_buff) +
+ size_t s = sizeof(*listen) + sizeof(*listen->base) +
+ sizeof(*listen->udp_buff) +
sldns_buffer_capacity(listen->udp_buff);
#ifdef USE_DNSCRYPT
s += sizeof(*listen->dnscrypt_udp_buff);
@@ -1959,7 +2046,7 @@ void tcp_req_info_clear(struct tcp_req_info* req)
}
req->open_req_list = NULL;
req->num_open_req = 0;
-
+
/* free pending writable result packets */
item = req->done_req_list;
while(item) {
@@ -2018,7 +2105,7 @@ tcp_req_info_setup_listen(struct tcp_req_info* req)
wr = 1;
if(!req->read_is_closed)
rd = 1;
-
+
if(wr) {
req->cp->tcp_is_reading = 0;
comm_point_stop_listening(req->cp);
@@ -2154,7 +2241,7 @@ tcp_req_info_handle_readdone(struct tcp_req_info* req)
}
req->in_worker_handle = 0;
/* it should be waiting in the mesh for recursion.
- * If mesh failed to add a new entry and called commpoint_drop_reply.
+ * If mesh failed to add a new entry and called commpoint_drop_reply.
* Then the mesh state has been cleared. */
if(req->is_drop) {
/* the reply has been dropped, stream has been closed. */
@@ -2214,7 +2301,7 @@ tcp_req_info_add_result(struct tcp_req_info* req, uint8_t* buf, size_t len)
last = req->done_req_list;
while(last && last->next)
last = last->next;
-
+
/* create new element */
item = (struct tcp_req_done_item*)malloc(sizeof(*item));
if(!item) {
@@ -2573,7 +2660,7 @@ static int http2_query_read_done(struct http2_session* h2_session,
"buffer already assigned to stream");
return -1;
}
-
+
/* the c->buffer might be used by mesh_send_reply and no be cleard
* need to be cleared before use */
sldns_buffer_clear(h2_session->c->buffer);