blob: a3bbdbc13ba900bf09bf1b321af1273fff74453e [file] [log] [blame]
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001/* dnsmasq is Copyright (c) 2000 - 2003 Simon Kelley
2
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
5 the Free Software Foundation; version 2 dated June, 1991.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11*/
12
13/* Author's email: simon@thekelleys.org.uk */
14
15#include "dnsmasq.h"
16
17static char *add_iface(struct irec **list, unsigned int flags,
18 char *name, union mysockaddr *addr,
19 struct iname *names, struct iname *addrs,
20 struct iname *except)
21{
22 struct irec *iface;
23 int fd, opt;
24 struct iname *tmp;
25
26 /* we may need to check the whitelist */
27 if (names)
28 {
29 for (tmp = names; tmp; tmp = tmp->next)
30 if (tmp->name && (strcmp(tmp->name, name) == 0))
31 {
32 tmp->found = 1;
33 break;
34 }
35 if (!(flags & IFF_LOOPBACK) && !tmp)
36 /* not on whitelist and not loopback */
37 return NULL;
38 }
39
40 if (addrs)
41 {
42 for (tmp = addrs; tmp; tmp = tmp->next)
43 if (sockaddr_isequal(&tmp->addr, addr))
44 {
45 tmp->found = 1;
46 break;
47 }
48
49 if (!tmp)
50 /* not on whitelist */
51 return NULL;
52 }
53
54 /* check blacklist */
55 if (except)
56 for (tmp = except; tmp; tmp = tmp->next)
57 if (tmp->name && strcmp(tmp->name, name) == 0)
58 return NULL;
59
60 /* check whether the interface IP has been added already
61 it is possible to have multiple interfaces with the same address
62 and we may be re-scanning. */
63 for (iface = *list; iface; iface = iface->next)
64 if (sockaddr_isequal(&iface->addr, addr))
65 break;
66 if (iface)
67 {
68 iface->valid = 1;
69 return NULL;
70 }
71
72 if ((fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
73 return "failed to create socket: %s";
74
75 /* Set SO_REUSEADDR on the socket, this allows is to bind
76 specific addresses even if BIND is running and has bound *:53 */
77 opt = 1;
78 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
79 bind(fd, &addr->sa, sa_len(addr)))
80 {
81 int errsave = errno;
82 close(fd);
83 errno = errsave;
84 return "failed to bind socket: %s";
85 }
86
87 /* If OK, add it to the head of the list */
88 if (!(iface = malloc(sizeof(struct irec))))
89 {
90 close(fd);
91 return "cannot allocate interface";
92 }
93
94 iface->fd = fd;
95 iface->addr = *addr;
96 iface->next = *list;
97 iface->valid = 1;
98 *list = iface;
99
100 return NULL;
101}
102
103/* get all interfaces in system and for each one allowed add it to the chain
104 at interfacep. May be called more that once: interfaces which still exist
105 are left on the chain, those which have gone have sockets close()ed an are
106 unlinked. Return value is NULL if OK, an error string and the value of errno
107 on error. */
108char *enumerate_interfaces(struct irec **interfacep,
109 struct iname *names,
110 struct iname *addrs,
111 struct iname *except,
112 struct dhcp_context *dhcp,
113 int port)
114{
115 /* this code is adapted from Stevens, page 434. It finally
116 destroyed my faith in the C/unix API */
117 int len = 100 * sizeof(struct ifreq);
118 int errsave, lastlen = 0;
119 struct irec *iface, *prev;
120 char *buf, *ptr, *err = NULL;
121 struct ifconf ifc;
122 int fd = socket(PF_INET, SOCK_DGRAM, 0);
123 int rawfd = -1;
124
125 if (fd == -1)
126 return "cannot create socket to enumerate interfaces: %s";
127
128 /* make all interfaces as old. Any left that way after the scan are reaped. */
129 for (iface = *interfacep; iface; iface = iface->next)
130 iface->valid = 0;
131
132 while (1)
133 {
134 if (!(buf = malloc(len)))
135 {
136 err = "cannot allocate buffer";
137 goto end;
138 }
139 ifc.ifc_len = len;
140 ifc.ifc_buf = buf;
141 if (ioctl(fd, SIOCGIFCONF, &ifc) < 0)
142 {
143 if (errno != EINVAL || lastlen != 0)
144 {
145 err = "ioctl error while enumerating interfaces: %s";
146 goto end;
147 }
148 }
149 else
150 {
151 if (ifc.ifc_len == lastlen)
152 break; /* got a big enough buffer now */
153 lastlen = ifc.ifc_len;
154 }
155 len += 10*sizeof(struct ifreq);
156 free(buf);
157 }
158
159 for (ptr = buf; ptr < buf + ifc.ifc_len; )
160 {
161 struct ifreq *ifr = (struct ifreq *) ptr;
162 union mysockaddr addr;
163
164#ifdef HAVE_SOCKADDR_SA_LEN
165 ptr += ifr->ifr_addr.sa_len + IF_NAMESIZE;
166#else
167 ptr += sizeof(struct ifreq);
168#endif
169
170 /* copy address since getting flags overwrites */
171 if (ifr->ifr_addr.sa_family == AF_INET)
172 {
173 addr.in = *((struct sockaddr_in *) &ifr->ifr_addr);
174 addr.in.sin_port = htons(port);
175 }
176#ifdef HAVE_IPV6
177 else if (ifr->ifr_addr.sa_family == AF_INET6)
178 {
179#ifdef HAVE_BROKEN_SOCKADDR_IN6
180 addr.in6 = *((struct my_sockaddr_in6 *) &ifr->ifr_addr);
181#else
182 addr.in6 = *((struct sockaddr_in6 *) &ifr->ifr_addr);
183#endif
184 addr.in6.sin6_port = htons(port);
185 addr.in6.sin6_flowinfo = htonl(0);
186 }
187#endif
188 else
189 continue; /* unknown address family */
190
191 if (ioctl(fd, SIOCGIFFLAGS, ifr) < 0)
192 {
193 err = "ioctl error getting interface flags: %m";
194 goto end;
195 }
196
197 if ((err = add_iface(interfacep, ifr->ifr_flags, ifr->ifr_name,
198 &addr, names, addrs, except)))
199 goto end;
200
201 /* dhcp is non-null only on the first call: set up the relevant
202 interface-related DHCP stuff here. DHCP is IPv4 only.
203 Because errors here are ultimately fatal we can return directly and not bother
204 closing the descriptor.
205 */
206 if (dhcp && addr.sa.sa_family == AF_INET &&
207 !(ifr->ifr_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)))
208 {
209 struct in_addr netmask, broadcast;
210 struct dhcp_context *context;
211 int opt = 1;
212
213 if (ioctl(fd, SIOCGIFNETMASK, ifr) < 0)
214 return "ioctl error getting interface netmask: %s";
215
216 netmask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
217
218 if (ioctl(fd, SIOCGIFBRDADDR, ifr) < 0)
219 return "ioctl error getting interface broadcast address: %s";
220
221 broadcast = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
222
223 for (context = dhcp; context; context = context->next)
224 if (!context->iface && /* may be more than one iface with same addr */
225 ((addr.in.sin_addr.s_addr & netmask.s_addr) == (context->start.s_addr & netmask.s_addr)) &&
226 ((addr.in.sin_addr.s_addr & netmask.s_addr) == (context->end.s_addr & netmask.s_addr)))
227 {
228 struct sockaddr_in saddr;
229#ifdef HAVE_BPF
230 char filename[50];
231 int b = 0;
232
233 while (1)
234 {
235 sprintf(filename, "/dev/bpf%d", b);
236 if ((rawfd = open(filename, O_RDWR, 0)) == -1)
237 {
238 if (errno != EBUSY)
239 return"Cannot create DHCP BPF socket: %s";
240 b++;
241 }
242 else if (ioctl(rawfd, BIOCSETIF, ifr) < 0)
243 return "Can't attach interface to BPF device: %s";
244 else
245 break;
246 }
247
248 if (context->next)
249 return "no support for DHCP on multiple networks under this OS";
250#endif
251
252#ifdef HAVE_PF_PACKET
253 if (rawfd == -1 && /* same packet socket for all interfaces */
254 (rawfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETHERTYPE_IP))) == -1)
255 return "Cannot create DHCP packet socket: %s";
256
257 /* do this last so that the index is still in ifr for the
258 call to setsockopt(SO_BINDTODEVICE) */
259 if (ioctl(fd, SIOCGIFINDEX, ifr) < 0)
260 return "ioctl error getting interface index: %m";
261 context->ifindex = ifr->ifr_ifindex;
262#endif
263
264 context->rawfd = rawfd;
265 context->serv_addr = addr.in.sin_addr;
266 context->netmask = netmask;
267 context->broadcast = broadcast;
268 if (!(context->iface = malloc(strlen(ifr->ifr_name) + 1)))
269 return "cannot allocate interface name";
270
271 strcpy(context->iface, ifr->ifr_name);
272 saddr.sin_family = AF_INET;
273 saddr.sin_port = htons(DHCP_SERVER_PORT);
274 saddr.sin_addr.s_addr = INADDR_ANY;
275
276 if ((context->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
277 return "cannot create DHCP server socket: %s";
278
279 if (setsockopt(context->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
280#ifdef HAVE_PF_PACKET
281 setsockopt(context->fd, SOL_SOCKET, SO_BINDTODEVICE, ifr, sizeof(*ifr)) == -1 ||
282#endif
283 setsockopt(context->fd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)) == -1)
284 return "failed to set options on DHCP socket: %s";
285
286 if (bind(context->fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)))
287 return "failed to bind DHCP server socket: %s";
288
289 }
290
291 }
292 }
293
294#ifdef HAVE_BPF
295 /* now go through the interfaces again, looking for AF_LINK records
296 to get hardware addresses from */
297 for (ptr = buf; ptr < buf + ifc.ifc_len; )
298 {
299 struct ifreq *ifr = (struct ifreq *) ptr;
300 struct dhcp_context *context;
301
302#ifdef HAVE_SOCKADDR_SA_LEN
303 ptr += ifr->ifr_addr.sa_len + IF_NAMESIZE;
304#else
305 ptr += sizeof(struct ifreq);
306#endif
307 if (ifr->ifr_addr.sa_family == AF_LINK)
308 for (context = dhcp; context; context = context->next)
309 if (context->iface && strcmp(context->iface, ifr->ifr_name) == 0)
310 memcpy(context->hwaddr, LLADDR((struct sockaddr_dl *)&ifr->ifr_addr), ETHER_ADDR_LEN);
311 }
312#endif
313
314 end:
315 errsave = errno; /* since errno gets overwritten by close */
316 if (buf)
317 free(buf);
318 close(fd);
319 if (err)
320 {
321 errno = errsave;
322 return err;
323 }
324
325#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
326 /* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
327 /* This code snarfed from net-tools 1.60 and certainly linux specific, though
328 it shouldn't break on other Unices, and their SIOGIFCONF might work. */
329 {
330 FILE *f = fopen(IP6INTERFACES, "r");
331
332 if (f)
333 {
334 union mysockaddr addr;
335 unsigned int plen, scope, flags, if_idx;
336 char devname[20], addrstring[32];
337
338 while (fscanf(f, "%32s %02x %02x %02x %02x %20s\n",
339 addrstring, &if_idx, &plen, &scope, &flags, devname) != EOF)
340 {
341 int i;
342 unsigned char *addr6p = (unsigned char *) &addr.in6.sin6_addr;
343 memset(&addr, 0, sizeof(addr));
344 addr.sa.sa_family = AF_INET6;
345 for (i=0; i<16; i++)
346 {
347 unsigned int byte;
348 sscanf(addrstring+i+i, "%02x", &byte);
349 addr6p[i] = byte;
350 }
351#ifdef HAVE_SOCKADDR_SA_LEN
352 /* For completeness - should never be defined on Linux. */
353 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
354#endif
355 addr.in6.sin6_port = htons(port);
356 addr.in6.sin6_flowinfo = htonl(0);
357 addr.in6.sin6_scope_id = htonl(scope);
358
359 if ((err = add_iface(interfacep, flags, devname, &addr, names, addrs, except)))
360 {
361 errsave = errno;
362 fclose(f);
363 errno = errsave;
364 return err;
365 }
366 }
367
368 fclose(f);
369 }
370 }
371#endif /* LINUX */
372
373 /* now remove interfaces which were not found on this scan */
374 for(prev = NULL, iface = *interfacep; iface; )
375 {
376 if (iface->valid)
377 {
378 prev = iface;
379 iface = iface->next;
380 }
381 else
382 {
383 struct irec *tmp = iface;
384 close(iface->fd);
385 /* remove pending queries from this interface */
386 reap_forward(iface->fd);
387 /* unlink */
388 if (prev)
389 prev->next = iface->next;
390 else
391 *interfacep = iface->next;
392 iface = iface->next;
393 free(tmp);
394 }
395 }
396
397 return NULL; /* no error */
398}
399
400static struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds)
401{
402 struct serverfd *sfd;
403
404 /* may have a suitable one already */
405 for (sfd = *sfds; sfd; sfd = sfd->next )
406 if (sockaddr_isequal(&sfd->source_addr, addr))
407 return sfd;
408
409 /* need to make a new one. */
410 errno = ENOMEM; /* in case malloc fails. */
411 if (!(sfd = malloc(sizeof(struct serverfd))))
412 return NULL;
413
414 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
415 {
416 free(sfd);
417 return NULL;
418 }
419
420 if (bind(sfd->fd, (struct sockaddr *)addr, sa_len(addr)) == -1)
421 {
422 int errsave = errno; /* save error from bind. */
423 close(sfd->fd);
424 free(sfd);
425 errno = errsave;
426 return NULL;
427 }
428
429 sfd->source_addr = *addr;
430 sfd->next = *sfds;
431 *sfds = sfd;
432
433 return sfd;
434}
435
436struct server *check_servers(struct server *new, struct irec *interfaces, struct serverfd **sfds)
437{
438 char addrbuff[ADDRSTRLEN];
439 struct irec *iface;
440 struct server *tmp, *ret = NULL;
441 int port = 0;
442
443 /* forward table rules reference servers, so have to blow them away */
444 forward_init(0);
445
446 for (;new; new = tmp)
447 {
448 tmp = new->next;
449
450 if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)))
451 {
452#ifdef HAVE_IPV6
453 if (new->addr.sa.sa_family == AF_INET)
454 {
455 inet_ntop(AF_INET, &new->addr.in.sin_addr, addrbuff, ADDRSTRLEN);
456 port = ntohs(new->addr.in.sin_port);
457 }
458 else if (new->addr.sa.sa_family == AF_INET6)
459 {
460 inet_ntop(AF_INET6, &new->addr.in6.sin6_addr, addrbuff, ADDRSTRLEN);
461 port = ntohs(new->addr.in6.sin6_port);
462 }
463#else
464 strcpy(addrbuff, inet_ntoa(new->addr.in.sin_addr));
465 port = ntohs(new->addr.in.sin_port);
466#endif
467 for (iface = interfaces; iface; iface = iface->next)
468 if (sockaddr_isequal(&new->addr, &iface->addr))
469 break;
470 if (iface)
471 {
472 syslog(LOG_WARNING, "ignoring nameserver %s - local interface", addrbuff);
473 free(new);
474 continue;
475 }
476
477 /* Do we need a socket set? */
478 if (!new->sfd && !(new->sfd = allocate_sfd(&new->source_addr, sfds)))
479 {
480 syslog(LOG_WARNING,
481 "ignoring nameserver %s - cannot make/bind socket: %m", addrbuff);
482 free(new);
483 continue;
484 }
485 }
486
487 /* reverse order - gets it right. */
488 new->next = ret;
489 ret = new;
490
491 if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS))
492 {
493 char *s1, *s2;
494 if (new->flags & SERV_HAS_DOMAIN)
495 s1 = "domain", s2 = new->domain;
496 else
497 s1 = "unqualified", s2 = "domains";
498
499 if (new->flags & SERV_NO_ADDR)
500 syslog(LOG_INFO, "using local addresses only for %s %s", s1, s2);
501 else if (!(new->flags & SERV_LITERAL_ADDRESS))
502 syslog(LOG_INFO, "using nameserver %s#%d for %s %s", addrbuff, port, s1, s2);
503 }
504 else
505 syslog(LOG_INFO, "using nameserver %s#%d", addrbuff, port);
506 }
507
508 return ret;
509}
510
511struct server *reload_servers(char *fname, char *buff, struct server *serv, int query_port)
512{
513 FILE *f;
514 char *line;
515 struct server *old_servers = NULL;
516 struct server *new_servers = NULL;
517
518 /* move old servers to free list - we can reuse the memory
519 and not risk malloc if there are the same or fewer new servers.
520 Servers which were specced on the command line go to the new list. */
521 while (serv)
522 {
523 struct server *tmp = serv->next;
524 if (serv->flags & SERV_FROM_RESOLV)
525 {
526 serv->next = old_servers;
527 old_servers = serv;
528 }
529 else
530 {
531 serv->next = new_servers;
532 new_servers = serv;
533 }
534 serv = tmp;
535 }
536
537 /* buff happens to be NAXDNAME long... */
538 f = fopen(fname, "r");
539 if (!f)
540 {
541 syslog(LOG_ERR, "failed to read %s: %m", fname);
542 }
543 else
544 {
545 syslog(LOG_INFO, "reading %s", fname);
546 while ((line = fgets(buff, MAXDNAME, f)))
547 {
548 union mysockaddr addr, source_addr;
549 char *token = strtok(line, " \t\n\r");
550 struct server *serv;
551
552 if (!token || strcmp(token, "nameserver") != 0)
553 continue;
554 if (!(token = strtok(NULL, " \t\n")))
555 continue;
556
557#ifdef HAVE_IPV6
558 if (inet_pton(AF_INET, token, &addr.in.sin_addr))
559#else
560 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
561#endif
562 {
563#ifdef HAVE_SOCKADDR_SA_LEN
564 source_addr.in.sin_len = addr.in.sin_len = sizeof(struct sockaddr_in);
565#endif
566 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
567 addr.in.sin_port = htons(NAMESERVER_PORT);
568 source_addr.in.sin_addr.s_addr = INADDR_ANY;
569 source_addr.in.sin_port = htons(query_port);
570 }
571#ifdef HAVE_IPV6
572 else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr))
573 {
574#ifdef HAVE_SOCKADDR_SA_LEN
575 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(struct sockaddr_in6);
576#endif
577 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
578 addr.in6.sin6_port = htons(NAMESERVER_PORT);
579 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = htonl(0);
580 source_addr.in6.sin6_addr= in6addr_any;
581 source_addr.in6.sin6_port = htons(query_port);
582 }
583#endif /* IPV6 */
584 else
585 continue;
586
587 if (old_servers)
588 {
589 serv = old_servers;
590 old_servers = old_servers->next;
591 }
592 else if (!(serv = malloc(sizeof (struct server))))
593 continue;
594
595 /* this list is reverse ordered:
596 it gets reversed again in check_servers */
597 serv->next = new_servers;
598 new_servers = serv;
599 serv->addr = addr;
600 serv->source_addr = source_addr;
601 serv->domain = NULL;
602 serv->sfd = NULL;
603 serv->flags = SERV_FROM_RESOLV;
604 }
605
606 fclose(f);
607 }
608
609 /* Free any memory not used. */
610 while(old_servers)
611 {
612 struct server *tmp = old_servers->next;
613 free(old_servers);
614 old_servers = tmp;
615 }
616
617 return new_servers;
618}
619
620
621
622
623
624
625