1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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 <sys/cdefs.h> 29 #include "opt_inet.h" 30 #include "opt_inet6.h" 31 #include <sys/types.h> 32 #include <sys/malloc.h> 33 #include <sys/rmlock.h> 34 #include <sys/socket.h> 35 #include <sys/stdarg.h> 36 37 #include <net/if.h> 38 #include <net/route.h> 39 #include <net/route/nhop.h> 40 41 #include <net/route/route_ctl.h> 42 #include <netinet/in.h> 43 #include <netlink/netlink.h> 44 #include <netlink/netlink_ctl.h> 45 #include <netlink/netlink_var.h> 46 #include <netlink/netlink_route.h> 47 48 #define DEBUG_MOD_NAME nl_parser 49 #define DEBUG_MAX_LEVEL LOG_DEBUG3 50 #include <netlink/netlink_debug.h> 51 _DECLARE_DEBUG(LOG_INFO); 52 53 bool 54 nlmsg_report_err_msg(struct nl_pstate *npt, const char *fmt, ...) 55 { 56 va_list ap; 57 58 if (npt->err_msg != NULL) 59 return (false); 60 char *buf = npt_alloc(npt, NL_MAX_ERROR_BUF); 61 if (buf == NULL) 62 return (false); 63 va_start(ap, fmt); 64 vsnprintf(buf, NL_MAX_ERROR_BUF, fmt, ap); 65 va_end(ap); 66 67 npt->err_msg = buf; 68 return (true); 69 } 70 71 bool 72 nlmsg_report_err_offset(struct nl_pstate *npt, uint32_t off) 73 { 74 if (npt->err_off != 0) 75 return (false); 76 npt->err_off = off; 77 return (true); 78 } 79 80 void 81 nlmsg_report_cookie(struct nl_pstate *npt, struct nlattr *nla) 82 { 83 MPASS(nla->nla_type == NLMSGERR_ATTR_COOKIE); 84 MPASS(nla->nla_len >= sizeof(struct nlattr)); 85 npt->cookie = nla; 86 } 87 88 void 89 nlmsg_report_cookie_u32(struct nl_pstate *npt, uint32_t val) 90 { 91 struct nlattr *nla = npt_alloc(npt, sizeof(*nla) + sizeof(uint32_t)); 92 93 nla->nla_type = NLMSGERR_ATTR_COOKIE; 94 nla->nla_len = sizeof(*nla) + sizeof(uint32_t); 95 memcpy(nla + 1, &val, sizeof(uint32_t)); 96 nlmsg_report_cookie(npt, nla); 97 } 98 99 static const struct nlattr_parser * 100 search_states(const struct nlattr_parser *ps, u_int pslen, int key) 101 { 102 int left_i = 0, right_i = pslen - 1; 103 104 if (key < ps[0].type || key > ps[pslen - 1].type) 105 return (NULL); 106 107 while (left_i + 1 < right_i) { 108 int mid_i = (left_i + right_i) / 2; 109 if (key < ps[mid_i].type) 110 right_i = mid_i; 111 else if (key > ps[mid_i].type) 112 left_i = mid_i + 1; 113 else 114 return (&ps[mid_i]); 115 } 116 if (ps[left_i].type == key) 117 return (&ps[left_i]); 118 else if (ps[right_i].type == key) 119 return (&ps[right_i]); 120 return (NULL); 121 } 122 123 int 124 nl_parse_attrs_raw(struct nlattr *nla_head, uint16_t len, 125 const struct nlattr_parser *ps, u_int pslen, struct nl_pstate *npt, 126 void *target) 127 { 128 const struct nlattr_parser *s; 129 struct nlattr *nla; 130 uint16_t orig_len, off; 131 int error = 0; 132 133 NL_LOG(LOG_DEBUG3, "parse %p remaining_len %d", nla_head, len); 134 orig_len = len; 135 NLA_FOREACH(nla, nla_head, len) { 136 NL_LOG(LOG_DEBUG3, ">> parsing %p attr_type %u len %u (rem %u)", 137 nla, nla->nla_type, nla->nla_len, len); 138 if (nla->nla_len < sizeof(struct nlattr)) { 139 NLMSG_REPORT_ERR_MSG(npt, 140 "Invalid attr %p type %u len: %u", 141 nla, nla->nla_type, nla->nla_len); 142 off = (char *)nla - (char *)npt->hdr; 143 nlmsg_report_err_offset(npt, off); 144 return (EINVAL); 145 } 146 147 s = search_states(ps, pslen, nla->nla_type & NLA_TYPE_MASK); 148 if (s != NULL) { 149 void *ptr; 150 151 ptr = (void *)((char *)target + s->off); 152 error = s->cb(nla, npt, s->arg, ptr); 153 if (error != 0) { 154 off = (char *)nla - (char *)npt->hdr; 155 nlmsg_report_err_offset(npt, off); 156 NL_LOG(LOG_DEBUG3, 157 "parse failed at offset %u", off); 158 return (error); 159 } 160 } else { 161 /* Ignore non-specified attributes */ 162 NL_LOG(LOG_DEBUG3, "ignoring attr %u", nla->nla_type); 163 } 164 } 165 if (len >= sizeof(struct nlattr)) { 166 nla = (struct nlattr *)((char *)nla_head + (orig_len - len)); 167 NL_LOG(LOG_DEBUG3, " >>> end %p attr_type %u len %u", nla, 168 nla->nla_type, nla->nla_len); 169 } 170 NL_LOG(LOG_DEBUG3, "end parse: %p remaining_len %u", nla, len); 171 172 return (0); 173 } 174 175 void 176 nl_get_attrs_bmask_raw(struct nlattr *nla_head, uint32_t len, 177 struct nlattr_bmask *bm) 178 { 179 struct nlattr *nla = NULL; 180 uint16_t nla_type; 181 182 BIT_ZERO(NL_ATTR_BMASK_SIZE, bm); 183 184 NLA_FOREACH(nla, nla_head, len) { 185 if (nla->nla_len < sizeof(struct nlattr)) 186 return; 187 nla_type = nla->nla_type & NLA_TYPE_MASK; 188 if (nla_type < NL_ATTR_BMASK_SIZE) 189 BIT_SET(NL_ATTR_BMASK_SIZE, nla_type, bm); 190 else 191 NL_LOG(LOG_DEBUG2, 192 "Skipping type %u in the mask: too short", 193 nla_type); 194 } 195 } 196 197 bool 198 nl_has_attr(const struct nlattr_bmask *bm, uint16_t nla_type) 199 { 200 MPASS(nla_type < NL_ATTR_BMASK_SIZE); 201 202 return (BIT_ISSET(NL_ATTR_BMASK_SIZE, nla_type, bm)); 203 } 204 205 int 206 nlattr_get_flag(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 207 void *target) 208 { 209 if (__predict_false(NLA_DATA_LEN(nla) != 0)) { 210 NLMSG_REPORT_ERR_MSG(npt, "nla type %d size(%u) is not a flag", 211 nla->nla_type, NLA_DATA_LEN(nla)); 212 return (EINVAL); 213 } 214 215 *((uint8_t *)target) = 1; 216 return (0); 217 } 218 219 static struct sockaddr * 220 parse_rta_ip4(void *rta_data, struct nl_pstate *npt, int *perror) 221 { 222 struct sockaddr_in *sin; 223 224 sin = (struct sockaddr_in *)npt_alloc_sockaddr(npt, 225 sizeof(struct sockaddr_in)); 226 if (__predict_false(sin == NULL)) { 227 *perror = ENOBUFS; 228 return (NULL); 229 } 230 sin->sin_len = sizeof(struct sockaddr_in); 231 sin->sin_family = AF_INET; 232 memcpy(&sin->sin_addr, rta_data, sizeof(struct in_addr)); 233 return ((struct sockaddr *)sin); 234 } 235 236 static struct sockaddr * 237 parse_rta_ip6(void *rta_data, struct nl_pstate *npt, int *perror) 238 { 239 struct sockaddr_in6 *sin6; 240 241 sin6 = (struct sockaddr_in6 *)npt_alloc_sockaddr(npt, 242 sizeof(struct sockaddr_in6)); 243 if (__predict_false(sin6 == NULL)) { 244 *perror = ENOBUFS; 245 return (NULL); 246 } 247 sin6->sin6_len = sizeof(struct sockaddr_in6); 248 sin6->sin6_family = AF_INET6; 249 memcpy(&sin6->sin6_addr, rta_data, sizeof(struct in6_addr)); 250 return ((struct sockaddr *)sin6); 251 } 252 253 static struct sockaddr * 254 parse_rta_ip(struct rtattr *rta, struct nl_pstate *npt, int *perror) 255 { 256 void *rta_data = NL_RTA_DATA(rta); 257 int rta_len = NL_RTA_DATA_LEN(rta); 258 259 if (rta_len == sizeof(struct in_addr)) { 260 return (parse_rta_ip4(rta_data, npt, perror)); 261 } else if (rta_len == sizeof(struct in6_addr)) { 262 return (parse_rta_ip6(rta_data, npt, perror)); 263 } else { 264 NLMSG_REPORT_ERR_MSG(npt, "unknown IP len: %d for rta type %d", 265 rta_len, rta->rta_type); 266 *perror = ENOTSUP; 267 return (NULL); 268 } 269 return (NULL); 270 } 271 272 int 273 nlattr_get_ip(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 274 void *target) 275 { 276 int error = 0; 277 278 struct sockaddr *sa = parse_rta_ip((struct rtattr *)nla, npt, &error); 279 280 *((struct sockaddr **)target) = sa; 281 return (error); 282 } 283 284 static struct sockaddr * 285 parse_rta_via(struct rtattr *rta, struct nl_pstate *npt, int *perror) 286 { 287 struct rtvia *via = NL_RTA_DATA(rta); 288 int data_len = NL_RTA_DATA_LEN(rta); 289 290 if (__predict_false(data_len) < sizeof(struct rtvia)) { 291 NLMSG_REPORT_ERR_MSG(npt, "undersized RTA_VIA(%d) attr: len %d", 292 rta->rta_type, data_len); 293 *perror = EINVAL; 294 return (NULL); 295 } 296 data_len -= offsetof(struct rtvia, rtvia_addr); 297 298 switch (via->rtvia_family) { 299 case AF_INET: 300 if (__predict_false(data_len < sizeof(struct in_addr))) { 301 *perror = EINVAL; 302 return (NULL); 303 } 304 return (parse_rta_ip4(via->rtvia_addr, npt, perror)); 305 case AF_INET6: 306 if (__predict_false(data_len < sizeof(struct in6_addr))) { 307 *perror = EINVAL; 308 return (NULL); 309 } 310 return (parse_rta_ip6(via->rtvia_addr, npt, perror)); 311 default: 312 *perror = ENOTSUP; 313 return (NULL); 314 } 315 } 316 317 int 318 nlattr_get_ipvia(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 319 void *target) 320 { 321 int error = 0; 322 323 struct sockaddr *sa = parse_rta_via((struct rtattr *)nla, npt, &error); 324 325 *((struct sockaddr **)target) = sa; 326 return (error); 327 } 328 329 int 330 nlattr_get_bool(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 331 void *target) 332 { 333 if (__predict_false(NLA_DATA_LEN(nla) != sizeof(bool))) { 334 NLMSG_REPORT_ERR_MSG(npt, "nla type %d size(%u) is not bool", 335 nla->nla_type, NLA_DATA_LEN(nla)); 336 return (EINVAL); 337 } 338 *((bool *)target) = *((const bool *)NL_RTA_DATA_CONST(nla)); 339 return (0); 340 } 341 342 int 343 nlattr_get_uint8(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 344 void *target) 345 { 346 if (__predict_false(NLA_DATA_LEN(nla) != sizeof(uint8_t))) { 347 NLMSG_REPORT_ERR_MSG(npt, "nla type %d size(%u) is not uint8", 348 nla->nla_type, NLA_DATA_LEN(nla)); 349 return (EINVAL); 350 } 351 *((uint8_t *)target) = *((const uint8_t *)NL_RTA_DATA_CONST(nla)); 352 return (0); 353 } 354 355 int 356 nlattr_get_uint16(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 357 void *target) 358 { 359 if (__predict_false(NLA_DATA_LEN(nla) != sizeof(uint16_t))) { 360 NLMSG_REPORT_ERR_MSG(npt, "nla type %d size(%u) is not uint16", 361 nla->nla_type, NLA_DATA_LEN(nla)); 362 return (EINVAL); 363 } 364 *((uint16_t *)target) = *((const uint16_t *)NL_RTA_DATA_CONST(nla)); 365 return (0); 366 } 367 368 int 369 nlattr_get_uint32(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 370 void *target) 371 { 372 if (__predict_false(NLA_DATA_LEN(nla) != sizeof(uint32_t))) { 373 NLMSG_REPORT_ERR_MSG(npt, "nla type %d size(%u) is not uint32", 374 nla->nla_type, NLA_DATA_LEN(nla)); 375 return (EINVAL); 376 } 377 *((uint32_t *)target) = *((const uint32_t *)NL_RTA_DATA_CONST(nla)); 378 return (0); 379 } 380 381 int 382 nlattr_get_uint64(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 383 void *target) 384 { 385 if (__predict_false(NLA_DATA_LEN(nla) != sizeof(uint64_t))) { 386 NLMSG_REPORT_ERR_MSG(npt, "nla type %d size(%u) is not uint64", 387 nla->nla_type, NLA_DATA_LEN(nla)); 388 return (EINVAL); 389 } 390 memcpy(target, NL_RTA_DATA_CONST(nla), sizeof(uint64_t)); 391 return (0); 392 } 393 394 int 395 nlattr_get_in_addr(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 396 void *target) 397 { 398 if (__predict_false(NLA_DATA_LEN(nla) != sizeof(in_addr_t))) { 399 NLMSG_REPORT_ERR_MSG(npt, 400 "nla type %d size(%u) is not in_addr_t", 401 nla->nla_type, NLA_DATA_LEN(nla)); 402 return (EINVAL); 403 } 404 memcpy(target, NLA_DATA_CONST(nla), sizeof(in_addr_t)); 405 return (0); 406 } 407 408 int 409 nlattr_get_in6_addr(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 410 void *target) 411 { 412 if (__predict_false(NLA_DATA_LEN(nla) != sizeof(struct in6_addr))) { 413 NLMSG_REPORT_ERR_MSG(npt, 414 "nla type %d size(%u) is not struct in6_addr", 415 nla->nla_type, NLA_DATA_LEN(nla)); 416 return (EINVAL); 417 } 418 memcpy(target, NLA_DATA_CONST(nla), sizeof(struct in6_addr)); 419 return (0); 420 } 421 422 static int 423 nlattr_get_ifp_internal(struct nlattr *nla, struct nl_pstate *npt, 424 void *target, bool zero_ok) 425 { 426 struct ifnet *ifp; 427 u_int ifindex; 428 429 if (__predict_false(NLA_DATA_LEN(nla) != sizeof(uint32_t))) { 430 NLMSG_REPORT_ERR_MSG(npt, "nla type %d size(%u) is not uint32", 431 nla->nla_type, NLA_DATA_LEN(nla)); 432 return (EINVAL); 433 } 434 ifindex = *((const u_int *)NLA_DATA_CONST(nla)); 435 436 if (ifindex == 0 && zero_ok) { 437 *((struct ifnet **)target) = NULL; 438 return (0); 439 } 440 441 NET_EPOCH_ASSERT(); 442 443 ifp = ifnet_byindex(ifindex); 444 if (__predict_false(ifp == NULL)) { 445 NLMSG_REPORT_ERR_MSG(npt, "nla type %d: ifindex %u invalid", 446 nla->nla_type, ifindex); 447 return (ENOENT); 448 } 449 *((struct ifnet **)target) = ifp; 450 NL_LOG(LOG_DEBUG3, "nla type %d: ifindex %u -> %s", nla->nla_type, 451 ifindex, if_name(ifp)); 452 453 return (0); 454 } 455 456 int 457 nlattr_get_ifp(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 458 void *target) 459 { 460 return (nlattr_get_ifp_internal(nla, npt, target, false)); 461 } 462 463 int 464 nlattr_get_ifpz(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 465 void *target) 466 { 467 return (nlattr_get_ifp_internal(nla, npt, target, true)); 468 } 469 470 int 471 nlattr_get_chara(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 472 void *target) 473 { 474 int maxlen = NLA_DATA_LEN(nla); 475 int target_size = (size_t)arg; 476 int len = strnlen((char *)NLA_DATA(nla), maxlen); 477 478 if (__predict_false(len >= maxlen) || 479 __predict_false(len >= target_size)) { 480 NLMSG_REPORT_ERR_MSG(npt, "nla type %d size(%u) is not " 481 "NULL-terminated or longer than %u", 482 nla->nla_type, maxlen, target_size); 483 return (EINVAL); 484 } 485 486 strncpy((char *)target, (char *)NLA_DATA(nla), target_size); 487 return (0); 488 } 489 490 int 491 nlattr_get_string(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 492 void *target) 493 { 494 int maxlen = NLA_DATA_LEN(nla); 495 496 if (__predict_false(strnlen((char *)NLA_DATA(nla), maxlen) >= maxlen)) { 497 NLMSG_REPORT_ERR_MSG(npt, 498 "nla type %d size(%u) is not NULL-terminated", 499 nla->nla_type, maxlen); 500 return (EINVAL); 501 } 502 503 *((char **)target) = (char *)NLA_DATA(nla); 504 return (0); 505 } 506 507 int 508 nlattr_get_stringn(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 509 void *target) 510 { 511 int maxlen = NLA_DATA_LEN(nla); 512 513 char *buf = npt_alloc(npt, maxlen + 1); 514 if (buf == NULL) 515 return (ENOMEM); 516 buf[maxlen] = '\0'; 517 memcpy(buf, NLA_DATA(nla), maxlen); 518 519 *((char **)target) = buf; 520 return (0); 521 } 522 523 int 524 nlattr_get_bytes(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 525 void *target) 526 { 527 size_t size = (size_t)arg; 528 529 if (NLA_DATA_LEN(nla) != size) 530 return (EINVAL); 531 532 memcpy(target, NLA_DATA(nla), size); 533 534 return (0); 535 } 536 537 int 538 nlattr_get_nla(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 539 void *target) 540 { 541 NL_LOG(LOG_DEBUG3, "STORING %p len %d", nla, nla->nla_len); 542 *((struct nlattr **)target) = nla; 543 return (0); 544 } 545 546 int 547 nlattr_get_nested(struct nlattr *nla, struct nl_pstate *npt, const void *arg, 548 void *target) 549 { 550 const struct nlhdr_parser *p = (const struct nlhdr_parser *)arg; 551 552 /* Assumes target points to the beginning of the structure. */ 553 return (nl_parse_header(NLA_DATA(nla), NLA_DATA_LEN(nla), p, npt, 554 target)); 555 } 556 557 int 558 nlattr_get_nested_ptr(struct nlattr *nla, struct nl_pstate *npt, 559 const void *arg, void *target) 560 { 561 const struct nlhdr_parser *p = (const struct nlhdr_parser *)arg; 562 563 /* Assumes target points to the beginning of the structure. */ 564 return (nl_parse_header(NLA_DATA(nla), NLA_DATA_LEN(nla), p, npt, 565 *(void **)target)); 566 } 567 568 int 569 nlf_get_ifp(void *src, struct nl_pstate *npt, void *target) 570 { 571 struct ifnet *ifp; 572 u_int ifindex; 573 574 NET_EPOCH_ASSERT(); 575 576 ifindex = *((const u_int *)src); 577 ifp = ifnet_byindex(ifindex); 578 if (ifp == NULL) { 579 NL_LOG(LOG_DEBUG, "ifindex %u invalid", ifindex); 580 return (ENOENT); 581 } 582 *((struct ifnet **)target) = ifp; 583 584 return (0); 585 } 586 587 int 588 nlf_get_ifpz(void *src, struct nl_pstate *npt, void *target) 589 { 590 struct ifnet *ifp; 591 u_int ifindex; 592 593 NET_EPOCH_ASSERT(); 594 595 ifindex = *((const u_int *)src); 596 ifp = ifnet_byindex(ifindex); 597 if (ifindex != 0 && ifp == NULL) { 598 NL_LOG(LOG_DEBUG, "ifindex %u invalid", ifindex); 599 return (ENOENT); 600 } 601 *((struct ifnet **)target) = ifp; 602 603 return (0); 604 } 605 606 int 607 nlf_get_u8(void *src, struct nl_pstate *npt, void *target) 608 { 609 uint8_t val = *((const uint8_t *)src); 610 611 *((uint8_t *)target) = val; 612 613 return (0); 614 } 615 616 int 617 nlf_get_u8_u32(void *src, struct nl_pstate *npt, void *target) 618 { 619 *((uint32_t *)target) = *((const uint8_t *)src); 620 return (0); 621 } 622 623 int 624 nlf_get_u16(void *src, struct nl_pstate *npt, void *target) 625 { 626 *((uint16_t *)target) = *((const uint16_t *)src); 627 return (0); 628 } 629 630 int 631 nlf_get_u32(void *src, struct nl_pstate *npt, void *target) 632 { 633 *((uint32_t *)target) = *((const uint32_t *)src); 634 return (0); 635 } 636