]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/unbound/services/listen_dnsport.c
Apply fixes in ena-com
[FreeBSD/FreeBSD.git] / contrib / unbound / services / listen_dnsport.c
1 /*
2  * services/listen_dnsport.c - listen on port 53 for incoming DNS queries.
3  *
4  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5  *
6  * This software is open source.
7  * 
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 
12  * Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  * 
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.
18  * 
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.
22  * 
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.
34  */
35
36 /**
37  * \file
38  *
39  * This file has functions to get queries from clients.
40  */
41 #include "config.h"
42 #ifdef HAVE_SYS_TYPES_H
43 #  include <sys/types.h>
44 #endif
45 #include <sys/time.h>
46 #ifdef USE_TCP_FASTOPEN
47 #include <netinet/tcp.h>
48 #endif
49 #include "services/listen_dnsport.h"
50 #include "services/outside_network.h"
51 #include "util/netevent.h"
52 #include "util/log.h"
53 #include "util/config_file.h"
54 #include "util/net_help.h"
55 #include "sldns/sbuffer.h"
56
57 #ifdef HAVE_NETDB_H
58 #include <netdb.h>
59 #endif
60 #include <fcntl.h>
61
62 #ifdef HAVE_SYS_UN_H
63 #include <sys/un.h>
64 #endif
65
66 /** number of queued TCP connections for listen() */
67 #define TCP_BACKLOG 256 
68
69 /**
70  * Debug print of the getaddrinfo returned address.
71  * @param addr: the address returned.
72  */
73 static void
74 verbose_print_addr(struct addrinfo *addr)
75 {
76         if(verbosity >= VERB_ALGO) {
77                 char buf[100];
78                 void* sinaddr = &((struct sockaddr_in*)addr->ai_addr)->sin_addr;
79 #ifdef INET6
80                 if(addr->ai_family == AF_INET6)
81                         sinaddr = &((struct sockaddr_in6*)addr->ai_addr)->
82                                 sin6_addr;
83 #endif /* INET6 */
84                 if(inet_ntop(addr->ai_family, sinaddr, buf,
85                         (socklen_t)sizeof(buf)) == 0) {
86                         (void)strlcpy(buf, "(null)", sizeof(buf));
87                 }
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":
94                         "_otherfam", buf, 
95                         ntohs(((struct sockaddr_in*)addr->ai_addr)->sin_port));
96         }
97 }
98
99 int
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,
103         int freebind)
104 {
105         int s;
106 #if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU)  || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND)
107         int on=1;
108 #endif
109 #ifdef IPV6_MTU
110         int mtu = IPV6_MIN_MTU;
111 #endif
112 #if !defined(SO_RCVBUFFORCE) && !defined(SO_RCVBUF)
113         (void)rcv;
114 #endif
115 #if !defined(SO_SNDBUFFORCE) && !defined(SO_SNDBUF)
116         (void)snd;
117 #endif
118 #ifndef IPV6_V6ONLY
119         (void)v6only;
120 #endif
121 #if !defined(IP_TRANSPARENT) && !defined(IP_BINDANY)
122         (void)transparent;
123 #endif
124 #if !defined(IP_FREEBIND)
125         (void)freebind;
126 #endif
127         if((s = socket(family, socktype, 0)) == -1) {
128                 *inuse = 0;
129 #ifndef USE_WINSOCK
130                 if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
131                         *noproto = 1;
132                         return -1;
133                 }
134                 log_err("can't create socket: %s", strerror(errno));
135 #else
136                 if(WSAGetLastError() == WSAEAFNOSUPPORT || 
137                         WSAGetLastError() == WSAEPROTONOSUPPORT) {
138                         *noproto = 1;
139                         return -1;
140                 }
141                 log_err("can't create socket: %s", 
142                         wsa_strerror(WSAGetLastError()));
143 #endif
144                 *noproto = 0;
145                 return -1;
146         }
147         if(listen) {
148 #ifdef SO_REUSEADDR
149                 if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, 
150                         (socklen_t)sizeof(on)) < 0) {
151 #ifndef USE_WINSOCK
152                         log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
153                                 strerror(errno));
154                         if(errno != ENOSYS) {
155                                 close(s);
156                                 *noproto = 0;
157                                 *inuse = 0;
158                                 return -1;
159                         }
160 #else
161                         log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
162                                 wsa_strerror(WSAGetLastError()));
163                         closesocket(s);
164                         *noproto = 0;
165                         *inuse = 0;
166                         return -1;
167 #endif
168                 }
169 #endif /* SO_REUSEADDR */
170 #ifdef SO_REUSEPORT
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.
175                  */
176                 if (reuseport && *reuseport &&
177                     setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on,
178                         (socklen_t)sizeof(on)) < 0) {
179 #ifdef ENOPROTOOPT
180                         if(errno != ENOPROTOOPT || verbosity >= 3)
181                                 log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s",
182                                         strerror(errno));
183 #endif
184                         /* this option is not essential, we can continue */
185                         *reuseport = 0;
186                 }
187 #else
188                 (void)reuseport;
189 #endif /* defined(SO_REUSEPORT) */
190 #ifdef IP_TRANSPARENT
191                 if (transparent &&
192                     setsockopt(s, IPPROTO_IP, IP_TRANSPARENT, (void*)&on,
193                     (socklen_t)sizeof(on)) < 0) {
194                         log_warn("setsockopt(.. IP_TRANSPARENT ..) failed: %s",
195                         strerror(errno));
196                 }
197 #elif defined(IP_BINDANY)
198                 if (transparent &&
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));
204                 }
205 #endif /* IP_TRANSPARENT || IP_BINDANY */
206         }
207 #ifdef IP_FREEBIND
208         if(freebind &&
209             setsockopt(s, IPPROTO_IP, IP_FREEBIND, (void*)&on,
210             (socklen_t)sizeof(on)) < 0) {
211                 log_warn("setsockopt(.. IP_FREEBIND ..) failed: %s",
212                 strerror(errno));
213         }
214 #endif /* IP_FREEBIND */
215         if(rcv) {
216 #ifdef SO_RCVBUF
217                 int got;
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) {
225                         if(errno != EPERM) {
226 #    ifndef USE_WINSOCK
227                                 log_err("setsockopt(..., SO_RCVBUFFORCE, "
228                                         "...) failed: %s", strerror(errno));
229                                 close(s);
230 #    else
231                                 log_err("setsockopt(..., SO_RCVBUFFORCE, "
232                                         "...) failed: %s", 
233                                         wsa_strerror(WSAGetLastError()));
234                                 closesocket(s);
235 #    endif
236                                 *noproto = 0;
237                                 *inuse = 0;
238                                 return -1;
239                         }
240 #  endif /* SO_RCVBUFFORCE */
241                         if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv, 
242                                 (socklen_t)sizeof(rcv)) < 0) {
243 #  ifndef USE_WINSOCK
244                                 log_err("setsockopt(..., SO_RCVBUF, "
245                                         "...) failed: %s", strerror(errno));
246                                 close(s);
247 #  else
248                                 log_err("setsockopt(..., SO_RCVBUF, "
249                                         "...) failed: %s", 
250                                         wsa_strerror(WSAGetLastError()));
251                                 closesocket(s);
252 #  endif
253                                 *noproto = 0;
254                                 *inuse = 0;
255                                 return -1;
256                         }
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);
267                         }
268 #  ifdef SO_RCVBUFFORCE
269                 }
270 #  endif
271 #endif /* SO_RCVBUF */
272         }
273         /* first do RCVBUF as the receive buffer is more important */
274         if(snd) {
275 #ifdef SO_SNDBUF
276                 int got;
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) {
284                         if(errno != EPERM) {
285 #    ifndef USE_WINSOCK
286                                 log_err("setsockopt(..., SO_SNDBUFFORCE, "
287                                         "...) failed: %s", strerror(errno));
288                                 close(s);
289 #    else
290                                 log_err("setsockopt(..., SO_SNDBUFFORCE, "
291                                         "...) failed: %s", 
292                                         wsa_strerror(WSAGetLastError()));
293                                 closesocket(s);
294 #    endif
295                                 *noproto = 0;
296                                 *inuse = 0;
297                                 return -1;
298                         }
299 #  endif /* SO_SNDBUFFORCE */
300                         if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd, 
301                                 (socklen_t)sizeof(snd)) < 0) {
302 #  ifndef USE_WINSOCK
303                                 log_err("setsockopt(..., SO_SNDBUF, "
304                                         "...) failed: %s", strerror(errno));
305                                 close(s);
306 #  else
307                                 log_err("setsockopt(..., SO_SNDBUF, "
308                                         "...) failed: %s", 
309                                         wsa_strerror(WSAGetLastError()));
310                                 closesocket(s);
311 #  endif
312                                 *noproto = 0;
313                                 *inuse = 0;
314                                 return -1;
315                         }
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);
326                         }
327 #  ifdef SO_SNDBUFFORCE
328                 }
329 #  endif
330 #endif /* SO_SNDBUF */
331         }
332         if(family == AF_INET6) {
333 # if defined(IPV6_V6ONLY)
334                 if(v6only) {
335                         int val=(v6only==2)?0:1;
336                         if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, 
337                                 (void*)&val, (socklen_t)sizeof(val)) < 0) {
338 #ifndef USE_WINSOCK
339                                 log_err("setsockopt(..., IPV6_V6ONLY"
340                                         ", ...) failed: %s", strerror(errno));
341                                 close(s);
342 #else
343                                 log_err("setsockopt(..., IPV6_V6ONLY"
344                                         ", ...) failed: %s", 
345                                         wsa_strerror(WSAGetLastError()));
346                                 closesocket(s);
347 #endif
348                                 *noproto = 0;
349                                 *inuse = 0;
350                                 return -1;
351                         }
352                 }
353 # endif
354 # if defined(IPV6_USE_MIN_MTU)
355                 /*
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.
362                  */
363                 if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
364                         (void*)&on, (socklen_t)sizeof(on)) < 0) {
365 #  ifndef USE_WINSOCK
366                         log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
367                                 "...) failed: %s", strerror(errno));
368                         close(s);
369 #  else
370                         log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
371                                 "...) failed: %s", 
372                                 wsa_strerror(WSAGetLastError()));
373                         closesocket(s);
374 #  endif
375                         *noproto = 0;
376                         *inuse = 0;
377                         return -1;
378                 }
379 # elif defined(IPV6_MTU)
380                 /*
381                  * On Linux, to send no larger than 1280, the PMTUD is
382                  * disabled by default for datagrams anyway, so we set
383                  * the MTU to use.
384                  */
385                 if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU,
386                         (void*)&mtu, (socklen_t)sizeof(mtu)) < 0) {
387 #  ifndef USE_WINSOCK
388                         log_err("setsockopt(..., IPV6_MTU, ...) failed: %s", 
389                                 strerror(errno));
390                         close(s);
391 #  else
392                         log_err("setsockopt(..., IPV6_MTU, ...) failed: %s", 
393                                 wsa_strerror(WSAGetLastError()));
394                         closesocket(s);
395 #  endif
396                         *noproto = 0;
397                         *inuse = 0;
398                         return -1;
399                 }
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. */
409                 int omit_set = 0;
410                 int action;
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) {
415
416                         if (errno != EINVAL) {
417                                 log_err("setsockopt(..., IP_MTU_DISCOVER, IP_PMTUDISC_OMIT...) failed: %s",
418                                         strerror(errno));
419
420 #    ifndef USE_WINSOCK
421                                 close(s);
422 #    else
423                                 closesocket(s);
424 #    endif
425                                 *noproto = 0;
426                                 *inuse = 0;
427                                 return -1;
428                         }
429                 }
430                 else
431                 {
432                     omit_set = 1;
433                 }
434 #   endif
435                 if (omit_set == 0) {
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",
440                                         strerror(errno));
441 #    ifndef USE_WINSOCK
442                                 close(s);
443 #    else
444                                 closesocket(s);
445 #    endif
446                                 *noproto = 0;
447                                 *inuse = 0;
448                                 return -1;
449                         }
450                 }
451 #  elif defined(IP_DONTFRAG)
452                 int off = 0;
453                 if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG, 
454                         &off, (socklen_t)sizeof(off)) < 0) {
455                         log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
456                                 strerror(errno));
457 #    ifndef USE_WINSOCK
458                         close(s);
459 #    else
460                         closesocket(s);
461 #    endif
462                         *noproto = 0;
463                         *inuse = 0;
464                         return -1;
465                 }
466 #  endif /* IPv4 MTU */
467         }
468         if(bind(s, (struct sockaddr*)addr, addrlen) != 0) {
469                 *noproto = 0;
470                 *inuse = 0;
471 #ifndef USE_WINSOCK
472 #ifdef EADDRINUSE
473                 *inuse = (errno == EADDRINUSE);
474                 /* detect freebsd jail with no ipv6 permission */
475                 if(family==AF_INET6 && errno==EINVAL)
476                         *noproto = 1;
477                 else if(errno != EADDRINUSE) {
478                         log_err_addr("can't bind socket", strerror(errno),
479                                 (struct sockaddr_storage*)addr, addrlen);
480                 }
481 #endif /* EADDRINUSE */
482                 close(s);
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);
489                 }
490                 closesocket(s);
491 #endif
492                 return -1;
493         }
494         if(!fd_set_nonblock(s)) {
495                 *noproto = 0;
496                 *inuse = 0;
497 #ifndef USE_WINSOCK
498                 close(s);
499 #else
500                 closesocket(s);
501 #endif
502                 return -1;
503         }
504         return s;
505 }
506
507 int
508 create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
509         int* reuseport, int transparent, int mss, int freebind)
510 {
511         int s;
512 #if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND)
513         int on = 1;
514 #endif
515 #ifdef USE_TCP_FASTOPEN
516         int qlen;
517 #endif
518 #if !defined(IP_TRANSPARENT) && !defined(IP_BINDANY)
519         (void)transparent;
520 #endif
521 #if !defined(IP_FREEBIND)
522         (void)freebind;
523 #endif
524         verbose_print_addr(addr);
525         *noproto = 0;
526         if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
527 #ifndef USE_WINSOCK
528                 if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
529                         *noproto = 1;
530                         return -1;
531                 }
532                 log_err("can't create socket: %s", strerror(errno));
533 #else
534                 if(WSAGetLastError() == WSAEAFNOSUPPORT ||
535                         WSAGetLastError() == WSAEPROTONOSUPPORT) {
536                         *noproto = 1;
537                         return -1;
538                 }
539                 log_err("can't create socket: %s", 
540                         wsa_strerror(WSAGetLastError()));
541 #endif
542                 return -1;
543         }
544         if (mss > 0) {
545 #if defined(IPPROTO_TCP) && defined(TCP_MAXSEG)
546                 if(setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, (void*)&mss,
547                         (socklen_t)sizeof(mss)) < 0) {
548                         #ifndef USE_WINSOCK
549                         log_err(" setsockopt(.. TCP_MAXSEG ..) failed: %s",
550                                 strerror(errno));
551                         #else
552                         log_err(" setsockopt(.. TCP_MAXSEG ..) failed: %s",
553                                 wsa_strerror(WSAGetLastError()));
554                         #endif
555                 } else {
556                         verbose(VERB_ALGO,
557                                 " tcp socket mss set to %d", mss);
558                 }
559 #else
560                 log_warn(" setsockopt(TCP_MAXSEG) unsupported");
561 #endif /* defined(IPPROTO_TCP) && defined(TCP_MAXSEG) */
562         }
563 #ifdef SO_REUSEADDR
564         if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, 
565                 (socklen_t)sizeof(on)) < 0) {
566 #ifndef USE_WINSOCK
567                 log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
568                         strerror(errno));
569                 close(s);
570 #else
571                 log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
572                         wsa_strerror(WSAGetLastError()));
573                 closesocket(s);
574 #endif
575                 return -1;
576         }
577 #endif /* SO_REUSEADDR */
578 #ifdef IP_FREEBIND
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",
582                 strerror(errno));
583         }
584 #endif /* IP_FREEBIND */
585 #ifdef SO_REUSEPORT
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.
590          */
591         if (reuseport && *reuseport &&
592                 setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on,
593                 (socklen_t)sizeof(on)) < 0) {
594 #ifdef ENOPROTOOPT
595                 if(errno != ENOPROTOOPT || verbosity >= 3)
596                         log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s",
597                                 strerror(errno));
598 #endif
599                 /* this option is not essential, we can continue */
600                 *reuseport = 0;
601         }
602 #else
603         (void)reuseport;
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) {
609 #ifndef USE_WINSOCK
610                         log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
611                                 strerror(errno));
612                         close(s);
613 #else
614                         log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
615                                 wsa_strerror(WSAGetLastError()));
616                         closesocket(s);
617 #endif
618                         return -1;
619                 }
620         }
621 #else
622         (void)v6only;
623 #endif /* IPV6_V6ONLY */
624 #ifdef IP_TRANSPARENT
625         if (transparent &&
626             setsockopt(s, IPPROTO_IP, IP_TRANSPARENT, (void*)&on,
627             (socklen_t)sizeof(on)) < 0) {
628                 log_warn("setsockopt(.. IP_TRANSPARENT ..) failed: %s",
629                         strerror(errno));
630         }
631 #elif defined(IP_BINDANY)
632         if (transparent &&
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));
638         }
639 #endif /* IP_TRANSPARENT || IP_BINDANY */
640         if(bind(s, addr->ai_addr, addr->ai_addrlen) != 0) {
641 #ifndef USE_WINSOCK
642                 /* detect freebsd jail with no ipv6 permission */
643                 if(addr->ai_family==AF_INET6 && errno==EINVAL)
644                         *noproto = 1;
645                 else {
646                         log_err_addr("can't bind socket", strerror(errno),
647                                 (struct sockaddr_storage*)addr->ai_addr,
648                                 addr->ai_addrlen);
649                 }
650                 close(s);
651 #else
652                 log_err_addr("can't bind socket", 
653                         wsa_strerror(WSAGetLastError()),
654                         (struct sockaddr_storage*)addr->ai_addr,
655                         addr->ai_addrlen);
656                 closesocket(s);
657 #endif
658                 return -1;
659         }
660         if(!fd_set_nonblock(s)) {
661 #ifndef USE_WINSOCK
662                 close(s);
663 #else
664                 closesocket(s);
665 #endif
666                 return -1;
667         }
668         if(listen(s, TCP_BACKLOG) == -1) {
669 #ifndef USE_WINSOCK
670                 log_err("can't listen: %s", strerror(errno));
671                 close(s);
672 #else
673                 log_err("can't listen: %s", wsa_strerror(WSAGetLastError()));
674                 closesocket(s);
675 #endif
676                 return -1;
677         }
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 */
681 #ifdef __APPLE__
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. */
684         qlen = 1;
685 #else
686         /* 5 is recommended on linux */
687         qlen = 5;
688 #endif
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));
692         }
693 #endif
694         return s;
695 }
696
697 int
698 create_local_accept_sock(const char *path, int* noproto)
699 {
700 #ifdef HAVE_SYS_UN_H
701         int s;
702         struct sockaddr_un usock;
703
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);
708 #endif
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));
712
713         if ((s = socket(AF_LOCAL, SOCK_STREAM, 0)) == -1) {
714                 log_err("Cannot create local socket %s (%s)",
715                         path, strerror(errno));
716                 return -1;
717         }
718
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));
723                 return -1;
724         }
725
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));
730                 return -1;
731         }
732
733         if (!fd_set_nonblock(s)) {
734                 log_err("Cannot set non-blocking mode");
735                 return -1;
736         }
737
738         if (listen(s, TCP_BACKLOG) == -1) {
739                 log_err("can't listen: %s", strerror(errno));
740                 return -1;
741         }
742
743         (void)noproto; /*unused*/
744         return s;
745 #else
746         (void)path;
747         log_err("Local sockets are not supported");
748         *noproto = 1;
749         return -1;
750 #endif
751 }
752
753
754 /**
755  * Create socket from getaddrinfo results
756  */
757 static int
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)
761 {
762         struct addrinfo *res = NULL;
763         int r, s, inuse, noproto;
764         hints->ai_socktype = stype;
765         *noip6 = 0;
766         if((r=getaddrinfo(ifname, port, hints, &res)) != 0 || !res) {
767 #ifdef USE_WINSOCK
768                 if(r == EAI_NONAME && hints->ai_family == AF_INET6){
769                         *noip6 = 1; /* 'Host not found' for IP6 on winXP */
770                         return -1;
771                 }
772 #endif
773                 log_err("node %s:%s getaddrinfo: %s %s", 
774                         ifname?ifname:"default", port, gai_strerror(r),
775 #ifdef EAI_SYSTEM
776                         r==EAI_SYSTEM?(char*)strerror(errno):""
777 #else
778                         ""
779 #endif
780                 );
781                 return -1;
782         }
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){
792                         *noip6 = 1;
793                 }
794         } else  {
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){
798                         *noip6 = 1;
799                 }
800         }
801         freeaddrinfo(res);
802         return s;
803 }
804
805 /** make socket and first see if ifname contains port override info */
806 static int
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)
810 {
811         char* s = strchr(ifname, '@');
812         if(s) {
813                 /* override port with ifspec@port */
814                 char p[16];
815                 char newif[128];
816                 if((size_t)(s-ifname) >= sizeof(newif)) {
817                         log_err("ifname too long: %s", ifname);
818                         *noip6 = 0;
819                         return -1;
820                 }
821                 if(strlen(s+1) >= sizeof(p)) {
822                         log_err("portnumber too long: %s", ifname);
823                         *noip6 = 0;
824                         return -1;
825                 }
826                 (void)strlcpy(newif, ifname, sizeof(newif));
827                 newif[s-ifname] = 0;
828                 (void)strlcpy(p, s+1, sizeof(p));
829                 p[strlen(s+1)]=0;
830                 return make_sock(stype, newif, p, hints, v6only, noip6,
831                         rcv, snd, reuseport, transparent, tcp_mss, freebind);
832         }
833         return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd,
834                 reuseport, transparent, tcp_mss, freebind);
835 }
836
837 /**
838  * Add port to open ports list.
839  * @param list: list head. changed.
840  * @param s: fd.
841  * @param ftype: if fd is UDP.
842  * @return false on failure. list in unchanged then.
843  */
844 static int
845 port_insert(struct listen_port** list, int s, enum listen_type ftype)
846 {
847         struct listen_port* item = (struct listen_port*)malloc(
848                 sizeof(struct listen_port));
849         if(!item)
850                 return 0;
851         item->next = *list;
852         item->fd = s;
853         item->ftype = ftype;
854         *list = item;
855         return 1;
856 }
857
858 /** set fd to receive source address packet info */
859 static int
860 set_recvpktinfo(int s, int family) 
861 {
862 #if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)) || defined(IP_PKTINFO)
863         int on = 1;
864 #else
865         (void)s;
866 #endif
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",
872                                 strerror(errno));
873                         return 0;
874                 }
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",
879                                 strerror(errno));
880                         return 0;
881                 }
882 #           else
883                 log_err("no IPV6_RECVPKTINFO and no IPV6_PKTINFO option, please "
884                         "disable interface-automatic in config");
885                 return 0;
886 #           endif /* defined IPV6_RECVPKTINFO */
887
888         } else if(family == AF_INET) {
889 #           ifdef IP_PKTINFO
890                 if(setsockopt(s, IPPROTO_IP, IP_PKTINFO,
891                         (void*)&on, (socklen_t)sizeof(on)) < 0) {
892                         log_err("setsockopt(..., IP_PKTINFO, ...) failed: %s",
893                                 strerror(errno));
894                         return 0;
895                 }
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",
900                                 strerror(errno));
901                         return 0;
902                 }
903 #           else
904                 log_err("no IP_SENDSRCADDR or IP_PKTINFO option, please disable "
905                         "interface-automatic in config");
906                 return 0;
907 #           endif /* IP_PKTINFO */
908
909         }
910         return 1;
911 }
912
913 /**
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.
932  */
933 static int
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)
938 {
939         int s, noip6=0;
940         if(!do_udp && !do_tcp)
941                 return 0;
942         if(do_auto) {
943                 if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, 
944                         &noip6, rcv, snd, reuseport, transparent,
945                         tcp_mss, freebind)) == -1) {
946                         if(noip6) {
947                                 log_warn("IPv6 protocol not available");
948                                 return 1;
949                         }
950                         return 0;
951                 }
952                 /* getting source addr packet info is highly non-portable */
953                 if(!set_recvpktinfo(s, hints->ai_family)) {
954 #ifndef USE_WINSOCK
955                         close(s);
956 #else
957                         closesocket(s);
958 #endif
959                         return 0;
960                 }
961                 if(!port_insert(list, s, listen_type_udpancil)) {
962 #ifndef USE_WINSOCK
963                         close(s);
964 #else
965                         closesocket(s);
966 #endif
967                         return 0;
968                 }
969         } else if(do_udp) {
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) {
974                         if(noip6) {
975                                 log_warn("IPv6 protocol not available");
976                                 return 1;
977                         }
978                         return 0;
979                 }
980                 if(!port_insert(list, s, listen_type_udp)) {
981 #ifndef USE_WINSOCK
982                         close(s);
983 #else
984                         closesocket(s);
985 #endif
986                         return 0;
987                 }
988         }
989         if(do_tcp) {
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,
995                         freebind)) == -1) {
996                         if(noip6) {
997                                 /*log_warn("IPv6 protocol not available");*/
998                                 return 1;
999                         }
1000                         return 0;
1001                 }
1002                 if(is_ssl)
1003                         verbose(VERB_ALGO, "setup TCP for SSL service");
1004                 if(!port_insert(list, s, is_ssl?listen_type_ssl:
1005                         listen_type_tcp)) {
1006 #ifndef USE_WINSOCK
1007                         close(s);
1008 #else
1009                         closesocket(s);
1010 #endif
1011                         return 0;
1012                 }
1013         }
1014         return 1;
1015 }
1016
1017 /** 
1018  * Add items to commpoint list in front.
1019  * @param c: commpoint to add.
1020  * @param front: listen struct.
1021  * @return: false on failure.
1022  */
1023 static int
1024 listen_cp_insert(struct comm_point* c, struct listen_dnsport* front)
1025 {
1026         struct listen_list* item = (struct listen_list*)malloc(
1027                 sizeof(struct listen_list));
1028         if(!item)
1029                 return 0;
1030         item->com = c;
1031         item->next = front->cps;
1032         front->cps = item;
1033         return 1;
1034 }
1035
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)
1040 {
1041         struct listen_dnsport* front = (struct listen_dnsport*)
1042                 malloc(sizeof(struct listen_dnsport));
1043         if(!front)
1044                 return NULL;
1045         front->cps = NULL;
1046         front->udp_buff = sldns_buffer_new(bufsize);
1047         if(!front->udp_buff) {
1048                 free(front);
1049                 return NULL;
1050         }
1051
1052         /* create comm points as needed */
1053         while(ports) {
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);
1064                         cp->ssl = sslctx;
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);
1068                 if(!cp) {
1069                         log_err("can't create commpoint");      
1070                         listen_delete(front);
1071                         return NULL;
1072                 }
1073                 cp->dtenv = dtenv;
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);
1079                         return NULL;
1080                 }
1081                 ports = ports->next;
1082         }
1083         if(!front->cps) {
1084                 log_err("Could not open sockets to accept queries.");
1085                 listen_delete(front);
1086                 return NULL;
1087         }
1088
1089         return front;
1090 }
1091
1092 void
1093 listen_list_delete(struct listen_list* list)
1094 {
1095         struct listen_list *p = list, *pn;
1096         while(p) {
1097                 pn = p->next;
1098                 comm_point_delete(p->com);
1099                 free(p);
1100                 p = pn;
1101         }
1102 }
1103
1104 void 
1105 listen_delete(struct listen_dnsport* front)
1106 {
1107         if(!front) 
1108                 return;
1109         listen_list_delete(front->cps);
1110         sldns_buffer_free(front->udp_buff);
1111         free(front);
1112 }
1113
1114 struct listen_port* 
1115 listening_ports_open(struct config_file* cfg, int* reuseport)
1116 {
1117         struct listen_port* list = NULL;
1118         struct addrinfo hints;
1119         int i, do_ip4, do_ip6;
1120         int do_tcp, do_auto;
1121         char portbuf[32];
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)
1128                 do_tcp = 0;
1129
1130         /* getaddrinfo */
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;
1137 #ifndef INET6
1138         do_ip6 = 0;
1139 #endif
1140         if(!do_ip4 && !do_ip6) {
1141                 return NULL;
1142         }
1143         /* create ip4 and ip6 ports so that return addresses are nice. */
1144         if(do_auto || cfg->num_ifs == 0) {
1145                 if(do_ip6) {
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);
1155                                 return NULL;
1156                         }
1157                 }
1158                 if(do_ip4) {
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);
1168                                 return NULL;
1169                         }
1170                 }
1171         } else for(i = 0; i<cfg->num_ifs; i++) {
1172                 if(str_is_ip6(cfg->ifs[i])) {
1173                         if(!do_ip6)
1174                                 continue;
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);
1183                                 return NULL;
1184                         }
1185                 } else {
1186                         if(!do_ip4)
1187                                 continue;
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);
1196                                 return NULL;
1197                         }
1198                 }
1199         }
1200         return list;
1201 }
1202
1203 void listening_ports_free(struct listen_port* list)
1204 {
1205         struct listen_port* nx;
1206         while(list) {
1207                 nx = list->next;
1208                 if(list->fd != -1) {
1209 #ifndef USE_WINSOCK
1210                         close(list->fd);
1211 #else
1212                         closesocket(list->fd);
1213 #endif
1214                 }
1215                 free(list);
1216                 list = nx;
1217         }
1218 }
1219
1220 size_t listen_get_mem(struct listen_dnsport* listen)
1221 {
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) {
1227                 s += sizeof(*p);
1228                 s += comm_point_get_mem(p->com);
1229         }
1230         return s;
1231 }
1232
1233 void listen_stop_accept(struct listen_dnsport* listen)
1234 {
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);
1242                 }
1243         }
1244 }
1245
1246 void listen_start_accept(struct listen_dnsport* listen)
1247 {
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);
1255                 }
1256         }
1257 }
1258