blob: 19f7b37c93b72540b723e753fec76b8b5bf66284 [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 Kelley309331f2006-04-22 15:05:01 +0100115 int ret = 1;
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)
137 ret = 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))
142 ret = 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
147 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000148 if (tmp->name && wildcard_match(tmp->name, name))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100149 ret = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000150
Simon Kelley429798f2012-12-10 20:45:53 +0000151
152 for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
153 if (tmp->name)
154 {
155 if (strcmp(tmp->name, name) == 0)
156 break;
157 }
158 else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
159 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
160 break;
161#ifdef HAVE_IPV6
162 else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
163 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6))
164 break;
165#endif
166
167 if (tmp && auth)
168 {
169 *auth = 1;
170 ret = 1;
171 }
172
Simon Kelley309331f2006-04-22 15:05:01 +0100173 return ret;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100174}
Simon Kelleye25db1f2013-01-29 22:10:26 +0000175
176
177/* Fix for problem that the kernel sometimes reports the loopback inerface as the
178 arrival interface when a packet originates locally, even when sent to address of
179 an interface other than the loopback. Accept packet if it arrived via a loopback
180 interface, even when we're not accepting packets that way, as long as the destination
181 address is one we're believing. Interface list must be up-to-date before calling. */
182int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
183{
184 struct ifreq ifr;
185 struct irec *iface;
186
187 strncpy(ifr.ifr_name, name, IF_NAMESIZE);
188 if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
189 ifr.ifr_flags & IFF_LOOPBACK)
190 {
191 for (iface = daemon->interfaces; iface; iface = iface->next)
192 if (iface->addr.sa.sa_family == family)
193 {
194 if (family == AF_INET)
195 {
196 if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
197 return 1;
198 }
199#ifdef HAVE_IPV6
200 else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6))
201 return 1;
202#endif
203
204 }
205 }
206 return 0;
207}
208
Simon Kelley3f2873d2013-05-14 11:28:47 +0100209/* If we're configured with something like --interface=eth0:0 then we'll listen correctly
210 on the relevant address, but the name of the arrival interface, derived from the
211 index won't match the config. Check that we found an interface address for the arrival
212 interface: daemon->interfaces must be up-to-date. */
213int label_exception(int index, int family, struct all_addr *addr)
214{
215 struct irec *iface;
216
217 /* labels only supported on IPv4 addresses. */
218 if (family != AF_INET)
219 return 0;
220
221 for (iface = daemon->interfaces; iface; iface = iface->next)
222 if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
223 iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
224 return 1;
225
226 return 0;
227}
228
Simon Kelley115ac3e2013-05-20 11:28:32 +0100229struct iface_param {
230 struct addrlist *spare;
231 int fd;
232};
233
234static int iface_allowed(struct iface_param *param, int if_index, char *label,
Simon Kelley74c95c22011-10-19 09:33:39 +0100235 union mysockaddr *addr, struct in_addr netmask, int dad)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100236{
237 struct irec *iface;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100238 int mtu = 0, loopback;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100239 struct ifreq ifr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100240 int tftp_ok = !!option_bool(OPT_TFTP);
Simon Kelley9380ba72012-04-16 14:41:56 +0100241 int dhcp_ok = 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000242 int auth_dns = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100243#ifdef HAVE_DHCP
Simon Kelley832af0b2007-01-21 20:01:28 +0000244 struct iname *tmp;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100245#endif
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100246
Simon Kelley115ac3e2013-05-20 11:28:32 +0100247 if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
248 ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
249 return 0;
Simon Kelley1f15b812009-10-13 17:49:32 +0100250
251 loopback = ifr.ifr_flags & IFF_LOOPBACK;
Simon Kelley9380ba72012-04-16 14:41:56 +0100252
253 if (loopback)
Simon Kelley3f2873d2013-05-14 11:28:47 +0100254 dhcp_ok = 0;
255
Simon Kelley115ac3e2013-05-20 11:28:32 +0100256 if (ioctl(param->fd, SIOCGIFMTU, &ifr) != -1)
Simon Kelley1f15b812009-10-13 17:49:32 +0100257 mtu = ifr.ifr_mtu;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100258
Simon Kelley115ac3e2013-05-20 11:28:32 +0100259 if (!label)
260 label = ifr.ifr_name;
261
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000262
Simon Kelley115ac3e2013-05-20 11:28:32 +0100263 /* Update addresses from interface_names. These are a set independent
264 of the set we're listening on. */
265#ifdef HAVE_IPV6
266 if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
267#endif
268 {
269 struct interface_name *int_name;
270 struct addrlist *al;
271
272 for (int_name = daemon->int_names; int_name; int_name = int_name->next)
273 if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0)
274 {
275 if (param->spare)
276 {
277 al = param->spare;
278 param->spare = al->next;
279 }
280 else
281 al = whine_malloc(sizeof(struct addrlist));
282
283 if (al)
284 {
285 if (addr->sa.sa_family == AF_INET)
286 {
287 al->addr.addr.addr4 = addr->in.sin_addr;
288 al->next = int_name->addr4;
289 int_name->addr4 = al;
290 }
291#ifdef HAVE_IPV6
292 else
293 {
294 al->addr.addr.addr6 = addr->in6.sin6_addr;
295 al->next = int_name->addr6;
296 int_name->addr6 = al;
297 }
298#endif
299 }
300 }
301 }
302
303 /* check whether the interface IP has been added already
304 we call this routine multiple times. */
305 for (iface = daemon->interfaces; iface; iface = iface->next)
306 if (sockaddr_isequal(&iface->addr, addr))
307 {
308 iface->dad = dad;
309 return 1;
310 }
311
312 /* If we are restricting the set of interfaces to use, make
Simon Kelley59353a62004-11-21 19:34:28 +0000313 sure that loopback interfaces are in that set. */
Simon Kelley1f15b812009-10-13 17:49:32 +0100314 if (daemon->if_names && loopback)
Simon Kelley59353a62004-11-21 19:34:28 +0000315 {
316 struct iname *lo;
317 for (lo = daemon->if_names; lo; lo = lo->next)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100318 if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
Simon Kelley4ce4f372012-06-14 11:50:45 +0100319 break;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100320
Simon Kelley38365ff2013-02-05 14:35:54 +0000321 if (!lo && (lo = whine_malloc(sizeof(struct iname))))
Simon Kelley59353a62004-11-21 19:34:28 +0000322 {
Simon Kelley38365ff2013-02-05 14:35:54 +0000323 if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
324 {
325 strcpy(lo->name, ifr.ifr_name);
326 lo->used = 1;
327 lo->next = daemon->if_names;
328 daemon->if_names = lo;
329 }
330 else
331 free(lo);
Simon Kelley59353a62004-11-21 19:34:28 +0000332 }
333 }
334
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100335 if (addr->sa.sa_family == AF_INET &&
Simon Kelley3f2873d2013-05-14 11:28:47 +0100336 !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100337 return 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000338
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100339#ifdef HAVE_IPV6
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100340 if (addr->sa.sa_family == AF_INET6 &&
Simon Kelley3f2873d2013-05-14 11:28:47 +0100341 !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100342 return 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100343#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000344
345#ifdef HAVE_DHCP
346 /* No DHCP where we're doing auth DNS. */
347 if (auth_dns)
348 {
349 tftp_ok = 0;
350 dhcp_ok = 0;
351 }
352 else
353 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000354 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
Simon Kelley4f7b3042012-11-28 21:27:02 +0000355 {
356 tftp_ok = 0;
357 dhcp_ok = 0;
358 }
359#endif
360
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100361 /* add to list */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100362 if ((iface = whine_malloc(sizeof(struct irec))))
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100363 {
364 iface->addr = *addr;
365 iface->netmask = netmask;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100366 iface->tftp_ok = tftp_ok;
Simon Kelley9380ba72012-04-16 14:41:56 +0100367 iface->dhcp_ok = dhcp_ok;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000368 iface->dns_auth = auth_dns;
Simon Kelley1f15b812009-10-13 17:49:32 +0100369 iface->mtu = mtu;
Simon Kelley74c95c22011-10-19 09:33:39 +0100370 iface->dad = dad;
Simon Kelley5d162f22012-12-20 14:55:46 +0000371 iface->done = iface->multicast_done = 0;
372 iface->index = if_index;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100373 if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
Simon Kelley6f13e532012-04-17 14:25:06 +0100374 {
375 strcpy(iface->name, ifr.ifr_name);
Simon Kelley115ac3e2013-05-20 11:28:32 +0100376 iface->next = daemon->interfaces;
377 daemon->interfaces = iface;
Simon Kelley6f13e532012-04-17 14:25:06 +0100378 return 1;
379 }
380 free(iface);
Simon Kelley5d162f22012-12-20 14:55:46 +0000381
Simon Kelley44a2a312004-03-10 20:04:35 +0000382 }
383
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100384 errno = ENOMEM;
385 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000386}
387
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100388#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000389static int iface_allowed_v6(struct in6_addr *local, int prefix,
Simon Kelleybad7b872012-12-20 22:00:39 +0000390 int scope, int if_index, int flags,
Simon Kelley1f776932012-12-16 19:46:08 +0000391 int preferred, int valid, void *vparam)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000392{
Simon Kelley59353a62004-11-21 19:34:28 +0000393 union mysockaddr addr;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100394 struct in_addr netmask; /* dummy */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100395 netmask.s_addr = 0;
Simon Kelley52b92f42012-01-22 16:05:15 +0000396
397 (void)prefix; /* warning */
398 (void)scope; /* warning */
Simon Kelley1f776932012-12-16 19:46:08 +0000399 (void)preferred;
400 (void)valid;
Simon Kelley44a2a312004-03-10 20:04:35 +0000401
Simon Kelley849a8352006-06-09 21:02:31 +0100402 memset(&addr, 0, sizeof(addr));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000403#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100404 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000405#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100406 addr.in6.sin6_family = AF_INET6;
407 addr.in6.sin6_addr = *local;
408 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley52b92f42012-01-22 16:05:15 +0000409 addr.in6.sin6_scope_id = if_index;
Simon Kelley849a8352006-06-09 21:02:31 +0100410
Simon Kelley115ac3e2013-05-20 11:28:32 +0100411 return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, !!(flags & IFACE_TENTATIVE));
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100412}
413#endif
Simon Kelley59353a62004-11-21 19:34:28 +0000414
Simon Kelley3f2873d2013-05-14 11:28:47 +0100415static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100416 struct in_addr netmask, struct in_addr broadcast, void *vparam)
417{
418 union mysockaddr addr;
Simon Kelley849a8352006-06-09 21:02:31 +0100419
420 memset(&addr, 0, sizeof(addr));
Simon Kelley1ab84e22004-01-29 16:48:35 +0000421#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100422 addr.in.sin_len = sizeof(addr.in);
Simon Kelley1ab84e22004-01-29 16:48:35 +0000423#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100424 addr.in.sin_family = AF_INET;
425 addr.in.sin_addr = broadcast; /* warning */
426 addr.in.sin_addr = local;
427 addr.in.sin_port = htons(daemon->port);
Simon Kelley44a2a312004-03-10 20:04:35 +0000428
Simon Kelley115ac3e2013-05-20 11:28:32 +0100429 return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, 0);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100430}
431
Simon Kelley115ac3e2013-05-20 11:28:32 +0100432int enumerate_interfaces(int reset)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100433{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100434 static struct addrlist *spare = NULL;
435 static int done = 0;
436 struct iface_param param;
437 int errsave, ret = 1;
438 struct addrlist *addr, *tmp;
439 struct interface_name *intname;
440
Simon Kelley76dd75d2013-05-23 10:04:25 +0100441 /* Do this max once per select cycle - also inhibits netlink socket use
442 in TCP child processes. */
443
Simon Kelley115ac3e2013-05-20 11:28:32 +0100444 if (reset)
445 {
446 done = 0;
447 return 1;
448 }
449
450 if (done)
451 return 1;
452
453 done = 1;
454
455 if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
456 return 0;
457
458 /* remove addresses stored against interface_names */
459 for (intname = daemon->int_names; intname; intname = intname->next)
460 {
461 for (addr = intname->addr4; addr; addr = tmp)
462 {
463 tmp = addr->next;
464 addr->next = spare;
465 spare = addr;
466 }
467
468 intname->addr4 = NULL;
469
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100470#ifdef HAVE_IPV6
Simon Kelley115ac3e2013-05-20 11:28:32 +0100471 for (addr = intname->addr6; addr; addr = tmp)
472 {
473 tmp = addr->next;
474 addr->next = spare;
475 spare = addr;
476 }
477
478 intname->addr6 = NULL;
479#endif
480 }
481
482 param.spare = spare;
483
484#ifdef HAVE_IPV6
485 ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100486#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000487
Simon Kelley115ac3e2013-05-20 11:28:32 +0100488 if (ret)
489 ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);
490
491 errsave = errno;
492 close(param.fd);
493 errno = errsave;
494
495 spare = param.spare;
496
497 return ret;
Simon Kelley44a2a312004-03-10 20:04:35 +0000498}
499
Simon Kelley5aabfc72007-08-29 11:24:47 +0100500/* set NONBLOCK bit on fd: See Stevens 16.6 */
Simon Kelley7cebd202006-05-06 14:13:33 +0100501int fix_fd(int fd)
502{
503 int flags;
504
505 if ((flags = fcntl(fd, F_GETFL)) == -1 ||
Simon Kelley5aabfc72007-08-29 11:24:47 +0100506 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
Simon Kelley7cebd202006-05-06 14:13:33 +0100507 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100508
Simon Kelley7cebd202006-05-06 14:13:33 +0100509 return 1;
510}
511
Simon Kelley74c95c22011-10-19 09:33:39 +0100512static int make_sock(union mysockaddr *addr, int type, int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000513{
Simon Kelley28866e92011-02-14 20:19:14 +0000514 int family = addr->sa.sa_family;
515 int fd, rc, opt = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100516
Simon Kelley28866e92011-02-14 20:19:14 +0000517 if ((fd = socket(family, type, 0)) == -1)
Simon Kelley316e2732010-01-22 20:16:09 +0000518 {
Simon Kelley28866e92011-02-14 20:19:14 +0000519 int port;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100520 char *s;
Simon Kelley28866e92011-02-14 20:19:14 +0000521
522 /* No error if the kernel just doesn't support this IP flavour */
523 if (errno == EPROTONOSUPPORT ||
524 errno == EAFNOSUPPORT ||
525 errno == EINVAL)
526 return -1;
527
528 err:
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100529 port = prettyprint_addr(addr, daemon->addrbuff);
530 if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
531 sprintf(daemon->addrbuff, "port %d", port);
532 s = _("failed to create listening socket for %s: %s");
533
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100534 if (fd != -1)
535 close (fd);
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100536
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100537 if (dienow)
538 {
539 /* failure to bind addresses given by --listen-address at this point
540 is OK if we're doing bind-dynamic */
541 if (!option_bool(OPT_CLEVERBIND))
542 die(s, daemon->addrbuff, EC_BADNET);
543 }
544 else
545 my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
546
Simon Kelley74c95c22011-10-19 09:33:39 +0100547 return -1;
Simon Kelley28866e92011-02-14 20:19:14 +0000548 }
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100549
Simon Kelley28866e92011-02-14 20:19:14 +0000550 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
551 goto err;
552
553#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000554 if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000555 goto err;
556#endif
557
Simon Kelley74c95c22011-10-19 09:33:39 +0100558 if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000559 goto err;
560
561 if (type == SOCK_STREAM)
562 {
563 if (listen(fd, 5) == -1)
564 goto err;
565 }
566 else if (!option_bool(OPT_NOWILD))
567 {
568 if (family == AF_INET)
569 {
570#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000571 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000572 goto err;
573#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
574 if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
575 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
576 goto err;
577#endif
578 }
579#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000580 else if (!set_ipv6pktinfo(fd))
581 goto err;
Simon Kelley316e2732010-01-22 20:16:09 +0000582#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000583 }
Simon Kelleyc72daea2012-01-05 21:33:27 +0000584
Simon Kelley28866e92011-02-14 20:19:14 +0000585 return fd;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100586}
Simon Kelleyc72daea2012-01-05 21:33:27 +0000587
588#ifdef HAVE_IPV6
589int set_ipv6pktinfo(int fd)
590{
591 int opt = 1;
592
593 /* The API changed around Linux 2.6.14 but the old ABI is still supported:
594 handle all combinations of headers and kernel.
595 OpenWrt note that this fixes the problem addressed by your very broken patch. */
596 daemon->v6pktinfo = IPV6_PKTINFO;
597
598#ifdef IPV6_RECVPKTINFO
599 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
600 return 1;
601# ifdef IPV6_2292PKTINFO
602 else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
603 {
604 daemon->v6pktinfo = IPV6_2292PKTINFO;
605 return 1;
606 }
607# endif
608#else
609 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
610 return 1;
611#endif
612
613 return 0;
614}
615#endif
Simon Kelley22ce5502013-01-22 13:53:04 +0000616
617
618/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
619int tcp_interface(int fd, int af)
620{
621 int if_index = 0;
622
623#ifdef HAVE_LINUX_NETWORK
624 int opt = 1;
625 struct cmsghdr *cmptr;
626 struct msghdr msg;
627
628 /* use mshdr do that the CMSDG_* macros are available */
629 msg.msg_control = daemon->packet;
630 msg.msg_controllen = daemon->packet_buff_sz;
631
632 /* we overwrote the buffer... */
633 daemon->srv_save = NULL;
634
635 if (af == AF_INET)
636 {
637 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
638 getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
639 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
640 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
641 {
642 union {
643 unsigned char *c;
644 struct in_pktinfo *p;
645 } p;
646
647 p.c = CMSG_DATA(cmptr);
648 if_index = p.p->ipi_ifindex;
649 }
650 }
651#ifdef HAVE_IPV6
652 else
653 {
654 /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
655 it was removed in RFC-3542 !!!!
656
657 Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
658 uses the old ABI, and should work with pre- and post-3542 kernel headers */
659
660#ifdef IPV6_2292PKTOPTIONS
661# define PKTOPTIONS IPV6_2292PKTOPTIONS
662#else
663# define PKTOPTIONS IPV6_PKTOPTIONS
664#endif
665
666 if (set_ipv6pktinfo(fd) &&
667 getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
668 {
669 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
670 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
671 {
672 union {
673 unsigned char *c;
674 struct in6_pktinfo *p;
675 } p;
676 p.c = CMSG_DATA(cmptr);
677
678 if_index = p.p->ipi6_ifindex;
679 }
680 }
681 }
682#endif /* IPV6 */
683#endif /* Linux */
684
685 return if_index;
686}
Simon Kelley28866e92011-02-14 20:19:14 +0000687
Simon Kelley74c95c22011-10-19 09:33:39 +0100688static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
Simon Kelley28866e92011-02-14 20:19:14 +0000689{
690 struct listener *l = NULL;
691 int fd = -1, tcpfd = -1, tftpfd = -1;
692
693 if (daemon->port != 0)
694 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100695 fd = make_sock(addr, SOCK_DGRAM, dienow);
696 tcpfd = make_sock(addr, SOCK_STREAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000697 }
698
699#ifdef HAVE_TFTP
700 if (do_tftp)
701 {
702 if (addr->sa.sa_family == AF_INET)
703 {
704 /* port must be restored to DNS port for TCP code */
705 short save = addr->in.sin_port;
706 addr->in.sin_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100707 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000708 addr->in.sin_port = save;
709 }
710# ifdef HAVE_IPV6
711 else
712 {
713 short save = addr->in6.sin6_port;
714 addr->in6.sin6_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100715 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000716 addr->in6.sin6_port = save;
717 }
718# endif
719 }
Simon Kelley44a2a312004-03-10 20:04:35 +0000720#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100721
Simon Kelley28866e92011-02-14 20:19:14 +0000722 if (fd != -1 || tcpfd != -1 || tftpfd != -1)
723 {
724 l = safe_malloc(sizeof(struct listener));
725 l->next = NULL;
726 l->family = addr->sa.sa_family;
727 l->fd = fd;
728 l->tcpfd = tcpfd;
729 l->tftpfd = tftpfd;
730 }
731
732 return l;
733}
734
Simon Kelley74c95c22011-10-19 09:33:39 +0100735void create_wildcard_listeners(void)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100736{
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100737 union mysockaddr addr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100738 struct listener *l, *l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100739
Simon Kelley849a8352006-06-09 21:02:31 +0100740 memset(&addr, 0, sizeof(addr));
Simon Kelley28866e92011-02-14 20:19:14 +0000741#ifdef HAVE_SOCKADDR_SA_LEN
742 addr.in.sin_len = sizeof(addr.in);
743#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100744 addr.in.sin_family = AF_INET;
745 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100746 addr.in.sin_port = htons(daemon->port);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100747
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100748 l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000749
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100750#ifdef HAVE_IPV6
Simon Kelley28866e92011-02-14 20:19:14 +0000751 memset(&addr, 0, sizeof(addr));
752# ifdef HAVE_SOCKADDR_SA_LEN
753 addr.in6.sin6_len = sizeof(addr.in6);
754# endif
755 addr.in6.sin6_family = AF_INET6;
756 addr.in6.sin6_addr = in6addr_any;
757 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100758
759 l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000760 if (l)
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100761 l->next = l6;
Simon Kelley28866e92011-02-14 20:19:14 +0000762 else
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100763 l = l6;
Simon Kelley832af0b2007-01-21 20:01:28 +0000764#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100765
Simon Kelley74c95c22011-10-19 09:33:39 +0100766 daemon->listeners = l;
Simon Kelley44a2a312004-03-10 20:04:35 +0000767}
768
Simon Kelley74c95c22011-10-19 09:33:39 +0100769void create_bound_listeners(int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000770{
Simon Kelley74c95c22011-10-19 09:33:39 +0100771 struct listener *new;
Simon Kelley44a2a312004-03-10 20:04:35 +0000772 struct irec *iface;
Simon Kelley52d4abf2012-03-21 21:39:48 +0000773 struct iname *if_tmp;
Simon Kelley73a08a22009-02-05 20:28:08 +0000774
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100775 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley74c95c22011-10-19 09:33:39 +0100776 if (!iface->done && !iface->dad &&
777 (new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
Simon Kelley28866e92011-02-14 20:19:14 +0000778 {
779 new->iface = iface;
Simon Kelley74c95c22011-10-19 09:33:39 +0100780 new->next = daemon->listeners;
781 daemon->listeners = new;
782 iface->done = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000783 }
Simon Kelley52d4abf2012-03-21 21:39:48 +0000784
785 /* Check for --listen-address options that haven't been used because there's
786 no interface with a matching address. These may be valid: eg it's possible
787 to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
788
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100789 If the address isn't valid the bind() will fail and we'll die()
790 (except in bind-dynamic mode, when we'll complain but keep trying.)
Simon Kelley52d4abf2012-03-21 21:39:48 +0000791
792 The resulting listeners have the ->iface field NULL, and this has to be
793 handled by the DNS and TFTP code. It disables --localise-queries processing
794 (no netmask) and some MTU login the tftp code. */
795
796 for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
797 if (!if_tmp->used &&
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100798 (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
Simon Kelley52d4abf2012-03-21 21:39:48 +0000799 {
800 new->iface = NULL;
801 new->next = daemon->listeners;
802 daemon->listeners = new;
803 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000804}
805
Simon Kelley74c95c22011-10-19 09:33:39 +0100806int is_dad_listeners(void)
807{
808 struct irec *iface;
809
810 if (option_bool(OPT_NOWILD))
811 for (iface = daemon->interfaces; iface; iface = iface->next)
812 if (iface->dad && !iface->done)
813 return 1;
814
815 return 0;
816}
Simon Kelley5d162f22012-12-20 14:55:46 +0000817
818#ifdef HAVE_DHCP6
819void join_multicast(int dienow)
820{
821 struct irec *iface, *tmp;
822
823 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley19624462012-12-28 11:18:09 +0000824 if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
Simon Kelley5d162f22012-12-20 14:55:46 +0000825 {
826 /* There's an irec per address but we only want to join for multicast
827 once per interface. Weed out duplicates. */
828 for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
829 if (tmp->multicast_done && tmp->index == iface->index)
830 break;
831
832 iface->multicast_done = 1;
833
834 if (!tmp)
835 {
836 struct ipv6_mreq mreq;
837 int err = 0;
838
839 mreq.ipv6mr_interface = iface->index;
840
841 inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
842
843 if (daemon->doing_dhcp6 &&
844 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
845 err = 1;
846
847 inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
848
849 if (daemon->doing_dhcp6 &&
850 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
851 err = 1;
852
853 inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
854
855 if (daemon->doing_ra &&
856 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
857 err = 1;
858
859 if (err)
860 {
861 char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
862 if (dienow)
863 die(s, iface->name, EC_BADNET);
864 else
865 my_syslog(LOG_ERR, s, iface->name, strerror(errno));
866 }
867 }
868 }
869}
870#endif
871
Simon Kelley9009d742008-11-14 20:04:27 +0000872/* return a UDP socket bound to a random port, have to cope with straying into
Simon Kelley1a6bca82008-07-11 11:11:42 +0100873 occupied port nos and reserved ones. */
874int random_sock(int family)
875{
876 int fd;
877
878 if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
879 {
Simon Kelley3927da42008-07-20 15:10:39 +0100880 union mysockaddr addr;
Simon Kelley1ad24ae2008-07-20 20:22:50 +0100881 unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
Simon Kelley9009d742008-11-14 20:04:27 +0000882 int tries = ports_avail < 30 ? 3 * ports_avail : 100;
Simon Kelley3927da42008-07-20 15:10:39 +0100883
Simon Kelley1a6bca82008-07-11 11:11:42 +0100884 memset(&addr, 0, sizeof(addr));
Simon Kelley3927da42008-07-20 15:10:39 +0100885 addr.sa.sa_family = family;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100886
Simon Kelley1ad24ae2008-07-20 20:22:50 +0100887 /* don't loop forever if all ports in use. */
888
Simon Kelley1a6bca82008-07-11 11:11:42 +0100889 if (fix_fd(fd))
Simon Kelley9009d742008-11-14 20:04:27 +0000890 while(tries--)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100891 {
892 unsigned short port = rand16();
893
Simon Kelley3927da42008-07-20 15:10:39 +0100894 if (daemon->min_port != 0)
Simon Kelley1ad24ae2008-07-20 20:22:50 +0100895 port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100896
897 if (family == AF_INET)
898 {
899 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley3927da42008-07-20 15:10:39 +0100900 addr.in.sin_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100901#ifdef HAVE_SOCKADDR_SA_LEN
902 addr.in.sin_len = sizeof(struct sockaddr_in);
903#endif
904 }
905#ifdef HAVE_IPV6
906 else
907 {
908 addr.in6.sin6_addr = in6addr_any;
Simon Kelley3927da42008-07-20 15:10:39 +0100909 addr.in6.sin6_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100910#ifdef HAVE_SOCKADDR_SA_LEN
911 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
912#endif
913 }
914#endif
915
916 if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
917 return fd;
918
919 if (errno != EADDRINUSE && errno != EACCES)
920 break;
921 }
922
923 close(fd);
924 }
925
926 return -1;
927}
928
929
Simon Kelley824af852008-02-12 20:43:05 +0000930int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
931{
932 union mysockaddr addr_copy = *addr;
933
934 /* cannot set source _port_ for TCP connections. */
935 if (is_tcp)
936 {
937 if (addr_copy.sa.sa_family == AF_INET)
938 addr_copy.in.sin_port = 0;
939#ifdef HAVE_IPV6
940 else
941 addr_copy.in6.sin6_port = 0;
942#endif
943 }
944
945 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
946 return 0;
947
948#if defined(SO_BINDTODEVICE)
Simon Kelley73a08a22009-02-05 20:28:08 +0000949 if (intname[0] != 0 &&
Simon Kelley316e2732010-01-22 20:16:09 +0000950 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
Simon Kelley824af852008-02-12 20:43:05 +0000951 return 0;
952#endif
953
954 return 1;
955}
956
957static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000958{
959 struct serverfd *sfd;
Simon Kelley824af852008-02-12 20:43:05 +0000960 int errsave;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100961
Simon Kelley1a6bca82008-07-11 11:11:42 +0100962 /* when using random ports, servers which would otherwise use
963 the INADDR_ANY/port0 socket have sfd set to NULL */
Simon Kelley73a08a22009-02-05 20:28:08 +0000964 if (!daemon->osport && intname[0] == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100965 {
966 errno = 0;
967
968 if (addr->sa.sa_family == AF_INET &&
969 addr->in.sin_addr.s_addr == INADDR_ANY &&
970 addr->in.sin_port == htons(0))
971 return NULL;
972
973#ifdef HAVE_IPV6
974 if (addr->sa.sa_family == AF_INET6 &&
975 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
976 addr->in6.sin6_port == htons(0))
977 return NULL;
978#endif
979 }
980
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000981 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +0000982 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
983 if (sockaddr_isequal(&sfd->source_addr, addr) &&
984 strcmp(intname, sfd->interface) == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000985 return sfd;
986
987 /* need to make a new one. */
988 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100989 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000990 return NULL;
991
992 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
993 {
994 free(sfd);
995 return NULL;
996 }
997
Simon Kelley824af852008-02-12 20:43:05 +0000998 if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
999 {
1000 errsave = errno; /* save error from bind. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001001 close(sfd->fd);
1002 free(sfd);
1003 errno = errsave;
1004 return NULL;
1005 }
Simon Kelley824af852008-02-12 20:43:05 +00001006
1007 strcpy(sfd->interface, intname);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001008 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +00001009 sfd->next = daemon->sfds;
1010 daemon->sfds = sfd;
1011 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001012}
1013
Simon Kelley824af852008-02-12 20:43:05 +00001014/* create upstream sockets during startup, before root is dropped which may be needed
1015 this allows query_port to be a low port and interface binding */
1016void pre_allocate_sfds(void)
1017{
1018 struct server *srv;
1019
1020 if (daemon->query_port != 0)
1021 {
1022 union mysockaddr addr;
1023 memset(&addr, 0, sizeof(addr));
1024 addr.in.sin_family = AF_INET;
1025 addr.in.sin_addr.s_addr = INADDR_ANY;
1026 addr.in.sin_port = htons(daemon->query_port);
1027#ifdef HAVE_SOCKADDR_SA_LEN
1028 addr.in.sin_len = sizeof(struct sockaddr_in);
1029#endif
1030 allocate_sfd(&addr, "");
1031#ifdef HAVE_IPV6
1032 memset(&addr, 0, sizeof(addr));
1033 addr.in6.sin6_family = AF_INET6;
1034 addr.in6.sin6_addr = in6addr_any;
1035 addr.in6.sin6_port = htons(daemon->query_port);
1036#ifdef HAVE_SOCKADDR_SA_LEN
1037 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1038#endif
1039 allocate_sfd(&addr, "");
1040#endif
1041 }
1042
1043 for (srv = daemon->servers; srv; srv = srv->next)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001044 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
Simon Kelley824af852008-02-12 20:43:05 +00001045 !allocate_sfd(&srv->source_addr, srv->interface) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001046 errno != 0 &&
Simon Kelley28866e92011-02-14 20:19:14 +00001047 option_bool(OPT_NOWILD))
Simon Kelley824af852008-02-12 20:43:05 +00001048 {
Simon Kelley316e2732010-01-22 20:16:09 +00001049 prettyprint_addr(&srv->source_addr, daemon->namebuff);
Simon Kelley73a08a22009-02-05 20:28:08 +00001050 if (srv->interface[0] != 0)
Simon Kelley824af852008-02-12 20:43:05 +00001051 {
1052 strcat(daemon->namebuff, " ");
1053 strcat(daemon->namebuff, srv->interface);
1054 }
1055 die(_("failed to bind server socket for %s: %s"),
1056 daemon->namebuff, EC_BADNET);
1057 }
1058}
1059
1060
Simon Kelley5aabfc72007-08-29 11:24:47 +01001061void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001062{
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001063 struct irec *iface;
Simon Kelley3be34542004-09-11 19:12:13 +01001064 struct server *new, *tmp, *ret = NULL;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001065 int port = 0;
1066
Simon Kelley316e2732010-01-22 20:16:09 +00001067 /* interface may be new since startup */
Simon Kelley28866e92011-02-14 20:19:14 +00001068 if (!option_bool(OPT_NOWILD))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001069 enumerate_interfaces(0);
Simon Kelley316e2732010-01-22 20:16:09 +00001070
Simon Kelley3be34542004-09-11 19:12:13 +01001071 for (new = daemon->servers; new; new = tmp)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001072 {
1073 tmp = new->next;
1074
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001075 if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001076 {
Simon Kelley3d8df262005-08-29 12:19:27 +01001077 port = prettyprint_addr(&new->addr, daemon->namebuff);
1078
Simon Kelley16972692006-10-16 20:04:18 +01001079 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
1080 if (new->addr.sa.sa_family == AF_INET &&
1081 new->addr.in.sin_addr.s_addr == 0)
1082 {
1083 free(new);
1084 continue;
1085 }
1086
Simon Kelley3d8df262005-08-29 12:19:27 +01001087 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001088 if (sockaddr_isequal(&new->addr, &iface->addr))
1089 break;
1090 if (iface)
1091 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001092 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001093 free(new);
1094 continue;
1095 }
1096
1097 /* Do we need a socket set? */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001098 if (!new->sfd &&
1099 !(new->sfd = allocate_sfd(&new->source_addr, new->interface)) &&
1100 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001101 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001102 my_syslog(LOG_WARNING,
1103 _("ignoring nameserver %s - cannot make/bind socket: %s"),
1104 daemon->namebuff, strerror(errno));
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001105 free(new);
1106 continue;
1107 }
1108 }
1109
1110 /* reverse order - gets it right. */
1111 new->next = ret;
1112 ret = new;
1113
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001114 if (!(new->flags & SERV_NO_REBIND))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001115 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001116 if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
1117 {
1118 char *s1, *s2;
1119 if (!(new->flags & SERV_HAS_DOMAIN))
1120 s1 = _("unqualified"), s2 = _("names");
1121 else if (strlen(new->domain) == 0)
1122 s1 = _("default"), s2 = "";
1123 else
1124 s1 = _("domain"), s2 = new->domain;
1125
1126 if (new->flags & SERV_NO_ADDR)
1127 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
1128 else if (new->flags & SERV_USE_RESOLV)
1129 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
1130 else if (!(new->flags & SERV_LITERAL_ADDRESS))
1131 my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
1132 }
1133 else if (new->interface[0] != 0)
1134 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001135 else
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001136 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001137 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001138 }
1139
Simon Kelley3be34542004-09-11 19:12:13 +01001140 daemon->servers = ret;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001141}
Simon Kelley849a8352006-06-09 21:02:31 +01001142
1143/* Return zero if no servers found, in that case we keep polling.
1144 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001145int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001146{
1147 FILE *f;
1148 char *line;
1149 struct server *old_servers = NULL;
1150 struct server *new_servers = NULL;
Simon Kelley849a8352006-06-09 21:02:31 +01001151 struct server *serv;
1152 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001153
Simon Kelley849a8352006-06-09 21:02:31 +01001154 /* buff happens to be MAXDNAME long... */
1155 if (!(f = fopen(fname, "r")))
1156 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001157 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +01001158 return 0;
1159 }
1160
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001161 /* move old servers to free list - we can reuse the memory
1162 and not risk malloc if there are the same or fewer new servers.
1163 Servers which were specced on the command line go to the new list. */
Simon Kelley849a8352006-06-09 21:02:31 +01001164 for (serv = daemon->servers; serv;)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001165 {
1166 struct server *tmp = serv->next;
1167 if (serv->flags & SERV_FROM_RESOLV)
1168 {
1169 serv->next = old_servers;
Simon Kelley849a8352006-06-09 21:02:31 +01001170 old_servers = serv;
1171 /* forward table rules reference servers, so have to blow them away */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001172 server_gone(serv);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001173 }
1174 else
1175 {
1176 serv->next = new_servers;
1177 new_servers = serv;
1178 }
1179 serv = tmp;
1180 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001181
Simon Kelley849a8352006-06-09 21:02:31 +01001182 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1183 {
1184 union mysockaddr addr, source_addr;
1185 char *token = strtok(line, " \t\n\r");
1186
Simon Kelley5aabfc72007-08-29 11:24:47 +01001187 if (!token)
1188 continue;
1189 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +01001190 continue;
1191 if (!(token = strtok(NULL, " \t\n\r")))
1192 continue;
1193
1194 memset(&addr, 0, sizeof(addr));
1195 memset(&source_addr, 0, sizeof(source_addr));
1196
1197 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
1198 {
1199#ifdef HAVE_SOCKADDR_SA_LEN
1200 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1201#endif
1202 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1203 addr.in.sin_port = htons(NAMESERVER_PORT);
1204 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1205 source_addr.in.sin_port = htons(daemon->query_port);
1206 }
1207#ifdef HAVE_IPV6
Simon Kelley7de060b2011-08-26 17:24:52 +01001208 else
1209 {
1210 int scope_index = 0;
1211 char *scope_id = strchr(token, '%');
1212
1213 if (scope_id)
1214 {
1215 *(scope_id++) = 0;
1216 scope_index = if_nametoindex(scope_id);
1217 }
1218
1219 if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1220 {
Simon Kelley849a8352006-06-09 21:02:31 +01001221#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley7de060b2011-08-26 17:24:52 +01001222 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
Simon Kelley849a8352006-06-09 21:02:31 +01001223#endif
Simon Kelley7de060b2011-08-26 17:24:52 +01001224 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1225 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
1226 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1227 addr.in6.sin6_scope_id = scope_index;
1228 source_addr.in6.sin6_addr = in6addr_any;
1229 source_addr.in6.sin6_port = htons(daemon->query_port);
1230 source_addr.in6.sin6_scope_id = 0;
1231 }
1232 else
1233 continue;
Simon Kelley849a8352006-06-09 21:02:31 +01001234 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001235#else /* IPV6 */
Simon Kelley849a8352006-06-09 21:02:31 +01001236 else
1237 continue;
Simon Kelley7de060b2011-08-26 17:24:52 +01001238#endif
1239
Simon Kelley849a8352006-06-09 21:02:31 +01001240 if (old_servers)
1241 {
1242 serv = old_servers;
1243 old_servers = old_servers->next;
1244 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001245 else if (!(serv = whine_malloc(sizeof (struct server))))
Simon Kelley849a8352006-06-09 21:02:31 +01001246 continue;
1247
1248 /* this list is reverse ordered:
1249 it gets reversed again in check_servers */
1250 serv->next = new_servers;
1251 new_servers = serv;
1252 serv->addr = addr;
1253 serv->source_addr = source_addr;
1254 serv->domain = NULL;
Simon Kelley824af852008-02-12 20:43:05 +00001255 serv->interface[0] = 0;
Simon Kelley849a8352006-06-09 21:02:31 +01001256 serv->sfd = NULL;
1257 serv->flags = SERV_FROM_RESOLV;
Simon Kelley824af852008-02-12 20:43:05 +00001258 serv->queries = serv->failed_queries = 0;
Simon Kelley849a8352006-06-09 21:02:31 +01001259 gotone = 1;
1260 }
1261
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001262 /* Free any memory not used. */
Simon Kelley849a8352006-06-09 21:02:31 +01001263 while (old_servers)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001264 {
1265 struct server *tmp = old_servers->next;
1266 free(old_servers);
1267 old_servers = tmp;
1268 }
1269
Simon Kelley3be34542004-09-11 19:12:13 +01001270 daemon->servers = new_servers;
Simon Kelley849a8352006-06-09 21:02:31 +01001271 fclose(f);
1272
1273 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001274}
1275
1276
1277
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001278
1279
1280