diff options
Diffstat (limited to 'contrib/unbound/services/listen_dnsport.c')
-rw-r--r-- | contrib/unbound/services/listen_dnsport.c | 293 |
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); |