1 /* $NetBSD: grabmyaddr.c,v 1.28 2011/03/14 17:18:12 tteras Exp $ */ 2 /* 3 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 4 * Copyright (C) 2008 Timo Teras <timo.teras (at) 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 70 static int kernel_receive __P((void *ctx, int fd)); 71 static int kernel_open_socket __P((void)); 72 static void kernel_sync __P((void)); 73 74 struct myaddr { 75 LIST_ENTRY(myaddr) chain; 76 struct sockaddr_storage addr; 77 int fd; 78 int udp_encap; 79 }; 80 81 static LIST_HEAD(_myaddr_list_, myaddr) configured, opened; 82 83 static void 84 myaddr_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 93 static int 94 myaddr_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 110 static int 111 myaddr_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 138 static int 139 myaddr_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 180 static void 181 myaddr_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 197 static void 198 myaddr_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 209 void 210 myaddr_flush() 211 { 212 myaddr_flush_list(&configured); 213 } 214 215 int 216 myaddr_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 240 void 241 myaddr_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 258 int 259 myaddr_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 272 int 273 myaddr_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 PORT_ISAKMP; 284 } 285 286 void 287 myaddr_init_lists() 288 { 289 LIST_INIT(&configured); 290 LIST_INIT(&opened); 291 } 292 293 int 294 myaddr_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 309 void 310 myaddr_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 322 static int netlink_fd = -1; 323 324 #define NLMSG_TAIL(nmsg) \ 325 ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) 326 327 static void 328 parse_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 338 static int 339 netlink_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 356 static int 357 netlink_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 384 static void 385 netlink_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 399 static int 400 netlink_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 435 static int 436 netlink_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 471 static int 472 netlink_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 534 static int 535 netlink_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 550 static int 551 kernel_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 591 static int 592 netlink_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 611 static int 612 kernel_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 657 static void 658 kernel_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 687 static size_t 688 parse_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 708 static void 709 parse_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 734 static void 735 kernel_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 777 static int 778 kernel_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 805 static int 806 kernel_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 825 static void 826 kernel_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