]> git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/network.c
import of dnsmasq-2.14.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(tcpfd, F_GETFL, 0)) == -1 ||
260 fcntl(tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
261 #ifdef IPV6_RECVPKTINFO
262 setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1 ||
263 #else
264 setsockopt(fd, IPV6_LEVEL, IPV6_PKTINFO, &opt, sizeof(opt)) == -1 ||
265 #endif
266 bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
267 listen(tcpfd, 5) == -1 ||
268 bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
269 {
270 save = errno;
271 close(fd);
272 close(tcpfd);
273 errno = save;
274 return 0;
275 }
276
277 l = safe_malloc(sizeof(struct listener));
278 l->fd = fd;
279 l->tcpfd = tcpfd;
280 l->family = AF_INET6;
281 l->next = NULL;
282 *link = l;
283
284 return 1;
285 }
286 #endif
287
288 struct listener *create_wildcard_listeners(int port)
289 {
290 #if !(defined(IP_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR)))
291 return NULL;
292 #else
293 union mysockaddr addr;
294 int opt = 1;
295 struct listener *l, *l6 = NULL;
296 int flags;
297 int tcpfd, fd;
298
299 addr.in.sin_family = AF_INET;
300 addr.in.sin_addr.s_addr = INADDR_ANY;
301 addr.in.sin_port = htons(port);
302 #ifdef HAVE_SOCKADDR_SA_LEN
303 addr.in.sin_len = sizeof(struct sockaddr_in);
304 #endif
305
306 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
307 return NULL;
308
309 if ((tcpfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
310 {
311 close (fd);
312 return NULL;
313 }
314
315 if (setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
316 bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
317 listen(tcpfd, 5) == -1 ||
318 (flags = fcntl(tcpfd, F_GETFL, 0)) == -1 ||
319 fcntl(tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
320 #ifdef HAVE_IPV6
321 !create_ipv6_listener(&l6, port) ||
322 #endif
323 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
324 #if defined(IP_PKTINFO)
325 setsockopt(fd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
326 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
327 setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
328 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 ||
329 #endif
330 bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
331 {
332 close(fd);
333 close(tcpfd);
334 return NULL;
335 }
336
337 l = safe_malloc(sizeof(struct listener));
338 l->family = AF_INET;
339 l->fd = fd;
340 l->tcpfd = tcpfd;
341 l->next = l6;
342
343 return l;
344
345 #endif
346 }
347
348 struct listener *create_bound_listeners(struct irec *interfaces, int port)
349 {
350
351 struct listener *listeners = NULL;
352 struct irec *iface;
353 int flags = port, opt = 1;
354
355 /* Create bound listeners only for IPv4, IPv6 always binds the wildcard */
356
357 #ifdef HAVE_IPV6
358 if (!create_ipv6_listener(&listeners, port))
359 die("failed to to create listening socket: %s", NULL);
360 #endif
361
362 for (iface = interfaces ;iface; iface = iface->next)
363 if (iface->addr.sa.sa_family == AF_INET)
364 {
365 struct listener *new = safe_malloc(sizeof(struct listener));
366 new->family = iface->addr.sa.sa_family;
367 new->next = listeners;
368 listeners = new;
369 if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 ||
370 (new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 ||
371 setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
372 setsockopt(new->tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
373 /* See Stevens 16.6 */
374 (flags = fcntl(new->tcpfd, F_GETFL, 0)) == -1 ||
375 fcntl(new->tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
376 bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
377 bind(new->fd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
378 listen(new->tcpfd, 5) == -1)
379 die("failed to to create listening socket: %s", NULL);
380 }
381
382 return listeners;
383 }
384
385 struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds)
386 {
387 struct serverfd *sfd;
388
389 /* may have a suitable one already */
390 for (sfd = *sfds; sfd; sfd = sfd->next )
391 if (sockaddr_isequal(&sfd->source_addr, addr))
392 return sfd;
393
394 /* need to make a new one. */
395 errno = ENOMEM; /* in case malloc fails. */
396 if (!(sfd = malloc(sizeof(struct serverfd))))
397 return NULL;
398
399 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
400 {
401 free(sfd);
402 return NULL;
403 }
404
405 if (bind(sfd->fd, (struct sockaddr *)addr, sa_len(addr)) == -1)
406 {
407 int errsave = errno; /* save error from bind. */
408 close(sfd->fd);
409 free(sfd);
410 errno = errsave;
411 return NULL;
412 }
413
414 sfd->source_addr = *addr;
415 sfd->next = *sfds;
416 *sfds = sfd;
417
418 return sfd;
419 }
420
421 void check_servers(struct daemon *daemon, struct irec *interfaces)
422 {
423 char addrbuff[ADDRSTRLEN];
424 struct irec *iface;
425 struct server *new, *tmp, *ret = NULL;
426 int port = 0;
427
428 /* forward table rules reference servers, so have to blow them away */
429 forward_init(0);
430
431 daemon->last_server = NULL;
432
433 for (new = daemon->servers; new; new = tmp)
434 {
435 tmp = new->next;
436
437 if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)))
438 {
439 #ifdef HAVE_IPV6
440 if (new->addr.sa.sa_family == AF_INET)
441 {
442 inet_ntop(AF_INET, &new->addr.in.sin_addr, addrbuff, ADDRSTRLEN);
443 port = ntohs(new->addr.in.sin_port);
444 }
445 else if (new->addr.sa.sa_family == AF_INET6)
446 {
447 inet_ntop(AF_INET6, &new->addr.in6.sin6_addr, addrbuff, ADDRSTRLEN);
448 port = ntohs(new->addr.in6.sin6_port);
449 }
450 #else
451 strcpy(addrbuff, inet_ntoa(new->addr.in.sin_addr));
452 port = ntohs(new->addr.in.sin_port);
453 #endif
454 for (iface = interfaces; iface; iface = iface->next)
455 if (sockaddr_isequal(&new->addr, &iface->addr))
456 break;
457 if (iface)
458 {
459 syslog(LOG_WARNING, "ignoring nameserver %s - local interface", addrbuff);
460 free(new);
461 continue;
462 }
463
464 /* Do we need a socket set? */
465 if (!new->sfd && !(new->sfd = allocate_sfd(&new->source_addr, &daemon->sfds)))
466 {
467 syslog(LOG_WARNING,
468 "ignoring nameserver %s - cannot make/bind socket: %m", addrbuff);
469 free(new);
470 continue;
471 }
472 }
473
474 /* reverse order - gets it right. */
475 new->next = ret;
476 ret = new;
477
478 if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS))
479 {
480 char *s1, *s2;
481 if (new->flags & SERV_HAS_DOMAIN)
482 s1 = "domain", s2 = new->domain;
483 else
484 s1 = "unqualified", s2 = "domains";
485
486 if (new->flags & SERV_NO_ADDR)
487 syslog(LOG_INFO, "using local addresses only for %s %s", s1, s2);
488 else if (!(new->flags & SERV_LITERAL_ADDRESS))
489 syslog(LOG_INFO, "using nameserver %s#%d for %s %s", addrbuff, port, s1, s2);
490 }
491 else
492 syslog(LOG_INFO, "using nameserver %s#%d", addrbuff, port);
493 }
494
495 daemon->servers = ret;
496 }
497
498 void reload_servers(char *fname, struct daemon *daemon)
499 {
500 FILE *f;
501 char *line;
502 struct server *old_servers = NULL;
503 struct server *new_servers = NULL;
504 struct server *serv = daemon->servers;
505
506 /* move old servers to free list - we can reuse the memory
507 and not risk malloc if there are the same or fewer new servers.
508 Servers which were specced on the command line go to the new list. */
509 while (serv)
510 {
511 struct server *tmp = serv->next;
512 if (serv->flags & SERV_FROM_RESOLV)
513 {
514 serv->next = old_servers;
515 old_servers = serv;
516 }
517 else
518 {
519 serv->next = new_servers;
520 new_servers = serv;
521 }
522 serv = tmp;
523 }
524
525 /* buff happens to be NAXDNAME long... */
526 f = fopen(fname, "r");
527 if (!f)
528 {
529 syslog(LOG_ERR, "failed to read %s: %m", fname);
530 }
531 else
532 {
533 syslog(LOG_INFO, "reading %s", fname);
534 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
535 {
536 union mysockaddr addr, source_addr;
537 char *token = strtok(line, " \t\n\r");
538 struct server *serv;
539
540 if (!token || strcmp(token, "nameserver") != 0)
541 continue;
542 if (!(token = strtok(NULL, " \t\n\r")))
543 continue;
544
545 #ifdef HAVE_IPV6
546 if (inet_pton(AF_INET, token, &addr.in.sin_addr))
547 #else
548 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
549 #endif
550 {
551 #ifdef HAVE_SOCKADDR_SA_LEN
552 source_addr.in.sin_len = addr.in.sin_len = sizeof(struct sockaddr_in);
553 #endif
554 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
555 addr.in.sin_port = htons(NAMESERVER_PORT);
556 source_addr.in.sin_addr.s_addr = INADDR_ANY;
557 source_addr.in.sin_port = htons(daemon->query_port);
558 }
559 #ifdef HAVE_IPV6
560 else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr))
561 {
562 #ifdef HAVE_SOCKADDR_SA_LEN
563 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(struct sockaddr_in6);
564 #endif
565 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
566 addr.in6.sin6_port = htons(NAMESERVER_PORT);
567 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = htonl(0);
568 source_addr.in6.sin6_addr = in6addr_any;
569 source_addr.in6.sin6_port = htons(daemon->query_port);
570 }
571 #endif /* IPV6 */
572 else
573 continue;
574
575 if (old_servers)
576 {
577 serv = old_servers;
578 old_servers = old_servers->next;
579 }
580 else if (!(serv = malloc(sizeof (struct server))))
581 continue;
582
583 /* this list is reverse ordered:
584 it gets reversed again in check_servers */
585 serv->next = new_servers;
586 new_servers = serv;
587 serv->addr = addr;
588 serv->source_addr = source_addr;
589 serv->domain = NULL;
590 serv->sfd = NULL;
591 serv->flags = SERV_FROM_RESOLV;
592 }
593
594 fclose(f);
595 }
596
597 /* Free any memory not used. */
598 while(old_servers)
599 {
600 struct server *tmp = old_servers->next;
601 free(old_servers);
602 old_servers = tmp;
603 }
604
605 daemon->servers = new_servers;
606 }
607
608
609
610
611
612
613