unix_seqpacket_test.c revision 261081
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: head/tests/sys/kern/unix_seqpacket_test.c 261081 2014-01-23 17:26:28Z asomers $"); 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 46261081Sasomersvoid 47261081Sasomersdo_socketpair(int *sv) 48261081Sasomers{ 49261081Sasomers int s; 50261081Sasomers 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 58261081Sasomersvoid 59261081Sasomersdo_socketpair_nonblocking(int *sv) 60261081Sasomers{ 61261081Sasomers int s; 62261081Sasomers 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 72261081Sasomers/* 73261081Sasomers * Returns a pair of sockets made the hard way: bind, listen, connect & accept 74261081Sasomers * @return const char* The path to the socket 75261081Sasomers */ 76261081Sasomersconst 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 ATF_CHECK_EQ(0, err); 95261081Sasomers 96261081Sasomers /* Create the other socket */ 97261081Sasomers s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 98261081Sasomers ATF_REQUIRE(s2 >= 0); 99261081Sasomers err = connect(s2, (struct sockaddr*)&sun, sizeof(sun)); 100261081Sasomers if (err != 0) { 101261081Sasomers perror("connect"); 102261081Sasomers atf_tc_fail("connect(2) failed"); 103261081Sasomers } 104261081Sasomers 105261081Sasomers /* Accept it */ 106261081Sasomers s1 = accept(s, NULL, NULL); 107261081Sasomers if (s1 == -1) { 108261081Sasomers perror("accept"); 109261081Sasomers atf_tc_fail("accept(2) failed"); 110261081Sasomers } 111261081Sasomers 112261081Sasomers sv[0] = s1; 113261081Sasomers sv[1] = s2; 114261081Sasomers return (path); 115261081Sasomers} 116261081Sasomers 117261081Sasomersstatic volatile sig_atomic_t got_sigpipe = 0; 118261081Sasomersstatic void 119261081Sasomersshutdown_send_sigpipe_handler(int x) 120261081Sasomers{ 121261081Sasomers got_sigpipe = 1; 122261081Sasomers} 123261081Sasomers 124261081Sasomers/* 125261081Sasomers * Parameterized test function bodies 126261081Sasomers */ 127261081Sasomersvoid 128261081Sasomerstest_eagain(size_t sndbufsize, size_t rcvbufsize) 129261081Sasomers{ 130261081Sasomers int i; 131261081Sasomers int sv[2]; 132261081Sasomers const size_t totalsize = (sndbufsize + rcvbufsize) * 2; 133261081Sasomers const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4; 134261081Sasomers char sndbuf[pktsize]; 135261081Sasomers char recv_buf[pktsize]; 136261081Sasomers ssize_t ssize, rsize; 137261081Sasomers 138261081Sasomers /* setup the socket pair */ 139261081Sasomers do_socketpair(sv); 140261081Sasomers /* Setup the buffers */ 141261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, 142261081Sasomers sizeof(sndbufsize))); 143261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, 144261081Sasomers sizeof(rcvbufsize))); 145261081Sasomers 146261081Sasomers bzero(sndbuf, pktsize); 147261081Sasomers /* Send data until we get EAGAIN */ 148261081Sasomers for(i=0; i < totalsize / pktsize; i++) { 149261081Sasomers ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 150261081Sasomers if (ssize == -1) { 151261081Sasomers if (errno == EAGAIN) 152261081Sasomers atf_tc_pass(); 153261081Sasomers else { 154261081Sasomers perror("send"); 155261081Sasomers atf_tc_fail("send returned < 0 but not EAGAIN"); 156261081Sasomers } 157261081Sasomers } 158261081Sasomers } 159261081Sasomers atf_tc_fail("Never got EAGAIN"); 160261081Sasomers} 161261081Sasomers 162261081Sasomersvoid 163261081Sasomerstest_sendrecv_symmetric_buffers(size_t bufsize, int blocking) { 164261081Sasomers int s; 165261081Sasomers int sv[2]; 166261081Sasomers const size_t pktsize = bufsize / 2; 167261081Sasomers char sndbuf[pktsize]; 168261081Sasomers char recv_buf[pktsize]; 169261081Sasomers ssize_t ssize, rsize; 170261081Sasomers 171261081Sasomers /* setup the socket pair */ 172261081Sasomers if (blocking) 173261081Sasomers do_socketpair(sv); 174261081Sasomers else 175261081Sasomers do_socketpair_nonblocking(sv); 176261081Sasomers 177261081Sasomers /* Setup the buffers */ 178261081Sasomers s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)); 179261081Sasomers ATF_REQUIRE_EQ(0, s); 180261081Sasomers s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)); 181261081Sasomers ATF_REQUIRE_EQ(0, s); 182261081Sasomers 183261081Sasomers /* Fill the send buffer */ 184261081Sasomers bzero(sndbuf, pktsize); 185261081Sasomers 186261081Sasomers /* send and receive the packet */ 187261081Sasomers ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 188261081Sasomers if (ssize < 0) { 189261081Sasomers perror("send"); 190261081Sasomers atf_tc_fail("send returned < 0"); 191261081Sasomers } 192261081Sasomers ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd", 193261081Sasomers pktsize, ssize); 194261081Sasomers 195261081Sasomers rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL); 196261081Sasomers if (rsize < 0) { 197261081Sasomers perror("recv"); 198261081Sasomers atf_tc_fail("recv returned < 0"); 199261081Sasomers } 200261081Sasomers ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd", 201261081Sasomers pktsize, rsize); 202261081Sasomers} 203261081Sasomers 204261081Sasomersvoid 205261081Sasomerstest_pipe_simulator(size_t sndbufsize, size_t rcvbufsize) 206261081Sasomers{ 207261081Sasomers int s, num_sent, num_received; 208261081Sasomers int sv[2]; 209261081Sasomers const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4; 210261081Sasomers int numpkts; 211261081Sasomers char sndbuf[pktsize]; 212261081Sasomers char rcvbuf[pktsize]; 213261081Sasomers char comparebuf[pktsize]; 214261081Sasomers ssize_t ssize, rsize; 215261081Sasomers bool currently_sending = true; 216261081Sasomers 217261081Sasomers /* setup the socket pair */ 218261081Sasomers do_socketpair_nonblocking(sv); 219261081Sasomers /* Setup the buffers */ 220261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, 221261081Sasomers sizeof(sndbufsize))); 222261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, 223261081Sasomers sizeof(rcvbufsize))); 224261081Sasomers 225261081Sasomers /* Send a total amount of data comfortably greater than the buffers */ 226261081Sasomers numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize; 227261081Sasomers for (num_sent=0, num_received=0; 228261081Sasomers num_sent < numpkts || num_received < numpkts; ) { 229261081Sasomers if (currently_sending && num_sent < numpkts) { 230261081Sasomers /* The simulated sending process */ 231261081Sasomers /* fill the buffer */ 232261081Sasomers memset(sndbuf, num_sent, pktsize); 233261081Sasomers ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 234261081Sasomers if (ssize < 0) { 235261081Sasomers /* 236261081Sasomers * XXX: This is bug-compatible with the kernel. 237261081Sasomers * The kernel returns EMSGSIZE when it should 238261081Sasomers * return EAGAIN 239261081Sasomers */ 240261081Sasomers if (errno == EAGAIN || errno == EMSGSIZE) 241261081Sasomers currently_sending = false; 242261081Sasomers else { 243261081Sasomers perror("send"); 244261081Sasomers atf_tc_fail("send failed"); 245261081Sasomers } 246261081Sasomers } else { 247261081Sasomers ATF_CHECK_EQ_MSG(pktsize, ssize, 248261081Sasomers "expected %zd=send(...) but got %zd", 249261081Sasomers pktsize, ssize); 250261081Sasomers num_sent++; 251261081Sasomers } 252261081Sasomers } else { 253261081Sasomers /* The simulated receiving process */ 254261081Sasomers rsize = recv(sv[1], rcvbuf, pktsize, MSG_WAITALL); 255261081Sasomers if (rsize < 0) { 256261081Sasomers if (errno == EAGAIN) { 257261081Sasomers currently_sending = true; 258261081Sasomers ATF_REQUIRE_MSG(num_sent < numpkts, 259261081Sasomers "Packets were lost!"); 260261081Sasomers } 261261081Sasomers else { 262261081Sasomers perror("recv"); 263261081Sasomers atf_tc_fail("recv failed"); 264261081Sasomers } 265261081Sasomers } else { 266261081Sasomers ATF_CHECK_EQ_MSG(pktsize, rsize, 267261081Sasomers "expected %zd=recv(...) but got %zd", 268261081Sasomers pktsize, rsize); 269261081Sasomers memset(comparebuf, num_received, pktsize); 270261081Sasomers ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf, 271261081Sasomers pktsize), 272261081Sasomers "Received data miscompare"); 273261081Sasomers num_received++; 274261081Sasomers } 275261081Sasomers } 276261081Sasomers } 277261081Sasomers} 278261081Sasomers 279261081Sasomerstypedef struct { 280261081Sasomers ssize_t pktsize; 281261081Sasomers int numpkts; 282261081Sasomers int so; 283261081Sasomers} test_pipe_thread_data_t; 284261081Sasomers 285261081Sasomersstatic void* 286261081Sasomerstest_pipe_writer(void* args) 287261081Sasomers{ 288261081Sasomers test_pipe_thread_data_t* td = args; 289261081Sasomers char sndbuf[td->pktsize]; 290261081Sasomers ssize_t ssize; 291261081Sasomers int i; 292261081Sasomers 293261081Sasomers for(i=0; i < td->numpkts; i++) { 294261081Sasomers memset(sndbuf, i, td->pktsize); 295261081Sasomers ssize = send(td->so, sndbuf, td->pktsize, MSG_EOR); 296261081Sasomers if (ssize < 0) { 297261081Sasomers perror("send"); 298261081Sasomers atf_tc_fail("send returned < 0"); 299261081Sasomers } 300261081Sasomers ATF_CHECK_EQ_MSG(td->pktsize, ssize, 301261081Sasomers "expected %zd=send(...) but got %zd", 302261081Sasomers td->pktsize, ssize); 303261081Sasomers } 304261081Sasomers return (0); 305261081Sasomers} 306261081Sasomers 307261081Sasomersstatic void* 308261081Sasomerstest_pipe_reader(void* args) 309261081Sasomers{ 310261081Sasomers test_pipe_thread_data_t* td = args; 311261081Sasomers char rcvbuf[td->pktsize]; 312261081Sasomers char comparebuf[td->pktsize]; 313261081Sasomers ssize_t rsize; 314261081Sasomers int i, d; 315261081Sasomers 316261081Sasomers for(i=0; i < td->numpkts; i++) { 317261081Sasomers memset(comparebuf, i, td->pktsize); 318261081Sasomers rsize = recv(td->so, rcvbuf, td->pktsize, MSG_WAITALL); 319261081Sasomers if (rsize < 0) { 320261081Sasomers perror("recv"); 321261081Sasomers atf_tc_fail("recv returned < 0"); 322261081Sasomers } 323261081Sasomers ATF_CHECK_EQ_MSG(td->pktsize, rsize, 324261081Sasomers "expected %zd=send(...) but got %zd", 325261081Sasomers td->pktsize, rsize); 326261081Sasomers d = memcmp(comparebuf, rcvbuf, td->pktsize); 327261081Sasomers ATF_CHECK_EQ_MSG(0, d, 328261081Sasomers "Received data miscompare on packet %d", i); 329261081Sasomers } 330261081Sasomers return (0); 331261081Sasomers} 332261081Sasomers 333261081Sasomers 334261081Sasomersvoid 335261081Sasomerstest_pipe(size_t sndbufsize, size_t rcvbufsize) 336261081Sasomers{ 337261081Sasomers test_pipe_thread_data_t writer_data, reader_data; 338261081Sasomers pthread_t writer, reader; 339261081Sasomers int num_sent, num_received; 340261081Sasomers int sv[2]; 341261081Sasomers const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4; 342261081Sasomers int numpkts; 343261081Sasomers 344261081Sasomers /* setup the socket pair */ 345261081Sasomers do_socketpair(sv); 346261081Sasomers /* Setup the buffers */ 347261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, 348261081Sasomers sizeof(sndbufsize))); 349261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, 350261081Sasomers sizeof(rcvbufsize))); 351261081Sasomers 352261081Sasomers /* Send a total amount of data comfortably greater than the buffers */ 353261081Sasomers numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize; 354261081Sasomers 355261081Sasomers /* Start the child threads */ 356261081Sasomers writer_data.pktsize = pktsize; 357261081Sasomers writer_data.numpkts = numpkts; 358261081Sasomers writer_data.so = sv[0]; 359261081Sasomers reader_data.pktsize = pktsize; 360261081Sasomers reader_data.numpkts = numpkts; 361261081Sasomers reader_data.so = sv[1]; 362261081Sasomers ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer, 363261081Sasomers (void*)&writer_data)); 364261081Sasomers ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader, 365261081Sasomers (void*)&reader_data)); 366261081Sasomers 367261081Sasomers /* Join the children */ 368261081Sasomers ATF_REQUIRE_EQ(0, pthread_join(writer, NULL)); 369261081Sasomers ATF_REQUIRE_EQ(0, pthread_join(reader, NULL)); 370261081Sasomers} 371261081Sasomers 372261081Sasomers 373261081Sasomers/* 374261081Sasomers * Test Cases 375261081Sasomers */ 376261081Sasomers 377261081Sasomers/* Create a SEQPACKET socket */ 378261081SasomersATF_TC_WITHOUT_HEAD(create_socket); 379261081SasomersATF_TC_BODY(create_socket, tc) 380261081Sasomers{ 381261081Sasomers int s; 382261081Sasomers 383261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 384261081Sasomers ATF_CHECK(s >= 0); 385261081Sasomers} 386261081Sasomers 387261081Sasomers/* Create SEQPACKET sockets using socketpair(2) */ 388261081SasomersATF_TC_WITHOUT_HEAD(create_socketpair); 389261081SasomersATF_TC_BODY(create_socketpair, tc) 390261081Sasomers{ 391261081Sasomers int sv[2]; 392261081Sasomers int s; 393261081Sasomers 394261081Sasomers s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv); 395261081Sasomers ATF_CHECK_EQ(0, s); 396261081Sasomers ATF_CHECK(sv[0] >= 0); 397261081Sasomers ATF_CHECK(sv[1] >= 0); 398261081Sasomers ATF_CHECK(sv[0] != sv[1]); 399261081Sasomers} 400261081Sasomers 401261081Sasomers/* Call listen(2) without first calling bind(2). It should fail */ 402261081SasomersATF_TC_WITHOUT_HEAD(listen_unbound); 403261081SasomersATF_TC_BODY(listen_unbound, tc) 404261081Sasomers{ 405261081Sasomers int s, r; 406261081Sasomers 407261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 408261081Sasomers ATF_REQUIRE(s > 0); 409261081Sasomers r = listen(s, -1); 410261081Sasomers /* expect listen to fail since we haven't called bind(2) */ 411261081Sasomers ATF_CHECK(r != 0); 412261081Sasomers} 413261081Sasomers 414261081Sasomers/* Bind the socket to a file */ 415261081SasomersATF_TC_WITHOUT_HEAD(bind); 416261081SasomersATF_TC_BODY(bind, tc) 417261081Sasomers{ 418261081Sasomers struct sockaddr_un sun; 419261081Sasomers /* ATF's isolation mechanisms will guarantee uniqueness of this file */ 420261081Sasomers const char *path = "sock"; 421261081Sasomers int s, r; 422261081Sasomers 423261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 424261081Sasomers ATF_REQUIRE(s >= 0); 425261081Sasomers 426261081Sasomers bzero(&sun, sizeof(sun)); 427261081Sasomers sun.sun_family = AF_LOCAL; 428261081Sasomers sun.sun_len = sizeof(sun); 429261081Sasomers strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); 430261081Sasomers r = bind(s, (struct sockaddr *)&sun, sizeof(sun)); 431261081Sasomers ATF_CHECK_EQ(0, r); 432261081Sasomers} 433261081Sasomers 434261081Sasomers/* listen(2) a socket that is already bound(2) should succeed */ 435261081SasomersATF_TC_WITHOUT_HEAD(listen_bound); 436261081SasomersATF_TC_BODY(listen_bound, 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, l; 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 l = listen(s, -1); 452261081Sasomers ATF_CHECK_EQ(0, r); 453261081Sasomers ATF_CHECK_EQ(0, l); 454261081Sasomers} 455261081Sasomers 456261081Sasomers/* connect(2) can make a connection */ 457261081SasomersATF_TC_WITHOUT_HEAD(connect); 458261081SasomersATF_TC_BODY(connect, tc) 459261081Sasomers{ 460261081Sasomers struct sockaddr_un sun; 461261081Sasomers /* ATF's isolation mechanisms will guarantee uniqueness of this file */ 462261081Sasomers const char *path = "sock"; 463261081Sasomers int s, r, err, l, s2; 464261081Sasomers 465261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 466261081Sasomers ATF_REQUIRE(s >= 0); 467261081Sasomers 468261081Sasomers bzero(&sun, sizeof(sun)); 469261081Sasomers sun.sun_family = AF_LOCAL; 470261081Sasomers sun.sun_len = sizeof(sun); 471261081Sasomers strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); 472261081Sasomers r = bind(s, (struct sockaddr *)&sun, sizeof(sun)); 473261081Sasomers l = listen(s, -1); 474261081Sasomers ATF_CHECK_EQ(0, r); 475261081Sasomers ATF_CHECK_EQ(0, l); 476261081Sasomers 477261081Sasomers /* Create the other socket */ 478261081Sasomers s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 479261081Sasomers ATF_REQUIRE(s2 >= 0); 480261081Sasomers err = connect(s2, (struct sockaddr*)&sun, sizeof(sun)); 481261081Sasomers if (err != 0) { 482261081Sasomers perror("connect"); 483261081Sasomers atf_tc_fail("connect(2) failed"); 484261081Sasomers } 485261081Sasomers} 486261081Sasomers 487261081Sasomers/* accept(2) can receive a connection */ 488261081SasomersATF_TC_WITHOUT_HEAD(accept); 489261081SasomersATF_TC_BODY(accept, tc) 490261081Sasomers{ 491261081Sasomers int sv[2]; 492261081Sasomers 493261081Sasomers mk_pair_of_sockets(sv); 494261081Sasomers} 495261081Sasomers 496261081Sasomers 497261081Sasomers/* Set O_NONBLOCK on the socket */ 498261081SasomersATF_TC_WITHOUT_HEAD(fcntl_nonblock); 499261081SasomersATF_TC_BODY(fcntl_nonblock, tc) 500261081Sasomers{ 501261081Sasomers int s; 502261081Sasomers 503261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 504261081Sasomers ATF_REQUIRE(s >= 0); 505261081Sasomers if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) { 506261081Sasomers perror("fcntl"); 507261081Sasomers atf_tc_fail("fcntl failed"); 508261081Sasomers } 509261081Sasomers} 510261081Sasomers 511261081Sasomers/* Resize the send and receive buffers */ 512261081SasomersATF_TC_WITHOUT_HEAD(resize_buffers); 513261081SasomersATF_TC_BODY(resize_buffers, tc) 514261081Sasomers{ 515261081Sasomers int s; 516261081Sasomers int sndbuf = 12345; 517261081Sasomers int rcvbuf = 23456; 518261081Sasomers int xs, xr; 519261081Sasomers socklen_t sl = sizeof(xs); 520261081Sasomers 521261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 522261081Sasomers ATF_REQUIRE(s >= 0); 523261081Sasomers 524261081Sasomers printf(" Socket Buffer Sizes\n"); 525261081Sasomers printf(" | SNDBUF | RCVBUF |\n"); 526261081Sasomers ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl)); 527261081Sasomers ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl)); 528261081Sasomers printf("Default | %7d | %7d |\n", xs, xr); 529261081Sasomers 530261081Sasomers if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){ 531261081Sasomers perror("setsockopt"); 532261081Sasomers atf_tc_fail("setsockopt(SO_SNDBUF) failed"); 533261081Sasomers } 534261081Sasomers ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl)); 535261081Sasomers ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl)); 536261081Sasomers printf("After changing SNDBUF | %7d | %7d |\n", xs, xr); 537261081Sasomers 538261081Sasomers if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){ 539261081Sasomers perror("setsockopt"); 540261081Sasomers atf_tc_fail("setsockopt(SO_RCVBUF) failed"); 541261081Sasomers } 542261081Sasomers ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl)); 543261081Sasomers ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl)); 544261081Sasomers printf("After changing RCVBUF | %7d | %7d |\n", xs, xr); 545261081Sasomers} 546261081Sasomers 547261081Sasomers/* 548261081Sasomers * Resize the send and receive buffers of a connected socketpair 549261081Sasomers * Print some useful debugging info too 550261081Sasomers */ 551261081SasomersATF_TC_WITHOUT_HEAD(resize_connected_buffers); 552261081SasomersATF_TC_BODY(resize_connected_buffers, tc) 553261081Sasomers{ 554261081Sasomers int sv[2]; 555261081Sasomers int sndbuf = 12345; 556261081Sasomers int rcvbuf = 23456; 557261081Sasomers int err; 558261081Sasomers int ls, lr, rs, rr; 559261081Sasomers socklen_t sl = sizeof(ls); 560261081Sasomers 561261081Sasomers /* setup the socket pair */ 562261081Sasomers do_socketpair(sv); 563261081Sasomers 564261081Sasomers printf(" Socket Buffer Sizes\n"); 565261081Sasomers printf(" | Left Socket | Right Socket |\n"); 566261081Sasomers printf(" | SNDBUF | RCVBUF | SNDBUF | RCVBUF |\n"); 567261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl)); 568261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl)); 569261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl)); 570261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl)); 571261081Sasomers printf("Default | %7d | %7d | %7d | %7d |\n", 572261081Sasomers ls, lr, rs, rr); 573261081Sasomers 574261081Sasomers /* Update one side's send buffer */ 575261081Sasomers err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)); 576261081Sasomers if (err != 0){ 577261081Sasomers perror("setsockopt"); 578261081Sasomers atf_tc_fail("setsockopt(SO_SNDBUF) failed"); 579261081Sasomers } 580261081Sasomers 581261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl)); 582261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl)); 583261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl)); 584261081Sasomers ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl)); 585261081Sasomers printf("After changing Left's SNDBUF | %7d | %7d | %7d | %7d |\n", 586261081Sasomers ls, lr, rs, rr); 587261081Sasomers 588261081Sasomers /* Update the same side's receive buffer */ 589261081Sasomers err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); 590261081Sasomers if (err != 0){ 591261081Sasomers perror("setsockopt"); 592261081Sasomers atf_tc_fail("setsockopt(SO_RCVBUF) failed"); 593261081Sasomers } 594261081Sasomers 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("After changing Left's RCVBUF | %7d | %7d | %7d | %7d |\n", 600261081Sasomers ls, lr, rs, rr); 601261081Sasomers} 602261081Sasomers 603261081Sasomers 604261081Sasomers/* send(2) and recv(2) a single short record */ 605261081SasomersATF_TC_WITHOUT_HEAD(send_recv); 606261081SasomersATF_TC_BODY(send_recv, tc) 607261081Sasomers{ 608261081Sasomers int s; 609261081Sasomers int sv[2]; 610261081Sasomers const int bufsize = 64; 611261081Sasomers const char *data = "data"; 612261081Sasomers char recv_buf[bufsize]; 613261081Sasomers size_t datalen; 614261081Sasomers ssize_t ssize, rsize; 615261081Sasomers 616261081Sasomers /* setup the socket pair */ 617261081Sasomers do_socketpair(sv); 618261081Sasomers 619261081Sasomers /* send and receive a small packet */ 620261081Sasomers datalen = strlen(data) + 1; /* +1 for the null */ 621261081Sasomers ssize = send(sv[0], data, datalen, MSG_EOR); 622261081Sasomers if (ssize < 0) { 623261081Sasomers perror("send"); 624261081Sasomers atf_tc_fail("send returned < 0"); 625261081Sasomers } 626261081Sasomers ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd", 627261081Sasomers datalen, ssize); 628261081Sasomers 629261081Sasomers rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL); 630261081Sasomers ATF_CHECK_EQ(datalen, rsize); 631261081Sasomers} 632261081Sasomers 633261081Sasomers/* sendto(2) and recvfrom(2) a single short record 634261081Sasomers * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 635261081Sasomers * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket 636261081Sasomers * 637261081Sasomers * According to the same spec, not all protocols are required to provide the 638261081Sasomers * source addres in recvfrom(2). 639261081Sasomers */ 640261081SasomersATF_TC_WITHOUT_HEAD(sendto_recvfrom); 641261081SasomersATF_TC_BODY(sendto_recvfrom, tc) 642261081Sasomers{ 643261081Sasomers const char* path; 644261081Sasomers struct sockaddr_storage from; 645261081Sasomers int s; 646261081Sasomers int sv[2]; 647261081Sasomers const int bufsize = 64; 648261081Sasomers const char *data = "data"; 649261081Sasomers char recv_buf[bufsize]; 650261081Sasomers size_t datalen; 651261081Sasomers ssize_t ssize, rsize; 652261081Sasomers socklen_t fromlen; 653261081Sasomers 654261081Sasomers /* setup the socket pair */ 655261081Sasomers path = mk_pair_of_sockets(sv); 656261081Sasomers 657261081Sasomers /* send and receive a small packet */ 658261081Sasomers datalen = strlen(data) + 1; /* +1 for the null */ 659261081Sasomers ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0); 660261081Sasomers if (ssize < 0) { 661261081Sasomers perror("send"); 662261081Sasomers atf_tc_fail("send returned < 0"); 663261081Sasomers } 664261081Sasomers ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd", 665261081Sasomers datalen, ssize); 666261081Sasomers 667261081Sasomers fromlen = sizeof(from); 668261081Sasomers rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL, 669261081Sasomers (struct sockaddr*)&from, &fromlen); 670261081Sasomers if (ssize < 0) { 671261081Sasomers perror("recvfrom"); 672261081Sasomers atf_tc_fail("recvfrom returned < 0"); 673261081Sasomers } 674261081Sasomers ATF_CHECK_EQ(datalen, rsize); 675261081Sasomers 676261081Sasomers /* 677261081Sasomers * FreeBSD does not currently provide the source address for SEQ_PACKET 678261081Sasomers * AF_UNIX sockets, and POSIX does not require it, so these two checks 679261081Sasomers * are disabled. If FreeBSD gains that feature in the future, then 680261081Sasomers * these checks may be reenabled 681261081Sasomers */ 682261081Sasomers /* ATF_CHECK_EQ(PF_LOCAL, from.ss_family); */ 683261081Sasomers /* ATF_CHECK_STREQ(path, ((struct sockaddr_un*)&from)->sun_path); */ 684261081Sasomers} 685261081Sasomers 686261081Sasomers/* 687261081Sasomers * send(2) and recv(2) a single short record with sockets created the 688261081Sasomers * traditional way, involving bind, listen, connect, and accept 689261081Sasomers */ 690261081SasomersATF_TC_WITHOUT_HEAD(send_recv_with_connect); 691261081SasomersATF_TC_BODY(send_recv_with_connect, tc) 692261081Sasomers{ 693261081Sasomers const char* path; 694261081Sasomers int sv[2]; 695261081Sasomers const int bufsize = 64; 696261081Sasomers const char *data = "data"; 697261081Sasomers char recv_buf[bufsize]; 698261081Sasomers size_t datalen; 699261081Sasomers ssize_t ssize, rsize; 700261081Sasomers 701261081Sasomers mk_pair_of_sockets(sv); 702261081Sasomers 703261081Sasomers /* send and receive a small packet */ 704261081Sasomers datalen = strlen(data) + 1; /* +1 for the null */ 705261081Sasomers ssize = send(sv[0], data, datalen, MSG_EOR); 706261081Sasomers if (ssize < 0) { 707261081Sasomers perror("send"); 708261081Sasomers atf_tc_fail("send returned < 0"); 709261081Sasomers } 710261081Sasomers ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd", 711261081Sasomers datalen, ssize); 712261081Sasomers 713261081Sasomers rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL); 714261081Sasomers ATF_CHECK_EQ(datalen, rsize); 715261081Sasomers} 716261081Sasomers 717261081Sasomers/* send(2) should fail on a shutdown socket */ 718261081SasomersATF_TC_WITHOUT_HEAD(shutdown_send); 719261081SasomersATF_TC_BODY(shutdown_send, tc) 720261081Sasomers{ 721261081Sasomers int s; 722261081Sasomers const char *data = "data"; 723261081Sasomers ssize_t ssize; 724261081Sasomers 725261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 726261081Sasomers ATF_CHECK(s >= 0); 727261081Sasomers ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR)); 728261081Sasomers /* USE MSG_NOSIGNAL so we don't get SIGPIPE */ 729261081Sasomers ssize = send(s, data, sizeof(data), MSG_EOR | MSG_NOSIGNAL); 730261081Sasomers ATF_CHECK_EQ(EPIPE, errno); 731261081Sasomers ATF_CHECK_EQ(-1, ssize); 732261081Sasomers} 733261081Sasomers 734261081Sasomers/* send(2) should cause SIGPIPE on a shutdown socket */ 735261081SasomersATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe); 736261081SasomersATF_TC_BODY(shutdown_send_sigpipe, tc) 737261081Sasomers{ 738261081Sasomers int s; 739261081Sasomers const char *data = "data"; 740261081Sasomers ssize_t ssize; 741261081Sasomers 742261081Sasomers s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 743261081Sasomers ATF_CHECK(s >= 0); 744261081Sasomers ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR)); 745261081Sasomers ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler)); 746261081Sasomers ssize = send(s, data, sizeof(data), MSG_EOR); 747261081Sasomers ATF_CHECK_EQ(1, got_sigpipe); 748261081Sasomers} 749261081Sasomers 750261081Sasomers/* nonblocking send(2) and recv(2) a single short record */ 751261081SasomersATF_TC_WITHOUT_HEAD(send_recv_nonblocking); 752261081SasomersATF_TC_BODY(send_recv_nonblocking, tc) 753261081Sasomers{ 754261081Sasomers int s; 755261081Sasomers int sv[2]; 756261081Sasomers const int bufsize = 64; 757261081Sasomers const char *data = "data"; 758261081Sasomers char recv_buf[bufsize]; 759261081Sasomers size_t datalen; 760261081Sasomers ssize_t ssize, rsize; 761261081Sasomers 762261081Sasomers /* setup the socket pair */ 763261081Sasomers do_socketpair_nonblocking(sv); 764261081Sasomers 765261081Sasomers /* Verify that there is nothing to receive */ 766261081Sasomers rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL); 767261081Sasomers ATF_CHECK_EQ(EAGAIN, errno); 768261081Sasomers ATF_CHECK_EQ(-1, rsize); 769261081Sasomers 770261081Sasomers /* send and receive a small packet */ 771261081Sasomers datalen = strlen(data) + 1; /* +1 for the null */ 772261081Sasomers ssize = send(sv[0], data, datalen, MSG_EOR); 773261081Sasomers if (ssize < 0) { 774261081Sasomers perror("send"); 775261081Sasomers atf_tc_fail("send returned < 0"); 776261081Sasomers } 777261081Sasomers ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd", 778261081Sasomers datalen, ssize); 779261081Sasomers 780261081Sasomers rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL); 781261081Sasomers ATF_CHECK_EQ(datalen, rsize); 782261081Sasomers} 783261081Sasomers 784261081Sasomers/* 785261081Sasomers * We should get EMSGSIZE if we try to send a message larger than the socket 786261081Sasomers * buffer, with blocking sockets 787261081Sasomers */ 788261081SasomersATF_TC_WITHOUT_HEAD(emsgsize); 789261081SasomersATF_TC_BODY(emsgsize, tc) 790261081Sasomers{ 791261081Sasomers int s; 792261081Sasomers int sv[2]; 793261081Sasomers const size_t sndbufsize = 8192; 794261081Sasomers const size_t rcvbufsize = 8192; 795261081Sasomers const size_t pktsize = (sndbufsize + rcvbufsize) * 2; 796261081Sasomers char sndbuf[pktsize]; 797261081Sasomers char recv_buf[pktsize]; 798261081Sasomers ssize_t ssize, rsize; 799261081Sasomers 800261081Sasomers /* setup the socket pair */ 801261081Sasomers do_socketpair(sv); 802261081Sasomers /* Setup the buffers */ 803261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, 804261081Sasomers sizeof(sndbufsize))); 805261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, 806261081Sasomers sizeof(rcvbufsize))); 807261081Sasomers 808261081Sasomers ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 809261081Sasomers ATF_CHECK_EQ(EMSGSIZE, errno); 810261081Sasomers ATF_CHECK_EQ(-1, ssize); 811261081Sasomers} 812261081Sasomers 813261081Sasomers/* 814261081Sasomers * We should get EMSGSIZE if we try to send a message larger than the socket 815261081Sasomers * buffer, with nonblocking sockets 816261081Sasomers */ 817261081SasomersATF_TC_WITHOUT_HEAD(emsgsize_nonblocking); 818261081SasomersATF_TC_BODY(emsgsize_nonblocking, tc) 819261081Sasomers{ 820261081Sasomers int s; 821261081Sasomers int sv[2]; 822261081Sasomers const size_t sndbufsize = 8192; 823261081Sasomers const size_t rcvbufsize = 8192; 824261081Sasomers const size_t pktsize = (sndbufsize + rcvbufsize) * 2; 825261081Sasomers char sndbuf[pktsize]; 826261081Sasomers char recv_buf[pktsize]; 827261081Sasomers ssize_t ssize, rsize; 828261081Sasomers 829261081Sasomers /* setup the socket pair */ 830261081Sasomers do_socketpair_nonblocking(sv); 831261081Sasomers /* Setup the buffers */ 832261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, 833261081Sasomers sizeof(sndbufsize))); 834261081Sasomers ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, 835261081Sasomers sizeof(rcvbufsize))); 836261081Sasomers 837261081Sasomers ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 838261081Sasomers ATF_CHECK_EQ(EMSGSIZE, errno); 839261081Sasomers ATF_CHECK_EQ(-1, ssize); 840261081Sasomers} 841261081Sasomers 842261081Sasomers 843261081Sasomers/* 844261081Sasomers * We should get EAGAIN if we try to send a message larger than the socket 845261081Sasomers * buffer, with nonblocking sockets. Test with several different sockbuf sizes 846261081Sasomers */ 847261081SasomersATF_TC_WITHOUT_HEAD(eagain_8k_8k); 848261081SasomersATF_TC_BODY(eagain_8k_8k, tc) 849261081Sasomers{ 850261081Sasomers atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN"); 851261081Sasomers test_eagain(8192, 8192); 852261081Sasomers} 853261081SasomersATF_TC_WITHOUT_HEAD(eagain_8k_128k); 854261081SasomersATF_TC_BODY(eagain_8k_128k, tc) 855261081Sasomers{ 856261081Sasomers atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN"); 857261081Sasomers test_eagain(8192, 131072); 858261081Sasomers} 859261081SasomersATF_TC_WITHOUT_HEAD(eagain_128k_8k); 860261081SasomersATF_TC_BODY(eagain_128k_8k, tc) 861261081Sasomers{ 862261081Sasomers atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN"); 863261081Sasomers test_eagain(131072, 8192); 864261081Sasomers} 865261081SasomersATF_TC_WITHOUT_HEAD(eagain_128k_128k); 866261081SasomersATF_TC_BODY(eagain_128k_128k, tc) 867261081Sasomers{ 868261081Sasomers atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN"); 869261081Sasomers test_eagain(131072, 131072); 870261081Sasomers} 871261081Sasomers 872261081Sasomers 873261081Sasomers/* 874261081Sasomers * nonblocking send(2) and recv(2) of several records, which should collectively 875261081Sasomers * fill up the send buffer but not the receive buffer 876261081Sasomers */ 877261081SasomersATF_TC_WITHOUT_HEAD(rcvbuf_oversized); 878261081SasomersATF_TC_BODY(rcvbuf_oversized, tc) 879261081Sasomers{ 880261081Sasomers int s, i, j; 881261081Sasomers int sv[2]; 882261081Sasomers const size_t sndbufsize = 8192; 883261081Sasomers const size_t rcvbufsize = 131072; 884261081Sasomers const size_t geom_mean_bufsize = 32768; 885261081Sasomers const int pktsize = 1024; 886261081Sasomers char sndbuf[pktsize]; 887261081Sasomers char recv_buf[pktsize]; 888261081Sasomers size_t datalen; 889261081Sasomers ssize_t ssize, rsize; 890261081Sasomers 891261081Sasomers /* setup the socket pair */ 892261081Sasomers do_socketpair_nonblocking(sv); 893261081Sasomers 894261081Sasomers /* 895261081Sasomers * Send and receive packets that are collectively greater than the send 896261081Sasomers * buffer, but less than the receive buffer 897261081Sasomers */ 898261081Sasomers for (i=0; i < geom_mean_bufsize / pktsize; i++) { 899261081Sasomers /* Fill the buffer */ 900261081Sasomers memset(sndbuf, i, pktsize); 901261081Sasomers 902261081Sasomers /* send the packet */ 903261081Sasomers ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 904261081Sasomers if (ssize < 0) { 905261081Sasomers perror("send"); 906261081Sasomers atf_tc_fail("send returned < 0"); 907261081Sasomers } 908261081Sasomers ATF_CHECK_EQ_MSG(pktsize, ssize, 909261081Sasomers "expected %zd=send(...) but got %zd", pktsize, ssize); 910261081Sasomers 911261081Sasomers /* Receive it */ 912261081Sasomers 913261081Sasomers rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL); 914261081Sasomers if (rsize < 0) { 915261081Sasomers perror("recv"); 916261081Sasomers atf_tc_fail("recv returned < 0"); 917261081Sasomers } 918261081Sasomers ATF_CHECK_EQ_MSG(pktsize, rsize, 919261081Sasomers "expected %zd=send(...) but got %zd", pktsize, rsize); 920261081Sasomers 921261081Sasomers /* Verify the contents */ 922261081Sasomers ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize), 923261081Sasomers "Received data miscompare"); 924261081Sasomers } 925261081Sasomers 926261081Sasomers /* Trying to receive again should return EAGAIN */ 927261081Sasomers rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL); 928261081Sasomers ATF_CHECK_EQ(EAGAIN, errno); 929261081Sasomers ATF_CHECK_EQ(-1, rsize); 930261081Sasomers} 931261081Sasomers 932261081Sasomers/* 933261081Sasomers * Simulate the behavior of a blocking pipe. The sender will send until his 934261081Sasomers * buffer fills up, then we'll simulate a scheduler switch that will allow the 935261081Sasomers * receiver to read until his buffer empties. Repeat the process until the 936261081Sasomers * transfer is complete. 937261081Sasomers * Repeat the test with multiple send and receive buffer sizes 938261081Sasomers */ 939261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k); 940261081SasomersATF_TC_BODY(pipe_simulator_8k_8k, tc) 941261081Sasomers{ 942261081Sasomers test_pipe_simulator(8192, 8192); 943261081Sasomers} 944261081Sasomers 945261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k); 946261081SasomersATF_TC_BODY(pipe_simulator_8k_128k, tc) 947261081Sasomers{ 948261081Sasomers test_pipe_simulator(8192, 131072); 949261081Sasomers} 950261081Sasomers 951261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k); 952261081SasomersATF_TC_BODY(pipe_simulator_128k_8k, tc) 953261081Sasomers{ 954261081Sasomers atf_tc_expect_fail("PR kern/185812 SOCK_SEQPACKET AF_UNIX sockets with asymmetrical buffers drop packets"); 955261081Sasomers test_pipe_simulator(131072, 8192); 956261081Sasomers} 957261081Sasomers 958261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k); 959261081SasomersATF_TC_BODY(pipe_simulator_128k_128k, tc) 960261081Sasomers{ 961261081Sasomers test_pipe_simulator(131072, 131072); 962261081Sasomers} 963261081Sasomers 964261081Sasomers/* 965261081Sasomers * Test blocking I/O by passing data between two threads. The total amount of 966261081Sasomers * data will be >> buffer size to force blocking. Repeat the test with multiple 967261081Sasomers * send and receive buffer sizes 968261081Sasomers */ 969261081SasomersATF_TC_WITHOUT_HEAD(pipe_8k_8k); 970261081SasomersATF_TC_BODY(pipe_8k_8k, tc) 971261081Sasomers{ 972261081Sasomers atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN"); 973261081Sasomers test_pipe(8192, 8192); 974261081Sasomers} 975261081Sasomers 976261081SasomersATF_TC_WITHOUT_HEAD(pipe_8k_128k); 977261081SasomersATF_TC_BODY(pipe_8k_128k, tc) 978261081Sasomers{ 979261081Sasomers atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN"); 980261081Sasomers test_pipe(8192, 131072); 981261081Sasomers} 982261081Sasomers 983261081SasomersATF_TC_WITHOUT_HEAD(pipe_128k_8k); 984261081SasomersATF_TC_BODY(pipe_128k_8k, tc) 985261081Sasomers{ 986261081Sasomers /* 987261081Sasomers * kern/185812 causes this test case to both fail and timeout. The 988261081Sasomers * atf-c-api(3) doesn't have a way to set such an expectation. 989261081Sasomers * If you use atf_tc_expect_fail, then it will timeout. If you use 990261081Sasomers * atf_tc_expect_timeout, then it will fail. If you use both, then it 991261081Sasomers * will show up as an unexpected pass, which is much worse 992261081Sasomers * 993261081Sasomers * https://code.google.com/p/kyua/issues/detail?id=76 994261081Sasomers */ 995261081Sasomers atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN"); 996261081Sasomers test_pipe(131072, 8192); 997261081Sasomers} 998261081Sasomers 999261081SasomersATF_TC_WITHOUT_HEAD(pipe_128k_128k); 1000261081SasomersATF_TC_BODY(pipe_128k_128k, tc) 1001261081Sasomers{ 1002261081Sasomers atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN"); 1003261081Sasomers test_pipe(131072, 131072); 1004261081Sasomers} 1005261081Sasomers 1006261081Sasomers 1007261081Sasomers/* 1008261081Sasomers * Test single-packet I/O with and without blocking, with symmetric buffers of 1009261081Sasomers * various sizes 1010261081Sasomers */ 1011261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_8k); 1012261081SasomersATF_TC_BODY(sendrecv_8k, tc) 1013261081Sasomers{ 1014261081Sasomers test_sendrecv_symmetric_buffers(8 * 1024, true); 1015261081Sasomers} 1016261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_16k); 1017261081SasomersATF_TC_BODY(sendrecv_16k, tc) 1018261081Sasomers{ 1019261081Sasomers test_sendrecv_symmetric_buffers(16 * 1024, true); 1020261081Sasomers} 1021261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_32k); 1022261081SasomersATF_TC_BODY(sendrecv_32k, tc) 1023261081Sasomers{ 1024261081Sasomers test_sendrecv_symmetric_buffers(32 * 1024, true); 1025261081Sasomers} 1026261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_64k); 1027261081SasomersATF_TC_BODY(sendrecv_64k, tc) 1028261081Sasomers{ 1029261081Sasomers test_sendrecv_symmetric_buffers(64 * 1024, true); 1030261081Sasomers} 1031261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_128k); 1032261081SasomersATF_TC_BODY(sendrecv_128k, tc) 1033261081Sasomers{ 1034261081Sasomers test_sendrecv_symmetric_buffers(128 * 1024, true); 1035261081Sasomers} 1036261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking); 1037261081SasomersATF_TC_BODY(sendrecv_8k_nonblocking, tc) 1038261081Sasomers{ 1039261081Sasomers test_sendrecv_symmetric_buffers(8 * 1024, false); 1040261081Sasomers} 1041261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking); 1042261081SasomersATF_TC_BODY(sendrecv_16k_nonblocking, tc) 1043261081Sasomers{ 1044261081Sasomers test_sendrecv_symmetric_buffers(16 * 1024, false); 1045261081Sasomers} 1046261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking); 1047261081SasomersATF_TC_BODY(sendrecv_32k_nonblocking, tc) 1048261081Sasomers{ 1049261081Sasomers test_sendrecv_symmetric_buffers(32 * 1024, false); 1050261081Sasomers} 1051261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking); 1052261081SasomersATF_TC_BODY(sendrecv_64k_nonblocking, tc) 1053261081Sasomers{ 1054261081Sasomers test_sendrecv_symmetric_buffers(64 * 1024, false); 1055261081Sasomers} 1056261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking); 1057261081SasomersATF_TC_BODY(sendrecv_128k_nonblocking, tc) 1058261081Sasomers{ 1059261081Sasomers test_sendrecv_symmetric_buffers(128 * 1024, false); 1060261081Sasomers} 1061261081Sasomers 1062261081Sasomers 1063261081Sasomers/* 1064261081Sasomers * Main. 1065261081Sasomers */ 1066261081Sasomers 1067261081SasomersATF_TP_ADD_TCS(tp) 1068261081Sasomers{ 1069261081Sasomers /* Basic creation and connection tests */ 1070261081Sasomers ATF_TP_ADD_TC(tp, create_socket); 1071261081Sasomers ATF_TP_ADD_TC(tp, create_socketpair); 1072261081Sasomers ATF_TP_ADD_TC(tp, listen_unbound); 1073261081Sasomers ATF_TP_ADD_TC(tp, bind); 1074261081Sasomers ATF_TP_ADD_TC(tp, listen_bound); 1075261081Sasomers ATF_TP_ADD_TC(tp, connect); 1076261081Sasomers ATF_TP_ADD_TC(tp, accept); 1077261081Sasomers ATF_TP_ADD_TC(tp, fcntl_nonblock); 1078261081Sasomers ATF_TP_ADD_TC(tp, resize_buffers); 1079261081Sasomers ATF_TP_ADD_TC(tp, resize_connected_buffers); 1080261081Sasomers 1081261081Sasomers /* Unthreaded I/O tests */ 1082261081Sasomers ATF_TP_ADD_TC(tp, send_recv); 1083261081Sasomers ATF_TP_ADD_TC(tp, send_recv_nonblocking); 1084261081Sasomers ATF_TP_ADD_TC(tp, send_recv_with_connect); 1085261081Sasomers ATF_TP_ADD_TC(tp, sendto_recvfrom); 1086261081Sasomers ATF_TP_ADD_TC(tp, shutdown_send); 1087261081Sasomers ATF_TP_ADD_TC(tp, shutdown_send_sigpipe); 1088261081Sasomers ATF_TP_ADD_TC(tp, emsgsize); 1089261081Sasomers ATF_TP_ADD_TC(tp, emsgsize_nonblocking); 1090261081Sasomers ATF_TP_ADD_TC(tp, eagain_8k_8k); 1091261081Sasomers ATF_TP_ADD_TC(tp, eagain_8k_128k); 1092261081Sasomers ATF_TP_ADD_TC(tp, eagain_128k_8k); 1093261081Sasomers ATF_TP_ADD_TC(tp, eagain_128k_128k); 1094261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_8k); 1095261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_16k); 1096261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_32k); 1097261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_64k); 1098261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_128k); 1099261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking); 1100261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking); 1101261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking); 1102261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking); 1103261081Sasomers ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking); 1104261081Sasomers ATF_TP_ADD_TC(tp, rcvbuf_oversized); 1105261081Sasomers ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k); 1106261081Sasomers ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k); 1107261081Sasomers ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k); 1108261081Sasomers ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k); 1109261081Sasomers 1110261081Sasomers /* Threaded I/O tests with blocking sockets */ 1111261081Sasomers ATF_TP_ADD_TC(tp, pipe_8k_8k); 1112261081Sasomers ATF_TP_ADD_TC(tp, pipe_8k_128k); 1113261081Sasomers ATF_TP_ADD_TC(tp, pipe_128k_8k); 1114261081Sasomers ATF_TP_ADD_TC(tp, pipe_128k_128k); 1115261081Sasomers 1116261081Sasomers return atf_no_error(); 1117261081Sasomers} 1118