1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2022 Alexander V. Chernikov 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_inet.h" 29 #include "opt_inet6.h" 30 31 #include <sys/types.h> 32 #include <sys/ck.h> 33 #include <sys/lock.h> 34 #include <sys/socket.h> 35 #include <sys/vnode.h> 36 37 #include <net/if.h> 38 #include <net/if_dl.h> 39 #include <net/route.h> 40 #include <net/route/nhop.h> 41 #include <net/route/route_ctl.h> 42 #include <netlink/netlink.h> 43 #include <netlink/netlink_ctl.h> 44 #include <netlink/netlink_linux.h> 45 #include <netlink/netlink_var.h> 46 #include <netlink/netlink_route.h> 47 48 #include <compat/linux/linux.h> 49 #include <compat/linux/linux_common.h> 50 #include <compat/linux/linux_util.h> 51 52 #define DEBUG_MOD_NAME nl_linux 53 #define DEBUG_MAX_LEVEL LOG_DEBUG3 54 #include <netlink/netlink_debug.h> 55 _DECLARE_DEBUG(LOG_INFO); 56 57 static bool 58 valid_rta_size(const struct rtattr *rta, int sz) 59 { 60 return (NL_RTA_DATA_LEN(rta) == sz); 61 } 62 63 static bool 64 valid_rta_u32(const struct rtattr *rta) 65 { 66 return (valid_rta_size(rta, sizeof(uint32_t))); 67 } 68 69 static uint32_t 70 _rta_get_uint32(const struct rtattr *rta) 71 { 72 return (*((const uint32_t *)NL_RTA_DATA_CONST(rta))); 73 } 74 75 static int 76 rtnl_neigh_from_linux(struct nlmsghdr *hdr, struct nl_pstate *npt) 77 { 78 struct ndmsg *ndm = (struct ndmsg *)(hdr + 1); 79 sa_family_t f; 80 81 if (hdr->nlmsg_len < sizeof(struct nlmsghdr) + sizeof(struct ndmsg)) 82 return (EBADMSG); 83 if ((f = linux_to_bsd_domain(ndm->ndm_family)) == AF_UNKNOWN) 84 return (EPFNOSUPPORT); 85 86 ndm->ndm_family = f; 87 88 return (0); 89 } 90 91 static int 92 rtnl_ifaddr_from_linux(struct nlmsghdr *hdr, struct nl_pstate *npt) 93 { 94 struct ifaddrmsg *ifam = (struct ifaddrmsg *)(hdr + 1); 95 sa_family_t f; 96 97 if (hdr->nlmsg_len < sizeof(struct nlmsghdr) + 98 offsetof(struct ifaddrmsg, ifa_family) + sizeof(ifam->ifa_family)) 99 return (EBADMSG); 100 if ((f = linux_to_bsd_domain(ifam->ifa_family)) == AF_UNKNOWN) 101 return (EPFNOSUPPORT); 102 103 ifam->ifa_family = f; 104 105 return (0); 106 } 107 108 /* 109 * XXX: in case of error state of hdr is inconsistent. 110 */ 111 static int 112 rtnl_route_from_linux(struct nlmsghdr *hdr, struct nl_pstate *npt) 113 { 114 /* Tweak address families and default fib only */ 115 struct rtmsg *rtm = (struct rtmsg *)(hdr + 1); 116 struct nlattr *nla, *nla_head; 117 int attrs_len; 118 sa_family_t f; 119 120 if (hdr->nlmsg_len < sizeof(struct nlmsghdr) + sizeof(struct rtmsg)) 121 return (EBADMSG); 122 if ((f = linux_to_bsd_domain(rtm->rtm_family)) == AF_UNKNOWN) 123 return (EPFNOSUPPORT); 124 rtm->rtm_family = f; 125 126 if (rtm->rtm_table == 254) 127 rtm->rtm_table = 0; 128 129 attrs_len = hdr->nlmsg_len - sizeof(struct nlmsghdr); 130 attrs_len -= NETLINK_ALIGN(sizeof(struct rtmsg)); 131 nla_head = (struct nlattr *)((char *)rtm + NETLINK_ALIGN(sizeof(struct rtmsg))); 132 133 NLA_FOREACH(nla, nla_head, attrs_len) { 134 RT_LOG(LOG_DEBUG3, "GOT type %d len %d total %d", 135 nla->nla_type, nla->nla_len, attrs_len); 136 struct rtattr *rta = (struct rtattr *)nla; 137 if (rta->rta_len < sizeof(struct rtattr)) { 138 break; 139 } 140 switch (rta->rta_type) { 141 case NL_RTA_TABLE: 142 if (!valid_rta_u32(rta)) 143 return (EBADMSG); 144 rtm->rtm_table = 0; 145 uint32_t fibnum = _rta_get_uint32(rta); 146 RT_LOG(LOG_DEBUG3, "GET RTABLE: %u", fibnum); 147 if (fibnum == 254) { 148 *((uint32_t *)NL_RTA_DATA(rta)) = 0; 149 } 150 break; 151 } 152 } 153 154 return (0); 155 } 156 157 static int 158 rtnl_from_linux(struct nlmsghdr *hdr, struct nl_pstate *npt) 159 { 160 161 switch (hdr->nlmsg_type) { 162 case NL_RTM_GETROUTE: 163 case NL_RTM_NEWROUTE: 164 case NL_RTM_DELROUTE: 165 return (rtnl_route_from_linux(hdr, npt)); 166 case NL_RTM_GETNEIGH: 167 return (rtnl_neigh_from_linux(hdr, npt)); 168 case NL_RTM_GETADDR: 169 return (rtnl_ifaddr_from_linux(hdr, npt)); 170 /* Silence warning for the messages where no translation is required */ 171 case NL_RTM_NEWLINK: 172 case NL_RTM_DELLINK: 173 case NL_RTM_GETLINK: 174 break; 175 default: 176 RT_LOG(LOG_DEBUG, "Passing message type %d untranslated", 177 hdr->nlmsg_type); 178 /* XXXGL: maybe return error? */ 179 } 180 181 return (0); 182 } 183 184 static int 185 nlmsg_from_linux(int netlink_family, struct nlmsghdr **hdr, 186 struct nl_pstate *npt) 187 { 188 switch (netlink_family) { 189 case NETLINK_ROUTE: 190 return (rtnl_from_linux(*hdr, npt)); 191 } 192 193 return (0); 194 } 195 196 197 /************************************************************ 198 * Kernel -> Linux 199 ************************************************************/ 200 201 static bool 202 handle_default_out(struct nlmsghdr *hdr, struct nl_writer *nw) 203 { 204 char *out_hdr; 205 out_hdr = nlmsg_reserve_data(nw, NLMSG_ALIGN(hdr->nlmsg_len), char); 206 207 if (out_hdr != NULL) { 208 memcpy(out_hdr, hdr, hdr->nlmsg_len); 209 nw->num_messages++; 210 return (true); 211 } 212 return (false); 213 } 214 215 static bool 216 nlmsg_copy_header(struct nlmsghdr *hdr, struct nl_writer *nw) 217 { 218 return (nlmsg_add(nw, hdr->nlmsg_pid, hdr->nlmsg_seq, hdr->nlmsg_type, 219 hdr->nlmsg_flags, 0)); 220 } 221 222 static void * 223 _nlmsg_copy_next_header(struct nlmsghdr *hdr, struct nl_writer *nw, int sz) 224 { 225 void *next_hdr = nlmsg_reserve_data(nw, sz, void); 226 memcpy(next_hdr, hdr + 1, NLMSG_ALIGN(sz)); 227 228 return (next_hdr); 229 } 230 #define nlmsg_copy_next_header(_hdr, _ns, _t) \ 231 ((_t *)(_nlmsg_copy_next_header(_hdr, _ns, sizeof(_t)))) 232 233 static bool 234 nlmsg_copy_nla(const struct nlattr *nla_orig, struct nl_writer *nw) 235 { 236 struct nlattr *nla = nlmsg_reserve_data(nw, nla_orig->nla_len, struct nlattr); 237 if (nla != NULL) { 238 memcpy(nla, nla_orig, nla_orig->nla_len); 239 return (true); 240 } 241 return (false); 242 } 243 244 /* 245 * Translate a FreeBSD interface name to a Linux interface name. 246 */ 247 static bool 248 nlmsg_translate_ifname_nla(struct nlattr *nla, struct nl_writer *nw) 249 { 250 char ifname[LINUX_IFNAMSIZ]; 251 252 if (nw->ifp == NULL) 253 return (false); 254 (void)ifname_bsd_to_linux_ifp(nw->ifp, ifname, sizeof(ifname)); 255 return (nlattr_add_string(nw, IFLA_IFNAME, ifname)); 256 } 257 258 #define LINUX_NLA_UNHANDLED -1 259 /* 260 * Translate a FreeBSD attribute to a Linux attribute. 261 * Returns LINUX_NLA_UNHANDLED when the attribute is not processed 262 * and the caller must take care of it, otherwise the result is returned. 263 */ 264 static int 265 nlmsg_translate_all_nla(struct nlmsghdr *hdr, struct nlattr *nla, 266 struct nl_writer *nw) 267 { 268 269 switch (hdr->nlmsg_type) { 270 case NL_RTM_NEWLINK: 271 case NL_RTM_DELLINK: 272 case NL_RTM_GETLINK: 273 switch (nla->nla_type) { 274 case IFLA_IFNAME: 275 return (nlmsg_translate_ifname_nla(nla, nw)); 276 default: 277 break; 278 } 279 default: 280 break; 281 } 282 return (LINUX_NLA_UNHANDLED); 283 } 284 285 static bool 286 nlmsg_copy_all_nla(struct nlmsghdr *hdr, int raw_hdrlen, struct nl_writer *nw) 287 { 288 struct nlattr *nla; 289 int ret; 290 291 int hdrlen = NETLINK_ALIGN(raw_hdrlen); 292 int attrs_len = hdr->nlmsg_len - sizeof(struct nlmsghdr) - hdrlen; 293 struct nlattr *nla_head = (struct nlattr *)((char *)(hdr + 1) + hdrlen); 294 295 NLA_FOREACH(nla, nla_head, attrs_len) { 296 RT_LOG(LOG_DEBUG3, "reading attr %d len %d", nla->nla_type, nla->nla_len); 297 if (nla->nla_len < sizeof(struct nlattr)) { 298 return (false); 299 } 300 ret = nlmsg_translate_all_nla(hdr, nla, nw); 301 if (ret == LINUX_NLA_UNHANDLED) 302 ret = nlmsg_copy_nla(nla, nw); 303 if (!ret) 304 return (false); 305 } 306 return (true); 307 } 308 #undef LINUX_NLA_UNHANDLED 309 310 static unsigned int 311 rtnl_if_flags_to_linux(unsigned int if_flags) 312 { 313 unsigned int result = 0; 314 315 for (int i = 0; i < 31; i++) { 316 unsigned int flag = 1 << i; 317 if (!(flag & if_flags)) 318 continue; 319 switch (flag) { 320 case IFF_UP: 321 case IFF_BROADCAST: 322 case IFF_DEBUG: 323 case IFF_LOOPBACK: 324 case IFF_POINTOPOINT: 325 case IFF_DRV_RUNNING: 326 case IFF_NOARP: 327 case IFF_PROMISC: 328 case IFF_ALLMULTI: 329 result |= flag; 330 break; 331 case IFF_NEEDSEPOCH: 332 case IFF_DRV_OACTIVE: 333 case IFF_SIMPLEX: 334 case IFF_LINK0: 335 case IFF_LINK1: 336 case IFF_LINK2: 337 case IFF_CANTCONFIG: 338 case IFF_PPROMISC: 339 case IFF_MONITOR: 340 case IFF_STATICARP: 341 case IFF_STICKYARP: 342 case IFF_DYING: 343 /* No Linux analogue */ 344 break; 345 case IFF_LOWER_UP: /* IFF_NETLINK_1 */ 346 result |= LINUX_IFF_LOWER_UP; 347 break; 348 case IFF_MULTICAST: 349 result |= LINUX_IFF_MULTICAST; 350 } 351 } 352 return (result); 353 } 354 355 static bool 356 rtnl_newlink_to_linux(struct nlmsghdr *hdr, struct nlpcb *nlp, 357 struct nl_writer *nw) 358 { 359 if (!nlmsg_copy_header(hdr, nw)) 360 return (false); 361 362 struct ifinfomsg *ifinfo; 363 ifinfo = nlmsg_copy_next_header(hdr, nw, struct ifinfomsg); 364 365 ifinfo->ifi_family = bsd_to_linux_domain(ifinfo->ifi_family); 366 /* Convert interface type */ 367 switch (ifinfo->ifi_type) { 368 case IFT_ETHER: 369 case IFT_BRIDGE: 370 case IFT_L2VLAN: 371 ifinfo->ifi_type = LINUX_ARPHRD_ETHER; 372 break; 373 case IFT_LOOP: 374 ifinfo->ifi_type = LINUX_ARPHRD_LOOPBACK; 375 break; 376 case IFT_STF: 377 ifinfo->ifi_type = LINUX_ARPHRD_SIT; 378 break; 379 } 380 ifinfo->ifi_flags = rtnl_if_flags_to_linux(ifinfo->ifi_flags); 381 382 /* Copy attributes unchanged */ 383 if (!nlmsg_copy_all_nla(hdr, sizeof(struct ifinfomsg), nw)) 384 return (false); 385 386 /* make ip(8) happy */ 387 if (!nlattr_add_string(nw, IFLA_QDISC, "noqueue")) 388 return (false); 389 390 if (!nlattr_add_u32(nw, IFLA_TXQLEN, 1000)) 391 return (false); 392 393 nlmsg_end(nw); 394 RT_LOG(LOG_DEBUG2, "done processing nw %p", nw); 395 return (true); 396 } 397 398 static bool 399 rtnl_newaddr_to_linux(struct nlmsghdr *hdr, struct nlpcb *nlp, 400 struct nl_writer *nw) 401 { 402 if (!nlmsg_copy_header(hdr, nw)) 403 return (false); 404 405 struct ifaddrmsg *ifamsg; 406 ifamsg = nlmsg_copy_next_header(hdr, nw, struct ifaddrmsg); 407 408 ifamsg->ifa_family = bsd_to_linux_domain(ifamsg->ifa_family); 409 /* XXX: fake ifa_flags? */ 410 411 /* Copy attributes unchanged */ 412 if (!nlmsg_copy_all_nla(hdr, sizeof(struct ifaddrmsg), nw)) 413 return (false); 414 415 nlmsg_end(nw); 416 RT_LOG(LOG_DEBUG2, "done processing nw %p", nw); 417 return (true); 418 } 419 420 static bool 421 rtnl_newneigh_to_linux(struct nlmsghdr *hdr, struct nlpcb *nlp, 422 struct nl_writer *nw) 423 { 424 if (!nlmsg_copy_header(hdr, nw)) 425 return (false); 426 427 struct ndmsg *ndm; 428 ndm = nlmsg_copy_next_header(hdr, nw, struct ndmsg); 429 430 ndm->ndm_family = bsd_to_linux_domain(ndm->ndm_family); 431 432 /* Copy attributes unchanged */ 433 if (!nlmsg_copy_all_nla(hdr, sizeof(struct ndmsg), nw)) 434 return (false); 435 436 nlmsg_end(nw); 437 RT_LOG(LOG_DEBUG2, "done processing nw %p", nw); 438 return (true); 439 } 440 441 static bool 442 rtnl_newroute_to_linux(struct nlmsghdr *hdr, struct nlpcb *nlp, 443 struct nl_writer *nw) 444 { 445 if (!nlmsg_copy_header(hdr, nw)) 446 return (false); 447 448 struct rtmsg *rtm; 449 rtm = nlmsg_copy_next_header(hdr, nw, struct rtmsg); 450 rtm->rtm_family = bsd_to_linux_domain(rtm->rtm_family); 451 452 struct nlattr *nla; 453 454 int hdrlen = NETLINK_ALIGN(sizeof(struct rtmsg)); 455 int attrs_len = hdr->nlmsg_len - sizeof(struct nlmsghdr) - hdrlen; 456 struct nlattr *nla_head = (struct nlattr *)((char *)(hdr + 1) + hdrlen); 457 458 NLA_FOREACH(nla, nla_head, attrs_len) { 459 struct rtattr *rta = (struct rtattr *)nla; 460 //RT_LOG(LOG_DEBUG, "READING attr %d len %d", nla->nla_type, nla->nla_len); 461 if (rta->rta_len < sizeof(struct rtattr)) { 462 break; 463 } 464 465 switch (rta->rta_type) { 466 case NL_RTA_TABLE: 467 { 468 uint32_t fibnum; 469 fibnum = _rta_get_uint32(rta); 470 if (fibnum == 0) 471 fibnum = 254; 472 RT_LOG(LOG_DEBUG3, "XFIBNUM %u", fibnum); 473 if (!nlattr_add_u32(nw, NL_RTA_TABLE, fibnum)) 474 return (false); 475 } 476 break; 477 default: 478 if (!nlmsg_copy_nla(nla, nw)) 479 return (false); 480 break; 481 } 482 } 483 484 nlmsg_end(nw); 485 RT_LOG(LOG_DEBUG2, "done processing nw %p", nw); 486 return (true); 487 } 488 489 static bool 490 rtnl_to_linux(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_writer *nw) 491 { 492 RT_LOG(LOG_DEBUG2, "Got message type %d", hdr->nlmsg_type); 493 494 switch (hdr->nlmsg_type) { 495 case NL_RTM_NEWLINK: 496 case NL_RTM_DELLINK: 497 case NL_RTM_GETLINK: 498 return (rtnl_newlink_to_linux(hdr, nlp, nw)); 499 case NL_RTM_NEWADDR: 500 case NL_RTM_DELADDR: 501 return (rtnl_newaddr_to_linux(hdr, nlp, nw)); 502 case NL_RTM_NEWROUTE: 503 case NL_RTM_DELROUTE: 504 return (rtnl_newroute_to_linux(hdr, nlp, nw)); 505 case NL_RTM_NEWNEIGH: 506 case NL_RTM_DELNEIGH: 507 case NL_RTM_GETNEIGH: 508 return (rtnl_newneigh_to_linux(hdr, nlp, nw)); 509 default: 510 RT_LOG(LOG_DEBUG, "[WARN] Passing message type %d untranslated", 511 hdr->nlmsg_type); 512 return (handle_default_out(hdr, nw)); 513 } 514 } 515 516 static bool 517 nlmsg_error_to_linux(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_writer *nw) 518 { 519 if (!nlmsg_copy_header(hdr, nw)) 520 return (false); 521 522 struct nlmsgerr *nlerr; 523 nlerr = nlmsg_copy_next_header(hdr, nw, struct nlmsgerr); 524 nlerr->error = bsd_to_linux_errno(nlerr->error); 525 526 int copied_len = sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr); 527 if (hdr->nlmsg_len == copied_len) { 528 nlmsg_end(nw); 529 return (true); 530 } 531 532 /* 533 * CAP_ACK was not set. Original request needs to be translated. 534 * XXX: implement translation of the original message 535 */ 536 RT_LOG(LOG_DEBUG, "[WARN] Passing ack message type %d untranslated", 537 nlerr->msg.nlmsg_type); 538 char *dst_payload, *src_payload; 539 int copy_len = hdr->nlmsg_len - copied_len; 540 dst_payload = nlmsg_reserve_data(nw, NLMSG_ALIGN(copy_len), char); 541 542 src_payload = (char *)hdr + copied_len; 543 544 memcpy(dst_payload, src_payload, copy_len); 545 nlmsg_end(nw); 546 547 return (true); 548 } 549 550 static bool 551 nlmsg_to_linux(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_writer *nw) 552 { 553 if (hdr->nlmsg_type < NLMSG_MIN_TYPE) { 554 switch (hdr->nlmsg_type) { 555 case NLMSG_ERROR: 556 return (nlmsg_error_to_linux(hdr, nlp, nw)); 557 case NLMSG_NOOP: 558 case NLMSG_DONE: 559 case NLMSG_OVERRUN: 560 return (handle_default_out(hdr, nw)); 561 default: 562 RT_LOG(LOG_DEBUG, "[WARN] Passing message type %d untranslated", 563 hdr->nlmsg_type); 564 return (handle_default_out(hdr, nw)); 565 } 566 } 567 568 switch (nlp->nl_proto) { 569 case NETLINK_ROUTE: 570 return (rtnl_to_linux(hdr, nlp, nw)); 571 default: 572 return (handle_default_out(hdr, nw)); 573 } 574 } 575 576 static struct nl_buf * 577 nlmsgs_to_linux(struct nl_buf *orig, struct nlpcb *nlp, const struct ifnet *ifp) 578 { 579 struct nl_writer nw; 580 u_int offset, msglen; 581 582 if (__predict_false(!nl_writer_unicast(&nw, 583 orig->datalen + SCRATCH_BUFFER_SIZE, nlp, false))) 584 return (NULL); 585 586 nw.ifp = ifp; 587 /* Assume correct headers. Buffer IS mutable */ 588 for (offset = 0; 589 offset + sizeof(struct nlmsghdr) <= orig->datalen; 590 offset += msglen) { 591 struct nlmsghdr *hdr = (struct nlmsghdr *)&orig->data[offset]; 592 593 msglen = NLMSG_ALIGN(hdr->nlmsg_len); 594 if (!nlmsg_to_linux(hdr, nlp, &nw)) { 595 RT_LOG(LOG_DEBUG, "failed to process msg type %d", 596 hdr->nlmsg_type); 597 nl_buf_free(nw.buf); 598 return (NULL); 599 } 600 } 601 602 RT_LOG(LOG_DEBUG3, "%p: in %u bytes %u messages", __func__, 603 nw.buf->datalen, nw.num_messages); 604 605 return (nw.buf); 606 } 607 608 static struct linux_netlink_provider linux_netlink_v1 = { 609 .msgs_to_linux = nlmsgs_to_linux, 610 .msg_from_linux = nlmsg_from_linux, 611 }; 612 613 void 614 linux_netlink_register(void) 615 { 616 linux_netlink_p = &linux_netlink_v1; 617 } 618 619 void 620 linux_netlink_deregister(void) 621 { 622 linux_netlink_p = NULL; 623 } 624