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 90static unsigned int if_maxindex __P((void)); 91#endif 92static struct myaddrs *find_myaddr __P((struct myaddrs *, struct myaddrs *)); 93static int suitable_ifaddr __P((const char *, const struct sockaddr *)); 94#ifdef INET6 95static 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 104struct 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 113static 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 123static 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 205skip_it: 206 h = NLMSG_NEXT(h, status); 207 } 208 if (msg.msg_flags & MSG_TRUNC) 209 continue; 210 } 211 return; 212} 213 214static 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 263static 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 277static unsigned int 278if_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 293void 294clear_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 306static struct myaddrs * 307find_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 331void 332grab_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 */ 551static int 552suitable_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 575static int 576suitable_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 621int 622update_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 */ 696int 697autoconf_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 */ 730u_short 731getmyaddrsport(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 760struct myaddrs * 761newmyaddr() 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 778struct myaddrs * 779dupmyaddr(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 805void 806insmyaddr(new, head) 807 struct myaddrs *new; 808 struct myaddrs **head; 809{ 810 new->next = *head; 811 *head = new; 812} 813 814void 815delmyaddr(myaddr) 816 struct myaddrs *myaddr; 817{ 818 if (myaddr->addr) 819 racoon_free(myaddr->addr); 820 racoon_free(myaddr); 821} 822 823int 824initmyaddr() 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. */ 872int 873getsockmyaddr(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