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