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