]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/grabmyaddr.c
ipsec-34.0.2.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / grabmyaddr.c
1 /* $Id: grabmyaddr.c,v 1.23.4.2 2005/07/16 04:41:01 monas Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include "config.h"
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 #include <sys/ioctl.h>
38
39 #include <net/if.h>
40 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
41 #include <net/if_var.h>
42 #endif
43 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__)
44 #include <netinet/in.h>
45 #include <netinet6/in6_var.h>
46 #endif
47 #include <net/route.h>
48
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <string.h>
52 #include <errno.h>
53 #ifdef HAVE_UNISTD_H
54 #include <unistd.h>
55 #endif
56 #include <netdb.h>
57 #ifdef HAVE_GETIFADDRS
58 #include <ifaddrs.h>
59 #include <net/if.h>
60 #endif
61
62 #include "var.h"
63 #include "misc.h"
64 #include "vmbuf.h"
65 #include "plog.h"
66 #include "sockmisc.h"
67 #include "debug.h"
68
69 #include "localconf.h"
70 #include "handler.h"
71 #include "grabmyaddr.h"
72 #include "sockmisc.h"
73 #include "isakmp_var.h"
74 #include "gcmalloc.h"
75 #include "nattraversal.h"
76
77 #ifdef __linux__
78 #include <linux/types.h>
79 #include <linux/rtnetlink.h>
80 #ifndef HAVE_GETIFADDRS
81 #define HAVE_GETIFADDRS
82 #define NEED_LINUX_GETIFADDRS
83 #endif
84 #endif
85
86 #ifndef HAVE_GETIFADDRS
87 static unsigned int if_maxindex __P((void));
88 #endif
89 #ifdef __APPLE__
90 static struct myaddrs *find_myaddr __P((struct myaddrs *, struct sockaddr *, int));
91 #else
92 static struct myaddrs *find_myaddr __P((struct myaddrs *, struct myaddrs *));
93 #endif
94 static int suitable_ifaddr __P((const char *, const struct sockaddr *));
95 #ifdef INET6
96 static int suitable_ifaddr6 __P((const char *, const struct sockaddr *));
97 #endif
98
99 #ifdef NEED_LINUX_GETIFADDRS
100
101 /* We could do this _much_ better. kame racoon in its current form
102 * will esentially die at frequent changes of address configuration.
103 */
104
105 struct ifaddrs
106 {
107 struct ifaddrs *ifa_next;
108 char ifa_name[16];
109 int ifa_ifindex;
110 struct sockaddr *ifa_addr;
111 struct sockaddr_storage ifa_addrbuf;
112 };
113
114 static int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
115 {
116 while (RTA_OK(rta, len)) {
117 if (rta->rta_type <= max)
118 tb[rta->rta_type] = rta;
119 rta = RTA_NEXT(rta,len);
120 }
121 return 0;
122 }
123
124 static void recvaddrs(int fd, struct ifaddrs **ifa, __u32 seq)
125 {
126 char buf[8192];
127 struct sockaddr_nl nladdr;
128 struct iovec iov = { buf, sizeof(buf) };
129 struct ifaddrmsg *m;
130 struct rtattr * rta_tb[IFA_MAX+1];
131 struct ifaddrs *I;
132
133 while (1) {
134 int status;
135 struct nlmsghdr *h;
136
137 struct msghdr msg = {
138 (void*)&nladdr, sizeof(nladdr),
139 &iov, 1,
140 NULL, 0,
141 0
142 };
143
144 status = recvmsg(fd, &msg, 0);
145
146 if (status < 0)
147 continue;
148
149 if (status == 0)
150 return;
151
152 if (nladdr.nl_pid) /* Message not from kernel */
153 continue;
154
155 h = (struct nlmsghdr*)buf;
156 while (NLMSG_OK(h, status)) {
157 if (h->nlmsg_seq != seq)
158 goto skip_it;
159
160 if (h->nlmsg_type == NLMSG_DONE)
161 return;
162
163 if (h->nlmsg_type == NLMSG_ERROR)
164 return;
165
166 if (h->nlmsg_type != RTM_NEWADDR)
167 goto skip_it;
168
169 m = NLMSG_DATA(h);
170
171 if (m->ifa_family != AF_INET &&
172 m->ifa_family != AF_INET6)
173 goto skip_it;
174
175 if (m->ifa_flags&IFA_F_TENTATIVE)
176 goto skip_it;
177
178 memset(rta_tb, 0, sizeof(rta_tb));
179 parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(m), h->nlmsg_len - NLMSG_LENGTH(sizeof(*m)));
180
181 if (rta_tb[IFA_LOCAL] == NULL)
182 rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
183 if (rta_tb[IFA_LOCAL] == NULL)
184 goto skip_it;
185
186 I = malloc(sizeof(struct ifaddrs));
187 if (!I)
188 return;
189 memset(I, 0, sizeof(*I));
190
191 I->ifa_ifindex = m->ifa_index;
192 I->ifa_addr = (struct sockaddr*)&I->ifa_addrbuf;
193 I->ifa_addr->sa_family = m->ifa_family;
194 if (m->ifa_family == AF_INET) {
195 struct sockaddr_in *sin = (void*)I->ifa_addr;
196 memcpy(&sin->sin_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 4);
197 } else {
198 struct sockaddr_in6 *sin = (void*)I->ifa_addr;
199 memcpy(&sin->sin6_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 16);
200 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
201 sin->sin6_scope_id = I->ifa_ifindex;
202 }
203 I->ifa_next = *ifa;
204 *ifa = I;
205
206 skip_it:
207 h = NLMSG_NEXT(h, status);
208 }
209 if (msg.msg_flags & MSG_TRUNC)
210 continue;
211 }
212 return;
213 }
214
215 static int getifaddrs(struct ifaddrs **ifa0)
216 {
217 struct {
218 struct nlmsghdr nlh;
219 struct rtgenmsg g;
220 } req;
221 struct sockaddr_nl nladdr;
222 static __u32 seq;
223 struct ifaddrs *i;
224 int fd;
225
226 fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
227 if (fd < 0)
228 return -1;
229
230 memset(&nladdr, 0, sizeof(nladdr));
231 nladdr.nl_family = AF_NETLINK;
232
233 req.nlh.nlmsg_len = sizeof(req);
234 req.nlh.nlmsg_type = RTM_GETADDR;
235 req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
236 req.nlh.nlmsg_pid = 0;
237 req.nlh.nlmsg_seq = ++seq;
238 req.g.rtgen_family = AF_UNSPEC;
239
240 if (sendto(fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr)) < 0) {
241 close(fd);
242 return -1;
243 }
244
245 *ifa0 = NULL;
246
247 recvaddrs(fd, ifa0, seq);
248
249 close(fd);
250
251 fd = socket(AF_INET, SOCK_DGRAM, 0);
252
253 for (i=*ifa0; i; i = i->ifa_next) {
254 struct ifreq ifr;
255 ifr.ifr_ifindex = i->ifa_ifindex;
256 ioctl(fd, SIOCGIFNAME, (void*)&ifr);
257 memcpy(i->ifa_name, ifr.ifr_name, 16);
258 }
259 close(fd);
260
261 return 0;
262 }
263
264 static void freeifaddrs(struct ifaddrs *ifa0)
265 {
266 struct ifaddrs *i;
267
268 while (ifa0) {
269 i = ifa0;
270 ifa0 = i->ifa_next;
271 free(i);
272 }
273 }
274
275 #endif
276
277 #ifndef HAVE_GETIFADDRS
278 static unsigned int
279 if_maxindex()
280 {
281 struct if_nameindex *p, *p0;
282 unsigned int max = 0;
283
284 p0 = if_nameindex();
285 for (p = p0; p && p->if_index && p->if_name; p++) {
286 if (max < p->if_index)
287 max = p->if_index;
288 }
289 if_freenameindex(p0);
290 return max;
291 }
292 #endif
293
294
295 void
296 clear_myaddr()
297 {
298 struct myaddrs *p, *next;
299
300 for (p = lcconf->myaddrs; p; p = next) {
301 next = p->next;
302
303 if (p->addr)
304 racoon_free(p->addr);
305 racoon_free(p);
306 }
307
308 lcconf->myaddrs = NULL;
309
310 }
311
312
313 static struct myaddrs *
314 find_myaddr(db, addr, udp_encap)
315 struct myaddrs *db;
316 struct sockaddr *addr;
317 int udp_encap;
318 {
319 struct myaddrs *q;
320 char h1[NI_MAXHOST], h2[NI_MAXHOST];
321
322 if (getnameinfo(addr, sysdep_sa_len(addr), h1, sizeof(h1), NULL, 0,
323 NI_NUMERICHOST | niflags) != 0)
324 return NULL;
325
326 for (q = db; q; q = q->next) {
327 if (!q->addr)
328 continue;
329 if (q->udp_encap && !udp_encap
330 || !q->udp_encap && udp_encap)
331 continue;
332 if (addr->sa_family != q->addr->sa_family)
333 continue;
334 if (getnameinfo(q->addr, sysdep_sa_len(q->addr), h2, sizeof(h2),
335 NULL, 0, NI_NUMERICHOST | niflags) != 0)
336 return NULL;
337 if (strcmp(h1, h2) == 0)
338 return q;
339 }
340
341 return NULL;
342 }
343
344
345 // modified to avoid closing and opening sockets for
346 // all interfaces each time an interface change occurs.
347 // on return: addrcount = zero indicates address no longer used
348 // sock = -1 indicates a new address - no socket opened yet.
349 void
350 grab_myaddrs()
351 {
352 #ifdef HAVE_GETIFADDRS
353 struct myaddrs *p, *q;
354 struct ifaddrs *ifa0, *ifap;
355 #ifdef INET6
356 struct sockaddr_in6 *sin6;
357 #endif
358
359 char addr1[NI_MAXHOST];
360
361 if (getifaddrs(&ifa0)) {
362 plog(LLV_ERROR2, LOCATION, NULL,
363 "getifaddrs failed: %s\n", strerror(errno));
364 exit(1);
365 /*NOTREACHED*/
366 }
367
368 // clear the in_use flag for each address in the list
369 for (p = lcconf->myaddrs; p; p = p->next)
370 p->in_use = 0;
371
372 for (ifap = ifa0; ifap; ifap = ifap->ifa_next) {
373
374 if (ifap->ifa_addr->sa_family != AF_INET
375 #ifdef INET6
376 && ifap->ifa_addr->sa_family != AF_INET6
377 #endif
378 )
379 continue;
380
381 if (!suitable_ifaddr(ifap->ifa_name, ifap->ifa_addr)) {
382 plog(LLV_ERROR, LOCATION, NULL,
383 "unsuitable address: %s %s\n",
384 ifap->ifa_name,
385 saddrwop2str(ifap->ifa_addr));
386 continue;
387 }
388
389 p = find_myaddr(lcconf->myaddrs, ifap->ifa_addr, 0);
390 if (p) {
391 p->in_use = 1;
392 #ifdef ENABLE_NATT
393 q = find_myaddr(lcconf->myaddrs, ifap->ifa_addr, 1);
394 if (q)
395 q->in_use = 1;
396 #endif
397 } else {
398 p = newmyaddr();
399 if (p == NULL) {
400 plog(LLV_ERROR2, LOCATION, NULL,
401 "unable to allocate space for addr.\n");
402 exit(1);
403 /*NOTREACHED*/
404 }
405 p->addr = dupsaddr(ifap->ifa_addr);
406 if (p->addr == NULL) {
407 plog(LLV_ERROR2, LOCATION, NULL,
408 "unable to duplicate addr.\n");
409 exit(1);
410 /*NOTREACHED*/
411 }
412 p->sock = -1;
413 p->in_use = 1;
414
415 if (getnameinfo(p->addr, p->addr->sa_len,
416 addr1, sizeof(addr1),
417 NULL, 0,
418 NI_NUMERICHOST | niflags))
419 strlcpy(addr1, "(invalid)", sizeof(addr1));
420 plog(LLV_DEBUG, LOCATION, NULL,
421 "my interface: %s (%s)\n",
422 addr1, ifap->ifa_name);
423
424 p->next = lcconf->myaddrs;
425 lcconf->myaddrs = p;
426
427 #ifdef ENABLE_NATT
428 if (natt_enabled_in_rmconf ()) {
429 q = dupmyaddr(p);
430 if (q == NULL) {
431 plog(LLV_ERROR2, LOCATION, NULL,
432 "unable to allocate space for natt addr.\n");
433 exit(1);
434 }
435 q->udp_encap = 1;
436 }
437 #endif
438
439 }
440 }
441
442 freeifaddrs(ifa0);
443
444
445 #else /*!HAVE_GETIFADDRS*/
446 #error "NOT SUPPORTED"
447 #endif /*HAVE_GETIFADDRS*/
448 }
449
450
451 /*
452 * check the interface is suitable or not
453 */
454 static int
455 suitable_ifaddr(ifname, ifaddr)
456 const char *ifname;
457 const struct sockaddr *ifaddr;
458 {
459 #ifdef ENABLE_HYBRID
460 /* Exclude any address we got through ISAKMP mode config */
461 if (exclude_cfg_addr(ifaddr) == 0)
462 return 0;
463 #endif
464 switch(ifaddr->sa_family) {
465 case AF_INET:
466 return 1;
467 #ifdef INET6
468 case AF_INET6:
469 return suitable_ifaddr6(ifname, ifaddr);
470 #endif
471 default:
472 return 0;
473 }
474 /*NOTREACHED*/
475 }
476
477 #ifdef INET6
478 static int
479 suitable_ifaddr6(ifname, ifaddr)
480 const char *ifname;
481 const struct sockaddr *ifaddr;
482 {
483 #ifndef __linux__
484 struct in6_ifreq ifr6;
485 int s;
486 #endif
487
488 if (ifaddr->sa_family != AF_INET6)
489 return 0;
490
491 #ifndef __linux__
492 s = socket(PF_INET6, SOCK_DGRAM, 0);
493 if (s == -1) {
494 plog(LLV_ERROR, LOCATION, NULL,
495 "socket(SOCK_DGRAM) failed:%s\n", strerror(errno));
496 return 0;
497 }
498
499 memset(&ifr6, 0, sizeof(ifr6));
500 strncpy(ifr6.ifr_name, ifname, strlen(ifname));
501
502 ifr6.ifr_addr = *(const struct sockaddr_in6 *)ifaddr;
503
504 if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
505 plog(LLV_ERROR, LOCATION, NULL,
506 "ioctl(SIOCGIFAFLAG_IN6) failed:%s\n", strerror(errno));
507 close(s);
508 return 0;
509 }
510
511 close(s);
512
513 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED
514 || ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED
515 || ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST)
516 return 0;
517 #endif
518
519 /* suitable */
520 return 1;
521 }
522 #endif
523
524 int
525 update_myaddrs()
526 {
527 #ifdef __linux__
528 char msg[BUFSIZ];
529 int len;
530 struct nlmsghdr *h = (void*)msg;
531 len = read(lcconf->rtsock, msg, sizeof(msg));
532 if (len < 0)
533 return errno == ENOBUFS;
534 if (len < sizeof(*h))
535 return 0;
536 if (h->nlmsg_pid) /* not from kernel! */
537 return 0;
538 if (h->nlmsg_type == RTM_NEWLINK)
539 return 0;
540 plog(LLV_DEBUG, LOCATION, NULL,
541 "netlink signals update interface address list\n");
542 return 1;
543 #else
544 char msg[BUFSIZ];
545 int len;
546 struct rt_msghdr *rtm;
547
548 len = read(lcconf->rtsock, msg, sizeof(msg));
549 if (len < 0) {
550 plog(LLV_ERROR, LOCATION, NULL,
551 "read(PF_ROUTE) failed: %s\n",
552 strerror(errno));
553 return 0;
554 }
555 rtm = (struct rt_msghdr *)msg;
556 if (len < rtm->rtm_msglen) {
557 plog(LLV_ERROR, LOCATION, NULL,
558 "read(PF_ROUTE) short read\n");
559 return 0;
560 }
561 if (rtm->rtm_version != RTM_VERSION) {
562 plog(LLV_ERROR, LOCATION, NULL,
563 "routing socket version mismatch\n");
564 close(lcconf->rtsock);
565 lcconf->rtsock = -1;
566 return 0;
567 }
568 switch (rtm->rtm_type) {
569 case RTM_NEWADDR:
570 case RTM_DELADDR:
571 case RTM_DELETE:
572 case RTM_IFINFO:
573 break;
574 case RTM_MISS:
575 /* ignore this message silently */
576 return 0;
577 default:
578 plog(LLV_DEBUG, LOCATION, NULL,
579 "msg %d not interesting\n", rtm->rtm_type);
580 return 0;
581 }
582 /* XXX more filters here? */
583
584 plog(LLV_DEBUG, LOCATION, NULL,
585 "caught rtm:%d, need update interface address list\n",
586 rtm->rtm_type);
587
588 return 1;
589 #endif /* __linux__ */
590 }
591
592 /*
593 * initialize default port for ISAKMP to send, if no "listen"
594 * directive is specified in config file.
595 *
596 * DO NOT listen to wildcard addresses. if you receive packets to
597 * wildcard address, you'll be in trouble (DoS attack possible by
598 * broadcast storm).
599 */
600 int
601 autoconf_myaddrsport()
602 {
603 struct myaddrs *p;
604 int n;
605
606 plog(LLV_DEBUG, LOCATION, NULL,
607 "configuring default isakmp port.\n");
608
609 for (p = lcconf->myaddrs, n = 0; p; p = p->next, n++) {
610 set_port (p->addr, p->udp_encap ? lcconf->port_isakmp_natt : lcconf->port_isakmp);
611 }
612 plog(LLV_DEBUG, LOCATION, NULL,
613 "%d addrs are configured successfully\n", n);
614
615 return 0;
616 }
617
618 /*
619 * get a port number to which racoon binded.
620 * NOTE: network byte order returned.
621 */
622 u_short
623 getmyaddrsport(local)
624 struct sockaddr *local;
625 {
626 struct myaddrs *p, *bestmatch = NULL;
627 u_short bestmatch_port = PORT_ISAKMP;
628
629 /* get a relative port */
630 for (p = lcconf->myaddrs; p; p = p->next) {
631 if (!p->addr)
632 continue;
633 if (!cmpsaddrwop(local, p->addr)) {
634 if (! bestmatch) {
635 bestmatch = p;
636 continue;
637 }
638
639 switch (p->addr->sa_family) {
640 case AF_INET:
641 if (((struct sockaddr_in *)p->addr)->sin_port == PORT_ISAKMP) {
642 bestmatch = p;
643 bestmatch_port = ((struct sockaddr_in *)p->addr)->sin_port;
644 break;
645 }
646 break;
647 #ifdef INET6
648 case AF_INET6:
649 if (((struct sockaddr_in6 *)p->addr)->sin6_port == PORT_ISAKMP) {
650 bestmatch = p;
651 bestmatch_port = ((struct sockaddr_in6 *)p->addr)->sin6_port;
652 break;
653 }
654 break;
655 #endif
656 default:
657 plog(LLV_ERROR, LOCATION, NULL,
658 "unsupported AF %d\n", p->addr->sa_family);
659 continue;
660 }
661 }
662 }
663
664 return htons(bestmatch_port);
665 }
666
667 struct myaddrs *
668 newmyaddr()
669 {
670 struct myaddrs *new;
671
672 new = racoon_calloc(1, sizeof(*new));
673 if (new == NULL) {
674 plog(LLV_ERROR, LOCATION, NULL,
675 "failed to allocate buffer for myaddrs.\n");
676 return NULL;
677 }
678
679 new->next = NULL;
680 new->addr = NULL;
681
682 return new;
683 }
684
685 struct myaddrs *
686 dupmyaddr(struct myaddrs *old)
687 {
688 struct myaddrs *new;
689
690 new = racoon_calloc(1, sizeof(*new));
691 if (new == NULL) {
692 plog(LLV_ERROR, LOCATION, NULL,
693 "failed to allocate buffer for myaddrs.\n");
694 return NULL;
695 }
696
697 /* Copy the whole structure and set the differences. */
698 memcpy (new, old, sizeof (*new));
699 new->addr = dupsaddr (old->addr);
700 if (new->addr == NULL) {
701 plog(LLV_ERROR, LOCATION, NULL,
702 "failed to allocate buffer for duplicate addr.\n");
703 racoon_free(new);
704 return NULL;
705 }
706 new->next = old->next;
707 old->next = new;
708
709 return new;
710 }
711
712 void
713 insmyaddr(new, head)
714 struct myaddrs *new;
715 struct myaddrs **head;
716 {
717 new->next = *head;
718 *head = new;
719 }
720
721 void
722 delmyaddr(myaddr)
723 struct myaddrs *myaddr;
724 {
725 if (myaddr->addr)
726 racoon_free(myaddr->addr);
727 racoon_free(myaddr);
728 }
729
730 int
731 initmyaddr()
732 {
733 /* initialize routing socket */
734 lcconf->rtsock = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC);
735 if (lcconf->rtsock < 0) {
736 plog(LLV_ERROR, LOCATION, NULL,
737 "socket(PF_ROUTE) failed: %s",
738 strerror(errno));
739 return -1;
740 }
741
742 #ifdef __linux__
743 {
744 struct sockaddr_nl nl;
745 u_int addr_len;
746
747 memset(&nl, 0, sizeof(nl));
748 nl.nl_family = AF_NETLINK;
749 nl.nl_groups = RTMGRP_IPV4_IFADDR|RTMGRP_LINK;
750
751 if (bind(lcconf->rtsock, (struct sockaddr*)&nl, sizeof(nl)) < 0) {
752 plog(LLV_ERROR, LOCATION, NULL,
753 "bind(PF_NETLINK) failed: %s\n",
754 strerror(errno));
755 return -1;
756 }
757 addr_len = sizeof(nl);
758 if (getsockname(lcconf->rtsock, (struct sockaddr*)&nl, &addr_len) < 0) {
759 plog(LLV_ERROR, LOCATION, NULL,
760 "getsockname(PF_NETLINK) failed: %s\n",
761 strerror(errno));
762 return -1;
763 }
764 }
765 #endif
766
767 if (lcconf->myaddrs == NULL && lcconf->autograbaddr == 1) {
768 grab_myaddrs();
769
770 if (autoconf_myaddrsport() < 0)
771 return -1;
772 }
773
774 return 0;
775 }
776
777 /* select the socket to be sent */
778 /* should implement other method. */
779 int
780 getsockmyaddr(my)
781 struct sockaddr *my;
782 {
783 struct myaddrs *p, *lastresort = NULL;
784 #if defined(INET6) && defined(__linux__)
785 struct myaddrs *match_wo_scope_id = NULL;
786 int check_wo_scope_id = (my->sa_family == AF_INET6) &&
787 IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)my)->sin6_addr);
788 #endif
789
790 for (p = lcconf->myaddrs; p; p = p->next) {
791 if (p->addr == NULL)
792 continue;
793 if (my->sa_family == p->addr->sa_family) {
794 lastresort = p;
795 } else continue;
796 if (sysdep_sa_len(my) == sysdep_sa_len(p->addr)
797 && memcmp(my, p->addr, sysdep_sa_len(my)) == 0) {
798 break;
799 }
800 #if defined(INET6) && defined(__linux__)
801 if (check_wo_scope_id && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)p->addr)->sin6_addr) &&
802 /* XXX: this depends on sin6_scope_id to be last
803 * item in struct sockaddr_in6 */
804 memcmp(my, p->addr,
805 sysdep_sa_len(my) - sizeof(uint32_t)) == 0) {
806 match_wo_scope_id = p;
807 }
808 #endif
809 }
810 #if defined(INET6) && defined(__linux__)
811 if (!p)
812 p = match_wo_scope_id;
813 #endif
814 if (!p)
815 p = lastresort;
816 if (!p) {
817 plog(LLV_ERROR, LOCATION, NULL,
818 "no socket matches address family %d\n",
819 my->sa_family);
820 return -1;
821 }
822
823 return p->sock;
824 }