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