blob: 43b157311253d6a58b348815d5908f83d6c1499f [file] [log] [blame]
San Mehatffd68722010-01-20 09:56:15 -08001/* dnsmasq is Copyright (c) 2000-2009 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, or
6 (at your option) version 3 dated 29 June, 2007.
7
8 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.
12
13 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/>.
15*/
16
17#include "dnsmasq.h"
18
19#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
37#else
38
39int indextoname(int fd, int index, char *name)
40{
41 if (index == 0 || !if_indextoname(index, name))
42 return 0;
43
44 return 1;
45}
46
47#endif
48
49int iface_check(int family, struct all_addr *addr, char *name, int *indexp)
50{
51 struct iname *tmp;
52 int ret = 1;
53
54 /* Note: have to check all and not bail out early, so that we set the
55 "used" flags. */
56
57 if (indexp)
58 {
59 /* One form of bridging on BSD has the property that packets
60 can be recieved on bridge interfaces which do not have an IP address.
61 We allow these to be treated as aliases of another interface which does have
62 an IP address with --dhcp-bridge=interface,alias,alias */
63 struct dhcp_bridge *bridge, *alias;
64 for (bridge = daemon->bridges; bridge; bridge = bridge->next)
65 {
66 for (alias = bridge->alias; alias; alias = alias->next)
67 if (strncmp(name, alias->iface, IF_NAMESIZE) == 0)
68 {
69 int newindex;
70
71 if (!(newindex = if_nametoindex(bridge->iface)))
72 {
73 my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), name);
74 return 0;
75 }
76 else
77 {
78 *indexp = newindex;
79 strncpy(name, bridge->iface, IF_NAMESIZE);
80 break;
81 }
82 }
83 if (alias)
84 break;
85 }
86 }
Robert Greenwalt41cd7ed2012-12-11 12:42:32 -080087
San Mehatffd68722010-01-20 09:56:15 -080088 if (daemon->if_names || (addr && daemon->if_addrs))
89 {
90 ret = 0;
91
92 for (tmp = daemon->if_names; tmp; tmp = tmp->next)
93 if (tmp->name && (strcmp(tmp->name, name) == 0))
94 ret = tmp->used = 1;
95
96 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
97 if (addr && tmp->addr.sa.sa_family == family)
98 {
99 if (family == AF_INET &&
100 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
101 ret = tmp->used = 1;
102#ifdef HAVE_IPV6
103 else if (family == AF_INET6 &&
104 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
105 &addr->addr.addr6))
106 ret = tmp->used = 1;
107#endif
108 }
109 }
110
111 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
112 if (tmp->name && (strcmp(tmp->name, name) == 0))
113 ret = 0;
114
115 return ret;
116}
117
118static int iface_allowed(struct irec **irecp, int if_index,
119 union mysockaddr *addr, struct in_addr netmask)
120{
121 struct irec *iface;
122 int fd, mtu = 0, loopback;
123 struct ifreq ifr;
124 int dhcp_ok = 1;
125 struct iname *tmp;
126
127 /* check whether the interface IP has been added already
128 we call this routine multiple times. */
129 for (iface = *irecp; iface; iface = iface->next)
130 if (sockaddr_isequal(&iface->addr, addr))
131 return 1;
132
133 if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1 ||
134 !indextoname(fd, if_index, ifr.ifr_name) ||
135 ioctl(fd, SIOCGIFFLAGS, &ifr) == -1)
136 {
137 if (fd != -1)
138 {
139 int errsave = errno;
140 close(fd);
141 errno = errsave;
142 }
143 return 0;
144 }
145
146 loopback = ifr.ifr_flags & IFF_LOOPBACK;
147
148 if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
149 mtu = ifr.ifr_mtu;
150
151 close(fd);
152
153 /* If we are restricting the set of interfaces to use, make
154 sure that loopback interfaces are in that set. */
155 if (daemon->if_names && loopback)
156 {
157 struct iname *lo;
158 for (lo = daemon->if_names; lo; lo = lo->next)
159 if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
160 {
161 lo->isloop = 1;
162 break;
163 }
164
165 if (!lo &&
166 (lo = whine_malloc(sizeof(struct iname))) &&
167 (lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
168 {
169 strcpy(lo->name, ifr.ifr_name);
170 lo->isloop = lo->used = 1;
171 lo->next = daemon->if_names;
172 daemon->if_names = lo;
173 }
174 }
175
176 if (addr->sa.sa_family == AF_INET &&
177 !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, NULL))
178 return 1;
179
180 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
181 if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
182 dhcp_ok = 0;
183
184#ifdef HAVE_IPV6
185 if (addr->sa.sa_family == AF_INET6 &&
186 !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, NULL))
187 return 1;
188#endif
189
190 /* add to list */
191 if ((iface = whine_malloc(sizeof(struct irec))))
192 {
193 iface->addr = *addr;
194 iface->netmask = netmask;
195 iface->dhcp_ok = dhcp_ok;
196 iface->mtu = mtu;
197 iface->next = *irecp;
198 *irecp = iface;
199 return 1;
200 }
201
202 errno = ENOMEM;
203 return 0;
204}
205
206#ifdef HAVE_IPV6
207static int iface_allowed_v6(struct in6_addr *local,
208 int scope, int if_index, void *vparam)
209{
210 union mysockaddr addr;
211 struct in_addr netmask; /* dummy */
212
213 netmask.s_addr = 0;
214
215 memset(&addr, 0, sizeof(addr));
216#ifdef HAVE_SOCKADDR_SA_LEN
217 addr.in6.sin6_len = sizeof(addr.in6);
218#endif
219 addr.in6.sin6_family = AF_INET6;
220 addr.in6.sin6_addr = *local;
221 addr.in6.sin6_port = htons(daemon->port);
222 addr.in6.sin6_scope_id = scope;
223
224 return iface_allowed((struct irec **)vparam, if_index, &addr, netmask);
225}
226#endif
227
228static int iface_allowed_v4(struct in_addr local, int if_index,
229 struct in_addr netmask, struct in_addr broadcast, void *vparam)
230{
231 union mysockaddr addr;
232
233 memset(&addr, 0, sizeof(addr));
234#ifdef HAVE_SOCKADDR_SA_LEN
235 addr.in.sin_len = sizeof(addr.in);
236#endif
237 addr.in.sin_family = AF_INET;
238 addr.in.sin_addr = broadcast; /* warning */
239 addr.in.sin_addr = local;
240 addr.in.sin_port = htons(daemon->port);
241
242 return iface_allowed((struct irec **)vparam, if_index, &addr, netmask);
243}
244
245int enumerate_interfaces(void)
246{
247#ifdef HAVE_IPV6
248 return iface_enumerate(&daemon->interfaces, iface_allowed_v4, iface_allowed_v6);
249#else
250 return iface_enumerate(&daemon->interfaces, iface_allowed_v4, NULL);
251#endif
252}
253
254/* set NONBLOCK bit on fd: See Stevens 16.6 */
255int fix_fd(int fd)
256{
257 int flags;
258
259 if ((flags = fcntl(fd, F_GETFL)) == -1 ||
260 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
261 return 0;
262
263 return 1;
264}
265
266#if defined(HAVE_IPV6)
267static int create_ipv6_listener(struct listener **link, int port)
268{
269 union mysockaddr addr;
270 int tcpfd, fd;
271 struct listener *l;
272 int opt = 1;
273
274 memset(&addr, 0, sizeof(addr));
275 addr.in6.sin6_family = AF_INET6;
276 addr.in6.sin6_addr = in6addr_any;
277 addr.in6.sin6_port = htons(port);
278#ifdef HAVE_SOCKADDR_SA_LEN
279 addr.in6.sin6_len = sizeof(addr.in6);
280#endif
281
282 /* No error of the kernel doesn't support IPv6 */
283 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
284 return (errno == EPROTONOSUPPORT ||
285 errno == EAFNOSUPPORT ||
286 errno == EINVAL);
287
288 if ((tcpfd = socket(AF_INET6, SOCK_STREAM, 0)) == -1)
289 return 0;
290
291 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
292 setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
293 setsockopt(fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
294 setsockopt(tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
295 !fix_fd(fd) ||
296 !fix_fd(tcpfd) ||
297#ifdef IPV6_RECVPKTINFO
298 setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1 ||
299#else
300 setsockopt(fd, IPV6_LEVEL, IPV6_PKTINFO, &opt, sizeof(opt)) == -1 ||
301#endif
302 bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
303 listen(tcpfd, 5) == -1 ||
304 bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
305 return 0;
306
307 l = safe_malloc(sizeof(struct listener));
308 l->fd = fd;
309 l->tcpfd = tcpfd;
310 l->tftpfd = -1;
311 l->family = AF_INET6;
312 l->next = NULL;
313 *link = l;
314
315 return 1;
316}
317#endif
318
319struct listener *create_wildcard_listeners(void)
320{
321 union mysockaddr addr;
322 int opt = 1;
323 struct listener *l, *l6 = NULL;
324 int tcpfd = -1, fd = -1, tftpfd = -1;
325
326 memset(&addr, 0, sizeof(addr));
327 addr.in.sin_family = AF_INET;
328 addr.in.sin_addr.s_addr = INADDR_ANY;
329 addr.in.sin_port = htons(daemon->port);
330#ifdef HAVE_SOCKADDR_SA_LEN
331 addr.in.sin_len = sizeof(struct sockaddr_in);
332#endif
333
334 if (daemon->port != 0)
335 {
336
337 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ||
338 (tcpfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
339 return NULL;
340
341 if (setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
342 bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
343 listen(tcpfd, 5) == -1 ||
344 !fix_fd(tcpfd) ||
345#ifdef HAVE_IPV6
346 !create_ipv6_listener(&l6, daemon->port) ||
347#endif
348 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
349 !fix_fd(fd) ||
350#if defined(HAVE_LINUX_NETWORK)
351 setsockopt(fd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
352#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
353 setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
354 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 ||
355#endif
356 bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
357 return NULL;
358 }
359
360#ifdef HAVE_TFTP
361 if (daemon->options & OPT_TFTP)
362 {
363 addr.in.sin_port = htons(TFTP_PORT);
364 if ((tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
365 return NULL;
366
367 if (!fix_fd(tftpfd) ||
368#if defined(HAVE_LINUX_NETWORK)
369 setsockopt(tftpfd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
370#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
371 setsockopt(tftpfd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
372 setsockopt(tftpfd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 ||
373#endif
374 bind(tftpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
375 return NULL;
376 }
377#endif
378
379 l = safe_malloc(sizeof(struct listener));
380 l->family = AF_INET;
381 l->fd = fd;
382 l->tcpfd = tcpfd;
383 l->tftpfd = tftpfd;
384 l->next = l6;
385
386 return l;
387}
388
Robert Greenwalt41cd7ed2012-12-11 12:42:32 -0800389#ifdef __ANDROID__
390/**
391 * for a single given irec (interface name and address) create
392 * a set of sockets listening. This is a copy of the code inside the loop
393 * of create_bound_listeners below and is added here to allow us
394 * to create just a single new listener dynamically when our interface
395 * list is changed.
396 *
397 * iface - input of the new interface details to listen on
398 * listeners - output. Creates a new struct listener and inserts at head of the list
399 *
400 * die's on errors, so don't pass bad data.
401 */
402void create_bound_listener(struct listener **listeners, struct irec *iface)
San Mehatffd68722010-01-20 09:56:15 -0800403{
San Mehatffd68722010-01-20 09:56:15 -0800404 int rc, opt = 1;
405#ifdef HAVE_IPV6
406 static int dad_count = 0;
407#endif
408
Robert Greenwalt41cd7ed2012-12-11 12:42:32 -0800409 struct listener *new = safe_malloc(sizeof(struct listener));
410 new->family = iface->addr.sa.sa_family;
411 new->iface = iface;
412 new->next = *listeners;
413 new->tftpfd = -1;
414 new->tcpfd = -1;
415 new->fd = -1;
416 *listeners = new;
417
418 if (daemon->port != 0)
419 {
420 if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 ||
421 (new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 ||
422 setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
423 setsockopt(new->tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
424 !fix_fd(new->tcpfd) ||
425 !fix_fd(new->fd))
426 die(_("failed to create listening socket: %s"), NULL, EC_BADNET);
427
428#ifdef HAVE_IPV6
429 if (iface->addr.sa.sa_family == AF_INET6)
430 {
431 if (setsockopt(new->fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
432 setsockopt(new->tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
433 die(_("failed to set IPV6 options on listening socket: %s"), NULL, EC_BADNET);\
434 }
435#endif
436
437 while(1)
438 {
439 if ((rc = bind(new->fd, &iface->addr.sa, sa_len(&iface->addr))) != -1)
440 break;
441
442#ifdef HAVE_IPV6
443 /* An interface may have an IPv6 address which is still undergoing DAD.
444 If so, the bind will fail until the DAD completes, so we try over 20 seconds
445 before failing. */
446 if (iface->addr.sa.sa_family == AF_INET6 && (errno == ENODEV || errno == EADDRNOTAVAIL) &&
447 dad_count++ < DAD_WAIT)
448 {
449 sleep(1);
450 continue;
451 }
452#endif
453 break;
454 }
455
456 if (rc == -1 || bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
457 {
458 prettyprint_addr(&iface->addr, daemon->namebuff);
459 die(_("failed to bind listening socket for %s: %s"), daemon->namebuff, EC_BADNET);
460 }
461
462 if (listen(new->tcpfd, 5) == -1)
463 die(_("failed to listen on socket: %s"), NULL, EC_BADNET);
464 }
465
466#ifdef HAVE_TFTP
467 if ((daemon->options & OPT_TFTP) && iface->addr.sa.sa_family == AF_INET && iface->dhcp_ok)
468 {
469 short save = iface->addr.in.sin_port;
470 iface->addr.in.sin_port = htons(TFTP_PORT);
471 if ((new->tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ||
472 setsockopt(new->tftpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
473 !fix_fd(new->tftpfd) ||
474 bind(new->tftpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
475 die(_("failed to create TFTP socket: %s"), NULL, EC_BADNET);
476 iface->addr.in.sin_port = save;
477 }
478#endif
479}
480
481/**
482 * Close the sockets listening on the given interface
483 *
484 * This new function is needed as we're dynamically changing the interfaces
485 * we listen on. Before they'd be opened once in create_bound_listeners and stay
486 * until we exited. Now, if an interface moves off the to-listen list we need to
487 * close out the listeners and keep trucking.
488 *
489 * interface - input of the interface details to listen on
490 */
491int close_bound_listener(struct irec *interface)
492{
493 /* find the listener */
494 struct listener **l, *listener;
495 for (l = &(daemon->listeners); *l; l = &((*l)->next)) {
496 struct irec *listener_iface = (*l)->iface;
497 if (listener_iface && interface) {
498 if (sockaddr_isequal(&listener_iface->addr, &interface->addr)) {
499 break;
500 }
501 } else {
502 if (interface == NULL && listener_iface == NULL) {
503 break;
504 }
505 }
506 }
507 listener = *l;
508 if (listener == NULL) return 0;
509
510 if (listener->tftpfd != -1)
511 {
512 close(listener->tftpfd);
513 listener->tftpfd = -1;
514 }
515 if (listener->tcpfd != -1)
516 {
517 close(listener->tcpfd);
518 listener->tcpfd = -1;
519 }
520 if (listener->fd != -1)
521 {
522 close(listener->fd);
523 listener->fd = -1;
524 }
525 *l = listener->next;
526 free(listener);
527 return -1;
528}
529#endif /* __ANDROID__ */
530
531struct listener *create_bound_listeners(void)
532{
533 struct listener *listeners = NULL;
534 struct irec *iface;
535#ifndef __ANDROID__
536 int rc, opt = 1;
537#ifdef HAVE_IPV6
538 static int dad_count = 0;
539#endif
540#endif
541
San Mehatffd68722010-01-20 09:56:15 -0800542 for (iface = daemon->interfaces; iface; iface = iface->next)
543 {
Robert Greenwalt41cd7ed2012-12-11 12:42:32 -0800544#ifdef __ANDROID__
545 create_bound_listener(&listeners, iface);
546#else
San Mehatffd68722010-01-20 09:56:15 -0800547 struct listener *new = safe_malloc(sizeof(struct listener));
548 new->family = iface->addr.sa.sa_family;
549 new->iface = iface;
550 new->next = listeners;
551 new->tftpfd = -1;
552 new->tcpfd = -1;
553 new->fd = -1;
554 listeners = new;
555
556 if (daemon->port != 0)
557 {
558 if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 ||
559 (new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 ||
560 setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
561 setsockopt(new->tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
562 !fix_fd(new->tcpfd) ||
563 !fix_fd(new->fd))
564 die(_("failed to create listening socket: %s"), NULL, EC_BADNET);
565
566#ifdef HAVE_IPV6
567 if (iface->addr.sa.sa_family == AF_INET6)
568 {
569 if (setsockopt(new->fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
570 setsockopt(new->tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
571 die(_("failed to set IPV6 options on listening socket: %s"), NULL, EC_BADNET);
572 }
573#endif
574
575 while(1)
576 {
577 if ((rc = bind(new->fd, &iface->addr.sa, sa_len(&iface->addr))) != -1)
578 break;
579
580#ifdef HAVE_IPV6
581 /* An interface may have an IPv6 address which is still undergoing DAD.
582 If so, the bind will fail until the DAD completes, so we try over 20 seconds
583 before failing. */
584 if (iface->addr.sa.sa_family == AF_INET6 && (errno == ENODEV || errno == EADDRNOTAVAIL) &&
585 dad_count++ < DAD_WAIT)
586 {
587 sleep(1);
588 continue;
589 }
590#endif
591 break;
592 }
593
594 if (rc == -1 || bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
595 {
596 prettyprint_addr(&iface->addr, daemon->namebuff);
597 die(_("failed to bind listening socket for %s: %s"),
598 daemon->namebuff, EC_BADNET);
599 }
600
601 if (listen(new->tcpfd, 5) == -1)
602 die(_("failed to listen on socket: %s"), NULL, EC_BADNET);
603 }
604
605#ifdef HAVE_TFTP
606 if ((daemon->options & OPT_TFTP) && iface->addr.sa.sa_family == AF_INET && iface->dhcp_ok)
607 {
608 short save = iface->addr.in.sin_port;
609 iface->addr.in.sin_port = htons(TFTP_PORT);
610 if ((new->tftpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ||
611 setsockopt(new->tftpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
612 !fix_fd(new->tftpfd) ||
613 bind(new->tftpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
614 die(_("failed to create TFTP socket: %s"), NULL, EC_BADNET);
615 iface->addr.in.sin_port = save;
616 }
617#endif
Robert Greenwalt41cd7ed2012-12-11 12:42:32 -0800618#endif /* !__ANDROID */
San Mehatffd68722010-01-20 09:56:15 -0800619 }
620
621 return listeners;
622}
623
624
625/* return a UDP socket bound to a random port, have to cope with straying into
626 occupied port nos and reserved ones. */
627int random_sock(int family)
628{
629 int fd;
630
631 if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
632 {
633 union mysockaddr addr;
634 unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
635 int tries = ports_avail < 30 ? 3 * ports_avail : 100;
636
637 memset(&addr, 0, sizeof(addr));
638 addr.sa.sa_family = family;
639
640 /* don't loop forever if all ports in use. */
641
642 if (fix_fd(fd))
643 while(tries--)
644 {
645 unsigned short port = rand16();
646
647 if (daemon->min_port != 0)
648 port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
649
650 if (family == AF_INET)
651 {
652 addr.in.sin_addr.s_addr = INADDR_ANY;
653 addr.in.sin_port = port;
654#ifdef HAVE_SOCKADDR_SA_LEN
655 addr.in.sin_len = sizeof(struct sockaddr_in);
656#endif
657 }
658#ifdef HAVE_IPV6
659 else
660 {
661 addr.in6.sin6_addr = in6addr_any;
662 addr.in6.sin6_port = port;
663#ifdef HAVE_SOCKADDR_SA_LEN
664 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
665#endif
666 }
667#endif
668
669 if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
670 return fd;
671
672 if (errno != EADDRINUSE && errno != EACCES)
673 break;
674 }
675
676 close(fd);
677 }
678
679 return -1;
680}
681
682
Lorenzo Colitti68eff532014-08-26 14:06:34 -0700683int local_bind(int fd, union mysockaddr *addr, char *intname, uint32_t mark, int is_tcp)
San Mehatffd68722010-01-20 09:56:15 -0800684{
685 union mysockaddr addr_copy = *addr;
686
687 /* cannot set source _port_ for TCP connections. */
688 if (is_tcp)
689 {
690 if (addr_copy.sa.sa_family == AF_INET)
691 addr_copy.in.sin_port = 0;
692#ifdef HAVE_IPV6
693 else
694 addr_copy.in6.sin6_port = 0;
695#endif
696 }
697
698 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
699 return 0;
700
701#if defined(SO_BINDTODEVICE)
702 if (intname[0] != 0 &&
703 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, strlen(intname)) == -1)
704 return 0;
705#endif
706
Lorenzo Colitti68eff532014-08-26 14:06:34 -0700707 if (mark != 0 && setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) == -1)
708 return 0;
709
San Mehatffd68722010-01-20 09:56:15 -0800710 return 1;
711}
712
Lorenzo Colitti68eff532014-08-26 14:06:34 -0700713static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname, uint32_t mark)
San Mehatffd68722010-01-20 09:56:15 -0800714{
715 struct serverfd *sfd;
716 int errsave;
717
718 /* when using random ports, servers which would otherwise use
719 the INADDR_ANY/port0 socket have sfd set to NULL */
720 if (!daemon->osport && intname[0] == 0)
721 {
722 errno = 0;
723
724 if (addr->sa.sa_family == AF_INET &&
725 addr->in.sin_addr.s_addr == INADDR_ANY &&
726 addr->in.sin_port == htons(0))
727 return NULL;
728
729#ifdef HAVE_IPV6
730 if (addr->sa.sa_family == AF_INET6 &&
731 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
732 addr->in6.sin6_port == htons(0))
733 return NULL;
734#endif
735 }
736
737 /* may have a suitable one already */
738 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
739 if (sockaddr_isequal(&sfd->source_addr, addr) &&
Lorenzo Colitti68eff532014-08-26 14:06:34 -0700740 mark == sfd->mark &&
San Mehatffd68722010-01-20 09:56:15 -0800741 strcmp(intname, sfd->interface) == 0)
742 return sfd;
743
744 /* need to make a new one. */
745 errno = ENOMEM; /* in case malloc fails. */
746 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
747 return NULL;
748
749 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
750 {
751 free(sfd);
752 return NULL;
753 }
754
Lorenzo Colitti68eff532014-08-26 14:06:34 -0700755 if (!local_bind(sfd->fd, addr, intname, mark, 0) || !fix_fd(sfd->fd))
San Mehatffd68722010-01-20 09:56:15 -0800756 {
757 errsave = errno; /* save error from bind. */
758 close(sfd->fd);
759 free(sfd);
760 errno = errsave;
761 return NULL;
762 }
763
764 strcpy(sfd->interface, intname);
765 sfd->source_addr = *addr;
Lorenzo Colitti68eff532014-08-26 14:06:34 -0700766 sfd->mark = mark;
San Mehatffd68722010-01-20 09:56:15 -0800767 sfd->next = daemon->sfds;
768 daemon->sfds = sfd;
769 return sfd;
770}
771
772/* create upstream sockets during startup, before root is dropped which may be needed
773 this allows query_port to be a low port and interface binding */
774void pre_allocate_sfds(void)
775{
776 struct server *srv;
777
778 if (daemon->query_port != 0)
779 {
780 union mysockaddr addr;
781 memset(&addr, 0, sizeof(addr));
782 addr.in.sin_family = AF_INET;
783 addr.in.sin_addr.s_addr = INADDR_ANY;
784 addr.in.sin_port = htons(daemon->query_port);
785#ifdef HAVE_SOCKADDR_SA_LEN
786 addr.in.sin_len = sizeof(struct sockaddr_in);
787#endif
Lorenzo Colitti68eff532014-08-26 14:06:34 -0700788 allocate_sfd(&addr, "", 0);
San Mehatffd68722010-01-20 09:56:15 -0800789#ifdef HAVE_IPV6
790 memset(&addr, 0, sizeof(addr));
791 addr.in6.sin6_family = AF_INET6;
792 addr.in6.sin6_addr = in6addr_any;
793 addr.in6.sin6_port = htons(daemon->query_port);
794#ifdef HAVE_SOCKADDR_SA_LEN
795 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
796#endif
Lorenzo Colitti68eff532014-08-26 14:06:34 -0700797 allocate_sfd(&addr, "", 0);
San Mehatffd68722010-01-20 09:56:15 -0800798#endif
799 }
800
801 for (srv = daemon->servers; srv; srv = srv->next)
802 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
Lorenzo Colitti68eff532014-08-26 14:06:34 -0700803 !allocate_sfd(&srv->source_addr, srv->interface, srv->mark) &&
San Mehatffd68722010-01-20 09:56:15 -0800804 errno != 0 &&
805 (daemon->options & OPT_NOWILD))
806 {
807 prettyprint_addr(&srv->addr, daemon->namebuff);
808 if (srv->interface[0] != 0)
809 {
810 strcat(daemon->namebuff, " ");
811 strcat(daemon->namebuff, srv->interface);
812 }
813 die(_("failed to bind server socket for %s: %s"),
814 daemon->namebuff, EC_BADNET);
815 }
816}
817
818
819void check_servers(void)
820{
821 struct irec *iface;
822 struct server *new, *tmp, *ret = NULL;
823 int port = 0;
824
825 for (new = daemon->servers; new; new = tmp)
826 {
827 tmp = new->next;
828
829 if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)))
830 {
831 port = prettyprint_addr(&new->addr, daemon->namebuff);
832
833 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
834 if (new->addr.sa.sa_family == AF_INET &&
835 new->addr.in.sin_addr.s_addr == 0)
836 {
837 free(new);
838 continue;
839 }
840
841 for (iface = daemon->interfaces; iface; iface = iface->next)
842 if (sockaddr_isequal(&new->addr, &iface->addr))
843 break;
844 if (iface)
845 {
846 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
847 free(new);
848 continue;
849 }
850
851 /* Do we need a socket set? */
852 if (!new->sfd &&
Lorenzo Colitti68eff532014-08-26 14:06:34 -0700853 !(new->sfd = allocate_sfd(&new->source_addr, new->interface, new->mark)) &&
San Mehatffd68722010-01-20 09:56:15 -0800854 errno != 0)
855 {
856 my_syslog(LOG_WARNING,
857 _("ignoring nameserver %s - cannot make/bind socket: %s"),
858 daemon->namebuff, strerror(errno));
859 free(new);
860 continue;
861 }
862 }
863
864 /* reverse order - gets it right. */
865 new->next = ret;
866 ret = new;
867
868 if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS))
869 {
870 char *s1, *s2;
871 if (!(new->flags & SERV_HAS_DOMAIN))
872 s1 = _("unqualified"), s2 = _("names");
873 else if (strlen(new->domain) == 0)
874 s1 = _("default"), s2 = "";
875 else
876 s1 = _("domain"), s2 = new->domain;
877
878 if (new->flags & SERV_NO_ADDR)
879 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
880 else if (!(new->flags & SERV_LITERAL_ADDRESS))
881 my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
882 }
883 else if (new->interface[0] != 0)
884 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface);
885 else
886 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
887 }
888
889 daemon->servers = ret;
890}
891
San Mehat33b34442010-01-20 10:54:48 -0800892#ifdef __ANDROID__
Robert Greenwalt41cd7ed2012-12-11 12:42:32 -0800893/* #define __ANDROID_DEBUG__ 1 */
894/*
895 * Ingests a new list of interfaces and starts to listen on them, adding only the new
896 * and stopping to listen to any interfaces not on the new list.
897 *
898 * interfaces - input in the format "bt-pan:eth0:wlan0:..>" up to 1024 bytes long
899 */
900void set_interfaces(const char *interfaces)
901{
902 struct iname *if_tmp;
903 struct iname *prev_if_names;
904 struct irec *old_iface, *new_iface, *prev_interfaces;
905 char s[1024];
906 char *next = s;
907 char *interface;
908 int was_wild = 0;
909
910#ifdef __ANDROID_DEBUG__
911 my_syslog(LOG_DEBUG, _("set_interfaces(%s)"), interfaces);
912#endif
913 prev_if_names = daemon->if_names;
914 daemon->if_names = NULL;
915
916 prev_interfaces = daemon->interfaces;
917 daemon->interfaces = NULL;
918
919 if (strlen(interfaces) > sizeof(s)) {
920 die(_("interface string too long: %s"), NULL, EC_BADNET);
921 }
922 strncpy(s, interfaces, sizeof(s));
923 while((interface = strsep(&next, ":"))) {
924 if_tmp = safe_malloc(sizeof(struct iname));
925 memset(if_tmp, sizeof(struct iname), 0);
926 if ((if_tmp->name = strdup(interface)) == NULL) {
927 die(_("malloc failure in set_interfaces: %s"), NULL, EC_BADNET);
928 }
929 if_tmp->next = daemon->if_names;
930 daemon->if_names = if_tmp;
931 }
932
933 if (!enumerate_interfaces()) {
934 die(_("enumerate interfaces error in set_interfaces: %s"), NULL, EC_BADNET);
935 }
936
937 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next) {
938 if (if_tmp->name && !if_tmp->used) {
939 die(_("unknown interface given %s in set_interfaces: %s"), if_tmp->name, EC_BADNET);
940 }
941 }
942 /* success! - setup to free the old */
943 /* check for any that have been removed */
944 for (old_iface = prev_interfaces; old_iface; old_iface=old_iface->next) {
945 int found = 0;
946 for (new_iface = daemon->interfaces; new_iface; new_iface = new_iface->next) {
947 if (sockaddr_isequal(&old_iface->addr, &new_iface->addr)) {
948 found = -1;
949 break;
950 }
951 }
952 if (!found) {
953#ifdef __ANDROID_DEBUG__
954 char debug_buff[MAXDNAME];
955 prettyprint_addr(&old_iface->addr, debug_buff);
956 my_syslog(LOG_DEBUG, _("closing listener for %s"), debug_buff);
957#endif
958
959 close_bound_listener(old_iface);
960 }
961 }
962
963 /* remove wildchar listeners */
964 was_wild = close_bound_listener(NULL);
965 if (was_wild) daemon->options |= OPT_NOWILD;
966
967 /* check for any that have been added */
968 for (new_iface = daemon->interfaces; new_iface; new_iface = new_iface->next) {
969 int found = 0;
970
971 /* if the previous setup used a wildchar, then add any current interfaces */
972 if (!was_wild) {
973 for (old_iface = prev_interfaces; old_iface; old_iface = old_iface->next) {
974 if(sockaddr_isequal(&old_iface->addr, &new_iface->addr)) {
975 found = -1;
976 break;
977 }
978 }
979 }
980 if (!found) {
981#ifdef __ANDROID_DEBUG__
982 char debug_buff[MAXDNAME];
983 prettyprint_addr(&new_iface->addr, debug_buff);
984 my_syslog(LOG_DEBUG, _("adding listener for %s"), debug_buff);
985#endif
986 create_bound_listener(&(daemon->listeners), new_iface);
987 }
988 }
989
990 while (prev_if_names) {
991 if (prev_if_names->name) free(prev_if_names->name);
992 if_tmp = prev_if_names->next;
993 free(prev_if_names);
994 prev_if_names = if_tmp;
995 }
996 while (prev_interfaces) {
997 struct irec *tmp_irec = prev_interfaces->next;
998 free(prev_interfaces);
999 prev_interfaces = tmp_irec;
1000 }
1001#ifdef __ANDROID_DEBUG__
1002 my_syslog(LOG_DEBUG, _("done with setInterfaces"));
1003#endif
1004}
1005
San Mehat33b34442010-01-20 10:54:48 -08001006/*
Lorenzo Colitti68eff532014-08-26 14:06:34 -07001007 * Takes a string in the format "0x100b:1.2.3.4:1.2.3.4:..." - up to 1024 bytes in length
1008 * - The first element is the socket mark to set on sockets that forward DNS queries.
1009 * - The subsequent elements are the DNS servers to forward queries to.
San Mehat33b34442010-01-20 10:54:48 -08001010 */
1011int set_servers(const char *servers)
1012{
1013 char s[1024];
1014 struct server *old_servers = NULL;
1015 struct server *new_servers = NULL;
1016 struct server *serv;
Lorenzo Colitti68eff532014-08-26 14:06:34 -07001017 char *mark_string;
1018 uint32_t mark;
San Mehat33b34442010-01-20 10:54:48 -08001019
1020 strncpy(s, servers, sizeof(s));
1021
1022 /* move old servers to free list - we can reuse the memory
1023 and not risk malloc if there are the same or fewer new servers.
1024 Servers which were specced on the command line go to the new list. */
1025 for (serv = daemon->servers; serv;)
1026 {
1027 struct server *tmp = serv->next;
1028 if (serv->flags & SERV_FROM_RESOLV)
1029 {
1030 serv->next = old_servers;
1031 old_servers = serv;
1032 /* forward table rules reference servers, so have to blow them away */
1033 server_gone(serv);
1034 }
1035 else
1036 {
1037 serv->next = new_servers;
1038 new_servers = serv;
1039 }
1040 serv = tmp;
1041 }
1042
Lorenzo Colitti68eff532014-08-26 14:06:34 -07001043 char *next = s;
1044 char *saddr;
San Mehat33b34442010-01-20 10:54:48 -08001045
Lorenzo Colitti68eff532014-08-26 14:06:34 -07001046 /* Parse the mark. */
1047 mark_string = strsep(&next, ":");
1048 mark = strtoul(mark_string, NULL, 0);
1049
1050 while ((saddr = strsep(&next, ":"))) {
San Mehat33b34442010-01-20 10:54:48 -08001051 union mysockaddr addr, source_addr;
1052 memset(&addr, 0, sizeof(addr));
1053 memset(&source_addr, 0, sizeof(source_addr));
1054
1055 if ((addr.in.sin_addr.s_addr = inet_addr(saddr)) != (in_addr_t) -1)
1056 {
1057#ifdef HAVE_SOCKADDR_SA_LEN
1058 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1059#endif
1060 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1061 addr.in.sin_port = htons(NAMESERVER_PORT);
1062 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1063 source_addr.in.sin_port = htons(daemon->query_port);
1064 }
1065#ifdef HAVE_IPV6
1066 else if (inet_pton(AF_INET6, saddr, &addr.in6.sin6_addr) > 0)
1067 {
1068#ifdef HAVE_SOCKADDR_SA_LEN
1069 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
1070#endif
1071 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1072 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1073 source_addr.in6.sin6_addr = in6addr_any;
1074 source_addr.in6.sin6_port = htons(daemon->query_port);
1075 }
1076#endif /* IPV6 */
1077 else
1078 continue;
1079
1080 if (old_servers)
1081 {
1082 serv = old_servers;
1083 old_servers = old_servers->next;
1084 }
1085 else if (!(serv = whine_malloc(sizeof (struct server))))
1086 continue;
1087
1088 /* this list is reverse ordered:
1089 it gets reversed again in check_servers */
1090 serv->next = new_servers;
1091 new_servers = serv;
1092 serv->addr = addr;
1093 serv->source_addr = source_addr;
1094 serv->domain = NULL;
1095 serv->interface[0] = 0;
Lorenzo Colitti68eff532014-08-26 14:06:34 -07001096 serv->mark = mark;
San Mehat33b34442010-01-20 10:54:48 -08001097 serv->sfd = NULL;
1098 serv->flags = SERV_FROM_RESOLV;
1099 serv->queries = serv->failed_queries = 0;
1100 }
1101
1102 /* Free any memory not used. */
1103 while (old_servers)
1104 {
1105 struct server *tmp = old_servers->next;
1106 free(old_servers);
1107 old_servers = tmp;
1108 }
1109
1110 daemon->servers = new_servers;
1111 return 0;
1112}
1113#endif
1114
San Mehatffd68722010-01-20 09:56:15 -08001115/* Return zero if no servers found, in that case we keep polling.
1116 This is a protection against an update-time/write race on resolv.conf */
1117int reload_servers(char *fname)
1118{
1119 FILE *f;
1120 char *line;
1121 struct server *old_servers = NULL;
1122 struct server *new_servers = NULL;
1123 struct server *serv;
1124 int gotone = 0;
1125
1126 /* buff happens to be MAXDNAME long... */
1127 if (!(f = fopen(fname, "r")))
1128 {
1129 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
1130 return 0;
1131 }
1132
1133 /* move old servers to free list - we can reuse the memory
1134 and not risk malloc if there are the same or fewer new servers.
1135 Servers which were specced on the command line go to the new list. */
1136 for (serv = daemon->servers; serv;)
1137 {
1138 struct server *tmp = serv->next;
1139 if (serv->flags & SERV_FROM_RESOLV)
1140 {
1141 serv->next = old_servers;
1142 old_servers = serv;
1143 /* forward table rules reference servers, so have to blow them away */
1144 server_gone(serv);
1145 }
1146 else
1147 {
1148 serv->next = new_servers;
1149 new_servers = serv;
1150 }
1151 serv = tmp;
1152 }
1153
1154 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1155 {
1156 union mysockaddr addr, source_addr;
1157 char *token = strtok(line, " \t\n\r");
1158
1159 if (!token)
1160 continue;
1161 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
1162 continue;
1163 if (!(token = strtok(NULL, " \t\n\r")))
1164 continue;
1165
1166 memset(&addr, 0, sizeof(addr));
1167 memset(&source_addr, 0, sizeof(source_addr));
1168
1169 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
1170 {
1171#ifdef HAVE_SOCKADDR_SA_LEN
1172 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1173#endif
1174 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1175 addr.in.sin_port = htons(NAMESERVER_PORT);
1176 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1177 source_addr.in.sin_port = htons(daemon->query_port);
1178 }
1179#ifdef HAVE_IPV6
1180 else if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1181 {
1182#ifdef HAVE_SOCKADDR_SA_LEN
1183 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
1184#endif
1185 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1186 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1187 source_addr.in6.sin6_addr = in6addr_any;
1188 source_addr.in6.sin6_port = htons(daemon->query_port);
1189 }
1190#endif /* IPV6 */
1191 else
1192 continue;
1193
1194 if (old_servers)
1195 {
1196 serv = old_servers;
1197 old_servers = old_servers->next;
1198 }
1199 else if (!(serv = whine_malloc(sizeof (struct server))))
1200 continue;
1201
1202 /* this list is reverse ordered:
1203 it gets reversed again in check_servers */
1204 serv->next = new_servers;
1205 new_servers = serv;
1206 serv->addr = addr;
1207 serv->source_addr = source_addr;
1208 serv->domain = NULL;
1209 serv->interface[0] = 0;
Lorenzo Colitti68eff532014-08-26 14:06:34 -07001210 serv->mark = 0;
San Mehatffd68722010-01-20 09:56:15 -08001211 serv->sfd = NULL;
1212 serv->flags = SERV_FROM_RESOLV;
1213 serv->queries = serv->failed_queries = 0;
1214 gotone = 1;
1215 }
1216
1217 /* Free any memory not used. */
1218 while (old_servers)
1219 {
1220 struct server *tmp = old_servers->next;
1221 free(old_servers);
1222 old_servers = tmp;
1223 }
1224
1225 daemon->servers = new_servers;
1226 fclose(f);
1227
1228 return gotone;
1229}
1230
1231
1232/* Use an IPv4 listener socket for ioctling */
1233struct in_addr get_ifaddr(char *intr)
1234{
1235 struct listener *l;
1236 struct ifreq ifr;
1237
1238 for (l = daemon->listeners; l && l->family != AF_INET; l = l->next);
1239
1240 strncpy(ifr.ifr_name, intr, IF_NAMESIZE);
1241 ifr.ifr_addr.sa_family = AF_INET;
1242
1243 if (!l || ioctl(l->fd, SIOCGIFADDR, &ifr) == -1)
1244 ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = -1;
1245
1246 return ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
1247}