1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * Copyright (c) Cyril Hrubis <chrubis (at) suse.cz> 2012 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 14 * the GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 * 20 */ 21 22 /* 23 * Test Name: sendmsg01 24 * 25 * Test Description: 26 * Verify that sendmsg() returns the proper errno for various failure cases 27 * 28 * HISTORY 29 * 07/2001 Ported by Wayne Boyer 30 * 05/2003 Modified by Manoj Iyer - Make setup function set up lo device. 31 */ 32 33 #include <stdio.h> 34 #include <unistd.h> 35 #include <errno.h> 36 #include <string.h> 37 #include <fcntl.h> 38 #include <time.h> 39 #include <stdlib.h> 40 #include <sys/types.h> 41 #include <sys/socket.h> 42 #include <sys/signal.h> 43 #include <sys/uio.h> 44 #include <sys/un.h> 45 #include <sys/file.h> 46 #include <sys/wait.h> 47 48 #include <netinet/in.h> 49 50 #include "test.h" 51 #include "safe_macros.h" 52 53 char *TCID = "sendmsg01"; 54 int testno; 55 56 static char buf[1024], bigbuf[128 * 1024]; 57 static int s; 58 static struct sockaddr_in sin1, sin2; 59 static struct sockaddr_un sun1; 60 static struct msghdr msgdat; 61 static char cbuf[4096]; 62 static struct cmsghdr *control; 63 static int controllen; 64 static struct iovec iov[1]; 65 static int sfd; /* shared between do_child and start_server */ 66 static int ufd; /* shared between do_child and start_server */ 67 68 static void setup(void); 69 static void setup0(void); 70 static void setup1(void); 71 static void setup2(void); 72 static void setup3(void); 73 static void setup4(void); 74 static void setup5(void); 75 static void setup6(void); 76 static void setup8(void); 77 78 static void cleanup(void); 79 static void cleanup0(void); 80 static void cleanup1(void); 81 static void cleanup4(void); 82 83 static void do_child(void); 84 85 struct test_case_t { /* test case structure */ 86 int domain; /* PF_INET, PF_UNIX, ... */ 87 int type; /* SOCK_STREAM, SOCK_DGRAM ... */ 88 int proto; /* protocol number (usually 0 = default) */ 89 struct iovec *iov; 90 int iovcnt; /* # elements in iovec */ 91 void *buf; /* send data buffer */ 92 int buflen; /* send buffer length */ 93 struct msghdr *msg; 94 unsigned flags; 95 struct sockaddr *to; /* destination */ 96 int tolen; /* length of "to" buffer */ 97 int retval; /* syscall return value */ 98 int experrno; /* expected errno */ 99 void (*setup) (void); 100 void (*cleanup) (void); 101 char *desc; 102 }; 103 104 struct test_case_t tdat[] = { 105 {.domain = PF_INET, 106 .type = SOCK_STREAM, 107 .proto = 0, 108 .iov = iov, 109 .iovcnt = 1, 110 .buf = buf, 111 .buflen = sizeof(buf), 112 .msg = &msgdat, 113 .flags = 0, 114 .to = (struct sockaddr *)&sin1, 115 .tolen = sizeof(sin1), 116 .retval = -1, 117 .experrno = EBADF, 118 .setup = setup0, 119 .cleanup = cleanup0, 120 .desc = "bad file descriptor"} 121 , 122 {.domain = 0, 123 .type = 0, 124 .proto = 0, 125 .iov = iov, 126 .iovcnt = 1, 127 .buf = buf, 128 .buflen = sizeof(buf), 129 .msg = &msgdat, 130 .flags = 0, 131 .to = (struct sockaddr *)&sin1, 132 .tolen = sizeof(sin1), 133 .retval = -1, 134 .experrno = ENOTSOCK, 135 .setup = setup0, 136 .cleanup = cleanup0, 137 .desc = "invalid socket"} 138 , 139 {.domain = PF_INET, 140 .type = SOCK_DGRAM, 141 .proto = 0, 142 .iov = iov, 143 .iovcnt = 1, 144 .buf = (void *)-1, 145 .buflen = sizeof(buf), 146 .msg = &msgdat, 147 .flags = 0, 148 .to = (struct sockaddr *)&sin1, 149 .tolen = sizeof(sin1), 150 .retval = -1, 151 .experrno = EFAULT, 152 .setup = setup1, 153 .cleanup = cleanup1, 154 .desc = "invalid send buffer"} 155 , 156 {.domain = PF_INET, 157 .type = SOCK_STREAM, 158 .proto = 0, 159 .iov = iov, 160 .iovcnt = 1, 161 .buf = buf, 162 .buflen = sizeof(buf), 163 .msg = &msgdat, 164 .flags = 0, 165 .to = (struct sockaddr *)&sin2, 166 .tolen = sizeof(sin2), 167 .retval = 0, 168 .experrno = EFAULT, 169 .setup = setup5, 170 .cleanup = cleanup1, 171 .desc = "connected TCP"} 172 , 173 {.domain = PF_INET, 174 .type = SOCK_STREAM, 175 .proto = 0, 176 .iov = iov, 177 .iovcnt = 1, 178 .buf = buf, 179 .buflen = sizeof(buf), 180 .msg = &msgdat, 181 .flags = 0, 182 .to = (struct sockaddr *)&sin1, 183 .tolen = sizeof(sin1), 184 .retval = -1, 185 .experrno = EPIPE, 186 .setup = setup3, 187 .cleanup = cleanup1, 188 .desc = "not connected TCP"} 189 , 190 {.domain = PF_INET, 191 .type = SOCK_DGRAM, 192 .proto = 0, 193 .iov = iov, 194 .iovcnt = 1, 195 .buf = buf, 196 .buflen = sizeof(buf), 197 .msg = &msgdat, 198 .flags = 0, 199 .to = (struct sockaddr *)&sin1, 200 .tolen = 1, 201 .retval = -1, 202 .experrno = EINVAL, 203 .setup = setup1, 204 .cleanup = cleanup1, 205 .desc = "invalid to buffer length"}, 206 {.domain = PF_INET, 207 .type = SOCK_DGRAM, 208 .proto = 0, 209 .iov = iov, 210 .iovcnt = 1, 211 .buf = buf, 212 .buflen = sizeof(buf), 213 .msg = &msgdat, 214 .flags = 0, 215 .to = (struct sockaddr *)-1, 216 .tolen = sizeof(struct sockaddr), 217 .retval = -1, 218 .experrno = EFAULT, 219 .setup = setup1, 220 .cleanup = cleanup1, 221 .desc = "invalid to buffer"}, 222 {.domain = PF_INET, 223 .type = SOCK_DGRAM, 224 .proto = 0, 225 .iov = iov, 226 .iovcnt = 1, 227 .buf = bigbuf, 228 .buflen = sizeof(bigbuf), 229 .msg = &msgdat, 230 .flags = 0, 231 .to = (struct sockaddr *)&sin1, 232 .tolen = sizeof(sin1), 233 .retval = -1, 234 .experrno = EMSGSIZE, 235 .setup = setup1, 236 .cleanup = cleanup1, 237 .desc = "UDP message too big"} 238 , 239 {.domain = PF_INET, 240 .type = SOCK_STREAM, 241 .proto = 0, 242 .iov = iov, 243 .iovcnt = 1, 244 .buf = buf, 245 .buflen = sizeof(buf), 246 .msg = &msgdat, 247 .flags = 0, 248 .to = (struct sockaddr *)&sin1, 249 .tolen = sizeof(sin1), 250 .retval = -1, 251 .experrno = EPIPE, 252 .setup = setup2, 253 .cleanup = cleanup1, 254 .desc = "local endpoint shutdown"} 255 , 256 {.domain = PF_INET, 257 .type = SOCK_STREAM, 258 .proto = 0, 259 .iov = NULL, 260 .iovcnt = 1, 261 .buf = buf, 262 .buflen = sizeof(buf), 263 .msg = &msgdat, 264 .flags = 0, 265 .to = (struct sockaddr *)&sin1, 266 .tolen = sizeof(sin1), 267 .retval = -1, 268 .experrno = EFAULT, 269 .setup = setup1, 270 .cleanup = cleanup1, 271 .desc = "invalid iovec pointer"} 272 , 273 {.domain = PF_INET, 274 .type = SOCK_STREAM, 275 .proto = 0, 276 .iov = iov, 277 .iovcnt = 1, 278 .buf = buf, 279 .buflen = sizeof(buf), 280 .msg = NULL, 281 .flags = 0, 282 .to = (struct sockaddr *)&sin1, 283 .tolen = sizeof(sin1), 284 .retval = -1, 285 .experrno = EFAULT, 286 .setup = setup1, 287 .cleanup = cleanup1, 288 .desc = "invalid msghdr pointer"} 289 , 290 {.domain = PF_UNIX, 291 .type = SOCK_DGRAM, 292 .proto = 0, 293 .iov = iov, 294 .iovcnt = 1, 295 .buf = buf, 296 .buflen = sizeof(buf), 297 .msg = &msgdat, 298 .flags = 0, 299 .to = (struct sockaddr *)&sun1, 300 .tolen = sizeof(sun1), 301 .retval = 0, 302 .experrno = 0, 303 .setup = setup4, 304 .cleanup = cleanup4, 305 .desc = "rights passing"} 306 , 307 {.domain = PF_INET, 308 .type = SOCK_DGRAM, 309 .proto = 0, 310 .iov = iov, 311 .iovcnt = 1, 312 .buf = buf, 313 .buflen = sizeof(buf), 314 .msg = &msgdat, 315 .flags = MSG_OOB, 316 .to = (struct sockaddr *)&sin1, 317 .tolen = sizeof(sin1), 318 .retval = -1, 319 .experrno = EOPNOTSUPP, 320 .setup = setup1, 321 .cleanup = cleanup1, 322 .desc = "invalid flags set"} 323 , 324 {.domain = PF_UNIX, 325 .type = SOCK_DGRAM, 326 .proto = 0, 327 .iov = iov, 328 .iovcnt = 1, 329 .buf = buf, 330 .buflen = sizeof(buf), 331 .msg = &msgdat, 332 .flags = 0, 333 .to = (struct sockaddr *)&sun1, 334 .tolen = sizeof(sun1), 335 .retval = 0, 336 .experrno = EOPNOTSUPP, 337 .setup = setup6, 338 .cleanup = cleanup4, 339 .desc = "invalid cmsg length"} 340 , 341 {.domain = PF_UNIX, 342 .type = SOCK_DGRAM, 343 .proto = 0, 344 .iov = iov, 345 .iovcnt = 1, 346 .buf = buf, 347 .buflen = sizeof(buf), 348 .msg = &msgdat, 349 .flags = 0, 350 .to = (struct sockaddr *)&sun1, 351 .tolen = sizeof(sun1), 352 .retval = -1, 353 .experrno = EFAULT, 354 .setup = setup8, 355 .cleanup = cleanup4, 356 .desc = "invalid cmsg pointer"} 357 }; 358 359 int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); 360 361 #ifdef UCLINUX 362 static char *argv0; 363 #endif 364 365 int main(int argc, char *argv[]) 366 { 367 int lc; 368 369 tst_parse_opts(argc, argv, NULL, NULL); 370 371 #ifdef UCLINUX 372 argv0 = argv[0]; 373 maybe_run_child(&do_child, "dd", &sfd, &ufd); 374 #endif 375 376 setup(); 377 378 for (lc = 0; TEST_LOOPING(lc); ++lc) { 379 tst_count = 0; 380 for (testno = 0; testno < TST_TOTAL; ++testno) { 381 tdat[testno].setup(); 382 383 iov[0].iov_base = tdat[testno].buf; 384 iov[0].iov_len = tdat[testno].buflen; 385 if (tdat[testno].type != SOCK_STREAM) { 386 msgdat.msg_name = tdat[testno].to; 387 msgdat.msg_namelen = tdat[testno].tolen; 388 } 389 msgdat.msg_iov = tdat[testno].iov; 390 msgdat.msg_iovlen = tdat[testno].iovcnt; 391 msgdat.msg_control = control; 392 msgdat.msg_controllen = controllen; 393 msgdat.msg_flags = 0; 394 395 TEST(sendmsg(s, tdat[testno].msg, tdat[testno].flags)); 396 397 if (TEST_RETURN > 0) 398 TEST_RETURN = 0; 399 400 if (TEST_RETURN != tdat[testno].retval || 401 (TEST_RETURN < 0 && 402 TEST_ERRNO != tdat[testno].experrno)) { 403 tst_resm(TFAIL, "%s ; returned" 404 " %ld (expected %d), errno %d (expected" 405 " %d)", tdat[testno].desc, 406 TEST_RETURN, tdat[testno].retval, 407 TEST_ERRNO, tdat[testno].experrno); 408 } else { 409 tst_resm(TPASS, "%s successful", 410 tdat[testno].desc); 411 } 412 tdat[testno].cleanup(); 413 } 414 } 415 cleanup(); 416 tst_exit(); 417 } 418 419 static pid_t start_server(struct sockaddr_in *sin0, struct sockaddr_un *sun0) 420 { 421 pid_t pid; 422 socklen_t slen = sizeof(*sin0); 423 424 sin0->sin_family = AF_INET; 425 sin0->sin_port = 0; /* pick random free port */ 426 sin0->sin_addr.s_addr = INADDR_ANY; 427 428 /* set up inet socket */ 429 sfd = socket(PF_INET, SOCK_STREAM, 0); 430 if (sfd < 0) { 431 tst_brkm(TBROK, cleanup, "server socket failed: %s", 432 strerror(errno)); 433 return -1; 434 } 435 if (bind(sfd, (struct sockaddr *)sin0, sizeof(*sin0)) < 0) { 436 tst_brkm(TBROK, cleanup, "server bind failed: %s", 437 strerror(errno)); 438 return -1; 439 } 440 if (listen(sfd, 10) < 0) { 441 tst_brkm(TBROK, cleanup, "server listen failed: %s", 442 strerror(errno)); 443 return -1; 444 } 445 SAFE_GETSOCKNAME(cleanup, sfd, (struct sockaddr *)sin0, &slen); 446 447 /* set up UNIX-domain socket */ 448 ufd = socket(PF_UNIX, SOCK_DGRAM, 0); 449 if (ufd < 0) { 450 tst_brkm(TBROK, cleanup, "server UD socket failed: %s", 451 strerror(errno)); 452 return -1; 453 } 454 if (bind(ufd, (struct sockaddr *)sun0, sizeof(*sun0))) { 455 tst_brkm(TBROK, cleanup, "server UD bind failed: %s", 456 strerror(errno)); 457 return -1; 458 } 459 460 switch ((pid = FORK_OR_VFORK())) { 461 case 0: 462 #ifdef UCLINUX 463 if (self_exec(argv0, "dd", sfd, ufd) < 0) 464 tst_brkm(TBROK, cleanup, "server self_exec failed"); 465 #else 466 do_child(); 467 #endif 468 break; 469 case -1: 470 tst_brkm(TBROK, cleanup, "server fork failed: %s", 471 strerror(errno)); 472 default: 473 close(sfd); 474 close(ufd); 475 return pid; 476 } 477 478 exit(1); 479 } 480 481 static void do_child(void) 482 { 483 struct sockaddr_in fsin; 484 struct sockaddr_un fsun; 485 fd_set afds, rfds; 486 int nfds, cc, fd; 487 488 FD_ZERO(&afds); 489 FD_SET(sfd, &afds); 490 FD_SET(ufd, &afds); 491 492 nfds = MAX(sfd + 1, ufd + 1); 493 494 /* accept connections until killed */ 495 while (1) { 496 socklen_t fromlen; 497 498 memcpy(&rfds, &afds, sizeof(rfds)); 499 500 if (select(nfds, &rfds, NULL, NULL, NULL) < 0) 501 if (errno != EINTR) 502 exit(1); 503 if (FD_ISSET(sfd, &rfds)) { 504 int newfd; 505 506 fromlen = sizeof(fsin); 507 newfd = accept(sfd, (struct sockaddr *)&fsin, &fromlen); 508 if (newfd >= 0) { 509 FD_SET(newfd, &afds); 510 nfds = MAX(nfds, newfd + 1); 511 } 512 } 513 if (FD_ISSET(ufd, &rfds)) { 514 int newfd; 515 516 fromlen = sizeof(fsun); 517 newfd = accept(ufd, (struct sockaddr *)&fsun, &fromlen); 518 if (newfd >= 0) 519 FD_SET(newfd, &afds); 520 } 521 for (fd = 0; fd < nfds; ++fd) { 522 if (fd != sfd && fd != ufd && FD_ISSET(fd, &rfds)) { 523 cc = read(fd, buf, sizeof(buf)); 524 if (cc == 0 || (cc < 0 && errno != EINTR)) { 525 close(fd); 526 FD_CLR(fd, &afds); 527 } 528 } 529 } 530 } 531 } 532 533 static pid_t pid; 534 static char tmpsunpath[1024]; 535 536 static void setup(void) 537 { 538 539 int ret = 0; 540 541 tst_require_root(); 542 tst_sig(FORK, DEF_HANDLER, cleanup); 543 TEST_PAUSE; 544 545 546 tst_tmpdir(); 547 snprintf(tmpsunpath, 1024, "udsock%ld", (long)time(NULL)); 548 sun1.sun_family = AF_UNIX; 549 strcpy(sun1.sun_path, tmpsunpath); 550 551 /* this test will fail or in some cases hang if no eth or lo is 552 * configured, so making sure in setup that at least lo is up 553 */ 554 ret = system("ip link set lo up"); 555 if (WEXITSTATUS(ret) != 0) { 556 ret = system("ifconfig lo up 127.0.0.1"); 557 if (WEXITSTATUS(ret) != 0) { 558 tst_brkm(TBROK, cleanup, 559 "ip/ifconfig failed to bring up loop back device"); 560 } 561 } 562 563 pid = start_server(&sin1, &sun1); 564 565 signal(SIGPIPE, SIG_IGN); 566 } 567 568 static void cleanup(void) 569 { 570 if (pid > 0) 571 kill(pid, SIGKILL); /* kill server, if server exists */ 572 unlink(tmpsunpath); 573 tst_rmdir(); 574 } 575 576 static void setup0(void) 577 { 578 if (tdat[testno].experrno == EBADF) 579 s = 400; /* anything not an open file */ 580 else if ((s = open("/dev/null", O_WRONLY)) == -1) 581 tst_brkm(TBROK, cleanup, "error opening /dev/null - " 582 "errno: %s", strerror(errno)); 583 } 584 585 static void cleanup0(void) 586 { 587 s = -1; 588 } 589 590 static void setup1(void) 591 { 592 s = SAFE_SOCKET(cleanup, tdat[testno].domain, tdat[testno].type, 593 tdat[testno].proto); 594 if (tdat[testno].type == SOCK_STREAM && 595 connect(s, (struct sockaddr *)tdat[testno].to, 596 tdat[testno].tolen) < 0) { 597 tst_brkm(TBROK, cleanup, "connect failed: %s", strerror(errno)); 598 } 599 } 600 601 static void cleanup1(void) 602 { 603 close(s); 604 s = -1; 605 } 606 607 static void setup2(void) 608 { 609 setup1(); /* get a socket in s */ 610 if (shutdown(s, 1) < 0) { 611 tst_brkm(TBROK, cleanup, "socket setup failed connect " 612 "test %d: %s", testno, strerror(errno)); 613 } 614 } 615 616 static void setup3(void) 617 { 618 s = SAFE_SOCKET(cleanup, tdat[testno].domain, tdat[testno].type, 619 tdat[testno].proto); 620 } 621 622 static char tmpfilename[1024]; 623 static int tfd; 624 625 static void setup4(void) 626 { 627 628 setup1(); /* get a socket in s */ 629 630 strcpy(tmpfilename, "sockXXXXXX"); 631 tfd = mkstemp(tmpfilename); 632 if (tfd < 0) { 633 tst_brkm(TBROK, cleanup4, "socket setup failed: %s", 634 strerror(errno)); 635 } 636 control = (struct cmsghdr *)cbuf; 637 memset(cbuf, 0x00, sizeof(cbuf)); 638 control->cmsg_len = sizeof(struct cmsghdr) + 4; 639 control->cmsg_level = SOL_SOCKET; 640 control->cmsg_type = SCM_RIGHTS; 641 *(int *)CMSG_DATA(control) = tfd; 642 controllen = control->cmsg_len; 643 } 644 645 static void cleanup4(void) 646 { 647 cleanup1(); 648 close(tfd); 649 tfd = -1; 650 control = 0; 651 controllen = 0; 652 } 653 654 static void setup5(void) 655 { 656 s = SAFE_SOCKET(cleanup, tdat[testno].domain, tdat[testno].type, 657 tdat[testno].proto); 658 659 SAFE_CONNECT(cleanup, s, (struct sockaddr *)&sin1, sizeof(sin1)); 660 661 /* slight change destination (port) so connect() is to different 662 * 5-tuple than already connected 663 */ 664 sin2 = sin1; 665 sin2.sin_port = tst_get_unused_port(cleanup, AF_INET, SOCK_STREAM); 666 } 667 668 static void setup6(void) 669 { 670 setup4(); 671 /* 672 controllen = control->cmsg_len = sizeof(struct cmsghdr) - 4; 673 */ 674 controllen = control->cmsg_len = 0; 675 } 676 677 static void setup8(void) 678 { 679 setup4(); 680 control = (struct cmsghdr *)-1; 681 } 682