blob: 32bd517075e352a490c41dadff46c832971f1c7f [file] [log] [blame]
Simon Kelley59546082012-01-06 20:02:04 +00001/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
Simon Kelley824af852008-02-12 20:43:05 +00005 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
Simon Kelley9e4abcb2004-01-22 19:47:41 +00008 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
Simon Kelley824af852008-02-12 20:43:05 +000012
Simon Kelley73a08a22009-02-05 20:28:08 +000013 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
Simon Kelley9e4abcb2004-01-22 19:47:41 +000015*/
16
Simon Kelley9e4abcb2004-01-22 19:47:41 +000017#include "dnsmasq.h"
18
Simon Kelley7622fc02009-06-04 20:32:05 +010019#ifdef HAVE_LINUX_NETWORK
20
21int indextoname(int fd, int index, char *name)
22{
23 struct ifreq ifr;
24
25 if (index == 0)
26 return 0;
27
28 ifr.ifr_ifindex = index;
29 if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
30 return 0;
31
32 strncpy(name, ifr.ifr_name, IF_NAMESIZE);
33
34 return 1;
35}
36
Simon Kelley28866e92011-02-14 20:19:14 +000037
38#elif defined(HAVE_SOLARIS_NETWORK)
39
40#include <zone.h>
41#include <alloca.h>
42#ifndef LIFC_UNDER_IPMP
43# define LIFC_UNDER_IPMP 0
44#endif
45
46int indextoname(int fd, int index, char *name)
47{
48 int64_t lifc_flags;
49 struct lifnum lifn;
50 int numifs, bufsize, i;
51 struct lifconf lifc;
52 struct lifreq *lifrp;
53
54 if (index == 0)
55 return 0;
56
57 if (getzoneid() == GLOBAL_ZONEID)
58 {
59 if (!if_indextoname(index, name))
60 return 0;
61 return 1;
62 }
63
64 lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES | LIFC_UNDER_IPMP;
65 lifn.lifn_family = AF_UNSPEC;
66 lifn.lifn_flags = lifc_flags;
67 if (ioctl(fd, SIOCGLIFNUM, &lifn) < 0)
68 return 0;
69
70 numifs = lifn.lifn_count;
71 bufsize = numifs * sizeof(struct lifreq);
72
73 lifc.lifc_family = AF_UNSPEC;
74 lifc.lifc_flags = lifc_flags;
75 lifc.lifc_len = bufsize;
76 lifc.lifc_buf = alloca(bufsize);
77
78 if (ioctl(fd, SIOCGLIFCONF, &lifc) < 0)
79 return 0;
80
81 lifrp = lifc.lifc_req;
82 for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++)
83 {
84 struct lifreq lifr;
85 strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
86 if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0)
87 return 0;
88
89 if (lifr.lifr_index == index) {
90 strncpy(name, lifr.lifr_name, IF_NAMESIZE);
91 return 1;
92 }
93 }
94 return 0;
95}
96
97
Simon Kelley7622fc02009-06-04 20:32:05 +010098#else
99
100int indextoname(int fd, int index, char *name)
101{
102 if (index == 0 || !if_indextoname(index, name))
103 return 0;
104
105 return 1;
106}
107
108#endif
109
Simon Kelleyc72daea2012-01-05 21:33:27 +0000110int iface_check(int family, struct all_addr *addr, char *name)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000111{
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000112 struct iname *tmp;
Simon Kelley309331f2006-04-22 15:05:01 +0100113 int ret = 1;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100114
Simon Kelley309331f2006-04-22 15:05:01 +0100115 /* Note: have to check all and not bail out early, so that we set the
116 "used" flags. */
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100117
Simon Kelleyc72daea2012-01-05 21:33:27 +0000118 if (daemon->if_names || daemon->if_addrs)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100119 {
120#ifdef HAVE_DHCP
121 struct dhcp_context *range;
122#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100123
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100124 ret = 0;
125
126#ifdef HAVE_DHCP
127 for (range = daemon->dhcp; range; range = range->next)
128 if (range->interface && strcmp(range->interface, name) == 0)
129 ret = 1;
130#endif
131
132 for (tmp = daemon->if_names; tmp; tmp = tmp->next)
133 if (tmp->name && (strcmp(tmp->name, name) == 0))
134 ret = tmp->used = 1;
135
136 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000137 if (tmp->addr.sa.sa_family == family)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100138 {
139 if (family == AF_INET &&
140 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
141 ret = tmp->used = 1;
142#ifdef HAVE_IPV6
143 else if (family == AF_INET6 &&
144 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
145 &addr->addr.addr6))
146 ret = tmp->used = 1;
147#endif
148 }
149 }
150
151 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
152 if (tmp->name && (strcmp(tmp->name, name) == 0))
153 ret = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000154
Simon Kelley309331f2006-04-22 15:05:01 +0100155 return ret;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100156}
157
Simon Kelley5aabfc72007-08-29 11:24:47 +0100158static int iface_allowed(struct irec **irecp, int if_index,
Simon Kelley74c95c22011-10-19 09:33:39 +0100159 union mysockaddr *addr, struct in_addr netmask, int dad)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100160{
161 struct irec *iface;
Simon Kelley1f15b812009-10-13 17:49:32 +0100162 int fd, mtu = 0, loopback;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100163 struct ifreq ifr;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100164 int tftp_ok = daemon->tftp_unlimited;
165#ifdef HAVE_DHCP
Simon Kelley832af0b2007-01-21 20:01:28 +0000166 struct iname *tmp;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100167#endif
168 struct interface_list *ir = NULL;
169
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100170 /* check whether the interface IP has been added already
171 we call this routine multiple times. */
172 for (iface = *irecp; iface; iface = iface->next)
173 if (sockaddr_isequal(&iface->addr, addr))
Simon Kelley74c95c22011-10-19 09:33:39 +0100174 {
175 iface->dad = dad;
176 return 1;
177 }
178
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100179 if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1 ||
Simon Kelley7622fc02009-06-04 20:32:05 +0100180 !indextoname(fd, if_index, ifr.ifr_name) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100181 ioctl(fd, SIOCGIFFLAGS, &ifr) == -1)
182 {
183 if (fd != -1)
184 {
185 int errsave = errno;
186 close(fd);
187 errno = errsave;
188 }
189 return 0;
190 }
Simon Kelley1f15b812009-10-13 17:49:32 +0100191
192 loopback = ifr.ifr_flags & IFF_LOOPBACK;
193
194 if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
195 mtu = ifr.ifr_mtu;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100196
197 close(fd);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000198
Simon Kelley59353a62004-11-21 19:34:28 +0000199 /* If we are restricting the set of interfaces to use, make
200 sure that loopback interfaces are in that set. */
Simon Kelley1f15b812009-10-13 17:49:32 +0100201 if (daemon->if_names && loopback)
Simon Kelley59353a62004-11-21 19:34:28 +0000202 {
203 struct iname *lo;
204 for (lo = daemon->if_names; lo; lo = lo->next)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100205 if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
Simon Kelley59353a62004-11-21 19:34:28 +0000206 {
207 lo->isloop = 1;
208 break;
209 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100210
Simon Kelley5aabfc72007-08-29 11:24:47 +0100211 if (!lo &&
212 (lo = whine_malloc(sizeof(struct iname))) &&
213 (lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
Simon Kelley59353a62004-11-21 19:34:28 +0000214 {
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100215 strcpy(lo->name, ifr.ifr_name);
Simon Kelley59353a62004-11-21 19:34:28 +0000216 lo->isloop = lo->used = 1;
217 lo->next = daemon->if_names;
218 daemon->if_names = lo;
219 }
220 }
221
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100222#ifdef HAVE_TFTP
223 /* implement wierd TFTP service rules */
Simon Kelley28866e92011-02-14 20:19:14 +0000224 for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
225 if (strcmp(ir->interface, ifr.ifr_name) == 0)
226 {
227 tftp_ok = 1;
228 break;
229 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100230#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000231
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100232 if (!ir)
233 {
234 if (addr->sa.sa_family == AF_INET &&
Simon Kelleyc72daea2012-01-05 21:33:27 +0000235 !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100236 return 1;
237
238#ifdef HAVE_DHCP
239 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
240 if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
241 tftp_ok = 0;
242#endif
243
244#ifdef HAVE_IPV6
245 if (addr->sa.sa_family == AF_INET6 &&
Simon Kelleyc72daea2012-01-05 21:33:27 +0000246 !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100247 return 1;
248#endif
249 }
250
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100251 /* add to list */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100252 if ((iface = whine_malloc(sizeof(struct irec))))
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100253 {
254 iface->addr = *addr;
255 iface->netmask = netmask;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100256 iface->tftp_ok = tftp_ok;
Simon Kelley1f15b812009-10-13 17:49:32 +0100257 iface->mtu = mtu;
Simon Kelley74c95c22011-10-19 09:33:39 +0100258 iface->dad = dad;
259 iface->done = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100260 if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
261 strcpy(iface->name, ifr.ifr_name);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100262 iface->next = *irecp;
Simon Kelley832af0b2007-01-21 20:01:28 +0000263 *irecp = iface;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100264 return 1;
Simon Kelley44a2a312004-03-10 20:04:35 +0000265 }
266
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100267 errno = ENOMEM;
268 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000269}
270
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100271#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000272static int iface_allowed_v6(struct in6_addr *local, int prefix,
Simon Kelley74c95c22011-10-19 09:33:39 +0100273 int scope, int if_index, int dad, void *vparam)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000274{
Simon Kelley59353a62004-11-21 19:34:28 +0000275 union mysockaddr addr;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100276 struct in_addr netmask; /* dummy */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100277 netmask.s_addr = 0;
Simon Kelley52b92f42012-01-22 16:05:15 +0000278
279 (void)prefix; /* warning */
280 (void)scope; /* warning */
Simon Kelley44a2a312004-03-10 20:04:35 +0000281
Simon Kelley849a8352006-06-09 21:02:31 +0100282 memset(&addr, 0, sizeof(addr));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000283#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100284 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000285#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100286 addr.in6.sin6_family = AF_INET6;
287 addr.in6.sin6_addr = *local;
288 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley52b92f42012-01-22 16:05:15 +0000289 addr.in6.sin6_scope_id = if_index;
Simon Kelley849a8352006-06-09 21:02:31 +0100290
Simon Kelley74c95c22011-10-19 09:33:39 +0100291 return iface_allowed((struct irec **)vparam, if_index, &addr, netmask, dad);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100292}
293#endif
Simon Kelley59353a62004-11-21 19:34:28 +0000294
Simon Kelley5aabfc72007-08-29 11:24:47 +0100295static int iface_allowed_v4(struct in_addr local, int if_index,
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100296 struct in_addr netmask, struct in_addr broadcast, void *vparam)
297{
298 union mysockaddr addr;
Simon Kelley849a8352006-06-09 21:02:31 +0100299
300 memset(&addr, 0, sizeof(addr));
Simon Kelley1ab84e22004-01-29 16:48:35 +0000301#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100302 addr.in.sin_len = sizeof(addr.in);
Simon Kelley1ab84e22004-01-29 16:48:35 +0000303#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100304 addr.in.sin_family = AF_INET;
305 addr.in.sin_addr = broadcast; /* warning */
306 addr.in.sin_addr = local;
307 addr.in.sin_port = htons(daemon->port);
Simon Kelley44a2a312004-03-10 20:04:35 +0000308
Simon Kelley74c95c22011-10-19 09:33:39 +0100309 return iface_allowed((struct irec **)vparam, if_index, &addr, netmask, 0);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100310}
311
Simon Kelley5aabfc72007-08-29 11:24:47 +0100312int enumerate_interfaces(void)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100313{
314#ifdef HAVE_IPV6
Simon Kelley28866e92011-02-14 20:19:14 +0000315 if (!iface_enumerate(AF_INET6, &daemon->interfaces, iface_allowed_v6))
316 return 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100317#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000318
319 return iface_enumerate(AF_INET, &daemon->interfaces, iface_allowed_v4);
Simon Kelley44a2a312004-03-10 20:04:35 +0000320}
321
Simon Kelley5aabfc72007-08-29 11:24:47 +0100322/* set NONBLOCK bit on fd: See Stevens 16.6 */
Simon Kelley7cebd202006-05-06 14:13:33 +0100323int fix_fd(int fd)
324{
325 int flags;
326
327 if ((flags = fcntl(fd, F_GETFL)) == -1 ||
Simon Kelley5aabfc72007-08-29 11:24:47 +0100328 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
Simon Kelley7cebd202006-05-06 14:13:33 +0100329 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100330
Simon Kelley7cebd202006-05-06 14:13:33 +0100331 return 1;
332}
333
Simon Kelley74c95c22011-10-19 09:33:39 +0100334static int make_sock(union mysockaddr *addr, int type, int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000335{
Simon Kelley28866e92011-02-14 20:19:14 +0000336 int family = addr->sa.sa_family;
337 int fd, rc, opt = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100338
Simon Kelley28866e92011-02-14 20:19:14 +0000339 if ((fd = socket(family, type, 0)) == -1)
Simon Kelley316e2732010-01-22 20:16:09 +0000340 {
Simon Kelley28866e92011-02-14 20:19:14 +0000341 int port;
342
343 /* No error if the kernel just doesn't support this IP flavour */
344 if (errno == EPROTONOSUPPORT ||
345 errno == EAFNOSUPPORT ||
346 errno == EINVAL)
347 return -1;
348
349 err:
Simon Kelley74c95c22011-10-19 09:33:39 +0100350 if (dienow)
351 {
352 port = prettyprint_addr(addr, daemon->namebuff);
353 if (!option_bool(OPT_NOWILD))
354 sprintf(daemon->namebuff, "port %d", port);
355 die(_("failed to create listening socket for %s: %s"),
356 daemon->namebuff, EC_BADNET);
357
358 }
359 return -1;
Simon Kelley28866e92011-02-14 20:19:14 +0000360 }
361
362 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
363 goto err;
364
365#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000366 if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000367 goto err;
368#endif
369
Simon Kelley74c95c22011-10-19 09:33:39 +0100370 if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000371 goto err;
372
373 if (type == SOCK_STREAM)
374 {
375 if (listen(fd, 5) == -1)
376 goto err;
377 }
378 else if (!option_bool(OPT_NOWILD))
379 {
380 if (family == AF_INET)
381 {
382#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000383 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000384 goto err;
385#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
386 if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
387 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
388 goto err;
389#endif
390 }
391#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000392 else if (!set_ipv6pktinfo(fd))
393 goto err;
Simon Kelley316e2732010-01-22 20:16:09 +0000394#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000395 }
Simon Kelleyc72daea2012-01-05 21:33:27 +0000396
Simon Kelley28866e92011-02-14 20:19:14 +0000397 return fd;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100398}
Simon Kelleyc72daea2012-01-05 21:33:27 +0000399
400#ifdef HAVE_IPV6
401int set_ipv6pktinfo(int fd)
402{
403 int opt = 1;
404
405 /* The API changed around Linux 2.6.14 but the old ABI is still supported:
406 handle all combinations of headers and kernel.
407 OpenWrt note that this fixes the problem addressed by your very broken patch. */
408 daemon->v6pktinfo = IPV6_PKTINFO;
409
410#ifdef IPV6_RECVPKTINFO
411 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
412 return 1;
413# ifdef IPV6_2292PKTINFO
414 else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
415 {
416 daemon->v6pktinfo = IPV6_2292PKTINFO;
417 return 1;
418 }
419# endif
420#else
421 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
422 return 1;
423#endif
424
425 return 0;
426}
427#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000428
Simon Kelley74c95c22011-10-19 09:33:39 +0100429static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
Simon Kelley28866e92011-02-14 20:19:14 +0000430{
431 struct listener *l = NULL;
432 int fd = -1, tcpfd = -1, tftpfd = -1;
433
434 if (daemon->port != 0)
435 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100436 fd = make_sock(addr, SOCK_DGRAM, dienow);
437 tcpfd = make_sock(addr, SOCK_STREAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000438 }
439
440#ifdef HAVE_TFTP
441 if (do_tftp)
442 {
443 if (addr->sa.sa_family == AF_INET)
444 {
445 /* port must be restored to DNS port for TCP code */
446 short save = addr->in.sin_port;
447 addr->in.sin_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100448 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000449 addr->in.sin_port = save;
450 }
451# ifdef HAVE_IPV6
452 else
453 {
454 short save = addr->in6.sin6_port;
455 addr->in6.sin6_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100456 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000457 addr->in6.sin6_port = save;
458 }
459# endif
460 }
Simon Kelley44a2a312004-03-10 20:04:35 +0000461#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100462
Simon Kelley28866e92011-02-14 20:19:14 +0000463 if (fd != -1 || tcpfd != -1 || tftpfd != -1)
464 {
465 l = safe_malloc(sizeof(struct listener));
466 l->next = NULL;
467 l->family = addr->sa.sa_family;
468 l->fd = fd;
469 l->tcpfd = tcpfd;
470 l->tftpfd = tftpfd;
471 }
472
473 return l;
474}
475
Simon Kelley74c95c22011-10-19 09:33:39 +0100476void create_wildcard_listeners(void)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100477{
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100478 union mysockaddr addr;
Simon Kelley28866e92011-02-14 20:19:14 +0000479 struct listener *l;
480 int tftp_enabled = daemon->tftp_unlimited || daemon->tftp_interfaces;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100481
Simon Kelley849a8352006-06-09 21:02:31 +0100482 memset(&addr, 0, sizeof(addr));
Simon Kelley28866e92011-02-14 20:19:14 +0000483#ifdef HAVE_SOCKADDR_SA_LEN
484 addr.in.sin_len = sizeof(addr.in);
485#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100486 addr.in.sin_family = AF_INET;
487 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100488 addr.in.sin_port = htons(daemon->port);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100489
Simon Kelley74c95c22011-10-19 09:33:39 +0100490 l = create_listeners(&addr, tftp_enabled, 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000491
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100492#ifdef HAVE_IPV6
Simon Kelley28866e92011-02-14 20:19:14 +0000493 memset(&addr, 0, sizeof(addr));
494# ifdef HAVE_SOCKADDR_SA_LEN
495 addr.in6.sin6_len = sizeof(addr.in6);
496# endif
497 addr.in6.sin6_family = AF_INET6;
498 addr.in6.sin6_addr = in6addr_any;
499 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley824af852008-02-12 20:43:05 +0000500
Simon Kelley28866e92011-02-14 20:19:14 +0000501 if (l)
Simon Kelley74c95c22011-10-19 09:33:39 +0100502 l->next = create_listeners(&addr, tftp_enabled, 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000503 else
Simon Kelley74c95c22011-10-19 09:33:39 +0100504 l = create_listeners(&addr, tftp_enabled, 1);
Simon Kelley832af0b2007-01-21 20:01:28 +0000505#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100506
Simon Kelley74c95c22011-10-19 09:33:39 +0100507 daemon->listeners = l;
Simon Kelley44a2a312004-03-10 20:04:35 +0000508}
509
Simon Kelley74c95c22011-10-19 09:33:39 +0100510void create_bound_listeners(int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000511{
Simon Kelley74c95c22011-10-19 09:33:39 +0100512 struct listener *new;
Simon Kelley44a2a312004-03-10 20:04:35 +0000513 struct irec *iface;
Simon Kelley73a08a22009-02-05 20:28:08 +0000514
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100515 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley74c95c22011-10-19 09:33:39 +0100516 if (!iface->done && !iface->dad &&
517 (new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
Simon Kelley28866e92011-02-14 20:19:14 +0000518 {
519 new->iface = iface;
Simon Kelley74c95c22011-10-19 09:33:39 +0100520 new->next = daemon->listeners;
521 daemon->listeners = new;
522 iface->done = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000523 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000524}
525
Simon Kelley74c95c22011-10-19 09:33:39 +0100526int is_dad_listeners(void)
527{
528 struct irec *iface;
529
530 if (option_bool(OPT_NOWILD))
531 for (iface = daemon->interfaces; iface; iface = iface->next)
532 if (iface->dad && !iface->done)
533 return 1;
534
535 return 0;
536}
Simon Kelley9009d742008-11-14 20:04:27 +0000537/* return a UDP socket bound to a random port, have to cope with straying into
Simon Kelley1a6bca82008-07-11 11:11:42 +0100538 occupied port nos and reserved ones. */
539int random_sock(int family)
540{
541 int fd;
542
543 if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
544 {
Simon Kelley3927da42008-07-20 15:10:39 +0100545 union mysockaddr addr;
Simon Kelley1ad24ae2008-07-20 20:22:50 +0100546 unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
Simon Kelley9009d742008-11-14 20:04:27 +0000547 int tries = ports_avail < 30 ? 3 * ports_avail : 100;
Simon Kelley3927da42008-07-20 15:10:39 +0100548
Simon Kelley1a6bca82008-07-11 11:11:42 +0100549 memset(&addr, 0, sizeof(addr));
Simon Kelley3927da42008-07-20 15:10:39 +0100550 addr.sa.sa_family = family;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100551
Simon Kelley1ad24ae2008-07-20 20:22:50 +0100552 /* don't loop forever if all ports in use. */
553
Simon Kelley1a6bca82008-07-11 11:11:42 +0100554 if (fix_fd(fd))
Simon Kelley9009d742008-11-14 20:04:27 +0000555 while(tries--)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100556 {
557 unsigned short port = rand16();
558
Simon Kelley3927da42008-07-20 15:10:39 +0100559 if (daemon->min_port != 0)
Simon Kelley1ad24ae2008-07-20 20:22:50 +0100560 port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100561
562 if (family == AF_INET)
563 {
564 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley3927da42008-07-20 15:10:39 +0100565 addr.in.sin_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100566#ifdef HAVE_SOCKADDR_SA_LEN
567 addr.in.sin_len = sizeof(struct sockaddr_in);
568#endif
569 }
570#ifdef HAVE_IPV6
571 else
572 {
573 addr.in6.sin6_addr = in6addr_any;
Simon Kelley3927da42008-07-20 15:10:39 +0100574 addr.in6.sin6_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100575#ifdef HAVE_SOCKADDR_SA_LEN
576 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
577#endif
578 }
579#endif
580
581 if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
582 return fd;
583
584 if (errno != EADDRINUSE && errno != EACCES)
585 break;
586 }
587
588 close(fd);
589 }
590
591 return -1;
592}
593
594
Simon Kelley824af852008-02-12 20:43:05 +0000595int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
596{
597 union mysockaddr addr_copy = *addr;
598
599 /* cannot set source _port_ for TCP connections. */
600 if (is_tcp)
601 {
602 if (addr_copy.sa.sa_family == AF_INET)
603 addr_copy.in.sin_port = 0;
604#ifdef HAVE_IPV6
605 else
606 addr_copy.in6.sin6_port = 0;
607#endif
608 }
609
610 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
611 return 0;
612
613#if defined(SO_BINDTODEVICE)
Simon Kelley73a08a22009-02-05 20:28:08 +0000614 if (intname[0] != 0 &&
Simon Kelley316e2732010-01-22 20:16:09 +0000615 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
Simon Kelley824af852008-02-12 20:43:05 +0000616 return 0;
617#endif
618
619 return 1;
620}
621
622static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000623{
624 struct serverfd *sfd;
Simon Kelley824af852008-02-12 20:43:05 +0000625 int errsave;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100626
Simon Kelley1a6bca82008-07-11 11:11:42 +0100627 /* when using random ports, servers which would otherwise use
628 the INADDR_ANY/port0 socket have sfd set to NULL */
Simon Kelley73a08a22009-02-05 20:28:08 +0000629 if (!daemon->osport && intname[0] == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100630 {
631 errno = 0;
632
633 if (addr->sa.sa_family == AF_INET &&
634 addr->in.sin_addr.s_addr == INADDR_ANY &&
635 addr->in.sin_port == htons(0))
636 return NULL;
637
638#ifdef HAVE_IPV6
639 if (addr->sa.sa_family == AF_INET6 &&
640 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
641 addr->in6.sin6_port == htons(0))
642 return NULL;
643#endif
644 }
645
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000646 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +0000647 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
648 if (sockaddr_isequal(&sfd->source_addr, addr) &&
649 strcmp(intname, sfd->interface) == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000650 return sfd;
651
652 /* need to make a new one. */
653 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100654 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000655 return NULL;
656
657 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
658 {
659 free(sfd);
660 return NULL;
661 }
662
Simon Kelley824af852008-02-12 20:43:05 +0000663 if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
664 {
665 errsave = errno; /* save error from bind. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000666 close(sfd->fd);
667 free(sfd);
668 errno = errsave;
669 return NULL;
670 }
Simon Kelley824af852008-02-12 20:43:05 +0000671
672 strcpy(sfd->interface, intname);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000673 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +0000674 sfd->next = daemon->sfds;
675 daemon->sfds = sfd;
676 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000677}
678
Simon Kelley824af852008-02-12 20:43:05 +0000679/* create upstream sockets during startup, before root is dropped which may be needed
680 this allows query_port to be a low port and interface binding */
681void pre_allocate_sfds(void)
682{
683 struct server *srv;
684
685 if (daemon->query_port != 0)
686 {
687 union mysockaddr addr;
688 memset(&addr, 0, sizeof(addr));
689 addr.in.sin_family = AF_INET;
690 addr.in.sin_addr.s_addr = INADDR_ANY;
691 addr.in.sin_port = htons(daemon->query_port);
692#ifdef HAVE_SOCKADDR_SA_LEN
693 addr.in.sin_len = sizeof(struct sockaddr_in);
694#endif
695 allocate_sfd(&addr, "");
696#ifdef HAVE_IPV6
697 memset(&addr, 0, sizeof(addr));
698 addr.in6.sin6_family = AF_INET6;
699 addr.in6.sin6_addr = in6addr_any;
700 addr.in6.sin6_port = htons(daemon->query_port);
701#ifdef HAVE_SOCKADDR_SA_LEN
702 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
703#endif
704 allocate_sfd(&addr, "");
705#endif
706 }
707
708 for (srv = daemon->servers; srv; srv = srv->next)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100709 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
Simon Kelley824af852008-02-12 20:43:05 +0000710 !allocate_sfd(&srv->source_addr, srv->interface) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +0100711 errno != 0 &&
Simon Kelley28866e92011-02-14 20:19:14 +0000712 option_bool(OPT_NOWILD))
Simon Kelley824af852008-02-12 20:43:05 +0000713 {
Simon Kelley316e2732010-01-22 20:16:09 +0000714 prettyprint_addr(&srv->source_addr, daemon->namebuff);
Simon Kelley73a08a22009-02-05 20:28:08 +0000715 if (srv->interface[0] != 0)
Simon Kelley824af852008-02-12 20:43:05 +0000716 {
717 strcat(daemon->namebuff, " ");
718 strcat(daemon->namebuff, srv->interface);
719 }
720 die(_("failed to bind server socket for %s: %s"),
721 daemon->namebuff, EC_BADNET);
722 }
723}
724
725
Simon Kelley5aabfc72007-08-29 11:24:47 +0100726void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000727{
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000728 struct irec *iface;
Simon Kelley3be34542004-09-11 19:12:13 +0100729 struct server *new, *tmp, *ret = NULL;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000730 int port = 0;
731
Simon Kelley316e2732010-01-22 20:16:09 +0000732 /* interface may be new since startup */
Simon Kelley28866e92011-02-14 20:19:14 +0000733 if (!option_bool(OPT_NOWILD))
Simon Kelley316e2732010-01-22 20:16:09 +0000734 enumerate_interfaces();
735
Simon Kelley3be34542004-09-11 19:12:13 +0100736 for (new = daemon->servers; new; new = tmp)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000737 {
738 tmp = new->next;
739
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100740 if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000741 {
Simon Kelley3d8df262005-08-29 12:19:27 +0100742 port = prettyprint_addr(&new->addr, daemon->namebuff);
743
Simon Kelley16972692006-10-16 20:04:18 +0100744 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
745 if (new->addr.sa.sa_family == AF_INET &&
746 new->addr.in.sin_addr.s_addr == 0)
747 {
748 free(new);
749 continue;
750 }
751
Simon Kelley3d8df262005-08-29 12:19:27 +0100752 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000753 if (sockaddr_isequal(&new->addr, &iface->addr))
754 break;
755 if (iface)
756 {
Simon Kelleyf2621c72007-04-29 19:47:21 +0100757 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000758 free(new);
759 continue;
760 }
761
762 /* Do we need a socket set? */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100763 if (!new->sfd &&
764 !(new->sfd = allocate_sfd(&new->source_addr, new->interface)) &&
765 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000766 {
Simon Kelleyf2621c72007-04-29 19:47:21 +0100767 my_syslog(LOG_WARNING,
768 _("ignoring nameserver %s - cannot make/bind socket: %s"),
769 daemon->namebuff, strerror(errno));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000770 free(new);
771 continue;
772 }
773 }
774
775 /* reverse order - gets it right. */
776 new->next = ret;
777 ret = new;
778
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100779 if (!(new->flags & SERV_NO_REBIND))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000780 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100781 if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
782 {
783 char *s1, *s2;
784 if (!(new->flags & SERV_HAS_DOMAIN))
785 s1 = _("unqualified"), s2 = _("names");
786 else if (strlen(new->domain) == 0)
787 s1 = _("default"), s2 = "";
788 else
789 s1 = _("domain"), s2 = new->domain;
790
791 if (new->flags & SERV_NO_ADDR)
792 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
793 else if (new->flags & SERV_USE_RESOLV)
794 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
795 else if (!(new->flags & SERV_LITERAL_ADDRESS))
796 my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
797 }
798 else if (new->interface[0] != 0)
799 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000800 else
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100801 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000802 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000803 }
804
Simon Kelley3be34542004-09-11 19:12:13 +0100805 daemon->servers = ret;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000806}
Simon Kelley849a8352006-06-09 21:02:31 +0100807
808/* Return zero if no servers found, in that case we keep polling.
809 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100810int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000811{
812 FILE *f;
813 char *line;
814 struct server *old_servers = NULL;
815 struct server *new_servers = NULL;
Simon Kelley849a8352006-06-09 21:02:31 +0100816 struct server *serv;
817 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000818
Simon Kelley849a8352006-06-09 21:02:31 +0100819 /* buff happens to be MAXDNAME long... */
820 if (!(f = fopen(fname, "r")))
821 {
Simon Kelleyf2621c72007-04-29 19:47:21 +0100822 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +0100823 return 0;
824 }
825
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000826 /* move old servers to free list - we can reuse the memory
827 and not risk malloc if there are the same or fewer new servers.
828 Servers which were specced on the command line go to the new list. */
Simon Kelley849a8352006-06-09 21:02:31 +0100829 for (serv = daemon->servers; serv;)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000830 {
831 struct server *tmp = serv->next;
832 if (serv->flags & SERV_FROM_RESOLV)
833 {
834 serv->next = old_servers;
Simon Kelley849a8352006-06-09 21:02:31 +0100835 old_servers = serv;
836 /* forward table rules reference servers, so have to blow them away */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100837 server_gone(serv);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000838 }
839 else
840 {
841 serv->next = new_servers;
842 new_servers = serv;
843 }
844 serv = tmp;
845 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000846
Simon Kelley849a8352006-06-09 21:02:31 +0100847 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
848 {
849 union mysockaddr addr, source_addr;
850 char *token = strtok(line, " \t\n\r");
851
Simon Kelley5aabfc72007-08-29 11:24:47 +0100852 if (!token)
853 continue;
854 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +0100855 continue;
856 if (!(token = strtok(NULL, " \t\n\r")))
857 continue;
858
859 memset(&addr, 0, sizeof(addr));
860 memset(&source_addr, 0, sizeof(source_addr));
861
862 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
863 {
864#ifdef HAVE_SOCKADDR_SA_LEN
865 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
866#endif
867 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
868 addr.in.sin_port = htons(NAMESERVER_PORT);
869 source_addr.in.sin_addr.s_addr = INADDR_ANY;
870 source_addr.in.sin_port = htons(daemon->query_port);
871 }
872#ifdef HAVE_IPV6
Simon Kelley7de060b2011-08-26 17:24:52 +0100873 else
874 {
875 int scope_index = 0;
876 char *scope_id = strchr(token, '%');
877
878 if (scope_id)
879 {
880 *(scope_id++) = 0;
881 scope_index = if_nametoindex(scope_id);
882 }
883
884 if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
885 {
Simon Kelley849a8352006-06-09 21:02:31 +0100886#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley7de060b2011-08-26 17:24:52 +0100887 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
Simon Kelley849a8352006-06-09 21:02:31 +0100888#endif
Simon Kelley7de060b2011-08-26 17:24:52 +0100889 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
890 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
891 addr.in6.sin6_port = htons(NAMESERVER_PORT);
892 addr.in6.sin6_scope_id = scope_index;
893 source_addr.in6.sin6_addr = in6addr_any;
894 source_addr.in6.sin6_port = htons(daemon->query_port);
895 source_addr.in6.sin6_scope_id = 0;
896 }
897 else
898 continue;
Simon Kelley849a8352006-06-09 21:02:31 +0100899 }
Simon Kelley7de060b2011-08-26 17:24:52 +0100900#else /* IPV6 */
Simon Kelley849a8352006-06-09 21:02:31 +0100901 else
902 continue;
Simon Kelley7de060b2011-08-26 17:24:52 +0100903#endif
904
Simon Kelley849a8352006-06-09 21:02:31 +0100905 if (old_servers)
906 {
907 serv = old_servers;
908 old_servers = old_servers->next;
909 }
Simon Kelley5aabfc72007-08-29 11:24:47 +0100910 else if (!(serv = whine_malloc(sizeof (struct server))))
Simon Kelley849a8352006-06-09 21:02:31 +0100911 continue;
912
913 /* this list is reverse ordered:
914 it gets reversed again in check_servers */
915 serv->next = new_servers;
916 new_servers = serv;
917 serv->addr = addr;
918 serv->source_addr = source_addr;
919 serv->domain = NULL;
Simon Kelley824af852008-02-12 20:43:05 +0000920 serv->interface[0] = 0;
Simon Kelley849a8352006-06-09 21:02:31 +0100921 serv->sfd = NULL;
922 serv->flags = SERV_FROM_RESOLV;
Simon Kelley824af852008-02-12 20:43:05 +0000923 serv->queries = serv->failed_queries = 0;
Simon Kelley849a8352006-06-09 21:02:31 +0100924 gotone = 1;
925 }
926
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000927 /* Free any memory not used. */
Simon Kelley849a8352006-06-09 21:02:31 +0100928 while (old_servers)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000929 {
930 struct server *tmp = old_servers->next;
931 free(old_servers);
932 old_servers = tmp;
933 }
934
Simon Kelley3be34542004-09-11 19:12:13 +0100935 daemon->servers = new_servers;
Simon Kelley849a8352006-06-09 21:02:31 +0100936 fclose(f);
937
938 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000939}
940
941
Simon Kelleyf2621c72007-04-29 19:47:21 +0100942/* Use an IPv4 listener socket for ioctling */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100943struct in_addr get_ifaddr(char *intr)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100944{
945 struct listener *l;
946 struct ifreq ifr;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100947 struct sockaddr_in ret;
948
949 ret.sin_addr.s_addr = -1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000950
Simon Kelley28866e92011-02-14 20:19:14 +0000951 for (l = daemon->listeners;
952 l && (l->family != AF_INET || l->fd == -1);
953 l = l->next);
Simon Kelleyf2621c72007-04-29 19:47:21 +0100954
955 strncpy(ifr.ifr_name, intr, IF_NAMESIZE);
956 ifr.ifr_addr.sa_family = AF_INET;
957
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100958 if (l && ioctl(l->fd, SIOCGIFADDR, &ifr) != -1)
959 memcpy(&ret, &ifr.ifr_addr, sizeof(ret));
Simon Kelleyf2621c72007-04-29 19:47:21 +0100960
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100961 return ret.sin_addr;
Simon Kelleyf2621c72007-04-29 19:47:21 +0100962}
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000963
964
965