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 } 8741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 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 38941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#ifdef __ANDROID__ 39041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt/** 39141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * for a single given irec (interface name and address) create 39241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * a set of sockets listening. This is a copy of the code inside the loop 39341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * of create_bound_listeners below and is added here to allow us 39441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * to create just a single new listener dynamically when our interface 39541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * list is changed. 39641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * 39741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * iface - input of the new interface details to listen on 39841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * listeners - output. Creates a new struct listener and inserts at head of the list 39941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * 40041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * die's on errors, so don't pass bad data. 40141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt */ 40241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwaltvoid create_bound_listener(struct listener **listeners, struct irec *iface) 40341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt{ 40441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt int rc, opt = 1; 40541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#ifdef HAVE_IPV6 40641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt static int dad_count = 0; 40741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#endif 40841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 40941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt struct listener *new = safe_malloc(sizeof(struct listener)); 41041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt new->family = iface->addr.sa.sa_family; 41141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt new->iface = iface; 41241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt new->next = *listeners; 41341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt new->tftpfd = -1; 41441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt new->tcpfd = -1; 41541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt new->fd = -1; 41641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt *listeners = new; 41741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 41841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (daemon->port != 0) 41941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt { 42041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 || 42141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt (new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 || 42241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || 42341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt setsockopt(new->tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || 42441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt !fix_fd(new->tcpfd) || 42541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt !fix_fd(new->fd)) 42641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt die(_("failed to create listening socket: %s"), NULL, EC_BADNET); 42741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 42841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#ifdef HAVE_IPV6 42941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (iface->addr.sa.sa_family == AF_INET6) 43041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt { 43141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (setsockopt(new->fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 || 43241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt setsockopt(new->tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) 43341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt die(_("failed to set IPV6 options on listening socket: %s"), NULL, EC_BADNET);\ 43441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 43541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#endif 43641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 43741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt while(1) 43841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt { 43941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if ((rc = bind(new->fd, &iface->addr.sa, sa_len(&iface->addr))) != -1) 44041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt break; 44141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 44241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#ifdef HAVE_IPV6 44341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt /* An interface may have an IPv6 address which is still undergoing DAD. 44441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt If so, the bind will fail until the DAD completes, so we try over 20 seconds 44541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt before failing. */ 44641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (iface->addr.sa.sa_family == AF_INET6 && (errno == ENODEV || errno == EADDRNOTAVAIL) && 44741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt dad_count++ < DAD_WAIT) 44841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt { 44941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt sleep(1); 45041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt continue; 45141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 45241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#endif 45341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt break; 45441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 45541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 45641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (rc == -1 || bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1) 45741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt { 45841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt prettyprint_addr(&iface->addr, daemon->namebuff); 45941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt die(_("failed to bind listening socket for %s: %s"), daemon->namebuff, EC_BADNET); 46041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 46141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 46241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (listen(new->tcpfd, 5) == -1) 46341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt die(_("failed to listen on socket: %s"), NULL, EC_BADNET); 46441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 46541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 46641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#ifdef HAVE_TFTP 46741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if ((daemon->options & OPT_TFTP) && iface->addr.sa.sa_family == AF_INET && iface->dhcp_ok) 46841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt { 46941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt short save = iface->addr.in.sin_port; 47041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt iface->addr.in.sin_port = htons(TFTP_PORT); 47141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if ((new->tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 || 47241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt setsockopt(new->tftpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || 47341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt !fix_fd(new->tftpfd) || 47441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt bind(new->tftpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1) 47541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt die(_("failed to create TFTP socket: %s"), NULL, EC_BADNET); 47641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt iface->addr.in.sin_port = save; 47741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 47841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#endif 47941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt} 48041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 48141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt/** 482e226badb960695447af4c480bb183ec35c411bbfErik Kline * If a listener has a struct irec pointer whose address matches the newly 483e226badb960695447af4c480bb183ec35c411bbfErik Kline * malloc()d struct irec's address, update its pointer to refer to this new 484e226badb960695447af4c480bb183ec35c411bbfErik Kline * struct irec instance. 485e226badb960695447af4c480bb183ec35c411bbfErik Kline * 486e226badb960695447af4c480bb183ec35c411bbfErik Kline * Otherwise, any listeners that are preserved across interface list changes 487e226badb960695447af4c480bb183ec35c411bbfErik Kline * will point at interface structures that are free()d at the end of 488e226badb960695447af4c480bb183ec35c411bbfErik Kline * set_interfaces(), and can get overwritten by subsequent memory allocations. 489e226badb960695447af4c480bb183ec35c411bbfErik Kline * 490e226badb960695447af4c480bb183ec35c411bbfErik Kline * See b/17475756 for further discussion. 491e226badb960695447af4c480bb183ec35c411bbfErik Kline */ 492e226badb960695447af4c480bb183ec35c411bbfErik Klinevoid fixup_possible_existing_listener(struct irec *new_iface) { 493e226badb960695447af4c480bb183ec35c411bbfErik Kline /* find the listener, if present */ 494e226badb960695447af4c480bb183ec35c411bbfErik Kline struct listener *l; 495e226badb960695447af4c480bb183ec35c411bbfErik Kline for (l = daemon->listeners; l; l = l->next) { 496e226badb960695447af4c480bb183ec35c411bbfErik Kline struct irec *listener_iface = l->iface; 497e226badb960695447af4c480bb183ec35c411bbfErik Kline if (listener_iface) { 498e226badb960695447af4c480bb183ec35c411bbfErik Kline if (sockaddr_isequal(&listener_iface->addr, &new_iface->addr)) { 499e226badb960695447af4c480bb183ec35c411bbfErik Kline l->iface = new_iface; 500e226badb960695447af4c480bb183ec35c411bbfErik Kline return; 501e226badb960695447af4c480bb183ec35c411bbfErik Kline } 502e226badb960695447af4c480bb183ec35c411bbfErik Kline } 503e226badb960695447af4c480bb183ec35c411bbfErik Kline } 504e226badb960695447af4c480bb183ec35c411bbfErik Kline} 505e226badb960695447af4c480bb183ec35c411bbfErik Kline 506e226badb960695447af4c480bb183ec35c411bbfErik Kline/** 50741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * Close the sockets listening on the given interface 50841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * 50941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * This new function is needed as we're dynamically changing the interfaces 51041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * we listen on. Before they'd be opened once in create_bound_listeners and stay 51141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * until we exited. Now, if an interface moves off the to-listen list we need to 51241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * close out the listeners and keep trucking. 51341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * 51441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * interface - input of the interface details to listen on 51541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt */ 51641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwaltint close_bound_listener(struct irec *interface) 51741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt{ 51841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt /* find the listener */ 51941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt struct listener **l, *listener; 52041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt for (l = &(daemon->listeners); *l; l = &((*l)->next)) { 52141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt struct irec *listener_iface = (*l)->iface; 52241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (listener_iface && interface) { 52341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (sockaddr_isequal(&listener_iface->addr, &interface->addr)) { 52441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt break; 52541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 52641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } else { 52741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (interface == NULL && listener_iface == NULL) { 52841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt break; 52941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 53041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 53141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 53241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt listener = *l; 53341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (listener == NULL) return 0; 53441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 53541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (listener->tftpfd != -1) 53641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt { 53741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt close(listener->tftpfd); 53841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt listener->tftpfd = -1; 53941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 54041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (listener->tcpfd != -1) 54141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt { 54241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt close(listener->tcpfd); 54341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt listener->tcpfd = -1; 54441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 54541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (listener->fd != -1) 54641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt { 54741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt close(listener->fd); 54841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt listener->fd = -1; 54941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 55041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt *l = listener->next; 55141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt free(listener); 55241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt return -1; 55341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt} 55441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#endif /* __ANDROID__ */ 55541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 556ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstruct listener *create_bound_listeners(void) 557ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 558ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct listener *listeners = NULL; 559ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct irec *iface; 56041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#ifndef __ANDROID__ 561ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int rc, opt = 1; 562ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 563ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat static int dad_count = 0; 564ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 56541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#endif 566ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 567ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (iface = daemon->interfaces; iface; iface = iface->next) 568ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 56941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#ifdef __ANDROID__ 57041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt create_bound_listener(&listeners, iface); 57141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#else 572ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct listener *new = safe_malloc(sizeof(struct listener)); 573ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->family = iface->addr.sa.sa_family; 574ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->iface = iface; 575ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->next = listeners; 576ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->tftpfd = -1; 577ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->tcpfd = -1; 578ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->fd = -1; 579ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat listeners = new; 580ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 581ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->port != 0) 582ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 583ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 || 584ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 || 585ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || 586ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(new->tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || 587ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !fix_fd(new->tcpfd) || 588ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !fix_fd(new->fd)) 589ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("failed to create listening socket: %s"), NULL, EC_BADNET); 590ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 591ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 592ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (iface->addr.sa.sa_family == AF_INET6) 593ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 594ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (setsockopt(new->fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 || 595ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(new->tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) 596ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("failed to set IPV6 options on listening socket: %s"), NULL, EC_BADNET); 597ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 598ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 599ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 600ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while(1) 601ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 602ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((rc = bind(new->fd, &iface->addr.sa, sa_len(&iface->addr))) != -1) 603ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 604ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 605ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 606ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* An interface may have an IPv6 address which is still undergoing DAD. 607ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat If so, the bind will fail until the DAD completes, so we try over 20 seconds 608ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat before failing. */ 609ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (iface->addr.sa.sa_family == AF_INET6 && (errno == ENODEV || errno == EADDRNOTAVAIL) && 610ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat dad_count++ < DAD_WAIT) 611ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 612ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sleep(1); 613ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 614ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 615ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 616ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 617ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 618ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 619ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (rc == -1 || bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1) 620ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 621ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat prettyprint_addr(&iface->addr, daemon->namebuff); 622ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("failed to bind listening socket for %s: %s"), 623ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->namebuff, EC_BADNET); 624ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 625ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 626ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (listen(new->tcpfd, 5) == -1) 627ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("failed to listen on socket: %s"), NULL, EC_BADNET); 628ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 629ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 630ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_TFTP 631ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((daemon->options & OPT_TFTP) && iface->addr.sa.sa_family == AF_INET && iface->dhcp_ok) 632ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 633ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat short save = iface->addr.in.sin_port; 634ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iface->addr.in.sin_port = htons(TFTP_PORT); 635ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((new->tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 || 636ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(new->tftpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || 637ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat !fix_fd(new->tftpfd) || 638ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat bind(new->tftpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1) 639ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("failed to create TFTP socket: %s"), NULL, EC_BADNET); 640ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat iface->addr.in.sin_port = save; 641ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 642ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 64341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#endif /* !__ANDROID */ 644ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 645ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 646ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return listeners; 647ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 648ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 649ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 650ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* return a UDP socket bound to a random port, have to cope with straying into 651ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat occupied port nos and reserved ones. */ 652ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint random_sock(int family) 653ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 654ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int fd; 655ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 656ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((fd = socket(family, SOCK_DGRAM, 0)) != -1) 657ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 658ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat union mysockaddr addr; 659ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port; 660ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int tries = ports_avail < 30 ? 3 * ports_avail : 100; 661ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 662ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(&addr, 0, sizeof(addr)); 663ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.sa.sa_family = family; 664ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 665ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* don't loop forever if all ports in use. */ 666ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 667ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (fix_fd(fd)) 668ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while(tries--) 669ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 670ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat unsigned short port = rand16(); 671ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 672ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->min_port != 0) 673ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat port = htons(daemon->min_port + (port % ((unsigned short)ports_avail))); 674ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 675ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (family == AF_INET) 676ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 677ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_addr.s_addr = INADDR_ANY; 678ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_port = port; 679ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 680ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_len = sizeof(struct sockaddr_in); 681ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 682ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 683ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 684ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 685ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 686ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_addr = in6addr_any; 687ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_port = port; 688ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 689ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_len = sizeof(struct sockaddr_in6); 690ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 691ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 692ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 693ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 694ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0) 695ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return fd; 696ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 697ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (errno != EADDRINUSE && errno != EACCES) 698ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 699ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 700ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 701ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat close(fd); 702ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 703ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 704ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return -1; 705ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 706ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 707ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 70868eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colittiint local_bind(int fd, union mysockaddr *addr, char *intname, uint32_t mark, int is_tcp) 709ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 710ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat union mysockaddr addr_copy = *addr; 711ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 712ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* cannot set source _port_ for TCP connections. */ 713ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (is_tcp) 714ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 715ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (addr_copy.sa.sa_family == AF_INET) 716ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr_copy.in.sin_port = 0; 717ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 718ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 719ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr_copy.in6.sin6_port = 0; 720ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 721ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 722ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 723ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1) 724ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 725ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 726ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(SO_BINDTODEVICE) 727ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (intname[0] != 0 && 728ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, strlen(intname)) == -1) 729ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 730ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 731ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 73268eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti if (mark != 0 && setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) == -1) 73368eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti return 0; 73468eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti 735ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 1; 736ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 737ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 73868eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colittistatic struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname, uint32_t mark) 739ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 740ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct serverfd *sfd; 741ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int errsave; 742ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 743ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* when using random ports, servers which would otherwise use 744ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat the INADDR_ANY/port0 socket have sfd set to NULL */ 745ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!daemon->osport && intname[0] == 0) 746ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 747ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno = 0; 748ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 749ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (addr->sa.sa_family == AF_INET && 750ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr->in.sin_addr.s_addr == INADDR_ANY && 751ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr->in.sin_port == htons(0)) 752ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 753ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 754ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 755ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (addr->sa.sa_family == AF_INET6 && 756ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 && 757ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr->in6.sin6_port == htons(0)) 758ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 759ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 760ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 761ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 762ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* may have a suitable one already */ 763ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (sfd = daemon->sfds; sfd; sfd = sfd->next ) 764ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (sockaddr_isequal(&sfd->source_addr, addr) && 76568eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti mark == sfd->mark && 766ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcmp(intname, sfd->interface) == 0) 767ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return sfd; 768ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 769ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* need to make a new one. */ 770ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno = ENOMEM; /* in case malloc fails. */ 771ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(sfd = whine_malloc(sizeof(struct serverfd)))) 772ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 773ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 774ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1) 775ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 776ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(sfd); 777ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 778ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 779ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 78068eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti if (!local_bind(sfd->fd, addr, intname, mark, 0) || !fix_fd(sfd->fd)) 781ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 782ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errsave = errno; /* save error from bind. */ 783ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat close(sfd->fd); 784ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(sfd); 785ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno = errsave; 786ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return NULL; 787ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 788ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 789ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcpy(sfd->interface, intname); 790ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sfd->source_addr = *addr; 79168eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti sfd->mark = mark; 792ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat sfd->next = daemon->sfds; 793ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->sfds = sfd; 794ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return sfd; 795ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 796ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 797ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* create upstream sockets during startup, before root is dropped which may be needed 798ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat this allows query_port to be a low port and interface binding */ 799ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid pre_allocate_sfds(void) 800ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 801ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct server *srv; 802ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 803ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (daemon->query_port != 0) 804ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 805ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat union mysockaddr addr; 806ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(&addr, 0, sizeof(addr)); 807ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_family = AF_INET; 808ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_addr.s_addr = INADDR_ANY; 809ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_port = htons(daemon->query_port); 810ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 811ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_len = sizeof(struct sockaddr_in); 812ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 81368eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti allocate_sfd(&addr, "", 0); 814ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 815ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(&addr, 0, sizeof(addr)); 816ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_family = AF_INET6; 817ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_addr = in6addr_any; 818ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_port = htons(daemon->query_port); 819ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 820ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_len = sizeof(struct sockaddr_in6); 821ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 82268eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti allocate_sfd(&addr, "", 0); 823ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 824ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 825ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 826ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (srv = daemon->servers; srv; srv = srv->next) 827ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) && 82868eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti !allocate_sfd(&srv->source_addr, srv->interface, srv->mark) && 829ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno != 0 && 830ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat (daemon->options & OPT_NOWILD)) 831ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 832ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat prettyprint_addr(&srv->addr, daemon->namebuff); 833ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (srv->interface[0] != 0) 834ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 835ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcat(daemon->namebuff, " "); 836ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strcat(daemon->namebuff, srv->interface); 837ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 838ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat die(_("failed to bind server socket for %s: %s"), 839ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->namebuff, EC_BADNET); 840ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 841ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 842ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 843ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 844ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid check_servers(void) 845ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 846ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct irec *iface; 847ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct server *new, *tmp, *ret = NULL; 848ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int port = 0; 849ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 850ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (new = daemon->servers; new; new = tmp) 851ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 852ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat tmp = new->next; 853ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 854ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR))) 855ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 856ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat port = prettyprint_addr(&new->addr, daemon->namebuff); 857ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 858ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */ 859ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (new->addr.sa.sa_family == AF_INET && 860ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->addr.in.sin_addr.s_addr == 0) 861ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 862ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(new); 863ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 864ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 865ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 866ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (iface = daemon->interfaces; iface; iface = iface->next) 867ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (sockaddr_isequal(&new->addr, &iface->addr)) 868ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat break; 869ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (iface) 870ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 871ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff); 872ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(new); 873ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 874ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 875ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 876ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Do we need a socket set? */ 877ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!new->sfd && 87868eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti !(new->sfd = allocate_sfd(&new->source_addr, new->interface, new->mark)) && 879ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat errno != 0) 880ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 881ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_WARNING, 882ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat _("ignoring nameserver %s - cannot make/bind socket: %s"), 883ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->namebuff, strerror(errno)); 884ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(new); 885ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 886ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 887ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 888ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 889ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* reverse order - gets it right. */ 890ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new->next = ret; 891ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ret = new; 892ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 893ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS)) 894ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 895ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *s1, *s2; 896ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(new->flags & SERV_HAS_DOMAIN)) 897ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat s1 = _("unqualified"), s2 = _("names"); 898ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (strlen(new->domain) == 0) 899ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat s1 = _("default"), s2 = ""; 900ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 901ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat s1 = _("domain"), s2 = new->domain; 902ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 903ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (new->flags & SERV_NO_ADDR) 904ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2); 905ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (!(new->flags & SERV_LITERAL_ADDRESS)) 906ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2); 907ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 908ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (new->interface[0] != 0) 909ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface); 910ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 911ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port); 912ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 913ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 914ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->servers = ret; 915ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 916ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 91733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifdef __ANDROID__ 91841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt/* #define __ANDROID_DEBUG__ 1 */ 91941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt/* 92041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * Ingests a new list of interfaces and starts to listen on them, adding only the new 92141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * and stopping to listen to any interfaces not on the new list. 92241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * 92341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt * interfaces - input in the format "bt-pan:eth0:wlan0:..>" up to 1024 bytes long 92441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt */ 92541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwaltvoid set_interfaces(const char *interfaces) 92641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt{ 92741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt struct iname *if_tmp; 92841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt struct iname *prev_if_names; 92941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt struct irec *old_iface, *new_iface, *prev_interfaces; 93041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt char s[1024]; 93141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt char *next = s; 93241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt char *interface; 93341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt int was_wild = 0; 93441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 93541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#ifdef __ANDROID_DEBUG__ 93641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt my_syslog(LOG_DEBUG, _("set_interfaces(%s)"), interfaces); 93741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#endif 93841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt prev_if_names = daemon->if_names; 93941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt daemon->if_names = NULL; 94041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 94141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt prev_interfaces = daemon->interfaces; 94241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt daemon->interfaces = NULL; 94341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 94441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (strlen(interfaces) > sizeof(s)) { 94541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt die(_("interface string too long: %s"), NULL, EC_BADNET); 94641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 94741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt strncpy(s, interfaces, sizeof(s)); 94841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt while((interface = strsep(&next, ":"))) { 94941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if_tmp = safe_malloc(sizeof(struct iname)); 950e226badb960695447af4c480bb183ec35c411bbfErik Kline memset(if_tmp, 0, sizeof(struct iname)); 95141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if ((if_tmp->name = strdup(interface)) == NULL) { 95241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt die(_("malloc failure in set_interfaces: %s"), NULL, EC_BADNET); 95341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 95441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if_tmp->next = daemon->if_names; 95541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt daemon->if_names = if_tmp; 95641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 95741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 95841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (!enumerate_interfaces()) { 95941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt die(_("enumerate interfaces error in set_interfaces: %s"), NULL, EC_BADNET); 96041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 96141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 96241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next) { 96341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (if_tmp->name && !if_tmp->used) { 96441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt die(_("unknown interface given %s in set_interfaces: %s"), if_tmp->name, EC_BADNET); 96541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 96641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 96741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt /* success! - setup to free the old */ 96841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt /* check for any that have been removed */ 96941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt for (old_iface = prev_interfaces; old_iface; old_iface=old_iface->next) { 97041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt int found = 0; 97141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt for (new_iface = daemon->interfaces; new_iface; new_iface = new_iface->next) { 97241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (sockaddr_isequal(&old_iface->addr, &new_iface->addr)) { 973e226badb960695447af4c480bb183ec35c411bbfErik Kline found = 1; 97441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt break; 97541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 97641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 977e226badb960695447af4c480bb183ec35c411bbfErik Kline 978e226badb960695447af4c480bb183ec35c411bbfErik Kline if (found) { 979e226badb960695447af4c480bb183ec35c411bbfErik Kline fixup_possible_existing_listener(new_iface); 980e226badb960695447af4c480bb183ec35c411bbfErik Kline } else { 98141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#ifdef __ANDROID_DEBUG__ 98241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt char debug_buff[MAXDNAME]; 98341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt prettyprint_addr(&old_iface->addr, debug_buff); 98441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt my_syslog(LOG_DEBUG, _("closing listener for %s"), debug_buff); 98541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#endif 98641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 98741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt close_bound_listener(old_iface); 98841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 98941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 99041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 99141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt /* remove wildchar listeners */ 99241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt was_wild = close_bound_listener(NULL); 99341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (was_wild) daemon->options |= OPT_NOWILD; 99441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 99541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt /* check for any that have been added */ 99641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt for (new_iface = daemon->interfaces; new_iface; new_iface = new_iface->next) { 99741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt int found = 0; 99841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 99941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt /* if the previous setup used a wildchar, then add any current interfaces */ 100041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (!was_wild) { 100141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt for (old_iface = prev_interfaces; old_iface; old_iface = old_iface->next) { 100241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if(sockaddr_isequal(&old_iface->addr, &new_iface->addr)) { 100341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt found = -1; 100441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt break; 100541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 100641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 100741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 100841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (!found) { 100941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#ifdef __ANDROID_DEBUG__ 101041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt char debug_buff[MAXDNAME]; 101141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt prettyprint_addr(&new_iface->addr, debug_buff); 101241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt my_syslog(LOG_DEBUG, _("adding listener for %s"), debug_buff); 101341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#endif 101441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt create_bound_listener(&(daemon->listeners), new_iface); 101541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 101641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 101741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 101841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt while (prev_if_names) { 101941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if (prev_if_names->name) free(prev_if_names->name); 102041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt if_tmp = prev_if_names->next; 102141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt free(prev_if_names); 102241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt prev_if_names = if_tmp; 102341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 102441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt while (prev_interfaces) { 102541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt struct irec *tmp_irec = prev_interfaces->next; 102641cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt free(prev_interfaces); 102741cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt prev_interfaces = tmp_irec; 102841cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt } 102941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#ifdef __ANDROID_DEBUG__ 103041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt my_syslog(LOG_DEBUG, _("done with setInterfaces")); 103141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#endif 103241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt} 103341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt 103433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat/* 103568eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti * Takes a string in the format "0x100b:1.2.3.4:1.2.3.4:..." - up to 1024 bytes in length 103668eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti * - The first element is the socket mark to set on sockets that forward DNS queries. 103768eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti * - The subsequent elements are the DNS servers to forward queries to. 103833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat */ 103933b344454b95ed99bad7d3fe4d493870923deaf6San Mehatint set_servers(const char *servers) 104033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat{ 104133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat char s[1024]; 104233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat struct server *old_servers = NULL; 104333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat struct server *new_servers = NULL; 104433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat struct server *serv; 104568eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti char *mark_string; 104668eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti uint32_t mark; 104733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 104833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat strncpy(s, servers, sizeof(s)); 104933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 105033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat /* move old servers to free list - we can reuse the memory 105133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat and not risk malloc if there are the same or fewer new servers. 105233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat Servers which were specced on the command line go to the new list. */ 105333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat for (serv = daemon->servers; serv;) 105433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat { 105533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat struct server *tmp = serv->next; 105633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat if (serv->flags & SERV_FROM_RESOLV) 105733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat { 105833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->next = old_servers; 105933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat old_servers = serv; 106033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat /* forward table rules reference servers, so have to blow them away */ 106133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat server_gone(serv); 106233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 106333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat else 106433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat { 106533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->next = new_servers; 106633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat new_servers = serv; 106733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 106833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv = tmp; 106933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 107033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 107168eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti char *next = s; 107268eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti char *saddr; 107368eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti 107468eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti /* Parse the mark. */ 107568eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti mark_string = strsep(&next, ":"); 107668eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti mark = strtoul(mark_string, NULL, 0); 107733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 107868eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti while ((saddr = strsep(&next, ":"))) { 107933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat union mysockaddr addr, source_addr; 108033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat memset(&addr, 0, sizeof(addr)); 108133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat memset(&source_addr, 0, sizeof(source_addr)); 108233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 108333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat if ((addr.in.sin_addr.s_addr = inet_addr(saddr)) != (in_addr_t) -1) 108433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat { 108533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 108633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in); 108733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif 108833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in.sin_family = addr.in.sin_family = AF_INET; 108933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat addr.in.sin_port = htons(NAMESERVER_PORT); 109033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in.sin_addr.s_addr = INADDR_ANY; 109133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in.sin_port = htons(daemon->query_port); 109233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 109333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifdef HAVE_IPV6 109433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat else if (inet_pton(AF_INET6, saddr, &addr.in6.sin6_addr) > 0) 109533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat { 109633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 109733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6); 109833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif 109933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6; 110033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat addr.in6.sin6_port = htons(NAMESERVER_PORT); 110133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in6.sin6_addr = in6addr_any; 110233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat source_addr.in6.sin6_port = htons(daemon->query_port); 110333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 110433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif /* IPV6 */ 110533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat else 110633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat continue; 110733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 110833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat if (old_servers) 110933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat { 111033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv = old_servers; 111133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat old_servers = old_servers->next; 111233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 111333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat else if (!(serv = whine_malloc(sizeof (struct server)))) 111433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat continue; 111533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 111633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat /* this list is reverse ordered: 111733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat it gets reversed again in check_servers */ 111833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->next = new_servers; 111933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat new_servers = serv; 112033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->addr = addr; 112133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->source_addr = source_addr; 112233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->domain = NULL; 112333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->interface[0] = 0; 112468eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti serv->mark = mark; 112533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->sfd = NULL; 112633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->flags = SERV_FROM_RESOLV; 112733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat serv->queries = serv->failed_queries = 0; 112833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 112933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 113033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat /* Free any memory not used. */ 113133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat while (old_servers) 113233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat { 113333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat struct server *tmp = old_servers->next; 113433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat free(old_servers); 113533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat old_servers = tmp; 113633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat } 113733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 113833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat daemon->servers = new_servers; 113933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat return 0; 114033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat} 114133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif 114233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat 1143ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* Return zero if no servers found, in that case we keep polling. 1144ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat This is a protection against an update-time/write race on resolv.conf */ 1145ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint reload_servers(char *fname) 1146ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 1147ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat FILE *f; 1148ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *line; 1149ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct server *old_servers = NULL; 1150ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct server *new_servers = NULL; 1151ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct server *serv; 1152ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat int gotone = 0; 1153ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1154ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* buff happens to be MAXDNAME long... */ 1155ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(f = fopen(fname, "r"))) 1156ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1157ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno)); 1158ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return 0; 1159ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1160ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1161ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* move old servers to free list - we can reuse the memory 1162ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat and not risk malloc if there are the same or fewer new servers. 1163ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat Servers which were specced on the command line go to the new list. */ 1164ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (serv = daemon->servers; serv;) 1165ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1166ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct server *tmp = serv->next; 1167ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (serv->flags & SERV_FROM_RESOLV) 1168ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1169ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->next = old_servers; 1170ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat old_servers = serv; 1171ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* forward table rules reference servers, so have to blow them away */ 1172ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat server_gone(serv); 1173ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1174ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 1175ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1176ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->next = new_servers; 1177ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new_servers = serv; 1178ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1179ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv = tmp; 1180ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1181ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1182ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while ((line = fgets(daemon->namebuff, MAXDNAME, f))) 1183ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1184ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat union mysockaddr addr, source_addr; 1185ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat char *token = strtok(line, " \t\n\r"); 1186ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1187ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!token) 1188ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 1189ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0) 1190ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 1191ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!(token = strtok(NULL, " \t\n\r"))) 1192ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 1193ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1194ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(&addr, 0, sizeof(addr)); 1195ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat memset(&source_addr, 0, sizeof(source_addr)); 1196ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1197ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1) 1198ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1199ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 1200ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in); 1201ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 1202ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in.sin_family = addr.in.sin_family = AF_INET; 1203ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in.sin_port = htons(NAMESERVER_PORT); 1204ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in.sin_addr.s_addr = INADDR_ANY; 1205ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in.sin_port = htons(daemon->query_port); 1206ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1207ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_IPV6 1208ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0) 1209ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1210ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN 1211ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6); 1212ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif 1213ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6; 1214ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat addr.in6.sin6_port = htons(NAMESERVER_PORT); 1215ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in6.sin6_addr = in6addr_any; 1216ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat source_addr.in6.sin6_port = htons(daemon->query_port); 1217ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1218ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif /* IPV6 */ 1219ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else 1220ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 1221ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1222ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (old_servers) 1223ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1224ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv = old_servers; 1225ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat old_servers = old_servers->next; 1226ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1227ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat else if (!(serv = whine_malloc(sizeof (struct server)))) 1228ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat continue; 1229ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1230ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* this list is reverse ordered: 1231ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat it gets reversed again in check_servers */ 1232ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->next = new_servers; 1233ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat new_servers = serv; 1234ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->addr = addr; 1235ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->source_addr = source_addr; 1236ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->domain = NULL; 1237ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->interface[0] = 0; 123868eff53e7ed9df06f194478930f39b31c7a32458Lorenzo Colitti serv->mark = 0; 1239ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->sfd = NULL; 1240ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->flags = SERV_FROM_RESOLV; 1241ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat serv->queries = serv->failed_queries = 0; 1242ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat gotone = 1; 1243ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1244ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1245ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat /* Free any memory not used. */ 1246ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat while (old_servers) 1247ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat { 1248ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct server *tmp = old_servers->next; 1249ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat free(old_servers); 1250ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat old_servers = tmp; 1251ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat } 1252ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1253ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat daemon->servers = new_servers; 1254ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat fclose(f); 1255ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1256ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return gotone; 1257ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 1258ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1259ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1260ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* Use an IPv4 listener socket for ioctling */ 1261ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstruct in_addr get_ifaddr(char *intr) 1262ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{ 1263ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct listener *l; 1264ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat struct ifreq ifr; 1265ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1266ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat for (l = daemon->listeners; l && l->family != AF_INET; l = l->next); 1267ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1268ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat strncpy(ifr.ifr_name, intr, IF_NAMESIZE); 1269ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ifr.ifr_addr.sa_family = AF_INET; 1270ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1271ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat if (!l || ioctl(l->fd, SIOCGIFADDR, &ifr) == -1) 1272ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = -1; 1273ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat 1274ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat return ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; 1275ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} 1276