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