1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2022 Alexander V. Chernikov <melifaro@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include "opt_netlink.h" 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 #include "opt_inet.h" 33 #include "opt_inet6.h" 34 #include <sys/types.h> 35 #include <sys/eventhandler.h> 36 #include <sys/kernel.h> 37 #include <sys/jail.h> 38 #include <sys/malloc.h> 39 #include <sys/socket.h> 40 #include <sys/sockio.h> 41 #include <sys/syslog.h> 42 43 #include <net/if.h> 44 #include <net/if_dl.h> 45 #include <net/if_media.h> 46 #include <net/if_var.h> 47 #include <net/if_clone.h> 48 #include <net/route.h> 49 #include <net/route/nhop.h> 50 #include <net/route/route_ctl.h> 51 #include <netlink/netlink.h> 52 #include <netlink/netlink_ctl.h> 53 #include <netlink/netlink_route.h> 54 #include <netlink/route/route_var.h> 55 56 #include <netinet6/scope6_var.h> /* scope deembedding */ 57 58 #define DEBUG_MOD_NAME nl_iface 59 #define DEBUG_MAX_LEVEL LOG_DEBUG3 60 #include <netlink/netlink_debug.h> 61 _DECLARE_DEBUG(LOG_DEBUG); 62 63 struct netlink_walkargs { 64 struct nl_writer *nw; 65 struct nlmsghdr hdr; 66 struct nlpcb *so; 67 struct ucred *cred; 68 uint32_t fibnum; 69 int family; 70 int error; 71 int count; 72 int dumped; 73 }; 74 75 static eventhandler_tag ifdetach_event, ifattach_event, iflink_event, ifaddr_event; 76 77 static SLIST_HEAD(, nl_cloner) nl_cloners = SLIST_HEAD_INITIALIZER(nl_cloners); 78 79 static struct sx rtnl_cloner_lock; 80 SX_SYSINIT(rtnl_cloner_lock, &rtnl_cloner_lock, "rtnl cloner lock"); 81 82 static struct nl_cloner *rtnl_iface_find_cloner_locked(const char *name); 83 84 /* 85 * RTM_GETLINK request 86 * sendto(3, {{len=32, type=RTM_GETLINK, flags=NLM_F_REQUEST|NLM_F_DUMP, seq=1641940952, pid=0}, 87 * {ifi_family=AF_INET, ifi_type=ARPHRD_NETROM, ifi_index=0, ifi_flags=0, ifi_change=0}}, 32, 0, NULL, 0) = 32 88 * 89 * Reply: 90 * {ifi_family=AF_UNSPEC, ifi_type=ARPHRD_ETHER, ifi_index=if_nametoindex("enp0s31f6"), ifi_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST|IFF_LOWER_UP, ifi_change=0}, 91 {{nla_len=10, nla_type=IFLA_ADDRESS}, "\xfe\x54\x00\x52\x3e\x90"} 92 93 [ 94 {{nla_len=14, nla_type=IFLA_IFNAME}, "enp0s31f6"}, 95 {{nla_len=8, nla_type=IFLA_TXQLEN}, 1000}, 96 {{nla_len=5, nla_type=IFLA_OPERSTATE}, 6}, 97 {{nla_len=5, nla_type=IFLA_LINKMODE}, 0}, 98 {{nla_len=8, nla_type=IFLA_MTU}, 1500}, 99 {{nla_len=8, nla_type=IFLA_MIN_MTU}, 68}, 100 {{nla_len=8, nla_type=IFLA_MAX_MTU}, 9000}, 101 {{nla_len=8, nla_type=IFLA_GROUP}, 0}, 102 {{nla_len=8, nla_type=IFLA_PROMISCUITY}, 0}, 103 {{nla_len=8, nla_type=IFLA_NUM_TX_QUEUES}, 1}, 104 {{nla_len=8, nla_type=IFLA_GSO_MAX_SEGS}, 65535}, 105 {{nla_len=8, nla_type=IFLA_GSO_MAX_SIZE}, 65536}, 106 {{nla_len=8, nla_type=IFLA_NUM_RX_QUEUES}, 1}, 107 {{nla_len=5, nla_type=IFLA_CARRIER}, 1}, 108 {{nla_len=13, nla_type=IFLA_QDISC}, "fq_codel"}, 109 {{nla_len=8, nla_type=IFLA_CARRIER_CHANGES}, 2}, 110 {{nla_len=5, nla_type=IFLA_PROTO_DOWN}, 0}, 111 {{nla_len=8, nla_type=IFLA_CARRIER_UP_COUNT}, 1}, 112 {{nla_len=8, nla_type=IFLA_CARRIER_DOWN_COUNT}, 1}, 113 */ 114 115 struct if_state { 116 uint8_t ifla_operstate; 117 uint8_t ifla_carrier; 118 }; 119 120 static void 121 get_operstate_ether(struct ifnet *ifp, struct if_state *pstate) 122 { 123 struct ifmediareq ifmr = {}; 124 int error; 125 error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (void *)&ifmr); 126 127 if (error != 0) { 128 NL_LOG(LOG_DEBUG, "error calling SIOCGIFMEDIA on %s: %d", 129 if_name(ifp), error); 130 return; 131 } 132 133 switch (IFM_TYPE(ifmr.ifm_active)) { 134 case IFM_ETHER: 135 if (ifmr.ifm_status & IFM_ACTIVE) { 136 pstate->ifla_carrier = 1; 137 if (ifp->if_flags & IFF_MONITOR) 138 pstate->ifla_operstate = IF_OPER_DORMANT; 139 else 140 pstate->ifla_operstate = IF_OPER_UP; 141 } else 142 pstate->ifla_operstate = IF_OPER_DOWN; 143 } 144 } 145 146 static bool 147 get_stats(struct nl_writer *nw, struct ifnet *ifp) 148 { 149 struct rtnl_link_stats64 *stats; 150 151 int nla_len = sizeof(struct nlattr) + sizeof(*stats); 152 struct nlattr *nla = nlmsg_reserve_data(nw, nla_len, struct nlattr); 153 if (nla == NULL) 154 return (false); 155 nla->nla_type = IFLA_STATS64; 156 nla->nla_len = nla_len; 157 stats = (struct rtnl_link_stats64 *)(nla + 1); 158 159 stats->rx_packets = ifp->if_get_counter(ifp, IFCOUNTER_IPACKETS); 160 stats->tx_packets = ifp->if_get_counter(ifp, IFCOUNTER_OPACKETS); 161 stats->rx_bytes = ifp->if_get_counter(ifp, IFCOUNTER_IBYTES); 162 stats->tx_bytes = ifp->if_get_counter(ifp, IFCOUNTER_OBYTES); 163 stats->rx_errors = ifp->if_get_counter(ifp, IFCOUNTER_IERRORS); 164 stats->tx_errors = ifp->if_get_counter(ifp, IFCOUNTER_OERRORS); 165 stats->rx_dropped = ifp->if_get_counter(ifp, IFCOUNTER_IQDROPS); 166 stats->tx_dropped = ifp->if_get_counter(ifp, IFCOUNTER_OQDROPS); 167 stats->multicast = ifp->if_get_counter(ifp, IFCOUNTER_IMCASTS); 168 stats->rx_nohandler = ifp->if_get_counter(ifp, IFCOUNTER_NOPROTO); 169 170 return (true); 171 } 172 173 static void 174 get_operstate(struct ifnet *ifp, struct if_state *pstate) 175 { 176 pstate->ifla_operstate = IF_OPER_UNKNOWN; 177 pstate->ifla_carrier = 0; /* no carrier */ 178 179 switch (ifp->if_type) { 180 case IFT_ETHER: 181 case IFT_L2VLAN: 182 get_operstate_ether(ifp, pstate); 183 break; 184 default: 185 /* Map admin state to the operstate */ 186 if (ifp->if_flags & IFF_UP) { 187 pstate->ifla_operstate = IF_OPER_UP; 188 pstate->ifla_carrier = 1; 189 } else 190 pstate->ifla_operstate = IF_OPER_DOWN; 191 break; 192 } 193 } 194 195 static unsigned 196 ifp_flags_to_netlink(const struct ifnet *ifp) 197 { 198 return (ifp->if_flags | ifp->if_drv_flags); 199 } 200 201 #define LLADDR_CONST(s) ((const void *)((s)->sdl_data + (s)->sdl_nlen)) 202 static bool 203 dump_sa(struct nl_writer *nw, int attr, const struct sockaddr *sa) 204 { 205 uint32_t addr_len = 0; 206 const void *addr_data = NULL; 207 #ifdef INET6 208 struct in6_addr addr6; 209 #endif 210 211 if (sa == NULL) 212 return (true); 213 214 switch (sa->sa_family) { 215 #ifdef INET 216 case AF_INET: 217 addr_len = sizeof(struct in_addr); 218 addr_data = &((const struct sockaddr_in *)sa)->sin_addr; 219 break; 220 #endif 221 #ifdef INET6 222 case AF_INET6: 223 in6_splitscope(&((const struct sockaddr_in6 *)sa)->sin6_addr, &addr6, &addr_len); 224 addr_len = sizeof(struct in6_addr); 225 addr_data = &addr6; 226 break; 227 #endif 228 case AF_LINK: 229 addr_len = ((const struct sockaddr_dl *)sa)->sdl_alen; 230 addr_data = LLADDR_CONST((const struct sockaddr_dl *)sa); 231 break; 232 default: 233 NL_LOG(LOG_DEBUG2, "unsupported family: %d, skipping", sa->sa_family); 234 return (true); 235 } 236 237 return (nlattr_add(nw, attr, addr_len, addr_data)); 238 } 239 240 /* 241 * Dumps interface state, properties and metrics. 242 * @nw: message writer 243 * @ifp: target interface 244 * @hdr: template header 245 * @if_flags_mask: changed if_[drv]_flags bitmask 246 * 247 * This function is called without epoch and MAY sleep. 248 */ 249 static bool 250 dump_iface(struct nl_writer *nw, struct ifnet *ifp, const struct nlmsghdr *hdr, 251 int if_flags_mask) 252 { 253 struct ifinfomsg *ifinfo; 254 255 NL_LOG(LOG_DEBUG3, "dumping interface %s data", if_name(ifp)); 256 257 if (!nlmsg_reply(nw, hdr, sizeof(struct ifinfomsg))) 258 goto enomem; 259 260 ifinfo = nlmsg_reserve_object(nw, struct ifinfomsg); 261 ifinfo->ifi_family = AF_UNSPEC; 262 ifinfo->__ifi_pad = 0; 263 ifinfo->ifi_type = ifp->if_type; 264 ifinfo->ifi_index = ifp->if_index; 265 ifinfo->ifi_flags = ifp_flags_to_netlink(ifp); 266 ifinfo->ifi_change = if_flags_mask; 267 268 struct if_state ifs = {}; 269 get_operstate(ifp, &ifs); 270 271 if (ifs.ifla_operstate == IF_OPER_UP) 272 ifinfo->ifi_flags |= IFF_LOWER_UP; 273 274 nlattr_add_string(nw, IFLA_IFNAME, if_name(ifp)); 275 nlattr_add_u8(nw, IFLA_OPERSTATE, ifs.ifla_operstate); 276 nlattr_add_u8(nw, IFLA_CARRIER, ifs.ifla_carrier); 277 278 /* 279 nlattr_add_u8(nw, IFLA_PROTO_DOWN, val); 280 nlattr_add_u8(nw, IFLA_LINKMODE, val); 281 */ 282 if ((ifp->if_addr != NULL)) { 283 dump_sa(nw, IFLA_ADDRESS, ifp->if_addr->ifa_addr); 284 } 285 286 if ((ifp->if_broadcastaddr != NULL)) { 287 nlattr_add(nw, IFLA_BROADCAST, ifp->if_addrlen, 288 ifp->if_broadcastaddr); 289 } 290 291 nlattr_add_u32(nw, IFLA_MTU, ifp->if_mtu); 292 /* 293 nlattr_add_u32(nw, IFLA_MIN_MTU, 60); 294 nlattr_add_u32(nw, IFLA_MAX_MTU, 9000); 295 nlattr_add_u32(nw, IFLA_GROUP, 0); 296 */ 297 298 if (ifp->if_description != NULL) 299 nlattr_add_string(nw, IFLA_IFALIAS, ifp->if_description); 300 301 get_stats(nw, ifp); 302 303 uint32_t val = (ifp->if_flags & IFF_PROMISC) != 0; 304 nlattr_add_u32(nw, IFLA_PROMISCUITY, val); 305 306 sx_slock(&rtnl_cloner_lock); 307 struct nl_cloner *cloner = rtnl_iface_find_cloner_locked(ifp->if_dname); 308 if (cloner != NULL && cloner->dump_f != NULL) { 309 /* Ignore any dump error */ 310 cloner->dump_f(ifp, nw); 311 } 312 sx_sunlock(&rtnl_cloner_lock); 313 314 if (nlmsg_end(nw)) 315 return (true); 316 317 enomem: 318 NL_LOG(LOG_DEBUG, "unable to dump interface %s state (ENOMEM)", if_name(ifp)); 319 nlmsg_abort(nw); 320 return (false); 321 } 322 323 static bool 324 check_ifmsg(void *hdr, struct nl_pstate *npt) 325 { 326 struct ifinfomsg *ifm = hdr; 327 328 if (ifm->__ifi_pad != 0 || ifm->ifi_type != 0 || 329 ifm->ifi_flags != 0 || ifm->ifi_change != 0) { 330 nlmsg_report_err_msg(npt, 331 "strict checking: non-zero values in ifinfomsg header"); 332 return (false); 333 } 334 335 return (true); 336 } 337 338 #define _IN(_field) offsetof(struct ifinfomsg, _field) 339 #define _OUT(_field) offsetof(struct nl_parsed_link, _field) 340 static const struct nlfield_parser nlf_p_if[] = { 341 { .off_in = _IN(ifi_type), .off_out = _OUT(ifi_type), .cb = nlf_get_u16 }, 342 { .off_in = _IN(ifi_index), .off_out = _OUT(ifi_index), .cb = nlf_get_u32 }, 343 { .off_in = _IN(ifi_flags), .off_out = _OUT(ifi_flags), .cb = nlf_get_u32 }, 344 { .off_in = _IN(ifi_change), .off_out = _OUT(ifi_change), .cb = nlf_get_u32 }, 345 }; 346 347 static const struct nlattr_parser nla_p_linfo[] = { 348 { .type = IFLA_INFO_KIND, .off = _OUT(ifla_cloner), .cb = nlattr_get_stringn }, 349 { .type = IFLA_INFO_DATA, .off = _OUT(ifla_idata), .cb = nlattr_get_nla }, 350 }; 351 NL_DECLARE_ATTR_PARSER(linfo_parser, nla_p_linfo); 352 353 static const struct nlattr_parser nla_p_if[] = { 354 { .type = IFLA_IFNAME, .off = _OUT(ifla_ifname), .cb = nlattr_get_string }, 355 { .type = IFLA_MTU, .off = _OUT(ifla_mtu), .cb = nlattr_get_uint32 }, 356 { .type = IFLA_LINK, .off = _OUT(ifi_index), .cb = nlattr_get_uint32 }, 357 { .type = IFLA_LINKINFO, .arg = &linfo_parser, .cb = nlattr_get_nested }, 358 { .type = IFLA_IFALIAS, .off = _OUT(ifla_ifalias), .cb = nlattr_get_string }, 359 { .type = IFLA_GROUP, .off = _OUT(ifla_group), .cb = nlattr_get_string }, 360 { .type = IFLA_ALT_IFNAME, .off = _OUT(ifla_ifname), .cb = nlattr_get_string }, 361 }; 362 #undef _IN 363 #undef _OUT 364 NL_DECLARE_STRICT_PARSER(ifmsg_parser, struct ifinfomsg, check_ifmsg, nlf_p_if, nla_p_if); 365 366 static bool 367 match_iface(struct ifnet *ifp, void *_arg) 368 { 369 struct nl_parsed_link *attrs = (struct nl_parsed_link *)_arg; 370 371 if (attrs->ifi_index != 0 && attrs->ifi_index != ifp->if_index) 372 return (false); 373 if (attrs->ifi_type != 0 && attrs->ifi_index != ifp->if_type) 374 return (false); 375 if (attrs->ifla_ifname != NULL && strcmp(attrs->ifla_ifname, if_name(ifp))) 376 return (false); 377 /* TODO: add group match */ 378 379 return (true); 380 } 381 382 static int 383 dump_cb(struct ifnet *ifp, void *_arg) 384 { 385 struct netlink_walkargs *wa = (struct netlink_walkargs *)_arg; 386 if (!dump_iface(wa->nw, ifp, &wa->hdr, 0)) 387 return (ENOMEM); 388 return (0); 389 } 390 391 /* 392 * {nlmsg_len=52, nlmsg_type=RTM_GETLINK, nlmsg_flags=NLM_F_REQUEST, nlmsg_seq=1662842818, nlmsg_pid=0}, 393 * {ifi_family=AF_PACKET, ifi_type=ARPHRD_NETROM, ifi_index=0, ifi_flags=0, ifi_change=0}, 394 * [ 395 * [{nla_len=10, nla_type=IFLA_IFNAME}, "vnet9"], 396 * [{nla_len=8, nla_type=IFLA_EXT_MASK}, RTEXT_FILTER_VF] 397 * ] 398 */ 399 static int 400 rtnl_handle_getlink(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate *npt) 401 { 402 struct epoch_tracker et; 403 struct ifnet *ifp; 404 int error = 0; 405 406 struct nl_parsed_link attrs = {}; 407 error = nl_parse_nlmsg(hdr, &ifmsg_parser, npt, &attrs); 408 if (error != 0) 409 return (error); 410 411 struct netlink_walkargs wa = { 412 .so = nlp, 413 .nw = npt->nw, 414 .hdr.nlmsg_pid = hdr->nlmsg_pid, 415 .hdr.nlmsg_seq = hdr->nlmsg_seq, 416 .hdr.nlmsg_flags = hdr->nlmsg_flags, 417 .hdr.nlmsg_type = NL_RTM_NEWLINK, 418 }; 419 420 /* Fast track for an interface w/ explicit name or index match */ 421 if ((attrs.ifi_index != 0) || (attrs.ifla_ifname != NULL)) { 422 if (attrs.ifi_index != 0) { 423 NLP_LOG(LOG_DEBUG3, nlp, "fast track -> searching index %u", 424 attrs.ifi_index); 425 NET_EPOCH_ENTER(et); 426 ifp = ifnet_byindex_ref(attrs.ifi_index); 427 NET_EPOCH_EXIT(et); 428 } else { 429 NLP_LOG(LOG_DEBUG3, nlp, "fast track -> searching name %s", 430 attrs.ifla_ifname); 431 ifp = ifunit_ref(attrs.ifla_ifname); 432 } 433 434 if (ifp != NULL) { 435 if (match_iface(ifp, &attrs)) { 436 if (!dump_iface(wa.nw, ifp, &wa.hdr, 0)) 437 error = ENOMEM; 438 } else 439 error = ENODEV; 440 if_rele(ifp); 441 } else 442 error = ENODEV; 443 return (error); 444 } 445 446 /* Always treat non-direct-match as a multipart message */ 447 wa.hdr.nlmsg_flags |= NLM_F_MULTI; 448 449 /* 450 * Fetching some link properties require performing ioctl's that may be blocking. 451 * Address it by saving referenced pointers of the matching links, 452 * exiting from epoch and going through the list one-by-one. 453 */ 454 455 NL_LOG(LOG_DEBUG2, "Start dump"); 456 if_foreach_sleep(match_iface, &attrs, dump_cb, &wa); 457 NL_LOG(LOG_DEBUG2, "End dump, iterated %d dumped %d", wa.count, wa.dumped); 458 459 if (!nlmsg_end_dump(wa.nw, error, &wa.hdr)) { 460 NL_LOG(LOG_DEBUG, "Unable to finalize the dump"); 461 return (ENOMEM); 462 } 463 464 return (error); 465 } 466 467 /* 468 * sendmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, msg_namelen=12, msg_iov=[{iov_base=[ 469 * {nlmsg_len=60, nlmsg_type=RTM_NEWLINK, nlmsg_flags=NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL|NLM_F_CREATE, nlmsg_seq=1662715618, nlmsg_pid=0}, 470 * {ifi_family=AF_UNSPEC, ifi_type=ARPHRD_NETROM, ifi_index=0, ifi_flags=0, ifi_change=0}, 471 * {nla_len=11, nla_type=IFLA_IFNAME}, "dummy0"], 472 * [ 473 * {nla_len=16, nla_type=IFLA_LINKINFO}, 474 * [ 475 * {nla_len=9, nla_type=IFLA_INFO_KIND}, "dummy"... 476 * ] 477 * ] 478 */ 479 480 static int 481 rtnl_handle_dellink(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate *npt) 482 { 483 struct epoch_tracker et; 484 struct ifnet *ifp; 485 int error; 486 487 struct nl_parsed_link attrs = {}; 488 error = nl_parse_nlmsg(hdr, &ifmsg_parser, npt, &attrs); 489 if (error != 0) 490 return (error); 491 492 NET_EPOCH_ENTER(et); 493 ifp = ifnet_byindex_ref(attrs.ifi_index); 494 NET_EPOCH_EXIT(et); 495 if (ifp == NULL) { 496 NLP_LOG(LOG_DEBUG, nlp, "unable to find interface %u", attrs.ifi_index); 497 return (ENOENT); 498 } 499 NLP_LOG(LOG_DEBUG3, nlp, "mapped ifindex %u to %s", attrs.ifi_index, if_name(ifp)); 500 501 sx_xlock(&ifnet_detach_sxlock); 502 error = if_clone_destroy(if_name(ifp)); 503 sx_xunlock(&ifnet_detach_sxlock); 504 505 NLP_LOG(LOG_DEBUG2, nlp, "deleting interface %s returned %d", if_name(ifp), error); 506 507 if_rele(ifp); 508 return (error); 509 } 510 511 /* 512 * New link: 513 * type=RTM_NEWLINK, flags=NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL|NLM_F_CREATE, seq=1668185590, pid=0}, 514 * {ifi_family=AF_UNSPEC, ifi_type=ARPHRD_NETROM, ifi_index=0, ifi_flags=0, ifi_change=0} 515 * [ 516 * {{nla_len=8, nla_type=IFLA_MTU}, 123}, 517 * {{nla_len=10, nla_type=IFLA_IFNAME}, "vlan1"}, 518 * {{nla_len=24, nla_type=IFLA_LINKINFO}, 519 * [ 520 * {{nla_len=8, nla_type=IFLA_INFO_KIND}, "vlan"...}, 521 * {{nla_len=12, nla_type=IFLA_INFO_DATA}, "\x06\x00\x01\x00\x7b\x00\x00\x00"}]}]} 522 * 523 * Update link: 524 * type=RTM_NEWLINK, flags=NLM_F_REQUEST|NLM_F_ACK, seq=1668185923, pid=0}, 525 * {ifi_family=AF_UNSPEC, ifi_type=ARPHRD_NETROM, ifi_index=if_nametoindex("lo"), ifi_flags=0, ifi_change=0}, 526 * {{nla_len=8, nla_type=IFLA_MTU}, 123}} 527 * 528 * 529 * Check command availability: 530 * type=RTM_NEWLINK, flags=NLM_F_REQUEST|NLM_F_ACK, seq=0, pid=0}, 531 * {ifi_family=AF_UNSPEC, ifi_type=ARPHRD_NETROM, ifi_index=0, ifi_flags=0, ifi_change=0} 532 */ 533 534 535 static int 536 create_link(struct nlmsghdr *hdr, struct nl_parsed_link *lattrs, 537 struct nlattr_bmask *bm, struct nlpcb *nlp, struct nl_pstate *npt) 538 { 539 if (lattrs->ifla_ifname == NULL || strlen(lattrs->ifla_ifname) == 0) { 540 NLMSG_REPORT_ERR_MSG(npt, "empty IFLA_IFNAME attribute"); 541 return (EINVAL); 542 } 543 if (lattrs->ifla_cloner == NULL || strlen(lattrs->ifla_cloner) == 0) { 544 NLMSG_REPORT_ERR_MSG(npt, "empty IFLA_INFO_KIND attribute"); 545 return (EINVAL); 546 } 547 548 bool found = false; 549 int error = 0; 550 551 sx_slock(&rtnl_cloner_lock); 552 struct nl_cloner *cloner = rtnl_iface_find_cloner_locked(lattrs->ifla_cloner); 553 if (cloner != NULL) { 554 found = true; 555 error = cloner->create_f(lattrs, bm, nlp, npt); 556 } 557 sx_sunlock(&rtnl_cloner_lock); 558 559 if (!found) 560 error = generic_cloner.create_f(lattrs, bm, nlp, npt); 561 562 return (error); 563 } 564 565 static int 566 modify_link(struct nlmsghdr *hdr, struct nl_parsed_link *lattrs, 567 struct nlattr_bmask *bm, struct nlpcb *nlp, struct nl_pstate *npt) 568 { 569 struct ifnet *ifp = NULL; 570 struct epoch_tracker et; 571 572 if (lattrs->ifi_index == 0 && lattrs->ifla_ifname == NULL) { 573 /* 574 * Applications like ip(8) verify RTM_NEWLINK command 575 * existence by calling it with empty arguments. Always 576 * return "innocent" error in that case. 577 */ 578 NLMSG_REPORT_ERR_MSG(npt, "empty ifi_index field"); 579 return (EPERM); 580 } 581 582 if (lattrs->ifi_index != 0) { 583 NET_EPOCH_ENTER(et); 584 ifp = ifnet_byindex_ref(lattrs->ifi_index); 585 NET_EPOCH_EXIT(et); 586 if (ifp == NULL) { 587 NLMSG_REPORT_ERR_MSG(npt, "unable to find interface #%u", 588 lattrs->ifi_index); 589 return (ENOENT); 590 } 591 } 592 593 if (ifp == NULL && lattrs->ifla_ifname != NULL) { 594 ifp = ifunit_ref(lattrs->ifla_ifname); 595 if (ifp == NULL) { 596 NLMSG_REPORT_ERR_MSG(npt, "unable to find interface %s", 597 lattrs->ifla_ifname); 598 return (ENOENT); 599 } 600 } 601 602 MPASS(ifp != NULL); 603 604 /* 605 * There can be multiple kinds of interfaces: 606 * 1) cloned, with additional options 607 * 2) cloned, but w/o additional options 608 * 3) non-cloned (e.g. "physical). 609 * 610 * Thus, try to find cloner-specific callback and fallback to the 611 * "default" handler if not found. 612 */ 613 bool found = false; 614 int error = 0; 615 616 sx_slock(&rtnl_cloner_lock); 617 struct nl_cloner *cloner = rtnl_iface_find_cloner_locked(ifp->if_dname); 618 if (cloner != NULL) { 619 found = true; 620 error = cloner->modify_f(ifp, lattrs, bm, nlp, npt); 621 } 622 sx_sunlock(&rtnl_cloner_lock); 623 624 if (!found) 625 error = generic_cloner.modify_f(ifp, lattrs, bm, nlp, npt); 626 627 if_rele(ifp); 628 629 return (error); 630 } 631 632 633 static int 634 rtnl_handle_newlink(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate *npt) 635 { 636 struct nlattr_bmask bm; 637 int error; 638 639 struct nl_parsed_link attrs = {}; 640 error = nl_parse_nlmsg(hdr, &ifmsg_parser, npt, &attrs); 641 if (error != 0) 642 return (error); 643 nl_get_attrs_bmask_nlmsg(hdr, &ifmsg_parser, &bm); 644 645 if (hdr->nlmsg_flags & NLM_F_CREATE) 646 return (create_link(hdr, &attrs, &bm, nlp, npt)); 647 else 648 return (modify_link(hdr, &attrs, &bm, nlp, npt)); 649 } 650 651 struct nl_parsed_ifa { 652 uint8_t ifa_family; 653 uint8_t ifa_prefixlen; 654 uint8_t ifa_scope; 655 uint32_t ifa_index; 656 uint32_t ifa_flags; 657 struct sockaddr *ifa_address; 658 struct sockaddr *ifa_local; 659 }; 660 661 #define _IN(_field) offsetof(struct ifaddrmsg, _field) 662 #define _OUT(_field) offsetof(struct nl_parsed_ifa, _field) 663 static const struct nlfield_parser nlf_p_ifa[] = { 664 { .off_in = _IN(ifa_family), .off_out = _OUT(ifa_family), .cb = nlf_get_u8 }, 665 { .off_in = _IN(ifa_prefixlen), .off_out = _OUT(ifa_prefixlen), .cb = nlf_get_u8 }, 666 { .off_in = _IN(ifa_scope), .off_out = _OUT(ifa_scope), .cb = nlf_get_u8 }, 667 { .off_in = _IN(ifa_flags), .off_out = _OUT(ifa_flags), .cb = nlf_get_u8_u32 }, 668 { .off_in = _IN(ifa_index), .off_out = _OUT(ifa_index), .cb = nlf_get_u32 }, 669 }; 670 671 static const struct nlattr_parser nla_p_ifa[] = { 672 { .type = IFA_ADDRESS, .off = _OUT(ifa_address), .cb = nlattr_get_ip }, 673 { .type = IFA_LOCAL, .off = _OUT(ifa_local), .cb = nlattr_get_ip }, 674 { .type = IFA_FLAGS, .off = _OUT(ifa_flags), .cb = nlattr_get_uint32 }, 675 }; 676 #undef _IN 677 #undef _OUT 678 NL_DECLARE_PARSER(ifaddrmsg_parser, struct ifaddrmsg, nlf_p_ifa, nla_p_ifa); 679 680 681 /* 682 683 {ifa_family=AF_INET, ifa_prefixlen=8, ifa_flags=IFA_F_PERMANENT, ifa_scope=RT_SCOPE_HOST, ifa_index=if_nametoindex("lo")}, 684 [ 685 {{nla_len=8, nla_type=IFA_ADDRESS}, inet_addr("127.0.0.1")}, 686 {{nla_len=8, nla_type=IFA_LOCAL}, inet_addr("127.0.0.1")}, 687 {{nla_len=7, nla_type=IFA_LABEL}, "lo"}, 688 {{nla_len=8, nla_type=IFA_FLAGS}, IFA_F_PERMANENT}, 689 {{nla_len=20, nla_type=IFA_CACHEINFO}, {ifa_prefered=4294967295, ifa_valid=4294967295, cstamp=3619, tstamp=3619}}]}, 690 --- 691 692 {{len=72, type=RTM_NEWADDR, flags=NLM_F_MULTI, seq=1642191126, pid=566735}, 693 {ifa_family=AF_INET6, ifa_prefixlen=96, ifa_flags=IFA_F_PERMANENT, ifa_scope=RT_SCOPE_UNIVERSE, ifa_index=if_nametoindex("virbr0")}, 694 [ 695 {{nla_len=20, nla_type=IFA_ADDRESS}, inet_pton(AF_INET6, "2a01:4f8:13a:70c:ffff::1")}, 696 {{nla_len=20, nla_type=IFA_CACHEINFO}, {ifa_prefered=4294967295, ifa_valid=4294967295, cstamp=4283, tstamp=4283}}, 697 {{nla_len=8, nla_type=IFA_FLAGS}, IFA_F_PERMANENT}]}, 698 */ 699 700 static uint8_t 701 ifa_get_scope(const struct ifaddr *ifa) 702 { 703 const struct sockaddr *sa; 704 uint8_t addr_scope = RT_SCOPE_UNIVERSE; 705 706 sa = ifa->ifa_addr; 707 switch (sa->sa_family) { 708 #ifdef INET 709 case AF_INET: 710 { 711 struct in_addr addr; 712 addr = ((const struct sockaddr_in *)sa)->sin_addr; 713 if (IN_LOOPBACK(addr.s_addr)) 714 addr_scope = RT_SCOPE_HOST; 715 else if (IN_LINKLOCAL(addr.s_addr)) 716 addr_scope = RT_SCOPE_LINK; 717 break; 718 } 719 #endif 720 #ifdef INET6 721 case AF_INET6: 722 { 723 const struct in6_addr *addr; 724 addr = &((const struct sockaddr_in6 *)sa)->sin6_addr; 725 if (IN6_IS_ADDR_LOOPBACK(addr)) 726 addr_scope = RT_SCOPE_HOST; 727 else if (IN6_IS_ADDR_LINKLOCAL(addr)) 728 addr_scope = RT_SCOPE_LINK; 729 break; 730 } 731 #endif 732 } 733 734 return (addr_scope); 735 } 736 737 #ifdef INET6 738 static uint8_t 739 inet6_get_plen(const struct in6_addr *addr) 740 { 741 742 return (bitcount32(addr->s6_addr32[0]) + bitcount32(addr->s6_addr32[1]) + 743 bitcount32(addr->s6_addr32[2]) + bitcount32(addr->s6_addr32[3])); 744 } 745 #endif 746 747 static uint8_t 748 get_sa_plen(const struct sockaddr *sa) 749 { 750 #ifdef INET 751 const struct in_addr *paddr; 752 #endif 753 #ifdef INET6 754 const struct in6_addr *paddr6; 755 #endif 756 757 switch (sa->sa_family) { 758 #ifdef INET 759 case AF_INET: 760 paddr = &(((const struct sockaddr_in *)sa)->sin_addr); 761 return bitcount32(paddr->s_addr);; 762 #endif 763 #ifdef INET6 764 case AF_INET6: 765 paddr6 = &(((const struct sockaddr_in6 *)sa)->sin6_addr); 766 return inet6_get_plen(paddr6); 767 #endif 768 } 769 770 return (0); 771 } 772 773 774 /* 775 * {'attrs': [('IFA_ADDRESS', '12.0.0.1'), 776 ('IFA_LOCAL', '12.0.0.1'), 777 ('IFA_LABEL', 'eth10'), 778 ('IFA_FLAGS', 128), 779 ('IFA_CACHEINFO', {'ifa_preferred': 4294967295, 'ifa_valid': 4294967295, 'cstamp': 63745746, 'tstamp': 63745746})], 780 */ 781 static bool 782 dump_iface_addr(struct nl_writer *nw, struct ifnet *ifp, struct ifaddr *ifa, 783 const struct nlmsghdr *hdr) 784 { 785 struct ifaddrmsg *ifamsg; 786 struct sockaddr *sa = ifa->ifa_addr; 787 788 NL_LOG(LOG_DEBUG3, "dumping ifa %p type %s(%d) for interface %s", 789 ifa, rib_print_family(sa->sa_family), sa->sa_family, if_name(ifp)); 790 791 if (!nlmsg_reply(nw, hdr, sizeof(struct ifaddrmsg))) 792 goto enomem; 793 794 ifamsg = nlmsg_reserve_object(nw, struct ifaddrmsg); 795 ifamsg->ifa_family = sa->sa_family; 796 ifamsg->ifa_prefixlen = get_sa_plen(ifa->ifa_netmask); 797 ifamsg->ifa_flags = 0; // ifa_flags is useless 798 ifamsg->ifa_scope = ifa_get_scope(ifa); 799 ifamsg->ifa_index = ifp->if_index; 800 801 if (ifp->if_flags & IFF_POINTOPOINT) { 802 dump_sa(nw, IFA_ADDRESS, ifa->ifa_dstaddr); 803 dump_sa(nw, IFA_LOCAL, sa); 804 } else { 805 dump_sa(nw, IFA_ADDRESS, sa); 806 #ifdef INET 807 /* 808 * In most cases, IFA_ADDRESS == IFA_LOCAL 809 * Skip IFA_LOCAL for anything except INET 810 */ 811 if (sa->sa_family == AF_INET) 812 dump_sa(nw, IFA_LOCAL, sa); 813 #endif 814 } 815 if (ifp->if_flags & IFF_BROADCAST) 816 dump_sa(nw, IFA_BROADCAST, ifa->ifa_broadaddr); 817 818 nlattr_add_string(nw, IFA_LABEL, if_name(ifp)); 819 820 uint32_t val = 0; // ifa->ifa_flags; 821 nlattr_add_u32(nw, IFA_FLAGS, val); 822 823 if (nlmsg_end(nw)) 824 return (true); 825 enomem: 826 NL_LOG(LOG_DEBUG, "Failed to dump ifa type %s(%d) for interface %s", 827 rib_print_family(sa->sa_family), sa->sa_family, if_name(ifp)); 828 nlmsg_abort(nw); 829 return (false); 830 } 831 832 static int 833 dump_iface_addrs(struct netlink_walkargs *wa, struct ifnet *ifp) 834 { 835 struct ifaddr *ifa; 836 837 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 838 if (wa->family != 0 && wa->family != ifa->ifa_addr->sa_family) 839 continue; 840 if (ifa->ifa_addr->sa_family == AF_LINK) 841 continue; 842 if (prison_if(wa->cred, ifa->ifa_addr) != 0) 843 continue; 844 wa->count++; 845 if (!dump_iface_addr(wa->nw, ifp, ifa, &wa->hdr)) 846 return (ENOMEM); 847 wa->dumped++; 848 } 849 850 return (0); 851 } 852 853 static int 854 rtnl_handle_getaddr(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate *npt) 855 { 856 struct ifnet *ifp; 857 int error = 0; 858 859 struct nl_parsed_ifa attrs = {}; 860 error = nl_parse_nlmsg(hdr, &ifaddrmsg_parser, npt, &attrs); 861 if (error != 0) 862 return (error); 863 864 struct netlink_walkargs wa = { 865 .so = nlp, 866 .nw = npt->nw, 867 .cred = nlp_get_cred(nlp), 868 .family = attrs.ifa_family, 869 .hdr.nlmsg_pid = hdr->nlmsg_pid, 870 .hdr.nlmsg_seq = hdr->nlmsg_seq, 871 .hdr.nlmsg_flags = hdr->nlmsg_flags | NLM_F_MULTI, 872 .hdr.nlmsg_type = NL_RTM_NEWADDR, 873 }; 874 875 NL_LOG(LOG_DEBUG2, "Start dump"); 876 877 if (attrs.ifa_index != 0) { 878 ifp = ifnet_byindex(attrs.ifa_index); 879 if (ifp == NULL) 880 error = ENOENT; 881 else 882 error = dump_iface_addrs(&wa, ifp); 883 } else { 884 CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { 885 error = dump_iface_addrs(&wa, ifp); 886 if (error != 0) 887 break; 888 } 889 } 890 891 NL_LOG(LOG_DEBUG2, "End dump, iterated %d dumped %d", wa.count, wa.dumped); 892 893 if (!nlmsg_end_dump(wa.nw, error, &wa.hdr)) { 894 NL_LOG(LOG_DEBUG, "Unable to finalize the dump"); 895 return (ENOMEM); 896 } 897 898 return (error); 899 } 900 901 static void 902 rtnl_handle_ifaddr(void *arg __unused, struct ifaddr *ifa, int cmd) 903 { 904 struct nlmsghdr hdr = {}; 905 struct nl_writer nw = {}; 906 uint32_t group = 0; 907 908 switch (ifa->ifa_addr->sa_family) { 909 #ifdef INET 910 case AF_INET: 911 group = RTNLGRP_IPV4_IFADDR; 912 break; 913 #endif 914 #ifdef INET6 915 case AF_INET6: 916 group = RTNLGRP_IPV6_IFADDR; 917 break; 918 #endif 919 default: 920 NL_LOG(LOG_DEBUG2, "ifa notification for unknown AF: %d", 921 ifa->ifa_addr->sa_family); 922 return; 923 } 924 925 if (!nl_has_listeners(NETLINK_ROUTE, group)) 926 return; 927 928 if (!nlmsg_get_group_writer(&nw, NLMSG_LARGE, NETLINK_ROUTE, group)) { 929 NL_LOG(LOG_DEBUG, "error allocating group writer"); 930 return; 931 } 932 933 hdr.nlmsg_type = (cmd == RTM_DELETE) ? NL_RTM_DELADDR : NL_RTM_NEWADDR; 934 935 dump_iface_addr(&nw, ifa->ifa_ifp, ifa, &hdr); 936 nlmsg_flush(&nw); 937 } 938 939 static void 940 rtnl_handle_ifevent(struct ifnet *ifp, int nlmsg_type, int if_flags_mask) 941 { 942 struct nlmsghdr hdr = { .nlmsg_type = nlmsg_type }; 943 struct nl_writer nw = {}; 944 945 if (!nl_has_listeners(NETLINK_ROUTE, RTNLGRP_LINK)) 946 return; 947 948 if (!nlmsg_get_group_writer(&nw, NLMSG_LARGE, NETLINK_ROUTE, RTNLGRP_LINK)) { 949 NL_LOG(LOG_DEBUG, "error allocating mbuf"); 950 return; 951 } 952 dump_iface(&nw, ifp, &hdr, if_flags_mask); 953 nlmsg_flush(&nw); 954 } 955 956 static void 957 rtnl_handle_ifattach(void *arg, struct ifnet *ifp) 958 { 959 NL_LOG(LOG_DEBUG2, "ifnet %s", if_name(ifp)); 960 rtnl_handle_ifevent(ifp, NL_RTM_NEWLINK, 0); 961 } 962 963 static void 964 rtnl_handle_ifdetach(void *arg, struct ifnet *ifp) 965 { 966 NL_LOG(LOG_DEBUG2, "ifnet %s", if_name(ifp)); 967 rtnl_handle_ifevent(ifp, NL_RTM_DELLINK, 0); 968 } 969 970 static void 971 rtnl_handle_iflink(void *arg, struct ifnet *ifp) 972 { 973 NL_LOG(LOG_DEBUG2, "ifnet %s", if_name(ifp)); 974 rtnl_handle_ifevent(ifp, NL_RTM_NEWLINK, 0); 975 } 976 977 void 978 rtnl_handle_ifnet_event(struct ifnet *ifp, int if_flags_mask) 979 { 980 NL_LOG(LOG_DEBUG2, "ifnet %s", if_name(ifp)); 981 rtnl_handle_ifevent(ifp, NL_RTM_NEWLINK, if_flags_mask); 982 } 983 984 static const struct rtnl_cmd_handler cmd_handlers[] = { 985 { 986 .cmd = NL_RTM_GETLINK, 987 .name = "RTM_GETLINK", 988 .cb = &rtnl_handle_getlink, 989 .flags = RTNL_F_NOEPOCH | RTNL_F_ALLOW_NONVNET_JAIL, 990 }, 991 { 992 .cmd = NL_RTM_DELLINK, 993 .name = "RTM_DELLINK", 994 .cb = &rtnl_handle_dellink, 995 .priv = PRIV_NET_IFDESTROY, 996 .flags = RTNL_F_NOEPOCH, 997 }, 998 { 999 .cmd = NL_RTM_NEWLINK, 1000 .name = "RTM_NEWLINK", 1001 .cb = &rtnl_handle_newlink, 1002 .priv = PRIV_NET_IFCREATE, 1003 .flags = RTNL_F_NOEPOCH, 1004 }, 1005 { 1006 .cmd = NL_RTM_GETADDR, 1007 .name = "RTM_GETADDR", 1008 .cb = &rtnl_handle_getaddr, 1009 .flags = RTNL_F_ALLOW_NONVNET_JAIL, 1010 }, 1011 { 1012 .cmd = NL_RTM_NEWADDR, 1013 .name = "RTM_NEWADDR", 1014 .cb = &rtnl_handle_getaddr, 1015 }, 1016 { 1017 .cmd = NL_RTM_DELADDR, 1018 .name = "RTM_DELADDR", 1019 .cb = &rtnl_handle_getaddr, 1020 }, 1021 }; 1022 1023 static const struct nlhdr_parser *all_parsers[] = { &ifmsg_parser, &ifaddrmsg_parser }; 1024 1025 void 1026 rtnl_iface_add_cloner(struct nl_cloner *cloner) 1027 { 1028 sx_xlock(&rtnl_cloner_lock); 1029 SLIST_INSERT_HEAD(&nl_cloners, cloner, next); 1030 sx_xunlock(&rtnl_cloner_lock); 1031 } 1032 1033 void 1034 rtnl_iface_del_cloner(struct nl_cloner *cloner) 1035 { 1036 sx_xlock(&rtnl_cloner_lock); 1037 SLIST_REMOVE(&nl_cloners, cloner, nl_cloner, next); 1038 sx_xunlock(&rtnl_cloner_lock); 1039 } 1040 1041 static struct nl_cloner * 1042 rtnl_iface_find_cloner_locked(const char *name) 1043 { 1044 struct nl_cloner *cloner; 1045 1046 SLIST_FOREACH(cloner, &nl_cloners, next) { 1047 if (!strcmp(name, cloner->name)) 1048 return (cloner); 1049 } 1050 1051 return (NULL); 1052 } 1053 1054 void 1055 rtnl_ifaces_init(void) 1056 { 1057 ifattach_event = EVENTHANDLER_REGISTER( 1058 ifnet_arrival_event, rtnl_handle_ifattach, NULL, 1059 EVENTHANDLER_PRI_ANY); 1060 ifdetach_event = EVENTHANDLER_REGISTER( 1061 ifnet_departure_event, rtnl_handle_ifdetach, NULL, 1062 EVENTHANDLER_PRI_ANY); 1063 ifaddr_event = EVENTHANDLER_REGISTER( 1064 rt_addrmsg, rtnl_handle_ifaddr, NULL, 1065 EVENTHANDLER_PRI_ANY); 1066 iflink_event = EVENTHANDLER_REGISTER( 1067 ifnet_link_event, rtnl_handle_iflink, NULL, 1068 EVENTHANDLER_PRI_ANY); 1069 NL_VERIFY_PARSERS(all_parsers); 1070 rtnl_iface_drivers_register(); 1071 rtnl_register_messages(cmd_handlers, NL_ARRAY_LEN(cmd_handlers)); 1072 } 1073 1074 void 1075 rtnl_ifaces_destroy(void) 1076 { 1077 EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ifattach_event); 1078 EVENTHANDLER_DEREGISTER(ifnet_departure_event, ifdetach_event); 1079 EVENTHANDLER_DEREGISTER(rt_addrmsg, ifaddr_event); 1080 EVENTHANDLER_DEREGISTER(ifnet_link_event, iflink_event); 1081 } 1082