blob: 7a5d49e660579e546202ed2a7f4f25d3e7a0b563 [file] [log] [blame]
Simon Kelley61744352013-01-31 14:34:40 +00001/* dnsmasq is Copyright (c) 2000-2013 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{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100102 (void)fd;
103
Simon Kelley7622fc02009-06-04 20:32:05 +0100104 if (index == 0 || !if_indextoname(index, name))
105 return 0;
106
107 return 1;
108}
109
110#endif
111
Simon Kelley4f7b3042012-11-28 21:27:02 +0000112int iface_check(int family, struct all_addr *addr, char *name, int *auth)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000113{
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000114 struct iname *tmp;
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100115 int ret = 1, match_addr = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100116
Simon Kelley309331f2006-04-22 15:05:01 +0100117 /* Note: have to check all and not bail out early, so that we set the
118 "used" flags. */
Simon Kelley429798f2012-12-10 20:45:53 +0000119
Simon Kelley4f7b3042012-11-28 21:27:02 +0000120 if (auth)
Simon Kelley429798f2012-12-10 20:45:53 +0000121 *auth = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100122
Simon Kelleyc72daea2012-01-05 21:33:27 +0000123 if (daemon->if_names || daemon->if_addrs)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100124 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100125 ret = 0;
126
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100127 for (tmp = daemon->if_names; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000128 if (tmp->name && wildcard_match(tmp->name, name))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100129 ret = tmp->used = 1;
130
Simon Kelley429798f2012-12-10 20:45:53 +0000131 if (addr)
132 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
133 if (tmp->addr.sa.sa_family == family)
134 {
135 if (family == AF_INET &&
136 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100137 ret = match_addr = tmp->used = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100138#ifdef HAVE_IPV6
Simon Kelley429798f2012-12-10 20:45:53 +0000139 else if (family == AF_INET6 &&
140 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
141 &addr->addr.addr6))
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100142 ret = match_addr = tmp->used = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100143#endif
Simon Kelley429798f2012-12-10 20:45:53 +0000144 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100145 }
146
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100147 if (!match_addr)
148 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
149 if (tmp->name && wildcard_match(tmp->name, name))
150 ret = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000151
Simon Kelley429798f2012-12-10 20:45:53 +0000152
153 for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
154 if (tmp->name)
155 {
156 if (strcmp(tmp->name, name) == 0)
157 break;
158 }
159 else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
160 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
161 break;
162#ifdef HAVE_IPV6
163 else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
164 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6))
165 break;
166#endif
167
168 if (tmp && auth)
169 {
170 *auth = 1;
171 ret = 1;
172 }
173
Simon Kelley309331f2006-04-22 15:05:01 +0100174 return ret;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100175}
Simon Kelleye25db1f2013-01-29 22:10:26 +0000176
177
178/* Fix for problem that the kernel sometimes reports the loopback inerface as the
179 arrival interface when a packet originates locally, even when sent to address of
180 an interface other than the loopback. Accept packet if it arrived via a loopback
181 interface, even when we're not accepting packets that way, as long as the destination
182 address is one we're believing. Interface list must be up-to-date before calling. */
183int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
184{
185 struct ifreq ifr;
186 struct irec *iface;
187
188 strncpy(ifr.ifr_name, name, IF_NAMESIZE);
189 if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
190 ifr.ifr_flags & IFF_LOOPBACK)
191 {
192 for (iface = daemon->interfaces; iface; iface = iface->next)
193 if (iface->addr.sa.sa_family == family)
194 {
195 if (family == AF_INET)
196 {
197 if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
198 return 1;
199 }
200#ifdef HAVE_IPV6
201 else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6))
202 return 1;
203#endif
204
205 }
206 }
207 return 0;
208}
209
Simon Kelley3f2873d2013-05-14 11:28:47 +0100210/* If we're configured with something like --interface=eth0:0 then we'll listen correctly
211 on the relevant address, but the name of the arrival interface, derived from the
212 index won't match the config. Check that we found an interface address for the arrival
213 interface: daemon->interfaces must be up-to-date. */
214int label_exception(int index, int family, struct all_addr *addr)
215{
216 struct irec *iface;
217
218 /* labels only supported on IPv4 addresses. */
219 if (family != AF_INET)
220 return 0;
221
222 for (iface = daemon->interfaces; iface; iface = iface->next)
223 if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
224 iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
225 return 1;
226
227 return 0;
228}
229
Simon Kelley115ac3e2013-05-20 11:28:32 +0100230struct iface_param {
231 struct addrlist *spare;
232 int fd;
233};
234
235static int iface_allowed(struct iface_param *param, int if_index, char *label,
Simon Kelley74c95c22011-10-19 09:33:39 +0100236 union mysockaddr *addr, struct in_addr netmask, int dad)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100237{
238 struct irec *iface;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100239 int mtu = 0, loopback;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100240 struct ifreq ifr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100241 int tftp_ok = !!option_bool(OPT_TFTP);
Simon Kelley9380ba72012-04-16 14:41:56 +0100242 int dhcp_ok = 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000243 int auth_dns = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100244#ifdef HAVE_DHCP
Simon Kelley832af0b2007-01-21 20:01:28 +0000245 struct iname *tmp;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100246#endif
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100247
Simon Kelley115ac3e2013-05-20 11:28:32 +0100248 if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
249 ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
250 return 0;
Simon Kelley1f15b812009-10-13 17:49:32 +0100251
252 loopback = ifr.ifr_flags & IFF_LOOPBACK;
Simon Kelley9380ba72012-04-16 14:41:56 +0100253
254 if (loopback)
Simon Kelley3f2873d2013-05-14 11:28:47 +0100255 dhcp_ok = 0;
256
Simon Kelley115ac3e2013-05-20 11:28:32 +0100257 if (ioctl(param->fd, SIOCGIFMTU, &ifr) != -1)
Simon Kelley1f15b812009-10-13 17:49:32 +0100258 mtu = ifr.ifr_mtu;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100259
Simon Kelley115ac3e2013-05-20 11:28:32 +0100260 if (!label)
261 label = ifr.ifr_name;
262
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000263
Simon Kelley115ac3e2013-05-20 11:28:32 +0100264 /* Update addresses from interface_names. These are a set independent
265 of the set we're listening on. */
266#ifdef HAVE_IPV6
267 if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
268#endif
269 {
270 struct interface_name *int_name;
271 struct addrlist *al;
272
273 for (int_name = daemon->int_names; int_name; int_name = int_name->next)
274 if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0)
275 {
276 if (param->spare)
277 {
278 al = param->spare;
279 param->spare = al->next;
280 }
281 else
282 al = whine_malloc(sizeof(struct addrlist));
283
284 if (al)
285 {
286 if (addr->sa.sa_family == AF_INET)
287 {
288 al->addr.addr.addr4 = addr->in.sin_addr;
289 al->next = int_name->addr4;
290 int_name->addr4 = al;
291 }
292#ifdef HAVE_IPV6
293 else
294 {
295 al->addr.addr.addr6 = addr->in6.sin6_addr;
296 al->next = int_name->addr6;
297 int_name->addr6 = al;
298 }
299#endif
300 }
301 }
302 }
303
304 /* check whether the interface IP has been added already
305 we call this routine multiple times. */
306 for (iface = daemon->interfaces; iface; iface = iface->next)
307 if (sockaddr_isequal(&iface->addr, addr))
308 {
309 iface->dad = dad;
310 return 1;
311 }
312
313 /* If we are restricting the set of interfaces to use, make
Simon Kelley59353a62004-11-21 19:34:28 +0000314 sure that loopback interfaces are in that set. */
Simon Kelley1f15b812009-10-13 17:49:32 +0100315 if (daemon->if_names && loopback)
Simon Kelley59353a62004-11-21 19:34:28 +0000316 {
317 struct iname *lo;
318 for (lo = daemon->if_names; lo; lo = lo->next)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100319 if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
Simon Kelley4ce4f372012-06-14 11:50:45 +0100320 break;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100321
Simon Kelley38365ff2013-02-05 14:35:54 +0000322 if (!lo && (lo = whine_malloc(sizeof(struct iname))))
Simon Kelley59353a62004-11-21 19:34:28 +0000323 {
Simon Kelley38365ff2013-02-05 14:35:54 +0000324 if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
325 {
326 strcpy(lo->name, ifr.ifr_name);
327 lo->used = 1;
328 lo->next = daemon->if_names;
329 daemon->if_names = lo;
330 }
331 else
332 free(lo);
Simon Kelley59353a62004-11-21 19:34:28 +0000333 }
334 }
335
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100336 if (addr->sa.sa_family == AF_INET &&
Simon Kelley3f2873d2013-05-14 11:28:47 +0100337 !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100338 return 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000339
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100340#ifdef HAVE_IPV6
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100341 if (addr->sa.sa_family == AF_INET6 &&
Simon Kelley3f2873d2013-05-14 11:28:47 +0100342 !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100343 return 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100344#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000345
346#ifdef HAVE_DHCP
347 /* No DHCP where we're doing auth DNS. */
348 if (auth_dns)
349 {
350 tftp_ok = 0;
351 dhcp_ok = 0;
352 }
353 else
354 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000355 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
Simon Kelley4f7b3042012-11-28 21:27:02 +0000356 {
357 tftp_ok = 0;
358 dhcp_ok = 0;
359 }
360#endif
361
Simon Kelley2937f8a2013-07-29 19:49:07 +0100362
363 if (daemon->tftp_interfaces)
364 {
365 /* dedicated tftp interface list */
366 tftp_ok = 0;
367 for (tmp = daemon->tftp_interfaces; tmp; tmp = tmp->next)
368 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
369 tftp_ok = 1;
370 }
371
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100372 /* add to list */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100373 if ((iface = whine_malloc(sizeof(struct irec))))
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100374 {
375 iface->addr = *addr;
376 iface->netmask = netmask;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100377 iface->tftp_ok = tftp_ok;
Simon Kelley9380ba72012-04-16 14:41:56 +0100378 iface->dhcp_ok = dhcp_ok;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000379 iface->dns_auth = auth_dns;
Simon Kelley1f15b812009-10-13 17:49:32 +0100380 iface->mtu = mtu;
Simon Kelley74c95c22011-10-19 09:33:39 +0100381 iface->dad = dad;
Simon Kelley5d162f22012-12-20 14:55:46 +0000382 iface->done = iface->multicast_done = 0;
383 iface->index = if_index;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100384 if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
Simon Kelley6f13e532012-04-17 14:25:06 +0100385 {
386 strcpy(iface->name, ifr.ifr_name);
Simon Kelley115ac3e2013-05-20 11:28:32 +0100387 iface->next = daemon->interfaces;
388 daemon->interfaces = iface;
Simon Kelley6f13e532012-04-17 14:25:06 +0100389 return 1;
390 }
391 free(iface);
Simon Kelley5d162f22012-12-20 14:55:46 +0000392
Simon Kelley44a2a312004-03-10 20:04:35 +0000393 }
394
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100395 errno = ENOMEM;
396 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000397}
398
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100399#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000400static int iface_allowed_v6(struct in6_addr *local, int prefix,
Simon Kelleybad7b872012-12-20 22:00:39 +0000401 int scope, int if_index, int flags,
Simon Kelley1f776932012-12-16 19:46:08 +0000402 int preferred, int valid, void *vparam)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000403{
Simon Kelley59353a62004-11-21 19:34:28 +0000404 union mysockaddr addr;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100405 struct in_addr netmask; /* dummy */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100406 netmask.s_addr = 0;
Simon Kelley52b92f42012-01-22 16:05:15 +0000407
408 (void)prefix; /* warning */
409 (void)scope; /* warning */
Simon Kelley1f776932012-12-16 19:46:08 +0000410 (void)preferred;
411 (void)valid;
Simon Kelley44a2a312004-03-10 20:04:35 +0000412
Simon Kelley849a8352006-06-09 21:02:31 +0100413 memset(&addr, 0, sizeof(addr));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000414#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100415 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000416#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100417 addr.in6.sin6_family = AF_INET6;
418 addr.in6.sin6_addr = *local;
419 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley52b92f42012-01-22 16:05:15 +0000420 addr.in6.sin6_scope_id = if_index;
Simon Kelley849a8352006-06-09 21:02:31 +0100421
Simon Kelley115ac3e2013-05-20 11:28:32 +0100422 return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, !!(flags & IFACE_TENTATIVE));
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100423}
424#endif
Simon Kelley59353a62004-11-21 19:34:28 +0000425
Simon Kelley3f2873d2013-05-14 11:28:47 +0100426static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100427 struct in_addr netmask, struct in_addr broadcast, void *vparam)
428{
429 union mysockaddr addr;
Simon Kelley849a8352006-06-09 21:02:31 +0100430
431 memset(&addr, 0, sizeof(addr));
Simon Kelley1ab84e22004-01-29 16:48:35 +0000432#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100433 addr.in.sin_len = sizeof(addr.in);
Simon Kelley1ab84e22004-01-29 16:48:35 +0000434#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100435 addr.in.sin_family = AF_INET;
436 addr.in.sin_addr = broadcast; /* warning */
437 addr.in.sin_addr = local;
438 addr.in.sin_port = htons(daemon->port);
Simon Kelley44a2a312004-03-10 20:04:35 +0000439
Simon Kelley115ac3e2013-05-20 11:28:32 +0100440 return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, 0);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100441}
442
Simon Kelley115ac3e2013-05-20 11:28:32 +0100443int enumerate_interfaces(int reset)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100444{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100445 static struct addrlist *spare = NULL;
446 static int done = 0;
447 struct iface_param param;
448 int errsave, ret = 1;
449 struct addrlist *addr, *tmp;
450 struct interface_name *intname;
451
Simon Kelley76dd75d2013-05-23 10:04:25 +0100452 /* Do this max once per select cycle - also inhibits netlink socket use
453 in TCP child processes. */
454
Simon Kelley115ac3e2013-05-20 11:28:32 +0100455 if (reset)
456 {
457 done = 0;
458 return 1;
459 }
460
461 if (done)
462 return 1;
463
464 done = 1;
465
466 if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
467 return 0;
468
469 /* remove addresses stored against interface_names */
470 for (intname = daemon->int_names; intname; intname = intname->next)
471 {
472 for (addr = intname->addr4; addr; addr = tmp)
473 {
474 tmp = addr->next;
475 addr->next = spare;
476 spare = addr;
477 }
478
479 intname->addr4 = NULL;
480
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100481#ifdef HAVE_IPV6
Simon Kelley115ac3e2013-05-20 11:28:32 +0100482 for (addr = intname->addr6; addr; addr = tmp)
483 {
484 tmp = addr->next;
485 addr->next = spare;
486 spare = addr;
487 }
488
489 intname->addr6 = NULL;
490#endif
491 }
492
493 param.spare = spare;
494
495#ifdef HAVE_IPV6
496 ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100497#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000498
Simon Kelley115ac3e2013-05-20 11:28:32 +0100499 if (ret)
500 ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);
501
502 errsave = errno;
503 close(param.fd);
504 errno = errsave;
505
506 spare = param.spare;
507
508 return ret;
Simon Kelley44a2a312004-03-10 20:04:35 +0000509}
510
Simon Kelley5aabfc72007-08-29 11:24:47 +0100511/* set NONBLOCK bit on fd: See Stevens 16.6 */
Simon Kelley7cebd202006-05-06 14:13:33 +0100512int fix_fd(int fd)
513{
514 int flags;
515
516 if ((flags = fcntl(fd, F_GETFL)) == -1 ||
Simon Kelley5aabfc72007-08-29 11:24:47 +0100517 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
Simon Kelley7cebd202006-05-06 14:13:33 +0100518 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100519
Simon Kelley7cebd202006-05-06 14:13:33 +0100520 return 1;
521}
522
Simon Kelley74c95c22011-10-19 09:33:39 +0100523static int make_sock(union mysockaddr *addr, int type, int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000524{
Simon Kelley28866e92011-02-14 20:19:14 +0000525 int family = addr->sa.sa_family;
526 int fd, rc, opt = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100527
Simon Kelley28866e92011-02-14 20:19:14 +0000528 if ((fd = socket(family, type, 0)) == -1)
Simon Kelley316e2732010-01-22 20:16:09 +0000529 {
Simon Kelley28866e92011-02-14 20:19:14 +0000530 int port;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100531 char *s;
Simon Kelley28866e92011-02-14 20:19:14 +0000532
533 /* No error if the kernel just doesn't support this IP flavour */
534 if (errno == EPROTONOSUPPORT ||
535 errno == EAFNOSUPPORT ||
536 errno == EINVAL)
537 return -1;
538
539 err:
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100540 port = prettyprint_addr(addr, daemon->addrbuff);
541 if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
542 sprintf(daemon->addrbuff, "port %d", port);
543 s = _("failed to create listening socket for %s: %s");
544
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100545 if (fd != -1)
546 close (fd);
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100547
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100548 if (dienow)
549 {
550 /* failure to bind addresses given by --listen-address at this point
551 is OK if we're doing bind-dynamic */
552 if (!option_bool(OPT_CLEVERBIND))
553 die(s, daemon->addrbuff, EC_BADNET);
554 }
555 else
556 my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
557
Simon Kelley74c95c22011-10-19 09:33:39 +0100558 return -1;
Simon Kelley28866e92011-02-14 20:19:14 +0000559 }
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100560
Simon Kelley28866e92011-02-14 20:19:14 +0000561 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
562 goto err;
563
564#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000565 if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000566 goto err;
567#endif
568
Simon Kelley74c95c22011-10-19 09:33:39 +0100569 if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000570 goto err;
571
572 if (type == SOCK_STREAM)
573 {
574 if (listen(fd, 5) == -1)
575 goto err;
576 }
577 else if (!option_bool(OPT_NOWILD))
578 {
579 if (family == AF_INET)
580 {
581#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000582 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000583 goto err;
584#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
585 if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
586 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
587 goto err;
588#endif
589 }
590#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000591 else if (!set_ipv6pktinfo(fd))
592 goto err;
Simon Kelley316e2732010-01-22 20:16:09 +0000593#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000594 }
Simon Kelleyc72daea2012-01-05 21:33:27 +0000595
Simon Kelley28866e92011-02-14 20:19:14 +0000596 return fd;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100597}
Simon Kelleyc72daea2012-01-05 21:33:27 +0000598
599#ifdef HAVE_IPV6
600int set_ipv6pktinfo(int fd)
601{
602 int opt = 1;
603
604 /* The API changed around Linux 2.6.14 but the old ABI is still supported:
605 handle all combinations of headers and kernel.
606 OpenWrt note that this fixes the problem addressed by your very broken patch. */
607 daemon->v6pktinfo = IPV6_PKTINFO;
608
609#ifdef IPV6_RECVPKTINFO
610 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
611 return 1;
612# ifdef IPV6_2292PKTINFO
613 else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
614 {
615 daemon->v6pktinfo = IPV6_2292PKTINFO;
616 return 1;
617 }
618# endif
619#else
620 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
621 return 1;
622#endif
623
624 return 0;
625}
626#endif
Simon Kelley22ce5502013-01-22 13:53:04 +0000627
628
629/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
630int tcp_interface(int fd, int af)
631{
632 int if_index = 0;
633
634#ifdef HAVE_LINUX_NETWORK
635 int opt = 1;
636 struct cmsghdr *cmptr;
637 struct msghdr msg;
638
639 /* use mshdr do that the CMSDG_* macros are available */
640 msg.msg_control = daemon->packet;
641 msg.msg_controllen = daemon->packet_buff_sz;
642
643 /* we overwrote the buffer... */
644 daemon->srv_save = NULL;
645
646 if (af == AF_INET)
647 {
648 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
649 getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
650 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
651 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
652 {
653 union {
654 unsigned char *c;
655 struct in_pktinfo *p;
656 } p;
657
658 p.c = CMSG_DATA(cmptr);
659 if_index = p.p->ipi_ifindex;
660 }
661 }
662#ifdef HAVE_IPV6
663 else
664 {
665 /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
666 it was removed in RFC-3542 !!!!
667
668 Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
669 uses the old ABI, and should work with pre- and post-3542 kernel headers */
670
671#ifdef IPV6_2292PKTOPTIONS
672# define PKTOPTIONS IPV6_2292PKTOPTIONS
673#else
674# define PKTOPTIONS IPV6_PKTOPTIONS
675#endif
676
677 if (set_ipv6pktinfo(fd) &&
678 getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
679 {
680 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
681 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
682 {
683 union {
684 unsigned char *c;
685 struct in6_pktinfo *p;
686 } p;
687 p.c = CMSG_DATA(cmptr);
688
689 if_index = p.p->ipi6_ifindex;
690 }
691 }
692 }
693#endif /* IPV6 */
694#endif /* Linux */
695
696 return if_index;
697}
Simon Kelley28866e92011-02-14 20:19:14 +0000698
Simon Kelley74c95c22011-10-19 09:33:39 +0100699static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
Simon Kelley28866e92011-02-14 20:19:14 +0000700{
701 struct listener *l = NULL;
702 int fd = -1, tcpfd = -1, tftpfd = -1;
703
704 if (daemon->port != 0)
705 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100706 fd = make_sock(addr, SOCK_DGRAM, dienow);
707 tcpfd = make_sock(addr, SOCK_STREAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000708 }
709
710#ifdef HAVE_TFTP
711 if (do_tftp)
712 {
713 if (addr->sa.sa_family == AF_INET)
714 {
715 /* port must be restored to DNS port for TCP code */
716 short save = addr->in.sin_port;
717 addr->in.sin_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100718 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000719 addr->in.sin_port = save;
720 }
721# ifdef HAVE_IPV6
722 else
723 {
724 short save = addr->in6.sin6_port;
725 addr->in6.sin6_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100726 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000727 addr->in6.sin6_port = save;
728 }
729# endif
730 }
Simon Kelley44a2a312004-03-10 20:04:35 +0000731#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100732
Simon Kelley28866e92011-02-14 20:19:14 +0000733 if (fd != -1 || tcpfd != -1 || tftpfd != -1)
734 {
735 l = safe_malloc(sizeof(struct listener));
736 l->next = NULL;
737 l->family = addr->sa.sa_family;
738 l->fd = fd;
739 l->tcpfd = tcpfd;
740 l->tftpfd = tftpfd;
741 }
742
743 return l;
744}
745
Simon Kelley74c95c22011-10-19 09:33:39 +0100746void create_wildcard_listeners(void)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100747{
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100748 union mysockaddr addr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100749 struct listener *l, *l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100750
Simon Kelley849a8352006-06-09 21:02:31 +0100751 memset(&addr, 0, sizeof(addr));
Simon Kelley28866e92011-02-14 20:19:14 +0000752#ifdef HAVE_SOCKADDR_SA_LEN
753 addr.in.sin_len = sizeof(addr.in);
754#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100755 addr.in.sin_family = AF_INET;
756 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100757 addr.in.sin_port = htons(daemon->port);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100758
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100759 l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000760
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100761#ifdef HAVE_IPV6
Simon Kelley28866e92011-02-14 20:19:14 +0000762 memset(&addr, 0, sizeof(addr));
763# ifdef HAVE_SOCKADDR_SA_LEN
764 addr.in6.sin6_len = sizeof(addr.in6);
765# endif
766 addr.in6.sin6_family = AF_INET6;
767 addr.in6.sin6_addr = in6addr_any;
768 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100769
770 l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000771 if (l)
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100772 l->next = l6;
Simon Kelley28866e92011-02-14 20:19:14 +0000773 else
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100774 l = l6;
Simon Kelley832af0b2007-01-21 20:01:28 +0000775#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100776
Simon Kelley74c95c22011-10-19 09:33:39 +0100777 daemon->listeners = l;
Simon Kelley44a2a312004-03-10 20:04:35 +0000778}
779
Simon Kelley74c95c22011-10-19 09:33:39 +0100780void create_bound_listeners(int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000781{
Simon Kelley74c95c22011-10-19 09:33:39 +0100782 struct listener *new;
Simon Kelley44a2a312004-03-10 20:04:35 +0000783 struct irec *iface;
Simon Kelley52d4abf2012-03-21 21:39:48 +0000784 struct iname *if_tmp;
Simon Kelley73a08a22009-02-05 20:28:08 +0000785
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100786 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley74c95c22011-10-19 09:33:39 +0100787 if (!iface->done && !iface->dad &&
788 (new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
Simon Kelley28866e92011-02-14 20:19:14 +0000789 {
790 new->iface = iface;
Simon Kelley74c95c22011-10-19 09:33:39 +0100791 new->next = daemon->listeners;
792 daemon->listeners = new;
793 iface->done = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000794 }
Simon Kelley52d4abf2012-03-21 21:39:48 +0000795
796 /* Check for --listen-address options that haven't been used because there's
797 no interface with a matching address. These may be valid: eg it's possible
798 to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
799
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100800 If the address isn't valid the bind() will fail and we'll die()
801 (except in bind-dynamic mode, when we'll complain but keep trying.)
Simon Kelley52d4abf2012-03-21 21:39:48 +0000802
803 The resulting listeners have the ->iface field NULL, and this has to be
804 handled by the DNS and TFTP code. It disables --localise-queries processing
805 (no netmask) and some MTU login the tftp code. */
806
807 for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
808 if (!if_tmp->used &&
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100809 (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
Simon Kelley52d4abf2012-03-21 21:39:48 +0000810 {
811 new->iface = NULL;
812 new->next = daemon->listeners;
813 daemon->listeners = new;
814 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000815}
816
Simon Kelley74c95c22011-10-19 09:33:39 +0100817int is_dad_listeners(void)
818{
819 struct irec *iface;
820
821 if (option_bool(OPT_NOWILD))
822 for (iface = daemon->interfaces; iface; iface = iface->next)
823 if (iface->dad && !iface->done)
824 return 1;
825
826 return 0;
827}
Simon Kelley5d162f22012-12-20 14:55:46 +0000828
829#ifdef HAVE_DHCP6
830void join_multicast(int dienow)
831{
832 struct irec *iface, *tmp;
833
834 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley19624462012-12-28 11:18:09 +0000835 if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
Simon Kelley5d162f22012-12-20 14:55:46 +0000836 {
837 /* There's an irec per address but we only want to join for multicast
838 once per interface. Weed out duplicates. */
839 for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
840 if (tmp->multicast_done && tmp->index == iface->index)
841 break;
842
843 iface->multicast_done = 1;
844
845 if (!tmp)
846 {
847 struct ipv6_mreq mreq;
848 int err = 0;
849
850 mreq.ipv6mr_interface = iface->index;
851
852 inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
853
854 if (daemon->doing_dhcp6 &&
855 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
856 err = 1;
857
858 inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
859
860 if (daemon->doing_dhcp6 &&
861 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
862 err = 1;
863
864 inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
865
866 if (daemon->doing_ra &&
867 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
868 err = 1;
869
870 if (err)
871 {
872 char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
873 if (dienow)
874 die(s, iface->name, EC_BADNET);
875 else
876 my_syslog(LOG_ERR, s, iface->name, strerror(errno));
877 }
878 }
879 }
880}
881#endif
882
Simon Kelley9009d742008-11-14 20:04:27 +0000883/* return a UDP socket bound to a random port, have to cope with straying into
Simon Kelley1a6bca82008-07-11 11:11:42 +0100884 occupied port nos and reserved ones. */
885int random_sock(int family)
886{
887 int fd;
888
889 if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
890 {
Simon Kelley3927da42008-07-20 15:10:39 +0100891 union mysockaddr addr;
Simon Kelley1ad24ae2008-07-20 20:22:50 +0100892 unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
Simon Kelley9009d742008-11-14 20:04:27 +0000893 int tries = ports_avail < 30 ? 3 * ports_avail : 100;
Simon Kelley3927da42008-07-20 15:10:39 +0100894
Simon Kelley1a6bca82008-07-11 11:11:42 +0100895 memset(&addr, 0, sizeof(addr));
Simon Kelley3927da42008-07-20 15:10:39 +0100896 addr.sa.sa_family = family;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100897
Simon Kelley1ad24ae2008-07-20 20:22:50 +0100898 /* don't loop forever if all ports in use. */
899
Simon Kelley1a6bca82008-07-11 11:11:42 +0100900 if (fix_fd(fd))
Simon Kelley9009d742008-11-14 20:04:27 +0000901 while(tries--)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100902 {
903 unsigned short port = rand16();
904
Simon Kelley3927da42008-07-20 15:10:39 +0100905 if (daemon->min_port != 0)
Simon Kelley1ad24ae2008-07-20 20:22:50 +0100906 port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100907
908 if (family == AF_INET)
909 {
910 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley3927da42008-07-20 15:10:39 +0100911 addr.in.sin_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100912#ifdef HAVE_SOCKADDR_SA_LEN
913 addr.in.sin_len = sizeof(struct sockaddr_in);
914#endif
915 }
916#ifdef HAVE_IPV6
917 else
918 {
919 addr.in6.sin6_addr = in6addr_any;
Simon Kelley3927da42008-07-20 15:10:39 +0100920 addr.in6.sin6_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100921#ifdef HAVE_SOCKADDR_SA_LEN
922 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
923#endif
924 }
925#endif
926
927 if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
928 return fd;
929
930 if (errno != EADDRINUSE && errno != EACCES)
931 break;
932 }
933
934 close(fd);
935 }
936
937 return -1;
938}
939
940
Simon Kelley824af852008-02-12 20:43:05 +0000941int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
942{
943 union mysockaddr addr_copy = *addr;
944
945 /* cannot set source _port_ for TCP connections. */
946 if (is_tcp)
947 {
948 if (addr_copy.sa.sa_family == AF_INET)
949 addr_copy.in.sin_port = 0;
950#ifdef HAVE_IPV6
951 else
952 addr_copy.in6.sin6_port = 0;
953#endif
954 }
955
956 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
957 return 0;
958
959#if defined(SO_BINDTODEVICE)
Simon Kelley73a08a22009-02-05 20:28:08 +0000960 if (intname[0] != 0 &&
Simon Kelley316e2732010-01-22 20:16:09 +0000961 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
Simon Kelley824af852008-02-12 20:43:05 +0000962 return 0;
963#endif
964
965 return 1;
966}
967
968static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000969{
970 struct serverfd *sfd;
Simon Kelley824af852008-02-12 20:43:05 +0000971 int errsave;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100972
Simon Kelley1a6bca82008-07-11 11:11:42 +0100973 /* when using random ports, servers which would otherwise use
974 the INADDR_ANY/port0 socket have sfd set to NULL */
Simon Kelley73a08a22009-02-05 20:28:08 +0000975 if (!daemon->osport && intname[0] == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100976 {
977 errno = 0;
978
979 if (addr->sa.sa_family == AF_INET &&
980 addr->in.sin_addr.s_addr == INADDR_ANY &&
981 addr->in.sin_port == htons(0))
982 return NULL;
983
984#ifdef HAVE_IPV6
985 if (addr->sa.sa_family == AF_INET6 &&
986 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
987 addr->in6.sin6_port == htons(0))
988 return NULL;
989#endif
990 }
991
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000992 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +0000993 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
994 if (sockaddr_isequal(&sfd->source_addr, addr) &&
995 strcmp(intname, sfd->interface) == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000996 return sfd;
997
998 /* need to make a new one. */
999 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001000 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001001 return NULL;
1002
1003 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
1004 {
1005 free(sfd);
1006 return NULL;
1007 }
1008
Simon Kelley824af852008-02-12 20:43:05 +00001009 if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
1010 {
1011 errsave = errno; /* save error from bind. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001012 close(sfd->fd);
1013 free(sfd);
1014 errno = errsave;
1015 return NULL;
1016 }
Simon Kelley824af852008-02-12 20:43:05 +00001017
1018 strcpy(sfd->interface, intname);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001019 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +00001020 sfd->next = daemon->sfds;
1021 daemon->sfds = sfd;
1022 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001023}
1024
Simon Kelley824af852008-02-12 20:43:05 +00001025/* create upstream sockets during startup, before root is dropped which may be needed
1026 this allows query_port to be a low port and interface binding */
1027void pre_allocate_sfds(void)
1028{
1029 struct server *srv;
1030
1031 if (daemon->query_port != 0)
1032 {
1033 union mysockaddr addr;
1034 memset(&addr, 0, sizeof(addr));
1035 addr.in.sin_family = AF_INET;
1036 addr.in.sin_addr.s_addr = INADDR_ANY;
1037 addr.in.sin_port = htons(daemon->query_port);
1038#ifdef HAVE_SOCKADDR_SA_LEN
1039 addr.in.sin_len = sizeof(struct sockaddr_in);
1040#endif
1041 allocate_sfd(&addr, "");
1042#ifdef HAVE_IPV6
1043 memset(&addr, 0, sizeof(addr));
1044 addr.in6.sin6_family = AF_INET6;
1045 addr.in6.sin6_addr = in6addr_any;
1046 addr.in6.sin6_port = htons(daemon->query_port);
1047#ifdef HAVE_SOCKADDR_SA_LEN
1048 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1049#endif
1050 allocate_sfd(&addr, "");
1051#endif
1052 }
1053
1054 for (srv = daemon->servers; srv; srv = srv->next)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001055 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
Simon Kelley824af852008-02-12 20:43:05 +00001056 !allocate_sfd(&srv->source_addr, srv->interface) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001057 errno != 0 &&
Simon Kelley28866e92011-02-14 20:19:14 +00001058 option_bool(OPT_NOWILD))
Simon Kelley824af852008-02-12 20:43:05 +00001059 {
Simon Kelley316e2732010-01-22 20:16:09 +00001060 prettyprint_addr(&srv->source_addr, daemon->namebuff);
Simon Kelley73a08a22009-02-05 20:28:08 +00001061 if (srv->interface[0] != 0)
Simon Kelley824af852008-02-12 20:43:05 +00001062 {
1063 strcat(daemon->namebuff, " ");
1064 strcat(daemon->namebuff, srv->interface);
1065 }
1066 die(_("failed to bind server socket for %s: %s"),
1067 daemon->namebuff, EC_BADNET);
1068 }
1069}
1070
1071
Simon Kelley5aabfc72007-08-29 11:24:47 +01001072void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001073{
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001074 struct irec *iface;
Simon Kelley3be34542004-09-11 19:12:13 +01001075 struct server *new, *tmp, *ret = NULL;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001076 int port = 0;
1077
Simon Kelley316e2732010-01-22 20:16:09 +00001078 /* interface may be new since startup */
Simon Kelley28866e92011-02-14 20:19:14 +00001079 if (!option_bool(OPT_NOWILD))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001080 enumerate_interfaces(0);
Simon Kelley316e2732010-01-22 20:16:09 +00001081
Simon Kelley3be34542004-09-11 19:12:13 +01001082 for (new = daemon->servers; new; new = tmp)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001083 {
1084 tmp = new->next;
1085
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001086 if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001087 {
Simon Kelley3d8df262005-08-29 12:19:27 +01001088 port = prettyprint_addr(&new->addr, daemon->namebuff);
1089
Simon Kelley16972692006-10-16 20:04:18 +01001090 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
1091 if (new->addr.sa.sa_family == AF_INET &&
1092 new->addr.in.sin_addr.s_addr == 0)
1093 {
1094 free(new);
1095 continue;
1096 }
1097
Simon Kelley3d8df262005-08-29 12:19:27 +01001098 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001099 if (sockaddr_isequal(&new->addr, &iface->addr))
1100 break;
1101 if (iface)
1102 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001103 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001104 free(new);
1105 continue;
1106 }
1107
1108 /* Do we need a socket set? */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001109 if (!new->sfd &&
1110 !(new->sfd = allocate_sfd(&new->source_addr, new->interface)) &&
1111 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001112 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001113 my_syslog(LOG_WARNING,
1114 _("ignoring nameserver %s - cannot make/bind socket: %s"),
1115 daemon->namebuff, strerror(errno));
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001116 free(new);
1117 continue;
1118 }
1119 }
1120
1121 /* reverse order - gets it right. */
1122 new->next = ret;
1123 ret = new;
1124
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001125 if (!(new->flags & SERV_NO_REBIND))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001126 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001127 if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
1128 {
1129 char *s1, *s2;
1130 if (!(new->flags & SERV_HAS_DOMAIN))
1131 s1 = _("unqualified"), s2 = _("names");
1132 else if (strlen(new->domain) == 0)
1133 s1 = _("default"), s2 = "";
1134 else
1135 s1 = _("domain"), s2 = new->domain;
1136
1137 if (new->flags & SERV_NO_ADDR)
1138 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
1139 else if (new->flags & SERV_USE_RESOLV)
1140 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
1141 else if (!(new->flags & SERV_LITERAL_ADDRESS))
1142 my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
1143 }
1144 else if (new->interface[0] != 0)
1145 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001146 else
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001147 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001148 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001149 }
1150
Simon Kelley3be34542004-09-11 19:12:13 +01001151 daemon->servers = ret;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001152}
Simon Kelley849a8352006-06-09 21:02:31 +01001153
1154/* Return zero if no servers found, in that case we keep polling.
1155 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001156int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001157{
1158 FILE *f;
1159 char *line;
1160 struct server *old_servers = NULL;
1161 struct server *new_servers = NULL;
Simon Kelley849a8352006-06-09 21:02:31 +01001162 struct server *serv;
1163 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001164
Simon Kelley849a8352006-06-09 21:02:31 +01001165 /* buff happens to be MAXDNAME long... */
1166 if (!(f = fopen(fname, "r")))
1167 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001168 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +01001169 return 0;
1170 }
1171
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001172 /* move old servers to free list - we can reuse the memory
1173 and not risk malloc if there are the same or fewer new servers.
1174 Servers which were specced on the command line go to the new list. */
Simon Kelley849a8352006-06-09 21:02:31 +01001175 for (serv = daemon->servers; serv;)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001176 {
1177 struct server *tmp = serv->next;
1178 if (serv->flags & SERV_FROM_RESOLV)
1179 {
1180 serv->next = old_servers;
Simon Kelley849a8352006-06-09 21:02:31 +01001181 old_servers = serv;
1182 /* forward table rules reference servers, so have to blow them away */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001183 server_gone(serv);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001184 }
1185 else
1186 {
1187 serv->next = new_servers;
1188 new_servers = serv;
1189 }
1190 serv = tmp;
1191 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001192
Simon Kelley849a8352006-06-09 21:02:31 +01001193 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1194 {
1195 union mysockaddr addr, source_addr;
1196 char *token = strtok(line, " \t\n\r");
1197
Simon Kelley5aabfc72007-08-29 11:24:47 +01001198 if (!token)
1199 continue;
1200 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +01001201 continue;
1202 if (!(token = strtok(NULL, " \t\n\r")))
1203 continue;
1204
1205 memset(&addr, 0, sizeof(addr));
1206 memset(&source_addr, 0, sizeof(source_addr));
1207
1208 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
1209 {
1210#ifdef HAVE_SOCKADDR_SA_LEN
1211 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1212#endif
1213 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1214 addr.in.sin_port = htons(NAMESERVER_PORT);
1215 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1216 source_addr.in.sin_port = htons(daemon->query_port);
1217 }
1218#ifdef HAVE_IPV6
Simon Kelley7de060b2011-08-26 17:24:52 +01001219 else
1220 {
1221 int scope_index = 0;
1222 char *scope_id = strchr(token, '%');
1223
1224 if (scope_id)
1225 {
1226 *(scope_id++) = 0;
1227 scope_index = if_nametoindex(scope_id);
1228 }
1229
1230 if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1231 {
Simon Kelley849a8352006-06-09 21:02:31 +01001232#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley7de060b2011-08-26 17:24:52 +01001233 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
Simon Kelley849a8352006-06-09 21:02:31 +01001234#endif
Simon Kelley7de060b2011-08-26 17:24:52 +01001235 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1236 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
1237 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1238 addr.in6.sin6_scope_id = scope_index;
1239 source_addr.in6.sin6_addr = in6addr_any;
1240 source_addr.in6.sin6_port = htons(daemon->query_port);
1241 source_addr.in6.sin6_scope_id = 0;
1242 }
1243 else
1244 continue;
Simon Kelley849a8352006-06-09 21:02:31 +01001245 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001246#else /* IPV6 */
Simon Kelley849a8352006-06-09 21:02:31 +01001247 else
1248 continue;
Simon Kelley7de060b2011-08-26 17:24:52 +01001249#endif
1250
Simon Kelley849a8352006-06-09 21:02:31 +01001251 if (old_servers)
1252 {
1253 serv = old_servers;
1254 old_servers = old_servers->next;
1255 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001256 else if (!(serv = whine_malloc(sizeof (struct server))))
Simon Kelley849a8352006-06-09 21:02:31 +01001257 continue;
1258
1259 /* this list is reverse ordered:
1260 it gets reversed again in check_servers */
1261 serv->next = new_servers;
1262 new_servers = serv;
1263 serv->addr = addr;
1264 serv->source_addr = source_addr;
1265 serv->domain = NULL;
Simon Kelley824af852008-02-12 20:43:05 +00001266 serv->interface[0] = 0;
Simon Kelley849a8352006-06-09 21:02:31 +01001267 serv->sfd = NULL;
1268 serv->flags = SERV_FROM_RESOLV;
Simon Kelley824af852008-02-12 20:43:05 +00001269 serv->queries = serv->failed_queries = 0;
Simon Kelley849a8352006-06-09 21:02:31 +01001270 gotone = 1;
1271 }
1272
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001273 /* Free any memory not used. */
Simon Kelley849a8352006-06-09 21:02:31 +01001274 while (old_servers)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001275 {
1276 struct server *tmp = old_servers->next;
1277 free(old_servers);
1278 old_servers = tmp;
1279 }
1280
Simon Kelley3be34542004-09-11 19:12:13 +01001281 daemon->servers = new_servers;
Simon Kelley849a8352006-06-09 21:02:31 +01001282 fclose(f);
1283
1284 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001285}
1286
1287
1288
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001289
1290
1291