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