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