2 * services/listen_dnsport.c - listen on port 53 for incoming DNS queries.
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
6 * This software is open source.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
19 * Neither the name of the NLNET LABS nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 * This file has functions to get queries from clients.
42 #ifdef HAVE_SYS_TYPES_H
43 # include <sys/types.h>
46 #ifdef USE_TCP_FASTOPEN
47 #include <netinet/tcp.h>
49 #include "services/listen_dnsport.h"
50 #include "services/outside_network.h"
51 #include "util/netevent.h"
53 #include "util/config_file.h"
54 #include "util/net_help.h"
55 #include "sldns/sbuffer.h"
66 /** number of queued TCP connections for listen() */
67 #define TCP_BACKLOG 256
70 * Debug print of the getaddrinfo returned address.
71 * @param addr: the address returned.
74 verbose_print_addr(struct addrinfo *addr)
76 if(verbosity >= VERB_ALGO) {
78 void* sinaddr = &((struct sockaddr_in*)addr->ai_addr)->sin_addr;
80 if(addr->ai_family == AF_INET6)
81 sinaddr = &((struct sockaddr_in6*)addr->ai_addr)->
84 if(inet_ntop(addr->ai_family, sinaddr, buf,
85 (socklen_t)sizeof(buf)) == 0) {
86 (void)strlcpy(buf, "(null)", sizeof(buf));
88 buf[sizeof(buf)-1] = 0;
89 verbose(VERB_ALGO, "creating %s%s socket %s %d",
90 addr->ai_socktype==SOCK_DGRAM?"udp":
91 addr->ai_socktype==SOCK_STREAM?"tcp":"otherproto",
92 addr->ai_family==AF_INET?"4":
93 addr->ai_family==AF_INET6?"6":
95 ntohs(((struct sockaddr_in*)addr->ai_addr)->sin_port));
100 create_udp_sock(int family, int socktype, struct sockaddr* addr,
101 socklen_t addrlen, int v6only, int* inuse, int* noproto,
102 int rcv, int snd, int listen, int* reuseport, int transparent,
106 #if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND)
110 int mtu = IPV6_MIN_MTU;
112 #if !defined(SO_RCVBUFFORCE) && !defined(SO_RCVBUF)
115 #if !defined(SO_SNDBUFFORCE) && !defined(SO_SNDBUF)
121 #if !defined(IP_TRANSPARENT) && !defined(IP_BINDANY)
124 #if !defined(IP_FREEBIND)
127 if((s = socket(family, socktype, 0)) == -1) {
130 if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
134 log_err("can't create socket: %s", strerror(errno));
136 if(WSAGetLastError() == WSAEAFNOSUPPORT ||
137 WSAGetLastError() == WSAEPROTONOSUPPORT) {
141 log_err("can't create socket: %s",
142 wsa_strerror(WSAGetLastError()));
149 if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
150 (socklen_t)sizeof(on)) < 0) {
152 log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
154 if(errno != ENOSYS) {
161 log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
162 wsa_strerror(WSAGetLastError()));
169 #endif /* SO_REUSEADDR */
171 /* try to set SO_REUSEPORT so that incoming
172 * queries are distributed evenly among the receiving threads.
173 * Each thread must have its own socket bound to the same port,
174 * with SO_REUSEPORT set on each socket.
176 if (reuseport && *reuseport &&
177 setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on,
178 (socklen_t)sizeof(on)) < 0) {
180 if(errno != ENOPROTOOPT || verbosity >= 3)
181 log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s",
184 /* this option is not essential, we can continue */
189 #endif /* defined(SO_REUSEPORT) */
190 #ifdef IP_TRANSPARENT
192 setsockopt(s, IPPROTO_IP, IP_TRANSPARENT, (void*)&on,
193 (socklen_t)sizeof(on)) < 0) {
194 log_warn("setsockopt(.. IP_TRANSPARENT ..) failed: %s",
197 #elif defined(IP_BINDANY)
199 setsockopt(s, (family==AF_INET6? IPPROTO_IPV6:IPPROTO_IP),
200 (family == AF_INET6? IPV6_BINDANY:IP_BINDANY),
201 (void*)&on, (socklen_t)sizeof(on)) < 0) {
202 log_warn("setsockopt(.. IP%s_BINDANY ..) failed: %s",
203 (family==AF_INET6?"V6":""), strerror(errno));
205 #endif /* IP_TRANSPARENT || IP_BINDANY */
209 setsockopt(s, IPPROTO_IP, IP_FREEBIND, (void*)&on,
210 (socklen_t)sizeof(on)) < 0) {
211 log_warn("setsockopt(.. IP_FREEBIND ..) failed: %s",
214 #endif /* IP_FREEBIND */
218 socklen_t slen = (socklen_t)sizeof(got);
219 # ifdef SO_RCVBUFFORCE
220 /* Linux specific: try to use root permission to override
221 * system limits on rcvbuf. The limit is stored in
222 * /proc/sys/net/core/rmem_max or sysctl net.core.rmem_max */
223 if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv,
224 (socklen_t)sizeof(rcv)) < 0) {
227 log_err("setsockopt(..., SO_RCVBUFFORCE, "
228 "...) failed: %s", strerror(errno));
231 log_err("setsockopt(..., SO_RCVBUFFORCE, "
233 wsa_strerror(WSAGetLastError()));
240 # endif /* SO_RCVBUFFORCE */
241 if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv,
242 (socklen_t)sizeof(rcv)) < 0) {
244 log_err("setsockopt(..., SO_RCVBUF, "
245 "...) failed: %s", strerror(errno));
248 log_err("setsockopt(..., SO_RCVBUF, "
250 wsa_strerror(WSAGetLastError()));
257 /* check if we got the right thing or if system
258 * reduced to some system max. Warn if so */
259 if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&got,
260 &slen) >= 0 && got < rcv/2) {
261 log_warn("so-rcvbuf %u was not granted. "
262 "Got %u. To fix: start with "
263 "root permissions(linux) or sysctl "
264 "bigger net.core.rmem_max(linux) or "
265 "kern.ipc.maxsockbuf(bsd) values.",
266 (unsigned)rcv, (unsigned)got);
268 # ifdef SO_RCVBUFFORCE
271 #endif /* SO_RCVBUF */
273 /* first do RCVBUF as the receive buffer is more important */
277 socklen_t slen = (socklen_t)sizeof(got);
278 # ifdef SO_SNDBUFFORCE
279 /* Linux specific: try to use root permission to override
280 * system limits on sndbuf. The limit is stored in
281 * /proc/sys/net/core/wmem_max or sysctl net.core.wmem_max */
282 if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd,
283 (socklen_t)sizeof(snd)) < 0) {
286 log_err("setsockopt(..., SO_SNDBUFFORCE, "
287 "...) failed: %s", strerror(errno));
290 log_err("setsockopt(..., SO_SNDBUFFORCE, "
292 wsa_strerror(WSAGetLastError()));
299 # endif /* SO_SNDBUFFORCE */
300 if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd,
301 (socklen_t)sizeof(snd)) < 0) {
303 log_err("setsockopt(..., SO_SNDBUF, "
304 "...) failed: %s", strerror(errno));
307 log_err("setsockopt(..., SO_SNDBUF, "
309 wsa_strerror(WSAGetLastError()));
316 /* check if we got the right thing or if system
317 * reduced to some system max. Warn if so */
318 if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got,
319 &slen) >= 0 && got < snd/2) {
320 log_warn("so-sndbuf %u was not granted. "
321 "Got %u. To fix: start with "
322 "root permissions(linux) or sysctl "
323 "bigger net.core.wmem_max(linux) or "
324 "kern.ipc.maxsockbuf(bsd) values.",
325 (unsigned)snd, (unsigned)got);
327 # ifdef SO_SNDBUFFORCE
330 #endif /* SO_SNDBUF */
332 if(family == AF_INET6) {
333 # if defined(IPV6_V6ONLY)
335 int val=(v6only==2)?0:1;
336 if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
337 (void*)&val, (socklen_t)sizeof(val)) < 0) {
339 log_err("setsockopt(..., IPV6_V6ONLY"
340 ", ...) failed: %s", strerror(errno));
343 log_err("setsockopt(..., IPV6_V6ONLY"
345 wsa_strerror(WSAGetLastError()));
354 # if defined(IPV6_USE_MIN_MTU)
356 * There is no fragmentation of IPv6 datagrams
357 * during forwarding in the network. Therefore
358 * we do not send UDP datagrams larger than
359 * the minimum IPv6 MTU of 1280 octets. The
360 * EDNS0 message length can be larger if the
361 * network stack supports IPV6_USE_MIN_MTU.
363 if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
364 (void*)&on, (socklen_t)sizeof(on)) < 0) {
366 log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
367 "...) failed: %s", strerror(errno));
370 log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
372 wsa_strerror(WSAGetLastError()));
379 # elif defined(IPV6_MTU)
381 * On Linux, to send no larger than 1280, the PMTUD is
382 * disabled by default for datagrams anyway, so we set
385 if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU,
386 (void*)&mtu, (socklen_t)sizeof(mtu)) < 0) {
388 log_err("setsockopt(..., IPV6_MTU, ...) failed: %s",
392 log_err("setsockopt(..., IPV6_MTU, ...) failed: %s",
393 wsa_strerror(WSAGetLastError()));
400 # endif /* IPv6 MTU */
401 } else if(family == AF_INET) {
402 # if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
403 /* linux 3.15 has IP_PMTUDISC_OMIT, Hannes Frederic Sowa made it so that
404 * PMTU information is not accepted, but fragmentation is allowed
405 * if and only if the packet size exceeds the outgoing interface MTU
406 * (and also uses the interface mtu to determine the size of the packets).
407 * So there won't be any EMSGSIZE error. Against DNS fragmentation attacks.
408 * FreeBSD already has same semantics without setting the option. */
411 # if defined(IP_PMTUDISC_OMIT)
412 action = IP_PMTUDISC_OMIT;
413 if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER,
414 &action, (socklen_t)sizeof(action)) < 0) {
416 if (errno != EINVAL) {
417 log_err("setsockopt(..., IP_MTU_DISCOVER, IP_PMTUDISC_OMIT...) failed: %s",
436 action = IP_PMTUDISC_DONT;
437 if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER,
438 &action, (socklen_t)sizeof(action)) < 0) {
439 log_err("setsockopt(..., IP_MTU_DISCOVER, IP_PMTUDISC_DONT...) failed: %s",
451 # elif defined(IP_DONTFRAG)
453 if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG,
454 &off, (socklen_t)sizeof(off)) < 0) {
455 log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
466 # endif /* IPv4 MTU */
468 if(bind(s, (struct sockaddr*)addr, addrlen) != 0) {
473 *inuse = (errno == EADDRINUSE);
474 /* detect freebsd jail with no ipv6 permission */
475 if(family==AF_INET6 && errno==EINVAL)
477 else if(errno != EADDRINUSE) {
478 log_err_addr("can't bind socket", strerror(errno),
479 (struct sockaddr_storage*)addr, addrlen);
481 #endif /* EADDRINUSE */
483 #else /* USE_WINSOCK */
484 if(WSAGetLastError() != WSAEADDRINUSE &&
485 WSAGetLastError() != WSAEADDRNOTAVAIL) {
486 log_err_addr("can't bind socket",
487 wsa_strerror(WSAGetLastError()),
488 (struct sockaddr_storage*)addr, addrlen);
494 if(!fd_set_nonblock(s)) {
508 create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
509 int* reuseport, int transparent, int mss, int freebind)
512 #if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND)
515 #ifdef USE_TCP_FASTOPEN
518 #if !defined(IP_TRANSPARENT) && !defined(IP_BINDANY)
521 #if !defined(IP_FREEBIND)
524 verbose_print_addr(addr);
526 if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
528 if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
532 log_err("can't create socket: %s", strerror(errno));
534 if(WSAGetLastError() == WSAEAFNOSUPPORT ||
535 WSAGetLastError() == WSAEPROTONOSUPPORT) {
539 log_err("can't create socket: %s",
540 wsa_strerror(WSAGetLastError()));
545 #if defined(IPPROTO_TCP) && defined(TCP_MAXSEG)
546 if(setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, (void*)&mss,
547 (socklen_t)sizeof(mss)) < 0) {
549 log_err(" setsockopt(.. TCP_MAXSEG ..) failed: %s",
552 log_err(" setsockopt(.. TCP_MAXSEG ..) failed: %s",
553 wsa_strerror(WSAGetLastError()));
557 " tcp socket mss set to %d", mss);
560 log_warn(" setsockopt(TCP_MAXSEG) unsupported");
561 #endif /* defined(IPPROTO_TCP) && defined(TCP_MAXSEG) */
564 if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
565 (socklen_t)sizeof(on)) < 0) {
567 log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
571 log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
572 wsa_strerror(WSAGetLastError()));
577 #endif /* SO_REUSEADDR */
579 if (freebind && setsockopt(s, IPPROTO_IP, IP_FREEBIND, (void*)&on,
580 (socklen_t)sizeof(on)) < 0) {
581 log_warn("setsockopt(.. IP_FREEBIND ..) failed: %s",
584 #endif /* IP_FREEBIND */
586 /* try to set SO_REUSEPORT so that incoming
587 * connections are distributed evenly among the receiving threads.
588 * Each thread must have its own socket bound to the same port,
589 * with SO_REUSEPORT set on each socket.
591 if (reuseport && *reuseport &&
592 setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on,
593 (socklen_t)sizeof(on)) < 0) {
595 if(errno != ENOPROTOOPT || verbosity >= 3)
596 log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s",
599 /* this option is not essential, we can continue */
604 #endif /* defined(SO_REUSEPORT) */
605 #if defined(IPV6_V6ONLY)
606 if(addr->ai_family == AF_INET6 && v6only) {
607 if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
608 (void*)&on, (socklen_t)sizeof(on)) < 0) {
610 log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
614 log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
615 wsa_strerror(WSAGetLastError()));
623 #endif /* IPV6_V6ONLY */
624 #ifdef IP_TRANSPARENT
626 setsockopt(s, IPPROTO_IP, IP_TRANSPARENT, (void*)&on,
627 (socklen_t)sizeof(on)) < 0) {
628 log_warn("setsockopt(.. IP_TRANSPARENT ..) failed: %s",
631 #elif defined(IP_BINDANY)
633 setsockopt(s, (addr->ai_family==AF_INET6? IPPROTO_IPV6:IPPROTO_IP),
634 (addr->ai_family == AF_INET6? IPV6_BINDANY:IP_BINDANY),
635 (void*)&on, (socklen_t)sizeof(on)) < 0) {
636 log_warn("setsockopt(.. IP%s_BINDANY ..) failed: %s",
637 (addr->ai_family==AF_INET6?"V6":""), strerror(errno));
639 #endif /* IP_TRANSPARENT || IP_BINDANY */
640 if(bind(s, addr->ai_addr, addr->ai_addrlen) != 0) {
642 /* detect freebsd jail with no ipv6 permission */
643 if(addr->ai_family==AF_INET6 && errno==EINVAL)
646 log_err_addr("can't bind socket", strerror(errno),
647 (struct sockaddr_storage*)addr->ai_addr,
652 log_err_addr("can't bind socket",
653 wsa_strerror(WSAGetLastError()),
654 (struct sockaddr_storage*)addr->ai_addr,
660 if(!fd_set_nonblock(s)) {
668 if(listen(s, TCP_BACKLOG) == -1) {
670 log_err("can't listen: %s", strerror(errno));
673 log_err("can't listen: %s", wsa_strerror(WSAGetLastError()));
678 #ifdef USE_TCP_FASTOPEN
679 /* qlen specifies how many outstanding TFO requests to allow. Limit is a defense
680 against IP spoofing attacks as suggested in RFC7413 */
682 /* OS X implementation only supports qlen of 1 via this call. Actual
683 value is configured by the net.inet.tcp.fastopen_backlog kernel parm. */
686 /* 5 is recommended on linux */
689 if ((setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &qlen,
690 sizeof(qlen))) == -1 ) {
691 log_err("Setting TCP Fast Open as server failed: %s", strerror(errno));
698 create_local_accept_sock(const char *path, int* noproto)
702 struct sockaddr_un usock;
704 verbose(VERB_ALGO, "creating unix socket %s", path);
705 #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
706 /* this member exists on BSDs, not Linux */
707 usock.sun_len = (unsigned)sizeof(usock);
709 usock.sun_family = AF_LOCAL;
710 /* length is 92-108, 104 on FreeBSD */
711 (void)strlcpy(usock.sun_path, path, sizeof(usock.sun_path));
713 if ((s = socket(AF_LOCAL, SOCK_STREAM, 0)) == -1) {
714 log_err("Cannot create local socket %s (%s)",
715 path, strerror(errno));
719 if (unlink(path) && errno != ENOENT) {
720 /* The socket already exists and cannot be removed */
721 log_err("Cannot remove old local socket %s (%s)",
722 path, strerror(errno));
726 if (bind(s, (struct sockaddr *)&usock,
727 (socklen_t)sizeof(struct sockaddr_un)) == -1) {
728 log_err("Cannot bind local socket %s (%s)",
729 path, strerror(errno));
733 if (!fd_set_nonblock(s)) {
734 log_err("Cannot set non-blocking mode");
738 if (listen(s, TCP_BACKLOG) == -1) {
739 log_err("can't listen: %s", strerror(errno));
743 (void)noproto; /*unused*/
747 log_err("Local sockets are not supported");
755 * Create socket from getaddrinfo results
758 make_sock(int stype, const char* ifname, const char* port,
759 struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
760 int* reuseport, int transparent, int tcp_mss, int freebind)
762 struct addrinfo *res = NULL;
763 int r, s, inuse, noproto;
764 hints->ai_socktype = stype;
766 if((r=getaddrinfo(ifname, port, hints, &res)) != 0 || !res) {
768 if(r == EAI_NONAME && hints->ai_family == AF_INET6){
769 *noip6 = 1; /* 'Host not found' for IP6 on winXP */
773 log_err("node %s:%s getaddrinfo: %s %s",
774 ifname?ifname:"default", port, gai_strerror(r),
776 r==EAI_SYSTEM?(char*)strerror(errno):""
783 if(stype == SOCK_DGRAM) {
784 verbose_print_addr(res);
785 s = create_udp_sock(res->ai_family, res->ai_socktype,
786 (struct sockaddr*)res->ai_addr, res->ai_addrlen,
787 v6only, &inuse, &noproto, (int)rcv, (int)snd, 1,
788 reuseport, transparent, freebind);
789 if(s == -1 && inuse) {
790 log_err("bind: address already in use");
791 } else if(s == -1 && noproto && hints->ai_family == AF_INET6){
795 s = create_tcp_accept_sock(res, v6only, &noproto, reuseport,
796 transparent, tcp_mss, freebind);
797 if(s == -1 && noproto && hints->ai_family == AF_INET6){
805 /** make socket and first see if ifname contains port override info */
807 make_sock_port(int stype, const char* ifname, const char* port,
808 struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
809 int* reuseport, int transparent, int tcp_mss, int freebind)
811 char* s = strchr(ifname, '@');
813 /* override port with ifspec@port */
816 if((size_t)(s-ifname) >= sizeof(newif)) {
817 log_err("ifname too long: %s", ifname);
821 if(strlen(s+1) >= sizeof(p)) {
822 log_err("portnumber too long: %s", ifname);
826 (void)strlcpy(newif, ifname, sizeof(newif));
828 (void)strlcpy(p, s+1, sizeof(p));
830 return make_sock(stype, newif, p, hints, v6only, noip6,
831 rcv, snd, reuseport, transparent, tcp_mss, freebind);
833 return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd,
834 reuseport, transparent, tcp_mss, freebind);
838 * Add port to open ports list.
839 * @param list: list head. changed.
841 * @param ftype: if fd is UDP.
842 * @return false on failure. list in unchanged then.
845 port_insert(struct listen_port** list, int s, enum listen_type ftype)
847 struct listen_port* item = (struct listen_port*)malloc(
848 sizeof(struct listen_port));
858 /** set fd to receive source address packet info */
860 set_recvpktinfo(int s, int family)
862 #if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)) || defined(IP_PKTINFO)
867 if(family == AF_INET6) {
868 # ifdef IPV6_RECVPKTINFO
869 if(setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
870 (void*)&on, (socklen_t)sizeof(on)) < 0) {
871 log_err("setsockopt(..., IPV6_RECVPKTINFO, ...) failed: %s",
875 # elif defined(IPV6_PKTINFO)
876 if(setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO,
877 (void*)&on, (socklen_t)sizeof(on)) < 0) {
878 log_err("setsockopt(..., IPV6_PKTINFO, ...) failed: %s",
883 log_err("no IPV6_RECVPKTINFO and no IPV6_PKTINFO option, please "
884 "disable interface-automatic in config");
886 # endif /* defined IPV6_RECVPKTINFO */
888 } else if(family == AF_INET) {
890 if(setsockopt(s, IPPROTO_IP, IP_PKTINFO,
891 (void*)&on, (socklen_t)sizeof(on)) < 0) {
892 log_err("setsockopt(..., IP_PKTINFO, ...) failed: %s",
896 # elif defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)
897 if(setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
898 (void*)&on, (socklen_t)sizeof(on)) < 0) {
899 log_err("setsockopt(..., IP_RECVDSTADDR, ...) failed: %s",
904 log_err("no IP_SENDSRCADDR or IP_PKTINFO option, please disable "
905 "interface-automatic in config");
907 # endif /* IP_PKTINFO */
914 * Helper for ports_open. Creates one interface (or NULL for default).
915 * @param ifname: The interface ip address.
916 * @param do_auto: use automatic interface detection.
917 * If enabled, then ifname must be the wildcard name.
918 * @param do_udp: if udp should be used.
919 * @param do_tcp: if udp should be used.
920 * @param hints: for getaddrinfo. family and flags have to be set by caller.
921 * @param port: Port number to use (as string).
922 * @param list: list of open ports, appended to, changed to point to list head.
923 * @param rcv: receive buffer size for UDP
924 * @param snd: send buffer size for UDP
925 * @param ssl_port: ssl service port number
926 * @param reuseport: try to set SO_REUSEPORT if nonNULL and true.
927 * set to false on exit if reuseport failed due to no kernel support.
928 * @param transparent: set IP_TRANSPARENT socket option.
929 * @param tcp_mss: maximum segment size of tcp socket. default if zero.
930 * @param freebind: set IP_FREEBIND socket option.
931 * @return: returns false on error.
934 ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
935 struct addrinfo *hints, const char* port, struct listen_port** list,
936 size_t rcv, size_t snd, int ssl_port, int* reuseport, int transparent,
937 int tcp_mss, int freebind)
940 if(!do_udp && !do_tcp)
943 if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
944 &noip6, rcv, snd, reuseport, transparent,
945 tcp_mss, freebind)) == -1) {
947 log_warn("IPv6 protocol not available");
952 /* getting source addr packet info is highly non-portable */
953 if(!set_recvpktinfo(s, hints->ai_family)) {
961 if(!port_insert(list, s, listen_type_udpancil)) {
970 /* regular udp socket */
971 if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
972 &noip6, rcv, snd, reuseport, transparent,
973 tcp_mss, freebind)) == -1) {
975 log_warn("IPv6 protocol not available");
980 if(!port_insert(list, s, listen_type_udp)) {
990 int is_ssl = ((strchr(ifname, '@') &&
991 atoi(strchr(ifname, '@')+1) == ssl_port) ||
992 (!strchr(ifname, '@') && atoi(port) == ssl_port));
993 if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
994 &noip6, 0, 0, reuseport, transparent, tcp_mss,
997 /*log_warn("IPv6 protocol not available");*/
1003 verbose(VERB_ALGO, "setup TCP for SSL service");
1004 if(!port_insert(list, s, is_ssl?listen_type_ssl:
1018 * Add items to commpoint list in front.
1019 * @param c: commpoint to add.
1020 * @param front: listen struct.
1021 * @return: false on failure.
1024 listen_cp_insert(struct comm_point* c, struct listen_dnsport* front)
1026 struct listen_list* item = (struct listen_list*)malloc(
1027 sizeof(struct listen_list));
1031 item->next = front->cps;
1036 struct listen_dnsport*
1037 listen_create(struct comm_base* base, struct listen_port* ports,
1038 size_t bufsize, int tcp_accept_count, void* sslctx,
1039 struct dt_env* dtenv, comm_point_callback_t* cb, void *cb_arg)
1041 struct listen_dnsport* front = (struct listen_dnsport*)
1042 malloc(sizeof(struct listen_dnsport));
1046 front->udp_buff = sldns_buffer_new(bufsize);
1047 if(!front->udp_buff) {
1052 /* create comm points as needed */
1054 struct comm_point* cp = NULL;
1055 if(ports->ftype == listen_type_udp)
1056 cp = comm_point_create_udp(base, ports->fd,
1057 front->udp_buff, cb, cb_arg);
1058 else if(ports->ftype == listen_type_tcp)
1059 cp = comm_point_create_tcp(base, ports->fd,
1060 tcp_accept_count, bufsize, cb, cb_arg);
1061 else if(ports->ftype == listen_type_ssl) {
1062 cp = comm_point_create_tcp(base, ports->fd,
1063 tcp_accept_count, bufsize, cb, cb_arg);
1065 } else if(ports->ftype == listen_type_udpancil)
1066 cp = comm_point_create_udp_ancil(base, ports->fd,
1067 front->udp_buff, cb, cb_arg);
1069 log_err("can't create commpoint");
1070 listen_delete(front);
1074 cp->do_not_close = 1;
1075 if(!listen_cp_insert(cp, front)) {
1076 log_err("malloc failed");
1077 comm_point_delete(cp);
1078 listen_delete(front);
1081 ports = ports->next;
1084 log_err("Could not open sockets to accept queries.");
1085 listen_delete(front);
1093 listen_list_delete(struct listen_list* list)
1095 struct listen_list *p = list, *pn;
1098 comm_point_delete(p->com);
1105 listen_delete(struct listen_dnsport* front)
1109 listen_list_delete(front->cps);
1110 sldns_buffer_free(front->udp_buff);
1115 listening_ports_open(struct config_file* cfg, int* reuseport)
1117 struct listen_port* list = NULL;
1118 struct addrinfo hints;
1119 int i, do_ip4, do_ip6;
1120 int do_tcp, do_auto;
1122 snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
1123 do_ip4 = cfg->do_ip4;
1124 do_ip6 = cfg->do_ip6;
1125 do_tcp = cfg->do_tcp;
1126 do_auto = cfg->if_automatic && cfg->do_udp;
1127 if(cfg->incoming_num_tcp == 0)
1131 memset(&hints, 0, sizeof(hints));
1132 hints.ai_flags = AI_PASSIVE;
1133 /* no name lookups on our listening ports */
1134 if(cfg->num_ifs > 0)
1135 hints.ai_flags |= AI_NUMERICHOST;
1136 hints.ai_family = AF_UNSPEC;
1140 if(!do_ip4 && !do_ip6) {
1143 /* create ip4 and ip6 ports so that return addresses are nice. */
1144 if(do_auto || cfg->num_ifs == 0) {
1146 hints.ai_family = AF_INET6;
1147 if(!ports_create_if(do_auto?"::0":"::1",
1148 do_auto, cfg->do_udp, do_tcp,
1149 &hints, portbuf, &list,
1150 cfg->so_rcvbuf, cfg->so_sndbuf,
1151 cfg->ssl_port, reuseport,
1152 cfg->ip_transparent,
1153 cfg->tcp_mss, cfg->ip_freebind)) {
1154 listening_ports_free(list);
1159 hints.ai_family = AF_INET;
1160 if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1",
1161 do_auto, cfg->do_udp, do_tcp,
1162 &hints, portbuf, &list,
1163 cfg->so_rcvbuf, cfg->so_sndbuf,
1164 cfg->ssl_port, reuseport,
1165 cfg->ip_transparent,
1166 cfg->tcp_mss, cfg->ip_freebind)) {
1167 listening_ports_free(list);
1171 } else for(i = 0; i<cfg->num_ifs; i++) {
1172 if(str_is_ip6(cfg->ifs[i])) {
1175 hints.ai_family = AF_INET6;
1176 if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
1177 do_tcp, &hints, portbuf, &list,
1178 cfg->so_rcvbuf, cfg->so_sndbuf,
1179 cfg->ssl_port, reuseport,
1180 cfg->ip_transparent,
1181 cfg->tcp_mss, cfg->ip_freebind)) {
1182 listening_ports_free(list);
1188 hints.ai_family = AF_INET;
1189 if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
1190 do_tcp, &hints, portbuf, &list,
1191 cfg->so_rcvbuf, cfg->so_sndbuf,
1192 cfg->ssl_port, reuseport,
1193 cfg->ip_transparent,
1194 cfg->tcp_mss, cfg->ip_freebind)) {
1195 listening_ports_free(list);
1203 void listening_ports_free(struct listen_port* list)
1205 struct listen_port* nx;
1208 if(list->fd != -1) {
1212 closesocket(list->fd);
1220 size_t listen_get_mem(struct listen_dnsport* listen)
1222 size_t s = sizeof(*listen) + sizeof(*listen->base) +
1223 sizeof(*listen->udp_buff) +
1224 sldns_buffer_capacity(listen->udp_buff);
1225 struct listen_list* p;
1226 for(p = listen->cps; p; p = p->next) {
1228 s += comm_point_get_mem(p->com);
1233 void listen_stop_accept(struct listen_dnsport* listen)
1235 /* do not stop the ones that have no tcp_free list
1236 * (they have already stopped listening) */
1237 struct listen_list* p;
1238 for(p=listen->cps; p; p=p->next) {
1239 if(p->com->type == comm_tcp_accept &&
1240 p->com->tcp_free != NULL) {
1241 comm_point_stop_listening(p->com);
1246 void listen_start_accept(struct listen_dnsport* listen)
1248 /* do not start the ones that have no tcp_free list, it is no
1249 * use to listen to them because they have no free tcp handlers */
1250 struct listen_list* p;
1251 for(p=listen->cps; p; p=p->next) {
1252 if(p->com->type == comm_tcp_accept &&
1253 p->com->tcp_free != NULL) {
1254 comm_point_start_listening(p->com, -1, -1);