1/* $NetBSD: grabmyaddr.c,v 1.29 2012/01/01 15:54:51 tteras Exp $ */ 2/* 3 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 4 * Copyright (C) 2008 Timo Teras <timo.teras@iki.fi>. 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 <errno.h> 35#include <fcntl.h> 36#include <unistd.h> 37#include <string.h> 38#include <sys/types.h> 39#include <sys/queue.h> 40#include <sys/socket.h> 41 42#ifdef __linux__ 43#include <linux/netlink.h> 44#include <linux/rtnetlink.h> 45#define USE_NETLINK 46#else 47#include <net/route.h> 48#include <net/if.h> 49#include <net/if_dl.h> 50#include <sys/sysctl.h> 51#define USE_ROUTE 52#endif 53 54#include "var.h" 55#include "misc.h" 56#include "vmbuf.h" 57#include "plog.h" 58#include "sockmisc.h" 59#include "session.h" 60#include "debug.h" 61 62#include "localconf.h" 63#include "handler.h" 64#include "grabmyaddr.h" 65#include "sockmisc.h" 66#include "isakmp_var.h" 67#include "gcmalloc.h" 68#include "nattraversal.h" 69 70static int kernel_receive __P((void *ctx, int fd)); 71static int kernel_open_socket __P((void)); 72static void kernel_sync __P((void)); 73 74struct myaddr { 75 LIST_ENTRY(myaddr) chain; 76 struct sockaddr_storage addr; 77 int fd; 78 int udp_encap; 79}; 80 81static LIST_HEAD(_myaddr_list_, myaddr) configured, opened; 82 83static void 84myaddr_delete(my) 85 struct myaddr *my; 86{ 87 if (my->fd != -1) 88 isakmp_close(my->fd); 89 LIST_REMOVE(my, chain); 90 racoon_free(my); 91} 92 93static int 94myaddr_configured(addr) 95 struct sockaddr *addr; 96{ 97 struct myaddr *cfg; 98 99 if (LIST_EMPTY(&configured)) 100 return TRUE; 101 102 LIST_FOREACH(cfg, &configured, chain) { 103 if (cmpsaddr(addr, (struct sockaddr *) &cfg->addr) <= CMPSADDR_WILDPORT_MATCH) 104 return TRUE; 105 } 106 107 return FALSE; 108} 109 110static int 111myaddr_open(addr, udp_encap) 112 struct sockaddr *addr; 113 int udp_encap; 114{ 115 struct myaddr *my; 116 117 /* Already open? */ 118 LIST_FOREACH(my, &opened, chain) { 119 if (cmpsaddr(addr, (struct sockaddr *) &my->addr) <= CMPSADDR_WILDPORT_MATCH) 120 return TRUE; 121 } 122 123 my = racoon_calloc(1, sizeof(struct myaddr)); 124 if (my == NULL) 125 return FALSE; 126 127 memcpy(&my->addr, addr, sysdep_sa_len(addr)); 128 my->fd = isakmp_open(addr, udp_encap); 129 if (my->fd < 0) { 130 racoon_free(my); 131 return FALSE; 132 } 133 my->udp_encap = udp_encap; 134 LIST_INSERT_HEAD(&opened, my, chain); 135 return TRUE; 136} 137 138static int 139myaddr_open_all_configured(addr) 140 struct sockaddr *addr; 141{ 142 /* create all configured, not already opened addresses */ 143 struct myaddr *cfg, *my; 144 145 if (addr != NULL) { 146 switch (addr->sa_family) { 147 case AF_INET: 148#ifdef INET6 149 case AF_INET6: 150#endif 151 break; 152 default: 153 return FALSE; 154 } 155 } 156 157 LIST_FOREACH(cfg, &configured, chain) { 158 if (addr != NULL && 159 cmpsaddr(addr, (struct sockaddr *) &cfg->addr) > CMPSADDR_WILDPORT_MATCH) 160 continue; 161 if (!myaddr_open((struct sockaddr *) &cfg->addr, cfg->udp_encap)) 162 return FALSE; 163 } 164 if (LIST_EMPTY(&configured)) { 165#ifdef ENABLE_HYBRID 166 /* Exclude any address we got through ISAKMP mode config */ 167 if (exclude_cfg_addr(addr) == 0) 168 return FALSE; 169#endif 170 set_port(addr, lcconf->port_isakmp); 171 myaddr_open(addr, FALSE); 172#ifdef ENABLE_NATT 173 set_port(addr, lcconf->port_isakmp_natt); 174 myaddr_open(addr, TRUE); 175#endif 176 } 177 return TRUE; 178} 179 180static void 181myaddr_close_all_open(addr) 182 struct sockaddr *addr; 183{ 184 /* delete all matching open sockets */ 185 struct myaddr *my, *next; 186 187 for (my = LIST_FIRST(&opened); my; my = next) { 188 next = LIST_NEXT(my, chain); 189 190 if (cmpsaddr((struct sockaddr *) addr, 191 (struct sockaddr *) &my->addr) 192 <= CMPSADDR_WOP_MATCH) 193 myaddr_delete(my); 194 } 195} 196 197static void 198myaddr_flush_list(list) 199 struct _myaddr_list_ *list; 200{ 201 struct myaddr *my, *next; 202 203 for (my = LIST_FIRST(list); my; my = next) { 204 next = LIST_NEXT(my, chain); 205 myaddr_delete(my); 206 } 207} 208 209void 210myaddr_flush() 211{ 212 myaddr_flush_list(&configured); 213} 214 215int 216myaddr_listen(addr, udp_encap) 217 struct sockaddr *addr; 218 int udp_encap; 219{ 220 struct myaddr *my; 221 222 if (sysdep_sa_len(addr) > sizeof(my->addr)) { 223 plog(LLV_ERROR, LOCATION, NULL, 224 "sockaddr size larger than sockaddr_storage\n"); 225 return -1; 226 } 227 228 my = racoon_calloc(1, sizeof(struct myaddr)); 229 if (my == NULL) 230 return -1; 231 232 memcpy(&my->addr, addr, sysdep_sa_len(addr)); 233 my->udp_encap = udp_encap; 234 my->fd = -1; 235 LIST_INSERT_HEAD(&configured, my, chain); 236 237 return 0; 238} 239 240void 241myaddr_sync() 242{ 243 struct myaddr *my, *next; 244 245 if (!lcconf->strict_address) { 246 kernel_sync(); 247 248 /* delete all existing listeners which are not configured */ 249 for (my = LIST_FIRST(&opened); my; my = next) { 250 next = LIST_NEXT(my, chain); 251 252 if (!myaddr_configured((struct sockaddr *) &my->addr)) 253 myaddr_delete(my); 254 } 255 } 256} 257 258int 259myaddr_getfd(addr) 260 struct sockaddr *addr; 261{ 262 struct myaddr *my; 263 264 LIST_FOREACH(my, &opened, chain) { 265 if (cmpsaddr((struct sockaddr *) &my->addr, addr) <= CMPSADDR_WILDPORT_MATCH) 266 return my->fd; 267 } 268 269 return -1; 270} 271 272int 273myaddr_getsport(addr) 274 struct sockaddr *addr; 275{ 276 struct myaddr *my; 277 278 LIST_FOREACH(my, &opened, chain) { 279 if (cmpsaddr((struct sockaddr *) &my->addr, addr) <= CMPSADDR_WILDPORT_MATCH) 280 return extract_port((struct sockaddr *) &my->addr); 281 } 282 283 return -1; 284} 285 286void 287myaddr_init_lists() 288{ 289 LIST_INIT(&configured); 290 LIST_INIT(&opened); 291} 292 293int 294myaddr_init() 295{ 296 if (!lcconf->strict_address) { 297 lcconf->rtsock = kernel_open_socket(); 298 if (lcconf->rtsock < 0) 299 return -1; 300 monitor_fd(lcconf->rtsock, kernel_receive, NULL, 0); 301 } else { 302 lcconf->rtsock = -1; 303 if (!myaddr_open_all_configured(NULL)) 304 return -1; 305 } 306 return 0; 307} 308 309void 310myaddr_close() 311{ 312 myaddr_flush_list(&configured); 313 myaddr_flush_list(&opened); 314 if (lcconf->rtsock != -1) { 315 unmonitor_fd(lcconf->rtsock); 316 close(lcconf->rtsock); 317 } 318} 319 320#if defined(USE_NETLINK) 321 322static int netlink_fd = -1; 323 324#define NLMSG_TAIL(nmsg) \ 325 ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) 326 327static void 328parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) 329{ 330 memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); 331 while (RTA_OK(rta, len)) { 332 if (rta->rta_type <= max) 333 tb[rta->rta_type] = rta; 334 rta = RTA_NEXT(rta,len); 335 } 336} 337 338static int 339netlink_add_rtattr_l(struct nlmsghdr *n, int maxlen, int type, 340 const void *data, int alen) 341{ 342 int len = RTA_LENGTH(alen); 343 struct rtattr *rta; 344 345 if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) 346 return FALSE; 347 348 rta = NLMSG_TAIL(n); 349 rta->rta_type = type; 350 rta->rta_len = len; 351 memcpy(RTA_DATA(rta), data, alen); 352 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); 353 return TRUE; 354} 355 356static int 357netlink_enumerate(fd, family, type) 358 int fd; 359 int family; 360 int type; 361{ 362 struct { 363 struct nlmsghdr nlh; 364 struct rtgenmsg g; 365 } req; 366 struct sockaddr_nl addr; 367 static __u32 seq = 0; 368 369 memset(&addr, 0, sizeof(addr)); 370 addr.nl_family = AF_NETLINK; 371 372 memset(&req, 0, sizeof(req)); 373 req.nlh.nlmsg_len = sizeof(req); 374 req.nlh.nlmsg_type = type; 375 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; 376 req.nlh.nlmsg_pid = 0; 377 req.nlh.nlmsg_seq = ++seq; 378 req.g.rtgen_family = family; 379 380 return sendto(fd, (void *) &req, sizeof(req), 0, 381 (struct sockaddr *) &addr, sizeof(addr)) >= 0; 382} 383 384static void 385netlink_add_del_address(int add, struct sockaddr *saddr) 386{ 387 plog(LLV_DEBUG, LOCATION, NULL, 388 "Netlink: address %s %s\n", 389 saddrwop2str((struct sockaddr *) saddr), 390 add ? "added" : "deleted"); 391 392 if (add) 393 myaddr_open_all_configured(saddr); 394 else 395 myaddr_close_all_open(saddr); 396} 397 398#ifdef INET6 399static int 400netlink_process_addr(struct nlmsghdr *h) 401{ 402 struct sockaddr_storage addr; 403 struct ifaddrmsg *ifa; 404 struct rtattr *rta[IFA_MAX+1]; 405 struct sockaddr_in6 *sin6; 406 407 ifa = NLMSG_DATA(h); 408 parse_rtattr(rta, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(h)); 409 410 if (ifa->ifa_family != AF_INET6) 411 return 0; 412 if (ifa->ifa_flags & IFA_F_TENTATIVE) 413 return 0; 414 if (rta[IFA_LOCAL] == NULL) 415 rta[IFA_LOCAL] = rta[IFA_ADDRESS]; 416 if (rta[IFA_LOCAL] == NULL) 417 return 0; 418 419 memset(&addr, 0, sizeof(addr)); 420 addr.ss_family = ifa->ifa_family; 421 sin6 = (struct sockaddr_in6 *) &addr; 422 memcpy(&sin6->sin6_addr, RTA_DATA(rta[IFA_LOCAL]), 423 sizeof(sin6->sin6_addr)); 424 if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 425 return 0; 426 sin6->sin6_scope_id = ifa->ifa_index; 427 428 netlink_add_del_address(h->nlmsg_type == RTM_NEWADDR, 429 (struct sockaddr *) &addr); 430 431 return 0; 432} 433#endif 434 435static int 436netlink_route_is_local(int family, const unsigned char *addr, size_t addr_len) 437{ 438 struct { 439 struct nlmsghdr n; 440 struct rtmsg r; 441 char buf[1024]; 442 } req; 443 struct rtmsg *r = NLMSG_DATA(&req.n); 444 struct rtattr *rta[RTA_MAX+1]; 445 struct sockaddr_nl nladdr; 446 ssize_t rlen; 447 448 memset(&req, 0, sizeof(req)); 449 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 450 req.n.nlmsg_flags = NLM_F_REQUEST; 451 req.n.nlmsg_type = RTM_GETROUTE; 452 req.r.rtm_family = family; 453 netlink_add_rtattr_l(&req.n, sizeof(req), RTA_DST, 454 addr, addr_len); 455 req.r.rtm_dst_len = addr_len * 8; 456 457 memset(&nladdr, 0, sizeof(nladdr)); 458 nladdr.nl_family = AF_NETLINK; 459 460 if (sendto(netlink_fd, &req, sizeof(req), 0, 461 (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) 462 return 0; 463 rlen = recv(netlink_fd, &req, sizeof(req), 0); 464 if (rlen < 0) 465 return 0; 466 467 return req.n.nlmsg_type == RTM_NEWROUTE && 468 req.r.rtm_type == RTN_LOCAL; 469} 470 471static int 472netlink_process_route(struct nlmsghdr *h) 473{ 474 struct sockaddr_storage addr; 475 struct rtmsg *rtm; 476 struct rtattr *rta[RTA_MAX+1]; 477 struct sockaddr_in *sin; 478#ifdef INET6 479 struct sockaddr_in6 *sin6; 480#endif 481 482 rtm = NLMSG_DATA(h); 483 484 /* local IP addresses get local route in the local table */ 485 if (rtm->rtm_type != RTN_LOCAL || 486 rtm->rtm_table != RT_TABLE_LOCAL) 487 return 0; 488 489 parse_rtattr(rta, IFA_MAX, RTM_RTA(rtm), IFA_PAYLOAD(h)); 490 if (rta[RTA_DST] == NULL) 491 return 0; 492 493 /* setup the socket address */ 494 memset(&addr, 0, sizeof(addr)); 495 addr.ss_family = rtm->rtm_family; 496 switch (rtm->rtm_family) { 497 case AF_INET: 498 sin = (struct sockaddr_in *) &addr; 499 memcpy(&sin->sin_addr, RTA_DATA(rta[RTA_DST]), 500 sizeof(sin->sin_addr)); 501 break; 502#ifdef INET6 503 case AF_INET6: 504 sin6 = (struct sockaddr_in6 *) &addr; 505 memcpy(&sin6->sin6_addr, RTA_DATA(rta[RTA_DST]), 506 sizeof(sin6->sin6_addr)); 507 /* Link-local addresses are handled with RTM_NEWADDR 508 * notifications */ 509 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 510 return 0; 511 break; 512#endif 513 default: 514 return 0; 515 } 516 517 /* If local route was deleted, check if there is still local 518 * route for the same IP on another interface */ 519 if (h->nlmsg_type == RTM_DELROUTE && 520 netlink_route_is_local(rtm->rtm_family, 521 RTA_DATA(rta[RTA_DST]), 522 RTA_PAYLOAD(rta[RTA_DST]))) { 523 plog(LLV_DEBUG, LOCATION, NULL, 524 "Netlink: not deleting %s yet, it exists still\n", 525 saddrwop2str((struct sockaddr *) &addr)); 526 return 0; 527 } 528 529 netlink_add_del_address(h->nlmsg_type == RTM_NEWROUTE, 530 (struct sockaddr *) &addr); 531 return 0; 532} 533 534static int 535netlink_process(struct nlmsghdr *h) 536{ 537 switch (h->nlmsg_type) { 538#ifdef INET6 539 case RTM_NEWADDR: 540 case RTM_DELADDR: 541 return netlink_process_addr(h); 542#endif 543 case RTM_NEWROUTE: 544 case RTM_DELROUTE: 545 return netlink_process_route(h); 546 } 547 return 0; 548} 549 550static int 551kernel_receive(ctx, fd) 552 void *ctx; 553 int fd; 554{ 555 struct sockaddr_nl nladdr; 556 struct iovec iov; 557 struct msghdr msg = { 558 .msg_name = &nladdr, 559 .msg_namelen = sizeof(nladdr), 560 .msg_iov = &iov, 561 .msg_iovlen = 1, 562 }; 563 struct nlmsghdr *h; 564 int len, status; 565 char buf[16*1024]; 566 567 iov.iov_base = buf; 568 while (1) { 569 iov.iov_len = sizeof(buf); 570 status = recvmsg(fd, &msg, MSG_DONTWAIT); 571 if (status < 0) { 572 if (errno == EINTR) 573 continue; 574 if (errno == EAGAIN) 575 return FALSE; 576 continue; 577 } 578 if (status == 0) 579 return FALSE; 580 581 h = (struct nlmsghdr *) buf; 582 while (NLMSG_OK(h, status)) { 583 netlink_process(h); 584 h = NLMSG_NEXT(h, status); 585 } 586 } 587 588 return TRUE; 589} 590 591static int 592netlink_open_socket() 593{ 594 int fd; 595 596 fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 597 if (fd < 0) { 598 plog(LLV_ERROR, LOCATION, NULL, 599 "socket(PF_NETLINK) failed: %s", 600 strerror(errno)); 601 return -1; 602 } 603 close_on_exec(fd); 604 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) 605 plog(LLV_WARNING, LOCATION, NULL, 606 "failed to put socket in non-blocking mode\n"); 607 608 return fd; 609} 610 611static int 612kernel_open_socket() 613{ 614 struct sockaddr_nl nl; 615 int fd; 616 617 if (netlink_fd < 0) { 618 netlink_fd = netlink_open_socket(); 619 if (netlink_fd < 0) 620 return -1; 621 } 622 623 fd = netlink_open_socket(); 624 if (fd < 0) 625 return fd; 626 627 /* We monitor IPv4 addresses using RTMGRP_IPV4_ROUTE group 628 * the get the RTN_LOCAL routes which are automatically added 629 * by kernel. This is because: 630 * - Linux kernel has a bug that calling bind() immediately 631 * after IPv4 RTM_NEWADDR event can fail 632 * - if IP is configured in multiple interfaces, we get 633 * RTM_DELADDR for each of them. RTN_LOCAL gets deleted only 634 * after the last IP address is deconfigured. 635 * The latter reason is also why I chose to use route 636 * notifications for IPv6. However, we do need to use RTM_NEWADDR 637 * for the link-local IPv6 addresses to get the interface index 638 * that is needed in bind(). 639 */ 640 memset(&nl, 0, sizeof(nl)); 641 nl.nl_family = AF_NETLINK; 642 nl.nl_groups = RTMGRP_IPV4_ROUTE 643#ifdef INET6 644 | RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE 645#endif 646 ; 647 if (bind(fd, (struct sockaddr*) &nl, sizeof(nl)) < 0) { 648 plog(LLV_ERROR, LOCATION, NULL, 649 "bind(PF_NETLINK) failed: %s\n", 650 strerror(errno)); 651 close(fd); 652 return -1; 653 } 654 return fd; 655} 656 657static void 658kernel_sync() 659{ 660 int fd = lcconf->rtsock; 661 662 /* refresh addresses */ 663 if (!netlink_enumerate(fd, PF_UNSPEC, RTM_GETROUTE)) { 664 plog(LLV_ERROR, LOCATION, NULL, 665 "unable to enumerate addresses: %s\n", 666 strerror(errno)); 667 } 668 while (kernel_receive(NULL, fd) == TRUE); 669 670#ifdef INET6 671 if (!netlink_enumerate(fd, PF_INET6, RTM_GETADDR)) { 672 plog(LLV_ERROR, LOCATION, NULL, 673 "unable to enumerate addresses: %s\n", 674 strerror(errno)); 675 } 676 while (kernel_receive(NULL, fd) == TRUE); 677#endif 678} 679 680#elif defined(USE_ROUTE) 681 682#define ROUNDUP(a) \ 683 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 684 685#define SAROUNDUP(X) ROUNDUP(((struct sockaddr *)(X))->sa_len) 686 687static size_t 688parse_address(start, end, dest) 689 caddr_t start; 690 caddr_t end; 691 struct sockaddr_storage *dest; 692{ 693 int len; 694 695 if (start >= end) 696 return 0; 697 698 len = SAROUNDUP(start); 699 if (start + len > end) 700 return end - start; 701 702 if (dest != NULL && len <= sizeof(struct sockaddr_storage)) 703 memcpy(dest, start, len); 704 705 return len; 706} 707 708static void 709parse_addresses(start, end, flags, addr) 710 caddr_t start; 711 caddr_t end; 712 int flags; 713 struct sockaddr_storage *addr; 714{ 715 memset(addr, 0, sizeof(*addr)); 716 if (flags & RTA_DST) 717 start += parse_address(start, end, NULL); 718 if (flags & RTA_GATEWAY) 719 start += parse_address(start, end, NULL); 720 if (flags & RTA_NETMASK) 721 start += parse_address(start, end, NULL); 722 if (flags & RTA_GENMASK) 723 start += parse_address(start, end, NULL); 724 if (flags & RTA_IFP) 725 start += parse_address(start, end, NULL); 726 if (flags & RTA_IFA) 727 start += parse_address(start, end, addr); 728 if (flags & RTA_AUTHOR) 729 start += parse_address(start, end, NULL); 730 if (flags & RTA_BRD) 731 start += parse_address(start, end, NULL); 732} 733 734static void 735kernel_handle_message(msg) 736 caddr_t msg; 737{ 738 struct rt_msghdr *rtm = (struct rt_msghdr *) msg; 739 struct ifa_msghdr *ifa = (struct ifa_msghdr *) msg; 740 struct sockaddr_storage addr; 741 742 switch (rtm->rtm_type) { 743 case RTM_NEWADDR: 744 parse_addresses(ifa + 1, msg + ifa->ifam_msglen, 745 ifa->ifam_addrs, &addr); 746 myaddr_open_all_configured((struct sockaddr *) &addr); 747 break; 748 case RTM_DELADDR: 749 parse_addresses(ifa + 1, msg + ifa->ifam_msglen, 750 ifa->ifam_addrs, &addr); 751 myaddr_close_all_open((struct sockaddr *) &addr); 752 break; 753 case RTM_ADD: 754 case RTM_DELETE: 755 case RTM_CHANGE: 756 case RTM_MISS: 757 case RTM_IFINFO: 758#ifdef RTM_OIFINFO 759 case RTM_OIFINFO: 760#endif 761#ifdef RTM_NEWMADDR 762 case RTM_NEWMADDR: 763 case RTM_DELMADDR: 764#endif 765#ifdef RTM_IFANNOUNCE 766 case RTM_IFANNOUNCE: 767#endif 768 break; 769 default: 770 plog(LLV_WARNING, LOCATION, NULL, 771 "unrecognized route message with rtm_type: %d", 772 rtm->rtm_type); 773 break; 774 } 775} 776 777static int 778kernel_receive(ctx, fd) 779 void *ctx; 780 int fd; 781{ 782 char buf[16*1024]; 783 struct rt_msghdr *rtm = (struct rt_msghdr *) buf; 784 int len; 785 786 len = read(fd, &buf, sizeof(buf)); 787 if (len <= 0) { 788 if (len < 0 && errno != EWOULDBLOCK && errno != EAGAIN) 789 plog(LLV_WARNING, LOCATION, NULL, 790 "routing socket error: %s", strerror(errno)); 791 return FALSE; 792 } 793 794 if (rtm->rtm_msglen != len) { 795 plog(LLV_WARNING, LOCATION, NULL, 796 "kernel_receive: rtm->rtm_msglen %d, len %d, type %d\n", 797 rtm->rtm_msglen, len, rtm->rtm_type); 798 return FALSE; 799 } 800 801 kernel_handle_message(buf); 802 return TRUE; 803} 804 805static int 806kernel_open_socket() 807{ 808 int fd; 809 810 fd = socket(PF_ROUTE, SOCK_RAW, 0); 811 if (fd < 0) { 812 plog(LLV_ERROR, LOCATION, NULL, 813 "socket(PF_ROUTE) failed: %s", 814 strerror(errno)); 815 return -1; 816 } 817 close_on_exec(fd); 818 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) 819 plog(LLV_WARNING, LOCATION, NULL, 820 "failed to put socket in non-blocking mode\n"); 821 822 return fd; 823} 824 825static void 826kernel_sync() 827{ 828 caddr_t ref, buf, end; 829 size_t bufsiz; 830 struct if_msghdr *ifm; 831 struct interface *ifp; 832 833#define MIBSIZ 6 834 int mib[MIBSIZ] = { 835 CTL_NET, 836 PF_ROUTE, 837 0, 838 0, /* AF_INET & AF_INET6 */ 839 NET_RT_IFLIST, 840 0 841 }; 842 843 if (sysctl(mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) { 844 plog(LLV_WARNING, LOCATION, NULL, 845 "sysctl() error: %s", strerror(errno)); 846 return; 847 } 848 849 ref = buf = racoon_malloc(bufsiz); 850 851 if (sysctl(mib, MIBSIZ, buf, &bufsiz, NULL, 0) >= 0) { 852 /* Parse both interfaces and addresses. */ 853 for (end = buf + bufsiz; buf < end; buf += ifm->ifm_msglen) { 854 ifm = (struct if_msghdr *) buf; 855 kernel_handle_message(buf); 856 } 857 } else { 858 plog(LLV_WARNING, LOCATION, NULL, 859 "sysctl() error: %s", strerror(errno)); 860 } 861 862 racoon_free(ref); 863} 864 865#else 866 867#error No supported interface to monitor local addresses. 868 869#endif 870