1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2019 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 * $FreeBSD$ 28 */ 29 30 #ifndef _NET_ROUTING_RTSOCK_COMMON_H_ 31 #define _NET_ROUTING_RTSOCK_COMMON_H_ 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <unistd.h> 37 #include <fcntl.h> 38 #include <stdbool.h> 39 #include <ctype.h> 40 #include <poll.h> 41 42 #include <sys/types.h> 43 #include <sys/time.h> 44 #include <sys/param.h> 45 #include <sys/socket.h> 46 #include <sys/ioctl.h> 47 #include <net/if.h> 48 #include <net/if_dl.h> 49 #include <net/route.h> 50 51 #include <arpa/inet.h> 52 #include <net/ethernet.h> 53 54 #include <netinet/in.h> 55 #include <netinet6/in6_var.h> 56 #include <netinet6/nd6.h> 57 58 #include <ifaddrs.h> 59 60 #include <errno.h> 61 #include <err.h> 62 #include <sysexits.h> 63 64 #include <atf-c.h> 65 66 #include "rtsock_print.h" 67 68 void rtsock_update_rtm_len(struct rt_msghdr *rtm); 69 void rtsock_validate_message(char *buffer, ssize_t len); 70 void rtsock_add_rtm_sa(struct rt_msghdr *rtm, int addr_type, struct sockaddr *sa); 71 72 static int _rtm_seq = 42; 73 74 75 /* 76 * Checks if the interface cloner module is present for @name. 77 */ 78 static int 79 _check_cloner(char *name) 80 { 81 struct if_clonereq ifcr; 82 char *cp, *buf; 83 int idx; 84 int s; 85 int found = 0; 86 87 s = socket(AF_LOCAL, SOCK_DGRAM, 0); 88 if (s == -1) 89 err(1, "socket(AF_LOCAL,SOCK_DGRAM)"); 90 91 memset(&ifcr, 0, sizeof(ifcr)); 92 93 if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0) 94 err(1, "SIOCIFGCLONERS for count"); 95 96 buf = malloc(ifcr.ifcr_total * IFNAMSIZ); 97 if (buf == NULL) 98 err(1, "unable to allocate cloner name buffer"); 99 100 ifcr.ifcr_count = ifcr.ifcr_total; 101 ifcr.ifcr_buffer = buf; 102 103 if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0) 104 err(1, "SIOCIFGCLONERS for names"); 105 106 /* 107 * In case some disappeared in the mean time, clamp it down. 108 */ 109 if (ifcr.ifcr_count > ifcr.ifcr_total) 110 ifcr.ifcr_count = ifcr.ifcr_total; 111 112 for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) { 113 if (!strcmp(cp, name)) { 114 found = 1; 115 break; 116 } 117 } 118 119 free(buf); 120 close(s); 121 122 return (found); 123 } 124 125 /* 126 * Tries to ensure if_tap is loaded. 127 * Checks list of interface cloners first, then tries 128 * to load the module. 129 * 130 * return nonzero on success. 131 */ 132 static int 133 _enforce_cloner_loaded(char *cloner_name) 134 { 135 if (_check_cloner(cloner_name)) 136 return (1); 137 /* need to load */ 138 RLOG("trying to load %s driver", cloner_name); 139 140 char cmd[64]; 141 142 snprintf(cmd, sizeof(cmd), "/sbin/kldload if_%s", cloner_name); 143 int ret = system(cmd); 144 if (ret != 0) { 145 RLOG("'%s' failed, error %d", cmd, ret); 146 return (0); 147 } 148 149 return (1); 150 } 151 152 static int 153 iface_create_cloned(char *ifname_ptr) 154 { 155 struct ifreq ifr; 156 int s; 157 char prefix[IFNAMSIZ]; 158 159 char *src, *dst; 160 for (src = ifname_ptr, dst = prefix; *src && isalpha(*src); src++) 161 *dst++ = *src; 162 *dst = '\0'; 163 164 if (_enforce_cloner_loaded(prefix) == 0) 165 return (0); 166 167 memset(&ifr, 0, sizeof(struct ifreq)); 168 169 s = socket(AF_LOCAL, SOCK_DGRAM, 0); 170 strlcpy(ifr.ifr_name, ifname_ptr, sizeof(ifr.ifr_name)); 171 172 RLOG("creating iface %s %s", prefix, ifr.ifr_name); 173 if (ioctl(s, SIOCIFCREATE2, &ifr) < 0) 174 err(1, "SIOCIFCREATE2"); 175 176 strlcpy(ifname_ptr, ifr.ifr_name, IFNAMSIZ); 177 RLOG("created interface %s", ifname_ptr); 178 179 return (1); 180 } 181 182 static int 183 iface_destroy(char *ifname) 184 { 185 struct ifreq ifr; 186 int s; 187 188 s = socket(AF_LOCAL, SOCK_DGRAM, 0); 189 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 190 191 RLOG("destroying interface %s", ifname); 192 if (ioctl(s, SIOCIFDESTROY, &ifr) < 0) 193 return (0); 194 195 return (1); 196 } 197 198 /* 199 * Open tunneling device such as tuntap and returns fd. 200 */ 201 int 202 iface_open(char *ifname) 203 { 204 char path[256]; 205 206 snprintf(path, sizeof(path), "/dev/%s", ifname); 207 208 RLOG("opening interface %s", ifname); 209 int fd = open(path, O_RDWR|O_EXCL); 210 if (fd == -1) { 211 RLOG_ERRNO("unable to open interface %s", ifname); 212 return (-1); 213 } 214 215 return (fd); 216 } 217 218 /* 219 * Sets primary IPv4 addr. 220 * Returns 0 on success. 221 */ 222 inline int 223 iface_setup_addr(char *ifname, char *addr, int plen) 224 { 225 char cmd[512]; 226 char *af; 227 228 if (strchr(addr, ':')) 229 af = "inet6"; 230 else 231 af = "inet"; 232 RLOG("setting af_%s %s/%d on %s", af, addr, plen, ifname); 233 snprintf(cmd, sizeof(cmd), "/sbin/ifconfig %s %s %s/%d", ifname, 234 af, addr, plen); 235 236 return system(cmd); 237 } 238 239 /* 240 * Removes primary IPv4 prefix. 241 * Returns 0 on success. 242 */ 243 inline int 244 iface_delete_addr(char *ifname, char *addr) 245 { 246 char cmd[512]; 247 248 if (strchr(addr, ':')) { 249 RLOG("removing IPv6 %s from %s", addr, ifname); 250 snprintf(cmd, sizeof(cmd), "/sbin/ifconfig %s inet6 %s delete", ifname, addr); 251 } else { 252 RLOG("removing IPv4 %s from %s", addr, ifname); 253 snprintf(cmd, sizeof(cmd), "/sbin/ifconfig %s -alias %s", ifname, addr); 254 } 255 256 return system(cmd); 257 } 258 259 int 260 iface_turn_up(char *ifname) 261 { 262 struct ifreq ifr; 263 int s; 264 265 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 266 RLOG_ERRNO("socket"); 267 return (-1); 268 } 269 memset(&ifr, 0, sizeof(struct ifreq)); 270 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 271 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 272 RLOG_ERRNO("ioctl(SIOCGIFFLAGS)"); 273 return (-1); 274 } 275 /* Update flags */ 276 if ((ifr.ifr_flags & IFF_UP) == 0) { 277 ifr.ifr_flags |= IFF_UP; 278 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) { 279 RLOG_ERRNO("ioctl(SIOSGIFFLAGS)"); 280 return (-1); 281 } 282 RLOG("turned interface %s up", ifname); 283 } 284 285 return (0); 286 } 287 288 /* 289 * Removes ND6_IFF_IFDISABLED from IPv6 interface flags. 290 * Returns 0 on success. 291 */ 292 int 293 iface_enable_ipv6(char *ifname) 294 { 295 struct in6_ndireq nd; 296 int s; 297 298 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 299 err(1, "socket"); 300 } 301 memset(&nd, 0, sizeof(nd)); 302 strlcpy(nd.ifname, ifname, sizeof(nd.ifname)); 303 if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) { 304 RLOG_ERRNO("ioctl(SIOCGIFINFO_IN6)"); 305 return (-1); 306 } 307 /* Update flags */ 308 if ((nd.ndi.flags & ND6_IFF_IFDISABLED) != 0) { 309 nd.ndi.flags &= ~ND6_IFF_IFDISABLED; 310 if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd) < 0) { 311 RLOG_ERRNO("ioctl(SIOCSIFINFO_IN6)"); 312 return (-1); 313 } 314 RLOG("enabled IPv6 for %s", ifname); 315 } 316 317 return (0); 318 } 319 320 #define SA_F_IGNORE_IFNAME 0x01 321 #define SA_F_IGNORE_IFTYPE 0x02 322 #define SA_F_IGNORE_MEMCMP 0x04 323 int 324 sa_equal_msg_flags(const struct sockaddr *a, const struct sockaddr *b, char *msg, size_t sz, int flags) 325 { 326 char a_s[64], b_s[64]; 327 const struct sockaddr_in *a4, *b4; 328 const struct sockaddr_in6 *a6, *b6; 329 const struct sockaddr_dl *al, *bl; 330 331 if (a == NULL) { 332 snprintf(msg, sz, "first sa is NULL"); 333 return 0; 334 } 335 if (b == NULL) { 336 snprintf(msg, sz, "second sa is NULL"); 337 return 0; 338 } 339 340 if (a->sa_family != b->sa_family) { 341 snprintf(msg, sz, "family: %d vs %d", a->sa_family, b->sa_family); 342 return 0; 343 } 344 if (a->sa_len != b->sa_len) { 345 snprintf(msg, sz, "len: %d vs %d", a->sa_len, b->sa_len); 346 return 0; 347 } 348 349 switch (a->sa_family) { 350 case AF_INET: 351 a4 = (const struct sockaddr_in *)a; 352 b4 = (const struct sockaddr_in *)b; 353 if (a4->sin_addr.s_addr != b4->sin_addr.s_addr) { 354 inet_ntop(AF_INET, &a4->sin_addr, a_s, sizeof(a_s)); 355 inet_ntop(AF_INET, &b4->sin_addr, b_s, sizeof(b_s)); 356 snprintf(msg, sz, "addr diff: %s vs %s", a_s, b_s); 357 return 0; 358 } 359 if (a4->sin_port != b4->sin_port) { 360 snprintf(msg, sz, "port diff: %d vs %d", 361 ntohs(a4->sin_port), ntohs(b4->sin_port)); 362 //return 0; 363 } 364 const uint32_t *a32, *b32; 365 a32 = (const uint32_t *)a4->sin_zero; 366 b32 = (const uint32_t *)b4->sin_zero; 367 if ((*a32 != *b32) || (*(a32 + 1) != *(b32 + 1))) { 368 snprintf(msg, sz, "zero diff: 0x%08X%08X vs 0x%08X%08X", 369 ntohl(*a32), ntohl(*(a32 + 1)), 370 ntohl(*b32), ntohl(*(b32 + 1))); 371 return 0; 372 } 373 return 1; 374 case AF_INET6: 375 a6 = (const struct sockaddr_in6 *)a; 376 b6 = (const struct sockaddr_in6 *)b; 377 if (!IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr)) { 378 inet_ntop(AF_INET6, &a6->sin6_addr, a_s, sizeof(a_s)); 379 inet_ntop(AF_INET6, &b6->sin6_addr, a_s, sizeof(a_s)); 380 snprintf(msg, sz, "addr diff: %s vs %s", a_s, b_s); 381 return 0; 382 } 383 if (a6->sin6_scope_id != b6->sin6_scope_id) { 384 snprintf(msg, sz, "scope diff: %u vs %u", a6->sin6_scope_id, b6->sin6_scope_id); 385 return 0; 386 } 387 break; 388 case AF_LINK: 389 al = (const struct sockaddr_dl *)a; 390 bl = (const struct sockaddr_dl *)b; 391 392 if (al->sdl_index != bl->sdl_index) { 393 snprintf(msg, sz, "sdl_index diff: %u vs %u", al->sdl_index, bl->sdl_index); 394 return 0; 395 } 396 397 if ((al->sdl_alen != bl->sdl_alen) || (memcmp(LLADDR(al), LLADDR(bl), al->sdl_alen) != 0)) { 398 char abuf[64], bbuf[64]; 399 sa_print_hd(abuf, sizeof(abuf), LLADDR(al), al->sdl_alen); 400 sa_print_hd(bbuf, sizeof(bbuf), LLADDR(bl), bl->sdl_alen); 401 snprintf(msg, sz, "sdl_alen diff: {%s} (%d) vs {%s} (%d)", 402 abuf, al->sdl_alen, bbuf, bl->sdl_alen); 403 return 0; 404 } 405 406 if (((flags & SA_F_IGNORE_IFTYPE) == 0) && (al->sdl_type != bl->sdl_type)) { 407 snprintf(msg, sz, "sdl_type diff: %u vs %u", al->sdl_type, bl->sdl_type); 408 return 0; 409 } 410 411 if (((flags & SA_F_IGNORE_IFNAME) == 0) && ((al->sdl_nlen != bl->sdl_nlen) || 412 (memcmp(al->sdl_data, bl->sdl_data, al->sdl_nlen) != 0))) { 413 char abuf[64], bbuf[64]; 414 memcpy(abuf, al->sdl_data, al->sdl_nlen); 415 abuf[al->sdl_nlen] = '\0'; 416 memcpy(bbuf, bl->sdl_data, bl->sdl_nlen); 417 abuf[bl->sdl_nlen] = '\0'; 418 snprintf(msg, sz, "sdl_nlen diff: {%s} (%d) vs {%s} (%d)", 419 abuf, al->sdl_nlen, bbuf, bl->sdl_nlen); 420 return 0; 421 } 422 423 if (flags & SA_F_IGNORE_MEMCMP) 424 return 1; 425 break; 426 } 427 428 if (memcmp(a, b, a->sa_len)) { 429 int i; 430 for (i = 0; i < a->sa_len; i++) 431 if (((const char *)a)[i] != ((const char *)b)[i]) 432 break; 433 434 sa_print(a, 1); 435 sa_print(b, 1); 436 437 snprintf(msg, sz, "overall memcmp() reports diff for af %d offset %d", 438 a->sa_family, i); 439 return 0; 440 } 441 return 1; 442 } 443 444 int 445 sa_equal_msg(const struct sockaddr *a, const struct sockaddr *b, char *msg, size_t sz) 446 { 447 448 return sa_equal_msg_flags(a, b, msg, sz, 0); 449 } 450 451 void 452 sa_fill_mask4(struct sockaddr_in *sin, int plen) 453 { 454 455 memset(sin, 0, sizeof(struct sockaddr_in)); 456 sin->sin_family = AF_INET; 457 sin->sin_len = sizeof(struct sockaddr_in); 458 sin->sin_addr.s_addr = htonl(plen ? ~((1 << (32 - plen)) - 1) : 0); 459 } 460 461 void 462 sa_fill_mask6(struct sockaddr_in6 *sin6, uint8_t mask) 463 { 464 uint32_t *cp; 465 466 memset(sin6, 0, sizeof(struct sockaddr_in6)); 467 sin6->sin6_family = AF_INET6; 468 sin6->sin6_len = sizeof(struct sockaddr_in6); 469 470 for (cp = (uint32_t *)&sin6->sin6_addr; mask >= 32; mask -= 32) 471 *cp++ = 0xFFFFFFFF; 472 if (mask > 0) 473 *cp = htonl(mask ? ~((1 << (32 - mask)) - 1) : 0); 474 } 475 476 /* 52:54:00:14:e3:10 */ 477 #define ETHER_MAC_MAX_LENGTH 17 478 479 int 480 sa_convert_str_to_sa(const char *_addr, struct sockaddr *sa) 481 { 482 int error; 483 484 int af = AF_UNSPEC; 485 486 char *addr = strdup(_addr); 487 int retcode = 0; 488 489 /* classify AF by str */ 490 if (strchr(addr, ':')) { 491 /* inet6 or ether */ 492 char *k; 493 int delim_cnt = 0; 494 for (k = addr; *k; k++) 495 if (*k == ':') 496 delim_cnt++; 497 af = AF_INET6; 498 499 if (delim_cnt == 5) { 500 k = strchr(addr, '%'); 501 if (k != NULL && (k - addr) <= ETHER_MAC_MAX_LENGTH) 502 af = AF_LINK; 503 } 504 } else if (strchr(addr, '.')) 505 af = AF_INET; 506 507 /* */ 508 char *delimiter; 509 int ifindex = 0; 510 char *ifname = NULL; 511 if ((delimiter = strchr(addr, '%')) != NULL) { 512 *delimiter = '\0'; 513 ifname = delimiter + 1; 514 ifindex = if_nametoindex(ifname); 515 if (ifindex == 0) 516 RLOG("unable to find ifindex for '%s'", ifname); 517 else 518 RLOG("if %s mapped to %d", ifname, ifindex); 519 } 520 521 if (af == AF_INET6) { 522 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 523 memset(sin6, 0, sizeof(struct sockaddr_in6)); 524 sin6->sin6_family = AF_INET6; 525 sin6->sin6_len = sizeof(struct sockaddr_in6); 526 sin6->sin6_scope_id = ifindex; 527 error = inet_pton(AF_INET6, addr, &sin6->sin6_addr); 528 if (error != 1) 529 RLOG_ERRNO("inet_ntop() failed: ret=%d", error); 530 else 531 retcode = 1; 532 } else if (af == AF_INET) { 533 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 534 memset(sin, 0, sizeof(struct sockaddr_in)); 535 sin->sin_family = AF_INET; 536 sin->sin_len = sizeof(struct sockaddr_in); 537 error = inet_pton(AF_INET, addr, &sin->sin_addr); 538 if (error != 1) 539 RLOG("inet_ntop() failed: ret=%d", error); 540 else 541 retcode = 1; 542 } else if (af == AF_LINK) { 543 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; 544 memset(sdl, 0, sizeof(struct sockaddr_dl)); 545 sdl->sdl_family = AF_LINK; 546 sdl->sdl_len = sizeof(struct sockaddr_dl); 547 sdl->sdl_index = ifindex; 548 sdl->sdl_alen = 6; 549 struct ether_addr *ea = (struct ether_addr *)LLADDR(sdl); 550 if (ether_aton_r(addr, ea) == NULL) 551 RLOG("ether_aton() failed"); 552 else 553 retcode = 1; 554 } 555 556 return (retcode); 557 } 558 559 560 int 561 rtsock_setup_socket() 562 { 563 int fd; 564 int af = AF_UNSPEC; /* 0 to capture messages from all AFs */ 565 fd = socket(PF_ROUTE, SOCK_RAW, af); 566 567 ATF_REQUIRE_MSG(fd != -1, "rtsock open failed: %s", strerror(errno)); 568 569 /* Listen for our messages */ 570 int on = 1; 571 if (setsockopt(fd, SOL_SOCKET,SO_USELOOPBACK, &on, sizeof(on)) < 0) 572 RLOG_ERRNO("setsockopt failed"); 573 574 return (fd); 575 } 576 577 ssize_t 578 rtsock_send_rtm(int fd, struct rt_msghdr *rtm) 579 { 580 int my_errno; 581 ssize_t len; 582 583 rtsock_update_rtm_len(rtm); 584 585 len = write(fd, rtm, rtm->rtm_msglen); 586 my_errno = errno; 587 RTSOCK_ATF_REQUIRE_MSG(rtm, len == rtm->rtm_msglen, 588 "rtsock write failed: want %d got %zd (%s)", 589 rtm->rtm_msglen, len, strerror(my_errno)); 590 591 return (len); 592 } 593 594 struct rt_msghdr * 595 rtsock_read_rtm(int fd, char *buffer, size_t buflen) 596 { 597 ssize_t len; 598 struct pollfd pfd; 599 int poll_delay = 5 * 1000; /* 5 seconds */ 600 601 /* Check for the data available to read first */ 602 memset(&pfd, 0, sizeof(pfd)); 603 pfd.fd = fd; 604 pfd.events = POLLIN; 605 606 if (poll(&pfd, 1, poll_delay) == 0) 607 ATF_REQUIRE_MSG(1 == 0, "rtsock read timed out (%d seconds passed)", 608 poll_delay / 1000); 609 610 len = read(fd, buffer, buflen); 611 int my_errno = errno; 612 ATF_REQUIRE_MSG(len > 0, "rtsock read failed: %s", strerror(my_errno)); 613 614 rtsock_validate_message(buffer, len); 615 return ((struct rt_msghdr *)buffer); 616 } 617 618 struct rt_msghdr * 619 rtsock_read_rtm_reply(int fd, char *buffer, size_t buflen, int seq) 620 { 621 struct rt_msghdr *rtm; 622 623 while (true) { 624 rtm = rtsock_read_rtm(fd, buffer, buflen); 625 if (rtm->rtm_pid != getpid()) 626 continue; 627 if (rtm->rtm_seq != seq) 628 continue; 629 630 return (rtm); 631 } 632 633 /* NOTREACHED */ 634 } 635 636 void 637 rtsock_prepare_route_message_base(struct rt_msghdr *rtm, int cmd) 638 { 639 640 memset(rtm, 0, sizeof(struct rt_msghdr)); 641 rtm->rtm_type = cmd; 642 rtm->rtm_version = RTM_VERSION; 643 rtm->rtm_seq = _rtm_seq++; 644 } 645 646 void 647 rtsock_prepare_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst, 648 struct sockaddr *mask, struct sockaddr *gw) 649 { 650 651 rtsock_prepare_route_message_base(rtm, cmd); 652 if (dst != NULL) 653 rtsock_add_rtm_sa(rtm, RTA_DST, dst); 654 655 if (gw != NULL) { 656 rtsock_add_rtm_sa(rtm, RTA_GATEWAY, gw); 657 rtm->rtm_flags |= RTF_GATEWAY; 658 } 659 660 if (mask != NULL) 661 rtsock_add_rtm_sa(rtm, RTA_NETMASK, mask); 662 } 663 664 void 665 rtsock_add_rtm_sa(struct rt_msghdr *rtm, int addr_type, struct sockaddr *sa) 666 { 667 char *ptr = (char *)(rtm + 1); 668 for (int i = 0; i < RTAX_MAX; i++) { 669 if (rtm->rtm_addrs & (1 << i)) { 670 /* add */ 671 ptr += ALIGN(((struct sockaddr *)ptr)->sa_len); 672 } 673 } 674 675 rtm->rtm_addrs |= addr_type; 676 memcpy(ptr, sa, sa->sa_len); 677 } 678 679 struct sockaddr * 680 rtsock_find_rtm_sa(struct rt_msghdr *rtm, int addr_type) 681 { 682 char *ptr = (char *)(rtm + 1); 683 for (int i = 0; i < RTAX_MAX; i++) { 684 if (rtm->rtm_addrs & (1 << i)) { 685 if (addr_type == (1 << i)) 686 return ((struct sockaddr *)ptr); 687 /* add */ 688 ptr += ALIGN(((struct sockaddr *)ptr)->sa_len); 689 } 690 } 691 692 return (NULL); 693 } 694 695 size_t 696 rtsock_calc_rtm_len(struct rt_msghdr *rtm) 697 { 698 size_t len = sizeof(struct rt_msghdr); 699 700 char *ptr = (char *)(rtm + 1); 701 for (int i = 0; i < RTAX_MAX; i++) { 702 if (rtm->rtm_addrs & (1 << i)) { 703 /* add */ 704 int sa_len = ALIGN(((struct sockaddr *)ptr)->sa_len); 705 len += sa_len; 706 ptr += sa_len; 707 } 708 } 709 710 return len; 711 } 712 713 void 714 rtsock_update_rtm_len(struct rt_msghdr *rtm) 715 { 716 717 rtm->rtm_msglen = rtsock_calc_rtm_len(rtm); 718 } 719 720 static void 721 _validate_message_sockaddrs(char *buffer, int rtm_len, size_t offset, int rtm_addrs) 722 { 723 struct sockaddr *sa; 724 size_t parsed_len = offset; 725 726 /* Offset denotes initial header size */ 727 sa = (struct sockaddr *)(buffer + offset); 728 729 for (int i = 0; i < RTAX_MAX; i++) { 730 if ((rtm_addrs & (1 << i)) == 0) 731 continue; 732 parsed_len += SA_SIZE(sa); 733 RTSOCK_ATF_REQUIRE_MSG((struct rt_msghdr *)buffer, parsed_len <= rtm_len, 734 "SA %d: len %d exceeds msg size %d", i, (int)sa->sa_len, rtm_len); 735 if (sa->sa_family == AF_LINK) { 736 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; 737 int data_len = sdl->sdl_nlen + sdl->sdl_alen; 738 data_len += offsetof(struct sockaddr_dl, sdl_data); 739 740 RTSOCK_ATF_REQUIRE_MSG((struct rt_msghdr *)buffer, 741 data_len <= rtm_len, 742 "AF_LINK data size exceeds total len: %u vs %u, nlen=%d alen=%d", 743 data_len, rtm_len, sdl->sdl_nlen, sdl->sdl_alen); 744 } 745 sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa)); 746 } 747 748 RTSOCK_ATF_REQUIRE_MSG((struct rt_msghdr *)buffer, parsed_len == rtm_len, 749 "message len != parsed len: expected %d parsed %d", 750 rtm_len, (int)parsed_len); 751 } 752 753 /* 754 * Raises error if base syntax checks fails. 755 */ 756 void 757 rtsock_validate_message(char *buffer, ssize_t len) 758 { 759 struct rt_msghdr *rtm; 760 761 ATF_REQUIRE_MSG(len > 0, "read() return %zd, error: %s", len, strerror(errno)); 762 763 rtm = (struct rt_msghdr *)buffer; 764 ATF_REQUIRE_MSG(rtm->rtm_version == RTM_VERSION, "unknown RTM_VERSION: expected %d got %d", 765 RTM_VERSION, rtm->rtm_version); 766 ATF_REQUIRE_MSG(rtm->rtm_msglen <= len, "wrong message length: expected %d got %d", 767 (int)len, (int)rtm->rtm_msglen); 768 769 switch (rtm->rtm_type) { 770 case RTM_GET: 771 case RTM_ADD: 772 case RTM_DELETE: 773 case RTM_CHANGE: 774 _validate_message_sockaddrs(buffer, rtm->rtm_msglen, 775 sizeof(struct rt_msghdr), rtm->rtm_addrs); 776 break; 777 case RTM_DELADDR: 778 case RTM_NEWADDR: 779 _validate_message_sockaddrs(buffer, rtm->rtm_msglen, 780 sizeof(struct ifa_msghdr), ((struct ifa_msghdr *)buffer)->ifam_addrs); 781 break; 782 } 783 } 784 785 void 786 rtsock_validate_pid_ours(struct rt_msghdr *rtm) 787 { 788 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_pid == getpid(), "expected pid %d, got %d", 789 getpid(), rtm->rtm_pid); 790 } 791 792 void 793 rtsock_validate_pid_user(struct rt_msghdr *rtm) 794 { 795 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_pid > 0, "expected non-zero pid, got %d", 796 rtm->rtm_pid); 797 } 798 799 void 800 rtsock_validate_pid_kernel(struct rt_msghdr *rtm) 801 { 802 RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_pid == 0, "expected zero pid, got %d", 803 rtm->rtm_pid); 804 } 805 806 #endif 807