]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/unbound/services/listen_dnsport.c
Reintegrate head revisions r273096-r277147
[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 #include "services/listen_dnsport.h"
47 #include "services/outside_network.h"
48 #include "util/netevent.h"
49 #include "util/log.h"
50 #include "util/config_file.h"
51 #include "util/net_help.h"
52 #include "ldns/sbuffer.h"
53
54 #ifdef HAVE_NETDB_H
55 #include <netdb.h>
56 #endif
57 #include <fcntl.h>
58
59 #ifdef HAVE_SYS_UN_H
60 #include <sys/un.h>
61 #endif
62
63 /** number of queued TCP connections for listen() */
64 #define TCP_BACKLOG 256 
65
66 /**
67  * Debug print of the getaddrinfo returned address.
68  * @param addr: the address returned.
69  */
70 static void
71 verbose_print_addr(struct addrinfo *addr)
72 {
73         if(verbosity >= VERB_ALGO) {
74                 char buf[100];
75                 void* sinaddr = &((struct sockaddr_in*)addr->ai_addr)->sin_addr;
76 #ifdef INET6
77                 if(addr->ai_family == AF_INET6)
78                         sinaddr = &((struct sockaddr_in6*)addr->ai_addr)->
79                                 sin6_addr;
80 #endif /* INET6 */
81                 if(inet_ntop(addr->ai_family, sinaddr, buf,
82                         (socklen_t)sizeof(buf)) == 0) {
83                         (void)strlcpy(buf, "(null)", sizeof(buf));
84                 }
85                 buf[sizeof(buf)-1] = 0;
86                 verbose(VERB_ALGO, "creating %s%s socket %s %d", 
87                         addr->ai_socktype==SOCK_DGRAM?"udp":
88                         addr->ai_socktype==SOCK_STREAM?"tcp":"otherproto",
89                         addr->ai_family==AF_INET?"4":
90                         addr->ai_family==AF_INET6?"6":
91                         "_otherfam", buf, 
92                         ntohs(((struct sockaddr_in*)addr->ai_addr)->sin_port));
93         }
94 }
95
96 int
97 create_udp_sock(int family, int socktype, struct sockaddr* addr,
98         socklen_t addrlen, int v6only, int* inuse, int* noproto,
99         int rcv, int snd, int listen, int* reuseport)
100 {
101         int s;
102 #if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU)
103         int on=1;
104 #endif
105 #ifdef IPV6_MTU
106         int mtu = IPV6_MIN_MTU;
107 #endif
108 #if !defined(SO_RCVBUFFORCE) && !defined(SO_RCVBUF)
109         (void)rcv;
110 #endif
111 #if !defined(SO_SNDBUFFORCE) && !defined(SO_SNDBUF)
112         (void)snd;
113 #endif
114 #ifndef IPV6_V6ONLY
115         (void)v6only;
116 #endif
117         if((s = socket(family, socktype, 0)) == -1) {
118                 *inuse = 0;
119 #ifndef USE_WINSOCK
120                 if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
121                         *noproto = 1;
122                         return -1;
123                 }
124                 log_err("can't create socket: %s", strerror(errno));
125 #else
126                 if(WSAGetLastError() == WSAEAFNOSUPPORT || 
127                         WSAGetLastError() == WSAEPROTONOSUPPORT) {
128                         *noproto = 1;
129                         return -1;
130                 }
131                 log_err("can't create socket: %s", 
132                         wsa_strerror(WSAGetLastError()));
133 #endif
134                 *noproto = 0;
135                 return -1;
136         }
137         if(listen) {
138 #ifdef SO_REUSEADDR
139                 if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, 
140                         (socklen_t)sizeof(on)) < 0) {
141 #ifndef USE_WINSOCK
142                         log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
143                                 strerror(errno));
144                         if(errno != ENOSYS) {
145                                 close(s);
146                                 *noproto = 0;
147                                 *inuse = 0;
148                                 return -1;
149                         }
150 #else
151                         log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
152                                 wsa_strerror(WSAGetLastError()));
153                         closesocket(s);
154                         *noproto = 0;
155                         *inuse = 0;
156                         return -1;
157 #endif
158                 }
159 #endif /* SO_REUSEADDR */
160 #ifdef SO_REUSEPORT
161                 /* try to set SO_REUSEPORT so that incoming
162                  * queries are distributed evenly among the receiving threads.
163                  * Each thread must have its own socket bound to the same port,
164                  * with SO_REUSEPORT set on each socket.
165                  */
166                 if (reuseport && *reuseport &&
167                     setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on,
168                         (socklen_t)sizeof(on)) < 0) {
169 #ifdef ENOPROTOOPT
170                         if(errno != ENOPROTOOPT || verbosity >= 3)
171                                 log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s",
172                                         strerror(errno));
173 #endif
174                         /* this option is not essential, we can continue */
175                         *reuseport = 0;
176                 }
177 #else
178                 (void)reuseport;
179 #endif /* defined(SO_REUSEPORT) */
180         }
181         if(rcv) {
182 #ifdef SO_RCVBUF
183                 int got;
184                 socklen_t slen = (socklen_t)sizeof(got);
185 #  ifdef SO_RCVBUFFORCE
186                 /* Linux specific: try to use root permission to override
187                  * system limits on rcvbuf. The limit is stored in 
188                  * /proc/sys/net/core/rmem_max or sysctl net.core.rmem_max */
189                 if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv, 
190                         (socklen_t)sizeof(rcv)) < 0) {
191                         if(errno != EPERM) {
192 #    ifndef USE_WINSOCK
193                                 log_err("setsockopt(..., SO_RCVBUFFORCE, "
194                                         "...) failed: %s", strerror(errno));
195                                 close(s);
196 #    else
197                                 log_err("setsockopt(..., SO_RCVBUFFORCE, "
198                                         "...) failed: %s", 
199                                         wsa_strerror(WSAGetLastError()));
200                                 closesocket(s);
201 #    endif
202                                 *noproto = 0;
203                                 *inuse = 0;
204                                 return -1;
205                         }
206 #  endif /* SO_RCVBUFFORCE */
207                         if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv, 
208                                 (socklen_t)sizeof(rcv)) < 0) {
209 #  ifndef USE_WINSOCK
210                                 log_err("setsockopt(..., SO_RCVBUF, "
211                                         "...) failed: %s", strerror(errno));
212                                 close(s);
213 #  else
214                                 log_err("setsockopt(..., SO_RCVBUF, "
215                                         "...) failed: %s", 
216                                         wsa_strerror(WSAGetLastError()));
217                                 closesocket(s);
218 #  endif
219                                 *noproto = 0;
220                                 *inuse = 0;
221                                 return -1;
222                         }
223                         /* check if we got the right thing or if system
224                          * reduced to some system max.  Warn if so */
225                         if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&got, 
226                                 &slen) >= 0 && got < rcv/2) {
227                                 log_warn("so-rcvbuf %u was not granted. "
228                                         "Got %u. To fix: start with "
229                                         "root permissions(linux) or sysctl "
230                                         "bigger net.core.rmem_max(linux) or "
231                                         "kern.ipc.maxsockbuf(bsd) values.",
232                                         (unsigned)rcv, (unsigned)got);
233                         }
234 #  ifdef SO_RCVBUFFORCE
235                 }
236 #  endif
237 #endif /* SO_RCVBUF */
238         }
239         /* first do RCVBUF as the receive buffer is more important */
240         if(snd) {
241 #ifdef SO_SNDBUF
242                 int got;
243                 socklen_t slen = (socklen_t)sizeof(got);
244 #  ifdef SO_SNDBUFFORCE
245                 /* Linux specific: try to use root permission to override
246                  * system limits on sndbuf. The limit is stored in 
247                  * /proc/sys/net/core/wmem_max or sysctl net.core.wmem_max */
248                 if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd, 
249                         (socklen_t)sizeof(snd)) < 0) {
250                         if(errno != EPERM) {
251 #    ifndef USE_WINSOCK
252                                 log_err("setsockopt(..., SO_SNDBUFFORCE, "
253                                         "...) failed: %s", strerror(errno));
254                                 close(s);
255 #    else
256                                 log_err("setsockopt(..., SO_SNDBUFFORCE, "
257                                         "...) failed: %s", 
258                                         wsa_strerror(WSAGetLastError()));
259                                 closesocket(s);
260 #    endif
261                                 *noproto = 0;
262                                 *inuse = 0;
263                                 return -1;
264                         }
265 #  endif /* SO_SNDBUFFORCE */
266                         if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd, 
267                                 (socklen_t)sizeof(snd)) < 0) {
268 #  ifndef USE_WINSOCK
269                                 log_err("setsockopt(..., SO_SNDBUF, "
270                                         "...) failed: %s", strerror(errno));
271                                 close(s);
272 #  else
273                                 log_err("setsockopt(..., SO_SNDBUF, "
274                                         "...) failed: %s", 
275                                         wsa_strerror(WSAGetLastError()));
276                                 closesocket(s);
277 #  endif
278                                 *noproto = 0;
279                                 *inuse = 0;
280                                 return -1;
281                         }
282                         /* check if we got the right thing or if system
283                          * reduced to some system max.  Warn if so */
284                         if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got, 
285                                 &slen) >= 0 && got < snd/2) {
286                                 log_warn("so-sndbuf %u was not granted. "
287                                         "Got %u. To fix: start with "
288                                         "root permissions(linux) or sysctl "
289                                         "bigger net.core.wmem_max(linux) or "
290                                         "kern.ipc.maxsockbuf(bsd) values.",
291                                         (unsigned)snd, (unsigned)got);
292                         }
293 #  ifdef SO_SNDBUFFORCE
294                 }
295 #  endif
296 #endif /* SO_SNDBUF */
297         }
298         if(family == AF_INET6) {
299 # if defined(IPV6_V6ONLY)
300                 if(v6only) {
301                         int val=(v6only==2)?0:1;
302                         if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, 
303                                 (void*)&val, (socklen_t)sizeof(val)) < 0) {
304 #ifndef USE_WINSOCK
305                                 log_err("setsockopt(..., IPV6_V6ONLY"
306                                         ", ...) failed: %s", strerror(errno));
307                                 close(s);
308 #else
309                                 log_err("setsockopt(..., IPV6_V6ONLY"
310                                         ", ...) failed: %s", 
311                                         wsa_strerror(WSAGetLastError()));
312                                 closesocket(s);
313 #endif
314                                 *noproto = 0;
315                                 *inuse = 0;
316                                 return -1;
317                         }
318                 }
319 # endif
320 # if defined(IPV6_USE_MIN_MTU)
321                 /*
322                  * There is no fragmentation of IPv6 datagrams
323                  * during forwarding in the network. Therefore
324                  * we do not send UDP datagrams larger than
325                  * the minimum IPv6 MTU of 1280 octets. The
326                  * EDNS0 message length can be larger if the
327                  * network stack supports IPV6_USE_MIN_MTU.
328                  */
329                 if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
330                         (void*)&on, (socklen_t)sizeof(on)) < 0) {
331 #  ifndef USE_WINSOCK
332                         log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
333                                 "...) failed: %s", strerror(errno));
334                         close(s);
335 #  else
336                         log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
337                                 "...) failed: %s", 
338                                 wsa_strerror(WSAGetLastError()));
339                         closesocket(s);
340 #  endif
341                         *noproto = 0;
342                         *inuse = 0;
343                         return -1;
344                 }
345 # elif defined(IPV6_MTU)
346                 /*
347                  * On Linux, to send no larger than 1280, the PMTUD is
348                  * disabled by default for datagrams anyway, so we set
349                  * the MTU to use.
350                  */
351                 if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU,
352                         (void*)&mtu, (socklen_t)sizeof(mtu)) < 0) {
353 #  ifndef USE_WINSOCK
354                         log_err("setsockopt(..., IPV6_MTU, ...) failed: %s", 
355                                 strerror(errno));
356                         close(s);
357 #  else
358                         log_err("setsockopt(..., IPV6_MTU, ...) failed: %s", 
359                                 wsa_strerror(WSAGetLastError()));
360                         closesocket(s);
361 #  endif
362                         *noproto = 0;
363                         *inuse = 0;
364                         return -1;
365                 }
366 # endif /* IPv6 MTU */
367         } else if(family == AF_INET) {
368 #  if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
369 /* linux 3.15 has IP_PMTUDISC_OMIT, Hannes Frederic Sowa made it so that
370  * PMTU information is not accepted, but fragmentation is allowed
371  * if and only if the packet size exceeds the outgoing interface MTU
372  * (and also uses the interface mtu to determine the size of the packets).
373  * So there won't be any EMSGSIZE error.  Against DNS fragmentation attacks.
374  * FreeBSD already has same semantics without setting the option. */
375 #    if defined(IP_PMTUDISC_OMIT)
376                 int action = IP_PMTUDISC_OMIT;
377 #    else
378                 int action = IP_PMTUDISC_DONT;
379 #    endif
380                 if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, 
381                         &action, (socklen_t)sizeof(action)) < 0) {
382                         log_err("setsockopt(..., IP_MTU_DISCOVER, "
383 #    if defined(IP_PMTUDISC_OMIT)
384                                 "IP_PMTUDISC_OMIT"
385 #    else
386                                 "IP_PMTUDISC_DONT"
387 #    endif
388                                 "...) failed: %s",
389                                 strerror(errno));
390 #    ifndef USE_WINSOCK
391                         close(s);
392 #    else
393                         closesocket(s);
394 #    endif
395                         *noproto = 0;
396                         *inuse = 0;
397                         return -1;
398                 }
399 #  elif defined(IP_DONTFRAG)
400                 int off = 0;
401                 if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG, 
402                         &off, (socklen_t)sizeof(off)) < 0) {
403                         log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
404                                 strerror(errno));
405 #    ifndef USE_WINSOCK
406                         close(s);
407 #    else
408                         closesocket(s);
409 #    endif
410                         *noproto = 0;
411                         *inuse = 0;
412                         return -1;
413                 }
414 #  endif /* IPv4 MTU */
415         }
416         if(bind(s, (struct sockaddr*)addr, addrlen) != 0) {
417                 *noproto = 0;
418                 *inuse = 0;
419 #ifndef USE_WINSOCK
420 #ifdef EADDRINUSE
421                 *inuse = (errno == EADDRINUSE);
422                 /* detect freebsd jail with no ipv6 permission */
423                 if(family==AF_INET6 && errno==EINVAL)
424                         *noproto = 1;
425                 else if(errno != EADDRINUSE) {
426                         log_err_addr("can't bind socket", strerror(errno),
427                                 (struct sockaddr_storage*)addr, addrlen);
428                 }
429 #endif /* EADDRINUSE */
430                 close(s);
431 #else /* USE_WINSOCK */
432                 if(WSAGetLastError() != WSAEADDRINUSE &&
433                         WSAGetLastError() != WSAEADDRNOTAVAIL) {
434                         log_err_addr("can't bind socket", 
435                                 wsa_strerror(WSAGetLastError()),
436                                 (struct sockaddr_storage*)addr, addrlen);
437                 }
438                 closesocket(s);
439 #endif
440                 return -1;
441         }
442         if(!fd_set_nonblock(s)) {
443                 *noproto = 0;
444                 *inuse = 0;
445 #ifndef USE_WINSOCK
446                 close(s);
447 #else
448                 closesocket(s);
449 #endif
450                 return -1;
451         }
452         return s;
453 }
454
455 int
456 create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
457         int* reuseport)
458 {
459         int s;
460 #if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY)
461         int on = 1;
462 #endif /* SO_REUSEADDR || IPV6_V6ONLY */
463         verbose_print_addr(addr);
464         *noproto = 0;
465         if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
466 #ifndef USE_WINSOCK
467                 if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
468                         *noproto = 1;
469                         return -1;
470                 }
471                 log_err("can't create socket: %s", strerror(errno));
472 #else
473                 if(WSAGetLastError() == WSAEAFNOSUPPORT ||
474                         WSAGetLastError() == WSAEPROTONOSUPPORT) {
475                         *noproto = 1;
476                         return -1;
477                 }
478                 log_err("can't create socket: %s", 
479                         wsa_strerror(WSAGetLastError()));
480 #endif
481                 return -1;
482         }
483 #ifdef SO_REUSEADDR
484         if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, 
485                 (socklen_t)sizeof(on)) < 0) {
486 #ifndef USE_WINSOCK
487                 log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
488                         strerror(errno));
489                 close(s);
490 #else
491                 log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
492                         wsa_strerror(WSAGetLastError()));
493                 closesocket(s);
494 #endif
495                 return -1;
496         }
497 #endif /* SO_REUSEADDR */
498 #ifdef SO_REUSEPORT
499         /* try to set SO_REUSEPORT so that incoming
500          * connections are distributed evenly among the receiving threads.
501          * Each thread must have its own socket bound to the same port,
502          * with SO_REUSEPORT set on each socket.
503          */
504         if (reuseport && *reuseport &&
505                 setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on,
506                 (socklen_t)sizeof(on)) < 0) {
507 #ifdef ENOPROTOOPT
508                 if(errno != ENOPROTOOPT || verbosity >= 3)
509                         log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s",
510                                 strerror(errno));
511 #endif
512                 /* this option is not essential, we can continue */
513                 *reuseport = 0;
514         }
515 #else
516         (void)reuseport;
517 #endif /* defined(SO_REUSEPORT) */
518 #if defined(IPV6_V6ONLY)
519         if(addr->ai_family == AF_INET6 && v6only) {
520                 if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, 
521                         (void*)&on, (socklen_t)sizeof(on)) < 0) {
522 #ifndef USE_WINSOCK
523                         log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
524                                 strerror(errno));
525                         close(s);
526 #else
527                         log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
528                                 wsa_strerror(WSAGetLastError()));
529                         closesocket(s);
530 #endif
531                         return -1;
532                 }
533         }
534 #else
535         (void)v6only;
536 #endif /* IPV6_V6ONLY */
537         if(bind(s, addr->ai_addr, addr->ai_addrlen) != 0) {
538 #ifndef USE_WINSOCK
539                 /* detect freebsd jail with no ipv6 permission */
540                 if(addr->ai_family==AF_INET6 && errno==EINVAL)
541                         *noproto = 1;
542                 else {
543                         log_err_addr("can't bind socket", strerror(errno),
544                                 (struct sockaddr_storage*)addr->ai_addr,
545                                 addr->ai_addrlen);
546                 }
547                 close(s);
548 #else
549                 log_err_addr("can't bind socket", 
550                         wsa_strerror(WSAGetLastError()),
551                         (struct sockaddr_storage*)addr->ai_addr,
552                         addr->ai_addrlen);
553                 closesocket(s);
554 #endif
555                 return -1;
556         }
557         if(!fd_set_nonblock(s)) {
558 #ifndef USE_WINSOCK
559                 close(s);
560 #else
561                 closesocket(s);
562 #endif
563                 return -1;
564         }
565         if(listen(s, TCP_BACKLOG) == -1) {
566 #ifndef USE_WINSOCK
567                 log_err("can't listen: %s", strerror(errno));
568                 close(s);
569 #else
570                 log_err("can't listen: %s", wsa_strerror(WSAGetLastError()));
571                 closesocket(s);
572 #endif
573                 return -1;
574         }
575         return s;
576 }
577
578 int
579 create_local_accept_sock(const char *path, int* noproto)
580 {
581 #ifdef HAVE_SYS_UN_H
582         int s;
583         struct sockaddr_un sun;
584
585 #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
586         /* this member exists on BSDs, not Linux */
587         sun.sun_len = (sa_family_t)sizeof(sun);
588 #endif
589         sun.sun_family = AF_LOCAL;
590         /* length is 92-108, 104 on FreeBSD */
591         (void)strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
592
593         if ((s = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1) {
594                 log_err("Cannot create local socket %s (%s)",
595                         path, strerror(errno));
596                 return -1;
597         }
598
599         if (unlink(path) && errno != ENOENT) {
600                 /* The socket already exists and cannot be removed */
601                 log_err("Cannot remove old local socket %s (%s)",
602                         path, strerror(errno));
603                 return -1;
604         }
605
606         if (bind(s, (struct sockaddr *)&sun,
607                 (socklen_t)sizeof(struct sockaddr_un)) == -1) {
608                 log_err("Cannot bind local socket %s (%s)",
609                         path, strerror(errno));
610                 return -1;
611         }
612
613         if (!fd_set_nonblock(s)) {
614                 log_err("Cannot set non-blocking mode");
615                 return -1;
616         }
617
618         if (listen(s, TCP_BACKLOG) == -1) {
619                 log_err("can't listen: %s", strerror(errno));
620                 return -1;
621         }
622
623         (void)noproto; /*unused*/
624         return s;
625 #else
626         log_err("Local sockets are not supported");
627         *noproto = 1;
628         return -1;
629 #endif
630 }
631
632
633 /**
634  * Create socket from getaddrinfo results
635  */
636 static int
637 make_sock(int stype, const char* ifname, const char* port, 
638         struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
639         int* reuseport)
640 {
641         struct addrinfo *res = NULL;
642         int r, s, inuse, noproto;
643         hints->ai_socktype = stype;
644         *noip6 = 0;
645         if((r=getaddrinfo(ifname, port, hints, &res)) != 0 || !res) {
646 #ifdef USE_WINSOCK
647                 if(r == EAI_NONAME && hints->ai_family == AF_INET6){
648                         *noip6 = 1; /* 'Host not found' for IP6 on winXP */
649                         return -1;
650                 }
651 #endif
652                 log_err("node %s:%s getaddrinfo: %s %s", 
653                         ifname?ifname:"default", port, gai_strerror(r),
654 #ifdef EAI_SYSTEM
655                         r==EAI_SYSTEM?(char*)strerror(errno):""
656 #else
657                         ""
658 #endif
659                 );
660                 return -1;
661         }
662         if(stype == SOCK_DGRAM) {
663                 verbose_print_addr(res);
664                 s = create_udp_sock(res->ai_family, res->ai_socktype,
665                         (struct sockaddr*)res->ai_addr, res->ai_addrlen,
666                         v6only, &inuse, &noproto, (int)rcv, (int)snd, 1,
667                         reuseport);
668                 if(s == -1 && inuse) {
669                         log_err("bind: address already in use");
670                 } else if(s == -1 && noproto && hints->ai_family == AF_INET6){
671                         *noip6 = 1;
672                 }
673         } else  {
674                 s = create_tcp_accept_sock(res, v6only, &noproto, reuseport);
675                 if(s == -1 && noproto && hints->ai_family == AF_INET6){
676                         *noip6 = 1;
677                 }
678         }
679         freeaddrinfo(res);
680         return s;
681 }
682
683 /** make socket and first see if ifname contains port override info */
684 static int
685 make_sock_port(int stype, const char* ifname, const char* port, 
686         struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
687         int* reuseport)
688 {
689         char* s = strchr(ifname, '@');
690         if(s) {
691                 /* override port with ifspec@port */
692                 char p[16];
693                 char newif[128];
694                 if((size_t)(s-ifname) >= sizeof(newif)) {
695                         log_err("ifname too long: %s", ifname);
696                         *noip6 = 0;
697                         return -1;
698                 }
699                 if(strlen(s+1) >= sizeof(p)) {
700                         log_err("portnumber too long: %s", ifname);
701                         *noip6 = 0;
702                         return -1;
703                 }
704                 (void)strlcpy(newif, ifname, sizeof(newif));
705                 newif[s-ifname] = 0;
706                 (void)strlcpy(p, s+1, sizeof(p));
707                 p[strlen(s+1)]=0;
708                 return make_sock(stype, newif, p, hints, v6only, noip6,
709                         rcv, snd, reuseport);
710         }
711         return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd,
712                 reuseport);
713 }
714
715 /**
716  * Add port to open ports list.
717  * @param list: list head. changed.
718  * @param s: fd.
719  * @param ftype: if fd is UDP.
720  * @return false on failure. list in unchanged then.
721  */
722 static int
723 port_insert(struct listen_port** list, int s, enum listen_type ftype)
724 {
725         struct listen_port* item = (struct listen_port*)malloc(
726                 sizeof(struct listen_port));
727         if(!item)
728                 return 0;
729         item->next = *list;
730         item->fd = s;
731         item->ftype = ftype;
732         *list = item;
733         return 1;
734 }
735
736 /** set fd to receive source address packet info */
737 static int
738 set_recvpktinfo(int s, int family) 
739 {
740 #if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)) || defined(IP_PKTINFO)
741         int on = 1;
742 #else
743         (void)s;
744 #endif
745         if(family == AF_INET6) {
746 #           ifdef IPV6_RECVPKTINFO
747                 if(setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
748                         (void*)&on, (socklen_t)sizeof(on)) < 0) {
749                         log_err("setsockopt(..., IPV6_RECVPKTINFO, ...) failed: %s",
750                                 strerror(errno));
751                         return 0;
752                 }
753 #           elif defined(IPV6_PKTINFO)
754                 if(setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO,
755                         (void*)&on, (socklen_t)sizeof(on)) < 0) {
756                         log_err("setsockopt(..., IPV6_PKTINFO, ...) failed: %s",
757                                 strerror(errno));
758                         return 0;
759                 }
760 #           else
761                 log_err("no IPV6_RECVPKTINFO and no IPV6_PKTINFO option, please "
762                         "disable interface-automatic in config");
763                 return 0;
764 #           endif /* defined IPV6_RECVPKTINFO */
765
766         } else if(family == AF_INET) {
767 #           ifdef IP_PKTINFO
768                 if(setsockopt(s, IPPROTO_IP, IP_PKTINFO,
769                         (void*)&on, (socklen_t)sizeof(on)) < 0) {
770                         log_err("setsockopt(..., IP_PKTINFO, ...) failed: %s",
771                                 strerror(errno));
772                         return 0;
773                 }
774 #           elif defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)
775                 if(setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
776                         (void*)&on, (socklen_t)sizeof(on)) < 0) {
777                         log_err("setsockopt(..., IP_RECVDSTADDR, ...) failed: %s",
778                                 strerror(errno));
779                         return 0;
780                 }
781 #           else
782                 log_err("no IP_SENDSRCADDR or IP_PKTINFO option, please disable "
783                         "interface-automatic in config");
784                 return 0;
785 #           endif /* IP_PKTINFO */
786
787         }
788         return 1;
789 }
790
791 /**
792  * Helper for ports_open. Creates one interface (or NULL for default).
793  * @param ifname: The interface ip address.
794  * @param do_auto: use automatic interface detection.
795  *      If enabled, then ifname must be the wildcard name.
796  * @param do_udp: if udp should be used.
797  * @param do_tcp: if udp should be used.
798  * @param hints: for getaddrinfo. family and flags have to be set by caller.
799  * @param port: Port number to use (as string).
800  * @param list: list of open ports, appended to, changed to point to list head.
801  * @param rcv: receive buffer size for UDP
802  * @param snd: send buffer size for UDP
803  * @param ssl_port: ssl service port number
804  * @param reuseport: try to set SO_REUSEPORT if nonNULL and true.
805  *      set to false on exit if reuseport failed due to no kernel support.
806  * @return: returns false on error.
807  */
808 static int
809 ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, 
810         struct addrinfo *hints, const char* port, struct listen_port** list,
811         size_t rcv, size_t snd, int ssl_port, int* reuseport)
812 {
813         int s, noip6=0;
814         if(!do_udp && !do_tcp)
815                 return 0;
816         if(do_auto) {
817                 if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, 
818                         &noip6, rcv, snd, reuseport)) == -1) {
819                         if(noip6) {
820                                 log_warn("IPv6 protocol not available");
821                                 return 1;
822                         }
823                         return 0;
824                 }
825                 /* getting source addr packet info is highly non-portable */
826                 if(!set_recvpktinfo(s, hints->ai_family)) {
827 #ifndef USE_WINSOCK
828                         close(s);
829 #else
830                         closesocket(s);
831 #endif
832                         return 0;
833                 }
834                 if(!port_insert(list, s, listen_type_udpancil)) {
835 #ifndef USE_WINSOCK
836                         close(s);
837 #else
838                         closesocket(s);
839 #endif
840                         return 0;
841                 }
842         } else if(do_udp) {
843                 /* regular udp socket */
844                 if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, 
845                         &noip6, rcv, snd, reuseport)) == -1) {
846                         if(noip6) {
847                                 log_warn("IPv6 protocol not available");
848                                 return 1;
849                         }
850                         return 0;
851                 }
852                 if(!port_insert(list, s, listen_type_udp)) {
853 #ifndef USE_WINSOCK
854                         close(s);
855 #else
856                         closesocket(s);
857 #endif
858                         return 0;
859                 }
860         }
861         if(do_tcp) {
862                 int is_ssl = ((strchr(ifname, '@') && 
863                         atoi(strchr(ifname, '@')+1) == ssl_port) ||
864                         (!strchr(ifname, '@') && atoi(port) == ssl_port));
865                 if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1, 
866                         &noip6, 0, 0, reuseport)) == -1) {
867                         if(noip6) {
868                                 /*log_warn("IPv6 protocol not available");*/
869                                 return 1;
870                         }
871                         return 0;
872                 }
873                 if(is_ssl)
874                         verbose(VERB_ALGO, "setup TCP for SSL service");
875                 if(!port_insert(list, s, is_ssl?listen_type_ssl:
876                         listen_type_tcp)) {
877 #ifndef USE_WINSOCK
878                         close(s);
879 #else
880                         closesocket(s);
881 #endif
882                         return 0;
883                 }
884         }
885         return 1;
886 }
887
888 /** 
889  * Add items to commpoint list in front.
890  * @param c: commpoint to add.
891  * @param front: listen struct.
892  * @return: false on failure.
893  */
894 static int
895 listen_cp_insert(struct comm_point* c, struct listen_dnsport* front)
896 {
897         struct listen_list* item = (struct listen_list*)malloc(
898                 sizeof(struct listen_list));
899         if(!item)
900                 return 0;
901         item->com = c;
902         item->next = front->cps;
903         front->cps = item;
904         return 1;
905 }
906
907 struct listen_dnsport* 
908 listen_create(struct comm_base* base, struct listen_port* ports,
909         size_t bufsize, int tcp_accept_count, void* sslctx,
910         struct dt_env* dtenv, comm_point_callback_t* cb, void *cb_arg)
911 {
912         struct listen_dnsport* front = (struct listen_dnsport*)
913                 malloc(sizeof(struct listen_dnsport));
914         if(!front)
915                 return NULL;
916         front->cps = NULL;
917         front->udp_buff = sldns_buffer_new(bufsize);
918         if(!front->udp_buff) {
919                 free(front);
920                 return NULL;
921         }
922
923         /* create comm points as needed */
924         while(ports) {
925                 struct comm_point* cp = NULL;
926                 if(ports->ftype == listen_type_udp) 
927                         cp = comm_point_create_udp(base, ports->fd, 
928                                 front->udp_buff, cb, cb_arg);
929                 else if(ports->ftype == listen_type_tcp)
930                         cp = comm_point_create_tcp(base, ports->fd, 
931                                 tcp_accept_count, bufsize, cb, cb_arg);
932                 else if(ports->ftype == listen_type_ssl) {
933                         cp = comm_point_create_tcp(base, ports->fd, 
934                                 tcp_accept_count, bufsize, cb, cb_arg);
935                         cp->ssl = sslctx;
936                 } else if(ports->ftype == listen_type_udpancil) 
937                         cp = comm_point_create_udp_ancil(base, ports->fd, 
938                                 front->udp_buff, cb, cb_arg);
939                 if(!cp) {
940                         log_err("can't create commpoint");      
941                         listen_delete(front);
942                         return NULL;
943                 }
944                 cp->dtenv = dtenv;
945                 cp->do_not_close = 1;
946                 if(!listen_cp_insert(cp, front)) {
947                         log_err("malloc failed");
948                         comm_point_delete(cp);
949                         listen_delete(front);
950                         return NULL;
951                 }
952                 ports = ports->next;
953         }
954         if(!front->cps) {
955                 log_err("Could not open sockets to accept queries.");
956                 listen_delete(front);
957                 return NULL;
958         }
959
960         return front;
961 }
962
963 void
964 listen_list_delete(struct listen_list* list)
965 {
966         struct listen_list *p = list, *pn;
967         while(p) {
968                 pn = p->next;
969                 comm_point_delete(p->com);
970                 free(p);
971                 p = pn;
972         }
973 }
974
975 void 
976 listen_delete(struct listen_dnsport* front)
977 {
978         if(!front) 
979                 return;
980         listen_list_delete(front->cps);
981         sldns_buffer_free(front->udp_buff);
982         free(front);
983 }
984
985 struct listen_port* 
986 listening_ports_open(struct config_file* cfg, int* reuseport)
987 {
988         struct listen_port* list = NULL;
989         struct addrinfo hints;
990         int i, do_ip4, do_ip6;
991         int do_tcp, do_auto;
992         char portbuf[32];
993         snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
994         do_ip4 = cfg->do_ip4;
995         do_ip6 = cfg->do_ip6;
996         do_tcp = cfg->do_tcp;
997         do_auto = cfg->if_automatic && cfg->do_udp;
998         if(cfg->incoming_num_tcp == 0)
999                 do_tcp = 0;
1000
1001         /* getaddrinfo */
1002         memset(&hints, 0, sizeof(hints));
1003         hints.ai_flags = AI_PASSIVE;
1004         /* no name lookups on our listening ports */
1005         if(cfg->num_ifs > 0)
1006                 hints.ai_flags |= AI_NUMERICHOST;
1007         hints.ai_family = AF_UNSPEC;
1008 #ifndef INET6
1009         do_ip6 = 0;
1010 #endif
1011         if(!do_ip4 && !do_ip6) {
1012                 return NULL;
1013         }
1014         /* create ip4 and ip6 ports so that return addresses are nice. */
1015         if(do_auto || cfg->num_ifs == 0) {
1016                 if(do_ip6) {
1017                         hints.ai_family = AF_INET6;
1018                         if(!ports_create_if(do_auto?"::0":"::1", 
1019                                 do_auto, cfg->do_udp, do_tcp, 
1020                                 &hints, portbuf, &list,
1021                                 cfg->so_rcvbuf, cfg->so_sndbuf,
1022                                 cfg->ssl_port, reuseport)) {
1023                                 listening_ports_free(list);
1024                                 return NULL;
1025                         }
1026                 }
1027                 if(do_ip4) {
1028                         hints.ai_family = AF_INET;
1029                         if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1", 
1030                                 do_auto, cfg->do_udp, do_tcp, 
1031                                 &hints, portbuf, &list,
1032                                 cfg->so_rcvbuf, cfg->so_sndbuf,
1033                                 cfg->ssl_port, reuseport)) {
1034                                 listening_ports_free(list);
1035                                 return NULL;
1036                         }
1037                 }
1038         } else for(i = 0; i<cfg->num_ifs; i++) {
1039                 if(str_is_ip6(cfg->ifs[i])) {
1040                         if(!do_ip6)
1041                                 continue;
1042                         hints.ai_family = AF_INET6;
1043                         if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp, 
1044                                 do_tcp, &hints, portbuf, &list, 
1045                                 cfg->so_rcvbuf, cfg->so_sndbuf,
1046                                 cfg->ssl_port, reuseport)) {
1047                                 listening_ports_free(list);
1048                                 return NULL;
1049                         }
1050                 } else {
1051                         if(!do_ip4)
1052                                 continue;
1053                         hints.ai_family = AF_INET;
1054                         if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp, 
1055                                 do_tcp, &hints, portbuf, &list, 
1056                                 cfg->so_rcvbuf, cfg->so_sndbuf,
1057                                 cfg->ssl_port, reuseport)) {
1058                                 listening_ports_free(list);
1059                                 return NULL;
1060                         }
1061                 }
1062         }
1063         return list;
1064 }
1065
1066 void listening_ports_free(struct listen_port* list)
1067 {
1068         struct listen_port* nx;
1069         while(list) {
1070                 nx = list->next;
1071                 if(list->fd != -1) {
1072 #ifndef USE_WINSOCK
1073                         close(list->fd);
1074 #else
1075                         closesocket(list->fd);
1076 #endif
1077                 }
1078                 free(list);
1079                 list = nx;
1080         }
1081 }
1082
1083 size_t listen_get_mem(struct listen_dnsport* listen)
1084 {
1085         size_t s = sizeof(*listen) + sizeof(*listen->base) + 
1086                 sizeof(*listen->udp_buff) + 
1087                 sldns_buffer_capacity(listen->udp_buff);
1088         struct listen_list* p;
1089         for(p = listen->cps; p; p = p->next) {
1090                 s += sizeof(*p);
1091                 s += comm_point_get_mem(p->com);
1092         }
1093         return s;
1094 }
1095
1096 void listen_stop_accept(struct listen_dnsport* listen)
1097 {
1098         /* do not stop the ones that have no tcp_free list
1099          * (they have already stopped listening) */
1100         struct listen_list* p;
1101         for(p=listen->cps; p; p=p->next) {
1102                 if(p->com->type == comm_tcp_accept &&
1103                         p->com->tcp_free != NULL) {
1104                         comm_point_stop_listening(p->com);
1105                 }
1106         }
1107 }
1108
1109 void listen_start_accept(struct listen_dnsport* listen)
1110 {
1111         /* do not start the ones that have no tcp_free list, it is no
1112          * use to listen to them because they have no free tcp handlers */
1113         struct listen_list* p;
1114         for(p=listen->cps; p; p=p->next) {
1115                 if(p->com->type == comm_tcp_accept &&
1116                         p->com->tcp_free != NULL) {
1117                         comm_point_start_listening(p->com, -1, -1);
1118                 }
1119         }
1120 }
1121