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 #include "services/listen_dnsport.h"
47 #include "services/outside_network.h"
48 #include "util/netevent.h"
50 #include "util/config_file.h"
51 #include "util/net_help.h"
52 #include "ldns/sbuffer.h"
59 /** number of queued TCP connections for listen() */
63 * Debug print of the getaddrinfo returned address.
64 * @param addr: the address returned.
67 verbose_print_addr(struct addrinfo *addr)
69 if(verbosity >= VERB_ALGO) {
71 void* sinaddr = &((struct sockaddr_in*)addr->ai_addr)->sin_addr;
73 if(addr->ai_family == AF_INET6)
74 sinaddr = &((struct sockaddr_in6*)addr->ai_addr)->
77 if(inet_ntop(addr->ai_family, sinaddr, buf,
78 (socklen_t)sizeof(buf)) == 0) {
79 (void)strlcpy(buf, "(null)", sizeof(buf));
81 buf[sizeof(buf)-1] = 0;
82 verbose(VERB_ALGO, "creating %s%s socket %s %d",
83 addr->ai_socktype==SOCK_DGRAM?"udp":
84 addr->ai_socktype==SOCK_STREAM?"tcp":"otherproto",
85 addr->ai_family==AF_INET?"4":
86 addr->ai_family==AF_INET6?"6":
88 ntohs(((struct sockaddr_in*)addr->ai_addr)->sin_port));
93 create_udp_sock(int family, int socktype, struct sockaddr* addr,
94 socklen_t addrlen, int v6only, int* inuse, int* noproto,
95 int rcv, int snd, int listen, int* reuseport)
98 #if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU)
102 int mtu = IPV6_MIN_MTU;
104 #if !defined(SO_RCVBUFFORCE) && !defined(SO_RCVBUF)
107 #if !defined(SO_SNDBUFFORCE) && !defined(SO_SNDBUF)
113 if((s = socket(family, socktype, 0)) == -1) {
116 if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
120 log_err("can't create socket: %s", strerror(errno));
122 if(WSAGetLastError() == WSAEAFNOSUPPORT ||
123 WSAGetLastError() == WSAEPROTONOSUPPORT) {
127 log_err("can't create socket: %s",
128 wsa_strerror(WSAGetLastError()));
135 if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
136 (socklen_t)sizeof(on)) < 0) {
138 log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
140 if(errno != ENOSYS) {
147 log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
148 wsa_strerror(WSAGetLastError()));
155 #endif /* SO_REUSEADDR */
156 #if defined(__linux__) && defined(SO_REUSEPORT)
157 /* Linux specific: try to set SO_REUSEPORT so that incoming
158 * queries are distributed evenly among the receiving threads.
159 * Each thread must have its own socket bound to the same port,
160 * with SO_REUSEPORT set on each socket.
162 if (reuseport && *reuseport &&
163 setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on,
164 (socklen_t)sizeof(on)) < 0) {
166 if(errno != ENOPROTOOPT || verbosity >= 3)
167 log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s",
170 /* this option is not essential, we can continue */
175 #endif /* defined(__linux__) && defined(SO_REUSEPORT) */
180 socklen_t slen = (socklen_t)sizeof(got);
181 # ifdef SO_RCVBUFFORCE
182 /* Linux specific: try to use root permission to override
183 * system limits on rcvbuf. The limit is stored in
184 * /proc/sys/net/core/rmem_max or sysctl net.core.rmem_max */
185 if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv,
186 (socklen_t)sizeof(rcv)) < 0) {
189 log_err("setsockopt(..., SO_RCVBUFFORCE, "
190 "...) failed: %s", strerror(errno));
193 log_err("setsockopt(..., SO_RCVBUFFORCE, "
195 wsa_strerror(WSAGetLastError()));
202 # endif /* SO_RCVBUFFORCE */
203 if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv,
204 (socklen_t)sizeof(rcv)) < 0) {
206 log_err("setsockopt(..., SO_RCVBUF, "
207 "...) failed: %s", strerror(errno));
210 log_err("setsockopt(..., SO_RCVBUF, "
212 wsa_strerror(WSAGetLastError()));
219 /* check if we got the right thing or if system
220 * reduced to some system max. Warn if so */
221 if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&got,
222 &slen) >= 0 && got < rcv/2) {
223 log_warn("so-rcvbuf %u was not granted. "
224 "Got %u. To fix: start with "
225 "root permissions(linux) or sysctl "
226 "bigger net.core.rmem_max(linux) or "
227 "kern.ipc.maxsockbuf(bsd) values.",
228 (unsigned)rcv, (unsigned)got);
230 # ifdef SO_RCVBUFFORCE
233 #endif /* SO_RCVBUF */
235 /* first do RCVBUF as the receive buffer is more important */
239 socklen_t slen = (socklen_t)sizeof(got);
240 # ifdef SO_SNDBUFFORCE
241 /* Linux specific: try to use root permission to override
242 * system limits on sndbuf. The limit is stored in
243 * /proc/sys/net/core/wmem_max or sysctl net.core.wmem_max */
244 if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd,
245 (socklen_t)sizeof(snd)) < 0) {
248 log_err("setsockopt(..., SO_SNDBUFFORCE, "
249 "...) failed: %s", strerror(errno));
252 log_err("setsockopt(..., SO_SNDBUFFORCE, "
254 wsa_strerror(WSAGetLastError()));
261 # endif /* SO_SNDBUFFORCE */
262 if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd,
263 (socklen_t)sizeof(snd)) < 0) {
265 log_err("setsockopt(..., SO_SNDBUF, "
266 "...) failed: %s", strerror(errno));
269 log_err("setsockopt(..., SO_SNDBUF, "
271 wsa_strerror(WSAGetLastError()));
278 /* check if we got the right thing or if system
279 * reduced to some system max. Warn if so */
280 if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got,
281 &slen) >= 0 && got < snd/2) {
282 log_warn("so-sndbuf %u was not granted. "
283 "Got %u. To fix: start with "
284 "root permissions(linux) or sysctl "
285 "bigger net.core.wmem_max(linux) or "
286 "kern.ipc.maxsockbuf(bsd) values.",
287 (unsigned)snd, (unsigned)got);
289 # ifdef SO_SNDBUFFORCE
292 #endif /* SO_SNDBUF */
294 if(family == AF_INET6) {
295 # if defined(IPV6_V6ONLY)
297 int val=(v6only==2)?0:1;
298 if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
299 (void*)&val, (socklen_t)sizeof(val)) < 0) {
301 log_err("setsockopt(..., IPV6_V6ONLY"
302 ", ...) failed: %s", strerror(errno));
305 log_err("setsockopt(..., IPV6_V6ONLY"
307 wsa_strerror(WSAGetLastError()));
316 # if defined(IPV6_USE_MIN_MTU)
318 * There is no fragmentation of IPv6 datagrams
319 * during forwarding in the network. Therefore
320 * we do not send UDP datagrams larger than
321 * the minimum IPv6 MTU of 1280 octets. The
322 * EDNS0 message length can be larger if the
323 * network stack supports IPV6_USE_MIN_MTU.
325 if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
326 (void*)&on, (socklen_t)sizeof(on)) < 0) {
328 log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
329 "...) failed: %s", strerror(errno));
332 log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
334 wsa_strerror(WSAGetLastError()));
341 # elif defined(IPV6_MTU)
343 * On Linux, to send no larger than 1280, the PMTUD is
344 * disabled by default for datagrams anyway, so we set
347 if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU,
348 (void*)&mtu, (socklen_t)sizeof(mtu)) < 0) {
350 log_err("setsockopt(..., IPV6_MTU, ...) failed: %s",
354 log_err("setsockopt(..., IPV6_MTU, ...) failed: %s",
355 wsa_strerror(WSAGetLastError()));
362 # endif /* IPv6 MTU */
363 } else if(family == AF_INET) {
364 # if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
365 int action = IP_PMTUDISC_DONT;
366 if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER,
367 &action, (socklen_t)sizeof(action)) < 0) {
368 log_err("setsockopt(..., IP_MTU_DISCOVER, "
369 "IP_PMTUDISC_DONT...) failed: %s",
380 # elif defined(IP_DONTFRAG)
382 if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG,
383 &off, (socklen_t)sizeof(off)) < 0) {
384 log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
395 # endif /* IPv4 MTU */
397 if(bind(s, (struct sockaddr*)addr, addrlen) != 0) {
402 *inuse = (errno == EADDRINUSE);
403 /* detect freebsd jail with no ipv6 permission */
404 if(family==AF_INET6 && errno==EINVAL)
406 else if(errno != EADDRINUSE) {
407 log_err("can't bind socket: %s", strerror(errno));
408 log_addr(0, "failed address",
409 (struct sockaddr_storage*)addr, addrlen);
411 #endif /* EADDRINUSE */
413 #else /* USE_WINSOCK */
414 if(WSAGetLastError() != WSAEADDRINUSE &&
415 WSAGetLastError() != WSAEADDRNOTAVAIL) {
416 log_err("can't bind socket: %s",
417 wsa_strerror(WSAGetLastError()));
418 log_addr(0, "failed address",
419 (struct sockaddr_storage*)addr, addrlen);
425 if(!fd_set_nonblock(s)) {
439 create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
443 #if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY)
445 #endif /* SO_REUSEADDR || IPV6_V6ONLY */
446 verbose_print_addr(addr);
448 if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
450 if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
454 log_err("can't create socket: %s", strerror(errno));
456 if(WSAGetLastError() == WSAEAFNOSUPPORT ||
457 WSAGetLastError() == WSAEPROTONOSUPPORT) {
461 log_err("can't create socket: %s",
462 wsa_strerror(WSAGetLastError()));
467 if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
468 (socklen_t)sizeof(on)) < 0) {
470 log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
474 log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
475 wsa_strerror(WSAGetLastError()));
480 #endif /* SO_REUSEADDR */
481 #if defined(__linux__) && defined(SO_REUSEPORT)
482 /* Linux specific: try to set SO_REUSEPORT so that incoming
483 * connections are distributed evenly among the receiving threads.
484 * Each thread must have its own socket bound to the same port,
485 * with SO_REUSEPORT set on each socket.
487 if (reuseport && *reuseport &&
488 setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on,
489 (socklen_t)sizeof(on)) < 0) {
491 if(errno != ENOPROTOOPT || verbosity >= 3)
492 log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s",
495 /* this option is not essential, we can continue */
500 #endif /* defined(__linux__) && defined(SO_REUSEPORT) */
501 #if defined(IPV6_V6ONLY)
502 if(addr->ai_family == AF_INET6 && v6only) {
503 if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
504 (void*)&on, (socklen_t)sizeof(on)) < 0) {
506 log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
510 log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
511 wsa_strerror(WSAGetLastError()));
519 #endif /* IPV6_V6ONLY */
520 if(bind(s, addr->ai_addr, addr->ai_addrlen) != 0) {
522 /* detect freebsd jail with no ipv6 permission */
523 if(addr->ai_family==AF_INET6 && errno==EINVAL)
526 log_err("can't bind socket: %s", strerror(errno));
527 log_addr(0, "failed address",
528 (struct sockaddr_storage*)addr->ai_addr,
533 log_err("can't bind socket: %s",
534 wsa_strerror(WSAGetLastError()));
535 log_addr(0, "failed address",
536 (struct sockaddr_storage*)addr->ai_addr,
542 if(!fd_set_nonblock(s)) {
550 if(listen(s, TCP_BACKLOG) == -1) {
552 log_err("can't listen: %s", strerror(errno));
555 log_err("can't listen: %s", wsa_strerror(WSAGetLastError()));
564 * Create socket from getaddrinfo results
567 make_sock(int stype, const char* ifname, const char* port,
568 struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
571 struct addrinfo *res = NULL;
572 int r, s, inuse, noproto;
573 hints->ai_socktype = stype;
575 if((r=getaddrinfo(ifname, port, hints, &res)) != 0 || !res) {
577 if(r == EAI_NONAME && hints->ai_family == AF_INET6){
578 *noip6 = 1; /* 'Host not found' for IP6 on winXP */
582 log_err("node %s:%s getaddrinfo: %s %s",
583 ifname?ifname:"default", port, gai_strerror(r),
585 r==EAI_SYSTEM?(char*)strerror(errno):""
592 if(stype == SOCK_DGRAM) {
593 verbose_print_addr(res);
594 s = create_udp_sock(res->ai_family, res->ai_socktype,
595 (struct sockaddr*)res->ai_addr, res->ai_addrlen,
596 v6only, &inuse, &noproto, (int)rcv, (int)snd, 1,
598 if(s == -1 && inuse) {
599 log_err("bind: address already in use");
600 } else if(s == -1 && noproto && hints->ai_family == AF_INET6){
604 s = create_tcp_accept_sock(res, v6only, &noproto, reuseport);
605 if(s == -1 && noproto && hints->ai_family == AF_INET6){
613 /** make socket and first see if ifname contains port override info */
615 make_sock_port(int stype, const char* ifname, const char* port,
616 struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
619 char* s = strchr(ifname, '@');
621 /* override port with ifspec@port */
624 if((size_t)(s-ifname) >= sizeof(newif)) {
625 log_err("ifname too long: %s", ifname);
629 if(strlen(s+1) >= sizeof(p)) {
630 log_err("portnumber too long: %s", ifname);
634 (void)strlcpy(newif, ifname, sizeof(newif));
636 (void)strlcpy(p, s+1, sizeof(p));
638 return make_sock(stype, newif, p, hints, v6only, noip6,
639 rcv, snd, reuseport);
641 return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd,
646 * Add port to open ports list.
647 * @param list: list head. changed.
649 * @param ftype: if fd is UDP.
650 * @return false on failure. list in unchanged then.
653 port_insert(struct listen_port** list, int s, enum listen_type ftype)
655 struct listen_port* item = (struct listen_port*)malloc(
656 sizeof(struct listen_port));
666 /** set fd to receive source address packet info */
668 set_recvpktinfo(int s, int family)
670 #if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)) || defined(IP_PKTINFO)
675 if(family == AF_INET6) {
676 # ifdef IPV6_RECVPKTINFO
677 if(setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
678 (void*)&on, (socklen_t)sizeof(on)) < 0) {
679 log_err("setsockopt(..., IPV6_RECVPKTINFO, ...) failed: %s",
683 # elif defined(IPV6_PKTINFO)
684 if(setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO,
685 (void*)&on, (socklen_t)sizeof(on)) < 0) {
686 log_err("setsockopt(..., IPV6_PKTINFO, ...) failed: %s",
691 log_err("no IPV6_RECVPKTINFO and no IPV6_PKTINFO option, please "
692 "disable interface-automatic in config");
694 # endif /* defined IPV6_RECVPKTINFO */
696 } else if(family == AF_INET) {
698 if(setsockopt(s, IPPROTO_IP, IP_PKTINFO,
699 (void*)&on, (socklen_t)sizeof(on)) < 0) {
700 log_err("setsockopt(..., IP_PKTINFO, ...) failed: %s",
704 # elif defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)
705 if(setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
706 (void*)&on, (socklen_t)sizeof(on)) < 0) {
707 log_err("setsockopt(..., IP_RECVDSTADDR, ...) failed: %s",
712 log_err("no IP_SENDSRCADDR or IP_PKTINFO option, please disable "
713 "interface-automatic in config");
715 # endif /* IP_PKTINFO */
722 * Helper for ports_open. Creates one interface (or NULL for default).
723 * @param ifname: The interface ip address.
724 * @param do_auto: use automatic interface detection.
725 * If enabled, then ifname must be the wildcard name.
726 * @param do_udp: if udp should be used.
727 * @param do_tcp: if udp should be used.
728 * @param hints: for getaddrinfo. family and flags have to be set by caller.
729 * @param port: Port number to use (as string).
730 * @param list: list of open ports, appended to, changed to point to list head.
731 * @param rcv: receive buffer size for UDP
732 * @param snd: send buffer size for UDP
733 * @param ssl_port: ssl service port number
734 * @param reuseport: try to set SO_REUSEPORT if nonNULL and true.
735 * set to false on exit if reuseport failed due to no kernel support.
736 * @return: returns false on error.
739 ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
740 struct addrinfo *hints, const char* port, struct listen_port** list,
741 size_t rcv, size_t snd, int ssl_port, int* reuseport)
744 if(!do_udp && !do_tcp)
747 if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
748 &noip6, rcv, snd, reuseport)) == -1) {
750 log_warn("IPv6 protocol not available");
755 /* getting source addr packet info is highly non-portable */
756 if(!set_recvpktinfo(s, hints->ai_family)) {
764 if(!port_insert(list, s, listen_type_udpancil)) {
773 /* regular udp socket */
774 if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
775 &noip6, rcv, snd, reuseport)) == -1) {
777 log_warn("IPv6 protocol not available");
782 if(!port_insert(list, s, listen_type_udp)) {
792 int is_ssl = ((strchr(ifname, '@') &&
793 atoi(strchr(ifname, '@')+1) == ssl_port) ||
794 (!strchr(ifname, '@') && atoi(port) == ssl_port));
795 if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
796 &noip6, 0, 0, reuseport)) == -1) {
798 /*log_warn("IPv6 protocol not available");*/
804 verbose(VERB_ALGO, "setup TCP for SSL service");
805 if(!port_insert(list, s, is_ssl?listen_type_ssl:
819 * Add items to commpoint list in front.
820 * @param c: commpoint to add.
821 * @param front: listen struct.
822 * @return: false on failure.
825 listen_cp_insert(struct comm_point* c, struct listen_dnsport* front)
827 struct listen_list* item = (struct listen_list*)malloc(
828 sizeof(struct listen_list));
832 item->next = front->cps;
837 struct listen_dnsport*
838 listen_create(struct comm_base* base, struct listen_port* ports,
839 size_t bufsize, int tcp_accept_count, void* sslctx,
840 comm_point_callback_t* cb, void *cb_arg)
842 struct listen_dnsport* front = (struct listen_dnsport*)
843 malloc(sizeof(struct listen_dnsport));
847 front->udp_buff = sldns_buffer_new(bufsize);
848 if(!front->udp_buff) {
853 /* create comm points as needed */
855 struct comm_point* cp = NULL;
856 if(ports->ftype == listen_type_udp)
857 cp = comm_point_create_udp(base, ports->fd,
858 front->udp_buff, cb, cb_arg);
859 else if(ports->ftype == listen_type_tcp)
860 cp = comm_point_create_tcp(base, ports->fd,
861 tcp_accept_count, bufsize, cb, cb_arg);
862 else if(ports->ftype == listen_type_ssl) {
863 cp = comm_point_create_tcp(base, ports->fd,
864 tcp_accept_count, bufsize, cb, cb_arg);
866 } else if(ports->ftype == listen_type_udpancil)
867 cp = comm_point_create_udp_ancil(base, ports->fd,
868 front->udp_buff, cb, cb_arg);
870 log_err("can't create commpoint");
871 listen_delete(front);
874 cp->do_not_close = 1;
875 if(!listen_cp_insert(cp, front)) {
876 log_err("malloc failed");
877 comm_point_delete(cp);
878 listen_delete(front);
884 log_err("Could not open sockets to accept queries.");
885 listen_delete(front);
893 listen_list_delete(struct listen_list* list)
895 struct listen_list *p = list, *pn;
898 comm_point_delete(p->com);
905 listen_delete(struct listen_dnsport* front)
909 listen_list_delete(front->cps);
910 sldns_buffer_free(front->udp_buff);
915 listening_ports_open(struct config_file* cfg, int* reuseport)
917 struct listen_port* list = NULL;
918 struct addrinfo hints;
919 int i, do_ip4, do_ip6;
922 snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
923 do_ip4 = cfg->do_ip4;
924 do_ip6 = cfg->do_ip6;
925 do_tcp = cfg->do_tcp;
926 do_auto = cfg->if_automatic && cfg->do_udp;
927 if(cfg->incoming_num_tcp == 0)
931 memset(&hints, 0, sizeof(hints));
932 hints.ai_flags = AI_PASSIVE;
933 /* no name lookups on our listening ports */
935 hints.ai_flags |= AI_NUMERICHOST;
936 hints.ai_family = AF_UNSPEC;
940 if(!do_ip4 && !do_ip6) {
943 /* create ip4 and ip6 ports so that return addresses are nice. */
944 if(do_auto || cfg->num_ifs == 0) {
946 hints.ai_family = AF_INET6;
947 if(!ports_create_if(do_auto?"::0":"::1",
948 do_auto, cfg->do_udp, do_tcp,
949 &hints, portbuf, &list,
950 cfg->so_rcvbuf, cfg->so_sndbuf,
951 cfg->ssl_port, reuseport)) {
952 listening_ports_free(list);
957 hints.ai_family = AF_INET;
958 if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1",
959 do_auto, cfg->do_udp, do_tcp,
960 &hints, portbuf, &list,
961 cfg->so_rcvbuf, cfg->so_sndbuf,
962 cfg->ssl_port, reuseport)) {
963 listening_ports_free(list);
967 } else for(i = 0; i<cfg->num_ifs; i++) {
968 if(str_is_ip6(cfg->ifs[i])) {
971 hints.ai_family = AF_INET6;
972 if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
973 do_tcp, &hints, portbuf, &list,
974 cfg->so_rcvbuf, cfg->so_sndbuf,
975 cfg->ssl_port, reuseport)) {
976 listening_ports_free(list);
982 hints.ai_family = AF_INET;
983 if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
984 do_tcp, &hints, portbuf, &list,
985 cfg->so_rcvbuf, cfg->so_sndbuf,
986 cfg->ssl_port, reuseport)) {
987 listening_ports_free(list);
995 void listening_ports_free(struct listen_port* list)
997 struct listen_port* nx;
1000 if(list->fd != -1) {
1004 closesocket(list->fd);
1012 size_t listen_get_mem(struct listen_dnsport* listen)
1014 size_t s = sizeof(*listen) + sizeof(*listen->base) +
1015 sizeof(*listen->udp_buff) +
1016 sldns_buffer_capacity(listen->udp_buff);
1017 struct listen_list* p;
1018 for(p = listen->cps; p; p = p->next) {
1020 s += comm_point_get_mem(p->com);
1025 void listen_stop_accept(struct listen_dnsport* listen)
1027 /* do not stop the ones that have no tcp_free list
1028 * (they have already stopped listening) */
1029 struct listen_list* p;
1030 for(p=listen->cps; p; p=p->next) {
1031 if(p->com->type == comm_tcp_accept &&
1032 p->com->tcp_free != NULL) {
1033 comm_point_stop_listening(p->com);
1038 void listen_start_accept(struct listen_dnsport* listen)
1040 /* do not start the ones that have no tcp_free list, it is no
1041 * use to listen to them because they have no free tcp handlers */
1042 struct listen_list* p;
1043 for(p=listen->cps; p; p=p->next) {
1044 if(p->com->type == comm_tcp_accept &&
1045 p->com->tcp_free != NULL) {
1046 comm_point_start_listening(p->com, -1, -1);