1 /** 2 * Copyright (C) 2017 Hans Dedecker <dedeckeh@gmail.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License v2 as published by 6 * the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 */ 14 15 #include <errno.h> 16 #include <string.h> 17 #include <syslog.h> 18 19 #include <linux/netlink.h> 20 #include <linux/if_addr.h> 21 #include <linux/neighbour.h> 22 #include <linux/rtnetlink.h> 23 24 #include <netlink/msg.h> 25 #include <netlink/socket.h> 26 #include <netlink/attr.h> 27 28 #include <arpa/inet.h> 29 #include <libubox/list.h> 30 31 #include "odhcpd.h" 32 33 struct event_socket { 34 struct odhcpd_event ev; 35 struct nl_sock *sock; 36 int sock_bufsize; 37 }; 38 39 static void handle_rtnl_event(struct odhcpd_event *ev); 40 static int cb_rtnl_valid(struct nl_msg *msg, void *arg); 41 static void catch_rtnl_err(struct odhcpd_event *e, int error); 42 static struct nl_sock *create_socket(int protocol); 43 44 static struct nl_sock *rtnl_socket = NULL; 45 struct list_head netevent_handler_list = LIST_HEAD_INIT(netevent_handler_list); 46 static struct event_socket rtnl_event = { 47 .ev = { 48 .uloop = {.fd = - 1, }, 49 .handle_dgram = NULL, 50 .handle_error = catch_rtnl_err, 51 .recv_msgs = handle_rtnl_event, 52 }, 53 .sock = NULL, 54 .sock_bufsize = 133120, 55 }; 56 57 int netlink_init(void) 58 { 59 rtnl_socket = create_socket(NETLINK_ROUTE); 60 if (!rtnl_socket) { 61 syslog(LOG_ERR, "Unable to open nl socket: %m"); 62 goto err; 63 } 64 65 rtnl_event.sock = create_socket(NETLINK_ROUTE); 66 if (!rtnl_event.sock) { 67 syslog(LOG_ERR, "Unable to open nl event socket: %m"); 68 goto err; 69 } 70 71 rtnl_event.ev.uloop.fd = nl_socket_get_fd(rtnl_event.sock); 72 73 if (nl_socket_set_buffer_size(rtnl_event.sock, rtnl_event.sock_bufsize, 0)) 74 goto err; 75 76 nl_socket_disable_seq_check(rtnl_event.sock); 77 78 nl_socket_modify_cb(rtnl_event.sock, NL_CB_VALID, NL_CB_CUSTOM, 79 cb_rtnl_valid, NULL); 80 81 /* Receive IPv4 address, IPv6 address, IPv6 routes and neighbor events */ 82 if (nl_socket_add_memberships(rtnl_event.sock, RTNLGRP_IPV4_IFADDR, 83 RTNLGRP_IPV6_IFADDR, RTNLGRP_IPV6_ROUTE, 84 RTNLGRP_NEIGH, RTNLGRP_LINK, 0)) 85 goto err; 86 87 odhcpd_register(&rtnl_event.ev); 88 89 return 0; 90 91 err: 92 if (rtnl_socket) { 93 nl_socket_free(rtnl_socket); 94 rtnl_socket = NULL; 95 } 96 97 if (rtnl_event.sock) { 98 nl_socket_free(rtnl_event.sock); 99 rtnl_event.sock = NULL; 100 rtnl_event.ev.uloop.fd = -1; 101 } 102 103 return -1; 104 } 105 106 107 int netlink_add_netevent_handler(struct netevent_handler *handler) 108 { 109 if (!handler->cb) 110 return -1; 111 112 list_add(&handler->head, &netevent_handler_list); 113 114 return 0; 115 } 116 117 static void call_netevent_handler_list(unsigned long event, struct netevent_handler_info *info) 118 { 119 struct netevent_handler *handler; 120 121 list_for_each_entry(handler, &netevent_handler_list, head) 122 handler->cb(event, info); 123 } 124 125 static void handle_rtnl_event(struct odhcpd_event *e) 126 { 127 struct event_socket *ev_sock = container_of(e, struct event_socket, ev); 128 129 nl_recvmsgs_default(ev_sock->sock); 130 } 131 132 static void refresh_iface_addr4(int ifindex) 133 { 134 struct odhcpd_ipaddr *addr = NULL; 135 struct interface *iface; 136 ssize_t len = netlink_get_interface_addrs(ifindex, false, &addr); 137 bool change = false; 138 139 if (len < 0) 140 return; 141 142 avl_for_each_element(&interfaces, iface, avl) { 143 struct netevent_handler_info event_info; 144 145 if (iface->ifindex != ifindex) 146 continue; 147 148 memset(&event_info, 0, sizeof(event_info)); 149 event_info.iface = iface; 150 event_info.addrs_old.addrs = iface->addr4; 151 event_info.addrs_old.len = iface->addr4_len; 152 153 if (!change) { 154 change = len != (ssize_t)iface->addr4_len; 155 for (ssize_t i = 0; !change && i < len; ++i) { 156 if (addr[i].addr.in.s_addr != iface->addr4[i].addr.in.s_addr) 157 change = true; 158 } 159 } 160 161 iface->addr4 = addr; 162 iface->addr4_len = len; 163 164 if (change) 165 call_netevent_handler_list(NETEV_ADDRLIST_CHANGE, &event_info); 166 167 free(event_info.addrs_old.addrs); 168 169 if (!len) 170 continue; 171 172 addr = malloc(len * sizeof(*addr)); 173 if (!addr) 174 break; 175 176 memcpy(addr, iface->addr4, len * sizeof(*addr)); 177 } 178 179 free(addr); 180 } 181 182 static void refresh_iface_addr6(int ifindex) 183 { 184 struct odhcpd_ipaddr *addr = NULL; 185 struct interface *iface; 186 ssize_t len = netlink_get_interface_addrs(ifindex, true, &addr); 187 time_t now = odhcpd_time(); 188 bool change = false; 189 190 if (len < 0) 191 return; 192 193 avl_for_each_element(&interfaces, iface, avl) { 194 struct netevent_handler_info event_info; 195 196 if (iface->ifindex != ifindex) 197 continue; 198 199 memset(&event_info, 0, sizeof(event_info)); 200 event_info.iface = iface; 201 event_info.addrs_old.addrs = iface->addr6; 202 event_info.addrs_old.len = iface->addr6_len; 203 204 if (!change) { 205 change = len != (ssize_t)iface->addr6_len; 206 for (ssize_t i = 0; !change && i < len; ++i) { 207 if (!IN6_ARE_ADDR_EQUAL(&addr[i].addr.in6, &iface->addr6[i].addr.in6) || 208 addr[i].prefix != iface->addr6[i].prefix || 209 (addr[i].preferred_lt > (uint32_t)now) != (iface->addr6[i].preferred_lt > (uint32_t)now) || 210 addr[i].valid_lt < iface->addr6[i].valid_lt || addr[i].preferred_lt < iface->addr6[i].preferred_lt) 211 change = true; 212 } 213 214 if (change) { 215 /* 216 * Keep track of removed prefixes, so we could advertise them as invalid 217 * for at least a couple of times. 218 * 219 * RFC7084 ยง 4.3 : 220 * L-13: If the delegated prefix changes, i.e., the current prefix is 221 * replaced with a new prefix without any overlapping time 222 * period, then the IPv6 CE router MUST immediately advertise the 223 * old prefix with a Preferred Lifetime of zero and a Valid 224 * Lifetime of either a) zero or b) the lower of the current 225 * Valid Lifetime and two hours (which must be decremented in 226 * real time) in a Router Advertisement message as described in 227 * Section 5.5.3, (e) of [RFC4862]. 228 */ 229 230 for (size_t i = 0; i < iface->addr6_len; ++i) { 231 bool removed = true; 232 233 if (iface->addr6[i].valid_lt <= (uint32_t)now) 234 continue; 235 236 for (ssize_t j = 0; removed && j < len; ++j) { 237 size_t plen = min(addr[j].prefix, iface->addr6[i].prefix); 238 239 if (odhcpd_bmemcmp(&addr[j].addr.in6, &iface->addr6[i].addr.in6, plen) == 0) 240 removed = false; 241 } 242 243 for (size_t j = 0; removed && j < iface->invalid_addr6_len; ++j) { 244 size_t plen = min(iface->invalid_addr6[j].prefix, iface->addr6[i].prefix); 245 246 if (odhcpd_bmemcmp(&iface->invalid_addr6[j].addr.in6, &iface->addr6[i].addr.in6, plen) == 0) 247 removed = false; 248 } 249 250 if (removed) { 251 size_t pos = iface->invalid_addr6_len; 252 struct odhcpd_ipaddr *new_invalid_addr6 = realloc(iface->invalid_addr6, 253 sizeof(*iface->invalid_addr6) * (pos + 1)); 254 255 if (!new_invalid_addr6) 256 break; 257 258 iface->invalid_addr6 = new_invalid_addr6; 259 iface->invalid_addr6_len++; 260 memcpy(&iface->invalid_addr6[pos], &iface->addr6[i], sizeof(*iface->invalid_addr6)); 261 iface->invalid_addr6[pos].valid_lt = iface->invalid_addr6[pos].preferred_lt = (uint32_t)now; 262 263 if (iface->invalid_addr6[pos].prefix < 64) 264 iface->invalid_addr6[pos].prefix = 64; 265 } 266 } 267 } 268 } 269 270 iface->addr6 = addr; 271 iface->addr6_len = len; 272 273 if (change) 274 call_netevent_handler_list(NETEV_ADDR6LIST_CHANGE, &event_info); 275 276 free(event_info.addrs_old.addrs); 277 278 if (!len) 279 continue; 280 281 addr = malloc(len * sizeof(*addr)); 282 if (!addr) 283 break; 284 285 memcpy(addr, iface->addr6, len * sizeof(*addr)); 286 } 287 288 free(addr); 289 } 290 291 static int handle_rtm_link(struct nlmsghdr *hdr) 292 { 293 struct ifinfomsg *ifi = nlmsg_data(hdr); 294 struct nlattr *nla[__IFLA_MAX]; 295 struct interface *iface; 296 struct netevent_handler_info event_info; 297 const char *ifname; 298 299 memset(&event_info, 0, sizeof(event_info)); 300 301 if (!nlmsg_valid_hdr(hdr, sizeof(*ifi)) || ifi->ifi_family != AF_UNSPEC) 302 return NL_SKIP; 303 304 nlmsg_parse(hdr, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL); 305 if (!nla[IFLA_IFNAME]) 306 return NL_SKIP; 307 308 ifname = nla_get_string(nla[IFLA_IFNAME]); 309 310 avl_for_each_element(&interfaces, iface, avl) { 311 if (strcmp(iface->ifname, ifname)) 312 continue; 313 314 iface->ifflags = ifi->ifi_flags; 315 316 /* 317 * Assume for link event of the same index, that link changed 318 * and reload services to enable or disable them based on the 319 * RUNNING state of the interface. 320 */ 321 if (iface->ifindex == ifi->ifi_index) { 322 reload_services(iface); 323 continue; 324 } 325 326 iface->ifindex = ifi->ifi_index; 327 event_info.iface = iface; 328 call_netevent_handler_list(NETEV_IFINDEX_CHANGE, &event_info); 329 } 330 331 return NL_OK; 332 } 333 334 static int handle_rtm_route(struct nlmsghdr *hdr, bool add) 335 { 336 struct rtmsg *rtm = nlmsg_data(hdr); 337 struct nlattr *nla[__RTA_MAX]; 338 struct interface *iface; 339 struct netevent_handler_info event_info; 340 int ifindex = 0; 341 342 if (!nlmsg_valid_hdr(hdr, sizeof(*rtm)) || rtm->rtm_family != AF_INET6) 343 return NL_SKIP; 344 345 nlmsg_parse(hdr, sizeof(*rtm), nla, __RTA_MAX - 1, NULL); 346 347 memset(&event_info, 0, sizeof(event_info)); 348 event_info.rt.dst_len = rtm->rtm_dst_len; 349 350 if (nla[RTA_DST]) 351 nla_memcpy(&event_info.rt.dst, nla[RTA_DST], 352 sizeof(event_info.rt.dst)); 353 354 if (nla[RTA_OIF]) 355 ifindex = nla_get_u32(nla[RTA_OIF]); 356 357 if (nla[RTA_GATEWAY]) 358 nla_memcpy(&event_info.rt.gateway, nla[RTA_GATEWAY], 359 sizeof(event_info.rt.gateway)); 360 361 avl_for_each_element(&interfaces, iface, avl) { 362 if (ifindex && iface->ifindex != ifindex) 363 continue; 364 365 event_info.iface = ifindex ? iface : NULL; 366 call_netevent_handler_list(add ? NETEV_ROUTE6_ADD : NETEV_ROUTE6_DEL, 367 &event_info); 368 } 369 370 return NL_OK; 371 } 372 373 static int handle_rtm_addr(struct nlmsghdr *hdr, bool add) 374 { 375 struct ifaddrmsg *ifa = nlmsg_data(hdr); 376 struct nlattr *nla[__IFA_MAX]; 377 struct interface *iface; 378 struct netevent_handler_info event_info; 379 char buf[INET6_ADDRSTRLEN]; 380 381 if (!nlmsg_valid_hdr(hdr, sizeof(*ifa)) || 382 (ifa->ifa_family != AF_INET6 && 383 ifa->ifa_family != AF_INET)) 384 return NL_SKIP; 385 386 memset(&event_info, 0, sizeof(event_info)); 387 388 nlmsg_parse(hdr, sizeof(*ifa), nla, __IFA_MAX - 1, NULL); 389 390 if (ifa->ifa_family == AF_INET6) { 391 if (!nla[IFA_ADDRESS]) 392 return NL_SKIP; 393 394 nla_memcpy(&event_info.addr, nla[IFA_ADDRESS], sizeof(event_info.addr)); 395 396 if (IN6_IS_ADDR_MULTICAST(&event_info.addr)) 397 return NL_SKIP; 398 399 inet_ntop(AF_INET6, &event_info.addr, buf, sizeof(buf)); 400 401 avl_for_each_element(&interfaces, iface, avl) { 402 if (iface->ifindex != (int)ifa->ifa_index) 403 continue; 404 405 if (add && IN6_IS_ADDR_LINKLOCAL(&event_info.addr)) { 406 iface->have_link_local = true; 407 return NL_SKIP; 408 } 409 410 syslog(LOG_DEBUG, "Netlink %s %s on %s", add ? "newaddr" : "deladdr", 411 buf, iface->name); 412 413 event_info.iface = iface; 414 call_netevent_handler_list(add ? NETEV_ADDR6_ADD : NETEV_ADDR6_DEL, 415 &event_info); 416 } 417 418 refresh_iface_addr6(ifa->ifa_index); 419 } else { 420 if (!nla[IFA_LOCAL]) 421 return NL_SKIP; 422 423 nla_memcpy(&event_info.addr, nla[IFA_LOCAL], sizeof(event_info.addr)); 424 425 inet_ntop(AF_INET, &event_info.addr, buf, sizeof(buf)); 426 427 avl_for_each_element(&interfaces, iface, avl) { 428 if (iface->ifindex != (int)ifa->ifa_index) 429 continue; 430 431 syslog(LOG_DEBUG, "Netlink %s %s on %s", add ? "newaddr" : "deladdr", 432 buf, iface->name); 433 434 event_info.iface = iface; 435 call_netevent_handler_list(add ? NETEV_ADDR_ADD : NETEV_ADDR_DEL, 436 &event_info); 437 } 438 439 refresh_iface_addr4(ifa->ifa_index); 440 } 441 442 return NL_OK; 443 } 444 445 static int handle_rtm_neigh(struct nlmsghdr *hdr, bool add) 446 { 447 struct ndmsg *ndm = nlmsg_data(hdr); 448 struct nlattr *nla[__NDA_MAX]; 449 struct interface *iface; 450 struct netevent_handler_info event_info; 451 char buf[INET6_ADDRSTRLEN]; 452 453 if (!nlmsg_valid_hdr(hdr, sizeof(*ndm)) || 454 ndm->ndm_family != AF_INET6) 455 return NL_SKIP; 456 457 nlmsg_parse(hdr, sizeof(*ndm), nla, __NDA_MAX - 1, NULL); 458 if (!nla[NDA_DST]) 459 return NL_SKIP; 460 461 memset(&event_info, 0, sizeof(event_info)); 462 463 nla_memcpy(&event_info.neigh.dst, nla[NDA_DST], sizeof(event_info.neigh.dst)); 464 465 if (IN6_IS_ADDR_LINKLOCAL(&event_info.neigh.dst) || 466 IN6_IS_ADDR_MULTICAST(&event_info.neigh.dst)) 467 return NL_SKIP; 468 469 inet_ntop(AF_INET6, &event_info.neigh.dst, buf, sizeof(buf)); 470 471 avl_for_each_element(&interfaces, iface, avl) { 472 if (iface->ifindex != ndm->ndm_ifindex) 473 continue; 474 475 syslog(LOG_DEBUG, "Netlink %s %s on %s", true ? "newneigh" : "delneigh", 476 buf, iface->name); 477 478 event_info.iface = iface; 479 event_info.neigh.state = ndm->ndm_state; 480 event_info.neigh.flags = ndm->ndm_flags; 481 482 call_netevent_handler_list(add ? NETEV_NEIGH6_ADD : NETEV_NEIGH6_DEL, 483 &event_info); 484 } 485 486 return NL_OK; 487 } 488 489 /* Handler for neighbor cache entries from the kernel. This is our source 490 * to learn and unlearn hosts on interfaces. */ 491 static int cb_rtnl_valid(struct nl_msg *msg, _unused void *arg) 492 { 493 struct nlmsghdr *hdr = nlmsg_hdr(msg); 494 int ret = NL_SKIP; 495 bool add = false; 496 497 switch (hdr->nlmsg_type) { 498 case RTM_NEWLINK: 499 ret = handle_rtm_link(hdr); 500 break; 501 502 case RTM_NEWROUTE: 503 add = true; 504 /* fall through */ 505 case RTM_DELROUTE: 506 ret = handle_rtm_route(hdr, add); 507 break; 508 509 case RTM_NEWADDR: 510 add = true; 511 /* fall through */ 512 case RTM_DELADDR: 513 ret = handle_rtm_addr(hdr, add); 514 break; 515 516 case RTM_NEWNEIGH: 517 add = true; 518 /* fall through */ 519 case RTM_DELNEIGH: 520 ret = handle_rtm_neigh(hdr, add); 521 break; 522 523 default: 524 break; 525 } 526 527 return ret; 528 } 529 530 static void catch_rtnl_err(struct odhcpd_event *e, int error) 531 { 532 struct event_socket *ev_sock = container_of(e, struct event_socket, ev); 533 534 if (error != ENOBUFS) 535 goto err; 536 537 /* Double netlink event buffer size */ 538 ev_sock->sock_bufsize *= 2; 539 540 if (nl_socket_set_buffer_size(ev_sock->sock, ev_sock->sock_bufsize, 0)) 541 goto err; 542 543 netlink_dump_addr_table(true); 544 return; 545 546 err: 547 odhcpd_deregister(e); 548 } 549 550 static struct nl_sock *create_socket(int protocol) 551 { 552 struct nl_sock *nl_sock; 553 554 nl_sock = nl_socket_alloc(); 555 if (!nl_sock) 556 goto err; 557 558 if (nl_connect(nl_sock, protocol) < 0) 559 goto err; 560 561 return nl_sock; 562 563 err: 564 if (nl_sock) 565 nl_socket_free(nl_sock); 566 567 return NULL; 568 } 569 570 571 struct addr_info { 572 int ifindex; 573 int af; 574 struct odhcpd_ipaddr **addrs; 575 int pending; 576 ssize_t ret; 577 }; 578 579 580 static int cb_addr_valid(struct nl_msg *msg, void *arg) 581 { 582 struct addr_info *ctxt = (struct addr_info *)arg; 583 struct odhcpd_ipaddr *addrs = *(ctxt->addrs); 584 struct nlmsghdr *hdr = nlmsg_hdr(msg); 585 struct ifaddrmsg *ifa; 586 struct nlattr *nla[__IFA_MAX], *nla_addr = NULL; 587 588 if (hdr->nlmsg_type != RTM_NEWADDR) 589 return NL_SKIP; 590 591 ifa = NLMSG_DATA(hdr); 592 if (ifa->ifa_scope != RT_SCOPE_UNIVERSE || 593 (ctxt->af != ifa->ifa_family) || 594 (ctxt->ifindex && ifa->ifa_index != (unsigned)ctxt->ifindex)) 595 return NL_SKIP; 596 597 nlmsg_parse(hdr, sizeof(*ifa), nla, __IFA_MAX - 1, NULL); 598 599 switch (ifa->ifa_family) { 600 case AF_INET6: 601 if (nla[IFA_ADDRESS]) 602 nla_addr = nla[IFA_ADDRESS]; 603 break; 604 605 case AF_INET: 606 if (nla[IFA_LOCAL]) 607 nla_addr = nla[IFA_LOCAL]; 608 break; 609 610 default: 611 break; 612 } 613 if (!nla_addr) 614 return NL_SKIP; 615 616 addrs = realloc(addrs, sizeof(*addrs)*(ctxt->ret + 1)); 617 if (!addrs) 618 return NL_SKIP; 619 620 memset(&addrs[ctxt->ret], 0, sizeof(addrs[ctxt->ret])); 621 addrs[ctxt->ret].prefix = ifa->ifa_prefixlen; 622 623 nla_memcpy(&addrs[ctxt->ret].addr, nla_addr, 624 sizeof(addrs[ctxt->ret].addr)); 625 626 if (nla[IFA_BROADCAST]) 627 nla_memcpy(&addrs[ctxt->ret].broadcast, nla[IFA_BROADCAST], 628 sizeof(addrs[ctxt->ret].broadcast)); 629 630 if (nla[IFA_CACHEINFO]) { 631 struct ifa_cacheinfo *ifc = nla_data(nla[IFA_CACHEINFO]); 632 633 addrs[ctxt->ret].preferred_lt = ifc->ifa_prefered; 634 addrs[ctxt->ret].valid_lt = ifc->ifa_valid; 635 } 636 637 if (ifa->ifa_flags & IFA_F_DEPRECATED) 638 addrs[ctxt->ret].preferred_lt = 0; 639 640 if (ifa->ifa_family == AF_INET6 && 641 ifa->ifa_flags & IFA_F_TENTATIVE) 642 addrs[ctxt->ret].tentative = true; 643 644 ctxt->ret++; 645 *(ctxt->addrs) = addrs; 646 647 return NL_OK; 648 } 649 650 651 static int cb_addr_finish(_unused struct nl_msg *msg, void *arg) 652 { 653 struct addr_info *ctxt = (struct addr_info *)arg; 654 655 ctxt->pending = 0; 656 657 return NL_STOP; 658 } 659 660 661 static int cb_addr_error(_unused struct sockaddr_nl *nla, struct nlmsgerr *err, 662 void *arg) 663 { 664 struct addr_info *ctxt = (struct addr_info *)arg; 665 666 ctxt->pending = 0; 667 ctxt->ret = err->error; 668 669 return NL_STOP; 670 } 671 672 673 static int prefix_cmp(const void *va, const void *vb) 674 { 675 const struct odhcpd_ipaddr *a = va, *b = vb; 676 int ret = 0; 677 678 if (a->prefix == b->prefix) { 679 ret = (ntohl(a->addr.in.s_addr) < ntohl(b->addr.in.s_addr)) ? 1 : 680 (ntohl(a->addr.in.s_addr) > ntohl(b->addr.in.s_addr)) ? -1 : 0; 681 } else 682 ret = a->prefix < b->prefix ? 1 : -1; 683 684 return ret; 685 } 686 687 688 /* compare IPv6 prefixes */ 689 static int prefix6_cmp(const void *va, const void *vb) 690 { 691 const struct odhcpd_ipaddr *a = va, *b = vb; 692 uint32_t a_pref_lt = IN6_IS_ADDR_ULA(&a->addr.in6) ? 1 : a->preferred_lt; 693 uint32_t b_pref_lt = IN6_IS_ADDR_ULA(&b->addr.in6) ? 1 : b->preferred_lt; 694 return (a_pref_lt < b_pref_lt) ? 1 : (a_pref_lt > b_pref_lt) ? -1 : 0; 695 } 696 697 698 /* Detect an IPV6-address currently assigned to the given interface */ 699 ssize_t netlink_get_interface_addrs(int ifindex, bool v6, struct odhcpd_ipaddr **addrs) 700 { 701 struct nl_msg *msg; 702 struct ifaddrmsg ifa = { 703 .ifa_family = v6? AF_INET6: AF_INET, 704 .ifa_prefixlen = 0, 705 .ifa_flags = 0, 706 .ifa_scope = 0, 707 .ifa_index = ifindex, }; 708 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); 709 struct addr_info ctxt = { 710 .ifindex = ifindex, 711 .af = v6? AF_INET6: AF_INET, 712 .addrs = addrs, 713 .ret = 0, 714 .pending = 1, 715 }; 716 717 if (!cb) { 718 ctxt.ret = -1; 719 goto out; 720 } 721 722 msg = nlmsg_alloc_simple(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP); 723 724 if (!msg) { 725 ctxt.ret = - 1; 726 goto out; 727 } 728 729 nlmsg_append(msg, &ifa, sizeof(ifa), 0); 730 731 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_addr_valid, &ctxt); 732 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_addr_finish, &ctxt); 733 nl_cb_err(cb, NL_CB_CUSTOM, cb_addr_error, &ctxt); 734 735 ctxt.ret = nl_send_auto_complete(rtnl_socket, msg); 736 if (ctxt.ret < 0) 737 goto free; 738 739 ctxt.ret = 0; 740 while (ctxt.pending > 0) 741 nl_recvmsgs(rtnl_socket, cb); 742 743 if (ctxt.ret <= 0) 744 goto free; 745 746 time_t now = odhcpd_time(); 747 struct odhcpd_ipaddr *addr = *addrs; 748 749 qsort(addr, ctxt.ret, sizeof(*addr), v6 ? prefix6_cmp : prefix_cmp); 750 751 for (ssize_t i = 0; i < ctxt.ret; ++i) { 752 if (addr[i].preferred_lt < UINT32_MAX - now) 753 addr[i].preferred_lt += now; 754 755 if (addr[i].valid_lt < UINT32_MAX - now) 756 addr[i].valid_lt += now; 757 } 758 759 free: 760 nlmsg_free(msg); 761 out: 762 nl_cb_put(cb); 763 764 return ctxt.ret; 765 } 766 767 768 static int cb_linklocal_valid(struct nl_msg *msg, void *arg) 769 { 770 struct addr_info *ctxt = (struct addr_info *)arg; 771 struct odhcpd_ipaddr *addrs = *(ctxt->addrs); 772 struct nlmsghdr *hdr = nlmsg_hdr(msg); 773 struct ifaddrmsg *ifa; 774 struct nlattr *nla[__IFA_MAX], *nla_addr = NULL; 775 struct in6_addr addr; 776 777 if (hdr->nlmsg_type != RTM_NEWADDR) 778 return NL_SKIP; 779 780 ifa = NLMSG_DATA(hdr); 781 if (ifa->ifa_scope != RT_SCOPE_LINK || 782 (ctxt->af != ifa->ifa_family) || 783 (ctxt->ifindex && ifa->ifa_index != (unsigned)ctxt->ifindex)) 784 return NL_SKIP; 785 786 nlmsg_parse(hdr, sizeof(*ifa), nla, __IFA_MAX - 1, NULL); 787 788 switch (ifa->ifa_family) { 789 case AF_INET6: 790 if (nla[IFA_ADDRESS]) 791 nla_addr = nla[IFA_ADDRESS]; 792 break; 793 794 default: 795 break; 796 } 797 if (!nla_addr) 798 return NL_SKIP; 799 800 nla_memcpy(&addr, nla_addr, sizeof(addr)); 801 802 if (!IN6_IS_ADDR_LINKLOCAL(&addr)) 803 return NL_SKIP; 804 805 addrs = realloc(addrs, sizeof(*addrs)*(ctxt->ret + 1)); 806 if (!addrs) 807 return NL_SKIP; 808 809 memset(&addrs[ctxt->ret], 0, sizeof(addrs[ctxt->ret])); 810 811 addrs = realloc(addrs, sizeof(*addrs)*(ctxt->ret + 1)); 812 if (!addrs) 813 return NL_SKIP; 814 815 816 memcpy(&addrs[ctxt->ret].addr, &addr, sizeof(addrs[ctxt->ret].addr)); 817 818 if (ifa->ifa_flags & IFA_F_TENTATIVE) 819 addrs[ctxt->ret].tentative = true; 820 821 ctxt->ret++; 822 *(ctxt->addrs) = addrs; 823 824 return NL_OK; 825 } 826 827 828 static int cb_linklocal_finish(_unused struct nl_msg *msg, void *arg) 829 { 830 struct addr_info *ctxt = (struct addr_info *)arg; 831 832 ctxt->pending = 0; 833 834 return NL_STOP; 835 } 836 837 838 static int cb_linklocal_error(_unused struct sockaddr_nl *nla, struct nlmsgerr *err, 839 void *arg) 840 { 841 struct addr_info *ctxt = (struct addr_info *)arg; 842 843 ctxt->pending = 0; 844 ctxt->ret = err->error; 845 846 return NL_STOP; 847 } 848 849 850 /* Detect a link local IPV6-address currently assigned to the given interface */ 851 ssize_t netlink_get_interface_linklocal(int ifindex, struct odhcpd_ipaddr **addrs) 852 { 853 struct nl_msg *msg; 854 struct ifaddrmsg ifa = { 855 .ifa_family = AF_INET6, 856 .ifa_prefixlen = 0, 857 .ifa_flags = 0, 858 .ifa_scope = 0, 859 .ifa_index = ifindex, }; 860 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); 861 struct addr_info ctxt = { 862 .ifindex = ifindex, 863 .af = AF_INET6, 864 .addrs = addrs, 865 .ret = 0, 866 .pending = 1, 867 }; 868 869 if (!cb) { 870 ctxt.ret = -1; 871 goto out; 872 } 873 874 msg = nlmsg_alloc_simple(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP); 875 876 if (!msg) { 877 ctxt.ret = - 1; 878 goto out; 879 } 880 881 nlmsg_append(msg, &ifa, sizeof(ifa), 0); 882 883 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_linklocal_valid, &ctxt); 884 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_linklocal_finish, &ctxt); 885 nl_cb_err(cb, NL_CB_CUSTOM, cb_linklocal_error, &ctxt); 886 887 ctxt.ret = nl_send_auto_complete(rtnl_socket, msg); 888 if (ctxt.ret < 0) 889 goto free; 890 891 ctxt.ret = 0; 892 while (ctxt.pending > 0) 893 nl_recvmsgs(rtnl_socket, cb); 894 895 if (ctxt.ret <= 0) 896 goto free; 897 898 free: 899 nlmsg_free(msg); 900 out: 901 nl_cb_put(cb); 902 903 return ctxt.ret; 904 } 905 906 907 struct neigh_info { 908 int ifindex; 909 int pending; 910 const struct in6_addr *addr; 911 int ret; 912 }; 913 914 915 static int cb_proxy_neigh_valid(struct nl_msg *msg, void *arg) 916 { 917 struct neigh_info *ctxt = (struct neigh_info *)arg; 918 struct nlmsghdr *hdr = nlmsg_hdr(msg); 919 struct ndmsg *ndm; 920 struct nlattr *nla_dst; 921 922 if (hdr->nlmsg_type != RTM_NEWNEIGH) 923 return NL_SKIP; 924 925 ndm = NLMSG_DATA(hdr); 926 if (ndm->ndm_family != AF_INET6 || 927 (ctxt->ifindex && ndm->ndm_ifindex != ctxt->ifindex)) 928 return NL_SKIP; 929 930 if (!(ndm->ndm_flags & NTF_PROXY)) 931 return NL_SKIP; 932 933 nla_dst = nlmsg_find_attr(hdr, sizeof(*ndm), NDA_DST); 934 if (!nla_dst) 935 return NL_SKIP; 936 937 if (nla_memcmp(nla_dst,ctxt->addr, 16) == 0) 938 ctxt->ret = 1; 939 940 return NL_OK; 941 } 942 943 944 static int cb_proxy_neigh_finish(_unused struct nl_msg *msg, void *arg) 945 { 946 struct neigh_info *ctxt = (struct neigh_info *)arg; 947 948 ctxt->pending = 0; 949 950 return NL_STOP; 951 } 952 953 954 static int cb_proxy_neigh_error(_unused struct sockaddr_nl *nla, struct nlmsgerr *err, 955 void *arg) 956 { 957 struct neigh_info *ctxt = (struct neigh_info *)arg; 958 959 ctxt->pending = 0; 960 ctxt->ret = err->error; 961 962 return NL_STOP; 963 } 964 965 /* Detect an IPV6-address proxy neighbor for the given interface */ 966 int netlink_get_interface_proxy_neigh(int ifindex, const struct in6_addr *addr) 967 { 968 struct nl_msg *msg; 969 struct ndmsg ndm = { 970 .ndm_family = AF_INET6, 971 .ndm_flags = NTF_PROXY, 972 .ndm_ifindex = ifindex, 973 }; 974 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); 975 struct neigh_info ctxt = { 976 .ifindex = ifindex, 977 .addr = addr, 978 .ret = 0, 979 .pending = 1, 980 }; 981 982 if (!cb) { 983 ctxt.ret = -1; 984 goto out; 985 } 986 987 msg = nlmsg_alloc_simple(RTM_GETNEIGH, NLM_F_REQUEST | NLM_F_MATCH); 988 989 if (!msg) { 990 ctxt.ret = -1; 991 goto out; 992 } 993 994 nlmsg_append(msg, &ndm, sizeof(ndm), 0); 995 nla_put(msg, NDA_DST, sizeof(*addr), addr); 996 997 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_proxy_neigh_valid, &ctxt); 998 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_proxy_neigh_finish, &ctxt); 999 nl_cb_err(cb, NL_CB_CUSTOM, cb_proxy_neigh_error, &ctxt); 1000 1001 ctxt.ret = nl_send_auto_complete(rtnl_socket, msg); 1002 if (ctxt.ret < 0) 1003 goto free; 1004 1005 while (ctxt.pending > 0) 1006 nl_recvmsgs(rtnl_socket, cb); 1007 1008 free: 1009 nlmsg_free(msg); 1010 out: 1011 nl_cb_put(cb); 1012 1013 return ctxt.ret; 1014 } 1015 1016 1017 int netlink_setup_route(const struct in6_addr *addr, const int prefixlen, 1018 const int ifindex, const struct in6_addr *gw, 1019 const uint32_t metric, const bool add) 1020 { 1021 struct nl_msg *msg; 1022 struct rtmsg rtm = { 1023 .rtm_family = AF_INET6, 1024 .rtm_dst_len = prefixlen, 1025 .rtm_src_len = 0, 1026 .rtm_table = RT_TABLE_MAIN, 1027 .rtm_protocol = (add ? RTPROT_STATIC : RTPROT_UNSPEC), 1028 .rtm_scope = (add ? (gw ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK) : RT_SCOPE_NOWHERE), 1029 .rtm_type = (add ? RTN_UNICAST : RTN_UNSPEC), 1030 }; 1031 int ret = 0; 1032 1033 msg = nlmsg_alloc_simple(add ? RTM_NEWROUTE : RTM_DELROUTE, 1034 add ? NLM_F_CREATE | NLM_F_REPLACE : 0); 1035 if (!msg) 1036 return -1; 1037 1038 nlmsg_append(msg, &rtm, sizeof(rtm), 0); 1039 1040 nla_put(msg, RTA_DST, sizeof(*addr), addr); 1041 nla_put_u32(msg, RTA_OIF, ifindex); 1042 nla_put_u32(msg, RTA_PRIORITY, metric); 1043 1044 if (gw) 1045 nla_put(msg, RTA_GATEWAY, sizeof(*gw), gw); 1046 1047 ret = nl_send_auto_complete(rtnl_socket, msg); 1048 nlmsg_free(msg); 1049 1050 if (ret < 0) 1051 return ret; 1052 1053 return nl_wait_for_ack(rtnl_socket); 1054 } 1055 1056 1057 int netlink_setup_proxy_neigh(const struct in6_addr *addr, 1058 const int ifindex, const bool add) 1059 { 1060 struct nl_msg *msg; 1061 struct ndmsg ndm = { 1062 .ndm_family = AF_INET6, 1063 .ndm_flags = NTF_PROXY, 1064 .ndm_ifindex = ifindex, 1065 }; 1066 int ret = 0, flags = NLM_F_REQUEST; 1067 1068 if (add) 1069 flags |= NLM_F_REPLACE | NLM_F_CREATE; 1070 1071 msg = nlmsg_alloc_simple(add ? RTM_NEWNEIGH : RTM_DELNEIGH, flags); 1072 if (!msg) 1073 return -1; 1074 1075 nlmsg_append(msg, &ndm, sizeof(ndm), 0); 1076 1077 nla_put(msg, NDA_DST, sizeof(*addr), addr); 1078 1079 ret = nl_send_auto_complete(rtnl_socket, msg); 1080 nlmsg_free(msg); 1081 1082 if (ret < 0) 1083 return ret; 1084 1085 return nl_wait_for_ack(rtnl_socket); 1086 } 1087 1088 1089 int netlink_setup_addr(struct odhcpd_ipaddr *addr, 1090 const int ifindex, const bool v6, const bool add) 1091 { 1092 struct nl_msg *msg; 1093 struct ifaddrmsg ifa = { 1094 .ifa_family = v6 ? AF_INET6 : AF_INET, 1095 .ifa_prefixlen = addr->prefix, 1096 .ifa_flags = 0, 1097 .ifa_scope = 0, 1098 .ifa_index = ifindex, }; 1099 int ret = 0, flags = NLM_F_REQUEST; 1100 1101 if (add) 1102 flags |= NLM_F_REPLACE | NLM_F_CREATE; 1103 1104 msg = nlmsg_alloc_simple(add ? RTM_NEWADDR : RTM_DELADDR, 0); 1105 if (!msg) 1106 return -1; 1107 1108 nlmsg_append(msg, &ifa, sizeof(ifa), flags); 1109 nla_put(msg, IFA_LOCAL, v6 ? 16 : 4, &addr->addr); 1110 if (v6) { 1111 struct ifa_cacheinfo cinfo = { .ifa_prefered = 0xffffffffU, 1112 .ifa_valid = 0xffffffffU, 1113 .cstamp = 0, 1114 .tstamp = 0 }; 1115 time_t now = odhcpd_time(); 1116 1117 if (addr->preferred_lt) { 1118 int64_t preferred_lt = addr->preferred_lt - now; 1119 if (preferred_lt < 0) 1120 preferred_lt = 0; 1121 else if (preferred_lt > UINT32_MAX) 1122 preferred_lt = UINT32_MAX; 1123 1124 cinfo.ifa_prefered = preferred_lt; 1125 } 1126 1127 if (addr->valid_lt) { 1128 int64_t valid_lt = addr->valid_lt - now; 1129 if (valid_lt <= 0) { 1130 nlmsg_free(msg); 1131 return -1; 1132 } 1133 else if (valid_lt > UINT32_MAX) 1134 valid_lt = UINT32_MAX; 1135 1136 cinfo.ifa_valid = valid_lt; 1137 } 1138 1139 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo); 1140 1141 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE); 1142 } else { 1143 if (addr->broadcast.s_addr) 1144 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast.s_addr); 1145 } 1146 1147 ret = nl_send_auto_complete(rtnl_socket, msg); 1148 nlmsg_free(msg); 1149 1150 if (ret < 0) 1151 return ret; 1152 1153 return nl_wait_for_ack(rtnl_socket); 1154 } 1155 1156 void netlink_dump_neigh_table(const bool proxy) 1157 { 1158 struct nl_msg *msg; 1159 struct ndmsg ndm = { 1160 .ndm_family = AF_INET6, 1161 .ndm_flags = proxy ? NTF_PROXY : 0, 1162 }; 1163 1164 msg = nlmsg_alloc_simple(RTM_GETNEIGH, NLM_F_REQUEST | NLM_F_DUMP); 1165 if (!msg) 1166 return; 1167 1168 nlmsg_append(msg, &ndm, sizeof(ndm), 0); 1169 1170 nl_send_auto_complete(rtnl_event.sock, msg); 1171 1172 nlmsg_free(msg); 1173 } 1174 1175 void netlink_dump_addr_table(const bool v6) 1176 { 1177 struct nl_msg *msg; 1178 struct ifaddrmsg ifa = { 1179 .ifa_family = v6 ? AF_INET6 : AF_INET, 1180 }; 1181 1182 msg = nlmsg_alloc_simple(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP); 1183 if (!msg) 1184 return; 1185 1186 nlmsg_append(msg, &ifa, sizeof(ifa), 0); 1187 1188 nl_send_auto_complete(rtnl_event.sock, msg); 1189 1190 nlmsg_free(msg); 1191 } 1192
This page was automatically generated by LXR 0.3.1. • OpenWrt