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