1238106Sdes/* 2238106Sdes * services/listen_dnsport.c - listen on port 53 for incoming DNS queries. 3238106Sdes * 4238106Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved. 5238106Sdes * 6238106Sdes * This software is open source. 7238106Sdes * 8238106Sdes * Redistribution and use in source and binary forms, with or without 9238106Sdes * modification, are permitted provided that the following conditions 10238106Sdes * are met: 11238106Sdes * 12238106Sdes * Redistributions of source code must retain the above copyright notice, 13238106Sdes * this list of conditions and the following disclaimer. 14238106Sdes * 15238106Sdes * Redistributions in binary form must reproduce the above copyright notice, 16238106Sdes * this list of conditions and the following disclaimer in the documentation 17238106Sdes * and/or other materials provided with the distribution. 18238106Sdes * 19238106Sdes * Neither the name of the NLNET LABS nor the names of its contributors may 20238106Sdes * be used to endorse or promote products derived from this software without 21238106Sdes * specific prior written permission. 22238106Sdes * 23238106Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24269257Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25269257Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26269257Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27269257Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28269257Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29269257Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30269257Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31269257Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32269257Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33269257Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34238106Sdes */ 35238106Sdes 36238106Sdes/** 37238106Sdes * \file 38238106Sdes * 39238106Sdes * This file has functions to get queries from clients. 40238106Sdes */ 41238106Sdes#include "config.h" 42238106Sdes#ifdef HAVE_SYS_TYPES_H 43238106Sdes# include <sys/types.h> 44238106Sdes#endif 45238106Sdes#include <sys/time.h> 46238106Sdes#include "services/listen_dnsport.h" 47238106Sdes#include "services/outside_network.h" 48238106Sdes#include "util/netevent.h" 49238106Sdes#include "util/log.h" 50238106Sdes#include "util/config_file.h" 51238106Sdes#include "util/net_help.h" 52291767Sdes#include "sldns/sbuffer.h" 53238106Sdes 54238106Sdes#ifdef HAVE_NETDB_H 55238106Sdes#include <netdb.h> 56238106Sdes#endif 57238106Sdes#include <fcntl.h> 58238106Sdes 59285206Sdes#ifdef HAVE_SYS_UN_H 60285206Sdes#include <sys/un.h> 61285206Sdes#endif 62285206Sdes 63238106Sdes/** number of queued TCP connections for listen() */ 64285206Sdes#define TCP_BACKLOG 256 65238106Sdes 66238106Sdes/** 67238106Sdes * Debug print of the getaddrinfo returned address. 68238106Sdes * @param addr: the address returned. 69238106Sdes */ 70238106Sdesstatic void 71238106Sdesverbose_print_addr(struct addrinfo *addr) 72238106Sdes{ 73238106Sdes if(verbosity >= VERB_ALGO) { 74238106Sdes char buf[100]; 75238106Sdes void* sinaddr = &((struct sockaddr_in*)addr->ai_addr)->sin_addr; 76238106Sdes#ifdef INET6 77238106Sdes if(addr->ai_family == AF_INET6) 78238106Sdes sinaddr = &((struct sockaddr_in6*)addr->ai_addr)-> 79238106Sdes sin6_addr; 80238106Sdes#endif /* INET6 */ 81238106Sdes if(inet_ntop(addr->ai_family, sinaddr, buf, 82238106Sdes (socklen_t)sizeof(buf)) == 0) { 83269257Sdes (void)strlcpy(buf, "(null)", sizeof(buf)); 84238106Sdes } 85238106Sdes buf[sizeof(buf)-1] = 0; 86238106Sdes verbose(VERB_ALGO, "creating %s%s socket %s %d", 87238106Sdes addr->ai_socktype==SOCK_DGRAM?"udp": 88238106Sdes addr->ai_socktype==SOCK_STREAM?"tcp":"otherproto", 89238106Sdes addr->ai_family==AF_INET?"4": 90238106Sdes addr->ai_family==AF_INET6?"6": 91238106Sdes "_otherfam", buf, 92238106Sdes ntohs(((struct sockaddr_in*)addr->ai_addr)->sin_port)); 93238106Sdes } 94238106Sdes} 95238106Sdes 96238106Sdesint 97238106Sdescreate_udp_sock(int family, int socktype, struct sockaddr* addr, 98238106Sdes socklen_t addrlen, int v6only, int* inuse, int* noproto, 99291767Sdes int rcv, int snd, int listen, int* reuseport, int transparent) 100238106Sdes{ 101238106Sdes int s; 102291767Sdes#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU) || defined(IP_TRANSPARENT) 103238106Sdes int on=1; 104238106Sdes#endif 105238106Sdes#ifdef IPV6_MTU 106238106Sdes int mtu = IPV6_MIN_MTU; 107238106Sdes#endif 108238106Sdes#if !defined(SO_RCVBUFFORCE) && !defined(SO_RCVBUF) 109238106Sdes (void)rcv; 110238106Sdes#endif 111238106Sdes#if !defined(SO_SNDBUFFORCE) && !defined(SO_SNDBUF) 112238106Sdes (void)snd; 113238106Sdes#endif 114238106Sdes#ifndef IPV6_V6ONLY 115238106Sdes (void)v6only; 116238106Sdes#endif 117291767Sdes#ifndef IP_TRANSPARENT 118291767Sdes (void)transparent; 119291767Sdes#endif 120238106Sdes if((s = socket(family, socktype, 0)) == -1) { 121238106Sdes *inuse = 0; 122238106Sdes#ifndef USE_WINSOCK 123238106Sdes if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) { 124238106Sdes *noproto = 1; 125238106Sdes return -1; 126238106Sdes } 127238106Sdes log_err("can't create socket: %s", strerror(errno)); 128238106Sdes#else 129238106Sdes if(WSAGetLastError() == WSAEAFNOSUPPORT || 130238106Sdes WSAGetLastError() == WSAEPROTONOSUPPORT) { 131238106Sdes *noproto = 1; 132238106Sdes return -1; 133238106Sdes } 134238106Sdes log_err("can't create socket: %s", 135238106Sdes wsa_strerror(WSAGetLastError())); 136238106Sdes#endif 137238106Sdes *noproto = 0; 138238106Sdes return -1; 139238106Sdes } 140269257Sdes if(listen) { 141269257Sdes#ifdef SO_REUSEADDR 142269257Sdes if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, 143269257Sdes (socklen_t)sizeof(on)) < 0) { 144269257Sdes#ifndef USE_WINSOCK 145269257Sdes log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s", 146269257Sdes strerror(errno)); 147269257Sdes if(errno != ENOSYS) { 148269257Sdes close(s); 149269257Sdes *noproto = 0; 150269257Sdes *inuse = 0; 151269257Sdes return -1; 152269257Sdes } 153269257Sdes#else 154269257Sdes log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s", 155269257Sdes wsa_strerror(WSAGetLastError())); 156269257Sdes closesocket(s); 157269257Sdes *noproto = 0; 158269257Sdes *inuse = 0; 159269257Sdes return -1; 160269257Sdes#endif 161269257Sdes } 162269257Sdes#endif /* SO_REUSEADDR */ 163285206Sdes#ifdef SO_REUSEPORT 164285206Sdes /* try to set SO_REUSEPORT so that incoming 165269257Sdes * queries are distributed evenly among the receiving threads. 166269257Sdes * Each thread must have its own socket bound to the same port, 167269257Sdes * with SO_REUSEPORT set on each socket. 168269257Sdes */ 169269257Sdes if (reuseport && *reuseport && 170269257Sdes setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on, 171269257Sdes (socklen_t)sizeof(on)) < 0) { 172269257Sdes#ifdef ENOPROTOOPT 173269257Sdes if(errno != ENOPROTOOPT || verbosity >= 3) 174269257Sdes log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s", 175269257Sdes strerror(errno)); 176269257Sdes#endif 177269257Sdes /* this option is not essential, we can continue */ 178269257Sdes *reuseport = 0; 179269257Sdes } 180269257Sdes#else 181269257Sdes (void)reuseport; 182285206Sdes#endif /* defined(SO_REUSEPORT) */ 183291767Sdes#ifdef IP_TRANSPARENT 184291767Sdes if (transparent && 185291767Sdes setsockopt(s, IPPROTO_IP, IP_TRANSPARENT, (void*)&on, 186291767Sdes (socklen_t)sizeof(on)) < 0) { 187291767Sdes log_warn("setsockopt(.. IP_TRANSPARENT ..) failed: %s", 188291767Sdes strerror(errno)); 189291767Sdes } 190291767Sdes#endif /* IP_TRANSPARENT */ 191269257Sdes } 192238106Sdes if(rcv) { 193238106Sdes#ifdef SO_RCVBUF 194238106Sdes int got; 195238106Sdes socklen_t slen = (socklen_t)sizeof(got); 196238106Sdes# ifdef SO_RCVBUFFORCE 197238106Sdes /* Linux specific: try to use root permission to override 198238106Sdes * system limits on rcvbuf. The limit is stored in 199238106Sdes * /proc/sys/net/core/rmem_max or sysctl net.core.rmem_max */ 200238106Sdes if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv, 201238106Sdes (socklen_t)sizeof(rcv)) < 0) { 202238106Sdes if(errno != EPERM) { 203238106Sdes# ifndef USE_WINSOCK 204238106Sdes log_err("setsockopt(..., SO_RCVBUFFORCE, " 205238106Sdes "...) failed: %s", strerror(errno)); 206238106Sdes close(s); 207238106Sdes# else 208238106Sdes log_err("setsockopt(..., SO_RCVBUFFORCE, " 209238106Sdes "...) failed: %s", 210238106Sdes wsa_strerror(WSAGetLastError())); 211238106Sdes closesocket(s); 212238106Sdes# endif 213238106Sdes *noproto = 0; 214238106Sdes *inuse = 0; 215238106Sdes return -1; 216238106Sdes } 217238106Sdes# endif /* SO_RCVBUFFORCE */ 218238106Sdes if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv, 219238106Sdes (socklen_t)sizeof(rcv)) < 0) { 220238106Sdes# ifndef USE_WINSOCK 221238106Sdes log_err("setsockopt(..., SO_RCVBUF, " 222238106Sdes "...) failed: %s", strerror(errno)); 223238106Sdes close(s); 224238106Sdes# else 225238106Sdes log_err("setsockopt(..., SO_RCVBUF, " 226238106Sdes "...) failed: %s", 227238106Sdes wsa_strerror(WSAGetLastError())); 228238106Sdes closesocket(s); 229238106Sdes# endif 230238106Sdes *noproto = 0; 231238106Sdes *inuse = 0; 232238106Sdes return -1; 233238106Sdes } 234238106Sdes /* check if we got the right thing or if system 235238106Sdes * reduced to some system max. Warn if so */ 236238106Sdes if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&got, 237238106Sdes &slen) >= 0 && got < rcv/2) { 238238106Sdes log_warn("so-rcvbuf %u was not granted. " 239238106Sdes "Got %u. To fix: start with " 240238106Sdes "root permissions(linux) or sysctl " 241238106Sdes "bigger net.core.rmem_max(linux) or " 242238106Sdes "kern.ipc.maxsockbuf(bsd) values.", 243238106Sdes (unsigned)rcv, (unsigned)got); 244238106Sdes } 245238106Sdes# ifdef SO_RCVBUFFORCE 246238106Sdes } 247238106Sdes# endif 248238106Sdes#endif /* SO_RCVBUF */ 249238106Sdes } 250238106Sdes /* first do RCVBUF as the receive buffer is more important */ 251238106Sdes if(snd) { 252238106Sdes#ifdef SO_SNDBUF 253238106Sdes int got; 254238106Sdes socklen_t slen = (socklen_t)sizeof(got); 255238106Sdes# ifdef SO_SNDBUFFORCE 256238106Sdes /* Linux specific: try to use root permission to override 257238106Sdes * system limits on sndbuf. The limit is stored in 258238106Sdes * /proc/sys/net/core/wmem_max or sysctl net.core.wmem_max */ 259238106Sdes if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd, 260238106Sdes (socklen_t)sizeof(snd)) < 0) { 261238106Sdes if(errno != EPERM) { 262238106Sdes# ifndef USE_WINSOCK 263238106Sdes log_err("setsockopt(..., SO_SNDBUFFORCE, " 264238106Sdes "...) failed: %s", strerror(errno)); 265238106Sdes close(s); 266238106Sdes# else 267238106Sdes log_err("setsockopt(..., SO_SNDBUFFORCE, " 268238106Sdes "...) failed: %s", 269238106Sdes wsa_strerror(WSAGetLastError())); 270238106Sdes closesocket(s); 271238106Sdes# endif 272238106Sdes *noproto = 0; 273238106Sdes *inuse = 0; 274238106Sdes return -1; 275238106Sdes } 276238106Sdes# endif /* SO_SNDBUFFORCE */ 277238106Sdes if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd, 278238106Sdes (socklen_t)sizeof(snd)) < 0) { 279238106Sdes# ifndef USE_WINSOCK 280238106Sdes log_err("setsockopt(..., SO_SNDBUF, " 281238106Sdes "...) failed: %s", strerror(errno)); 282238106Sdes close(s); 283238106Sdes# else 284238106Sdes log_err("setsockopt(..., SO_SNDBUF, " 285238106Sdes "...) failed: %s", 286238106Sdes wsa_strerror(WSAGetLastError())); 287238106Sdes closesocket(s); 288238106Sdes# endif 289238106Sdes *noproto = 0; 290238106Sdes *inuse = 0; 291238106Sdes return -1; 292238106Sdes } 293238106Sdes /* check if we got the right thing or if system 294238106Sdes * reduced to some system max. Warn if so */ 295238106Sdes if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got, 296238106Sdes &slen) >= 0 && got < snd/2) { 297238106Sdes log_warn("so-sndbuf %u was not granted. " 298238106Sdes "Got %u. To fix: start with " 299238106Sdes "root permissions(linux) or sysctl " 300238106Sdes "bigger net.core.wmem_max(linux) or " 301238106Sdes "kern.ipc.maxsockbuf(bsd) values.", 302238106Sdes (unsigned)snd, (unsigned)got); 303238106Sdes } 304238106Sdes# ifdef SO_SNDBUFFORCE 305238106Sdes } 306238106Sdes# endif 307238106Sdes#endif /* SO_SNDBUF */ 308238106Sdes } 309238106Sdes if(family == AF_INET6) { 310238106Sdes# if defined(IPV6_V6ONLY) 311238106Sdes if(v6only) { 312238106Sdes int val=(v6only==2)?0:1; 313238106Sdes if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, 314238106Sdes (void*)&val, (socklen_t)sizeof(val)) < 0) { 315238106Sdes#ifndef USE_WINSOCK 316238106Sdes log_err("setsockopt(..., IPV6_V6ONLY" 317238106Sdes ", ...) failed: %s", strerror(errno)); 318238106Sdes close(s); 319238106Sdes#else 320238106Sdes log_err("setsockopt(..., IPV6_V6ONLY" 321238106Sdes ", ...) failed: %s", 322238106Sdes wsa_strerror(WSAGetLastError())); 323238106Sdes closesocket(s); 324238106Sdes#endif 325238106Sdes *noproto = 0; 326238106Sdes *inuse = 0; 327238106Sdes return -1; 328238106Sdes } 329238106Sdes } 330238106Sdes# endif 331238106Sdes# if defined(IPV6_USE_MIN_MTU) 332238106Sdes /* 333238106Sdes * There is no fragmentation of IPv6 datagrams 334238106Sdes * during forwarding in the network. Therefore 335238106Sdes * we do not send UDP datagrams larger than 336238106Sdes * the minimum IPv6 MTU of 1280 octets. The 337238106Sdes * EDNS0 message length can be larger if the 338238106Sdes * network stack supports IPV6_USE_MIN_MTU. 339238106Sdes */ 340238106Sdes if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU, 341238106Sdes (void*)&on, (socklen_t)sizeof(on)) < 0) { 342238106Sdes# ifndef USE_WINSOCK 343238106Sdes log_err("setsockopt(..., IPV6_USE_MIN_MTU, " 344238106Sdes "...) failed: %s", strerror(errno)); 345238106Sdes close(s); 346238106Sdes# else 347238106Sdes log_err("setsockopt(..., IPV6_USE_MIN_MTU, " 348238106Sdes "...) failed: %s", 349238106Sdes wsa_strerror(WSAGetLastError())); 350238106Sdes closesocket(s); 351238106Sdes# endif 352238106Sdes *noproto = 0; 353238106Sdes *inuse = 0; 354238106Sdes return -1; 355238106Sdes } 356238106Sdes# elif defined(IPV6_MTU) 357238106Sdes /* 358238106Sdes * On Linux, to send no larger than 1280, the PMTUD is 359238106Sdes * disabled by default for datagrams anyway, so we set 360238106Sdes * the MTU to use. 361238106Sdes */ 362238106Sdes if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU, 363238106Sdes (void*)&mtu, (socklen_t)sizeof(mtu)) < 0) { 364238106Sdes# ifndef USE_WINSOCK 365238106Sdes log_err("setsockopt(..., IPV6_MTU, ...) failed: %s", 366238106Sdes strerror(errno)); 367238106Sdes close(s); 368238106Sdes# else 369238106Sdes log_err("setsockopt(..., IPV6_MTU, ...) failed: %s", 370238106Sdes wsa_strerror(WSAGetLastError())); 371238106Sdes closesocket(s); 372238106Sdes# endif 373238106Sdes *noproto = 0; 374238106Sdes *inuse = 0; 375238106Sdes return -1; 376238106Sdes } 377238106Sdes# endif /* IPv6 MTU */ 378238106Sdes } else if(family == AF_INET) { 379238106Sdes# if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 380285206Sdes/* linux 3.15 has IP_PMTUDISC_OMIT, Hannes Frederic Sowa made it so that 381285206Sdes * PMTU information is not accepted, but fragmentation is allowed 382285206Sdes * if and only if the packet size exceeds the outgoing interface MTU 383285206Sdes * (and also uses the interface mtu to determine the size of the packets). 384285206Sdes * So there won't be any EMSGSIZE error. Against DNS fragmentation attacks. 385285206Sdes * FreeBSD already has same semantics without setting the option. */ 386285206Sdes int omit_set = 0; 387285206Sdes int action; 388285206Sdes# if defined(IP_PMTUDISC_OMIT) 389285206Sdes action = IP_PMTUDISC_OMIT; 390238106Sdes if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, 391238106Sdes &action, (socklen_t)sizeof(action)) < 0) { 392285206Sdes 393285206Sdes if (errno != EINVAL) { 394285206Sdes log_err("setsockopt(..., IP_MTU_DISCOVER, IP_PMTUDISC_OMIT...) failed: %s", 395285206Sdes strerror(errno)); 396285206Sdes 397249141Sdes# ifndef USE_WINSOCK 398285206Sdes close(s); 399249141Sdes# else 400285206Sdes closesocket(s); 401249141Sdes# endif 402285206Sdes *noproto = 0; 403285206Sdes *inuse = 0; 404285206Sdes return -1; 405285206Sdes } 406238106Sdes } 407285206Sdes else 408285206Sdes { 409285206Sdes omit_set = 1; 410285206Sdes } 411285206Sdes# endif 412285206Sdes if (omit_set == 0) { 413285206Sdes action = IP_PMTUDISC_DONT; 414285206Sdes if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, 415285206Sdes &action, (socklen_t)sizeof(action)) < 0) { 416285206Sdes log_err("setsockopt(..., IP_MTU_DISCOVER, IP_PMTUDISC_DONT...) failed: %s", 417285206Sdes strerror(errno)); 418285206Sdes# ifndef USE_WINSOCK 419285206Sdes close(s); 420285206Sdes# else 421285206Sdes closesocket(s); 422285206Sdes# endif 423285206Sdes *noproto = 0; 424285206Sdes *inuse = 0; 425285206Sdes return -1; 426285206Sdes } 427285206Sdes } 428238106Sdes# elif defined(IP_DONTFRAG) 429238106Sdes int off = 0; 430238106Sdes if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG, 431238106Sdes &off, (socklen_t)sizeof(off)) < 0) { 432238106Sdes log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s", 433238106Sdes strerror(errno)); 434249141Sdes# ifndef USE_WINSOCK 435249141Sdes close(s); 436249141Sdes# else 437249141Sdes closesocket(s); 438249141Sdes# endif 439269257Sdes *noproto = 0; 440269257Sdes *inuse = 0; 441238106Sdes return -1; 442238106Sdes } 443238106Sdes# endif /* IPv4 MTU */ 444238106Sdes } 445238106Sdes if(bind(s, (struct sockaddr*)addr, addrlen) != 0) { 446238106Sdes *noproto = 0; 447269257Sdes *inuse = 0; 448238106Sdes#ifndef USE_WINSOCK 449238106Sdes#ifdef EADDRINUSE 450238106Sdes *inuse = (errno == EADDRINUSE); 451238106Sdes /* detect freebsd jail with no ipv6 permission */ 452238106Sdes if(family==AF_INET6 && errno==EINVAL) 453238106Sdes *noproto = 1; 454238106Sdes else if(errno != EADDRINUSE) { 455285206Sdes log_err_addr("can't bind socket", strerror(errno), 456238106Sdes (struct sockaddr_storage*)addr, addrlen); 457238106Sdes } 458238106Sdes#endif /* EADDRINUSE */ 459238106Sdes close(s); 460238106Sdes#else /* USE_WINSOCK */ 461238106Sdes if(WSAGetLastError() != WSAEADDRINUSE && 462238106Sdes WSAGetLastError() != WSAEADDRNOTAVAIL) { 463285206Sdes log_err_addr("can't bind socket", 464285206Sdes wsa_strerror(WSAGetLastError()), 465238106Sdes (struct sockaddr_storage*)addr, addrlen); 466238106Sdes } 467238106Sdes closesocket(s); 468238106Sdes#endif 469238106Sdes return -1; 470238106Sdes } 471238106Sdes if(!fd_set_nonblock(s)) { 472238106Sdes *noproto = 0; 473238106Sdes *inuse = 0; 474238106Sdes#ifndef USE_WINSOCK 475238106Sdes close(s); 476238106Sdes#else 477238106Sdes closesocket(s); 478238106Sdes#endif 479238106Sdes return -1; 480238106Sdes } 481238106Sdes return s; 482238106Sdes} 483238106Sdes 484238106Sdesint 485269257Sdescreate_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto, 486291767Sdes int* reuseport, int transparent) 487238106Sdes{ 488238106Sdes int s; 489291767Sdes#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) 490238106Sdes int on = 1; 491291767Sdes#endif 492291767Sdes#ifndef IP_TRANSPARENT 493291767Sdes (void)transparent; 494291767Sdes#endif 495238106Sdes verbose_print_addr(addr); 496238106Sdes *noproto = 0; 497238106Sdes if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) { 498238106Sdes#ifndef USE_WINSOCK 499238106Sdes if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) { 500238106Sdes *noproto = 1; 501238106Sdes return -1; 502238106Sdes } 503238106Sdes log_err("can't create socket: %s", strerror(errno)); 504238106Sdes#else 505238106Sdes if(WSAGetLastError() == WSAEAFNOSUPPORT || 506238106Sdes WSAGetLastError() == WSAEPROTONOSUPPORT) { 507238106Sdes *noproto = 1; 508238106Sdes return -1; 509238106Sdes } 510238106Sdes log_err("can't create socket: %s", 511238106Sdes wsa_strerror(WSAGetLastError())); 512238106Sdes#endif 513238106Sdes return -1; 514238106Sdes } 515238106Sdes#ifdef SO_REUSEADDR 516238106Sdes if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, 517238106Sdes (socklen_t)sizeof(on)) < 0) { 518238106Sdes#ifndef USE_WINSOCK 519238106Sdes log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s", 520238106Sdes strerror(errno)); 521249141Sdes close(s); 522238106Sdes#else 523238106Sdes log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s", 524238106Sdes wsa_strerror(WSAGetLastError())); 525249141Sdes closesocket(s); 526238106Sdes#endif 527238106Sdes return -1; 528238106Sdes } 529238106Sdes#endif /* SO_REUSEADDR */ 530285206Sdes#ifdef SO_REUSEPORT 531285206Sdes /* try to set SO_REUSEPORT so that incoming 532269257Sdes * connections are distributed evenly among the receiving threads. 533269257Sdes * Each thread must have its own socket bound to the same port, 534269257Sdes * with SO_REUSEPORT set on each socket. 535269257Sdes */ 536269257Sdes if (reuseport && *reuseport && 537269257Sdes setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on, 538269257Sdes (socklen_t)sizeof(on)) < 0) { 539269257Sdes#ifdef ENOPROTOOPT 540269257Sdes if(errno != ENOPROTOOPT || verbosity >= 3) 541269257Sdes log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s", 542269257Sdes strerror(errno)); 543269257Sdes#endif 544269257Sdes /* this option is not essential, we can continue */ 545269257Sdes *reuseport = 0; 546269257Sdes } 547269257Sdes#else 548269257Sdes (void)reuseport; 549285206Sdes#endif /* defined(SO_REUSEPORT) */ 550238106Sdes#if defined(IPV6_V6ONLY) 551238106Sdes if(addr->ai_family == AF_INET6 && v6only) { 552238106Sdes if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, 553238106Sdes (void*)&on, (socklen_t)sizeof(on)) < 0) { 554238106Sdes#ifndef USE_WINSOCK 555238106Sdes log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s", 556238106Sdes strerror(errno)); 557249141Sdes close(s); 558238106Sdes#else 559238106Sdes log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s", 560238106Sdes wsa_strerror(WSAGetLastError())); 561249141Sdes closesocket(s); 562238106Sdes#endif 563238106Sdes return -1; 564238106Sdes } 565238106Sdes } 566238106Sdes#else 567238106Sdes (void)v6only; 568238106Sdes#endif /* IPV6_V6ONLY */ 569291767Sdes#ifdef IP_TRANSPARENT 570291767Sdes if (transparent && 571291767Sdes setsockopt(s, IPPROTO_IP, IP_TRANSPARENT, (void*)&on, 572291767Sdes (socklen_t)sizeof(on)) < 0) { 573291767Sdes log_warn("setsockopt(.. IP_TRANSPARENT ..) failed: %s", 574291767Sdes strerror(errno)); 575291767Sdes } 576291767Sdes#endif /* IP_TRANSPARENT */ 577238106Sdes if(bind(s, addr->ai_addr, addr->ai_addrlen) != 0) { 578238106Sdes#ifndef USE_WINSOCK 579238106Sdes /* detect freebsd jail with no ipv6 permission */ 580238106Sdes if(addr->ai_family==AF_INET6 && errno==EINVAL) 581238106Sdes *noproto = 1; 582238106Sdes else { 583285206Sdes log_err_addr("can't bind socket", strerror(errno), 584238106Sdes (struct sockaddr_storage*)addr->ai_addr, 585238106Sdes addr->ai_addrlen); 586238106Sdes } 587249141Sdes close(s); 588238106Sdes#else 589285206Sdes log_err_addr("can't bind socket", 590285206Sdes wsa_strerror(WSAGetLastError()), 591238106Sdes (struct sockaddr_storage*)addr->ai_addr, 592238106Sdes addr->ai_addrlen); 593249141Sdes closesocket(s); 594238106Sdes#endif 595238106Sdes return -1; 596238106Sdes } 597238106Sdes if(!fd_set_nonblock(s)) { 598249141Sdes#ifndef USE_WINSOCK 599249141Sdes close(s); 600249141Sdes#else 601249141Sdes closesocket(s); 602249141Sdes#endif 603238106Sdes return -1; 604238106Sdes } 605238106Sdes if(listen(s, TCP_BACKLOG) == -1) { 606238106Sdes#ifndef USE_WINSOCK 607238106Sdes log_err("can't listen: %s", strerror(errno)); 608249141Sdes close(s); 609238106Sdes#else 610238106Sdes log_err("can't listen: %s", wsa_strerror(WSAGetLastError())); 611249141Sdes closesocket(s); 612238106Sdes#endif 613238106Sdes return -1; 614238106Sdes } 615238106Sdes return s; 616238106Sdes} 617238106Sdes 618285206Sdesint 619285206Sdescreate_local_accept_sock(const char *path, int* noproto) 620285206Sdes{ 621285206Sdes#ifdef HAVE_SYS_UN_H 622285206Sdes int s; 623285206Sdes struct sockaddr_un usock; 624285206Sdes 625285206Sdes verbose(VERB_ALGO, "creating unix socket %s", path); 626285206Sdes#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN 627285206Sdes /* this member exists on BSDs, not Linux */ 628285206Sdes usock.sun_len = (socklen_t)sizeof(usock); 629285206Sdes#endif 630285206Sdes usock.sun_family = AF_LOCAL; 631285206Sdes /* length is 92-108, 104 on FreeBSD */ 632285206Sdes (void)strlcpy(usock.sun_path, path, sizeof(usock.sun_path)); 633285206Sdes 634285206Sdes if ((s = socket(AF_LOCAL, SOCK_STREAM, 0)) == -1) { 635285206Sdes log_err("Cannot create local socket %s (%s)", 636285206Sdes path, strerror(errno)); 637285206Sdes return -1; 638285206Sdes } 639285206Sdes 640285206Sdes if (unlink(path) && errno != ENOENT) { 641285206Sdes /* The socket already exists and cannot be removed */ 642285206Sdes log_err("Cannot remove old local socket %s (%s)", 643285206Sdes path, strerror(errno)); 644285206Sdes return -1; 645285206Sdes } 646285206Sdes 647285206Sdes if (bind(s, (struct sockaddr *)&usock, 648285206Sdes (socklen_t)sizeof(struct sockaddr_un)) == -1) { 649285206Sdes log_err("Cannot bind local socket %s (%s)", 650285206Sdes path, strerror(errno)); 651285206Sdes return -1; 652285206Sdes } 653285206Sdes 654285206Sdes if (!fd_set_nonblock(s)) { 655285206Sdes log_err("Cannot set non-blocking mode"); 656285206Sdes return -1; 657285206Sdes } 658285206Sdes 659285206Sdes if (listen(s, TCP_BACKLOG) == -1) { 660285206Sdes log_err("can't listen: %s", strerror(errno)); 661285206Sdes return -1; 662285206Sdes } 663285206Sdes 664285206Sdes (void)noproto; /*unused*/ 665285206Sdes return s; 666285206Sdes#else 667285206Sdes (void)path; 668285206Sdes log_err("Local sockets are not supported"); 669285206Sdes *noproto = 1; 670285206Sdes return -1; 671285206Sdes#endif 672285206Sdes} 673285206Sdes 674285206Sdes 675238106Sdes/** 676238106Sdes * Create socket from getaddrinfo results 677238106Sdes */ 678238106Sdesstatic int 679238106Sdesmake_sock(int stype, const char* ifname, const char* port, 680269257Sdes struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd, 681291767Sdes int* reuseport, int transparent) 682238106Sdes{ 683238106Sdes struct addrinfo *res = NULL; 684238106Sdes int r, s, inuse, noproto; 685238106Sdes hints->ai_socktype = stype; 686238106Sdes *noip6 = 0; 687238106Sdes if((r=getaddrinfo(ifname, port, hints, &res)) != 0 || !res) { 688238106Sdes#ifdef USE_WINSOCK 689238106Sdes if(r == EAI_NONAME && hints->ai_family == AF_INET6){ 690238106Sdes *noip6 = 1; /* 'Host not found' for IP6 on winXP */ 691238106Sdes return -1; 692238106Sdes } 693238106Sdes#endif 694238106Sdes log_err("node %s:%s getaddrinfo: %s %s", 695238106Sdes ifname?ifname:"default", port, gai_strerror(r), 696238106Sdes#ifdef EAI_SYSTEM 697238106Sdes r==EAI_SYSTEM?(char*)strerror(errno):"" 698238106Sdes#else 699238106Sdes "" 700238106Sdes#endif 701238106Sdes ); 702238106Sdes return -1; 703238106Sdes } 704238106Sdes if(stype == SOCK_DGRAM) { 705238106Sdes verbose_print_addr(res); 706238106Sdes s = create_udp_sock(res->ai_family, res->ai_socktype, 707238106Sdes (struct sockaddr*)res->ai_addr, res->ai_addrlen, 708269257Sdes v6only, &inuse, &noproto, (int)rcv, (int)snd, 1, 709291767Sdes reuseport, transparent); 710238106Sdes if(s == -1 && inuse) { 711238106Sdes log_err("bind: address already in use"); 712238106Sdes } else if(s == -1 && noproto && hints->ai_family == AF_INET6){ 713238106Sdes *noip6 = 1; 714238106Sdes } 715238106Sdes } else { 716291767Sdes s = create_tcp_accept_sock(res, v6only, &noproto, reuseport, 717291767Sdes transparent); 718238106Sdes if(s == -1 && noproto && hints->ai_family == AF_INET6){ 719238106Sdes *noip6 = 1; 720238106Sdes } 721238106Sdes } 722238106Sdes freeaddrinfo(res); 723238106Sdes return s; 724238106Sdes} 725238106Sdes 726238106Sdes/** make socket and first see if ifname contains port override info */ 727238106Sdesstatic int 728238106Sdesmake_sock_port(int stype, const char* ifname, const char* port, 729269257Sdes struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd, 730291767Sdes int* reuseport, int transparent) 731238106Sdes{ 732238106Sdes char* s = strchr(ifname, '@'); 733238106Sdes if(s) { 734238106Sdes /* override port with ifspec@port */ 735238106Sdes char p[16]; 736238106Sdes char newif[128]; 737238106Sdes if((size_t)(s-ifname) >= sizeof(newif)) { 738238106Sdes log_err("ifname too long: %s", ifname); 739238106Sdes *noip6 = 0; 740238106Sdes return -1; 741238106Sdes } 742238106Sdes if(strlen(s+1) >= sizeof(p)) { 743238106Sdes log_err("portnumber too long: %s", ifname); 744238106Sdes *noip6 = 0; 745238106Sdes return -1; 746238106Sdes } 747269257Sdes (void)strlcpy(newif, ifname, sizeof(newif)); 748238106Sdes newif[s-ifname] = 0; 749269257Sdes (void)strlcpy(p, s+1, sizeof(p)); 750238106Sdes p[strlen(s+1)]=0; 751238106Sdes return make_sock(stype, newif, p, hints, v6only, noip6, 752291767Sdes rcv, snd, reuseport, transparent); 753238106Sdes } 754269257Sdes return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd, 755291767Sdes reuseport, transparent); 756238106Sdes} 757238106Sdes 758238106Sdes/** 759238106Sdes * Add port to open ports list. 760238106Sdes * @param list: list head. changed. 761238106Sdes * @param s: fd. 762238106Sdes * @param ftype: if fd is UDP. 763238106Sdes * @return false on failure. list in unchanged then. 764238106Sdes */ 765238106Sdesstatic int 766238106Sdesport_insert(struct listen_port** list, int s, enum listen_type ftype) 767238106Sdes{ 768238106Sdes struct listen_port* item = (struct listen_port*)malloc( 769238106Sdes sizeof(struct listen_port)); 770238106Sdes if(!item) 771238106Sdes return 0; 772238106Sdes item->next = *list; 773238106Sdes item->fd = s; 774238106Sdes item->ftype = ftype; 775238106Sdes *list = item; 776238106Sdes return 1; 777238106Sdes} 778238106Sdes 779238106Sdes/** set fd to receive source address packet info */ 780238106Sdesstatic int 781238106Sdesset_recvpktinfo(int s, int family) 782238106Sdes{ 783238106Sdes#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)) || defined(IP_PKTINFO) 784238106Sdes int on = 1; 785238106Sdes#else 786238106Sdes (void)s; 787238106Sdes#endif 788238106Sdes if(family == AF_INET6) { 789238106Sdes# ifdef IPV6_RECVPKTINFO 790238106Sdes if(setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, 791238106Sdes (void*)&on, (socklen_t)sizeof(on)) < 0) { 792238106Sdes log_err("setsockopt(..., IPV6_RECVPKTINFO, ...) failed: %s", 793238106Sdes strerror(errno)); 794238106Sdes return 0; 795238106Sdes } 796238106Sdes# elif defined(IPV6_PKTINFO) 797238106Sdes if(setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, 798238106Sdes (void*)&on, (socklen_t)sizeof(on)) < 0) { 799238106Sdes log_err("setsockopt(..., IPV6_PKTINFO, ...) failed: %s", 800238106Sdes strerror(errno)); 801238106Sdes return 0; 802238106Sdes } 803238106Sdes# else 804238106Sdes log_err("no IPV6_RECVPKTINFO and no IPV6_PKTINFO option, please " 805238106Sdes "disable interface-automatic in config"); 806238106Sdes return 0; 807238106Sdes# endif /* defined IPV6_RECVPKTINFO */ 808238106Sdes 809238106Sdes } else if(family == AF_INET) { 810238106Sdes# ifdef IP_PKTINFO 811238106Sdes if(setsockopt(s, IPPROTO_IP, IP_PKTINFO, 812238106Sdes (void*)&on, (socklen_t)sizeof(on)) < 0) { 813238106Sdes log_err("setsockopt(..., IP_PKTINFO, ...) failed: %s", 814238106Sdes strerror(errno)); 815238106Sdes return 0; 816238106Sdes } 817238106Sdes# elif defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR) 818238106Sdes if(setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, 819238106Sdes (void*)&on, (socklen_t)sizeof(on)) < 0) { 820238106Sdes log_err("setsockopt(..., IP_RECVDSTADDR, ...) failed: %s", 821238106Sdes strerror(errno)); 822238106Sdes return 0; 823238106Sdes } 824238106Sdes# else 825238106Sdes log_err("no IP_SENDSRCADDR or IP_PKTINFO option, please disable " 826238106Sdes "interface-automatic in config"); 827238106Sdes return 0; 828238106Sdes# endif /* IP_PKTINFO */ 829238106Sdes 830238106Sdes } 831238106Sdes return 1; 832238106Sdes} 833238106Sdes 834238106Sdes/** 835238106Sdes * Helper for ports_open. Creates one interface (or NULL for default). 836238106Sdes * @param ifname: The interface ip address. 837238106Sdes * @param do_auto: use automatic interface detection. 838238106Sdes * If enabled, then ifname must be the wildcard name. 839238106Sdes * @param do_udp: if udp should be used. 840238106Sdes * @param do_tcp: if udp should be used. 841238106Sdes * @param hints: for getaddrinfo. family and flags have to be set by caller. 842238106Sdes * @param port: Port number to use (as string). 843238106Sdes * @param list: list of open ports, appended to, changed to point to list head. 844238106Sdes * @param rcv: receive buffer size for UDP 845238106Sdes * @param snd: send buffer size for UDP 846238106Sdes * @param ssl_port: ssl service port number 847269257Sdes * @param reuseport: try to set SO_REUSEPORT if nonNULL and true. 848269257Sdes * set to false on exit if reuseport failed due to no kernel support. 849291767Sdes * @param transparent: set IP_TRANSPARENT socket option. 850238106Sdes * @return: returns false on error. 851238106Sdes */ 852238106Sdesstatic int 853238106Sdesports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, 854238106Sdes struct addrinfo *hints, const char* port, struct listen_port** list, 855291767Sdes size_t rcv, size_t snd, int ssl_port, int* reuseport, int transparent) 856238106Sdes{ 857238106Sdes int s, noip6=0; 858238106Sdes if(!do_udp && !do_tcp) 859238106Sdes return 0; 860238106Sdes if(do_auto) { 861238106Sdes if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, 862291767Sdes &noip6, rcv, snd, reuseport, transparent)) == -1) { 863238106Sdes if(noip6) { 864238106Sdes log_warn("IPv6 protocol not available"); 865238106Sdes return 1; 866238106Sdes } 867238106Sdes return 0; 868238106Sdes } 869238106Sdes /* getting source addr packet info is highly non-portable */ 870249141Sdes if(!set_recvpktinfo(s, hints->ai_family)) { 871249141Sdes#ifndef USE_WINSOCK 872249141Sdes close(s); 873249141Sdes#else 874249141Sdes closesocket(s); 875249141Sdes#endif 876238106Sdes return 0; 877249141Sdes } 878238106Sdes if(!port_insert(list, s, listen_type_udpancil)) { 879238106Sdes#ifndef USE_WINSOCK 880238106Sdes close(s); 881238106Sdes#else 882238106Sdes closesocket(s); 883238106Sdes#endif 884238106Sdes return 0; 885238106Sdes } 886238106Sdes } else if(do_udp) { 887238106Sdes /* regular udp socket */ 888238106Sdes if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, 889291767Sdes &noip6, rcv, snd, reuseport, transparent)) == -1) { 890238106Sdes if(noip6) { 891238106Sdes log_warn("IPv6 protocol not available"); 892238106Sdes return 1; 893238106Sdes } 894238106Sdes return 0; 895238106Sdes } 896238106Sdes if(!port_insert(list, s, listen_type_udp)) { 897238106Sdes#ifndef USE_WINSOCK 898238106Sdes close(s); 899238106Sdes#else 900238106Sdes closesocket(s); 901238106Sdes#endif 902238106Sdes return 0; 903238106Sdes } 904238106Sdes } 905238106Sdes if(do_tcp) { 906238106Sdes int is_ssl = ((strchr(ifname, '@') && 907238106Sdes atoi(strchr(ifname, '@')+1) == ssl_port) || 908238106Sdes (!strchr(ifname, '@') && atoi(port) == ssl_port)); 909238106Sdes if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1, 910291767Sdes &noip6, 0, 0, reuseport, transparent)) == -1) { 911238106Sdes if(noip6) { 912238106Sdes /*log_warn("IPv6 protocol not available");*/ 913238106Sdes return 1; 914238106Sdes } 915238106Sdes return 0; 916238106Sdes } 917238106Sdes if(is_ssl) 918238106Sdes verbose(VERB_ALGO, "setup TCP for SSL service"); 919238106Sdes if(!port_insert(list, s, is_ssl?listen_type_ssl: 920238106Sdes listen_type_tcp)) { 921238106Sdes#ifndef USE_WINSOCK 922238106Sdes close(s); 923238106Sdes#else 924238106Sdes closesocket(s); 925238106Sdes#endif 926238106Sdes return 0; 927238106Sdes } 928238106Sdes } 929238106Sdes return 1; 930238106Sdes} 931238106Sdes 932238106Sdes/** 933238106Sdes * Add items to commpoint list in front. 934238106Sdes * @param c: commpoint to add. 935238106Sdes * @param front: listen struct. 936238106Sdes * @return: false on failure. 937238106Sdes */ 938238106Sdesstatic int 939238106Sdeslisten_cp_insert(struct comm_point* c, struct listen_dnsport* front) 940238106Sdes{ 941238106Sdes struct listen_list* item = (struct listen_list*)malloc( 942238106Sdes sizeof(struct listen_list)); 943238106Sdes if(!item) 944238106Sdes return 0; 945238106Sdes item->com = c; 946238106Sdes item->next = front->cps; 947238106Sdes front->cps = item; 948238106Sdes return 1; 949238106Sdes} 950238106Sdes 951238106Sdesstruct listen_dnsport* 952238106Sdeslisten_create(struct comm_base* base, struct listen_port* ports, 953238106Sdes size_t bufsize, int tcp_accept_count, void* sslctx, 954285206Sdes struct dt_env* dtenv, comm_point_callback_t* cb, void *cb_arg) 955238106Sdes{ 956238106Sdes struct listen_dnsport* front = (struct listen_dnsport*) 957238106Sdes malloc(sizeof(struct listen_dnsport)); 958238106Sdes if(!front) 959238106Sdes return NULL; 960238106Sdes front->cps = NULL; 961269257Sdes front->udp_buff = sldns_buffer_new(bufsize); 962238106Sdes if(!front->udp_buff) { 963238106Sdes free(front); 964238106Sdes return NULL; 965238106Sdes } 966238106Sdes 967238106Sdes /* create comm points as needed */ 968238106Sdes while(ports) { 969238106Sdes struct comm_point* cp = NULL; 970238106Sdes if(ports->ftype == listen_type_udp) 971238106Sdes cp = comm_point_create_udp(base, ports->fd, 972238106Sdes front->udp_buff, cb, cb_arg); 973238106Sdes else if(ports->ftype == listen_type_tcp) 974238106Sdes cp = comm_point_create_tcp(base, ports->fd, 975238106Sdes tcp_accept_count, bufsize, cb, cb_arg); 976238106Sdes else if(ports->ftype == listen_type_ssl) { 977238106Sdes cp = comm_point_create_tcp(base, ports->fd, 978238106Sdes tcp_accept_count, bufsize, cb, cb_arg); 979238106Sdes cp->ssl = sslctx; 980238106Sdes } else if(ports->ftype == listen_type_udpancil) 981238106Sdes cp = comm_point_create_udp_ancil(base, ports->fd, 982238106Sdes front->udp_buff, cb, cb_arg); 983238106Sdes if(!cp) { 984238106Sdes log_err("can't create commpoint"); 985238106Sdes listen_delete(front); 986238106Sdes return NULL; 987238106Sdes } 988285206Sdes cp->dtenv = dtenv; 989238106Sdes cp->do_not_close = 1; 990238106Sdes if(!listen_cp_insert(cp, front)) { 991238106Sdes log_err("malloc failed"); 992238106Sdes comm_point_delete(cp); 993238106Sdes listen_delete(front); 994238106Sdes return NULL; 995238106Sdes } 996238106Sdes ports = ports->next; 997238106Sdes } 998238106Sdes if(!front->cps) { 999238106Sdes log_err("Could not open sockets to accept queries."); 1000238106Sdes listen_delete(front); 1001238106Sdes return NULL; 1002238106Sdes } 1003238106Sdes 1004238106Sdes return front; 1005238106Sdes} 1006238106Sdes 1007238106Sdesvoid 1008238106Sdeslisten_list_delete(struct listen_list* list) 1009238106Sdes{ 1010238106Sdes struct listen_list *p = list, *pn; 1011238106Sdes while(p) { 1012238106Sdes pn = p->next; 1013238106Sdes comm_point_delete(p->com); 1014238106Sdes free(p); 1015238106Sdes p = pn; 1016238106Sdes } 1017238106Sdes} 1018238106Sdes 1019238106Sdesvoid 1020238106Sdeslisten_delete(struct listen_dnsport* front) 1021238106Sdes{ 1022238106Sdes if(!front) 1023238106Sdes return; 1024238106Sdes listen_list_delete(front->cps); 1025269257Sdes sldns_buffer_free(front->udp_buff); 1026238106Sdes free(front); 1027238106Sdes} 1028238106Sdes 1029238106Sdesstruct listen_port* 1030269257Sdeslistening_ports_open(struct config_file* cfg, int* reuseport) 1031238106Sdes{ 1032238106Sdes struct listen_port* list = NULL; 1033238106Sdes struct addrinfo hints; 1034238106Sdes int i, do_ip4, do_ip6; 1035238106Sdes int do_tcp, do_auto; 1036238106Sdes char portbuf[32]; 1037238106Sdes snprintf(portbuf, sizeof(portbuf), "%d", cfg->port); 1038238106Sdes do_ip4 = cfg->do_ip4; 1039238106Sdes do_ip6 = cfg->do_ip6; 1040238106Sdes do_tcp = cfg->do_tcp; 1041238106Sdes do_auto = cfg->if_automatic && cfg->do_udp; 1042238106Sdes if(cfg->incoming_num_tcp == 0) 1043238106Sdes do_tcp = 0; 1044238106Sdes 1045238106Sdes /* getaddrinfo */ 1046238106Sdes memset(&hints, 0, sizeof(hints)); 1047238106Sdes hints.ai_flags = AI_PASSIVE; 1048238106Sdes /* no name lookups on our listening ports */ 1049238106Sdes if(cfg->num_ifs > 0) 1050238106Sdes hints.ai_flags |= AI_NUMERICHOST; 1051238106Sdes hints.ai_family = AF_UNSPEC; 1052238106Sdes#ifndef INET6 1053238106Sdes do_ip6 = 0; 1054238106Sdes#endif 1055238106Sdes if(!do_ip4 && !do_ip6) { 1056238106Sdes return NULL; 1057238106Sdes } 1058238106Sdes /* create ip4 and ip6 ports so that return addresses are nice. */ 1059238106Sdes if(do_auto || cfg->num_ifs == 0) { 1060238106Sdes if(do_ip6) { 1061238106Sdes hints.ai_family = AF_INET6; 1062238106Sdes if(!ports_create_if(do_auto?"::0":"::1", 1063238106Sdes do_auto, cfg->do_udp, do_tcp, 1064238106Sdes &hints, portbuf, &list, 1065238106Sdes cfg->so_rcvbuf, cfg->so_sndbuf, 1066291767Sdes cfg->ssl_port, reuseport, 1067291767Sdes cfg->ip_transparent)) { 1068238106Sdes listening_ports_free(list); 1069238106Sdes return NULL; 1070238106Sdes } 1071238106Sdes } 1072238106Sdes if(do_ip4) { 1073238106Sdes hints.ai_family = AF_INET; 1074238106Sdes if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1", 1075238106Sdes do_auto, cfg->do_udp, do_tcp, 1076238106Sdes &hints, portbuf, &list, 1077238106Sdes cfg->so_rcvbuf, cfg->so_sndbuf, 1078291767Sdes cfg->ssl_port, reuseport, 1079291767Sdes cfg->ip_transparent)) { 1080238106Sdes listening_ports_free(list); 1081238106Sdes return NULL; 1082238106Sdes } 1083238106Sdes } 1084238106Sdes } else for(i = 0; i<cfg->num_ifs; i++) { 1085238106Sdes if(str_is_ip6(cfg->ifs[i])) { 1086238106Sdes if(!do_ip6) 1087238106Sdes continue; 1088238106Sdes hints.ai_family = AF_INET6; 1089238106Sdes if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp, 1090238106Sdes do_tcp, &hints, portbuf, &list, 1091238106Sdes cfg->so_rcvbuf, cfg->so_sndbuf, 1092291767Sdes cfg->ssl_port, reuseport, 1093291767Sdes cfg->ip_transparent)) { 1094238106Sdes listening_ports_free(list); 1095238106Sdes return NULL; 1096238106Sdes } 1097238106Sdes } else { 1098238106Sdes if(!do_ip4) 1099238106Sdes continue; 1100238106Sdes hints.ai_family = AF_INET; 1101238106Sdes if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp, 1102238106Sdes do_tcp, &hints, portbuf, &list, 1103238106Sdes cfg->so_rcvbuf, cfg->so_sndbuf, 1104291767Sdes cfg->ssl_port, reuseport, 1105291767Sdes cfg->ip_transparent)) { 1106238106Sdes listening_ports_free(list); 1107238106Sdes return NULL; 1108238106Sdes } 1109238106Sdes } 1110238106Sdes } 1111238106Sdes return list; 1112238106Sdes} 1113238106Sdes 1114238106Sdesvoid listening_ports_free(struct listen_port* list) 1115238106Sdes{ 1116238106Sdes struct listen_port* nx; 1117238106Sdes while(list) { 1118238106Sdes nx = list->next; 1119238106Sdes if(list->fd != -1) { 1120238106Sdes#ifndef USE_WINSOCK 1121238106Sdes close(list->fd); 1122238106Sdes#else 1123238106Sdes closesocket(list->fd); 1124238106Sdes#endif 1125238106Sdes } 1126238106Sdes free(list); 1127238106Sdes list = nx; 1128238106Sdes } 1129238106Sdes} 1130238106Sdes 1131238106Sdessize_t listen_get_mem(struct listen_dnsport* listen) 1132238106Sdes{ 1133238106Sdes size_t s = sizeof(*listen) + sizeof(*listen->base) + 1134238106Sdes sizeof(*listen->udp_buff) + 1135269257Sdes sldns_buffer_capacity(listen->udp_buff); 1136238106Sdes struct listen_list* p; 1137238106Sdes for(p = listen->cps; p; p = p->next) { 1138238106Sdes s += sizeof(*p); 1139238106Sdes s += comm_point_get_mem(p->com); 1140238106Sdes } 1141238106Sdes return s; 1142238106Sdes} 1143238106Sdes 1144238106Sdesvoid listen_stop_accept(struct listen_dnsport* listen) 1145238106Sdes{ 1146238106Sdes /* do not stop the ones that have no tcp_free list 1147238106Sdes * (they have already stopped listening) */ 1148238106Sdes struct listen_list* p; 1149238106Sdes for(p=listen->cps; p; p=p->next) { 1150238106Sdes if(p->com->type == comm_tcp_accept && 1151238106Sdes p->com->tcp_free != NULL) { 1152238106Sdes comm_point_stop_listening(p->com); 1153238106Sdes } 1154238106Sdes } 1155238106Sdes} 1156238106Sdes 1157238106Sdesvoid listen_start_accept(struct listen_dnsport* listen) 1158238106Sdes{ 1159238106Sdes /* do not start the ones that have no tcp_free list, it is no 1160238106Sdes * use to listen to them because they have no free tcp handlers */ 1161238106Sdes struct listen_list* p; 1162238106Sdes for(p=listen->cps; p; p=p->next) { 1163238106Sdes if(p->com->type == comm_tcp_accept && 1164238106Sdes p->com->tcp_free != NULL) { 1165238106Sdes comm_point_start_listening(p->com, -1, -1); 1166238106Sdes } 1167238106Sdes } 1168238106Sdes} 1169238106Sdes 1170