]> git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/network.c
import of dnsmasq-2.40.tar.gz
[people/ms/dnsmasq.git] / src / network.c
1 /* dnsmasq is Copyright (c) 2000 - 2006 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 #include "dnsmasq.h"
14
15 int iface_check(int family, struct all_addr *addr,
16 struct ifreq *ifr, int *indexp)
17 {
18 struct iname *tmp;
19 int ret = 1;
20
21 /* Note: have to check all and not bail out early, so that we set the
22 "used" flags. */
23
24 if (indexp)
25 {
26 #if defined(__FreeBSD__) || defined(__DragonFly__)
27 /* One form of bridging on FreeBSD has the property that packets
28 can be recieved on bridge interfaces which do not have an IP address.
29 We allow these to be treated as aliases of another interface which does have
30 an IP address with --dhcp-bridge=interface,alias,alias */
31 struct dhcp_bridge *bridge, *alias;
32 for (bridge = daemon->bridges; bridge; bridge = bridge->next)
33 {
34 for (alias = bridge->alias; alias; alias = alias->next)
35 if (strncmp(ifr->ifr_name, alias->iface, IF_NAMESIZE) == 0)
36 {
37 int newindex;
38
39 if (!(newindex = if_nametoindex(bridge->iface)))
40 {
41 my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), ifr->ifr_name);
42 return 0;
43 }
44 else
45 {
46 *indexp = newindex;
47 strncpy(ifr->ifr_name, bridge->iface, IF_NAMESIZE);
48 break;
49 }
50 }
51 if (alias)
52 break;
53 }
54 #endif
55 }
56
57 if (daemon->if_names || (addr && daemon->if_addrs))
58 {
59 ret = 0;
60
61 for (tmp = daemon->if_names; tmp; tmp = tmp->next)
62 if (tmp->name && (strcmp(tmp->name, ifr->ifr_name) == 0))
63 ret = tmp->used = 1;
64
65 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
66 if (addr && tmp->addr.sa.sa_family == family)
67 {
68 if (family == AF_INET &&
69 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
70 ret = tmp->used = 1;
71 #ifdef HAVE_IPV6
72 else if (family == AF_INET6 &&
73 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
74 &addr->addr.addr6))
75 ret = tmp->used = 1;
76 #endif
77 }
78 }
79
80 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
81 if (tmp->name && (strcmp(tmp->name, ifr->ifr_name) == 0))
82 ret = 0;
83
84 return ret;
85 }
86
87 static int iface_allowed(struct irec **irecp, int if_index,
88 union mysockaddr *addr, struct in_addr netmask)
89 {
90 struct irec *iface;
91 int fd;
92 struct ifreq ifr;
93 int dhcp_ok = 1;
94 struct iname *tmp;
95
96 /* check whether the interface IP has been added already
97 we call this routine multiple times. */
98 for (iface = *irecp; iface; iface = iface->next)
99 if (sockaddr_isequal(&iface->addr, addr))
100 return 1;
101
102 #ifdef HAVE_LINUX_NETWORK
103 ifr.ifr_ifindex = if_index;
104 #endif
105
106 if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1 ||
107 #ifdef HAVE_LINUX_NETWORK
108 ioctl(fd, SIOCGIFNAME, &ifr) == -1 ||
109 #else
110 !if_indextoname(if_index, ifr.ifr_name) ||
111 #endif
112 ioctl(fd, SIOCGIFFLAGS, &ifr) == -1)
113 {
114 if (fd != -1)
115 {
116 int errsave = errno;
117 close(fd);
118 errno = errsave;
119 }
120 return 0;
121 }
122
123 close(fd);
124
125 /* If we are restricting the set of interfaces to use, make
126 sure that loopback interfaces are in that set. */
127 if (daemon->if_names && (ifr.ifr_flags & IFF_LOOPBACK))
128 {
129 struct iname *lo;
130 for (lo = daemon->if_names; lo; lo = lo->next)
131 if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
132 {
133 lo->isloop = 1;
134 break;
135 }
136
137 if (!lo &&
138 (lo = whine_malloc(sizeof(struct iname))) &&
139 (lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
140 {
141 strcpy(lo->name, ifr.ifr_name);
142 lo->isloop = lo->used = 1;
143 lo->next = daemon->if_names;
144 daemon->if_names = lo;
145 }
146 }
147
148 if (addr->sa.sa_family == AF_INET &&
149 !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, &ifr, NULL))
150 return 1;
151
152 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
153 if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
154 dhcp_ok = 0;
155
156 #ifdef HAVE_IPV6
157 if (addr->sa.sa_family == AF_INET6 &&
158 !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, &ifr, NULL))
159 return 1;
160 #endif
161
162 /* add to list */
163 if ((iface = whine_malloc(sizeof(struct irec))))
164 {
165 iface->addr = *addr;
166 iface->netmask = netmask;
167 iface->dhcp_ok = dhcp_ok;
168 iface->next = *irecp;
169 *irecp = iface;
170 return 1;
171 }
172
173 errno = ENOMEM;
174 return 0;
175 }
176
177 #ifdef HAVE_IPV6
178 static int iface_allowed_v6(struct in6_addr *local,
179 int scope, int if_index, void *vparam)
180 {
181 union mysockaddr addr;
182 struct in_addr netmask; /* dummy */
183
184 netmask.s_addr = 0;
185
186 memset(&addr, 0, sizeof(addr));
187 #ifdef HAVE_SOCKADDR_SA_LEN
188 addr.in6.sin6_len = sizeof(addr.in6);
189 #endif
190 addr.in6.sin6_family = AF_INET6;
191 addr.in6.sin6_addr = *local;
192 addr.in6.sin6_port = htons(daemon->port);
193 addr.in6.sin6_scope_id = scope;
194
195 return iface_allowed((struct irec **)vparam, if_index, &addr, netmask);
196 }
197 #endif
198
199 static int iface_allowed_v4(struct in_addr local, int if_index,
200 struct in_addr netmask, struct in_addr broadcast, void *vparam)
201 {
202 union mysockaddr addr;
203
204 memset(&addr, 0, sizeof(addr));
205 #ifdef HAVE_SOCKADDR_SA_LEN
206 addr.in.sin_len = sizeof(addr.in);
207 #endif
208 addr.in.sin_family = AF_INET;
209 addr.in.sin_addr = broadcast; /* warning */
210 addr.in.sin_addr = local;
211 addr.in.sin_port = htons(daemon->port);
212
213 return iface_allowed((struct irec **)vparam, if_index, &addr, netmask);
214 }
215
216
217 int enumerate_interfaces(void)
218 {
219 #ifdef HAVE_IPV6
220 return iface_enumerate(&daemon->interfaces, iface_allowed_v4, iface_allowed_v6);
221 #else
222 return iface_enumerate(&daemon->interfaces, iface_allowed_v4, NULL);
223 #endif
224 }
225
226 /* set NONBLOCK bit on fd: See Stevens 16.6 */
227 int fix_fd(int fd)
228 {
229 int flags;
230
231 if ((flags = fcntl(fd, F_GETFL)) == -1 ||
232 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
233 return 0;
234
235 return 1;
236 }
237
238 #if defined(HAVE_IPV6)
239 static int create_ipv6_listener(struct listener **link, int port)
240 {
241 union mysockaddr addr;
242 int tcpfd, fd;
243 struct listener *l;
244 int opt = 1;
245
246 memset(&addr, 0, sizeof(addr));
247 addr.in6.sin6_family = AF_INET6;
248 addr.in6.sin6_addr = in6addr_any;
249 addr.in6.sin6_port = htons(port);
250 #ifdef HAVE_SOCKADDR_SA_LEN
251 addr.in6.sin6_len = sizeof(addr.in6);
252 #endif
253
254 /* No error of the kernel doesn't support IPv6 */
255 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
256 return (errno == EPROTONOSUPPORT ||
257 errno == EAFNOSUPPORT ||
258 errno == EINVAL);
259
260 if ((tcpfd = socket(AF_INET6, SOCK_STREAM, 0)) == -1)
261 return 0;
262
263 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
264 setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
265 setsockopt(fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
266 setsockopt(tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
267 !fix_fd(fd) ||
268 !fix_fd(tcpfd) ||
269 #ifdef IPV6_RECVPKTINFO
270 setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1 ||
271 #else
272 setsockopt(fd, IPV6_LEVEL, IPV6_PKTINFO, &opt, sizeof(opt)) == -1 ||
273 #endif
274 bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
275 listen(tcpfd, 5) == -1 ||
276 bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
277 return 0;
278
279 l = safe_malloc(sizeof(struct listener));
280 l->fd = fd;
281 l->tcpfd = tcpfd;
282 l->tftpfd = -1;
283 l->family = AF_INET6;
284 l->next = NULL;
285 *link = l;
286
287 return 1;
288 }
289 #endif
290
291 struct listener *create_wildcard_listeners(void)
292 {
293 union mysockaddr addr;
294 int opt = 1;
295 struct listener *l, *l6 = NULL;
296 int tcpfd, fd, tftpfd = -1;
297
298 memset(&addr, 0, sizeof(addr));
299 addr.in.sin_family = AF_INET;
300 addr.in.sin_addr.s_addr = INADDR_ANY;
301 addr.in.sin_port = htons(daemon->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 (tcpfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
308 return NULL;
309
310 if (setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
311 bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
312 listen(tcpfd, 5) == -1 ||
313 !fix_fd(tcpfd) ||
314 #ifdef HAVE_IPV6
315 !create_ipv6_listener(&l6, daemon->port) ||
316 #endif
317 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
318 !fix_fd(fd) ||
319 #if defined(HAVE_LINUX_NETWORK)
320 setsockopt(fd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
321 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
322 setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
323 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 ||
324 #endif
325 bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
326 return NULL;
327
328 #ifdef HAVE_TFTP
329 if (daemon->options & OPT_TFTP)
330 {
331 addr.in.sin_port = htons(TFTP_PORT);
332 if ((tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
333 return NULL;
334
335 if (!fix_fd(tftpfd) ||
336 #if defined(HAVE_LINUX_NETWORK)
337 setsockopt(tftpfd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
338 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
339 setsockopt(tftpfd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
340 setsockopt(tftpfd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 ||
341 #endif
342 bind(tftpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
343 return NULL;
344 }
345 #endif
346
347 l = safe_malloc(sizeof(struct listener));
348 l->family = AF_INET;
349 l->fd = fd;
350 l->tcpfd = tcpfd;
351 l->tftpfd = tftpfd;
352 l->next = l6;
353
354 return l;
355 }
356
357 struct listener *create_bound_listeners(void)
358 {
359 struct listener *listeners = NULL;
360 struct irec *iface;
361 int opt = 1;
362
363 for (iface = daemon->interfaces; iface; iface = iface->next)
364 {
365 struct listener *new = safe_malloc(sizeof(struct listener));
366 new->family = iface->addr.sa.sa_family;
367 new->iface = iface;
368 new->next = listeners;
369 new->tftpfd = -1;
370
371 if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 ||
372 (new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 ||
373 setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
374 setsockopt(new->tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
375 !fix_fd(new->tcpfd) ||
376 !fix_fd(new->fd))
377 die(_("failed to create listening socket: %s"), NULL, EC_BADNET);
378
379 #ifdef HAVE_IPV6
380 if (iface->addr.sa.sa_family == AF_INET6)
381 {
382 if (setsockopt(new->fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
383 setsockopt(new->tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
384 die(_("failed to set IPV6 options on listening socket: %s"), NULL, EC_BADNET);
385 }
386 #endif
387
388 if (bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
389 bind(new->fd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
390 {
391 #ifdef HAVE_IPV6
392 if (iface->addr.sa.sa_family == AF_INET6 && errno == ENODEV)
393 {
394 close(new->tcpfd);
395 close(new->fd);
396 free(new);
397 }
398 else
399 #endif
400 {
401 prettyprint_addr(&iface->addr, daemon->namebuff);
402 die(_("failed to bind listening socket for %s: %s"),
403 daemon->namebuff, EC_BADNET);
404 }
405 }
406 else
407 {
408 listeners = new;
409 if (listen(new->tcpfd, 5) == -1)
410 die(_("failed to listen on socket: %s"), NULL, EC_BADNET);
411 }
412
413 if ((daemon->options & OPT_TFTP) && iface->addr.sa.sa_family == AF_INET && iface->dhcp_ok)
414 {
415 short save = iface->addr.in.sin_port;
416 iface->addr.in.sin_port = htons(TFTP_PORT);
417 if ((new->tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ||
418 setsockopt(new->tftpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
419 !fix_fd(new->tftpfd) ||
420 bind(new->tftpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
421 die(_("failed to create TFTP socket: %s"), NULL, EC_BADNET);
422 iface->addr.in.sin_port = save;
423 }
424 }
425
426 return listeners;
427 }
428
429 struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds)
430 {
431 struct serverfd *sfd;
432
433 /* may have a suitable one already */
434 for (sfd = *sfds; sfd; sfd = sfd->next )
435 if (sockaddr_isequal(&sfd->source_addr, addr))
436 return sfd;
437
438 /* need to make a new one. */
439 errno = ENOMEM; /* in case malloc fails. */
440 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
441 return NULL;
442
443 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
444 {
445 free(sfd);
446 return NULL;
447 }
448
449 if (bind(sfd->fd, (struct sockaddr *)addr, sa_len(addr)) == -1 ||
450 !fix_fd(sfd->fd))
451 {
452 int errsave = errno; /* save error from bind. */
453 close(sfd->fd);
454 free(sfd);
455 errno = errsave;
456 return NULL;
457 }
458
459 sfd->source_addr = *addr;
460 sfd->next = *sfds;
461 *sfds = sfd;
462
463 return sfd;
464 }
465
466 void check_servers(void)
467 {
468 struct irec *iface;
469 struct server *new, *tmp, *ret = NULL;
470 int port = 0;
471
472 for (new = daemon->servers; new; new = tmp)
473 {
474 tmp = new->next;
475
476 if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)))
477 {
478 port = prettyprint_addr(&new->addr, daemon->namebuff);
479
480 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
481 if (new->addr.sa.sa_family == AF_INET &&
482 new->addr.in.sin_addr.s_addr == 0)
483 {
484 free(new);
485 continue;
486 }
487
488 for (iface = daemon->interfaces; iface; iface = iface->next)
489 if (sockaddr_isequal(&new->addr, &iface->addr))
490 break;
491 if (iface)
492 {
493 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
494 free(new);
495 continue;
496 }
497
498 /* Do we need a socket set? */
499 if (!new->sfd && !(new->sfd = allocate_sfd(&new->source_addr, &daemon->sfds)))
500 {
501 my_syslog(LOG_WARNING,
502 _("ignoring nameserver %s - cannot make/bind socket: %s"),
503 daemon->namebuff, strerror(errno));
504 free(new);
505 continue;
506 }
507 }
508
509 /* reverse order - gets it right. */
510 new->next = ret;
511 ret = new;
512
513 if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS))
514 {
515 char *s1, *s2;
516 if (!(new->flags & SERV_HAS_DOMAIN))
517 s1 = _("unqualified"), s2 = _("names");
518 else if (strlen(new->domain) == 0)
519 s1 = _("default"), s2 = "";
520 else
521 s1 = _("domain"), s2 = new->domain;
522
523 if (new->flags & SERV_NO_ADDR)
524 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
525 else if (!(new->flags & SERV_LITERAL_ADDRESS))
526 my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
527 }
528 else
529 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
530 }
531
532 daemon->servers = ret;
533 }
534
535 /* Return zero if no servers found, in that case we keep polling.
536 This is a protection against an update-time/write race on resolv.conf */
537 int reload_servers(char *fname)
538 {
539 FILE *f;
540 char *line;
541 struct server *old_servers = NULL;
542 struct server *new_servers = NULL;
543 struct server *serv;
544 int gotone = 0;
545
546 /* buff happens to be MAXDNAME long... */
547 if (!(f = fopen(fname, "r")))
548 {
549 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
550 return 0;
551 }
552
553 /* move old servers to free list - we can reuse the memory
554 and not risk malloc if there are the same or fewer new servers.
555 Servers which were specced on the command line go to the new list. */
556 for (serv = daemon->servers; serv;)
557 {
558 struct server *tmp = serv->next;
559 if (serv->flags & SERV_FROM_RESOLV)
560 {
561 serv->next = old_servers;
562 old_servers = serv;
563 /* forward table rules reference servers, so have to blow them away */
564 server_gone(serv);
565 }
566 else
567 {
568 serv->next = new_servers;
569 new_servers = serv;
570 }
571 serv = tmp;
572 }
573
574 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
575 {
576 union mysockaddr addr, source_addr;
577 char *token = strtok(line, " \t\n\r");
578
579 if (!token)
580 continue;
581 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
582 continue;
583 if (!(token = strtok(NULL, " \t\n\r")))
584 continue;
585
586 memset(&addr, 0, sizeof(addr));
587 memset(&source_addr, 0, sizeof(source_addr));
588
589 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
590 {
591 #ifdef HAVE_SOCKADDR_SA_LEN
592 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
593 #endif
594 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
595 addr.in.sin_port = htons(NAMESERVER_PORT);
596 source_addr.in.sin_addr.s_addr = INADDR_ANY;
597 source_addr.in.sin_port = htons(daemon->query_port);
598 }
599 #ifdef HAVE_IPV6
600 else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
601 {
602 #ifdef HAVE_SOCKADDR_SA_LEN
603 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
604 #endif
605 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
606 addr.in6.sin6_port = htons(NAMESERVER_PORT);
607 source_addr.in6.sin6_addr = in6addr_any;
608 source_addr.in6.sin6_port = htons(daemon->query_port);
609 }
610 #endif /* IPV6 */
611 else
612 continue;
613
614 if (old_servers)
615 {
616 serv = old_servers;
617 old_servers = old_servers->next;
618 }
619 else if (!(serv = whine_malloc(sizeof (struct server))))
620 continue;
621
622 /* this list is reverse ordered:
623 it gets reversed again in check_servers */
624 serv->next = new_servers;
625 new_servers = serv;
626 serv->addr = addr;
627 serv->source_addr = source_addr;
628 serv->domain = NULL;
629 serv->sfd = NULL;
630 serv->flags = SERV_FROM_RESOLV;
631
632 gotone = 1;
633 }
634
635 /* Free any memory not used. */
636 while (old_servers)
637 {
638 struct server *tmp = old_servers->next;
639 free(old_servers);
640 old_servers = tmp;
641 }
642
643 daemon->servers = new_servers;
644 fclose(f);
645
646 return gotone;
647 }
648
649
650 /* Use an IPv4 listener socket for ioctling */
651 struct in_addr get_ifaddr(char *intr)
652 {
653 struct listener *l;
654 struct ifreq ifr;
655
656 for (l = daemon->listeners; l && l->family != AF_INET; l = l->next);
657
658 strncpy(ifr.ifr_name, intr, IF_NAMESIZE);
659 ifr.ifr_addr.sa_family = AF_INET;
660
661 if (!l || ioctl(l->fd, SIOCGIFADDR, &ifr) == -1)
662 ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = -1;
663
664 return ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
665 }
666
667
668