1261081Sasomers/*- 2261081Sasomers * Copyright (c) 2014 Spectra Logic Corporation. All rights reserved. 3261081Sasomers * Redistribution and use in source and binary forms, with or without 4261081Sasomers * modification, are permitted provided that the following conditions 5261081Sasomers * are met: 6261081Sasomers * 1. Redistributions of source code must retain the above copyright 7261081Sasomers * notice, this list of conditions and the following disclaimer. 8261081Sasomers * 2. Redistributions in binary form must reproduce the above copyright 9261081Sasomers * notice, this list of conditions and the following disclaimer in the 10261081Sasomers * documentation and/or other materials provided with the distribution. 11261081Sasomers * 12261081Sasomers * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 13261081Sasomers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14261081Sasomers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15261081Sasomers * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 16261081Sasomers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 17261081Sasomers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 18261081Sasomers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 19261081Sasomers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 20261081Sasomers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 21261081Sasomers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 22261081Sasomers * SUCH DAMAGE. 23261081Sasomers */ 24261081Sasomers 25261081Sasomers#include <sys/cdefs.h> 26261081Sasomers__FBSDID("$FreeBSD: stable/11/tests/sys/kern/unix_seqpacket_test.c 321165 2017-07-18 18:51:34Z ngie $"); 27261081Sasomers 28261081Sasomers#include <errno.h> 29261081Sasomers#include <fcntl.h> 30261081Sasomers#include <pthread.h> 31261081Sasomers#include <signal.h> 32261081Sasomers#include <sys/socket.h> 33261081Sasomers#include <sys/un.h> 34261081Sasomers 35261081Sasomers#include <stdio.h> 36261081Sasomers 37261081Sasomers#include <atf-c.h> 38261081Sasomers 39261081Sasomers/* 40261081Sasomers * Helper functions 41261081Sasomers */ 42261081Sasomers 43261081Sasomers#define MIN(x, y) ((x) < (y) ? (x) : (y)) 44261081Sasomers#define MAX(x, y) ((x) > (y) ? (x) : (y)) 45261081Sasomers 46262894Sasomersstatic void 47261081Sasomersdo_socketpair(int *sv) 48261081Sasomers{ 49261081Sasomers int s; 50292820Sngie 51261081Sasomers s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv); 52261081Sasomers ATF_REQUIRE_EQ(0, s); 53261081Sasomers ATF_REQUIRE(sv[0] >= 0); 54261081Sasomers ATF_REQUIRE(sv[1] >= 0); 55261081Sasomers ATF_REQUIRE(sv[0] != sv[1]); 56261081Sasomers} 57261081Sasomers 58262894Sasomersstatic void 59261081Sasomersdo_socketpair_nonblocking(int *sv) 60261081Sasomers{ 61261081Sasomers int s; 62292820Sngie 63261081Sasomers s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv); 64261081Sasomers ATF_REQUIRE_EQ(0, s); 65261081Sasomers ATF_REQUIRE(sv[0] >= 0); 66261081Sasomers ATF_REQUIRE(sv[1] >= 0); 67261081Sasomers ATF_REQUIRE(sv[0] != sv[1]); 68261081Sasomers ATF_REQUIRE(-1 != fcntl(sv[0], F_SETFL, O_NONBLOCK)); 69261081Sasomers ATF_REQUIRE(-1 != fcntl(sv[1], F_SETFL, O_NONBLOCK)); 70261081Sasomers} 71261081Sasomers 72292820Sngie/* 73261081Sasomers * Returns a pair of sockets made the hard way: bind, listen, connect & accept 74261081Sasomers * @return const char* The path to the socket 75261081Sasomers */ 76262894Sasomersstatic const char* 77261081Sasomersmk_pair_of_sockets(int *sv) 78261081Sasomers{ 79261081Sasomers struct sockaddr_un sun; 80261081Sasomers /* ATF's isolation mechanisms will guarantee uniqueness of this file */ 81261081Sasomers const char *path = "sock"; 82261081Sasomers int s, err, s2, s1; 83261081Sasomers 84261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 85261081Sasomers ATF_REQUIRE(s >= 0); 86261081Sasomers 87261081Sasomers bzero(&sun, sizeof(sun)); 88261081Sasomers sun.sun_family = AF_LOCAL; 89261081Sasomers sun.sun_len = sizeof(sun); 90261081Sasomers strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); 91261081Sasomers err = bind(s, (struct sockaddr *)&sun, sizeof(sun)); 92261081Sasomers err = listen(s, -1); 93261081Sasomers ATF_CHECK_EQ(0, err); 94261081Sasomers 95261081Sasomers /* Create the other socket */ 96261081Sasomers s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 97261081Sasomers ATF_REQUIRE(s2 >= 0); 98261081Sasomers err = connect(s2, (struct sockaddr*)&sun, sizeof(sun)); 99261081Sasomers if (err != 0) { 100261081Sasomers perror("connect"); 101261081Sasomers atf_tc_fail("connect(2) failed"); 102261081Sasomers } 103292820Sngie 104261081Sasomers /* Accept it */ 105261081Sasomers s1 = accept(s, NULL, NULL); 106261081Sasomers if (s1 == -1) { 107261081Sasomers perror("accept"); 108261081Sasomers atf_tc_fail("accept(2) failed"); 109261081Sasomers } 110261081Sasomers 111261081Sasomers sv[0] = s1; 112261081Sasomers sv[1] = s2; 113270228Sasomers 114270228Sasomers close(s); 115270228Sasomers 116261081Sasomers return (path); 117261081Sasomers} 118261081Sasomers 119261081Sasomersstatic volatile sig_atomic_t got_sigpipe = 0; 120261081Sasomersstatic void 121262894Sasomersshutdown_send_sigpipe_handler(int __unused x) 122261081Sasomers{ 123261081Sasomers got_sigpipe = 1; 124261081Sasomers} 125261081Sasomers 126261081Sasomers/* 127261081Sasomers * Parameterized test function bodies 128261081Sasomers */ 129262894Sasomersstatic void 130317831Sbrookstest_eagain(int sndbufsize, int rcvbufsize) 131261081Sasomers{ 132261081Sasomers int i; 133261081Sasomers int sv[2]; 134261081Sasomers const size_t totalsize = (sndbufsize + rcvbufsize) * 2; 135261081Sasomers const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4; 136262894Sasomers const int numpkts = totalsize / pktsize; 137261081Sasomers char sndbuf[pktsize]; 138262894Sasomers ssize_t ssize; 139261081Sasomers 140261081Sasomers /* setup the socket pair */ 141262133Sasomers do_socketpair_nonblocking(sv); 142261081Sasomers /* Setup the buffers */ 143261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, 144261081Sasomers sizeof(sndbufsize))); 145261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, 146261081Sasomers sizeof(rcvbufsize))); 147261081Sasomers 148261081Sasomers bzero(sndbuf, pktsize); 149261081Sasomers /* Send data until we get EAGAIN */ 150262894Sasomers for(i=0; i < numpkts; i++) { 151261081Sasomers ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 152261081Sasomers if (ssize == -1) { 153270228Sasomers if (errno == EAGAIN) { 154270228Sasomers close(sv[0]); 155270228Sasomers close(sv[1]); 156261081Sasomers atf_tc_pass(); 157270228Sasomers } 158261081Sasomers else { 159261081Sasomers perror("send"); 160261081Sasomers atf_tc_fail("send returned < 0 but not EAGAIN"); 161261081Sasomers } 162261081Sasomers } 163261081Sasomers } 164261081Sasomers atf_tc_fail("Never got EAGAIN"); 165261081Sasomers} 166261081Sasomers 167262894Sasomersstatic void 168317831Sbrookstest_sendrecv_symmetric_buffers(int bufsize, int blocking) { 169261081Sasomers int s; 170261081Sasomers int sv[2]; 171262894Sasomers const ssize_t pktsize = bufsize / 2; 172261081Sasomers char sndbuf[pktsize]; 173261081Sasomers char recv_buf[pktsize]; 174261081Sasomers ssize_t ssize, rsize; 175261081Sasomers 176261081Sasomers /* setup the socket pair */ 177261081Sasomers if (blocking) 178261081Sasomers do_socketpair(sv); 179261081Sasomers else 180261081Sasomers do_socketpair_nonblocking(sv); 181261081Sasomers 182261081Sasomers /* Setup the buffers */ 183261081Sasomers s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)); 184261081Sasomers ATF_REQUIRE_EQ(0, s); 185261081Sasomers s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)); 186261081Sasomers ATF_REQUIRE_EQ(0, s); 187261081Sasomers 188261081Sasomers /* Fill the send buffer */ 189261081Sasomers bzero(sndbuf, pktsize); 190261081Sasomers 191261081Sasomers /* send and receive the packet */ 192261081Sasomers ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 193261081Sasomers if (ssize < 0) { 194261081Sasomers perror("send"); 195261081Sasomers atf_tc_fail("send returned < 0"); 196261081Sasomers } 197261081Sasomers ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd", 198261081Sasomers pktsize, ssize); 199261081Sasomers 200261081Sasomers rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL); 201261081Sasomers if (rsize < 0) { 202261081Sasomers perror("recv"); 203261081Sasomers atf_tc_fail("recv returned < 0"); 204261081Sasomers } 205261081Sasomers ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd", 206261081Sasomers pktsize, rsize); 207270228Sasomers close(sv[0]); 208270228Sasomers close(sv[1]); 209261081Sasomers} 210261081Sasomers 211262894Sasomersstatic void 212317831Sbrookstest_pipe_simulator(int sndbufsize, int rcvbufsize) 213261081Sasomers{ 214262894Sasomers int num_sent, num_received; 215261081Sasomers int sv[2]; 216262894Sasomers const ssize_t pktsize = MIN(sndbufsize, rcvbufsize) / 4; 217261081Sasomers int numpkts; 218261081Sasomers char sndbuf[pktsize]; 219261081Sasomers char rcvbuf[pktsize]; 220261081Sasomers char comparebuf[pktsize]; 221261081Sasomers ssize_t ssize, rsize; 222261081Sasomers bool currently_sending = true; 223261081Sasomers 224261081Sasomers /* setup the socket pair */ 225261081Sasomers do_socketpair_nonblocking(sv); 226261081Sasomers /* Setup the buffers */ 227261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, 228261081Sasomers sizeof(sndbufsize))); 229261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, 230261081Sasomers sizeof(rcvbufsize))); 231261081Sasomers 232261081Sasomers /* Send a total amount of data comfortably greater than the buffers */ 233261081Sasomers numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize; 234261081Sasomers for (num_sent=0, num_received=0; 235261081Sasomers num_sent < numpkts || num_received < numpkts; ) { 236261081Sasomers if (currently_sending && num_sent < numpkts) { 237261081Sasomers /* The simulated sending process */ 238261081Sasomers /* fill the buffer */ 239261081Sasomers memset(sndbuf, num_sent, pktsize); 240261081Sasomers ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 241261081Sasomers if (ssize < 0) { 242292820Sngie /* 243261081Sasomers * XXX: This is bug-compatible with the kernel. 244261081Sasomers * The kernel returns EMSGSIZE when it should 245261081Sasomers * return EAGAIN 246261081Sasomers */ 247261081Sasomers if (errno == EAGAIN || errno == EMSGSIZE) 248261081Sasomers currently_sending = false; 249261081Sasomers else { 250261081Sasomers perror("send"); 251261081Sasomers atf_tc_fail("send failed"); 252261081Sasomers } 253261081Sasomers } else { 254261081Sasomers ATF_CHECK_EQ_MSG(pktsize, ssize, 255261081Sasomers "expected %zd=send(...) but got %zd", 256261081Sasomers pktsize, ssize); 257261081Sasomers num_sent++; 258261081Sasomers } 259261081Sasomers } else { 260261081Sasomers /* The simulated receiving process */ 261261081Sasomers rsize = recv(sv[1], rcvbuf, pktsize, MSG_WAITALL); 262261081Sasomers if (rsize < 0) { 263261081Sasomers if (errno == EAGAIN) { 264261081Sasomers currently_sending = true; 265261081Sasomers ATF_REQUIRE_MSG(num_sent < numpkts, 266261081Sasomers "Packets were lost!"); 267261081Sasomers } 268261081Sasomers else { 269261081Sasomers perror("recv"); 270261081Sasomers atf_tc_fail("recv failed"); 271261081Sasomers } 272261081Sasomers } else { 273261081Sasomers ATF_CHECK_EQ_MSG(pktsize, rsize, 274261081Sasomers "expected %zd=recv(...) but got %zd", 275261081Sasomers pktsize, rsize); 276261081Sasomers memset(comparebuf, num_received, pktsize); 277261081Sasomers ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf, 278292820Sngie pktsize), 279261081Sasomers "Received data miscompare"); 280261081Sasomers num_received++; 281261081Sasomers } 282261081Sasomers } 283261081Sasomers } 284270228Sasomers close(sv[0]); 285270228Sasomers close(sv[1]); 286261081Sasomers} 287261081Sasomers 288261081Sasomerstypedef struct { 289261081Sasomers ssize_t pktsize; 290261081Sasomers int numpkts; 291261081Sasomers int so; 292261081Sasomers} test_pipe_thread_data_t; 293261081Sasomers 294261081Sasomersstatic void* 295261081Sasomerstest_pipe_writer(void* args) 296261081Sasomers{ 297261081Sasomers test_pipe_thread_data_t* td = args; 298261081Sasomers char sndbuf[td->pktsize]; 299261081Sasomers ssize_t ssize; 300261081Sasomers int i; 301261081Sasomers 302261081Sasomers for(i=0; i < td->numpkts; i++) { 303261081Sasomers memset(sndbuf, i, td->pktsize); 304261081Sasomers ssize = send(td->so, sndbuf, td->pktsize, MSG_EOR); 305261081Sasomers if (ssize < 0) { 306261081Sasomers perror("send"); 307261081Sasomers atf_tc_fail("send returned < 0"); 308261081Sasomers } 309261081Sasomers ATF_CHECK_EQ_MSG(td->pktsize, ssize, 310261081Sasomers "expected %zd=send(...) but got %zd", 311261081Sasomers td->pktsize, ssize); 312261081Sasomers } 313261081Sasomers return (0); 314261081Sasomers} 315261081Sasomers 316261081Sasomersstatic void* 317261081Sasomerstest_pipe_reader(void* args) 318261081Sasomers{ 319261081Sasomers test_pipe_thread_data_t* td = args; 320261081Sasomers char rcvbuf[td->pktsize]; 321261081Sasomers char comparebuf[td->pktsize]; 322261081Sasomers ssize_t rsize; 323261081Sasomers int i, d; 324261081Sasomers 325261081Sasomers for(i=0; i < td->numpkts; i++) { 326261081Sasomers memset(comparebuf, i, td->pktsize); 327261081Sasomers rsize = recv(td->so, rcvbuf, td->pktsize, MSG_WAITALL); 328261081Sasomers if (rsize < 0) { 329261081Sasomers perror("recv"); 330261081Sasomers atf_tc_fail("recv returned < 0"); 331261081Sasomers } 332261081Sasomers ATF_CHECK_EQ_MSG(td->pktsize, rsize, 333261081Sasomers "expected %zd=send(...) but got %zd", 334261081Sasomers td->pktsize, rsize); 335261081Sasomers d = memcmp(comparebuf, rcvbuf, td->pktsize); 336292820Sngie ATF_CHECK_EQ_MSG(0, d, 337261081Sasomers "Received data miscompare on packet %d", i); 338261081Sasomers } 339261081Sasomers return (0); 340261081Sasomers} 341261081Sasomers 342261081Sasomers 343262894Sasomersstatic void 344317831Sbrookstest_pipe(int sndbufsize, int rcvbufsize) 345261081Sasomers{ 346261081Sasomers test_pipe_thread_data_t writer_data, reader_data; 347261081Sasomers pthread_t writer, reader; 348261081Sasomers int sv[2]; 349261081Sasomers const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4; 350261081Sasomers int numpkts; 351261081Sasomers 352261081Sasomers /* setup the socket pair */ 353261081Sasomers do_socketpair(sv); 354261081Sasomers /* Setup the buffers */ 355261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, 356261081Sasomers sizeof(sndbufsize))); 357261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, 358261081Sasomers sizeof(rcvbufsize))); 359261081Sasomers 360261081Sasomers /* Send a total amount of data comfortably greater than the buffers */ 361261081Sasomers numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize; 362261081Sasomers 363261081Sasomers /* Start the child threads */ 364261081Sasomers writer_data.pktsize = pktsize; 365261081Sasomers writer_data.numpkts = numpkts; 366261081Sasomers writer_data.so = sv[0]; 367261081Sasomers reader_data.pktsize = pktsize; 368261081Sasomers reader_data.numpkts = numpkts; 369261081Sasomers reader_data.so = sv[1]; 370261081Sasomers ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer, 371261081Sasomers (void*)&writer_data)); 372292820Sngie /* 373262867Sasomers * Give the writer time to start writing, and hopefully block, before 374262867Sasomers * starting the reader. This increases the likelihood of the test case 375262867Sasomers * failing due to PR kern/185812 376262867Sasomers */ 377262867Sasomers usleep(1000); 378261081Sasomers ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader, 379261081Sasomers (void*)&reader_data)); 380261081Sasomers 381261081Sasomers /* Join the children */ 382261081Sasomers ATF_REQUIRE_EQ(0, pthread_join(writer, NULL)); 383261081Sasomers ATF_REQUIRE_EQ(0, pthread_join(reader, NULL)); 384270228Sasomers close(sv[0]); 385270228Sasomers close(sv[1]); 386261081Sasomers} 387261081Sasomers 388261081Sasomers 389261081Sasomers/* 390261081Sasomers * Test Cases 391261081Sasomers */ 392261081Sasomers 393261081Sasomers/* Create a SEQPACKET socket */ 394261081SasomersATF_TC_WITHOUT_HEAD(create_socket); 395261081SasomersATF_TC_BODY(create_socket, tc) 396261081Sasomers{ 397261081Sasomers int s; 398261081Sasomers 399261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 400271397Sasomers ATF_REQUIRE(s >= 0); 401270228Sasomers close(s); 402261081Sasomers} 403261081Sasomers 404261081Sasomers/* Create SEQPACKET sockets using socketpair(2) */ 405261081SasomersATF_TC_WITHOUT_HEAD(create_socketpair); 406261081SasomersATF_TC_BODY(create_socketpair, tc) 407261081Sasomers{ 408261081Sasomers int sv[2]; 409261081Sasomers int s; 410261081Sasomers 411261081Sasomers s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv); 412261081Sasomers ATF_CHECK_EQ(0, s); 413261081Sasomers ATF_CHECK(sv[0] >= 0); 414261081Sasomers ATF_CHECK(sv[1] >= 0); 415261081Sasomers ATF_CHECK(sv[0] != sv[1]); 416270228Sasomers close(sv[0]); 417270228Sasomers close(sv[1]); 418261081Sasomers} 419261081Sasomers 420261081Sasomers/* Call listen(2) without first calling bind(2). It should fail */ 421261081SasomersATF_TC_WITHOUT_HEAD(listen_unbound); 422261081SasomersATF_TC_BODY(listen_unbound, tc) 423261081Sasomers{ 424261081Sasomers int s, r; 425261081Sasomers 426261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 427261081Sasomers ATF_REQUIRE(s > 0); 428261081Sasomers r = listen(s, -1); 429261081Sasomers /* expect listen to fail since we haven't called bind(2) */ 430261081Sasomers ATF_CHECK(r != 0); 431270228Sasomers close(s); 432261081Sasomers} 433261081Sasomers 434261081Sasomers/* Bind the socket to a file */ 435261081SasomersATF_TC_WITHOUT_HEAD(bind); 436261081SasomersATF_TC_BODY(bind, tc) 437261081Sasomers{ 438261081Sasomers struct sockaddr_un sun; 439261081Sasomers /* ATF's isolation mechanisms will guarantee uniqueness of this file */ 440261081Sasomers const char *path = "sock"; 441261081Sasomers int s, r; 442261081Sasomers 443261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 444261081Sasomers ATF_REQUIRE(s >= 0); 445261081Sasomers 446261081Sasomers bzero(&sun, sizeof(sun)); 447261081Sasomers sun.sun_family = AF_LOCAL; 448261081Sasomers sun.sun_len = sizeof(sun); 449261081Sasomers strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); 450261081Sasomers r = bind(s, (struct sockaddr *)&sun, sizeof(sun)); 451261081Sasomers ATF_CHECK_EQ(0, r); 452270228Sasomers close(s); 453261081Sasomers} 454261081Sasomers 455261081Sasomers/* listen(2) a socket that is already bound(2) should succeed */ 456261081SasomersATF_TC_WITHOUT_HEAD(listen_bound); 457261081SasomersATF_TC_BODY(listen_bound, tc) 458261081Sasomers{ 459261081Sasomers struct sockaddr_un sun; 460261081Sasomers /* ATF's isolation mechanisms will guarantee uniqueness of this file */ 461261081Sasomers const char *path = "sock"; 462261081Sasomers int s, r, l; 463261081Sasomers 464261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 465261081Sasomers ATF_REQUIRE(s >= 0); 466261081Sasomers 467261081Sasomers bzero(&sun, sizeof(sun)); 468261081Sasomers sun.sun_family = AF_LOCAL; 469261081Sasomers sun.sun_len = sizeof(sun); 470261081Sasomers strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); 471261081Sasomers r = bind(s, (struct sockaddr *)&sun, sizeof(sun)); 472261081Sasomers l = listen(s, -1); 473261081Sasomers ATF_CHECK_EQ(0, r); 474261081Sasomers ATF_CHECK_EQ(0, l); 475270228Sasomers close(s); 476261081Sasomers} 477261081Sasomers 478261081Sasomers/* connect(2) can make a connection */ 479261081SasomersATF_TC_WITHOUT_HEAD(connect); 480261081SasomersATF_TC_BODY(connect, tc) 481261081Sasomers{ 482261081Sasomers struct sockaddr_un sun; 483261081Sasomers /* ATF's isolation mechanisms will guarantee uniqueness of this file */ 484261081Sasomers const char *path = "sock"; 485261081Sasomers int s, r, err, l, s2; 486261081Sasomers 487261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 488261081Sasomers ATF_REQUIRE(s >= 0); 489261081Sasomers 490261081Sasomers bzero(&sun, sizeof(sun)); 491261081Sasomers sun.sun_family = AF_LOCAL; 492261081Sasomers sun.sun_len = sizeof(sun); 493261081Sasomers strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); 494261081Sasomers r = bind(s, (struct sockaddr *)&sun, sizeof(sun)); 495261081Sasomers l = listen(s, -1); 496261081Sasomers ATF_CHECK_EQ(0, r); 497261081Sasomers ATF_CHECK_EQ(0, l); 498261081Sasomers 499261081Sasomers /* Create the other socket */ 500261081Sasomers s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 501261081Sasomers ATF_REQUIRE(s2 >= 0); 502261081Sasomers err = connect(s2, (struct sockaddr*)&sun, sizeof(sun)); 503261081Sasomers if (err != 0) { 504261081Sasomers perror("connect"); 505261081Sasomers atf_tc_fail("connect(2) failed"); 506261081Sasomers } 507270228Sasomers close(s); 508270228Sasomers close(s2); 509261081Sasomers} 510261081Sasomers 511261081Sasomers/* accept(2) can receive a connection */ 512261081SasomersATF_TC_WITHOUT_HEAD(accept); 513261081SasomersATF_TC_BODY(accept, tc) 514261081Sasomers{ 515261081Sasomers int sv[2]; 516261081Sasomers 517261081Sasomers mk_pair_of_sockets(sv); 518270228Sasomers close(sv[0]); 519270228Sasomers close(sv[1]); 520261081Sasomers} 521261081Sasomers 522261081Sasomers 523261081Sasomers/* Set O_NONBLOCK on the socket */ 524261081SasomersATF_TC_WITHOUT_HEAD(fcntl_nonblock); 525261081SasomersATF_TC_BODY(fcntl_nonblock, tc) 526261081Sasomers{ 527261081Sasomers int s; 528261081Sasomers 529261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 530261081Sasomers ATF_REQUIRE(s >= 0); 531261081Sasomers if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) { 532261081Sasomers perror("fcntl"); 533261081Sasomers atf_tc_fail("fcntl failed"); 534261081Sasomers } 535270228Sasomers close(s); 536261081Sasomers} 537261081Sasomers 538261081Sasomers/* Resize the send and receive buffers */ 539261081SasomersATF_TC_WITHOUT_HEAD(resize_buffers); 540261081SasomersATF_TC_BODY(resize_buffers, tc) 541261081Sasomers{ 542261081Sasomers int s; 543261081Sasomers int sndbuf = 12345; 544261081Sasomers int rcvbuf = 23456; 545261081Sasomers int xs, xr; 546261081Sasomers socklen_t sl = sizeof(xs); 547261081Sasomers 548261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 549261081Sasomers ATF_REQUIRE(s >= 0); 550261081Sasomers 551261081Sasomers printf(" Socket Buffer Sizes\n"); 552261081Sasomers printf(" | SNDBUF | RCVBUF |\n"); 553261081Sasomers ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl)); 554261081Sasomers ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl)); 555261081Sasomers printf("Default | %7d | %7d |\n", xs, xr); 556261081Sasomers 557261081Sasomers if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){ 558261081Sasomers perror("setsockopt"); 559261081Sasomers atf_tc_fail("setsockopt(SO_SNDBUF) failed"); 560261081Sasomers } 561261081Sasomers ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl)); 562261081Sasomers ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl)); 563261081Sasomers printf("After changing SNDBUF | %7d | %7d |\n", xs, xr); 564292820Sngie 565261081Sasomers if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){ 566261081Sasomers perror("setsockopt"); 567261081Sasomers atf_tc_fail("setsockopt(SO_RCVBUF) failed"); 568261081Sasomers } 569261081Sasomers ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl)); 570261081Sasomers ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl)); 571261081Sasomers printf("After changing RCVBUF | %7d | %7d |\n", xs, xr); 572270228Sasomers close(s); 573261081Sasomers} 574261081Sasomers 575261081Sasomers/* 576261081Sasomers * Resize the send and receive buffers of a connected socketpair 577261081Sasomers * Print some useful debugging info too 578261081Sasomers */ 579261081SasomersATF_TC_WITHOUT_HEAD(resize_connected_buffers); 580261081SasomersATF_TC_BODY(resize_connected_buffers, tc) 581261081Sasomers{ 582261081Sasomers int sv[2]; 583261081Sasomers int sndbuf = 12345; 584261081Sasomers int rcvbuf = 23456; 585261081Sasomers int err; 586261081Sasomers int ls, lr, rs, rr; 587261081Sasomers socklen_t sl = sizeof(ls); 588261081Sasomers 589261081Sasomers /* setup the socket pair */ 590261081Sasomers do_socketpair(sv); 591261081Sasomers 592261081Sasomers printf(" Socket Buffer Sizes\n"); 593261081Sasomers printf(" | Left Socket | Right Socket |\n"); 594261081Sasomers printf(" | SNDBUF | RCVBUF | SNDBUF | RCVBUF |\n"); 595261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl)); 596261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl)); 597261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl)); 598261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl)); 599261081Sasomers printf("Default | %7d | %7d | %7d | %7d |\n", 600261081Sasomers ls, lr, rs, rr); 601261081Sasomers 602261081Sasomers /* Update one side's send buffer */ 603261081Sasomers err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)); 604261081Sasomers if (err != 0){ 605261081Sasomers perror("setsockopt"); 606261081Sasomers atf_tc_fail("setsockopt(SO_SNDBUF) failed"); 607261081Sasomers } 608261081Sasomers 609261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl)); 610261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl)); 611261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl)); 612261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl)); 613261081Sasomers printf("After changing Left's SNDBUF | %7d | %7d | %7d | %7d |\n", 614261081Sasomers ls, lr, rs, rr); 615261081Sasomers 616261081Sasomers /* Update the same side's receive buffer */ 617261081Sasomers err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); 618261081Sasomers if (err != 0){ 619261081Sasomers perror("setsockopt"); 620261081Sasomers atf_tc_fail("setsockopt(SO_RCVBUF) failed"); 621261081Sasomers } 622261081Sasomers 623261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl)); 624261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl)); 625261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl)); 626261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl)); 627261081Sasomers printf("After changing Left's RCVBUF | %7d | %7d | %7d | %7d |\n", 628261081Sasomers ls, lr, rs, rr); 629270228Sasomers close(sv[0]); 630270228Sasomers close(sv[1]); 631261081Sasomers} 632261081Sasomers 633261081Sasomers 634261081Sasomers/* send(2) and recv(2) a single short record */ 635261081SasomersATF_TC_WITHOUT_HEAD(send_recv); 636261081SasomersATF_TC_BODY(send_recv, tc) 637261081Sasomers{ 638261081Sasomers int sv[2]; 639261081Sasomers const int bufsize = 64; 640261081Sasomers const char *data = "data"; 641261081Sasomers char recv_buf[bufsize]; 642262894Sasomers ssize_t datalen; 643261081Sasomers ssize_t ssize, rsize; 644261081Sasomers 645261081Sasomers /* setup the socket pair */ 646261081Sasomers do_socketpair(sv); 647261081Sasomers 648261081Sasomers /* send and receive a small packet */ 649261081Sasomers datalen = strlen(data) + 1; /* +1 for the null */ 650261081Sasomers ssize = send(sv[0], data, datalen, MSG_EOR); 651261081Sasomers if (ssize < 0) { 652261081Sasomers perror("send"); 653261081Sasomers atf_tc_fail("send returned < 0"); 654261081Sasomers } 655261081Sasomers ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd", 656261081Sasomers datalen, ssize); 657261081Sasomers 658261081Sasomers rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL); 659261081Sasomers ATF_CHECK_EQ(datalen, rsize); 660270228Sasomers close(sv[0]); 661270228Sasomers close(sv[1]); 662261081Sasomers} 663261081Sasomers 664261081Sasomers/* sendto(2) and recvfrom(2) a single short record 665261081Sasomers * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 666261081Sasomers * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket 667261081Sasomers * 668261081Sasomers * According to the same spec, not all protocols are required to provide the 669261081Sasomers * source addres in recvfrom(2). 670261081Sasomers */ 671261081SasomersATF_TC_WITHOUT_HEAD(sendto_recvfrom); 672261081SasomersATF_TC_BODY(sendto_recvfrom, tc) 673261081Sasomers{ 674292821Sngie#ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS 675261081Sasomers const char* path; 676292821Sngie#endif 677261081Sasomers struct sockaddr_storage from; 678261081Sasomers int sv[2]; 679261081Sasomers const int bufsize = 64; 680261081Sasomers const char *data = "data"; 681261081Sasomers char recv_buf[bufsize]; 682262894Sasomers ssize_t datalen; 683261081Sasomers ssize_t ssize, rsize; 684261081Sasomers socklen_t fromlen; 685261081Sasomers 686261081Sasomers /* setup the socket pair */ 687292821Sngie#ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS 688292821Sngie path = 689292821Sngie#endif 690292821Sngie mk_pair_of_sockets(sv); 691261081Sasomers 692261081Sasomers /* send and receive a small packet */ 693261081Sasomers datalen = strlen(data) + 1; /* +1 for the null */ 694261081Sasomers ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0); 695261081Sasomers if (ssize < 0) { 696261081Sasomers perror("send"); 697261081Sasomers atf_tc_fail("send returned < 0"); 698261081Sasomers } 699261081Sasomers ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd", 700261081Sasomers datalen, ssize); 701261081Sasomers 702261081Sasomers fromlen = sizeof(from); 703261081Sasomers rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL, 704261081Sasomers (struct sockaddr*)&from, &fromlen); 705261081Sasomers if (ssize < 0) { 706261081Sasomers perror("recvfrom"); 707261081Sasomers atf_tc_fail("recvfrom returned < 0"); 708261081Sasomers } 709261081Sasomers ATF_CHECK_EQ(datalen, rsize); 710261081Sasomers 711292821Sngie#ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS 712292820Sngie /* 713261081Sasomers * FreeBSD does not currently provide the source address for SEQ_PACKET 714261081Sasomers * AF_UNIX sockets, and POSIX does not require it, so these two checks 715261081Sasomers * are disabled. If FreeBSD gains that feature in the future, then 716261081Sasomers * these checks may be reenabled 717261081Sasomers */ 718292821Sngie ATF_CHECK_EQ(PF_LOCAL, from.ss_family); 719292821Sngie ATF_CHECK_STREQ(path, ((struct sockaddr_un*)&from)->sun_path); 720292821Sngie#endif 721270228Sasomers close(sv[0]); 722270228Sasomers close(sv[1]); 723261081Sasomers} 724261081Sasomers 725292820Sngie/* 726261081Sasomers * send(2) and recv(2) a single short record with sockets created the 727261081Sasomers * traditional way, involving bind, listen, connect, and accept 728261081Sasomers */ 729261081SasomersATF_TC_WITHOUT_HEAD(send_recv_with_connect); 730261081SasomersATF_TC_BODY(send_recv_with_connect, tc) 731261081Sasomers{ 732261081Sasomers int sv[2]; 733261081Sasomers const int bufsize = 64; 734261081Sasomers const char *data = "data"; 735261081Sasomers char recv_buf[bufsize]; 736262894Sasomers ssize_t datalen; 737261081Sasomers ssize_t ssize, rsize; 738261081Sasomers 739261081Sasomers mk_pair_of_sockets(sv); 740261081Sasomers 741261081Sasomers /* send and receive a small packet */ 742261081Sasomers datalen = strlen(data) + 1; /* +1 for the null */ 743261081Sasomers ssize = send(sv[0], data, datalen, MSG_EOR); 744261081Sasomers if (ssize < 0) { 745261081Sasomers perror("send"); 746261081Sasomers atf_tc_fail("send returned < 0"); 747261081Sasomers } 748261081Sasomers ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd", 749261081Sasomers datalen, ssize); 750261081Sasomers 751261081Sasomers rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL); 752261081Sasomers ATF_CHECK_EQ(datalen, rsize); 753270228Sasomers close(sv[0]); 754270228Sasomers close(sv[1]); 755261081Sasomers} 756261081Sasomers 757261081Sasomers/* send(2) should fail on a shutdown socket */ 758261081SasomersATF_TC_WITHOUT_HEAD(shutdown_send); 759261081SasomersATF_TC_BODY(shutdown_send, tc) 760261081Sasomers{ 761286011Spluknet struct sockaddr_un sun; 762286011Spluknet /* ATF's isolation mechanisms will guarantee uniqueness of this file */ 763286011Spluknet const char *path = "sock"; 764286011Spluknet const char *data = "data"; 765321165Sngie ssize_t datalen, ssize; 766286011Spluknet int s, err, s2; 767261081Sasomers 768261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 769270228Sasomers ATF_REQUIRE(s >= 0); 770286011Spluknet 771286011Spluknet bzero(&sun, sizeof(sun)); 772286011Spluknet sun.sun_family = AF_LOCAL; 773286011Spluknet sun.sun_len = sizeof(sun); 774286011Spluknet strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); 775286011Spluknet err = bind(s, (struct sockaddr *)&sun, sizeof(sun)); 776286011Spluknet err = listen(s, -1); 777286011Spluknet ATF_CHECK_EQ(0, err); 778286011Spluknet 779286011Spluknet /* Create the other socket */ 780286011Spluknet s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 781286011Spluknet ATF_REQUIRE(s2 >= 0); 782286011Spluknet err = connect(s2, (struct sockaddr*)&sun, sizeof(sun)); 783286011Spluknet if (err != 0) { 784286011Spluknet perror("connect"); 785286011Spluknet atf_tc_fail("connect(2) failed"); 786286011Spluknet } 787286011Spluknet 788286011Spluknet ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR)); 789321165Sngie datalen = strlen(data) + 1; /* +1 for the null */ 790261081Sasomers /* USE MSG_NOSIGNAL so we don't get SIGPIPE */ 791321165Sngie ssize = send(s2, data, datalen, MSG_EOR | MSG_NOSIGNAL); 792261081Sasomers ATF_CHECK_EQ(EPIPE, errno); 793261081Sasomers ATF_CHECK_EQ(-1, ssize); 794270228Sasomers close(s); 795286011Spluknet close(s2); 796261081Sasomers} 797261081Sasomers 798261081Sasomers/* send(2) should cause SIGPIPE on a shutdown socket */ 799261081SasomersATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe); 800261081SasomersATF_TC_BODY(shutdown_send_sigpipe, tc) 801261081Sasomers{ 802286011Spluknet struct sockaddr_un sun; 803286011Spluknet /* ATF's isolation mechanisms will guarantee uniqueness of this file */ 804286011Spluknet const char *path = "sock"; 805286011Spluknet const char *data = "data"; 806321165Sngie ssize_t datalen; 807286011Spluknet int s, err, s2; 808261081Sasomers 809261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 810270228Sasomers ATF_REQUIRE(s >= 0); 811286011Spluknet 812286011Spluknet bzero(&sun, sizeof(sun)); 813286011Spluknet sun.sun_family = AF_LOCAL; 814286011Spluknet sun.sun_len = sizeof(sun); 815286011Spluknet strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); 816286011Spluknet err = bind(s, (struct sockaddr *)&sun, sizeof(sun)); 817286011Spluknet err = listen(s, -1); 818286011Spluknet ATF_CHECK_EQ(0, err); 819286011Spluknet 820286011Spluknet /* Create the other socket */ 821286011Spluknet s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 822286011Spluknet ATF_REQUIRE(s2 >= 0); 823286011Spluknet err = connect(s2, (struct sockaddr*)&sun, sizeof(sun)); 824286011Spluknet if (err != 0) { 825286011Spluknet perror("connect"); 826286011Spluknet atf_tc_fail("connect(2) failed"); 827286011Spluknet } 828286011Spluknet 829286011Spluknet ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR)); 830261081Sasomers ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler)); 831321165Sngie datalen = strlen(data) + 1; /* +1 for the null */ 832321165Sngie (void)send(s2, data, sizeof(*data), MSG_EOR); 833261081Sasomers ATF_CHECK_EQ(1, got_sigpipe); 834270228Sasomers close(s); 835286011Spluknet close(s2); 836261081Sasomers} 837261081Sasomers 838261081Sasomers/* nonblocking send(2) and recv(2) a single short record */ 839261081SasomersATF_TC_WITHOUT_HEAD(send_recv_nonblocking); 840261081SasomersATF_TC_BODY(send_recv_nonblocking, tc) 841261081Sasomers{ 842261081Sasomers int sv[2]; 843261081Sasomers const int bufsize = 64; 844261081Sasomers const char *data = "data"; 845261081Sasomers char recv_buf[bufsize]; 846262894Sasomers ssize_t datalen; 847261081Sasomers ssize_t ssize, rsize; 848261081Sasomers 849261081Sasomers /* setup the socket pair */ 850261081Sasomers do_socketpair_nonblocking(sv); 851261081Sasomers 852261081Sasomers /* Verify that there is nothing to receive */ 853261081Sasomers rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL); 854261081Sasomers ATF_CHECK_EQ(EAGAIN, errno); 855261081Sasomers ATF_CHECK_EQ(-1, rsize); 856261081Sasomers 857261081Sasomers /* send and receive a small packet */ 858261081Sasomers datalen = strlen(data) + 1; /* +1 for the null */ 859261081Sasomers ssize = send(sv[0], data, datalen, MSG_EOR); 860261081Sasomers if (ssize < 0) { 861261081Sasomers perror("send"); 862261081Sasomers atf_tc_fail("send returned < 0"); 863261081Sasomers } 864261081Sasomers ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd", 865261081Sasomers datalen, ssize); 866261081Sasomers 867261081Sasomers rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL); 868261081Sasomers ATF_CHECK_EQ(datalen, rsize); 869270228Sasomers close(sv[0]); 870270228Sasomers close(sv[1]); 871261081Sasomers} 872261081Sasomers 873292820Sngie/* 874261081Sasomers * We should get EMSGSIZE if we try to send a message larger than the socket 875261081Sasomers * buffer, with blocking sockets 876261081Sasomers */ 877261081SasomersATF_TC_WITHOUT_HEAD(emsgsize); 878261081SasomersATF_TC_BODY(emsgsize, tc) 879261081Sasomers{ 880261081Sasomers int sv[2]; 881317831Sbrooks const int sndbufsize = 8192; 882317831Sbrooks const int rcvbufsize = 8192; 883261081Sasomers const size_t pktsize = (sndbufsize + rcvbufsize) * 2; 884261081Sasomers char sndbuf[pktsize]; 885262894Sasomers ssize_t ssize; 886261081Sasomers 887261081Sasomers /* setup the socket pair */ 888261081Sasomers do_socketpair(sv); 889261081Sasomers /* Setup the buffers */ 890261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, 891261081Sasomers sizeof(sndbufsize))); 892261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, 893261081Sasomers sizeof(rcvbufsize))); 894261081Sasomers 895261081Sasomers ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 896261081Sasomers ATF_CHECK_EQ(EMSGSIZE, errno); 897261081Sasomers ATF_CHECK_EQ(-1, ssize); 898270228Sasomers close(sv[0]); 899270228Sasomers close(sv[1]); 900261081Sasomers} 901261081Sasomers 902292820Sngie/* 903261081Sasomers * We should get EMSGSIZE if we try to send a message larger than the socket 904261081Sasomers * buffer, with nonblocking sockets 905261081Sasomers */ 906261081SasomersATF_TC_WITHOUT_HEAD(emsgsize_nonblocking); 907261081SasomersATF_TC_BODY(emsgsize_nonblocking, tc) 908261081Sasomers{ 909261081Sasomers int sv[2]; 910317831Sbrooks const int sndbufsize = 8192; 911317831Sbrooks const int rcvbufsize = 8192; 912261081Sasomers const size_t pktsize = (sndbufsize + rcvbufsize) * 2; 913261081Sasomers char sndbuf[pktsize]; 914262894Sasomers ssize_t ssize; 915261081Sasomers 916261081Sasomers /* setup the socket pair */ 917261081Sasomers do_socketpair_nonblocking(sv); 918261081Sasomers /* Setup the buffers */ 919261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, 920261081Sasomers sizeof(sndbufsize))); 921261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, 922261081Sasomers sizeof(rcvbufsize))); 923261081Sasomers 924261081Sasomers ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 925261081Sasomers ATF_CHECK_EQ(EMSGSIZE, errno); 926261081Sasomers ATF_CHECK_EQ(-1, ssize); 927270228Sasomers close(sv[0]); 928270228Sasomers close(sv[1]); 929261081Sasomers} 930261081Sasomers 931261081Sasomers 932292820Sngie/* 933261081Sasomers * We should get EAGAIN if we try to send a message larger than the socket 934261081Sasomers * buffer, with nonblocking sockets. Test with several different sockbuf sizes 935261081Sasomers */ 936261081SasomersATF_TC_WITHOUT_HEAD(eagain_8k_8k); 937261081SasomersATF_TC_BODY(eagain_8k_8k, tc) 938261081Sasomers{ 939261081Sasomers test_eagain(8192, 8192); 940261081Sasomers} 941261081SasomersATF_TC_WITHOUT_HEAD(eagain_8k_128k); 942261081SasomersATF_TC_BODY(eagain_8k_128k, tc) 943261081Sasomers{ 944261081Sasomers test_eagain(8192, 131072); 945261081Sasomers} 946261081SasomersATF_TC_WITHOUT_HEAD(eagain_128k_8k); 947261081SasomersATF_TC_BODY(eagain_128k_8k, tc) 948261081Sasomers{ 949261081Sasomers test_eagain(131072, 8192); 950261081Sasomers} 951261081SasomersATF_TC_WITHOUT_HEAD(eagain_128k_128k); 952261081SasomersATF_TC_BODY(eagain_128k_128k, tc) 953261081Sasomers{ 954261081Sasomers test_eagain(131072, 131072); 955261081Sasomers} 956261081Sasomers 957261081Sasomers 958292820Sngie/* 959261081Sasomers * nonblocking send(2) and recv(2) of several records, which should collectively 960261081Sasomers * fill up the send buffer but not the receive buffer 961261081Sasomers */ 962261081SasomersATF_TC_WITHOUT_HEAD(rcvbuf_oversized); 963261081SasomersATF_TC_BODY(rcvbuf_oversized, tc) 964261081Sasomers{ 965262894Sasomers int i; 966261081Sasomers int sv[2]; 967264133Sjmmv const ssize_t pktsize = 1024; 968317831Sbrooks const int sndbufsize = 8192; 969317831Sbrooks const int rcvbufsize = 131072; 970262894Sasomers const size_t geometric_mean_bufsize = 32768; 971262894Sasomers const int numpkts = geometric_mean_bufsize / pktsize; 972261081Sasomers char sndbuf[pktsize]; 973261081Sasomers char recv_buf[pktsize]; 974261081Sasomers ssize_t ssize, rsize; 975261081Sasomers 976261081Sasomers /* setup the socket pair */ 977261081Sasomers do_socketpair_nonblocking(sv); 978262894Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, 979262894Sasomers sizeof(sndbufsize))); 980262894Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, 981262894Sasomers sizeof(rcvbufsize))); 982261081Sasomers 983292820Sngie /* 984261081Sasomers * Send and receive packets that are collectively greater than the send 985261081Sasomers * buffer, but less than the receive buffer 986261081Sasomers */ 987262894Sasomers for (i=0; i < numpkts; i++) { 988261081Sasomers /* Fill the buffer */ 989261081Sasomers memset(sndbuf, i, pktsize); 990261081Sasomers 991261081Sasomers /* send the packet */ 992261081Sasomers ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 993261081Sasomers if (ssize < 0) { 994261081Sasomers perror("send"); 995261081Sasomers atf_tc_fail("send returned < 0"); 996261081Sasomers } 997261081Sasomers ATF_CHECK_EQ_MSG(pktsize, ssize, 998261081Sasomers "expected %zd=send(...) but got %zd", pktsize, ssize); 999261081Sasomers 1000261081Sasomers /* Receive it */ 1001261081Sasomers 1002261081Sasomers rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL); 1003261081Sasomers if (rsize < 0) { 1004261081Sasomers perror("recv"); 1005261081Sasomers atf_tc_fail("recv returned < 0"); 1006261081Sasomers } 1007261081Sasomers ATF_CHECK_EQ_MSG(pktsize, rsize, 1008261081Sasomers "expected %zd=send(...) but got %zd", pktsize, rsize); 1009261081Sasomers 1010261081Sasomers /* Verify the contents */ 1011292820Sngie ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize), 1012261081Sasomers "Received data miscompare"); 1013261081Sasomers } 1014261081Sasomers 1015261081Sasomers /* Trying to receive again should return EAGAIN */ 1016261081Sasomers rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL); 1017261081Sasomers ATF_CHECK_EQ(EAGAIN, errno); 1018261081Sasomers ATF_CHECK_EQ(-1, rsize); 1019270228Sasomers close(sv[0]); 1020270228Sasomers close(sv[1]); 1021261081Sasomers} 1022261081Sasomers 1023292820Sngie/* 1024261081Sasomers * Simulate the behavior of a blocking pipe. The sender will send until his 1025261081Sasomers * buffer fills up, then we'll simulate a scheduler switch that will allow the 1026261081Sasomers * receiver to read until his buffer empties. Repeat the process until the 1027261081Sasomers * transfer is complete. 1028261081Sasomers * Repeat the test with multiple send and receive buffer sizes 1029261081Sasomers */ 1030261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k); 1031261081SasomersATF_TC_BODY(pipe_simulator_8k_8k, tc) 1032261081Sasomers{ 1033261081Sasomers test_pipe_simulator(8192, 8192); 1034261081Sasomers} 1035261081Sasomers 1036261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k); 1037261081SasomersATF_TC_BODY(pipe_simulator_8k_128k, tc) 1038261081Sasomers{ 1039261081Sasomers test_pipe_simulator(8192, 131072); 1040261081Sasomers} 1041261081Sasomers 1042261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k); 1043261081SasomersATF_TC_BODY(pipe_simulator_128k_8k, tc) 1044261081Sasomers{ 1045261081Sasomers test_pipe_simulator(131072, 8192); 1046261081Sasomers} 1047261081Sasomers 1048261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k); 1049261081SasomersATF_TC_BODY(pipe_simulator_128k_128k, tc) 1050261081Sasomers{ 1051261081Sasomers test_pipe_simulator(131072, 131072); 1052261081Sasomers} 1053261081Sasomers 1054292820Sngie/* 1055261081Sasomers * Test blocking I/O by passing data between two threads. The total amount of 1056261081Sasomers * data will be >> buffer size to force blocking. Repeat the test with multiple 1057261081Sasomers * send and receive buffer sizes 1058261081Sasomers */ 1059261081SasomersATF_TC_WITHOUT_HEAD(pipe_8k_8k); 1060261081SasomersATF_TC_BODY(pipe_8k_8k, tc) 1061261081Sasomers{ 1062261081Sasomers test_pipe(8192, 8192); 1063261081Sasomers} 1064261081Sasomers 1065261081SasomersATF_TC_WITHOUT_HEAD(pipe_8k_128k); 1066261081SasomersATF_TC_BODY(pipe_8k_128k, tc) 1067261081Sasomers{ 1068261081Sasomers test_pipe(8192, 131072); 1069261081Sasomers} 1070261081Sasomers 1071261081SasomersATF_TC_WITHOUT_HEAD(pipe_128k_8k); 1072261081SasomersATF_TC_BODY(pipe_128k_8k, tc) 1073261081Sasomers{ 1074261081Sasomers test_pipe(131072, 8192); 1075261081Sasomers} 1076261081Sasomers 1077261081SasomersATF_TC_WITHOUT_HEAD(pipe_128k_128k); 1078261081SasomersATF_TC_BODY(pipe_128k_128k, tc) 1079261081Sasomers{ 1080261081Sasomers test_pipe(131072, 131072); 1081261081Sasomers} 1082261081Sasomers 1083261081Sasomers 1084261081Sasomers/* 1085261081Sasomers * Test single-packet I/O with and without blocking, with symmetric buffers of 1086261081Sasomers * various sizes 1087261081Sasomers */ 1088261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_8k); 1089261081SasomersATF_TC_BODY(sendrecv_8k, tc) 1090261081Sasomers{ 1091261081Sasomers test_sendrecv_symmetric_buffers(8 * 1024, true); 1092261081Sasomers} 1093261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_16k); 1094261081SasomersATF_TC_BODY(sendrecv_16k, tc) 1095261081Sasomers{ 1096261081Sasomers test_sendrecv_symmetric_buffers(16 * 1024, true); 1097261081Sasomers} 1098261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_32k); 1099261081SasomersATF_TC_BODY(sendrecv_32k, tc) 1100261081Sasomers{ 1101261081Sasomers test_sendrecv_symmetric_buffers(32 * 1024, true); 1102261081Sasomers} 1103261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_64k); 1104261081SasomersATF_TC_BODY(sendrecv_64k, tc) 1105261081Sasomers{ 1106261081Sasomers test_sendrecv_symmetric_buffers(64 * 1024, true); 1107261081Sasomers} 1108261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_128k); 1109261081SasomersATF_TC_BODY(sendrecv_128k, tc) 1110261081Sasomers{ 1111261081Sasomers test_sendrecv_symmetric_buffers(128 * 1024, true); 1112261081Sasomers} 1113261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking); 1114261081SasomersATF_TC_BODY(sendrecv_8k_nonblocking, tc) 1115261081Sasomers{ 1116261081Sasomers test_sendrecv_symmetric_buffers(8 * 1024, false); 1117261081Sasomers} 1118261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking); 1119261081SasomersATF_TC_BODY(sendrecv_16k_nonblocking, tc) 1120261081Sasomers{ 1121261081Sasomers test_sendrecv_symmetric_buffers(16 * 1024, false); 1122261081Sasomers} 1123261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking); 1124261081SasomersATF_TC_BODY(sendrecv_32k_nonblocking, tc) 1125261081Sasomers{ 1126261081Sasomers test_sendrecv_symmetric_buffers(32 * 1024, false); 1127261081Sasomers} 1128261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking); 1129261081SasomersATF_TC_BODY(sendrecv_64k_nonblocking, tc) 1130261081Sasomers{ 1131261081Sasomers test_sendrecv_symmetric_buffers(64 * 1024, false); 1132261081Sasomers} 1133261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking); 1134261081SasomersATF_TC_BODY(sendrecv_128k_nonblocking, tc) 1135261081Sasomers{ 1136261081Sasomers test_sendrecv_symmetric_buffers(128 * 1024, false); 1137261081Sasomers} 1138261081Sasomers 1139261081Sasomers 1140261081Sasomers/* 1141261081Sasomers * Main. 1142261081Sasomers */ 1143261081Sasomers 1144261081SasomersATF_TP_ADD_TCS(tp) 1145261081Sasomers{ 1146261081Sasomers /* Basic creation and connection tests */ 1147261081Sasomers ATF_TP_ADD_TC(tp, create_socket); 1148261081Sasomers ATF_TP_ADD_TC(tp, create_socketpair); 1149261081Sasomers ATF_TP_ADD_TC(tp, listen_unbound); 1150261081Sasomers ATF_TP_ADD_TC(tp, bind); 1151261081Sasomers ATF_TP_ADD_TC(tp, listen_bound); 1152261081Sasomers ATF_TP_ADD_TC(tp, connect); 1153261081Sasomers ATF_TP_ADD_TC(tp, accept); 1154261081Sasomers ATF_TP_ADD_TC(tp, fcntl_nonblock); 1155261081Sasomers ATF_TP_ADD_TC(tp, resize_buffers); 1156261081Sasomers ATF_TP_ADD_TC(tp, resize_connected_buffers); 1157261081Sasomers 1158261081Sasomers /* Unthreaded I/O tests */ 1159261081Sasomers ATF_TP_ADD_TC(tp, send_recv); 1160261081Sasomers ATF_TP_ADD_TC(tp, send_recv_nonblocking); 1161261081Sasomers ATF_TP_ADD_TC(tp, send_recv_with_connect); 1162261081Sasomers ATF_TP_ADD_TC(tp, sendto_recvfrom); 1163261081Sasomers ATF_TP_ADD_TC(tp, shutdown_send); 1164261081Sasomers ATF_TP_ADD_TC(tp, shutdown_send_sigpipe); 1165261081Sasomers ATF_TP_ADD_TC(tp, emsgsize); 1166261081Sasomers ATF_TP_ADD_TC(tp, emsgsize_nonblocking); 1167261081Sasomers ATF_TP_ADD_TC(tp, eagain_8k_8k); 1168261081Sasomers ATF_TP_ADD_TC(tp, eagain_8k_128k); 1169261081Sasomers ATF_TP_ADD_TC(tp, eagain_128k_8k); 1170261081Sasomers ATF_TP_ADD_TC(tp, eagain_128k_128k); 1171261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_8k); 1172261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_16k); 1173261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_32k); 1174261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_64k); 1175261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_128k); 1176261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking); 1177261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking); 1178261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking); 1179261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking); 1180261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking); 1181261081Sasomers ATF_TP_ADD_TC(tp, rcvbuf_oversized); 1182261081Sasomers ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k); 1183261081Sasomers ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k); 1184261081Sasomers ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k); 1185261081Sasomers ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k); 1186261081Sasomers 1187261081Sasomers /* Threaded I/O tests with blocking sockets */ 1188261081Sasomers ATF_TP_ADD_TC(tp, pipe_8k_8k); 1189261081Sasomers ATF_TP_ADD_TC(tp, pipe_8k_128k); 1190261081Sasomers ATF_TP_ADD_TC(tp, pipe_128k_8k); 1191261081Sasomers ATF_TP_ADD_TC(tp, pipe_128k_128k); 1192261081Sasomers 1193261081Sasomers return atf_no_error(); 1194261081Sasomers} 1195