ATF_TC_BODY(send_recv, tc) { int s; int sv[2]; const int bufsize = 64; const char *data = "data"; char recv_buf[bufsize]; size_t datalen; ssize_t ssize, rsize; /* setup the socket pair */ do_socketpair(sv); /* send and receive a small packet */ datalen = strlen(data) + 1; /* +1 for the null */ ssize = send(sv[0], data, datalen, MSG_EOR); if (ssize < 0) { perror("send"); atf_tc_fail("send returned < 0"); } ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd", datalen, ssize); rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL); ATF_CHECK_EQ(datalen, rsize); }
ATF_TC_BODY(resize_connected_buffers, tc) { int sv[2]; int sndbuf = 12345; int rcvbuf = 23456; int err; int ls, lr, rs, rr; socklen_t sl = sizeof(ls); /* setup the socket pair */ do_socketpair(sv); printf(" Socket Buffer Sizes\n"); printf(" | Left Socket | Right Socket |\n"); printf(" | SNDBUF | RCVBUF | SNDBUF | RCVBUF |\n"); ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl)); ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl)); ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl)); ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl)); printf("Default | %7d | %7d | %7d | %7d |\n", ls, lr, rs, rr); /* Update one side's send buffer */ err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)); if (err != 0){ perror("setsockopt"); atf_tc_fail("setsockopt(SO_SNDBUF) failed"); } ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl)); ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl)); ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl)); ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl)); printf("After changing Left's SNDBUF | %7d | %7d | %7d | %7d |\n", ls, lr, rs, rr); /* Update the same side's receive buffer */ err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); if (err != 0){ perror("setsockopt"); atf_tc_fail("setsockopt(SO_RCVBUF) failed"); } ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl)); ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl)); ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl)); ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl)); printf("After changing Left's RCVBUF | %7d | %7d | %7d | %7d |\n", ls, lr, rs, rr); }
static void test_pipe(size_t sndbufsize, size_t rcvbufsize) { test_pipe_thread_data_t writer_data, reader_data; pthread_t writer, reader; int sv[2]; const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4; int numpkts; /* setup the socket pair */ do_socketpair(sv); /* Setup the buffers */ ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, sizeof(sndbufsize))); ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, sizeof(rcvbufsize))); /* Send a total amount of data comfortably greater than the buffers */ numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize; /* Start the child threads */ writer_data.pktsize = pktsize; writer_data.numpkts = numpkts; writer_data.so = sv[0]; reader_data.pktsize = pktsize; reader_data.numpkts = numpkts; reader_data.so = sv[1]; ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer, (void*)&writer_data)); /* * Give the writer time to start writing, and hopefully block, before * starting the reader. This increases the likelihood of the test case * failing due to PR kern/185812 */ usleep(1000); ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader, (void*)&reader_data)); /* Join the children */ ATF_REQUIRE_EQ(0, pthread_join(writer, NULL)); ATF_REQUIRE_EQ(0, pthread_join(reader, NULL)); }
void test_sendrecv_symmetric_buffers(size_t bufsize, int blocking) { int s; int sv[2]; const size_t pktsize = bufsize / 2; char sndbuf[pktsize]; char recv_buf[pktsize]; ssize_t ssize, rsize; /* setup the socket pair */ if (blocking) do_socketpair(sv); else do_socketpair_nonblocking(sv); /* Setup the buffers */ s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)); ATF_REQUIRE_EQ(0, s); s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)); ATF_REQUIRE_EQ(0, s); /* Fill the send buffer */ bzero(sndbuf, pktsize); /* send and receive the packet */ ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); if (ssize < 0) { perror("send"); atf_tc_fail("send returned < 0"); } ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd", pktsize, ssize); rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL); if (rsize < 0) { perror("recv"); atf_tc_fail("recv returned < 0"); } ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd", pktsize, rsize); }
ATF_TC_BODY(emsgsize, tc) { int sv[2]; const size_t sndbufsize = 8192; const size_t rcvbufsize = 8192; const size_t pktsize = (sndbufsize + rcvbufsize) * 2; char sndbuf[pktsize]; ssize_t ssize; /* setup the socket pair */ do_socketpair(sv); /* Setup the buffers */ ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, sizeof(sndbufsize))); ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, sizeof(rcvbufsize))); ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); ATF_CHECK_EQ(EMSGSIZE, errno); ATF_CHECK_EQ(-1, ssize); }
void test_pipe(size_t sndbufsize, size_t rcvbufsize) { test_pipe_thread_data_t writer_data, reader_data; pthread_t writer, reader; int num_sent, num_received; int sv[2]; const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4; int numpkts; /* setup the socket pair */ do_socketpair(sv); /* Setup the buffers */ ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, sizeof(sndbufsize))); ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, sizeof(rcvbufsize))); /* Send a total amount of data comfortably greater than the buffers */ numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize; /* Start the child threads */ writer_data.pktsize = pktsize; writer_data.numpkts = numpkts; writer_data.so = sv[0]; reader_data.pktsize = pktsize; reader_data.numpkts = numpkts; reader_data.so = sv[1]; ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer, (void*)&writer_data)); ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader, (void*)&reader_data)); /* Join the children */ ATF_REQUIRE_EQ(0, pthread_join(writer, NULL)); ATF_REQUIRE_EQ(0, pthread_join(reader, NULL)); }
PUBLIC int uds_ioctl(message *dev_m_in, message *dev_m_out) { int minor; #if DEBUG == 1 static int call_count = 0; printf("(uds) [%d] uds_ioctl() call_count=%d\n", uds_minor(dev_m_in), ++call_count); printf("Endpoint: 0x%x | Position 0x%x\n", dev_m_in->IO_ENDPT, dev_m_in->POSITION); #endif minor = uds_minor(dev_m_in); if (uds_fd_table[minor].state != UDS_INUSE) { /* attempted to close a socket that hasn't been opened -- * something is very wrong :( */ uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->IO_ENDPT, (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL); return EINVAL; } /* track the system call we are performing in case it gets cancelled */ uds_fd_table[minor].call_nr = dev_m_in->m_type; uds_fd_table[minor].ioctl = dev_m_in->COUNT; uds_fd_table[minor].syscall_done = 0; /* setup select(2) framework */ uds_fd_table[minor].selecting = 0; /* update the owner endpoint - yes it's really stored in POSITION */ uds_fd_table[minor].owner = dev_m_in->POSITION; switch (dev_m_in->COUNT) { /* Handle the ioctl(2) command */ case NWIOSUDSCONN: /* connect to a listening socket -- connect() */ return do_connect(dev_m_in, dev_m_out); case NWIOSUDSACCEPT: /* accept an incoming connection -- accept() */ return do_accept(dev_m_in, dev_m_out); case NWIOSUDSBLOG: /* set the backlog_size and put the socket into the * listening state -- listen() */ return do_listen(dev_m_in, dev_m_out); case NWIOSUDSTYPE: /* set the type for this socket (i.e. * SOCK_STREAM, SOCK_DGRAM, etc) -- socket() */ return do_socket(dev_m_in, dev_m_out); case NWIOSUDSADDR: /* set the address for this socket -- bind() */ return do_bind(dev_m_in, dev_m_out); case NWIOGUDSADDR: /* get the address for this socket -- getsockname() */ return do_getsockname(dev_m_in, dev_m_out); case NWIOGUDSPADDR: /* get the address for the peer -- getpeername() */ return do_getpeername(dev_m_in, dev_m_out); case NWIOSUDSSHUT: /* shutdown a socket for reading, writing, or * both -- shutdown() */ return do_shutdown(dev_m_in, dev_m_out); case NWIOSUDSPAIR: /* connect two sockets -- socketpair() */ return do_socketpair(dev_m_in, dev_m_out); case NWIOGUDSSOTYPE: /* get socket type -- getsockopt(SO_TYPE) */ return do_getsockopt_sotype(dev_m_in, dev_m_out); case NWIOGUDSPEERCRED: /* get peer endpoint -- getsockopt(SO_PEERCRED) */ return do_getsockopt_peercred(dev_m_in, dev_m_out); case NWIOSUDSTADDR: /* set target address -- sendto() */ return do_sendto(dev_m_in, dev_m_out); case NWIOGUDSFADDR: /* get from address -- recvfrom() */ return do_recvfrom(dev_m_in, dev_m_out); case NWIOGUDSSNDBUF: /* get the send buffer size -- getsockopt(SO_SNDBUF) */ return do_getsockopt_sndbuf(dev_m_in, dev_m_out); case NWIOSUDSSNDBUF: /* set the send buffer size -- setsockopt(SO_SNDBUF) */ return do_setsockopt_sndbuf(dev_m_in, dev_m_out); case NWIOGUDSRCVBUF: /* get the send buffer size -- getsockopt(SO_SNDBUF) */ return do_getsockopt_rcvbuf(dev_m_in, dev_m_out); case NWIOSUDSRCVBUF: /* set the send buffer size -- setsockopt(SO_SNDBUF) */ return do_setsockopt_rcvbuf(dev_m_in, dev_m_out); case NWIOSUDSCTRL: /* set the control data -- sendmsg() */ return do_sendmsg(dev_m_in, dev_m_out); case NWIOGUDSCTRL: /* set the control data -- recvmsg() */ return do_recvmsg(dev_m_in, dev_m_out); default: /* the IOCTL command is not valid for /dev/uds -- * this happens a lot and is normal. a lot of * libc functions determine the socket type with * IOCTLs. Any not for us simply get a EBADIOCTL * response. */ uds_fd_table[minor].syscall_done = 1; uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->IO_ENDPT, (cp_grant_id_t) dev_m_in->IO_GRANT, EBADIOCTL); return EBADIOCTL; } }