1ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley 2ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 3ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat This program is free software; you can redistribute it and/or modify 4ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat it under the terms of the GNU General Public License as published by 5ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat the Free Software Foundation; version 2 dated June, 1991, or 6ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (at your option) version 3 dated 29 June, 2007. 7ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 8ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat This program is distributed in the hope that it will be useful, 9ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat but WITHOUT ANY WARRANTY; without even the implied warranty of 10ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat GNU General Public License for more details. 12ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 13ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat You should have received a copy of the GNU General Public License 14ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat along with this program. If not, see <http://www.gnu.org/licenses/>. 15ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat*/ 16ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 17ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#include "dnsmasq.h" 18ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 19ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_LINUX_NETWORK 20ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 21ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint indextoname(int fd, int index, char *name) 22ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 23ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct ifreq ifr; 24ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 25ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (index == 0) 26ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 27ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 28ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ifr.ifr_ifindex = index; 29ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ioctl(fd, SIOCGIFNAME, &ifr) == -1) 30ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 31ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 32ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strncpy(name, ifr.ifr_name, IF_NAMESIZE); 33ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 34ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 35ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 36ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 37ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else 38ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 39ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint indextoname(int fd, int index, char *name) 40ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 41ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (index == 0 || !if_indextoname(index, name)) 42ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 43ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 44ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 45ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 46ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 47ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 48ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 49ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint iface_check(int family, struct all_addr *addr, char *name, int *indexp) 50ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 51ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct iname *tmp; 52ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int ret = 1; 53ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 54ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Note: have to check all and not bail out early, so that we set the 55ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat "used" flags. */ 56ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 57ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (indexp) 58ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 59ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* One form of bridging on BSD has the property that packets 60ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat can be recieved on bridge interfaces which do not have an IP address. 61ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat We allow these to be treated as aliases of another interface which does have 62ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat an IP address with --dhcp-bridge=interface,alias,alias */ 63ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct dhcp_bridge *bridge, *alias; 64ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (bridge = daemon->bridges; bridge; bridge = bridge->next) 65ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 66ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (alias = bridge->alias; alias; alias = alias->next) 67ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (strncmp(name, alias->iface, IF_NAMESIZE) == 0) 68ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 69ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int newindex; 70ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 71ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(newindex = if_nametoindex(bridge->iface))) 72ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 73ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), name); 74ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 75ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 76ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 77ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 78ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *indexp = newindex; 79ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strncpy(name, bridge->iface, IF_NAMESIZE); 80ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 81ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 82ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 83ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (alias) 84ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 85ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 86ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 87ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 88ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->if_names || (addr && daemon->if_addrs)) 89ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 90ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ret = 0; 91ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 92ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (tmp = daemon->if_names; tmp; tmp = tmp->next) 93ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (tmp->name && (strcmp(tmp->name, name) == 0)) 94ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ret = tmp->used = 1; 95ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 96ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (tmp = daemon->if_addrs; tmp; tmp = tmp->next) 97ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (addr && tmp->addr.sa.sa_family == family) 98ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 99ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (family == AF_INET && 100ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr) 101ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ret = tmp->used = 1; 102ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 103ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (family == AF_INET6 && 104ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, 105ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat &addr->addr.addr6)) 106ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ret = tmp->used = 1; 107ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 108ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 109ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 110ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 111ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (tmp = daemon->if_except; tmp; tmp = tmp->next) 112ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (tmp->name && (strcmp(tmp->name, name) == 0)) 113ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ret = 0; 114ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 115ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return ret; 116ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 117ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 118ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int iface_allowed(struct irec **irecp, int if_index, 119ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat union mysockaddr *addr, struct in_addr netmask) 120ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 121ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct irec *iface; 122ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int fd, mtu = 0, loopback; 123ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct ifreq ifr; 124ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int dhcp_ok = 1; 125ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct iname *tmp; 126ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 127ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* check whether the interface IP has been added already 128ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat we call this routine multiple times. */ 129ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (iface = *irecp; iface; iface = iface->next) 130ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (sockaddr_isequal(&iface->addr, addr)) 131ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 132ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 133ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1 || 134ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !indextoname(fd, if_index, ifr.ifr_name) || 135ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) 136ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 137ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (fd != -1) 138ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 139ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int errsave = errno; 140ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat close(fd); 141ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno = errsave; 142ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 143ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 144ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 145ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 146ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat loopback = ifr.ifr_flags & IFF_LOOPBACK; 147ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 148ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (ioctl(fd, SIOCGIFMTU, &ifr) != -1) 149ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat mtu = ifr.ifr_mtu; 150ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 151ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat close(fd); 152ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 153ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* If we are restricting the set of interfaces to use, make 154ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sure that loopback interfaces are in that set. */ 155ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->if_names && loopback) 156ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 157ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct iname *lo; 158ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (lo = daemon->if_names; lo; lo = lo->next) 159ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0) 160ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 161ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lo->isloop = 1; 162ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 163ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 164ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 165ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!lo && 166ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (lo = whine_malloc(sizeof(struct iname))) && 167ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (lo->name = whine_malloc(strlen(ifr.ifr_name)+1))) 168ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 169ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcpy(lo->name, ifr.ifr_name); 170ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lo->isloop = lo->used = 1; 171ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat lo->next = daemon->if_names; 172ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->if_names = lo; 173ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 174ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 175ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 176ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (addr->sa.sa_family == AF_INET && 177ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, NULL)) 178ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 179ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 180ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) 181ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0)) 182ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat dhcp_ok = 0; 183ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 184ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 185ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (addr->sa.sa_family == AF_INET6 && 186ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, NULL)) 187ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 188ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 189ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 190ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* add to list */ 191ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((iface = whine_malloc(sizeof(struct irec)))) 192ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 193ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iface->addr = *addr; 194ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iface->netmask = netmask; 195ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iface->dhcp_ok = dhcp_ok; 196ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iface->mtu = mtu; 197ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iface->next = *irecp; 198ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *irecp = iface; 199ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 200ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 201ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 202ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno = ENOMEM; 203ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 204ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 205ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 206ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 207ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int iface_allowed_v6(struct in6_addr *local, 208ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int scope, int if_index, void *vparam) 209ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 210ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat union mysockaddr addr; 211ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct in_addr netmask; /* dummy */ 212ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 213ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat netmask.s_addr = 0; 214ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 215ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(&addr, 0, sizeof(addr)); 216ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 217ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_len = sizeof(addr.in6); 218ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 219ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_family = AF_INET6; 220ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_addr = *local; 221ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_port = htons(daemon->port); 222ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_scope_id = scope; 223ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 224ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return iface_allowed((struct irec **)vparam, if_index, &addr, netmask); 225ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 226ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 227ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 228ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int iface_allowed_v4(struct in_addr local, int if_index, 229ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct in_addr netmask, struct in_addr broadcast, void *vparam) 230ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 231ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat union mysockaddr addr; 232ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 233ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(&addr, 0, sizeof(addr)); 234ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 235ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_len = sizeof(addr.in); 236ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 237ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_family = AF_INET; 238ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_addr = broadcast; /* warning */ 239ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_addr = local; 240ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_port = htons(daemon->port); 241ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 242ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return iface_allowed((struct irec **)vparam, if_index, &addr, netmask); 243ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 244ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 245ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint enumerate_interfaces(void) 246ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 247ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 248ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return iface_enumerate(&daemon->interfaces, iface_allowed_v4, iface_allowed_v6); 249ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else 250ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return iface_enumerate(&daemon->interfaces, iface_allowed_v4, NULL); 251ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 252ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 253ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 254ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* set NONBLOCK bit on fd: See Stevens 16.6 */ 255ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint fix_fd(int fd) 256ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 257ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int flags; 258ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 259ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((flags = fcntl(fd, F_GETFL)) == -1 || 260ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) 261ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 262ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 263ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 264ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 265ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 266ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(HAVE_IPV6) 267ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int create_ipv6_listener(struct listener **link, int port) 268ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 269ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat union mysockaddr addr; 270ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int tcpfd, fd; 271ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct listener *l; 272ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int opt = 1; 273ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 274ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(&addr, 0, sizeof(addr)); 275ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_family = AF_INET6; 276ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_addr = in6addr_any; 277ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_port = htons(port); 278ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 279ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_len = sizeof(addr.in6); 280ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 281ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 282ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* No error of the kernel doesn't support IPv6 */ 283ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) == -1) 284ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return (errno == EPROTONOSUPPORT || 285ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno == EAFNOSUPPORT || 286ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno == EINVAL); 287ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 288ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((tcpfd = socket(AF_INET6, SOCK_STREAM, 0)) == -1) 289ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 290ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 291ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || 292ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || 293ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 || 294ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 || 295ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !fix_fd(fd) || 296ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !fix_fd(tcpfd) || 297ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef IPV6_RECVPKTINFO 298ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1 || 299ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else 300ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(fd, IPV6_LEVEL, IPV6_PKTINFO, &opt, sizeof(opt)) == -1 || 301ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 302ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 || 303ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat listen(tcpfd, 5) == -1 || 304ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1) 305ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 306ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 307ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat l = safe_malloc(sizeof(struct listener)); 308ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat l->fd = fd; 309ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat l->tcpfd = tcpfd; 310ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat l->tftpfd = -1; 311ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat l->family = AF_INET6; 312ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat l->next = NULL; 313ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat *link = l; 314ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 315ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 316ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 317ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 318ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 319ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstruct listener *create_wildcard_listeners(void) 320ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 321ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat union mysockaddr addr; 322ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int opt = 1; 323ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct listener *l, *l6 = NULL; 324ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int tcpfd = -1, fd = -1, tftpfd = -1; 325ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 326ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(&addr, 0, sizeof(addr)); 327ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_family = AF_INET; 328ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_addr.s_addr = INADDR_ANY; 329ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_port = htons(daemon->port); 330ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 331ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_len = sizeof(struct sockaddr_in); 332ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 333ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 334ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->port != 0) 335ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 336ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 337ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 || 338ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (tcpfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 339ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 340ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 341ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || 342ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 || 343ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat listen(tcpfd, 5) == -1 || 344ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !fix_fd(tcpfd) || 345ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 346ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !create_ipv6_listener(&l6, daemon->port) || 347ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 348ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || 349ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !fix_fd(fd) || 350ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(HAVE_LINUX_NETWORK) 351ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(fd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 || 352ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF) 353ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 || 354ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 || 355ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 356ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1) 357ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 358ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 359ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 360ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_TFTP 361ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->options & OPT_TFTP) 362ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 363ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_port = htons(TFTP_PORT); 364ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 365ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 366ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 367ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!fix_fd(tftpfd) || 368ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(HAVE_LINUX_NETWORK) 369ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(tftpfd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 || 370ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF) 371ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(tftpfd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 || 372ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(tftpfd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 || 373ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 374ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat bind(tftpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1) 375ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 376ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 377ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 378ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 379ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat l = safe_malloc(sizeof(struct listener)); 380ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat l->family = AF_INET; 381ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat l->fd = fd; 382ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat l->tcpfd = tcpfd; 383ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat l->tftpfd = tftpfd; 384ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat l->next = l6; 385ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 386ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return l; 387ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 388ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 389ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstruct listener *create_bound_listeners(void) 390ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 391ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct listener *listeners = NULL; 392ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct irec *iface; 393ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int rc, opt = 1; 394ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 395ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat static int dad_count = 0; 396ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 397ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 398ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (iface = daemon->interfaces; iface; iface = iface->next) 399ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 400ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct listener *new = safe_malloc(sizeof(struct listener)); 401ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->family = iface->addr.sa.sa_family; 402ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->iface = iface; 403ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->next = listeners; 404ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->tftpfd = -1; 405ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->tcpfd = -1; 406ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->fd = -1; 407ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat listeners = new; 408ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 409ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->port != 0) 410ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 411ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 || 412ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 || 413ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || 414ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(new->tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || 415ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !fix_fd(new->tcpfd) || 416ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !fix_fd(new->fd)) 417ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("failed to create listening socket: %s"), NULL, EC_BADNET); 418ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 419ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 420ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (iface->addr.sa.sa_family == AF_INET6) 421ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 422ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (setsockopt(new->fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 || 423ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(new->tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) 424ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("failed to set IPV6 options on listening socket: %s"), NULL, EC_BADNET); 425ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 426ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 427ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 428ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while(1) 429ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 430ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((rc = bind(new->fd, &iface->addr.sa, sa_len(&iface->addr))) != -1) 431ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 432ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 433ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 434ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* An interface may have an IPv6 address which is still undergoing DAD. 435ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat If so, the bind will fail until the DAD completes, so we try over 20 seconds 436ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat before failing. */ 437ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (iface->addr.sa.sa_family == AF_INET6 && (errno == ENODEV || errno == EADDRNOTAVAIL) && 438ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat dad_count++ < DAD_WAIT) 439ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 440ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sleep(1); 441ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 442ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 443ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 444ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 445ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 446ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 447ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (rc == -1 || bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1) 448ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 449ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat prettyprint_addr(&iface->addr, daemon->namebuff); 450ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("failed to bind listening socket for %s: %s"), 451ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->namebuff, EC_BADNET); 452ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 453ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 454ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (listen(new->tcpfd, 5) == -1) 455ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("failed to listen on socket: %s"), NULL, EC_BADNET); 456ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 457ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 458ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_TFTP 459ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((daemon->options & OPT_TFTP) && iface->addr.sa.sa_family == AF_INET && iface->dhcp_ok) 460ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 461ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat short save = iface->addr.in.sin_port; 462ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iface->addr.in.sin_port = htons(TFTP_PORT); 463ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((new->tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 || 464ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(new->tftpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || 465ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !fix_fd(new->tftpfd) || 466ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat bind(new->tftpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1) 467ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("failed to create TFTP socket: %s"), NULL, EC_BADNET); 468ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iface->addr.in.sin_port = save; 469ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 470ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 471ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 472ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 473ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 474ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return listeners; 475ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 476ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 477ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 478ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* return a UDP socket bound to a random port, have to cope with straying into 479ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat occupied port nos and reserved ones. */ 480ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint random_sock(int family) 481ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 482ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int fd; 483ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 484ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((fd = socket(family, SOCK_DGRAM, 0)) != -1) 485ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 486ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat union mysockaddr addr; 487ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port; 488ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int tries = ports_avail < 30 ? 3 * ports_avail : 100; 489ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 490ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(&addr, 0, sizeof(addr)); 491ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.sa.sa_family = family; 492ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 493ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* don't loop forever if all ports in use. */ 494ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 495ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (fix_fd(fd)) 496ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while(tries--) 497ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 498ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned short port = rand16(); 499ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 500ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->min_port != 0) 501ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat port = htons(daemon->min_port + (port % ((unsigned short)ports_avail))); 502ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 503ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (family == AF_INET) 504ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 505ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_addr.s_addr = INADDR_ANY; 506ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_port = port; 507ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 508ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_len = sizeof(struct sockaddr_in); 509ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 510ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 511ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 512ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 513ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 514ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_addr = in6addr_any; 515ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_port = port; 516ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 517ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_len = sizeof(struct sockaddr_in6); 518ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 519ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 520ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 521ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 522ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0) 523ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return fd; 524ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 525ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (errno != EADDRINUSE && errno != EACCES) 526ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 527ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 528ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 529ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat close(fd); 530ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 531ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 532ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return -1; 533ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 534ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 535ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 536ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp) 537ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 538ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat union mysockaddr addr_copy = *addr; 539ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 540ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* cannot set source _port_ for TCP connections. */ 541ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (is_tcp) 542ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 543ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (addr_copy.sa.sa_family == AF_INET) 544ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr_copy.in.sin_port = 0; 545ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 546ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 547ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr_copy.in6.sin6_port = 0; 548ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 549ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 550ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 551ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1) 552ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 553ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 554ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(SO_BINDTODEVICE) 555ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (intname[0] != 0 && 556ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, strlen(intname)) == -1) 557ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 558ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 559ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 560ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 561ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 562ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 563ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname) 564ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 565ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct serverfd *sfd; 566ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int errsave; 567ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 568ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* when using random ports, servers which would otherwise use 569ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat the INADDR_ANY/port0 socket have sfd set to NULL */ 570ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!daemon->osport && intname[0] == 0) 571ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 572ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno = 0; 573ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 574ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (addr->sa.sa_family == AF_INET && 575ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr->in.sin_addr.s_addr == INADDR_ANY && 576ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr->in.sin_port == htons(0)) 577ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 578ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 579ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 580ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (addr->sa.sa_family == AF_INET6 && 581ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 && 582ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr->in6.sin6_port == htons(0)) 583ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 584ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 585ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 586ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 587ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* may have a suitable one already */ 588ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (sfd = daemon->sfds; sfd; sfd = sfd->next ) 589ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (sockaddr_isequal(&sfd->source_addr, addr) && 590ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcmp(intname, sfd->interface) == 0) 591ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return sfd; 592ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 593ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* need to make a new one. */ 594ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno = ENOMEM; /* in case malloc fails. */ 595ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(sfd = whine_malloc(sizeof(struct serverfd)))) 596ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 597ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 598ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1) 599ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 600ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(sfd); 601ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 602ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 603ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 604ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd)) 605ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 606ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errsave = errno; /* save error from bind. */ 607ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat close(sfd->fd); 608ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(sfd); 609ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno = errsave; 610ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 611ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 612ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 613ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcpy(sfd->interface, intname); 614ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sfd->source_addr = *addr; 615ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sfd->next = daemon->sfds; 616ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->sfds = sfd; 617ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return sfd; 618ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 619ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 620ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* create upstream sockets during startup, before root is dropped which may be needed 621ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat this allows query_port to be a low port and interface binding */ 622ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid pre_allocate_sfds(void) 623ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 624ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct server *srv; 625ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 626ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->query_port != 0) 627ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 628ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat union mysockaddr addr; 629ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(&addr, 0, sizeof(addr)); 630ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_family = AF_INET; 631ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_addr.s_addr = INADDR_ANY; 632ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_port = htons(daemon->query_port); 633ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 634ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_len = sizeof(struct sockaddr_in); 635ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 636ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat allocate_sfd(&addr, ""); 637ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 638ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(&addr, 0, sizeof(addr)); 639ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_family = AF_INET6; 640ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_addr = in6addr_any; 641ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_port = htons(daemon->query_port); 642ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 643ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_len = sizeof(struct sockaddr_in6); 644ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 645ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat allocate_sfd(&addr, ""); 646ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 647ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 648ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 649ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (srv = daemon->servers; srv; srv = srv->next) 650ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) && 651ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !allocate_sfd(&srv->source_addr, srv->interface) && 652ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno != 0 && 653ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (daemon->options & OPT_NOWILD)) 654ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 655ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat prettyprint_addr(&srv->addr, daemon->namebuff); 656ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (srv->interface[0] != 0) 657ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 658ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcat(daemon->namebuff, " "); 659ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcat(daemon->namebuff, srv->interface); 660ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 661ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("failed to bind server socket for %s: %s"), 662ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->namebuff, EC_BADNET); 663ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 664ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 665ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 666ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 667ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid check_servers(void) 668ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 669ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct irec *iface; 670ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct server *new, *tmp, *ret = NULL; 671ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int port = 0; 672ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 673ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (new = daemon->servers; new; new = tmp) 674ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 675ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat tmp = new->next; 676ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 677ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR))) 678ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 679ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat port = prettyprint_addr(&new->addr, daemon->namebuff); 680ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 681ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */ 682ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (new->addr.sa.sa_family == AF_INET && 683ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->addr.in.sin_addr.s_addr == 0) 684ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 685ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(new); 686ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 687ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 688ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 689ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (iface = daemon->interfaces; iface; iface = iface->next) 690ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (sockaddr_isequal(&new->addr, &iface->addr)) 691ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 692ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (iface) 693ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 694ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff); 695ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(new); 696ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 697ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 698ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 699ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Do we need a socket set? */ 700ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!new->sfd && 701ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !(new->sfd = allocate_sfd(&new->source_addr, new->interface)) && 702ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno != 0) 703ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 704ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_WARNING, 705ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat _("ignoring nameserver %s - cannot make/bind socket: %s"), 706ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->namebuff, strerror(errno)); 707ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(new); 708ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 709ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 710ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 711ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 712ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* reverse order - gets it right. */ 713ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->next = ret; 714ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ret = new; 715ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 716ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS)) 717ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 718ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *s1, *s2; 719ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(new->flags & SERV_HAS_DOMAIN)) 720ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat s1 = _("unqualified"), s2 = _("names"); 721ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (strlen(new->domain) == 0) 722ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat s1 = _("default"), s2 = ""; 723ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 724ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat s1 = _("domain"), s2 = new->domain; 725ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 726ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (new->flags & SERV_NO_ADDR) 727ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2); 728ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (!(new->flags & SERV_LITERAL_ADDRESS)) 729ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2); 730ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 731ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (new->interface[0] != 0) 732ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface); 733ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 734ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port); 735ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 736ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 737ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->servers = ret; 738ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 739ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 74033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifdef __ANDROID__ 74133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat/* 74233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat * Takes a string in the format "1.2.3.4:1.2.3.4:..." - up to 1024 bytes in length 74333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat */ 74433b344454b95ed99bad7d3fe4d493870923deaf6San Mehatint set_servers(const char *servers) 74533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat{ 74633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat char s[1024]; 74733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat struct server *old_servers = NULL; 74833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat struct server *new_servers = NULL; 74933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat struct server *serv; 75033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 75133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat strncpy(s, servers, sizeof(s)); 75233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 75333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat /* move old servers to free list - we can reuse the memory 75433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat and not risk malloc if there are the same or fewer new servers. 75533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat Servers which were specced on the command line go to the new list. */ 75633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat for (serv = daemon->servers; serv;) 75733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat { 75833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat struct server *tmp = serv->next; 75933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat if (serv->flags & SERV_FROM_RESOLV) 76033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat { 76133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->next = old_servers; 76233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat old_servers = serv; 76333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat /* forward table rules reference servers, so have to blow them away */ 76433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat server_gone(serv); 76533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 76633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat else 76733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat { 76833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->next = new_servers; 76933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat new_servers = serv; 77033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 77133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv = tmp; 77233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 77333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 77433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat char *next = s; 77533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat char *saddr; 77633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 77733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat while ((saddr = strsep(&next, ":"))) { 77833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat union mysockaddr addr, source_addr; 77933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat memset(&addr, 0, sizeof(addr)); 78033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat memset(&source_addr, 0, sizeof(source_addr)); 78133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 78233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat if ((addr.in.sin_addr.s_addr = inet_addr(saddr)) != (in_addr_t) -1) 78333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat { 78433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 78533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in); 78633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif 78733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in.sin_family = addr.in.sin_family = AF_INET; 78833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat addr.in.sin_port = htons(NAMESERVER_PORT); 78933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in.sin_addr.s_addr = INADDR_ANY; 79033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in.sin_port = htons(daemon->query_port); 79133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 79233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifdef HAVE_IPV6 79333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat else if (inet_pton(AF_INET6, saddr, &addr.in6.sin6_addr) > 0) 79433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat { 79533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 79633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6); 79733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif 79833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6; 79933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat addr.in6.sin6_port = htons(NAMESERVER_PORT); 80033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in6.sin6_addr = in6addr_any; 80133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in6.sin6_port = htons(daemon->query_port); 80233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 80333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif /* IPV6 */ 80433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat else 80533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat continue; 80633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 80733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat if (old_servers) 80833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat { 80933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv = old_servers; 81033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat old_servers = old_servers->next; 81133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 81233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat else if (!(serv = whine_malloc(sizeof (struct server)))) 81333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat continue; 81433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 81533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat /* this list is reverse ordered: 81633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat it gets reversed again in check_servers */ 81733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->next = new_servers; 81833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat new_servers = serv; 81933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->addr = addr; 82033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->source_addr = source_addr; 82133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->domain = NULL; 82233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->interface[0] = 0; 82333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->sfd = NULL; 82433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->flags = SERV_FROM_RESOLV; 82533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->queries = serv->failed_queries = 0; 82633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 82733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 82833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat /* Free any memory not used. */ 82933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat while (old_servers) 83033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat { 83133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat struct server *tmp = old_servers->next; 83233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat free(old_servers); 83333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat old_servers = tmp; 83433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 83533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 83633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat daemon->servers = new_servers; 83733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat return 0; 83833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat} 83933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif 84033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 841ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* Return zero if no servers found, in that case we keep polling. 842ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat This is a protection against an update-time/write race on resolv.conf */ 843ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint reload_servers(char *fname) 844ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 845ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat FILE *f; 846ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *line; 847ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct server *old_servers = NULL; 848ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct server *new_servers = NULL; 849ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct server *serv; 850ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int gotone = 0; 851ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 852ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* buff happens to be MAXDNAME long... */ 853ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(f = fopen(fname, "r"))) 854ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 855ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno)); 856ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 857ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 858ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 859ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* move old servers to free list - we can reuse the memory 860ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat and not risk malloc if there are the same or fewer new servers. 861ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat Servers which were specced on the command line go to the new list. */ 862ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (serv = daemon->servers; serv;) 863ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 864ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct server *tmp = serv->next; 865ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (serv->flags & SERV_FROM_RESOLV) 866ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 867ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->next = old_servers; 868ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat old_servers = serv; 869ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* forward table rules reference servers, so have to blow them away */ 870ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat server_gone(serv); 871ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 872ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 873ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 874ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->next = new_servers; 875ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new_servers = serv; 876ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 877ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv = tmp; 878ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 879ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 880ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while ((line = fgets(daemon->namebuff, MAXDNAME, f))) 881ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 882ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat union mysockaddr addr, source_addr; 883ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *token = strtok(line, " \t\n\r"); 884ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 885ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!token) 886ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 887ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0) 888ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 889ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(token = strtok(NULL, " \t\n\r"))) 890ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 891ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 892ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(&addr, 0, sizeof(addr)); 893ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(&source_addr, 0, sizeof(source_addr)); 894ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 895ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1) 896ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 897ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 898ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in); 899ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 900ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in.sin_family = addr.in.sin_family = AF_INET; 901ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_port = htons(NAMESERVER_PORT); 902ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in.sin_addr.s_addr = INADDR_ANY; 903ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in.sin_port = htons(daemon->query_port); 904ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 905ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 906ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0) 907ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 908ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 909ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6); 910ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 911ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6; 912ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_port = htons(NAMESERVER_PORT); 913ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in6.sin6_addr = in6addr_any; 914ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in6.sin6_port = htons(daemon->query_port); 915ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 916ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif /* IPV6 */ 917ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 918ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 919ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 920ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (old_servers) 921ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 922ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv = old_servers; 923ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat old_servers = old_servers->next; 924ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 925ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (!(serv = whine_malloc(sizeof (struct server)))) 926ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 927ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 928ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* this list is reverse ordered: 929ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat it gets reversed again in check_servers */ 930ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->next = new_servers; 931ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new_servers = serv; 932ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->addr = addr; 933ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->source_addr = source_addr; 934ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->domain = NULL; 935ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->interface[0] = 0; 936ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->sfd = NULL; 937ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->flags = SERV_FROM_RESOLV; 938ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->queries = serv->failed_queries = 0; 939ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat gotone = 1; 940ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 941ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 942ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Free any memory not used. */ 943ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while (old_servers) 944ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 945ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct server *tmp = old_servers->next; 946ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(old_servers); 947ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat old_servers = tmp; 948ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 949ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 950ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->servers = new_servers; 951ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat fclose(f); 952ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 953ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return gotone; 954ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 955ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 956ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 957ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* Use an IPv4 listener socket for ioctling */ 958ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstruct in_addr get_ifaddr(char *intr) 959ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 960ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct listener *l; 961ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct ifreq ifr; 962ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 963ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (l = daemon->listeners; l && l->family != AF_INET; l = l->next); 964ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 965ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strncpy(ifr.ifr_name, intr, IF_NAMESIZE); 966ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ifr.ifr_addr.sa_family = AF_INET; 967ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 968ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!l || ioctl(l->fd, SIOCGIFADDR, &ifr) == -1) 969ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = -1; 970ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 971ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; 972ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 973ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 974ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 975ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 976