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