]> git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/network.c
import of dnsmasq-2.16.tar.gz
[people/ms/dnsmasq.git] / src / network.c
1 /* 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
17 static struct irec *add_iface(struct daemon *daemon, struct irec *list, char *name, union mysockaddr *addr)
18 {
19 struct irec *iface;
20 struct iname *tmp;
21
22 /* check blacklist */
23 if (daemon->if_except)
24 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
25 if (tmp->name && strcmp(tmp->name, name) == 0)
26 {
27 /* record address of named interfaces, for TCP access control */
28 tmp->addr = *addr;
29 return list;
30 }
31
32 /* we may need to check the whitelist */
33 if (daemon->if_names || daemon->if_addrs)
34 {
35 int found = 0;
36
37 for (tmp = daemon->if_names; tmp; tmp = tmp->next)
38 if (tmp->name && (strcmp(tmp->name, name) == 0))
39 {
40 tmp->addr = *addr;
41 found = tmp->used = 1;
42 }
43
44 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
45 if (sockaddr_isequal(&tmp->addr, addr))
46 found = tmp->used = 1;
47
48 if (!found)
49 return list;
50 }
51
52 /* check whether the interface IP has been added already
53 it is possible to have multiple interfaces with the same address */
54 for (iface = list; iface; iface = iface->next)
55 if (sockaddr_isequal(&iface->addr, addr))
56 break;
57 if (iface)
58 return list;
59
60 /* If OK, add it to the head of the list */
61 iface = safe_malloc(sizeof(struct irec));
62 iface->addr = *addr;
63 iface->next = list;
64 return iface;
65 }
66
67
68 struct irec *enumerate_interfaces(struct daemon *daemon)
69 {
70 struct irec *iface = NULL;
71 char *buf, *ptr;
72 struct ifreq *ifr = NULL;
73 struct ifconf ifc;
74 int lastlen = 0;
75 int len = 20 * sizeof(struct ifreq);
76 int fd = socket(PF_INET, SOCK_DGRAM, 0);
77
78 if (fd == -1)
79 die ("cannot create socket to enumerate interfaces: %s", NULL);
80
81 while (1)
82 {
83 buf = safe_malloc(len);
84
85 ifc.ifc_len = len;
86 ifc.ifc_buf = buf;
87 if (ioctl(fd, SIOCGIFCONF, &ifc) < 0)
88 {
89 if (errno != EINVAL || lastlen != 0)
90 die ("ioctl error while enumerating interfaces: %s", NULL);
91 }
92 else
93 {
94 if (ifc.ifc_len == lastlen)
95 break; /* got a big enough buffer now */
96 lastlen = ifc.ifc_len;
97 }
98 len += 10*sizeof(struct ifreq);
99 free(buf);
100 }
101
102 for (ptr = buf; ptr < buf + len; )
103 {
104 union mysockaddr addr;
105 #ifdef HAVE_SOCKADDR_SA_LEN
106 /* subsequent entries may not be aligned, so copy into
107 an aligned buffer to avoid nasty complaints about
108 unaligned accesses. */
109 int ifr_len = ((struct ifreq *)ptr)->ifr_addr.sa_len + IF_NAMESIZE;
110 if (!(ifr = realloc(ifr, ifr_len)))
111 die("cannot allocate buffer", NULL);
112
113 memcpy(ifr, ptr, ifr_len);
114 ptr += ifr_len;
115 #else
116 ifr = (struct ifreq *)ptr;
117 ptr += sizeof(struct ifreq);
118 #endif
119
120 /* copy address since getting flags overwrites */
121 if (ifr->ifr_addr.sa_family == AF_INET)
122 {
123 addr.in = *((struct sockaddr_in *) &ifr->ifr_addr);
124 addr.in.sin_port = htons(daemon->port);
125 }
126 #ifdef HAVE_IPV6
127 else if (ifr->ifr_addr.sa_family == AF_INET6)
128 {
129 #ifdef HAVE_BROKEN_SOCKADDR_IN6
130 addr.in6 = *((struct my_sockaddr_in6 *) &ifr->ifr_addr);
131 #else
132 addr.in6 = *((struct sockaddr_in6 *) &ifr->ifr_addr);
133 #endif
134 addr.in6.sin6_port = htons(daemon->port);
135 addr.in6.sin6_flowinfo = htonl(0);
136 }
137 #endif
138 else
139 continue; /* unknown address family */
140
141 if (ioctl(fd, SIOCGIFFLAGS, ifr) < 0)
142 die("ioctl error getting interface flags: %m", NULL);
143
144 /* If we are restricting the set of interfaces to use, make
145 sure that loopback interfaces are in that set. */
146 if (daemon->if_names && (ifr->ifr_flags & IFF_LOOPBACK))
147 {
148 struct iname *lo;
149 for (lo = daemon->if_names; lo; lo = lo->next)
150 if (lo->name && strcmp(lo->name, ifr->ifr_name) == 0)
151 {
152 lo->isloop = 1;
153 break;
154 }
155 if (!lo)
156 {
157 lo = safe_malloc(sizeof(struct iname));
158 lo->name = safe_string_alloc(ifr->ifr_name);
159 lo->isloop = lo->used = 1;
160 lo->next = daemon->if_names;
161 daemon->if_names = lo;
162 }
163 }
164
165 iface = add_iface(daemon, iface, ifr->ifr_name, &addr);
166
167 #if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
168 /* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
169 /* This code snarfed from net-tools 1.60 and certainly linux specific, though
170 it shouldn't break on other Unices, and their SIOGIFCONF might work. */
171 {
172 FILE *f = fopen(IP6INTERFACES, "r");
173 int found = 0;
174 union mysockaddr addr6;
175
176 if (f)
177 {
178 unsigned int plen, scope, flags, if_idx;
179 char devname[20], addrstring[32];
180
181 while (fscanf(f, "%32s %02x %02x %02x %02x %20s\n",
182 addrstring, &if_idx, &plen, &scope, &flags, devname) != EOF)
183 {
184 if (strcmp(devname, ifr->ifr_name) == 0)
185 {
186 int i;
187 unsigned char *addr6p = (unsigned char *) &addr6.in6.sin6_addr;
188 memset(&addr6, 0, sizeof(addr6));
189 addr6.sa.sa_family = AF_INET6;
190 for (i=0; i<16; i++)
191 {
192 unsigned int byte;
193 sscanf(addrstring+i+i, "%02x", &byte);
194 addr6p[i] = byte;
195 }
196 addr6.in6.sin6_port = htons(daemon->port);
197 addr6.in6.sin6_flowinfo = htonl(0);
198 addr6.in6.sin6_scope_id = htonl(scope);
199
200 found = 1;
201 break;
202 }
203 }
204
205 fclose(f);
206 }
207
208 if (found)
209 iface = add_iface(daemon, iface, ifr->ifr_name, &addr6);
210 }
211 #endif /* LINUX */
212 }
213
214 if (buf)
215 free(buf);
216 #ifdef HAVE_SOCKADDR_SA_LEN
217 if (ifr)
218 free(ifr);
219 #endif
220 close(fd);
221
222 return iface;
223 }
224
225 #ifdef HAVE_IPV6
226 static int create_ipv6_listener(struct listener **link, int port)
227 {
228 union mysockaddr addr;
229 int tcpfd, fd, flags, save;
230 struct listener *l;
231 int opt = 1;
232
233 addr.in6.sin6_family = AF_INET6;
234 addr.in6.sin6_addr = in6addr_any;
235 addr.in6.sin6_port = htons(port);
236 addr.in6.sin6_flowinfo = htonl(0);
237 #ifdef HAVE_SOCKADDR_SA_LEN
238 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
239 #endif
240
241 /* No error of the kernel doesn't support IPv6 */
242 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
243 return (errno == EPROTONOSUPPORT ||
244 errno == EAFNOSUPPORT ||
245 errno == EINVAL);
246
247 if ((tcpfd = socket(AF_INET6, SOCK_STREAM, 0)) == -1)
248 {
249 save = errno;
250 close(fd);
251 errno = save;
252 return 0;
253 }
254
255 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
256 setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
257 setsockopt(fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
258 setsockopt(tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
259 (flags = fcntl(fd, F_GETFL, 0)) == -1 ||
260 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
261 (flags = fcntl(tcpfd, F_GETFL, 0)) == -1 ||
262 fcntl(tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
263 #ifdef IPV6_RECVPKTINFO
264 setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1 ||
265 #else
266 setsockopt(fd, IPV6_LEVEL, IPV6_PKTINFO, &opt, sizeof(opt)) == -1 ||
267 #endif
268 bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
269 listen(tcpfd, 5) == -1 ||
270 bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
271 {
272 save = errno;
273 close(fd);
274 close(tcpfd);
275 errno = save;
276 return 0;
277 }
278
279 l = safe_malloc(sizeof(struct listener));
280 l->fd = fd;
281 l->tcpfd = tcpfd;
282 l->family = AF_INET6;
283 l->next = NULL;
284 *link = l;
285
286 return 1;
287 }
288 #endif
289
290 struct listener *create_wildcard_listeners(int port)
291 {
292 #if !(defined(IP_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR)))
293 return NULL;
294 #else
295 union mysockaddr addr;
296 int opt = 1;
297 struct listener *l, *l6 = NULL;
298 int flags;
299 int tcpfd, fd;
300
301 addr.in.sin_family = AF_INET;
302 addr.in.sin_addr.s_addr = INADDR_ANY;
303 addr.in.sin_port = htons(port);
304 #ifdef HAVE_SOCKADDR_SA_LEN
305 addr.in.sin_len = sizeof(struct sockaddr_in);
306 #endif
307
308 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
309 return NULL;
310
311 if ((tcpfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
312 {
313 close (fd);
314 return NULL;
315 }
316
317 if (setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
318 bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
319 listen(tcpfd, 5) == -1 ||
320 (flags = fcntl(tcpfd, F_GETFL, 0)) == -1 ||
321 fcntl(tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
322 #ifdef HAVE_IPV6
323 !create_ipv6_listener(&l6, port) ||
324 #endif
325 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
326 (flags = fcntl(fd, F_GETFL, 0)) == -1 ||
327 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
328 #if defined(IP_PKTINFO)
329 setsockopt(fd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
330 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
331 setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
332 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 ||
333 #endif
334 bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
335 {
336 close(fd);
337 close(tcpfd);
338 return NULL;
339 }
340
341 l = safe_malloc(sizeof(struct listener));
342 l->family = AF_INET;
343 l->fd = fd;
344 l->tcpfd = tcpfd;
345 l->next = l6;
346
347 return l;
348
349 #endif
350 }
351
352 struct listener *create_bound_listeners(struct irec *interfaces, int port)
353 {
354
355 struct listener *listeners = NULL;
356 struct irec *iface;
357 int flags = port, opt = 1;
358
359 /* Create bound listeners only for IPv4, IPv6 always binds the wildcard */
360
361 #ifdef HAVE_IPV6
362 if (!create_ipv6_listener(&listeners, port))
363 die("failed to to create listening socket: %s", NULL);
364 #endif
365
366 for (iface = interfaces ;iface; iface = iface->next)
367 if (iface->addr.sa.sa_family == AF_INET)
368 {
369 struct listener *new = safe_malloc(sizeof(struct listener));
370 new->family = iface->addr.sa.sa_family;
371 new->next = listeners;
372 listeners = new;
373 if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 ||
374 (new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 ||
375 setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
376 setsockopt(new->tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
377 /* See Stevens 16.6 */
378 (flags = fcntl(new->tcpfd, F_GETFL, 0)) == -1 ||
379 fcntl(new->tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
380 (flags = fcntl(new->fd, F_GETFL, 0)) == -1 ||
381 fcntl(new->fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
382 bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
383 bind(new->fd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
384 listen(new->tcpfd, 5) == -1)
385 die("failed to to create listening socket: %s", NULL);
386 }
387
388 return listeners;
389 }
390
391 struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds)
392 {
393 struct serverfd *sfd;
394 int flags;
395
396 /* may have a suitable one already */
397 for (sfd = *sfds; sfd; sfd = sfd->next )
398 if (sockaddr_isequal(&sfd->source_addr, addr))
399 return sfd;
400
401 /* need to make a new one. */
402 errno = ENOMEM; /* in case malloc fails. */
403 if (!(sfd = malloc(sizeof(struct serverfd))))
404 return NULL;
405
406 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
407 {
408 free(sfd);
409 return NULL;
410 }
411
412 if (bind(sfd->fd, (struct sockaddr *)addr, sa_len(addr)) == -1 ||
413 (flags = fcntl(sfd->fd, F_GETFL, 0)) == -1 ||
414 fcntl(sfd->fd, F_SETFL, flags | O_NONBLOCK) == -1)
415 {
416 int errsave = errno; /* save error from bind. */
417 close(sfd->fd);
418 free(sfd);
419 errno = errsave;
420 return NULL;
421 }
422
423 sfd->source_addr = *addr;
424 sfd->next = *sfds;
425 *sfds = sfd;
426
427 return sfd;
428 }
429
430 void check_servers(struct daemon *daemon, struct irec *interfaces)
431 {
432 char addrbuff[ADDRSTRLEN];
433 struct irec *iface;
434 struct server *new, *tmp, *ret = NULL;
435 int port = 0;
436
437 /* forward table rules reference servers, so have to blow them away */
438 forward_init(0);
439
440 daemon->last_server = NULL;
441
442 for (new = daemon->servers; new; new = tmp)
443 {
444 tmp = new->next;
445
446 if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)))
447 {
448 #ifdef HAVE_IPV6
449 if (new->addr.sa.sa_family == AF_INET)
450 {
451 inet_ntop(AF_INET, &new->addr.in.sin_addr, addrbuff, ADDRSTRLEN);
452 port = ntohs(new->addr.in.sin_port);
453 }
454 else if (new->addr.sa.sa_family == AF_INET6)
455 {
456 inet_ntop(AF_INET6, &new->addr.in6.sin6_addr, addrbuff, ADDRSTRLEN);
457 port = ntohs(new->addr.in6.sin6_port);
458 }
459 #else
460 strcpy(addrbuff, inet_ntoa(new->addr.in.sin_addr));
461 port = ntohs(new->addr.in.sin_port);
462 #endif
463 for (iface = interfaces; iface; iface = iface->next)
464 if (sockaddr_isequal(&new->addr, &iface->addr))
465 break;
466 if (iface)
467 {
468 syslog(LOG_WARNING, "ignoring nameserver %s - local interface", addrbuff);
469 free(new);
470 continue;
471 }
472
473 /* Do we need a socket set? */
474 if (!new->sfd && !(new->sfd = allocate_sfd(&new->source_addr, &daemon->sfds)))
475 {
476 syslog(LOG_WARNING,
477 "ignoring nameserver %s - cannot make/bind socket: %m", addrbuff);
478 free(new);
479 continue;
480 }
481 }
482
483 /* reverse order - gets it right. */
484 new->next = ret;
485 ret = new;
486
487 if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS))
488 {
489 char *s1, *s2;
490 if (new->flags & SERV_HAS_DOMAIN)
491 s1 = "domain", s2 = new->domain;
492 else
493 s1 = "unqualified", s2 = "domains";
494
495 if (new->flags & SERV_NO_ADDR)
496 syslog(LOG_INFO, "using local addresses only for %s %s", s1, s2);
497 else if (!(new->flags & SERV_LITERAL_ADDRESS))
498 syslog(LOG_INFO, "using nameserver %s#%d for %s %s", addrbuff, port, s1, s2);
499 }
500 else
501 syslog(LOG_INFO, "using nameserver %s#%d", addrbuff, port);
502 }
503
504 daemon->servers = ret;
505 }
506
507 void reload_servers(char *fname, struct daemon *daemon)
508 {
509 FILE *f;
510 char *line;
511 struct server *old_servers = NULL;
512 struct server *new_servers = NULL;
513 struct server *serv = daemon->servers;
514
515 /* move old servers to free list - we can reuse the memory
516 and not risk malloc if there are the same or fewer new servers.
517 Servers which were specced on the command line go to the new list. */
518 while (serv)
519 {
520 struct server *tmp = serv->next;
521 if (serv->flags & SERV_FROM_RESOLV)
522 {
523 serv->next = old_servers;
524 old_servers = serv;
525 }
526 else
527 {
528 serv->next = new_servers;
529 new_servers = serv;
530 }
531 serv = tmp;
532 }
533
534 /* buff happens to be NAXDNAME long... */
535 f = fopen(fname, "r");
536 if (!f)
537 {
538 syslog(LOG_ERR, "failed to read %s: %m", fname);
539 }
540 else
541 {
542 syslog(LOG_INFO, "reading %s", fname);
543 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
544 {
545 union mysockaddr addr, source_addr;
546 char *token = strtok(line, " \t\n\r");
547 struct server *serv;
548
549 if (!token || strcmp(token, "nameserver") != 0)
550 continue;
551 if (!(token = strtok(NULL, " \t\n\r")))
552 continue;
553
554 #ifdef HAVE_IPV6
555 if (inet_pton(AF_INET, token, &addr.in.sin_addr))
556 #else
557 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
558 #endif
559 {
560 #ifdef HAVE_SOCKADDR_SA_LEN
561 source_addr.in.sin_len = addr.in.sin_len = sizeof(struct sockaddr_in);
562 #endif
563 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
564 addr.in.sin_port = htons(NAMESERVER_PORT);
565 source_addr.in.sin_addr.s_addr = INADDR_ANY;
566 source_addr.in.sin_port = htons(daemon->query_port);
567 }
568 #ifdef HAVE_IPV6
569 else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr))
570 {
571 #ifdef HAVE_SOCKADDR_SA_LEN
572 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(struct sockaddr_in6);
573 #endif
574 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
575 addr.in6.sin6_port = htons(NAMESERVER_PORT);
576 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = htonl(0);
577 source_addr.in6.sin6_addr = in6addr_any;
578 source_addr.in6.sin6_port = htons(daemon->query_port);
579 }
580 #endif /* IPV6 */
581 else
582 continue;
583
584 if (old_servers)
585 {
586 serv = old_servers;
587 old_servers = old_servers->next;
588 }
589 else if (!(serv = malloc(sizeof (struct server))))
590 continue;
591
592 /* this list is reverse ordered:
593 it gets reversed again in check_servers */
594 serv->next = new_servers;
595 new_servers = serv;
596 serv->addr = addr;
597 serv->source_addr = source_addr;
598 serv->domain = NULL;
599 serv->sfd = NULL;
600 serv->flags = SERV_FROM_RESOLV;
601 }
602
603 fclose(f);
604 }
605
606 /* Free any memory not used. */
607 while(old_servers)
608 {
609 struct server *tmp = old_servers->next;
610 free(old_servers);
611 old_servers = tmp;
612 }
613
614 daemon->servers = new_servers;
615 }
616
617
618
619
620
621
622