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 /* ifa_prefixlen is 0..32. A /0 prefix turns "32 - prefix" into a 592 * 32-bit shift on a 32-bit type, which is undefined behaviour; 593 * compute the host mask in 64-bit and truncate so /0 yields a 594 * zero netmask as expected. */ 595 uint32_t host_bits = (uint32_t)((1ULL << (32 - ifa->ifa_prefixlen)) - 1); 596 oaddrs[ctxt->ret].netmask = htonl(~host_bits); 597 } 598 599 nla_memcpy(&oaddrs[ctxt->ret].addr, nla_addr, sizeof(oaddrs[ctxt->ret].addr)); 600 601 if (nla[IFA_BROADCAST]) 602 nla_memcpy(&oaddrs[ctxt->ret].broadcast, nla[IFA_BROADCAST], 603 sizeof(oaddrs[ctxt->ret].broadcast)); 604 605 if (nla[IFA_CACHEINFO]) { 606 struct ifa_cacheinfo *ifc = nla_data(nla[IFA_CACHEINFO]); 607 608 oaddrs[ctxt->ret].preferred_lt = ifc->ifa_prefered; 609 oaddrs[ctxt->ret].valid_lt = ifc->ifa_valid; 610 } 611 612 if (ifa->ifa_flags & IFA_F_DEPRECATED) 613 oaddrs[ctxt->ret].preferred_lt = 0; 614 615 if (ifa->ifa_family == AF_INET6 && 616 ifa->ifa_flags & IFA_F_TENTATIVE) 617 oaddrs[ctxt->ret].tentative = true; 618 619 ctxt->ret++; 620 *(ctxt->oaddrs) = oaddrs; 621 622 return NL_OK; 623 } 624 625 626 static int cb_addr_finish(_o_unused struct nl_msg *msg, void *arg) 627 { 628 struct addr_info *ctxt = (struct addr_info *)arg; 629 630 ctxt->pending = false; 631 632 return NL_STOP; 633 } 634 635 636 static int cb_addr_error(_o_unused struct sockaddr_nl *nla, struct nlmsgerr *err, 637 void *arg) 638 { 639 struct addr_info *ctxt = (struct addr_info *)arg; 640 641 ctxt->pending = false; 642 ctxt->ret = err->error; 643 644 return NL_STOP; 645 } 646 647 648 static int prefix_cmp(const void *va, const void *vb) 649 { 650 const struct odhcpd_ipaddr *a = va, *b = vb; 651 652 if (a->prefix_len != b->prefix_len) 653 return a->prefix_len < b->prefix_len ? 1 : -1; 654 655 if (ntohl(a->addr.in.s_addr) == ntohl(b->addr.in.s_addr)) 656 return 0; 657 658 return ntohl(a->addr.in.s_addr) < ntohl(b->addr.in.s_addr) ? 1 : -1; 659 } 660 661 662 /* compare IPv6 prefixes */ 663 static int prefix6_cmp(const void *va, const void *vb) 664 { 665 const struct odhcpd_ipaddr *a = va, *b = vb; 666 uint32_t a_pref_lt = IN6_IS_ADDR_ULA(&a->addr.in6) ? 1 : a->preferred_lt; 667 uint32_t b_pref_lt = IN6_IS_ADDR_ULA(&b->addr.in6) ? 1 : b->preferred_lt; 668 return (a_pref_lt < b_pref_lt) ? 1 : (a_pref_lt > b_pref_lt) ? -1 : 0; 669 } 670 671 672 /* Detect all IPv[46]-addresses currently assigned to the given interface */ 673 ssize_t netlink_get_interface_addrs(int ifindex, bool v6, struct odhcpd_ipaddr **oaddrs) 674 { 675 struct nl_msg *msg; 676 struct ifaddrmsg ifa = { 677 .ifa_family = v6? AF_INET6: AF_INET, 678 .ifa_prefixlen = 0, 679 .ifa_flags = 0, 680 .ifa_scope = 0, 681 .ifa_index = ifindex, 682 }; 683 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); 684 struct addr_info ctxt = { 685 .ifindex = ifindex, 686 .af = v6? AF_INET6: AF_INET, 687 .oaddrs = oaddrs, 688 .ret = 0, 689 .pending = true, 690 }; 691 692 if (!cb) { 693 ctxt.ret = -1; 694 goto out; 695 } 696 697 msg = nlmsg_alloc_simple(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP); 698 699 if (!msg) { 700 ctxt.ret = - 1; 701 goto out; 702 } 703 704 nlmsg_append(msg, &ifa, sizeof(ifa), 0); 705 706 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_addr_valid, &ctxt); 707 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_addr_finish, &ctxt); 708 nl_cb_err(cb, NL_CB_CUSTOM, cb_addr_error, &ctxt); 709 710 ctxt.ret = nl_send_auto_complete(rtnl_socket, msg); 711 if (ctxt.ret < 0) 712 goto free; 713 714 ctxt.ret = 0; 715 while (ctxt.pending) 716 nl_recvmsgs(rtnl_socket, cb); 717 718 if (ctxt.ret <= 0) 719 goto free; 720 721 time_t now = odhcpd_time(); 722 struct odhcpd_ipaddr *oaddr = *oaddrs; 723 724 qsort(oaddr, ctxt.ret, sizeof(*oaddr), v6 ? prefix6_cmp : prefix_cmp); 725 726 for (ssize_t i = 0; i < ctxt.ret; ++i) { 727 if (oaddr[i].preferred_lt < UINT32_MAX - now) 728 oaddr[i].preferred_lt += now; 729 730 if (oaddr[i].valid_lt < UINT32_MAX - now) 731 oaddr[i].valid_lt += now; 732 } 733 734 free: 735 nlmsg_free(msg); 736 out: 737 nl_cb_put(cb); 738 739 return ctxt.ret; 740 } 741 742 743 static int cb_linklocal_valid(struct nl_msg *msg, void *arg) 744 { 745 struct addr_info *ctxt = (struct addr_info *)arg; 746 struct odhcpd_ipaddr *oaddrs; 747 struct nlmsghdr *hdr = nlmsg_hdr(msg); 748 struct ifaddrmsg *ifa; 749 struct nlattr *nla[__IFA_MAX], *nla_addr = NULL; 750 struct in6_addr addr; 751 752 if (hdr->nlmsg_type != RTM_NEWADDR) 753 return NL_SKIP; 754 755 ifa = NLMSG_DATA(hdr); 756 if (ifa->ifa_scope != RT_SCOPE_LINK || 757 (ctxt->af != ifa->ifa_family) || 758 (ctxt->ifindex && ifa->ifa_index != (unsigned)ctxt->ifindex)) 759 return NL_SKIP; 760 761 nlmsg_parse(hdr, sizeof(*ifa), nla, __IFA_MAX - 1, NULL); 762 763 switch (ifa->ifa_family) { 764 case AF_INET6: 765 if (nla[IFA_ADDRESS]) 766 nla_addr = nla[IFA_ADDRESS]; 767 break; 768 769 default: 770 break; 771 } 772 if (!nla_addr) 773 return NL_SKIP; 774 775 nla_memcpy(&addr, nla_addr, sizeof(addr)); 776 777 if (!IN6_IS_ADDR_LINKLOCAL(&addr)) 778 return NL_SKIP; 779 780 oaddrs = realloc(*(ctxt->oaddrs), sizeof(*oaddrs) * (ctxt->ret + 1)); 781 if (!oaddrs) 782 return NL_SKIP; 783 784 memset(&oaddrs[ctxt->ret], 0, sizeof(oaddrs[ctxt->ret])); 785 memcpy(&oaddrs[ctxt->ret].addr, &addr, sizeof(oaddrs[ctxt->ret].addr)); 786 787 if (ifa->ifa_flags & IFA_F_TENTATIVE) 788 oaddrs[ctxt->ret].tentative = true; 789 790 ctxt->ret++; 791 *(ctxt->oaddrs) = oaddrs; 792 793 return NL_OK; 794 } 795 796 797 static int cb_linklocal_finish(_o_unused struct nl_msg *msg, void *arg) 798 { 799 struct addr_info *ctxt = (struct addr_info *)arg; 800 801 ctxt->pending = false; 802 803 return NL_STOP; 804 } 805 806 807 static int cb_linklocal_error(_o_unused struct sockaddr_nl *nla, struct nlmsgerr *err, 808 void *arg) 809 { 810 struct addr_info *ctxt = (struct addr_info *)arg; 811 812 ctxt->pending = false; 813 ctxt->ret = err->error; 814 815 return NL_STOP; 816 } 817 818 819 /* Detect link-local IPv6-addresses currently assigned to the given interface */ 820 ssize_t netlink_get_interface_linklocal(int ifindex, struct odhcpd_ipaddr **oaddrs) 821 { 822 struct nl_msg *msg; 823 struct ifaddrmsg ifa = { 824 .ifa_family = AF_INET6, 825 .ifa_prefixlen = 0, 826 .ifa_flags = 0, 827 .ifa_scope = 0, 828 .ifa_index = ifindex, 829 }; 830 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); 831 struct addr_info ctxt = { 832 .ifindex = ifindex, 833 .af = AF_INET6, 834 .oaddrs = oaddrs, 835 .ret = 0, 836 .pending = true, 837 }; 838 839 if (!cb) { 840 ctxt.ret = -1; 841 goto out; 842 } 843 844 msg = nlmsg_alloc_simple(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP); 845 846 if (!msg) { 847 ctxt.ret = - 1; 848 goto out; 849 } 850 851 nlmsg_append(msg, &ifa, sizeof(ifa), 0); 852 853 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_linklocal_valid, &ctxt); 854 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_linklocal_finish, &ctxt); 855 nl_cb_err(cb, NL_CB_CUSTOM, cb_linklocal_error, &ctxt); 856 857 ctxt.ret = nl_send_auto_complete(rtnl_socket, msg); 858 if (ctxt.ret < 0) 859 goto free; 860 861 ctxt.ret = 0; 862 while (ctxt.pending) 863 nl_recvmsgs(rtnl_socket, cb); 864 865 if (ctxt.ret <= 0) 866 goto free; 867 868 free: 869 nlmsg_free(msg); 870 out: 871 nl_cb_put(cb); 872 873 return ctxt.ret; 874 } 875 876 877 struct neigh_info { 878 int ifindex; 879 bool pending; 880 const struct in6_addr *addr; 881 int ret; 882 }; 883 884 885 static int cb_proxy_neigh_valid(struct nl_msg *msg, void *arg) 886 { 887 struct neigh_info *ctxt = (struct neigh_info *)arg; 888 struct nlmsghdr *hdr = nlmsg_hdr(msg); 889 struct ndmsg *ndm; 890 struct nlattr *nla_dst; 891 892 if (hdr->nlmsg_type != RTM_NEWNEIGH) 893 return NL_SKIP; 894 895 ndm = NLMSG_DATA(hdr); 896 if (ndm->ndm_family != AF_INET6 || 897 (ctxt->ifindex && ndm->ndm_ifindex != ctxt->ifindex)) 898 return NL_SKIP; 899 900 if (!(ndm->ndm_flags & NTF_PROXY)) 901 return NL_SKIP; 902 903 nla_dst = nlmsg_find_attr(hdr, sizeof(*ndm), NDA_DST); 904 if (!nla_dst) 905 return NL_SKIP; 906 907 if (nla_memcmp(nla_dst,ctxt->addr, 16) == 0) 908 ctxt->ret = 1; 909 910 return NL_OK; 911 } 912 913 914 static int cb_proxy_neigh_finish(_o_unused struct nl_msg *msg, void *arg) 915 { 916 struct neigh_info *ctxt = (struct neigh_info *)arg; 917 918 ctxt->pending = false; 919 920 return NL_STOP; 921 } 922 923 924 static int cb_proxy_neigh_error(_o_unused struct sockaddr_nl *nla, struct nlmsgerr *err, 925 void *arg) 926 { 927 struct neigh_info *ctxt = (struct neigh_info *)arg; 928 929 ctxt->pending = false; 930 ctxt->ret = err->error; 931 932 return NL_STOP; 933 } 934 935 /* Detect an IPV6-address proxy neighbor for the given interface */ 936 int netlink_get_interface_proxy_neigh(int ifindex, const struct in6_addr *addr) 937 { 938 struct nl_msg *msg; 939 struct ndmsg ndm = { 940 .ndm_family = AF_INET6, 941 .ndm_flags = NTF_PROXY, 942 .ndm_ifindex = ifindex, 943 }; 944 struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); 945 struct neigh_info ctxt = { 946 .ifindex = ifindex, 947 .addr = addr, 948 .ret = 0, 949 .pending = true, 950 }; 951 952 if (!cb) { 953 ctxt.ret = -1; 954 goto out; 955 } 956 957 msg = nlmsg_alloc_simple(RTM_GETNEIGH, NLM_F_REQUEST | NLM_F_MATCH); 958 959 if (!msg) { 960 ctxt.ret = -1; 961 goto out; 962 } 963 964 nlmsg_append(msg, &ndm, sizeof(ndm), 0); 965 nla_put(msg, NDA_DST, sizeof(*addr), addr); 966 967 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_proxy_neigh_valid, &ctxt); 968 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_proxy_neigh_finish, &ctxt); 969 nl_cb_err(cb, NL_CB_CUSTOM, cb_proxy_neigh_error, &ctxt); 970 971 ctxt.ret = nl_send_auto_complete(rtnl_socket, msg); 972 if (ctxt.ret < 0) 973 goto free; 974 975 while (ctxt.pending) 976 nl_recvmsgs(rtnl_socket, cb); 977 978 free: 979 nlmsg_free(msg); 980 out: 981 nl_cb_put(cb); 982 983 return ctxt.ret; 984 } 985 986 987 int netlink_setup_route(const struct in6_addr *addr, const int prefixlen, 988 const int ifindex, const struct in6_addr *gw, 989 const uint32_t metric, const bool add) 990 { 991 struct nl_msg *msg; 992 struct rtmsg rtm = { 993 .rtm_family = AF_INET6, 994 .rtm_dst_len = prefixlen, 995 .rtm_src_len = 0, 996 .rtm_table = RT_TABLE_MAIN, 997 .rtm_protocol = (add ? RTPROT_STATIC : RTPROT_UNSPEC), 998 .rtm_scope = (add ? (gw ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK) : RT_SCOPE_NOWHERE), 999 .rtm_type = (add ? RTN_UNICAST : RTN_UNSPEC), 1000 }; 1001 int ret = 0; 1002 1003 msg = nlmsg_alloc_simple(add ? RTM_NEWROUTE : RTM_DELROUTE, 1004 add ? NLM_F_CREATE | NLM_F_REPLACE : 0); 1005 if (!msg) 1006 return -1; 1007 1008 nlmsg_append(msg, &rtm, sizeof(rtm), 0); 1009 1010 nla_put(msg, RTA_DST, sizeof(*addr), addr); 1011 nla_put_u32(msg, RTA_OIF, ifindex); 1012 nla_put_u32(msg, RTA_PRIORITY, metric); 1013 1014 if (gw) 1015 nla_put(msg, RTA_GATEWAY, sizeof(*gw), gw); 1016 1017 ret = nl_send_auto_complete(rtnl_socket, msg); 1018 nlmsg_free(msg); 1019 1020 if (ret < 0) 1021 return ret; 1022 1023 return nl_wait_for_ack(rtnl_socket); 1024 } 1025 1026 1027 int netlink_setup_proxy_neigh(const struct in6_addr *addr, 1028 const int ifindex, const bool add) 1029 { 1030 struct nl_msg *msg; 1031 struct ndmsg ndm = { 1032 .ndm_family = AF_INET6, 1033 .ndm_flags = NTF_PROXY, 1034 .ndm_ifindex = ifindex, 1035 }; 1036 int ret = 0, flags = NLM_F_REQUEST; 1037 1038 if (add) 1039 flags |= NLM_F_REPLACE | NLM_F_CREATE; 1040 1041 msg = nlmsg_alloc_simple(add ? RTM_NEWNEIGH : RTM_DELNEIGH, flags); 1042 if (!msg) 1043 return -1; 1044 1045 nlmsg_append(msg, &ndm, sizeof(ndm), 0); 1046 1047 nla_put(msg, NDA_DST, sizeof(*addr), addr); 1048 1049 ret = nl_send_auto_complete(rtnl_socket, msg); 1050 nlmsg_free(msg); 1051 1052 if (ret < 0) 1053 return ret; 1054 1055 return nl_wait_for_ack(rtnl_socket); 1056 } 1057 1058 1059 int netlink_setup_addr(struct odhcpd_ipaddr *oaddr, 1060 const int ifindex, const bool v6, const bool add) 1061 { 1062 struct nl_msg *msg; 1063 struct ifaddrmsg ifa = { 1064 .ifa_family = v6 ? AF_INET6 : AF_INET, 1065 .ifa_prefixlen = oaddr->prefix_len, 1066 .ifa_flags = 0, 1067 .ifa_scope = 0, 1068 .ifa_index = ifindex, 1069 }; 1070 int ret = 0, flags = NLM_F_REQUEST; 1071 1072 if (add) 1073 flags |= NLM_F_REPLACE | NLM_F_CREATE; 1074 1075 msg = nlmsg_alloc_simple(add ? RTM_NEWADDR : RTM_DELADDR, 0); 1076 if (!msg) 1077 return -1; 1078 1079 nlmsg_append(msg, &ifa, sizeof(ifa), flags); 1080 nla_put(msg, IFA_LOCAL, v6 ? 16 : 4, &oaddr->addr); 1081 if (v6) { 1082 struct ifa_cacheinfo cinfo = { 1083 .ifa_prefered = 0xffffffffU, 1084 .ifa_valid = 0xffffffffU, 1085 .cstamp = 0, 1086 .tstamp = 0, 1087 }; 1088 time_t now = odhcpd_time(); 1089 1090 if (oaddr->preferred_lt) { 1091 int64_t preferred_lt = oaddr->preferred_lt - now; 1092 if (preferred_lt < 0) 1093 preferred_lt = 0; 1094 else if (preferred_lt > UINT32_MAX) 1095 preferred_lt = UINT32_MAX; 1096 1097 cinfo.ifa_prefered = preferred_lt; 1098 } 1099 1100 if (oaddr->valid_lt) { 1101 int64_t valid_lt = oaddr->valid_lt - now; 1102 if (valid_lt <= 0) { 1103 nlmsg_free(msg); 1104 return -1; 1105 } 1106 else if (valid_lt > UINT32_MAX) 1107 valid_lt = UINT32_MAX; 1108 1109 cinfo.ifa_valid = valid_lt; 1110 } 1111 1112 nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo); 1113 1114 nla_put_u32(msg, IFA_FLAGS, IFA_F_NOPREFIXROUTE); 1115 } else { 1116 if (oaddr->broadcast.s_addr) 1117 nla_put_u32(msg, IFA_BROADCAST, oaddr->broadcast.s_addr); 1118 } 1119 1120 ret = nl_send_auto_complete(rtnl_socket, msg); 1121 nlmsg_free(msg); 1122 1123 if (ret < 0) 1124 return ret; 1125 1126 return nl_wait_for_ack(rtnl_socket); 1127 } 1128 1129 void netlink_dump_neigh_table(const bool proxy) 1130 { 1131 struct nl_msg *msg; 1132 struct ndmsg ndm = { 1133 .ndm_family = AF_INET6, 1134 .ndm_flags = proxy ? NTF_PROXY : 0, 1135 }; 1136 1137 msg = nlmsg_alloc_simple(RTM_GETNEIGH, NLM_F_REQUEST | NLM_F_DUMP); 1138 if (!msg) 1139 return; 1140 1141 nlmsg_append(msg, &ndm, sizeof(ndm), 0); 1142 1143 nl_send_auto_complete(rtnl_event.sock, msg); 1144 1145 nlmsg_free(msg); 1146 } 1147 1148 void netlink_dump_addr_table(const bool v6) 1149 { 1150 struct nl_msg *msg; 1151 struct ifaddrmsg ifa = { 1152 .ifa_family = v6 ? AF_INET6 : AF_INET, 1153 }; 1154 1155 msg = nlmsg_alloc_simple(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP); 1156 if (!msg) 1157 return; 1158 1159 nlmsg_append(msg, &ifa, sizeof(ifa), 0); 1160 1161 nl_send_auto_complete(rtnl_event.sock, msg); 1162 1163 nlmsg_free(msg); 1164 } 1165
This page was automatically generated by LXR 0.3.1. • OpenWrt