1 /*- 2 * Copyright (c) 2005 Andrey Simonenko 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/types.h> 31 #include <sys/resource.h> 32 #include <sys/time.h> 33 #include <sys/socket.h> 34 #include <sys/un.h> 35 #include <sys/wait.h> 36 37 #include <assert.h> 38 #include <ctype.h> 39 #include <err.h> 40 #include <errno.h> 41 #include <inttypes.h> 42 #include <limits.h> 43 #include <setjmp.h> 44 #include <signal.h> 45 #include <stdarg.h> 46 #include <stdint.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <sysexits.h> 51 #include <unistd.h> 52 53 /* 54 * There are tables with tests descriptions and pointers to test 55 * functions. Each t_*() function returns 0 if its test passed, 56 * -1 if its test failed (something wrong was found in local domain 57 * control messages), -2 if some system error occurred. If test 58 * function returns -2, then a program exits. 59 * 60 * Each test function completely control what to do (eg. fork or 61 * do not fork a client process). If a test function forks a client 62 * process, then it waits for its termination. If a return code of a 63 * client process is not equal to zero, or if a client process was 64 * terminated by a signal, then test function returns -2. 65 * 66 * Each test function and complete program are not optimized 67 * a lot to allow easy to modify tests. 68 * 69 * Each function which can block, is run under TIMEOUT, if timeout 70 * occurs, then test function returns -2 or a client process exits 71 * with nonzero return code. 72 */ 73 74 #ifndef LISTENQ 75 # define LISTENQ 1 76 #endif 77 78 #ifndef TIMEOUT 79 # define TIMEOUT 60 80 #endif 81 82 #define EXTRA_CMSG_SPACE 512 /* Memory for not expected control data. */ 83 84 static int t_cmsgcred(void), t_sockcred_stream1(void); 85 static int t_sockcred_stream2(void), t_cmsgcred_sockcred(void); 86 static int t_sockcred_dgram(void), t_timestamp(void); 87 88 struct test_func { 89 int (*func)(void); /* Pointer to function. */ 90 const char *desc; /* Test description. */ 91 }; 92 93 static struct test_func test_stream_tbl[] = { 94 { NULL, " 0: All tests" }, 95 { t_cmsgcred, " 1: Sending, receiving cmsgcred" }, 96 { t_sockcred_stream1, " 2: Receiving sockcred (listening socket has LOCAL_CREDS)" }, 97 { t_sockcred_stream2, " 3: Receiving sockcred (accepted socket has LOCAL_CREDS)" }, 98 { t_cmsgcred_sockcred, " 4: Sending cmsgcred, receiving sockcred" }, 99 { t_timestamp, " 5: Sending, receiving timestamp" }, 100 { NULL, NULL } 101 }; 102 103 static struct test_func test_dgram_tbl[] = { 104 { NULL, " 0: All tests" }, 105 { t_cmsgcred, " 1: Sending, receiving cmsgcred" }, 106 { t_sockcred_dgram, " 2: Receiving sockcred" }, 107 { t_cmsgcred_sockcred, " 3: Sending cmsgcred, receiving sockcred" }, 108 { t_timestamp, " 4: Sending, receiving timestamp" }, 109 { NULL, NULL } 110 }; 111 112 #define TEST_STREAM_NO_MAX (sizeof(test_stream_tbl) / sizeof(struct test_func) - 2) 113 #define TEST_DGRAM_NO_MAX (sizeof(test_dgram_tbl) / sizeof(struct test_func) - 2) 114 115 static const char *myname = "SERVER"; /* "SERVER" or "CLIENT" */ 116 117 static int debug = 0; /* 1, if -d. */ 118 static int no_control_data = 0; /* 1, if -z. */ 119 120 static u_int nfailed = 0; /* Number of failed tests. */ 121 122 static int sock_type; /* SOCK_STREAM or SOCK_DGRAM */ 123 static const char *sock_type_str; /* "SOCK_STREAM" or "SOCK_DGRAN" */ 124 125 static char tempdir[] = "/tmp/unix_cmsg.XXXXXXX"; 126 static char serv_sock_path[PATH_MAX]; 127 128 static char ipc_message[] = "hello"; 129 130 #define IPC_MESSAGE_SIZE (sizeof(ipc_message)) 131 132 static struct sockaddr_un servaddr; /* Server address. */ 133 134 static sigjmp_buf env_alrm; 135 136 static uid_t my_uid; 137 static uid_t my_euid; 138 static gid_t my_gid; 139 static gid_t my_egid; 140 141 /* 142 * my_gids[0] is EGID, next items are supplementary GIDs, 143 * my_ngids determines valid items in my_gids array. 144 */ 145 static gid_t my_gids[NGROUPS_MAX]; 146 static int my_ngids; 147 148 static pid_t client_pid; /* PID of forked client. */ 149 150 #define dbgmsg(x) do { \ 151 if (debug) \ 152 logmsgx x ; \ 153 } while (/* CONSTCOND */0) 154 155 static void logmsg(const char *, ...) __printflike(1, 2); 156 static void logmsgx(const char *, ...) __printflike(1, 2); 157 static void output(const char *, ...) __printflike(1, 2); 158 159 extern char *__progname; /* The name of program. */ 160 161 /* 162 * Output the help message (-h switch). 163 */ 164 static void 165 usage(int quick) 166 { 167 const struct test_func *test_func; 168 169 fprintf(stderr, "Usage: %s [-dhz] [-t <socktype>] [testno]\n", 170 __progname); 171 if (quick) 172 return; 173 fprintf(stderr, "\n Options are:\n\ 174 -d\t\t\tOutput debugging information\n\ 175 -h\t\t\tOutput this help message and exit\n\ 176 -t <socktype>\t\tRun test only for the given socket type:\n\ 177 \t\t\tstream or dgram\n\ 178 -z\t\t\tDo not send real control data if possible\n\n"); 179 fprintf(stderr, " Available tests for stream sockets:\n"); 180 for (test_func = test_stream_tbl; test_func->desc != NULL; ++test_func) 181 fprintf(stderr, " %s\n", test_func->desc); 182 fprintf(stderr, "\n Available tests for datagram sockets:\n"); 183 for (test_func = test_dgram_tbl; test_func->desc != NULL; ++test_func) 184 fprintf(stderr, " %s\n", test_func->desc); 185 } 186 187 /* 188 * printf-like function for outputting to STDOUT_FILENO. 189 */ 190 static void 191 output(const char *format, ...) 192 { 193 char buf[128]; 194 va_list ap; 195 196 va_start(ap, format); 197 if (vsnprintf(buf, sizeof(buf), format, ap) < 0) 198 err(EX_SOFTWARE, "output: vsnprintf failed"); 199 write(STDOUT_FILENO, buf, strlen(buf)); 200 va_end(ap); 201 } 202 203 /* 204 * printf-like function for logging, also outputs message for errno. 205 */ 206 static void 207 logmsg(const char *format, ...) 208 { 209 char buf[128]; 210 va_list ap; 211 int errno_save; 212 213 errno_save = errno; /* Save errno. */ 214 215 va_start(ap, format); 216 if (vsnprintf(buf, sizeof(buf), format, ap) < 0) 217 err(EX_SOFTWARE, "logmsg: vsnprintf failed"); 218 if (errno_save == 0) 219 output("%s: %s\n", myname, buf); 220 else 221 output("%s: %s: %s\n", myname, buf, strerror(errno_save)); 222 va_end(ap); 223 224 errno = errno_save; /* Restore errno. */ 225 } 226 227 /* 228 * printf-like function for logging, do not output message for errno. 229 */ 230 static void 231 logmsgx(const char *format, ...) 232 { 233 char buf[128]; 234 va_list ap; 235 236 va_start(ap, format); 237 if (vsnprintf(buf, sizeof(buf), format, ap) < 0) 238 err(EX_SOFTWARE, "logmsgx: vsnprintf failed"); 239 output("%s: %s\n", myname, buf); 240 va_end(ap); 241 } 242 243 /* 244 * Run tests from testno1 to testno2. 245 */ 246 static int 247 run_tests(u_int testno1, u_int testno2) 248 { 249 const struct test_func *test_func; 250 u_int i, nfailed1; 251 252 output("Running tests for %s sockets:\n", sock_type_str); 253 test_func = (sock_type == SOCK_STREAM ? 254 test_stream_tbl : test_dgram_tbl) + testno1; 255 256 nfailed1 = 0; 257 for (i = testno1; i <= testno2; ++test_func, ++i) { 258 output(" %s\n", test_func->desc); 259 switch (test_func->func()) { 260 case -1: 261 ++nfailed1; 262 break; 263 case -2: 264 logmsgx("some system error occurred, exiting"); 265 return (-1); 266 } 267 } 268 269 nfailed += nfailed1; 270 271 if (testno1 != testno2) { 272 if (nfailed1 == 0) 273 output("-- all tests were passed!\n"); 274 else 275 output("-- %u test%s failed!\n", nfailed1, 276 nfailed1 == 1 ? "" : "s"); 277 } else { 278 if (nfailed == 0) 279 output("-- test was passed!\n"); 280 else 281 output("-- test failed!\n"); 282 } 283 284 return (0); 285 } 286 287 /* ARGSUSED */ 288 static void 289 sig_alrm(int signo __unused) 290 { 291 siglongjmp(env_alrm, 1); 292 } 293 294 /* 295 * Initialize signals handlers. 296 */ 297 static void 298 sig_init(void) 299 { 300 struct sigaction sa; 301 302 sa.sa_handler = SIG_IGN; 303 sigemptyset(&sa.sa_mask); 304 sa.sa_flags = 0; 305 if (sigaction(SIGPIPE, &sa, (struct sigaction *)NULL) < 0) 306 err(EX_OSERR, "sigaction(SIGPIPE)"); 307 308 sa.sa_handler = sig_alrm; 309 if (sigaction(SIGALRM, &sa, (struct sigaction *)NULL) < 0) 310 err(EX_OSERR, "sigaction(SIGALRM)"); 311 } 312 313 int 314 main(int argc, char *argv[]) 315 { 316 const char *errstr; 317 int opt, dgramflag, streamflag; 318 u_int testno1, testno2; 319 320 dgramflag = streamflag = 0; 321 while ((opt = getopt(argc, argv, "dht:z")) != -1) 322 switch (opt) { 323 case 'd': 324 debug = 1; 325 break; 326 case 'h': 327 usage(0); 328 return (EX_OK); 329 case 't': 330 if (strcmp(optarg, "stream") == 0) 331 streamflag = 1; 332 else if (strcmp(optarg, "dgram") == 0) 333 dgramflag = 1; 334 else 335 errx(EX_USAGE, "wrong socket type in -t option"); 336 break; 337 case 'z': 338 no_control_data = 1; 339 break; 340 case '?': 341 default: 342 usage(1); 343 return (EX_USAGE); 344 } 345 346 if (optind < argc) { 347 if (optind + 1 != argc) 348 errx(EX_USAGE, "too many arguments"); 349 testno1 = strtonum(argv[optind], 0, UINT_MAX, &errstr); 350 if (errstr != NULL) 351 errx(EX_USAGE, "wrong test number: %s", errstr); 352 } else 353 testno1 = 0; 354 355 if (dgramflag == 0 && streamflag == 0) 356 dgramflag = streamflag = 1; 357 358 if (dgramflag && streamflag && testno1 != 0) 359 errx(EX_USAGE, "you can use particular test, only with datagram or stream sockets"); 360 361 if (streamflag) { 362 if (testno1 > TEST_STREAM_NO_MAX) 363 errx(EX_USAGE, "given test %u for stream sockets does not exist", 364 testno1); 365 } else { 366 if (testno1 > TEST_DGRAM_NO_MAX) 367 errx(EX_USAGE, "given test %u for datagram sockets does not exist", 368 testno1); 369 } 370 371 my_uid = getuid(); 372 my_euid = geteuid(); 373 my_gid = getgid(); 374 my_egid = getegid(); 375 switch (my_ngids = getgroups(sizeof(my_gids) / sizeof(my_gids[0]), my_gids)) { 376 case -1: 377 err(EX_SOFTWARE, "getgroups"); 378 /* NOTREACHED */ 379 case 0: 380 errx(EX_OSERR, "getgroups returned 0 groups"); 381 } 382 383 sig_init(); 384 385 if (mkdtemp(tempdir) == NULL) 386 err(EX_OSERR, "mkdtemp"); 387 388 if (streamflag) { 389 sock_type = SOCK_STREAM; 390 sock_type_str = "SOCK_STREAM"; 391 if (testno1 == 0) { 392 testno1 = 1; 393 testno2 = TEST_STREAM_NO_MAX; 394 } else 395 testno2 = testno1; 396 if (run_tests(testno1, testno2) < 0) 397 goto failed; 398 testno1 = 0; 399 } 400 401 if (dgramflag) { 402 sock_type = SOCK_DGRAM; 403 sock_type_str = "SOCK_DGRAM"; 404 if (testno1 == 0) { 405 testno1 = 1; 406 testno2 = TEST_DGRAM_NO_MAX; 407 } else 408 testno2 = testno1; 409 if (run_tests(testno1, testno2) < 0) 410 goto failed; 411 } 412 413 if (rmdir(tempdir) < 0) { 414 logmsg("rmdir(%s)", tempdir); 415 return (EX_OSERR); 416 } 417 418 return (nfailed ? EX_OSERR : EX_OK); 419 420 failed: 421 if (rmdir(tempdir) < 0) 422 logmsg("rmdir(%s)", tempdir); 423 return (EX_OSERR); 424 } 425 426 /* 427 * Create PF_LOCAL socket, if sock_path is not equal to NULL, then 428 * bind() it. Return socket address in addr. Return file descriptor 429 * or -1 if some error occurred. 430 */ 431 static int 432 create_socket(char *sock_path, size_t sock_path_len, struct sockaddr_un *addr) 433 { 434 int rv, fd; 435 436 if ((fd = socket(PF_LOCAL, sock_type, 0)) < 0) { 437 logmsg("create_socket: socket(PF_LOCAL, %s, 0)", sock_type_str); 438 return (-1); 439 } 440 441 if (sock_path != NULL) { 442 if ((rv = snprintf(sock_path, sock_path_len, "%s/%s", 443 tempdir, myname)) < 0) { 444 logmsg("create_socket: snprintf failed"); 445 goto failed; 446 } 447 if ((size_t)rv >= sock_path_len) { 448 logmsgx("create_socket: too long path name for given buffer"); 449 goto failed; 450 } 451 452 memset(addr, 0, sizeof(addr)); 453 addr->sun_family = AF_LOCAL; 454 if (strlen(sock_path) >= sizeof(addr->sun_path)) { 455 logmsgx("create_socket: too long path name (>= %lu) for local domain socket", 456 (u_long)sizeof(addr->sun_path)); 457 goto failed; 458 } 459 strcpy(addr->sun_path, sock_path); 460 461 if (bind(fd, (struct sockaddr *)addr, SUN_LEN(addr)) < 0) { 462 logmsg("create_socket: bind(%s)", sock_path); 463 goto failed; 464 } 465 } 466 467 return (fd); 468 469 failed: 470 if (close(fd) < 0) 471 logmsg("create_socket: close"); 472 return (-1); 473 } 474 475 /* 476 * Call create_socket() for server listening socket. 477 * Return socket descriptor or -1 if some error occurred. 478 */ 479 static int 480 create_server_socket(void) 481 { 482 return (create_socket(serv_sock_path, sizeof(serv_sock_path), &servaddr)); 483 } 484 485 /* 486 * Create unbound socket. 487 */ 488 static int 489 create_unbound_socket(void) 490 { 491 return (create_socket((char *)NULL, 0, (struct sockaddr_un *)NULL)); 492 } 493 494 /* 495 * Close socket descriptor, if sock_path is not equal to NULL, 496 * then unlink the given path. 497 */ 498 static int 499 close_socket(const char *sock_path, int fd) 500 { 501 int error = 0; 502 503 if (close(fd) < 0) { 504 logmsg("close_socket: close"); 505 error = -1; 506 } 507 if (sock_path != NULL) 508 if (unlink(sock_path) < 0) { 509 logmsg("close_socket: unlink(%s)", sock_path); 510 error = -1; 511 } 512 return (error); 513 } 514 515 /* 516 * Connect to server (socket address in servaddr). 517 */ 518 static int 519 connect_server(int fd) 520 { 521 dbgmsg(("connecting to %s", serv_sock_path)); 522 523 /* 524 * If PF_LOCAL listening socket's queue is full, then connect() 525 * returns ECONNREFUSED immediately, do not need timeout. 526 */ 527 if (connect(fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { 528 logmsg("connect_server: connect(%s)", serv_sock_path); 529 return (-1); 530 } 531 532 return (0); 533 } 534 535 /* 536 * sendmsg() with timeout. 537 */ 538 static int 539 sendmsg_timeout(int fd, struct msghdr *msg, size_t n) 540 { 541 ssize_t nsent; 542 543 dbgmsg(("sending %lu bytes", (u_long)n)); 544 545 if (sigsetjmp(env_alrm, 1) != 0) { 546 logmsgx("sendmsg_timeout: cannot send message to %s (timeout)", serv_sock_path); 547 return (-1); 548 } 549 550 (void)alarm(TIMEOUT); 551 552 nsent = sendmsg(fd, msg, 0); 553 554 (void)alarm(0); 555 556 if (nsent < 0) { 557 logmsg("sendmsg_timeout: sendmsg"); 558 return (-1); 559 } 560 561 if ((size_t)nsent != n) { 562 logmsgx("sendmsg_timeout: sendmsg: short send: %ld of %lu bytes", 563 (long)nsent, (u_long)n); 564 return (-1); 565 } 566 567 return (0); 568 } 569 570 /* 571 * accept() with timeout. 572 */ 573 static int 574 accept_timeout(int listenfd) 575 { 576 int fd; 577 578 dbgmsg(("accepting connection")); 579 580 if (sigsetjmp(env_alrm, 1) != 0) { 581 logmsgx("accept_timeout: cannot accept connection (timeout)"); 582 return (-1); 583 } 584 585 (void)alarm(TIMEOUT); 586 587 fd = accept(listenfd, (struct sockaddr *)NULL, (socklen_t *)NULL); 588 589 (void)alarm(0); 590 591 if (fd < 0) { 592 logmsg("accept_timeout: accept"); 593 return (-1); 594 } 595 596 return (fd); 597 } 598 599 /* 600 * recvmsg() with timeout. 601 */ 602 static int 603 recvmsg_timeout(int fd, struct msghdr *msg, size_t n) 604 { 605 ssize_t nread; 606 607 dbgmsg(("receiving %lu bytes", (u_long)n)); 608 609 if (sigsetjmp(env_alrm, 1) != 0) { 610 logmsgx("recvmsg_timeout: cannot receive message (timeout)"); 611 return (-1); 612 } 613 614 (void)alarm(TIMEOUT); 615 616 nread = recvmsg(fd, msg, MSG_WAITALL); 617 618 (void)alarm(0); 619 620 if (nread < 0) { 621 logmsg("recvmsg_timeout: recvmsg"); 622 return (-1); 623 } 624 625 if ((size_t)nread != n) { 626 logmsgx("recvmsg_timeout: recvmsg: short read: %ld of %lu bytes", 627 (long)nread, (u_long)n); 628 return (-1); 629 } 630 631 return (0); 632 } 633 634 /* 635 * Wait for synchronization message (1 byte) with timeout. 636 */ 637 static int 638 sync_recv(int fd) 639 { 640 ssize_t nread; 641 char buf; 642 643 dbgmsg(("waiting for sync message")); 644 645 if (sigsetjmp(env_alrm, 1) != 0) { 646 logmsgx("sync_recv: cannot receive sync message (timeout)"); 647 return (-1); 648 } 649 650 (void)alarm(TIMEOUT); 651 652 nread = read(fd, &buf, 1); 653 654 (void)alarm(0); 655 656 if (nread < 0) { 657 logmsg("sync_recv: read"); 658 return (-1); 659 } 660 661 if (nread != 1) { 662 logmsgx("sync_recv: read: short read: %ld of 1 byte", 663 (long)nread); 664 return (-1); 665 } 666 667 return (0); 668 } 669 670 /* 671 * Send synchronization message (1 byte) with timeout. 672 */ 673 static int 674 sync_send(int fd) 675 { 676 ssize_t nsent; 677 678 dbgmsg(("sending sync message")); 679 680 if (sigsetjmp(env_alrm, 1) != 0) { 681 logmsgx("sync_send: cannot send sync message (timeout)"); 682 return (-1); 683 } 684 685 (void)alarm(TIMEOUT); 686 687 nsent = write(fd, "", 1); 688 689 (void)alarm(0); 690 691 if (nsent < 0) { 692 logmsg("sync_send: write"); 693 return (-1); 694 } 695 696 if (nsent != 1) { 697 logmsgx("sync_send: write: short write: %ld of 1 byte", 698 (long)nsent); 699 return (-1); 700 } 701 702 return (0); 703 } 704 705 /* 706 * waitpid() for client with timeout. 707 */ 708 static int 709 wait_client(void) 710 { 711 int status; 712 pid_t pid; 713 714 if (sigsetjmp(env_alrm, 1) != 0) { 715 logmsgx("wait_client: cannot get exit status of client PID %ld (timeout)", 716 (long)client_pid); 717 return (-1); 718 } 719 720 (void)alarm(TIMEOUT); 721 722 pid = waitpid(client_pid, &status, 0); 723 724 (void)alarm(0); 725 726 if (pid == (pid_t)-1) { 727 logmsg("wait_client: waitpid"); 728 return (-1); 729 } 730 731 if (WIFEXITED(status)) { 732 if (WEXITSTATUS(status) != 0) { 733 logmsgx("wait_client: exit status of client PID %ld is %d", 734 (long)client_pid, WEXITSTATUS(status)); 735 return (-1); 736 } 737 } else { 738 if (WIFSIGNALED(status)) 739 logmsgx("wait_client: abnormal termination of client PID %ld, signal %d%s", 740 (long)client_pid, WTERMSIG(status), WCOREDUMP(status) ? " (core file generated)" : ""); 741 else 742 logmsgx("wait_client: termination of client PID %ld, unknown status", 743 (long)client_pid); 744 return (-1); 745 } 746 747 return (0); 748 } 749 750 /* 751 * Check if n supplementary GIDs in gids are correct. (my_gids + 1) 752 * has (my_ngids - 1) supplementary GIDs of current process. 753 */ 754 static int 755 check_groups(const gid_t *gids, int n) 756 { 757 char match[NGROUPS_MAX] = { 0 }; 758 int error, i, j; 759 760 if (n != my_ngids - 1) { 761 logmsgx("wrong number of groups %d != %d (returned from getgroups() - 1)", 762 n, my_ngids - 1); 763 error = -1; 764 } else 765 error = 0; 766 for (i = 0; i < n; ++i) { 767 for (j = 1; j < my_ngids; ++j) { 768 if (gids[i] == my_gids[j]) { 769 if (match[j]) { 770 logmsgx("duplicated GID %lu", 771 (u_long)gids[i]); 772 error = -1; 773 } else 774 match[j] = 1; 775 break; 776 } 777 } 778 if (j == my_ngids) { 779 logmsgx("unexpected GID %lu", (u_long)gids[i]); 780 error = -1; 781 } 782 } 783 for (j = 1; j < my_ngids; ++j) 784 if (match[j] == 0) { 785 logmsgx("did not receive supplementary GID %u", my_gids[j]); 786 error = -1; 787 } 788 return (error); 789 } 790 791 /* 792 * Send n messages with data and control message with SCM_CREDS type 793 * to server and exit. 794 */ 795 static void 796 t_cmsgcred_client(u_int n) 797 { 798 union { 799 struct cmsghdr cm; 800 char control[CMSG_SPACE(sizeof(struct cmsgcred))]; 801 } control_un; 802 struct msghdr msg; 803 struct iovec iov[1]; 804 struct cmsghdr *cmptr; 805 int fd; 806 u_int i; 807 808 assert(n == 1 || n == 2); 809 810 if ((fd = create_unbound_socket()) < 0) 811 goto failed; 812 813 if (connect_server(fd) < 0) 814 goto failed_close; 815 816 iov[0].iov_base = ipc_message; 817 iov[0].iov_len = IPC_MESSAGE_SIZE; 818 819 msg.msg_name = NULL; 820 msg.msg_namelen = 0; 821 msg.msg_iov = iov; 822 msg.msg_iovlen = 1; 823 msg.msg_control = control_un.control; 824 msg.msg_controllen = no_control_data ? 825 sizeof(struct cmsghdr) : sizeof(control_un.control); 826 msg.msg_flags = 0; 827 828 cmptr = CMSG_FIRSTHDR(&msg); 829 cmptr->cmsg_len = CMSG_LEN(no_control_data ? 830 0 : sizeof(struct cmsgcred)); 831 cmptr->cmsg_level = SOL_SOCKET; 832 cmptr->cmsg_type = SCM_CREDS; 833 834 for (i = 0; i < n; ++i) { 835 dbgmsg(("#%u msg_controllen = %u, cmsg_len = %u", i, 836 (u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len)); 837 if (sendmsg_timeout(fd, &msg, IPC_MESSAGE_SIZE) < 0) 838 goto failed_close; 839 } 840 841 if (close_socket((const char *)NULL, fd) < 0) 842 goto failed; 843 844 _exit(0); 845 846 failed_close: 847 (void)close_socket((const char *)NULL, fd); 848 849 failed: 850 _exit(1); 851 } 852 853 /* 854 * Receive two messages with data and control message with SCM_CREDS 855 * type followed by struct cmsgcred{} from client. fd1 is a listen 856 * socket for stream sockets or simply socket for datagram sockets. 857 */ 858 static int 859 t_cmsgcred_server(int fd1) 860 { 861 char buf[IPC_MESSAGE_SIZE]; 862 union { 863 struct cmsghdr cm; 864 char control[CMSG_SPACE(sizeof(struct cmsgcred)) + EXTRA_CMSG_SPACE]; 865 } control_un; 866 struct msghdr msg; 867 struct iovec iov[1]; 868 struct cmsghdr *cmptr; 869 const struct cmsgcred *cmcredptr; 870 socklen_t controllen; 871 int error, error2, fd2; 872 u_int i; 873 874 if (sock_type == SOCK_STREAM) { 875 if ((fd2 = accept_timeout(fd1)) < 0) 876 return (-2); 877 } else 878 fd2 = fd1; 879 880 error = 0; 881 882 controllen = sizeof(control_un.control); 883 884 for (i = 0; i < 2; ++i) { 885 iov[0].iov_base = buf; 886 iov[0].iov_len = sizeof(buf); 887 888 msg.msg_name = NULL; 889 msg.msg_namelen = 0; 890 msg.msg_iov = iov; 891 msg.msg_iovlen = 1; 892 msg.msg_control = control_un.control; 893 msg.msg_controllen = controllen; 894 msg.msg_flags = 0; 895 896 controllen = CMSG_SPACE(sizeof(struct cmsgcred)); 897 898 if (recvmsg_timeout(fd2, &msg, sizeof(buf)) < 0) 899 goto failed; 900 901 if (msg.msg_flags & MSG_CTRUNC) { 902 logmsgx("#%u control data was truncated, MSG_CTRUNC flag is on", 903 i); 904 goto next_error; 905 } 906 907 if (msg.msg_controllen < sizeof(struct cmsghdr)) { 908 logmsgx("#%u msg_controllen %u < %lu (sizeof(struct cmsghdr))", 909 i, (u_int)msg.msg_controllen, (u_long)sizeof(struct cmsghdr)); 910 goto next_error; 911 } 912 913 if ((cmptr = CMSG_FIRSTHDR(&msg)) == NULL) { 914 logmsgx("CMSG_FIRSTHDR is NULL"); 915 goto next_error; 916 } 917 918 dbgmsg(("#%u msg_controllen = %u, cmsg_len = %u", i, 919 (u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len)); 920 921 if (cmptr->cmsg_level != SOL_SOCKET) { 922 logmsgx("#%u cmsg_level %d != SOL_SOCKET", i, 923 cmptr->cmsg_level); 924 goto next_error; 925 } 926 927 if (cmptr->cmsg_type != SCM_CREDS) { 928 logmsgx("#%u cmsg_type %d != SCM_CREDS", i, 929 cmptr->cmsg_type); 930 goto next_error; 931 } 932 933 if (cmptr->cmsg_len != CMSG_LEN(sizeof(struct cmsgcred))) { 934 logmsgx("#%u cmsg_len %u != %lu (CMSG_LEN(sizeof(struct cmsgcred))", 935 i, (u_int)cmptr->cmsg_len, (u_long)CMSG_LEN(sizeof(struct cmsgcred))); 936 goto next_error; 937 } 938 939 cmcredptr = (const struct cmsgcred *)CMSG_DATA(cmptr); 940 941 error2 = 0; 942 if (cmcredptr->cmcred_pid != client_pid) { 943 logmsgx("#%u cmcred_pid %ld != %ld (PID of client)", 944 i, (long)cmcredptr->cmcred_pid, (long)client_pid); 945 error2 = 1; 946 } 947 if (cmcredptr->cmcred_uid != my_uid) { 948 logmsgx("#%u cmcred_uid %lu != %lu (UID of current process)", 949 i, (u_long)cmcredptr->cmcred_uid, (u_long)my_uid); 950 error2 = 1; 951 } 952 if (cmcredptr->cmcred_euid != my_euid) { 953 logmsgx("#%u cmcred_euid %lu != %lu (EUID of current process)", 954 i, (u_long)cmcredptr->cmcred_euid, (u_long)my_euid); 955 error2 = 1; 956 } 957 if (cmcredptr->cmcred_gid != my_gid) { 958 logmsgx("#%u cmcred_gid %lu != %lu (GID of current process)", 959 i, (u_long)cmcredptr->cmcred_gid, (u_long)my_gid); 960 error2 = 1; 961 } 962 if (cmcredptr->cmcred_ngroups == 0) { 963 logmsgx("#%u cmcred_ngroups = 0, this is wrong", i); 964 error2 = 1; 965 } else { 966 if (cmcredptr->cmcred_ngroups > NGROUPS_MAX) { 967 logmsgx("#%u cmcred_ngroups %d > %u (NGROUPS_MAX)", 968 i, cmcredptr->cmcred_ngroups, NGROUPS_MAX); 969 error2 = 1; 970 } else if (cmcredptr->cmcred_ngroups < 0) { 971 logmsgx("#%u cmcred_ngroups %d < 0", 972 i, cmcredptr->cmcred_ngroups); 973 error2 = 1; 974 } else { 975 dbgmsg(("#%u cmcred_ngroups = %d", i, 976 cmcredptr->cmcred_ngroups)); 977 if (cmcredptr->cmcred_groups[0] != my_egid) { 978 logmsgx("#%u cmcred_groups[0] %lu != %lu (EGID of current process)", 979 i, (u_long)cmcredptr->cmcred_groups[0], (u_long)my_egid); 980 error2 = 1; 981 } 982 if (check_groups(cmcredptr->cmcred_groups + 1, cmcredptr->cmcred_ngroups - 1) < 0) { 983 logmsgx("#%u cmcred_groups has wrong GIDs", i); 984 error2 = 1; 985 } 986 } 987 } 988 989 if (error2) 990 goto next_error; 991 992 if ((cmptr = CMSG_NXTHDR(&msg, cmptr)) != NULL) { 993 logmsgx("#%u control data has extra header", i); 994 goto next_error; 995 } 996 997 continue; 998 next_error: 999 error = -1; 1000 } 1001 1002 if (sock_type == SOCK_STREAM) 1003 if (close(fd2) < 0) { 1004 logmsg("close"); 1005 return (-2); 1006 } 1007 return (error); 1008 1009 failed: 1010 if (sock_type == SOCK_STREAM) 1011 if (close(fd2) < 0) 1012 logmsg("close"); 1013 return (-2); 1014 } 1015 1016 static int 1017 t_cmsgcred(void) 1018 { 1019 int error, fd; 1020 1021 if ((fd = create_server_socket()) < 0) 1022 return (-2); 1023 1024 if (sock_type == SOCK_STREAM) 1025 if (listen(fd, LISTENQ) < 0) { 1026 logmsg("listen"); 1027 goto failed; 1028 } 1029 1030 if ((client_pid = fork()) == (pid_t)-1) { 1031 logmsg("fork"); 1032 goto failed; 1033 } 1034 1035 if (client_pid == 0) { 1036 myname = "CLIENT"; 1037 if (close_socket((const char *)NULL, fd) < 0) 1038 _exit(1); 1039 t_cmsgcred_client(2); 1040 } 1041 1042 if ((error = t_cmsgcred_server(fd)) == -2) { 1043 (void)wait_client(); 1044 goto failed; 1045 } 1046 1047 if (wait_client() < 0) 1048 goto failed; 1049 1050 if (close_socket(serv_sock_path, fd) < 0) { 1051 logmsgx("close_socket failed"); 1052 return (-2); 1053 } 1054 return (error); 1055 1056 failed: 1057 if (close_socket(serv_sock_path, fd) < 0) 1058 logmsgx("close_socket failed"); 1059 return (-2); 1060 } 1061 1062 /* 1063 * Send two messages with data to server and exit. 1064 */ 1065 static void 1066 t_sockcred_client(int type) 1067 { 1068 struct msghdr msg; 1069 struct iovec iov[1]; 1070 int fd; 1071 u_int i; 1072 1073 assert(type == 0 || type == 1); 1074 1075 if ((fd = create_unbound_socket()) < 0) 1076 goto failed; 1077 1078 if (connect_server(fd) < 0) 1079 goto failed_close; 1080 1081 if (type == 1) 1082 if (sync_recv(fd) < 0) 1083 goto failed_close; 1084 1085 iov[0].iov_base = ipc_message; 1086 iov[0].iov_len = IPC_MESSAGE_SIZE; 1087 1088 msg.msg_name = NULL; 1089 msg.msg_namelen = 0; 1090 msg.msg_iov = iov; 1091 msg.msg_iovlen = 1; 1092 msg.msg_control = NULL; 1093 msg.msg_controllen = 0; 1094 msg.msg_flags = 0; 1095 1096 for (i = 0; i < 2; ++i) 1097 if (sendmsg_timeout(fd, &msg, IPC_MESSAGE_SIZE) < 0) 1098 goto failed_close; 1099 1100 if (close_socket((const char *)NULL, fd) < 0) 1101 goto failed; 1102 1103 _exit(0); 1104 1105 failed_close: 1106 (void)close_socket((const char *)NULL, fd); 1107 1108 failed: 1109 _exit(1); 1110 } 1111 1112 /* 1113 * Receive one message with data and control message with SCM_CREDS 1114 * type followed by struct sockcred{} and if n is not equal 1, then 1115 * receive another one message with data. fd1 is a listen socket for 1116 * stream sockets or simply socket for datagram sockets. If type is 1117 * 1, then set LOCAL_CREDS option for accepted stream socket. 1118 */ 1119 static int 1120 t_sockcred_server(int type, int fd1, u_int n) 1121 { 1122 char buf[IPC_MESSAGE_SIZE]; 1123 union { 1124 struct cmsghdr cm; 1125 char control[CMSG_SPACE(SOCKCREDSIZE(NGROUPS_MAX)) + EXTRA_CMSG_SPACE]; 1126 } control_un; 1127 struct msghdr msg; 1128 struct iovec iov[1]; 1129 struct cmsghdr *cmptr; 1130 const struct sockcred *sockcred; 1131 int error, error2, fd2, optval; 1132 u_int i; 1133 1134 assert(n == 1 || n == 2); 1135 assert(type == 0 || type == 1); 1136 1137 if (sock_type == SOCK_STREAM) { 1138 if ((fd2 = accept_timeout(fd1)) < 0) 1139 return (-2); 1140 if (type == 1) { 1141 optval = 1; 1142 if (setsockopt(fd2, 0, LOCAL_CREDS, &optval, sizeof optval) < 0) { 1143 logmsg("setsockopt(LOCAL_CREDS) for accepted socket"); 1144 if (errno == ENOPROTOOPT) { 1145 error = -1; 1146 goto done_close; 1147 } 1148 goto failed; 1149 } 1150 if (sync_send(fd2) < 0) 1151 goto failed; 1152 } 1153 } else 1154 fd2 = fd1; 1155 1156 error = 0; 1157 1158 for (i = 0; i < n; ++i) { 1159 iov[0].iov_base = buf; 1160 iov[0].iov_len = sizeof buf; 1161 1162 msg.msg_name = NULL; 1163 msg.msg_namelen = 0; 1164 msg.msg_iov = iov; 1165 msg.msg_iovlen = 1; 1166 msg.msg_control = control_un.control; 1167 msg.msg_controllen = sizeof control_un.control; 1168 msg.msg_flags = 0; 1169 1170 if (recvmsg_timeout(fd2, &msg, sizeof buf) < 0) 1171 goto failed; 1172 1173 if (msg.msg_flags & MSG_CTRUNC) { 1174 logmsgx("control data was truncated, MSG_CTRUNC flag is on"); 1175 goto next_error; 1176 } 1177 1178 if (i != 0 && sock_type == SOCK_STREAM) { 1179 if (msg.msg_controllen != 0) { 1180 logmsgx("second message has control data, this is wrong for stream sockets"); 1181 goto next_error; 1182 } 1183 dbgmsg(("#%u msg_controllen = %u", i, 1184 (u_int)msg.msg_controllen)); 1185 continue; 1186 } 1187 1188 if (msg.msg_controllen < sizeof(struct cmsghdr)) { 1189 logmsgx("#%u msg_controllen %u < %lu (sizeof(struct cmsghdr))", 1190 i, (u_int)msg.msg_controllen, (u_long)sizeof(struct cmsghdr)); 1191 goto next_error; 1192 } 1193 1194 if ((cmptr = CMSG_FIRSTHDR(&msg)) == NULL) { 1195 logmsgx("CMSG_FIRSTHDR is NULL"); 1196 goto next_error; 1197 } 1198 1199 dbgmsg(("#%u msg_controllen = %u, cmsg_len = %u", i, 1200 (u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len)); 1201 1202 if (cmptr->cmsg_level != SOL_SOCKET) { 1203 logmsgx("#%u cmsg_level %d != SOL_SOCKET", i, 1204 cmptr->cmsg_level); 1205 goto next_error; 1206 } 1207 1208 if (cmptr->cmsg_type != SCM_CREDS) { 1209 logmsgx("#%u cmsg_type %d != SCM_CREDS", i, 1210 cmptr->cmsg_type); 1211 goto next_error; 1212 } 1213 1214 if (cmptr->cmsg_len < CMSG_LEN(SOCKCREDSIZE(1))) { 1215 logmsgx("#%u cmsg_len %u != %lu (CMSG_LEN(SOCKCREDSIZE(1)))", 1216 i, (u_int)cmptr->cmsg_len, (u_long)CMSG_LEN(SOCKCREDSIZE(1))); 1217 goto next_error; 1218 } 1219 1220 sockcred = (const struct sockcred *)CMSG_DATA(cmptr); 1221 1222 error2 = 0; 1223 if (sockcred->sc_uid != my_uid) { 1224 logmsgx("#%u sc_uid %lu != %lu (UID of current process)", 1225 i, (u_long)sockcred->sc_uid, (u_long)my_uid); 1226 error2 = 1; 1227 } 1228 if (sockcred->sc_euid != my_euid) { 1229 logmsgx("#%u sc_euid %lu != %lu (EUID of current process)", 1230 i, (u_long)sockcred->sc_euid, (u_long)my_euid); 1231 error2 = 1; 1232 } 1233 if (sockcred->sc_gid != my_gid) { 1234 logmsgx("#%u sc_gid %lu != %lu (GID of current process)", 1235 i, (u_long)sockcred->sc_gid, (u_long)my_gid); 1236 error2 = 1; 1237 } 1238 if (sockcred->sc_egid != my_egid) { 1239 logmsgx("#%u sc_egid %lu != %lu (EGID of current process)", 1240 i, (u_long)sockcred->sc_gid, (u_long)my_egid); 1241 error2 = 1; 1242 } 1243 if (sockcred->sc_ngroups > NGROUPS_MAX) { 1244 logmsgx("#%u sc_ngroups %d > %u (NGROUPS_MAX)", 1245 i, sockcred->sc_ngroups, NGROUPS_MAX); 1246 error2 = 1; 1247 } else if (sockcred->sc_ngroups < 0) { 1248 logmsgx("#%u sc_ngroups %d < 0", 1249 i, sockcred->sc_ngroups); 1250 error2 = 1; 1251 } else { 1252 dbgmsg(("#%u sc_ngroups = %d", i, sockcred->sc_ngroups)); 1253 if (check_groups(sockcred->sc_groups, sockcred->sc_ngroups) < 0) { 1254 logmsgx("#%u sc_groups has wrong GIDs", i); 1255 error2 = 1; 1256 } 1257 } 1258 1259 if (error2) 1260 goto next_error; 1261 1262 if ((cmptr = CMSG_NXTHDR(&msg, cmptr)) != NULL) { 1263 logmsgx("#%u control data has extra header, this is wrong", 1264 i); 1265 goto next_error; 1266 } 1267 1268 continue; 1269 next_error: 1270 error = -1; 1271 } 1272 1273 done_close: 1274 if (sock_type == SOCK_STREAM) 1275 if (close(fd2) < 0) { 1276 logmsg("close"); 1277 return (-2); 1278 } 1279 return (error); 1280 1281 failed: 1282 if (sock_type == SOCK_STREAM) 1283 if (close(fd2) < 0) 1284 logmsg("close"); 1285 return (-2); 1286 } 1287 1288 static int 1289 t_sockcred(int type) 1290 { 1291 int error, fd, optval; 1292 1293 assert(type == 0 || type == 1); 1294 1295 if ((fd = create_server_socket()) < 0) 1296 return (-2); 1297 1298 if (sock_type == SOCK_STREAM) 1299 if (listen(fd, LISTENQ) < 0) { 1300 logmsg("listen"); 1301 goto failed; 1302 } 1303 1304 if (type == 0) { 1305 optval = 1; 1306 if (setsockopt(fd, 0, LOCAL_CREDS, &optval, sizeof optval) < 0) { 1307 logmsg("setsockopt(LOCAL_CREDS) for %s socket", 1308 sock_type == SOCK_STREAM ? "stream listening" : "datagram"); 1309 if (errno == ENOPROTOOPT) { 1310 error = -1; 1311 goto done_close; 1312 } 1313 goto failed; 1314 } 1315 } 1316 1317 if ((client_pid = fork()) == (pid_t)-1) { 1318 logmsg("fork"); 1319 goto failed; 1320 } 1321 1322 if (client_pid == 0) { 1323 myname = "CLIENT"; 1324 if (close_socket((const char *)NULL, fd) < 0) 1325 _exit(1); 1326 t_sockcred_client(type); 1327 } 1328 1329 if ((error = t_sockcred_server(type, fd, 2)) == -2) { 1330 (void)wait_client(); 1331 goto failed; 1332 } 1333 1334 if (wait_client() < 0) 1335 goto failed; 1336 1337 done_close: 1338 if (close_socket(serv_sock_path, fd) < 0) { 1339 logmsgx("close_socket failed"); 1340 return (-2); 1341 } 1342 return (error); 1343 1344 failed: 1345 if (close_socket(serv_sock_path, fd) < 0) 1346 logmsgx("close_socket failed"); 1347 return (-2); 1348 } 1349 1350 static int 1351 t_sockcred_stream1(void) 1352 { 1353 return (t_sockcred(0)); 1354 } 1355 1356 static int 1357 t_sockcred_stream2(void) 1358 { 1359 return (t_sockcred(1)); 1360 } 1361 1362 static int 1363 t_sockcred_dgram(void) 1364 { 1365 return (t_sockcred(0)); 1366 } 1367 1368 static int 1369 t_cmsgcred_sockcred(void) 1370 { 1371 int error, fd, optval; 1372 1373 if ((fd = create_server_socket()) < 0) 1374 return (-2); 1375 1376 if (sock_type == SOCK_STREAM) 1377 if (listen(fd, LISTENQ) < 0) { 1378 logmsg("listen"); 1379 goto failed; 1380 } 1381 1382 optval = 1; 1383 if (setsockopt(fd, 0, LOCAL_CREDS, &optval, sizeof optval) < 0) { 1384 logmsg("setsockopt(LOCAL_CREDS) for %s socket", 1385 sock_type == SOCK_STREAM ? "stream listening" : "datagram"); 1386 if (errno == ENOPROTOOPT) { 1387 error = -1; 1388 goto done_close; 1389 } 1390 goto failed; 1391 } 1392 1393 if ((client_pid = fork()) == (pid_t)-1) { 1394 logmsg("fork"); 1395 goto failed; 1396 } 1397 1398 if (client_pid == 0) { 1399 myname = "CLIENT"; 1400 if (close_socket((const char *)NULL, fd) < 0) 1401 _exit(1); 1402 t_cmsgcred_client(1); 1403 } 1404 1405 if ((error = t_sockcred_server(0, fd, 1)) == -2) { 1406 (void)wait_client(); 1407 goto failed; 1408 } 1409 1410 if (wait_client() < 0) 1411 goto failed; 1412 1413 done_close: 1414 if (close_socket(serv_sock_path, fd) < 0) { 1415 logmsgx("close_socket failed"); 1416 return (-2); 1417 } 1418 return (error); 1419 1420 failed: 1421 if (close_socket(serv_sock_path, fd) < 0) 1422 logmsgx("close_socket failed"); 1423 return (-2); 1424 } 1425 1426 /* 1427 * Send one message with data and control message with SCM_TIMESTAMP 1428 * type to server and exit. 1429 */ 1430 static void 1431 t_timestamp_client(void) 1432 { 1433 union { 1434 struct cmsghdr cm; 1435 char control[CMSG_SPACE(sizeof(struct timeval))]; 1436 } control_un; 1437 struct msghdr msg; 1438 struct iovec iov[1]; 1439 struct cmsghdr *cmptr; 1440 int fd; 1441 1442 if ((fd = create_unbound_socket()) < 0) 1443 goto failed; 1444 1445 if (connect_server(fd) < 0) 1446 goto failed_close; 1447 1448 iov[0].iov_base = ipc_message; 1449 iov[0].iov_len = IPC_MESSAGE_SIZE; 1450 1451 msg.msg_name = NULL; 1452 msg.msg_namelen = 0; 1453 msg.msg_iov = iov; 1454 msg.msg_iovlen = 1; 1455 msg.msg_control = control_un.control; 1456 msg.msg_controllen = no_control_data ? 1457 sizeof(struct cmsghdr) :sizeof control_un.control; 1458 msg.msg_flags = 0; 1459 1460 cmptr = CMSG_FIRSTHDR(&msg); 1461 cmptr->cmsg_len = CMSG_LEN(no_control_data ? 1462 0 : sizeof(struct timeval)); 1463 cmptr->cmsg_level = SOL_SOCKET; 1464 cmptr->cmsg_type = SCM_TIMESTAMP; 1465 1466 dbgmsg(("msg_controllen = %u, cmsg_len = %u", 1467 (u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len)); 1468 1469 if (sendmsg_timeout(fd, &msg, IPC_MESSAGE_SIZE) < 0) 1470 goto failed_close; 1471 1472 if (close_socket((const char *)NULL, fd) < 0) 1473 goto failed; 1474 1475 _exit(0); 1476 1477 failed_close: 1478 (void)close_socket((const char *)NULL, fd); 1479 1480 failed: 1481 _exit(1); 1482 } 1483 1484 /* 1485 * Receive one message with data and control message with SCM_TIMESTAMP 1486 * type followed by struct timeval{} from client. 1487 */ 1488 static int 1489 t_timestamp_server(int fd1) 1490 { 1491 union { 1492 struct cmsghdr cm; 1493 char control[CMSG_SPACE(sizeof(struct timeval)) + EXTRA_CMSG_SPACE]; 1494 } control_un; 1495 char buf[IPC_MESSAGE_SIZE]; 1496 int error, fd2; 1497 struct msghdr msg; 1498 struct iovec iov[1]; 1499 struct cmsghdr *cmptr; 1500 const struct timeval *timeval; 1501 1502 if (sock_type == SOCK_STREAM) { 1503 if ((fd2 = accept_timeout(fd1)) < 0) 1504 return (-2); 1505 } else 1506 fd2 = fd1; 1507 1508 iov[0].iov_base = buf; 1509 iov[0].iov_len = sizeof buf; 1510 1511 msg.msg_name = NULL; 1512 msg.msg_namelen = 0; 1513 msg.msg_iov = iov; 1514 msg.msg_iovlen = 1; 1515 msg.msg_control = control_un.control; 1516 msg.msg_controllen = sizeof control_un.control;; 1517 msg.msg_flags = 0; 1518 1519 if (recvmsg_timeout(fd2, &msg, sizeof buf) < 0) 1520 goto failed; 1521 1522 error = -1; 1523 1524 if (msg.msg_flags & MSG_CTRUNC) { 1525 logmsgx("control data was truncated, MSG_CTRUNC flag is on"); 1526 goto done; 1527 } 1528 1529 if (msg.msg_controllen < sizeof(struct cmsghdr)) { 1530 logmsgx("msg_controllen %u < %lu (sizeof(struct cmsghdr))", 1531 (u_int)msg.msg_controllen, (u_long)sizeof(struct cmsghdr)); 1532 goto done; 1533 } 1534 1535 if ((cmptr = CMSG_FIRSTHDR(&msg)) == NULL) { 1536 logmsgx("CMSG_FIRSTHDR is NULL"); 1537 goto done; 1538 } 1539 1540 dbgmsg(("msg_controllen = %u, cmsg_len = %u", 1541 (u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len)); 1542 1543 if (cmptr->cmsg_level != SOL_SOCKET) { 1544 logmsgx("cmsg_level %d != SOL_SOCKET", cmptr->cmsg_level); 1545 goto done; 1546 } 1547 1548 if (cmptr->cmsg_type != SCM_TIMESTAMP) { 1549 logmsgx("cmsg_type %d != SCM_TIMESTAMP", cmptr->cmsg_type); 1550 goto done; 1551 } 1552 1553 if (cmptr->cmsg_len != CMSG_LEN(sizeof(struct timeval))) { 1554 logmsgx("cmsg_len %u != %lu (CMSG_LEN(sizeof(struct timeval))", 1555 (u_int)cmptr->cmsg_len, (u_long)CMSG_LEN(sizeof(struct timeval))); 1556 goto done; 1557 } 1558 1559 timeval = (const struct timeval *)CMSG_DATA(cmptr); 1560 1561 dbgmsg(("timeval tv_sec %jd, tv_usec %jd", 1562 (intmax_t)timeval->tv_sec, (intmax_t)timeval->tv_usec)); 1563 1564 if ((cmptr = CMSG_NXTHDR(&msg, cmptr)) != NULL) { 1565 logmsgx("control data has extra header"); 1566 goto done; 1567 } 1568 1569 error = 0; 1570 1571 done: 1572 if (sock_type == SOCK_STREAM) 1573 if (close(fd2) < 0) { 1574 logmsg("close"); 1575 return (-2); 1576 } 1577 return (error); 1578 1579 failed: 1580 if (sock_type == SOCK_STREAM) 1581 if (close(fd2) < 0) 1582 logmsg("close"); 1583 return (-2); 1584 } 1585 1586 static int 1587 t_timestamp(void) 1588 { 1589 int error, fd; 1590 1591 if ((fd = create_server_socket()) < 0) 1592 return (-2); 1593 1594 if (sock_type == SOCK_STREAM) 1595 if (listen(fd, LISTENQ) < 0) { 1596 logmsg("listen"); 1597 goto failed; 1598 } 1599 1600 if ((client_pid = fork()) == (pid_t)-1) { 1601 logmsg("fork"); 1602 goto failed; 1603 } 1604 1605 if (client_pid == 0) { 1606 myname = "CLIENT"; 1607 if (close_socket((const char *)NULL, fd) < 0) 1608 _exit(1); 1609 t_timestamp_client(); 1610 } 1611 1612 if ((error = t_timestamp_server(fd)) == -2) { 1613 (void)wait_client(); 1614 goto failed; 1615 } 1616 1617 if (wait_client() < 0) 1618 goto failed; 1619 1620 if (close_socket(serv_sock_path, fd) < 0) { 1621 logmsgx("close_socket failed"); 1622 return (-2); 1623 } 1624 return (error); 1625 1626 failed: 1627 if (close_socket(serv_sock_path, fd) < 0) 1628 logmsgx("close_socket failed"); 1629 return (-2); 1630 } 1631