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