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