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 LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * 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"
58 /** number of queued TCP connections for listen() */
62 * Debug print of the getaddrinfo returned address.
63 * @param addr: the address returned.
66 verbose_print_addr(struct addrinfo *addr)
68 if(verbosity >= VERB_ALGO) {
70 void* sinaddr = &((struct sockaddr_in*)addr->ai_addr)->sin_addr;
72 if(addr->ai_family == AF_INET6)
73 sinaddr = &((struct sockaddr_in6*)addr->ai_addr)->
76 if(inet_ntop(addr->ai_family, sinaddr, buf,
77 (socklen_t)sizeof(buf)) == 0) {
78 strncpy(buf, "(null)", sizeof(buf));
80 buf[sizeof(buf)-1] = 0;
81 verbose(VERB_ALGO, "creating %s%s socket %s %d",
82 addr->ai_socktype==SOCK_DGRAM?"udp":
83 addr->ai_socktype==SOCK_STREAM?"tcp":"otherproto",
84 addr->ai_family==AF_INET?"4":
85 addr->ai_family==AF_INET6?"6":
87 ntohs(((struct sockaddr_in*)addr->ai_addr)->sin_port));
92 create_udp_sock(int family, int socktype, struct sockaddr* addr,
93 socklen_t addrlen, int v6only, int* inuse, int* noproto,
97 #if defined(IPV6_USE_MIN_MTU)
101 int mtu = IPV6_MIN_MTU;
103 #if !defined(SO_RCVBUFFORCE) && !defined(SO_RCVBUF)
106 #if !defined(SO_SNDBUFFORCE) && !defined(SO_SNDBUF)
112 if((s = socket(family, socktype, 0)) == -1) {
115 if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
119 log_err("can't create socket: %s", strerror(errno));
121 if(WSAGetLastError() == WSAEAFNOSUPPORT ||
122 WSAGetLastError() == WSAEPROTONOSUPPORT) {
126 log_err("can't create socket: %s",
127 wsa_strerror(WSAGetLastError()));
135 socklen_t slen = (socklen_t)sizeof(got);
136 # ifdef SO_RCVBUFFORCE
137 /* Linux specific: try to use root permission to override
138 * system limits on rcvbuf. The limit is stored in
139 * /proc/sys/net/core/rmem_max or sysctl net.core.rmem_max */
140 if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv,
141 (socklen_t)sizeof(rcv)) < 0) {
144 log_err("setsockopt(..., SO_RCVBUFFORCE, "
145 "...) failed: %s", strerror(errno));
148 log_err("setsockopt(..., SO_RCVBUFFORCE, "
150 wsa_strerror(WSAGetLastError()));
157 # endif /* SO_RCVBUFFORCE */
158 if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv,
159 (socklen_t)sizeof(rcv)) < 0) {
161 log_err("setsockopt(..., SO_RCVBUF, "
162 "...) failed: %s", strerror(errno));
165 log_err("setsockopt(..., SO_RCVBUF, "
167 wsa_strerror(WSAGetLastError()));
174 /* check if we got the right thing or if system
175 * reduced to some system max. Warn if so */
176 if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&got,
177 &slen) >= 0 && got < rcv/2) {
178 log_warn("so-rcvbuf %u was not granted. "
179 "Got %u. To fix: start with "
180 "root permissions(linux) or sysctl "
181 "bigger net.core.rmem_max(linux) or "
182 "kern.ipc.maxsockbuf(bsd) values.",
183 (unsigned)rcv, (unsigned)got);
185 # ifdef SO_RCVBUFFORCE
188 #endif /* SO_RCVBUF */
190 /* first do RCVBUF as the receive buffer is more important */
194 socklen_t slen = (socklen_t)sizeof(got);
195 # ifdef SO_SNDBUFFORCE
196 /* Linux specific: try to use root permission to override
197 * system limits on sndbuf. The limit is stored in
198 * /proc/sys/net/core/wmem_max or sysctl net.core.wmem_max */
199 if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd,
200 (socklen_t)sizeof(snd)) < 0) {
203 log_err("setsockopt(..., SO_SNDBUFFORCE, "
204 "...) failed: %s", strerror(errno));
207 log_err("setsockopt(..., SO_SNDBUFFORCE, "
209 wsa_strerror(WSAGetLastError()));
216 # endif /* SO_SNDBUFFORCE */
217 if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd,
218 (socklen_t)sizeof(snd)) < 0) {
220 log_err("setsockopt(..., SO_SNDBUF, "
221 "...) failed: %s", strerror(errno));
224 log_err("setsockopt(..., SO_SNDBUF, "
226 wsa_strerror(WSAGetLastError()));
233 /* check if we got the right thing or if system
234 * reduced to some system max. Warn if so */
235 if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got,
236 &slen) >= 0 && got < snd/2) {
237 log_warn("so-sndbuf %u was not granted. "
238 "Got %u. To fix: start with "
239 "root permissions(linux) or sysctl "
240 "bigger net.core.wmem_max(linux) or "
241 "kern.ipc.maxsockbuf(bsd) values.",
242 (unsigned)snd, (unsigned)got);
244 # ifdef SO_SNDBUFFORCE
247 #endif /* SO_SNDBUF */
249 if(family == AF_INET6) {
250 # if defined(IPV6_V6ONLY)
252 int val=(v6only==2)?0:1;
253 if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
254 (void*)&val, (socklen_t)sizeof(val)) < 0) {
256 log_err("setsockopt(..., IPV6_V6ONLY"
257 ", ...) failed: %s", strerror(errno));
260 log_err("setsockopt(..., IPV6_V6ONLY"
262 wsa_strerror(WSAGetLastError()));
271 # if defined(IPV6_USE_MIN_MTU)
273 * There is no fragmentation of IPv6 datagrams
274 * during forwarding in the network. Therefore
275 * we do not send UDP datagrams larger than
276 * the minimum IPv6 MTU of 1280 octets. The
277 * EDNS0 message length can be larger if the
278 * network stack supports IPV6_USE_MIN_MTU.
280 if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
281 (void*)&on, (socklen_t)sizeof(on)) < 0) {
283 log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
284 "...) failed: %s", strerror(errno));
287 log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
289 wsa_strerror(WSAGetLastError()));
296 # elif defined(IPV6_MTU)
298 * On Linux, to send no larger than 1280, the PMTUD is
299 * disabled by default for datagrams anyway, so we set
302 if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU,
303 (void*)&mtu, (socklen_t)sizeof(mtu)) < 0) {
305 log_err("setsockopt(..., IPV6_MTU, ...) failed: %s",
309 log_err("setsockopt(..., IPV6_MTU, ...) failed: %s",
310 wsa_strerror(WSAGetLastError()));
317 # endif /* IPv6 MTU */
318 } else if(family == AF_INET) {
319 # if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
320 int action = IP_PMTUDISC_DONT;
321 if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER,
322 &action, (socklen_t)sizeof(action)) < 0) {
323 log_err("setsockopt(..., IP_MTU_DISCOVER, "
324 "IP_PMTUDISC_DONT...) failed: %s",
333 # elif defined(IP_DONTFRAG)
335 if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG,
336 &off, (socklen_t)sizeof(off)) < 0) {
337 log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
346 # endif /* IPv4 MTU */
348 if(bind(s, (struct sockaddr*)addr, addrlen) != 0) {
352 *inuse = (errno == EADDRINUSE);
353 /* detect freebsd jail with no ipv6 permission */
354 if(family==AF_INET6 && errno==EINVAL)
356 else if(errno != EADDRINUSE) {
357 log_err("can't bind socket: %s", strerror(errno));
358 log_addr(0, "failed address",
359 (struct sockaddr_storage*)addr, addrlen);
361 #endif /* EADDRINUSE */
363 #else /* USE_WINSOCK */
364 if(WSAGetLastError() != WSAEADDRINUSE &&
365 WSAGetLastError() != WSAEADDRNOTAVAIL) {
366 log_err("can't bind socket: %s",
367 wsa_strerror(WSAGetLastError()));
368 log_addr(0, "failed address",
369 (struct sockaddr_storage*)addr, addrlen);
375 if(!fd_set_nonblock(s)) {
389 create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
392 #if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY)
394 #endif /* SO_REUSEADDR || IPV6_V6ONLY */
395 verbose_print_addr(addr);
397 if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
399 if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
403 log_err("can't create socket: %s", strerror(errno));
405 if(WSAGetLastError() == WSAEAFNOSUPPORT ||
406 WSAGetLastError() == WSAEPROTONOSUPPORT) {
410 log_err("can't create socket: %s",
411 wsa_strerror(WSAGetLastError()));
416 if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
417 (socklen_t)sizeof(on)) < 0) {
419 log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
423 log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
424 wsa_strerror(WSAGetLastError()));
429 #endif /* SO_REUSEADDR */
430 #if defined(IPV6_V6ONLY)
431 if(addr->ai_family == AF_INET6 && v6only) {
432 if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
433 (void*)&on, (socklen_t)sizeof(on)) < 0) {
435 log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
439 log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
440 wsa_strerror(WSAGetLastError()));
448 #endif /* IPV6_V6ONLY */
449 if(bind(s, addr->ai_addr, addr->ai_addrlen) != 0) {
451 /* detect freebsd jail with no ipv6 permission */
452 if(addr->ai_family==AF_INET6 && errno==EINVAL)
455 log_err("can't bind socket: %s", strerror(errno));
456 log_addr(0, "failed address",
457 (struct sockaddr_storage*)addr->ai_addr,
462 log_err("can't bind socket: %s",
463 wsa_strerror(WSAGetLastError()));
464 log_addr(0, "failed address",
465 (struct sockaddr_storage*)addr->ai_addr,
471 if(!fd_set_nonblock(s)) {
479 if(listen(s, TCP_BACKLOG) == -1) {
481 log_err("can't listen: %s", strerror(errno));
484 log_err("can't listen: %s", wsa_strerror(WSAGetLastError()));
493 * Create socket from getaddrinfo results
496 make_sock(int stype, const char* ifname, const char* port,
497 struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd)
499 struct addrinfo *res = NULL;
500 int r, s, inuse, noproto;
501 hints->ai_socktype = stype;
503 if((r=getaddrinfo(ifname, port, hints, &res)) != 0 || !res) {
505 if(r == EAI_NONAME && hints->ai_family == AF_INET6){
506 *noip6 = 1; /* 'Host not found' for IP6 on winXP */
510 log_err("node %s:%s getaddrinfo: %s %s",
511 ifname?ifname:"default", port, gai_strerror(r),
513 r==EAI_SYSTEM?(char*)strerror(errno):""
520 if(stype == SOCK_DGRAM) {
521 verbose_print_addr(res);
522 s = create_udp_sock(res->ai_family, res->ai_socktype,
523 (struct sockaddr*)res->ai_addr, res->ai_addrlen,
524 v6only, &inuse, &noproto, (int)rcv, (int)snd);
525 if(s == -1 && inuse) {
526 log_err("bind: address already in use");
527 } else if(s == -1 && noproto && hints->ai_family == AF_INET6){
531 s = create_tcp_accept_sock(res, v6only, &noproto);
532 if(s == -1 && noproto && hints->ai_family == AF_INET6){
540 /** make socket and first see if ifname contains port override info */
542 make_sock_port(int stype, const char* ifname, const char* port,
543 struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd)
545 char* s = strchr(ifname, '@');
547 /* override port with ifspec@port */
550 if((size_t)(s-ifname) >= sizeof(newif)) {
551 log_err("ifname too long: %s", ifname);
555 if(strlen(s+1) >= sizeof(p)) {
556 log_err("portnumber too long: %s", ifname);
560 strncpy(newif, ifname, sizeof(newif));
562 strncpy(p, s+1, sizeof(p));
564 return make_sock(stype, newif, p, hints, v6only, noip6,
567 return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd);
571 * Add port to open ports list.
572 * @param list: list head. changed.
574 * @param ftype: if fd is UDP.
575 * @return false on failure. list in unchanged then.
578 port_insert(struct listen_port** list, int s, enum listen_type ftype)
580 struct listen_port* item = (struct listen_port*)malloc(
581 sizeof(struct listen_port));
591 /** set fd to receive source address packet info */
593 set_recvpktinfo(int s, int family)
595 #if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)) || defined(IP_PKTINFO)
600 if(family == AF_INET6) {
601 # ifdef IPV6_RECVPKTINFO
602 if(setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
603 (void*)&on, (socklen_t)sizeof(on)) < 0) {
604 log_err("setsockopt(..., IPV6_RECVPKTINFO, ...) failed: %s",
608 # elif defined(IPV6_PKTINFO)
609 if(setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO,
610 (void*)&on, (socklen_t)sizeof(on)) < 0) {
611 log_err("setsockopt(..., IPV6_PKTINFO, ...) failed: %s",
616 log_err("no IPV6_RECVPKTINFO and no IPV6_PKTINFO option, please "
617 "disable interface-automatic in config");
619 # endif /* defined IPV6_RECVPKTINFO */
621 } else if(family == AF_INET) {
623 if(setsockopt(s, IPPROTO_IP, IP_PKTINFO,
624 (void*)&on, (socklen_t)sizeof(on)) < 0) {
625 log_err("setsockopt(..., IP_PKTINFO, ...) failed: %s",
629 # elif defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)
630 if(setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
631 (void*)&on, (socklen_t)sizeof(on)) < 0) {
632 log_err("setsockopt(..., IP_RECVDSTADDR, ...) failed: %s",
637 log_err("no IP_SENDSRCADDR or IP_PKTINFO option, please disable "
638 "interface-automatic in config");
640 # endif /* IP_PKTINFO */
647 * Helper for ports_open. Creates one interface (or NULL for default).
648 * @param ifname: The interface ip address.
649 * @param do_auto: use automatic interface detection.
650 * If enabled, then ifname must be the wildcard name.
651 * @param do_udp: if udp should be used.
652 * @param do_tcp: if udp should be used.
653 * @param hints: for getaddrinfo. family and flags have to be set by caller.
654 * @param port: Port number to use (as string).
655 * @param list: list of open ports, appended to, changed to point to list head.
656 * @param rcv: receive buffer size for UDP
657 * @param snd: send buffer size for UDP
658 * @param ssl_port: ssl service port number
659 * @return: returns false on error.
662 ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
663 struct addrinfo *hints, const char* port, struct listen_port** list,
664 size_t rcv, size_t snd, int ssl_port)
667 if(!do_udp && !do_tcp)
670 if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
671 &noip6, rcv, snd)) == -1) {
673 log_warn("IPv6 protocol not available");
678 /* getting source addr packet info is highly non-portable */
679 if(!set_recvpktinfo(s, hints->ai_family)) {
687 if(!port_insert(list, s, listen_type_udpancil)) {
696 /* regular udp socket */
697 if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
698 &noip6, rcv, snd)) == -1) {
700 log_warn("IPv6 protocol not available");
705 if(!port_insert(list, s, listen_type_udp)) {
715 int is_ssl = ((strchr(ifname, '@') &&
716 atoi(strchr(ifname, '@')+1) == ssl_port) ||
717 (!strchr(ifname, '@') && atoi(port) == ssl_port));
718 if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
719 &noip6, 0, 0)) == -1) {
721 /*log_warn("IPv6 protocol not available");*/
727 verbose(VERB_ALGO, "setup TCP for SSL service");
728 if(!port_insert(list, s, is_ssl?listen_type_ssl:
742 * Add items to commpoint list in front.
743 * @param c: commpoint to add.
744 * @param front: listen struct.
745 * @return: false on failure.
748 listen_cp_insert(struct comm_point* c, struct listen_dnsport* front)
750 struct listen_list* item = (struct listen_list*)malloc(
751 sizeof(struct listen_list));
755 item->next = front->cps;
760 struct listen_dnsport*
761 listen_create(struct comm_base* base, struct listen_port* ports,
762 size_t bufsize, int tcp_accept_count, void* sslctx,
763 comm_point_callback_t* cb, void *cb_arg)
765 struct listen_dnsport* front = (struct listen_dnsport*)
766 malloc(sizeof(struct listen_dnsport));
770 front->udp_buff = ldns_buffer_new(bufsize);
771 if(!front->udp_buff) {
776 /* create comm points as needed */
778 struct comm_point* cp = NULL;
779 if(ports->ftype == listen_type_udp)
780 cp = comm_point_create_udp(base, ports->fd,
781 front->udp_buff, cb, cb_arg);
782 else if(ports->ftype == listen_type_tcp)
783 cp = comm_point_create_tcp(base, ports->fd,
784 tcp_accept_count, bufsize, cb, cb_arg);
785 else if(ports->ftype == listen_type_ssl) {
786 cp = comm_point_create_tcp(base, ports->fd,
787 tcp_accept_count, bufsize, cb, cb_arg);
789 } else if(ports->ftype == listen_type_udpancil)
790 cp = comm_point_create_udp_ancil(base, ports->fd,
791 front->udp_buff, cb, cb_arg);
793 log_err("can't create commpoint");
794 listen_delete(front);
797 cp->do_not_close = 1;
798 if(!listen_cp_insert(cp, front)) {
799 log_err("malloc failed");
800 comm_point_delete(cp);
801 listen_delete(front);
807 log_err("Could not open sockets to accept queries.");
808 listen_delete(front);
816 listen_list_delete(struct listen_list* list)
818 struct listen_list *p = list, *pn;
821 comm_point_delete(p->com);
828 listen_delete(struct listen_dnsport* front)
832 listen_list_delete(front->cps);
833 ldns_buffer_free(front->udp_buff);
838 listening_ports_open(struct config_file* cfg)
840 struct listen_port* list = NULL;
841 struct addrinfo hints;
842 int i, do_ip4, do_ip6;
845 snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
846 do_ip4 = cfg->do_ip4;
847 do_ip6 = cfg->do_ip6;
848 do_tcp = cfg->do_tcp;
849 do_auto = cfg->if_automatic && cfg->do_udp;
850 if(cfg->incoming_num_tcp == 0)
854 memset(&hints, 0, sizeof(hints));
855 hints.ai_flags = AI_PASSIVE;
856 /* no name lookups on our listening ports */
858 hints.ai_flags |= AI_NUMERICHOST;
859 hints.ai_family = AF_UNSPEC;
863 if(!do_ip4 && !do_ip6) {
866 /* create ip4 and ip6 ports so that return addresses are nice. */
867 if(do_auto || cfg->num_ifs == 0) {
869 hints.ai_family = AF_INET6;
870 if(!ports_create_if(do_auto?"::0":"::1",
871 do_auto, cfg->do_udp, do_tcp,
872 &hints, portbuf, &list,
873 cfg->so_rcvbuf, cfg->so_sndbuf,
875 listening_ports_free(list);
880 hints.ai_family = AF_INET;
881 if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1",
882 do_auto, cfg->do_udp, do_tcp,
883 &hints, portbuf, &list,
884 cfg->so_rcvbuf, cfg->so_sndbuf,
886 listening_ports_free(list);
890 } else for(i = 0; i<cfg->num_ifs; i++) {
891 if(str_is_ip6(cfg->ifs[i])) {
894 hints.ai_family = AF_INET6;
895 if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
896 do_tcp, &hints, portbuf, &list,
897 cfg->so_rcvbuf, cfg->so_sndbuf,
899 listening_ports_free(list);
905 hints.ai_family = AF_INET;
906 if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
907 do_tcp, &hints, portbuf, &list,
908 cfg->so_rcvbuf, cfg->so_sndbuf,
910 listening_ports_free(list);
918 void listening_ports_free(struct listen_port* list)
920 struct listen_port* nx;
927 closesocket(list->fd);
935 size_t listen_get_mem(struct listen_dnsport* listen)
937 size_t s = sizeof(*listen) + sizeof(*listen->base) +
938 sizeof(*listen->udp_buff) +
939 ldns_buffer_capacity(listen->udp_buff);
940 struct listen_list* p;
941 for(p = listen->cps; p; p = p->next) {
943 s += comm_point_get_mem(p->com);
948 void listen_stop_accept(struct listen_dnsport* listen)
950 /* do not stop the ones that have no tcp_free list
951 * (they have already stopped listening) */
952 struct listen_list* p;
953 for(p=listen->cps; p; p=p->next) {
954 if(p->com->type == comm_tcp_accept &&
955 p->com->tcp_free != NULL) {
956 comm_point_stop_listening(p->com);
961 void listen_start_accept(struct listen_dnsport* listen)
963 /* do not start the ones that have no tcp_free list, it is no
964 * use to listen to them because they have no free tcp handlers */
965 struct listen_list* p;
966 for(p=listen->cps; p; p=p->next) {
967 if(p->com->type == comm_tcp_accept &&
968 p->com->tcp_free != NULL) {
969 comm_point_start_listening(p->com, -1, -1);