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 memcpy(&addrs[ctxt->ret].addr, &addr, sizeof(addrs[ctxt->ret].addr)); 811 812 if (ifa->ifa_flags & IFA_F_TENTATIVE) 813 addrs[ctxt->ret].tentative = true; 814 815 ctxt->ret++; 816 *(ctxt->addrs) = addrs; 817 818 return NL_OK; 819 } 820 821 822 static int cb_linklocal_finish(_unused struct nl_msg *msg, void *arg) 823 { 824 struct addr_info *ctxt = (struct addr_info *)arg; 825 826 ctxt->pending = 0; 827 828 return NL_STOP; 829 } 830 831 832 static int cb_linklocal_error(_unused struct sockaddr_nl *nla, struct nlmsgerr *err, 833 void *arg) 834 { 835 struct addr_info *ctxt = (struct addr_info *)arg; 836 837 ctxt->pending = 0; 838 ctxt->ret = err->error; 839 840 return NL_STOP; 841 } 842 843 844 /* Detect a link local IPV6-address currently assigned to the given interface */ 845 ssize_t netlink_get_interface_linklocal(int ifindex, struct odhcpd_ipaddr **addrs) 846 { 847 struct nl_msg *msg; 848 struct ifaddrmsg ifa = { 849 .ifa_family = AF_INET6, 850 .ifa_prefixlen = 0, 851 .ifa_flags = 0, 852 .ifa_scope = 0, 853 .ifa_index = ifindex, }; 854 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); 855 struct addr_info ctxt = { 856 .ifindex = ifindex, 857 .af = AF_INET6, 858 .addrs = addrs, 859 .ret = 0, 860 .pending = 1, 861 }; 862 863 if (!cb) { 864 ctxt.ret = -1; 865 goto out; 866 } 867 868 msg = nlmsg_alloc_simple(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP); 869 870 if (!msg) { 871 ctxt.ret = - 1; 872 goto out; 873 } 874 875 nlmsg_append(msg, &ifa, sizeof(ifa), 0); 876 877 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_linklocal_valid, &ctxt); 878 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_linklocal_finish, &ctxt); 879 nl_cb_err(cb, NL_CB_CUSTOM, cb_linklocal_error, &ctxt); 880 881 ctxt.ret = nl_send_auto_complete(rtnl_socket, msg); 882 if (ctxt.ret < 0) 883 goto free; 884 885 ctxt.ret = 0; 886 while (ctxt.pending > 0) 887 nl_recvmsgs(rtnl_socket, cb); 888 889 if (ctxt.ret <= 0) 890 goto free; 891 892 free: 893 nlmsg_free(msg); 894 out: 895 nl_cb_put(cb); 896 897 return ctxt.ret; 898 } 899 900 901 struct neigh_info { 902 int ifindex; 903 int pending; 904 const struct in6_addr *addr; 905 int ret; 906 }; 907 908 909 static int cb_proxy_neigh_valid(struct nl_msg *msg, void *arg) 910 { 911 struct neigh_info *ctxt = (struct neigh_info *)arg; 912 struct nlmsghdr *hdr = nlmsg_hdr(msg); 913 struct ndmsg *ndm; 914 struct nlattr *nla_dst; 915 916 if (hdr->nlmsg_type != RTM_NEWNEIGH) 917 return NL_SKIP; 918 919 ndm = NLMSG_DATA(hdr); 920 if (ndm->ndm_family != AF_INET6 || 921 (ctxt->ifindex && ndm->ndm_ifindex != ctxt->ifindex)) 922 return NL_SKIP; 923 924 if (!(ndm->ndm_flags & NTF_PROXY)) 925 return NL_SKIP; 926 927 nla_dst = nlmsg_find_attr(hdr, sizeof(*ndm), NDA_DST); 928 if (!nla_dst) 929 return NL_SKIP; 930 931 if (nla_memcmp(nla_dst,ctxt->addr, 16) == 0) 932 ctxt->ret = 1; 933 934 return NL_OK; 935 } 936 937 938 static int cb_proxy_neigh_finish(_unused struct nl_msg *msg, void *arg) 939 { 940 struct neigh_info *ctxt = (struct neigh_info *)arg; 941 942 ctxt->pending = 0; 943 944 return NL_STOP; 945 } 946 947 948 static int cb_proxy_neigh_error(_unused struct sockaddr_nl *nla, struct nlmsgerr *err, 949 void *arg) 950 { 951 struct neigh_info *ctxt = (struct neigh_info *)arg; 952 953 ctxt->pending = 0; 954 ctxt->ret = err->error; 955 956 return NL_STOP; 957 } 958 959 /* Detect an IPV6-address proxy neighbor for the given interface */ 960 int netlink_get_interface_proxy_neigh(int ifindex, const struct in6_addr *addr) 961 { 962 struct nl_msg *msg; 963 struct ndmsg ndm = { 964 .ndm_family = AF_INET6, 965 .ndm_flags = NTF_PROXY, 966 .ndm_ifindex = ifindex, 967 }; 968 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); 969 struct neigh_info ctxt = { 970 .ifindex = ifindex, 971 .addr = addr, 972 .ret = 0, 973 .pending = 1, 974 }; 975 976 if (!cb) { 977 ctxt.ret = -1; 978 goto out; 979 } 980 981 msg = nlmsg_alloc_simple(RTM_GETNEIGH, NLM_F_REQUEST | NLM_F_MATCH); 982 983 if (!msg) { 984 ctxt.ret = -1; 985 goto out; 986 } 987 988 nlmsg_append(msg, &ndm, sizeof(ndm), 0); 989 nla_put(msg, NDA_DST, sizeof(*addr), addr); 990 991 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_proxy_neigh_valid, &ctxt); 992 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_proxy_neigh_finish, &ctxt); 993 nl_cb_err(cb, NL_CB_CUSTOM, cb_proxy_neigh_error, &ctxt); 994 995 ctxt.ret = nl_send_auto_complete(rtnl_socket, msg); 996 if (ctxt.ret < 0) 997 goto free; 998 999 while (ctxt.pending > 0) 1000 nl_recvmsgs(rtnl_socket, cb); 1001 1002 free: 1003 nlmsg_free(msg); 1004 out: 1005 nl_cb_put(cb); 1006 1007 return ctxt.ret; 1008 } 1009 1010 1011 int netlink_setup_route(const struct in6_addr *addr, const int prefixlen, 1012 const int ifindex, const struct in6_addr *gw, 1013 const uint32_t metric, const bool add) 1014 { 1015 struct nl_msg *msg; 1016 struct rtmsg rtm = { 1017 .rtm_family = AF_INET6, 1018 .rtm_dst_len = prefixlen, 1019 .rtm_src_len = 0, 1020 .rtm_table = RT_TABLE_MAIN, 1021 .rtm_protocol = (add ? RTPROT_STATIC : RTPROT_UNSPEC), 1022 .rtm_scope = (add ? (gw ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK) : RT_SCOPE_NOWHERE), 1023 .rtm_type = (add ? RTN_UNICAST : RTN_UNSPEC), 1024 }; 1025 int ret = 0; 1026 1027 msg = nlmsg_alloc_simple(add ? RTM_NEWROUTE : RTM_DELROUTE, 1028 add ? NLM_F_CREATE | NLM_F_REPLACE : 0); 1029 if (!msg) 1030 return -1; 1031 1032 nlmsg_append(msg, &rtm, sizeof(rtm), 0); 1033 1034 nla_put(msg, RTA_DST, sizeof(*addr), addr); 1035 nla_put_u32(msg, RTA_OIF, ifindex); 1036 nla_put_u32(msg, RTA_PRIORITY, metric); 1037 1038 if (gw) 1039 nla_put(msg, RTA_GATEWAY, sizeof(*gw), gw); 1040 1041 ret = nl_send_auto_complete(rtnl_socket, msg); 1042 nlmsg_free(msg); 1043 1044 if (ret < 0) 1045 return ret; 1046 1047 return nl_wait_for_ack(rtnl_socket); 1048 } 1049 1050 1051 int netlink_setup_proxy_neigh(const struct in6_addr *addr, 1052 const int ifindex, const bool add) 1053 { 1054 struct nl_msg *msg; 1055 struct ndmsg ndm = { 1056 .ndm_family = AF_INET6, 1057 .ndm_flags = NTF_PROXY, 1058 .ndm_ifindex = ifindex, 1059 }; 1060 int ret = 0, flags = NLM_F_REQUEST; 1061 1062 if (add) 1063 flags |= NLM_F_REPLACE | NLM_F_CREATE; 1064 1065 msg = nlmsg_alloc_simple(add ? RTM_NEWNEIGH : RTM_DELNEIGH, flags); 1066 if (!msg) 1067 return -1; 1068 1069 nlmsg_append(msg, &ndm, sizeof(ndm), 0); 1070 1071 nla_put(msg, NDA_DST, sizeof(*addr), addr); 1072 1073 ret = nl_send_auto_complete(rtnl_socket, msg); 1074 nlmsg_free(msg); 1075 1076 if (ret < 0) 1077 return ret; 1078 1079 return nl_wait_for_ack(rtnl_socket); 1080 } 1081 1082 1083 int netlink_setup_addr(struct odhcpd_ipaddr *addr, 1084 const int ifindex, const bool v6, const bool add) 1085 { 1086 struct nl_msg *msg; 1087 struct ifaddrmsg ifa = { 1088 .ifa_family = v6 ? AF_INET6 : AF_INET, 1089 .ifa_prefixlen = addr->prefix, 1090 .ifa_flags = 0, 1091 .ifa_scope = 0, 1092 .ifa_index = ifindex, }; 1093 int ret = 0, flags = NLM_F_REQUEST; 1094 1095 if (add) 1096 flags |= NLM_F_REPLACE | NLM_F_CREATE; 1097 1098 msg = nlmsg_alloc_simple(add ? RTM_NEWADDR : RTM_DELADDR, 0); 1099 if (!msg) 1100 return -1; 1101 1102 nlmsg_append(msg, &ifa, sizeof(ifa), flags); 1103 nla_put(msg, IFA_LOCAL, v6 ? 16 : 4, &addr->addr); 1104 if (v6) { 1105 struct ifa_cacheinfo cinfo = { .ifa_prefered = 0xffffffffU, 1106 .ifa_valid = 0xffffffffU, 1107 .cstamp = 0, 1108 .tstamp = 0 }; 1109 time_t now = odhcpd_time(); 1110 1111 if (addr->preferred_lt) { 1112 int64_t preferred_lt = addr->preferred_lt - now; 1113 if (preferred_lt < 0) 1114 preferred_lt = 0; 1115 else if (preferred_lt > UINT32_MAX) 1116 preferred_lt = UINT32_MAX; 1117 1118 cinfo.ifa_prefered = preferred_lt; 1119 } 1120 1121 if (addr->valid_lt) { 1122 int64_t valid_lt = addr->valid_lt - now; 1123 if (valid_lt <= 0) { 1124 nlmsg_free(msg); 1125 return -1; 1126 } 1127 else if (valid_lt > UINT32_MAX) 1128 valid_lt = UINT32_MAX; 1129 1130 cinfo.ifa_valid = valid_lt; 1131 } 1132 1133 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo); 1134 1135 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE); 1136 } else { 1137 if (addr->broadcast.s_addr) 1138 nla_put_u32(msg, IFA_BROADCAST, addr->broadcast.s_addr); 1139 } 1140 1141 ret = nl_send_auto_complete(rtnl_socket, msg); 1142 nlmsg_free(msg); 1143 1144 if (ret < 0) 1145 return ret; 1146 1147 return nl_wait_for_ack(rtnl_socket); 1148 } 1149 1150 void netlink_dump_neigh_table(const bool proxy) 1151 { 1152 struct nl_msg *msg; 1153 struct ndmsg ndm = { 1154 .ndm_family = AF_INET6, 1155 .ndm_flags = proxy ? NTF_PROXY : 0, 1156 }; 1157 1158 msg = nlmsg_alloc_simple(RTM_GETNEIGH, NLM_F_REQUEST | NLM_F_DUMP); 1159 if (!msg) 1160 return; 1161 1162 nlmsg_append(msg, &ndm, sizeof(ndm), 0); 1163 1164 nl_send_auto_complete(rtnl_event.sock, msg); 1165 1166 nlmsg_free(msg); 1167 } 1168 1169 void netlink_dump_addr_table(const bool v6) 1170 { 1171 struct nl_msg *msg; 1172 struct ifaddrmsg ifa = { 1173 .ifa_family = v6 ? AF_INET6 : AF_INET, 1174 }; 1175 1176 msg = nlmsg_alloc_simple(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP); 1177 if (!msg) 1178 return; 1179 1180 nlmsg_append(msg, &ifa, sizeof(ifa), 0); 1181 1182 nl_send_auto_complete(rtnl_event.sock, msg); 1183 1184 nlmsg_free(msg); 1185 } 1186
This page was automatically generated by LXR 0.3.1. • OpenWrt