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