/test/test56.c
C | 2647 lines | 1954 code | 554 blank | 139 comment | 615 complexity | 54b697e43c5bc00740a11ef9fd7d5255 MD5 | raw file
Possible License(s): MIT, WTFPL, AGPL-1.0, BSD-3-Clause, GPL-3.0, LGPL-2.0, JSON, 0BSD
Large files files are truncated, but you can click here to view the full file
- /*
- * Test Program for Unix Domain Sockets
- *
- * Overview: This program tests Unix Domain Sockets. It attempts
- * to exercise the functions associated with Unix Domain Sockets.
- * It also attempts to make sure all of the functions which handle
- * file/socket descriptors work correctly when given a socket
- * descriptor for a Unix domain socket. It also implicitly checks
- * for the existance of constants like AF_UNIX and structures like
- * sockaddr_un (it won't compile if they aren't defined). Besides
- * checking that the sockets work properly, this test program also
- * checks that the errors returned conform to the POSIX 2008
- * standards. Some tests are omitted as they could adversely affect
- * the operation of the host system. For example, implementing a test
- * for socket() failing with errno = ENFILE would require using up all
- * of the file descriptors supported by the OS (defined in
- * /proc/sys/fs/file-max on Linux); this could cause problems for
- * daemons and other processes running on the system. Some tests are
- * omitted because they would require changes to libc or the kernel.
- * For example, getting EINTR would require delaying the system call
- * execution time long enough to raise a signal to interupt it. Some
- * tests were omitted because the particular errors cannot occur when
- * using Unix domain sockets. For example, write() will never fail with
- * ENETDOWN because Unix domain sockets don't use network interfaces.
- *
- * Structure: Some functions can be tested or partially tested without
- * making a connection, socket() for example. These have test
- * functions like test_NAME(). The functionality that needs two way
- * communication is contained within test_xfer().
- *
- * Functions Tested: accept(), bind(), close(), connect(), dup(),
- * dup2(), fstat(), getpeername(), getsockname(), getsockopt(),
- * listen(), read(), readv(), recv(), recvfrom(), recvmsg(), select(),
- * send(), sendmsg(), sendto(), setsockopt(), shutdown(), socket(),
- * socketpair(), write(), writev()
- */
- #define DEBUG 0
- #include <ctype.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/socket.h>
- #include <sys/stat.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <sys/uio.h>
- #include <sys/un.h>
- #include <sys/wait.h>
- #include <time.h>
- #include <unistd.h>
- /* Maximum number of errors that we'll allow to occur before this test
- * program gives us and quits.
- */
- #define MAX_ERROR 4
- /* Use the common testing code instead of reinventing the wheel. */
- #include "common.c"
- /* path of the unix domain socket */
- #define TEST_SUN_PATH "test.sock"
- #define TEST_SUN_PATHB "testb.sock"
- /* filenames for symlinks -- we link these to each other to test ELOOP .*/
- #define TEST_SYM_A "test.a"
- #define TEST_SYM_B "test.b"
- /* text file and test phrase for testing file descriptor passing */
- #define TEST_TXT_FILE "test.txt"
- #define MSG "This raccoon loves to eat bugs.\n"
- /* buffer for send/recv */
- #define BUFSIZE (128)
- #define ISO8601_FORMAT "%Y-%m-%dT%H:%M:%S"
- /* socket types supported */
- int types[3] = {SOCK_STREAM, SOCK_SEQPACKET, SOCK_DGRAM};
- char sock_fullpath[PATH_MAX + 1];
- /* timestamps for debug and error logs */
- char *get_timestamp(void)
- {
- struct tm *tm;
- time_t t;
- size_t len;
- char *s;
- len = sizeof(char) * 32;
- t = time(NULL);
- if (t == -1) {
- return NULL;
- }
- tm = gmtime(&t);
- if (tm == NULL) {
- return NULL;
- }
- s = (char *) malloc(len);
- if (!s) {
- perror("malloc");
- return NULL;
- }
- memset(s, '\0', len);
- strftime(s, len - 1, ISO8601_FORMAT, tm);
- return s;
- }
- /* macro to display information about a failed test and increment the errct */
- #define test_fail(msg) \
- do { \
- char *timestamp; \
- timestamp = get_timestamp(); \
- if (errct == 0) fprintf(stderr, "\n"); \
- fprintf(stderr, "[ERROR][%s] (%s Line %d) %s [pid=%d:errno=%d:%s]\n", \
- timestamp, __FILE__, __LINE__, msg, getpid(), \
- errno, strerror(errno)); \
- fflush(stderr); \
- if (timestamp != NULL) { \
- free(timestamp); \
- timestamp = NULL; \
- } \
- errct++; \
- if (errct++ > MAX_ERROR) { \
- printf("Too many errors; test aborted\n"); \
- quit(); \
- exit(1); \
- } \
- } while (0)
- /* Convert name to the full path of the socket. Assumes name is in cwd. */
- char *fullpath(char *name)
- {
- char cwd[PATH_MAX + 1];
- if (realpath(".", cwd) == NULL)
- test_fail("Couldn't retrieve current working dir");
- snprintf(sock_fullpath, PATH_MAX, "%s/%s", cwd, name);
- return(sock_fullpath);
- }
- #if DEBUG == 1
- /* macros to display debugging information */
- #define debug(msg) \
- do { \
- char *timestamp; \
- timestamp = get_timestamp(); \
- fprintf(stdout,"[DEBUG][%s] (%s:%d) %s [pid=%d]\n", \
- timestamp, __FILE__, __LINE__, msg, getpid()); \
- fflush(stdout); \
- if (timestamp != NULL) { \
- free(timestamp); \
- timestamp = NULL; \
- } \
- } while (0)
- #else
- #define debug(msg) \
- do { /* nothing */; } while (0)
- #endif
- #define SOCKET(sd,domain,type,protocol) \
- do { \
- errno = 0; \
- sd = socket(domain, type, protocol); \
- if (sd == -1) { \
- test_fail("sd = socket(domain, type, protocol) failed");\
- } \
- } while (0)
- #define UNLINK(path) \
- do { \
- int rc; \
- errno = 0; \
- rc = unlink(path); \
- if (rc == -1 && errno != ENOENT) { \
- test_fail("unlink(path) failed"); \
- } \
- } while(0)
- #define SYMLINK(oldpath,newpath) \
- do { \
- int rc; \
- errno = 0; \
- rc = symlink(oldpath,newpath); \
- if (rc == -1) { \
- test_fail("symlink(oldpath,newpath) failed"); \
- } \
- } while(0)
- #define CLOSE(sd) \
- do { \
- int rc; \
- errno = 0; \
- rc = close(sd); \
- if (rc == -1) { \
- test_fail("close(sd) failed"); \
- } \
- } while (0)
- void test_socket(void)
- {
- struct stat statbuf, statbuf2;
- int sd, sd2;
- int rc;
- int i;
- debug("entering test_socket()");
- debug("Test socket() with an unsupported address family");
- errno = 0;
- sd = socket(-1, SOCK_STREAM, 0);
- if (!(sd == -1 && errno == EAFNOSUPPORT)) {
- test_fail("socket");
- if (sd != -1) {
- CLOSE(sd);
- }
- }
- debug("Test socket() with all available FDs open by this process");
- for (i = 3; i < getdtablesize(); i++) {
- rc = open("/dev/null", O_RDONLY);
- if (rc == -1) {
- test_fail("we couldn't open /dev/null for read");
- }
- }
- errno = 0;
- sd = socket(PF_UNIX, SOCK_STREAM, 0);
- if (!(sd == -1 && errno == EMFILE)) {
- test_fail("socket() call with all fds open should fail");
- if (sd != -1) {
- CLOSE(sd);
- }
- }
- for (i = 3; i < getdtablesize(); i++) {
- CLOSE(i);
- }
- debug("Test socket() with an mismatched protocol");
- errno = 0;
- sd = socket(PF_UNIX, SOCK_STREAM, 4);
- if (!(sd == -1 && errno == EPROTONOSUPPORT)) {
- test_fail("socket() should fail with errno = EPROTONOSUPPORT");
- if (sd != -1) {
- CLOSE(sd);
- }
- }
- debug("Test socket() success");
- /*
- * open 2 sockets at once and *then* close them.
- * This will test that /dev/uds is cloning properly.
- */
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- SOCKET(sd2, PF_UNIX, SOCK_STREAM, 0);
- rc = fstat(sd, &statbuf);
- if (rc == -1) {
- test_fail("fstat failed on sd");
- }
- rc = fstat(sd2, &statbuf2);
- if (rc == -1) {
- test_fail("fstat failed on sd2");
- }
- if (statbuf.st_dev == statbuf2.st_dev) {
- test_fail("/dev/uds isn't being cloned");
- }
- CLOSE(sd2);
- CLOSE(sd);
- debug("leaving test_socket()");
- }
- void test_header(void)
- {
- struct sockaddr_un sun;
- debug("entering test_header()");
- sun.sun_family = AF_UNIX;
- sun.sun_path[0] = 'x';
- sun.sun_path[1] = 'x';
- sun.sun_path[2] = 'x';
- sun.sun_path[3] = '\0';
- if (SUN_LEN(&sun) != 4) {
- test_fail("SUN_LEN(&sun) should be 4");
- }
- if (PF_UNIX != PF_LOCAL || PF_UNIX != PF_FILE || PF_UNIX != AF_UNIX) {
- test_fail("PF_UNIX, PF_LOCAL, PF_FILE, and AF_UNIX");
- }
- }
- void test_socketpair(void)
- {
- char buf[128];
- struct sockaddr_un addr;
- int socket_vector[2];
- int rc;
- int i;
- debug("entering test_socketpair()");
- UNLINK(TEST_SUN_PATH);
- memset(&addr, '\0', sizeof(struct sockaddr_un));
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, TEST_SUN_PATH, sizeof(addr.sun_path) - 1);
- debug("Testing socketpair() success");
- rc = socketpair(PF_UNIX, SOCK_STREAM, 0, socket_vector);
- if (rc == -1) {
- test_fail("socketpair() should have worked");
- }
- debug("Testing a simple read/write using sockets from socketpair()");
- memset(buf, '\0', sizeof(buf));
- strncpy(buf, "Howdy Partner", sizeof(buf) - 1);
- rc = write(socket_vector[0], buf, sizeof(buf));
- if (rc == -1) {
- test_fail("write(sd, buf, sizeof(buf)) failed unexpectedly");
- }
- memset(buf, '\0', sizeof(buf));
- rc = read(socket_vector[1], buf, sizeof(buf));
- if (rc == -1) {
- test_fail("read() failed unexpectedly");
- }
- if (strncmp(buf, "Howdy Partner", strlen("Howdy Partner")) != 0) {
- test_fail("We did not read what we wrote");
- }
- CLOSE(socket_vector[0]);
- CLOSE(socket_vector[1]);
- debug("Test socketpair() with all FDs open by this process");
- for (i = 3; i < getdtablesize(); i++) {
- rc = open("/dev/null", O_RDONLY);
- if (rc == -1) {
- test_fail("we couldn't open /dev/null for read");
- }
- }
- rc = socketpair(PF_UNIX, SOCK_STREAM, 0, socket_vector);
- if (!(rc == -1 && errno == EMFILE)) {
- test_fail("socketpair() should have failed with EMFILE");
- }
- for (i = 3; i < getdtablesize(); i++) {
- CLOSE(i);
- }
- rc = socketpair(PF_UNIX, SOCK_STREAM, 4, socket_vector);
- if (!(rc == -1 && errno == EPROTONOSUPPORT)) {
- test_fail("socketpair() should have failed");
- }
- debug("leaving test_socketpair()");
- }
- void test_ucred(void)
- {
- struct ucred credentials;
- socklen_t ucred_length;
- uid_t euid = geteuid();
- gid_t egid = getegid();
- int sv[2];
- int rc;
- debug("Test credentials passing");
- ucred_length = sizeof(struct ucred);
- rc = socketpair(PF_UNIX, SOCK_STREAM, 0, sv);
- if (rc == -1) {
- test_fail("socketpair(PF_UNIX, SOCK_STREAM, 0, sv) failed");
- }
- memset(&credentials, '\0', ucred_length);
- rc = getsockopt(sv[0], SOL_SOCKET, SO_PEERCRED, &credentials,
- &ucred_length);
- if (rc == -1) {
- test_fail("getsockopt(SO_PEERCRED) failed");
- } else if (credentials.pid != getpid() ||
- credentials.uid != geteuid() ||
- credentials.gid != getegid()) {
- /* printf("%d=%d %d=%d %d=%d",credentials.pid, getpid(),
- credentials.uid, geteuid(), credentials.gid, getegid()); */
- test_fail("Credential passing gave us the wrong cred");
- }
- rc = getpeereid(sv[0], &euid, &egid);
- if (rc == -1) {
- test_fail("getpeereid(sv[0], &euid, &egid) failed");
- } else if (credentials.uid != euid || credentials.gid != egid) {
- test_fail("getpeereid() didn't give the correct euid/egid");
- }
- CLOSE(sv[0]);
- CLOSE(sv[1]);
- }
- void test_getsockname(void)
- {
- int sd;
- int rc;
- struct sockaddr_un addr, sock_addr;
- socklen_t sock_addr_len;
- memset(&addr, '\0', sizeof(struct sockaddr_un));
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, TEST_SUN_PATH, sizeof(addr.sun_path) - 1);
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- rc = bind(sd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un));
- if (rc == -1) {
- test_fail("bind() should have worked");
- }
- debug("Test getsockname() success");
- memset(&sock_addr, '\0', sizeof(struct sockaddr_un));
- sock_addr_len = sizeof(struct sockaddr_un);
- rc = getsockname(sd, (struct sockaddr *) &sock_addr, &sock_addr_len);
- if (rc == -1) {
- test_fail("getsockname() should have worked");
- }
- if (!(sock_addr.sun_family == AF_UNIX && strncmp(sock_addr.sun_path,
- fullpath(TEST_SUN_PATH),
- sizeof(sock_addr.sun_path) - 1) == 0)) {
- test_fail("getsockname() did return the right address");
- fprintf(stderr, "exp: '%s' | got: '%s'\n", addr.sun_path,
- sock_addr.sun_path);
- }
- CLOSE(sd);
- }
- void test_bind(void)
- {
- struct sockaddr_un addr;
- struct sockaddr_un sock_addr;
- socklen_t sock_addr_len;
- int sd;
- int sd2;
- int rc;
- debug("entering test_bind()");
- UNLINK(TEST_SUN_PATH);
- memset(&addr, '\0', sizeof(struct sockaddr_un));
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, TEST_SUN_PATH, sizeof(addr.sun_path) - 1);
- debug("Test bind() success");
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- rc = bind(sd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un));
- if (rc == -1) {
- test_fail("bind() should have worked");
- }
- debug("Test getsockname() success");
- memset(&sock_addr, '\0', sizeof(struct sockaddr_un));
- sock_addr_len = sizeof(struct sockaddr_un);
- rc = getsockname(sd, (struct sockaddr *) &sock_addr, &sock_addr_len);
- if (rc == -1) {
- test_fail("getsockname() should have worked");
- }
- if (!(sock_addr.sun_family == AF_UNIX &&
- strncmp(sock_addr.sun_path,
- fullpath(TEST_SUN_PATH),
- sizeof(sock_addr.sun_path) - 1) == 0)) {
- test_fail("getsockname() didn't return the right addr");
- fprintf(stderr, "exp: '%s' | got: '%s'\n", addr.sun_path,
- sock_addr.sun_path);
- }
- debug("Test bind() with a address that has already been bind()'d");
- SOCKET(sd2, PF_UNIX, SOCK_STREAM, 0);
- errno = 0;
- rc = bind(sd2, (struct sockaddr *) &addr, sizeof(struct sockaddr_un));
- if (!((rc == -1) && (errno == EADDRINUSE))) {
- test_fail("bind() should have failed with EADDRINUSE");
- }
- CLOSE(sd2);
- CLOSE(sd);
- UNLINK(TEST_SUN_PATH);
- debug("Test bind() with an empty sun_path");
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- memset(addr.sun_path, '\0', sizeof(addr.sun_path));
- errno = 0;
- rc = bind(sd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un));
- if (!(rc == -1 && errno == ENOENT)) {
- test_fail("bind() should have failed with ENOENT");
- }
- CLOSE(sd);
- debug("Test bind() with a NULL address");
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- errno = 0;
- rc = bind(sd, (struct sockaddr *) NULL, sizeof(struct sockaddr_un));
- if (!((rc == -1) && (errno == EFAULT))) {
- test_fail("bind() should have failed with EFAULT");
- }
- CLOSE(sd);
- debug("Test bind() using a symlink loop");
- UNLINK(TEST_SUN_PATH);
- UNLINK(TEST_SYM_A);
- UNLINK(TEST_SYM_B);
- SYMLINK(TEST_SYM_A, TEST_SYM_B);
- SYMLINK(TEST_SYM_B, TEST_SYM_A);
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- strncpy(addr.sun_path, TEST_SYM_A, sizeof(addr.sun_path) - 1);
- errno = 0;
- rc = bind(sd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un));
- if (!((rc == -1) && (errno == ELOOP))) {
- test_fail("bind() should have failed with ELOOP");
- }
- CLOSE(sd);
- UNLINK(TEST_SUN_PATH);
- UNLINK(TEST_SYM_A);
- UNLINK(TEST_SYM_B);
- debug("leaving test_bind()");
- }
- void test_listen(void)
- {
- int rc;
- debug("entering test_listen()");
- debug("Test listen() with a bad file descriptor");
- errno = 0;
- rc = listen(-1, 0);
- if (!(rc == -1 && errno == EBADF)) {
- test_fail("listen(-1, 0) should have failed");
- }
- debug("Test listen() with a non-socket file descriptor");
- errno = 0;
- rc = listen(0, 0);
- if (!(rc == -1 && errno == ENOTTY)) {
- test_fail("listen(0, 0) should have failed");
- }
- debug("leaving test_listen()");
- }
- void test_shutdown(void)
- {
- int how[3] = { SHUT_RD, SHUT_WR, SHUT_RDWR };
- int sd;
- int rc;
- int i;
- debug("entering test_shutdown()");
- /* test for each direction (read, write, read-write) */
- for (i = 0; i < 3; i++) {
- debug("test shutdown() with an invalid descriptor");
- errno = 0;
- rc = shutdown(-1, how[i]);
- if (!(rc == -1 && errno == EBADF)) {
- test_fail("shutdown(-1, how[i]) should have failed");
- }
- debug("test shutdown() with a non-socket descriptor");
- errno = 0;
- rc = shutdown(0, how[i]);
- if (!(rc == -1 && errno == ENOSYS)) {
- test_fail("shutdown() should have failed with ENOSYS");
- }
- debug("test shutdown() with a socket that is not connected");
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- errno = 0;
- rc = shutdown(sd, how[i]);
- if (!(rc == -1 && errno == ENOTCONN)) {
- test_fail("shutdown() should have failed");
- }
- CLOSE(sd);
- }
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- errno = 0;
- rc = shutdown(sd, -1);
- if (!(rc == -1 && errno == ENOTCONN)) {
- test_fail("shutdown(sd, -1) should have failed with ENOTCONN");
- }
- CLOSE(sd);
- debug("leaving test_shutdown()");
- }
- void test_close(void)
- {
- struct sockaddr_un addr;
- int sd, sd2;
- int rc, i;
- debug("entering test_close()");
- UNLINK(TEST_SUN_PATH);
- memset(&addr, '\0', sizeof(struct sockaddr_un));
- strncpy(addr.sun_path, TEST_SUN_PATH, sizeof(addr.sun_path) - 1);
- addr.sun_family = AF_UNIX;
- debug("Test close() success");
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- rc = bind(sd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un));
- if (rc != 0) {
- test_fail("bind() should have worked");
- }
- CLOSE(sd);
- debug("Close an already closed file descriptor");
- errno = 0;
- rc = close(sd);
- if (!(rc == -1 && errno == EBADF)) {
- test_fail("close(sd) should have failed with EBADF");
- }
- UNLINK(TEST_SUN_PATH);
- debug("dup()'ing a file descriptor and closing both should work");
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- rc = bind(sd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un));
- if (rc != 0) {
- test_fail("bind() should have worked");
- }
- errno = 0;
- sd2 = dup(sd);
- if (sd2 == -1) {
- test_fail("dup(sd) should have worked");
- } else {
- CLOSE(sd2);
- CLOSE(sd);
- }
- UNLINK(TEST_SUN_PATH);
- /* Create and close a socket a bunch of times.
- * If the implementation doesn't properly free the
- * socket during close(), eventually socket() will
- * fail when the internal descriptor table is full.
- */
- for (i = 0; i < 1024; i++) {
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- CLOSE(sd);
- }
- debug("leaving test_close()");
- }
- void test_sockopts(void)
- {
- int i;
- int rc;
- int sd;
- int option_value;
- socklen_t option_len;
- debug("entering test_sockopts()");
- for (i = 0; i < 3; i++) {
- SOCKET(sd, PF_UNIX, types[i], 0);
- debug("Test setsockopt() works");
- option_value = 0;
- option_len = sizeof(option_value);
- errno = 0;
- rc = getsockopt(sd, SOL_SOCKET, SO_TYPE, &option_value,
- &option_len);
- if (rc != 0) {
- test_fail("setsockopt() should have worked");
- }
- if (option_value != types[i]) {
- test_fail("SO_TYPE didn't seem to work.");
- }
- CLOSE(sd);
- }
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- debug("Test setsockopt() works");
- option_value = 0;
- option_len = sizeof(option_value);
- errno = 0;
- rc = getsockopt(sd, SOL_SOCKET, SO_SNDBUF, &option_value, &option_len);
- if (rc != 0) {
- test_fail("getsockopt() should have worked");
- }
- if (option_value != PIPE_BUF) {
- test_fail("SO_SNDBUF didn't seem to work.");
- }
- CLOSE(sd);
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- debug("Test setsockopt() works");
- option_value = 0;
- option_len = sizeof(option_value);
- errno = 0;
- rc = getsockopt(sd, SOL_SOCKET, SO_RCVBUF, &option_value, &option_len);
- if (rc != 0) {
- test_fail("getsockopt() should have worked");
- }
- if (option_value != PIPE_BUF) {
- test_fail("SO_RCVBUF didn't seem to work.");
- }
- CLOSE(sd);
- debug("leaving test_sockopts()");
- }
- void test_read(void)
- {
- int rc;
- int fd;
- char buf[BUFSIZE];
- debug("entering test_read()");
- errno = 0;
- rc = read(-1, buf, sizeof(buf));
- if (!(rc == -1 && errno == EBADF)) {
- test_fail("read() should have failed with EBADF");
- }
- fd = open("/tmp", O_RDONLY);
- if (fd == -1) {
- test_fail("open(\"/tmp\", O_RDONLY) should have worked");
- }
- CLOSE(fd);
- debug("leaving test_read()");
- }
- void test_write(void)
- {
- int rc;
- char buf[BUFSIZE];
- debug("entering test_write()");
- errno = 0;
- rc = write(-1, buf, sizeof(buf));
- if (!(rc == -1 && errno == EBADF)) {
- test_fail("write() should have failed with EBADF");
- }
- debug("leaving test_write()");
- }
- void test_dup(void)
- {
- struct stat info1;
- struct stat info2;
- struct sockaddr_un addr;
- int sd, sd2;
- int rc;
- int i;
- debug("entering test_dup()");
- UNLINK(TEST_SUN_PATH);
- memset(&addr, '\0', sizeof(struct sockaddr_un));
- strncpy(addr.sun_path, TEST_SUN_PATH, sizeof(addr.sun_path) - 1);
- addr.sun_family = AF_UNIX;
- debug("Test dup()");
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- rc = bind(sd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un));
- if (rc != 0) {
- test_fail("bind() should have worked");
- }
- errno = 0;
- sd2 = dup(sd);
- if (sd2 == -1) {
- test_fail("dup(sd) should have worked");
- }
- rc = fstat(sd, &info1);
- if (rc == -1) {
- test_fail("fstat(fd, &info1) failed");
- }
- rc = fstat(sd2, &info2);
- if (rc == -1) {
- test_fail("fstat(sd, &info2) failed");
- }
- if (info1.st_ino != info2.st_ino) {
- test_fail("dup() failed info1.st_ino != info2.st_ino");
- }
- CLOSE(sd);
- CLOSE(sd2);
- debug("Test dup() with a closed socket");
- errno = 0;
- rc = dup(sd);
- if (!(rc == -1 && errno == EBADF)) {
- test_fail("dup(sd) on a closed socket shouldn't have worked");
- }
- debug("Test dup() with socket descriptor of -1");
- errno = 0;
- rc = dup(-1);
- if (!(rc == -1 && errno == EBADF)) {
- test_fail("dup(-1) shouldn't have worked");
- }
- debug("Test dup() when all of the file descriptors are taken");
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- for (i = 4; i < getdtablesize(); i++) {
- rc = open("/dev/null", O_RDONLY);
- if (rc == -1) {
- test_fail("we couldn't open /dev/null for read");
- }
- }
- errno = 0;
- sd2 = dup(sd);
- if (!(sd2 == -1 && errno == EMFILE)) {
- test_fail("dup(sd) should have failed with errno = EMFILE");
- }
- for (i = 3; i < getdtablesize(); i++) {
- CLOSE(i);
- }
- UNLINK(TEST_SUN_PATH);
- debug("leaving test_dup()");
- }
- void test_dup2(void)
- {
- struct stat info1;
- struct stat info2;
- struct sockaddr_un addr;
- int sd;
- int fd;
- int rc;
- debug("entering test_dup2()");
- UNLINK(TEST_SUN_PATH);
- memset(&addr, '\0', sizeof(struct sockaddr_un));
- strncpy(addr.sun_path, TEST_SUN_PATH, sizeof(addr.sun_path) - 1);
- addr.sun_family = AF_UNIX;
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- rc = bind(sd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un));
- if (rc != 0) {
- test_fail("bind() should have worked");
- }
- fd = open("/dev/null", O_RDONLY);
- if (fd == -1) {
- test_fail("open(\"/dev/null\", O_RDONLY) failed");
- }
- fd = dup2(sd, fd);
- if (fd == -1) {
- test_fail("dup2(sd, fd) failed.");
- }
- memset(&info1, '\0', sizeof(struct stat));
- memset(&info2, '\0', sizeof(struct stat));
- rc = fstat(fd, &info1);
- if (rc == -1) {
- test_fail("fstat(fd, &info1) failed");
- }
- rc = fstat(sd, &info2);
- if (rc == -1) {
- test_fail("fstat(sd, &info2) failed");
- }
- if (!(info1.st_ino == info2.st_ino &&
- major(info1.st_dev) == major(info2.st_dev) &&
- minor(info1.st_dev) == minor(info2.st_dev))) {
- test_fail("dup2() failed");
- }
- CLOSE(fd);
- CLOSE(sd);
- UNLINK(TEST_SUN_PATH);
- debug("leaving test_dup2()");
- }
- /*
- * A toupper() server. This toy server converts a string to upper case.
- */
- void test_xfer_server(pid_t pid)
- {
- int i;
- struct timeval tv;
- fd_set readfds;
- int status;
- int rc;
- int sd;
- char buf[BUFSIZE];
- socklen_t client_addr_size;
- int client_sd;
- struct sockaddr_un addr;
- struct sockaddr_un client_addr;
- status = 0;
- rc = 0;
- sd = 0;
- client_sd = 0;
- client_addr_size = sizeof(struct sockaddr_un);
- memset(&buf, '\0', sizeof(buf));
- memset(&addr, '\0', sizeof(struct sockaddr_un));
- memset(&client_addr, '\0', sizeof(struct sockaddr_un));
- strncpy(addr.sun_path, TEST_SUN_PATH, sizeof(addr.sun_path) - 1);
- addr.sun_family = AF_UNIX;
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- rc = bind(sd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un));
- if (rc == -1) {
- test_fail("bind() should have worked");
- }
- rc = listen(sd, 8);
- if (rc == -1) {
- test_fail("listen(sd, 8) should have worked");
- }
- /* we're ready for connections, time to tell the client to start
- * the test
- */
- kill(pid, SIGUSR1);
- tv.tv_sec = 10;
- tv.tv_usec = 0;
- FD_ZERO(&readfds);
- FD_SET(sd, &readfds);
- /* use select() in case the client is really broken and never
- * attempts to connect (we don't want to block on accept()
- * forever).
- */
- rc = select(sd + 1, &readfds, NULL, NULL, &tv);
- if (rc == -1) {
- test_fail("[server] select() should not have failed");
- }
- if (rc != 1) {
- test_fail("[server] select() should have returned 1");
- printf("[server] select returned %d\n", rc);
- }
- if (!(FD_ISSET(sd, &readfds))) {
- test_fail("[server] client didn't connect within 10 seconds");
- kill(pid, SIGKILL);
- return;
- }
- client_sd = accept(sd, (struct sockaddr *) &client_addr,
- &client_addr_size);
- if (client_sd == -1) {
- test_fail("accept() should have worked");
- kill(pid, SIGKILL);
- return;
- } else {
- debug("[server] client accept()'d");
- }
- debug("[server] Reading message");
- rc = read(client_sd, buf, sizeof(buf));
- if (rc == -1) {
- test_fail("read() failed unexpectedly");
- kill(pid, SIGKILL);
- return;
- }
- debug("[server] we got the following message:");
- debug(buf);
- for (i = 0; i < rc && i < 127; i++) {
- buf[i] = toupper(buf[i]);
- }
- debug("[server] Writing message...");
- rc = write(client_sd, buf, sizeof(buf));
- if (rc == -1) {
- test_fail("write(client_sd, buf, sizeof(buf)) failed");
- kill(pid, SIGKILL);
- return;
- }
- if (rc < strlen(buf)) {
- test_fail("[server] write didn't write all the bytes");
- }
- memset(&buf, '\0', sizeof(buf));
- debug("[server] Recv message");
- rc = recv(client_sd, buf, sizeof(buf), 0);
- if (rc == -1) {
- test_fail("recv() failed unexpectedly");
- kill(pid, SIGKILL);
- return;
- }
- debug("[server] we got the following message:");
- debug(buf);
- for (i = 0; i < rc && i < 127; i++) {
- buf[i] = toupper(buf[i]);
- }
- debug("[server] Sending message...");
- rc = send(client_sd, buf, sizeof(buf), 0);
- if (rc == -1) {
- test_fail("send(client_sd, buf, sizeof(buf), 0) failed");
- kill(pid, SIGKILL);
- return;
- }
- if (rc < strlen(buf)) {
- test_fail("[server] write didn't write all the bytes");
- }
- memset(&buf, '\0', sizeof(buf));
- debug("[server] Recvfrom message");
- rc = recvfrom(client_sd, buf, sizeof(buf), 0, NULL, 0);
- if (rc == -1) {
- test_fail("recvfrom() failed unexpectedly");
- kill(pid, SIGKILL);
- return;
- }
- debug("[server] we got the following message:");
- debug(buf);
- for (i = 0; i < rc && i < 127; i++) {
- buf[i] = toupper(buf[i]);
- }
- debug("[server] Sendto message...");
- rc = sendto(client_sd, buf, sizeof(buf), 0, NULL, 0);
- if (rc == -1) {
- test_fail("sendto() failed");
- kill(pid, SIGKILL);
- return;
- }
- if (rc < strlen(buf)) {
- test_fail("[server] write didn't write all the bytes");
- }
- shutdown(client_sd, SHUT_RDWR);
- CLOSE(client_sd);
- shutdown(sd, SHUT_RDWR);
- CLOSE(sd);
- /* wait for client to exit */
- do {
- errno = 0;
- rc = waitpid(pid, &status, 0);
- } while (rc == -1 && errno == EINTR);
- /* we use the exit status to get its error count */
- errct += WEXITSTATUS(status);
- }
- int server_ready = 0;
- /* signal handler for the client */
- void test_xfer_sighdlr(int sig)
- {
- debug("entering signal handler");
- switch (sig) {
- /* the server will send SIGUSR1 when it is time for us
- * to start the tests
- */
- case SIGUSR1:
- server_ready = 1;
- debug("got SIGUSR1, the server is ready for the client");
- break;
- default:
- debug("didn't get SIGUSR1");
- }
- debug("leaving signal handler");
- }
- /*
- * A toupper() client.
- */
- void test_xfer_client(void)
- {
- struct ucred credentials;
- socklen_t ucred_length;
- struct timeval tv;
- fd_set readfds;
- struct sockaddr_un addr;
- struct sockaddr_un peer_addr;
- socklen_t peer_addr_len;
- int sd;
- int rc;
- char buf[BUFSIZE];
- debug("[client] entering test_xfer_client()");
- errct = 0; /* reset error count */
- ucred_length = sizeof(struct ucred);
- memset(&buf, '\0', sizeof(buf));
- while (server_ready == 0) {
- debug("[client] waiting for the server to signal");
- sleep(1);
- }
- peer_addr_len = sizeof(struct sockaddr_un);
- debug("Creating symlink to TEST_SUN_PATH");
- SYMLINK(TEST_SUN_PATH, TEST_SYM_A);
- memset(&addr, '\0', sizeof(struct sockaddr_un));
- strncpy(addr.sun_path, TEST_SYM_A, sizeof(addr.sun_path) - 1);
- addr.sun_family = AF_UNIX;
- debug("[client] creating client socket");
- SOCKET(sd, PF_UNIX, SOCK_STREAM, 0);
- debug("[client] connecting to server through the symlink");
- rc = connect(sd, (struct sockaddr *) &addr,
- sizeof(struct sockaddr_un));
- if (rc == -1) {
- test_fail("[client] connect() should have worked");
- } else {
- debug("[client] connected");
- }
- debug("[client] testing getpeername()");
- memset(&peer_addr, '\0', sizeof(struct sockaddr_un));
- rc = getpeername(sd, (struct sockaddr *) &peer_addr, &peer_addr_len);
- if (rc == -1) {
- test_fail("[client] getpeername() should have worked");
- }
- /* we need to use the full path "/usr/src/test/DIR_56/test.sock"
- * because that is what is returned by getpeername().
- */
- if (!(peer_addr.sun_family == AF_UNIX &&
- strncmp(peer_addr.sun_path,
- fullpath(TEST_SUN_PATH),
- sizeof(peer_addr.sun_path) - 1) == 0)) {
- test_fail("getpeername() didn't return the right address");
- }
- strncpy(buf, "Hello, World!", sizeof(buf) - 1);
- debug("[client] send to server");
- rc = write(sd, buf, sizeof(buf));
- if (rc == -1) {
- test_fail("[client] write() failed unexpectedly");
- }
- memset(buf, '\0', sizeof(buf));
- debug("[client] read from server");
- rc = read(sd, buf, sizeof(buf));
- if (rc == -1) {
- test_fail("[client] read() failed unexpectedly");
- } else {
- debug("[client] we got the following message:");
- debug(buf);
- }
- if (strncmp(buf, "HELLO, WORLD!", sizeof(buf)) != 0) {
- test_fail("[client] We didn't get the correct response");
- }
- memset(&buf, '\0', sizeof(buf));
- strncpy(buf, "Bonjour!", sizeof(buf) - 1);
- debug("[client] send to server");
- rc = send(sd, buf, sizeof(buf), 0);
- if (rc == -1) {
- test_fail("[client] send() failed unexpectedly");
- }
- debug("Test passing the client credentials to the server");
- memset(&credentials, '\0', ucred_length);
- rc = getsockopt(sd, SOL_SOCKET, SO_PEERCRED, &credentials,
- &ucred_length);
- if (rc == -1) {
- test_fail("[client] getsockopt() failed");
- } else if (credentials.uid != geteuid() ||
- credentials.gid != getegid()) {
- printf("%d=%d=%d %d=%d=%d\n", credentials.uid, getuid(),
- geteuid(), credentials.gid, getgid(), getegid());
- test_fail("[client] Credential passing gave us a bad UID/GID");
- }
- debug("Testing select()");
- tv.tv_sec = 2;
- tv.tv_usec = 500000;
- FD_ZERO(&readfds);
- FD_SET(sd, &readfds);
- rc = select(sd + 1, &readfds, NULL, NULL, &tv);
- if (rc == -1) {
- test_fail("[client] select() should not have failed");
- }
- if (rc != 1) {
- test_fail("[client] select() should have returned 1");
- }
- if (!(FD_ISSET(sd, &readfds))) {
- test_fail("The server didn't respond within 2.5 seconds");
- }
- memset(buf, '\0', sizeof(buf));
- debug("[client] recv from server");
- rc = recv(sd, buf, sizeof(buf), 0);
- if (rc == -1) {
- test_fail("[client] recv() failed unexpectedly");
- } else {
- debug("[client] we got the following message:");
- debug(buf);
- }
- if (strncmp(buf, "BONJOUR!", sizeof(buf)) != 0) {
- test_fail("[client] We didn't get the right response.");
- }
- memset(&buf, '\0', sizeof(buf));
- strncpy(buf, "Hola!", sizeof(buf) - 1);
- debug("[client] sendto to server");
- rc = sendto(sd, buf, sizeof(buf), 0, NULL, 0);
- if (rc == -1) {
- test_fail("[client] sendto() failed");
- }
- debug("Testing select()");
- tv.tv_sec = 2;
- tv.tv_usec = 500000;
- FD_ZERO(&readfds);
- FD_SET(sd, &readfds);
- rc = select(sd + 1, &readfds, NULL, NULL, &tv);
- if (rc == -1) {
- test_fail("[client] select() should not have failed");
- }
- if (rc != 1) {
- test_fail("[client] select() should have returned 1");
- }
- if (!(FD_ISSET(sd, &readfds))) {
- test_fail("[client] The server didn't respond in 2.5 seconds");
- }
- memset(buf, '\0', sizeof(buf));
- debug("[client] recvfrom from server");
- rc = recvfrom(sd, buf, sizeof(buf), 0, NULL, 0);
- if (rc == -1) {
- test_fail("[cleint] recvfrom() failed unexpectedly");
- } else {
- debug("[client] we got the following message:");
- debug(buf);
- }
- if (strncmp(buf, "HOLA!", sizeof(buf)) != 0) {
- test_fail("[client] We didn't get the right response.");
- }
- debug("[client] closing socket");
- CLOSE(sd);
- debug("[client] leaving test_xfer_client()");
- exit(errct);
- }
- void test_xfer(void)
- {
- pid_t pid;
- UNLINK(TEST_SYM_A);
- UNLINK(TEST_SUN_PATH);
- /* the signal handler is only used by the client, but we have to
- * install it now. if we don't the server may signal the client
- * before the handler is installed.
- */
- debug("installing signal handler");
- if (signal(SIGUSR1, test_xfer_sighdlr) == SIG_ERR) {
- test_fail("signal(SIGUSR1, test_xfer_sighdlr) failed");
- }
- debug("signal handler installed");
- server_ready = 0;
- pid = fork();
- if (pid == -1) {
- test_fail("fork() failed");
- return;
- } else if (pid == 0) {
- debug("child");
- test_xfer_client();
- test_fail("we should never get here");
- exit(1);
- } else {
- debug("parent");
- test_xfer_server(pid);
- debug("parent done");
- }
- UNLINK(TEST_SYM_A);
- UNLINK(TEST_SUN_PATH);
- }
- void test_simple_client(int type)
- {
- char buf[BUFSIZE];
- int sd, rc;
- struct sockaddr_un addr;
- sd = socket(PF_UNIX, type, 0);
- if (sd == -1) {
- test_fail("socket");
- exit(errct);
- }
- while (server_ready == 0) {
- debug("[client] waiting for the server");
- sleep(1);
- }
- strncpy(addr.sun_path, TEST_SUN_PATH, sizeof(addr.sun_path) - 1);
- addr.sun_family = AF_UNIX;
- bzero(buf, BUFSIZE);
- snprintf(buf, BUFSIZE-1, "Hello, My Name is Client.");
- if (type == SOCK_DGRAM) {
- rc = sendto(sd, buf, strlen(buf) + 1, 0,
- (struct sockaddr *) &addr, sizeof(struct sockaddr_un));
- if (rc == -1) {
- test_fail("sendto");
- exit(errct);
- }
- } else {
- rc = connect(sd, (struct sockaddr *) &addr,
- sizeof(struct sockaddr_un));
- if (rc == -1) {
- test_fail("connect");
- exit(errct);
- }
- rc = write(sd, buf, strlen(buf) + 1);
- if (rc == -1) {
- test_fail("write");
- }
- memset(buf, '\0', BUFSIZE);
- rc = read(sd, buf, BUFSIZE);
- if (rc == -1) {
- test_fail("read");
- }
- if (strcmp("Hello, My Name is Server.", buf) != 0) {
- test_fail("didn't read the correct string");
- }
- }
- rc = close(sd);
- if (rc == -1) {
- test_fail("close");
- }
- exit(errct);
- }
- void test_simple_server(int type, pid_t pid)
- {
- char buf[BUFSIZE];
- int sd, rc, client_sd, status;
- struct sockaddr_un addr;
- socklen_t addr_len;
- addr_len = sizeof(struct sockaddr_un);
- sd = socket(PF_UNIX, type, 0);
- if (sd == -1) {
- test_fail("socket");
- }
- strncpy(addr.sun_path, TEST_SUN_PATH, sizeof(addr.sun_path) - 1);
- addr.sun_family = AF_UNIX;
- rc = bind(sd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un));
- if (rc == -1) {
- test_fail("bind");
- }
- if (type == SOCK_DGRAM) {
- /* ready for client */
- kill(pid, SIGUSR1);
- rc = recvfrom(sd, buf, BUFSIZE, 0,
- (struct sockaddr *) &addr, &addr_len);
- if (rc == -1) {
- test_fail("recvfrom");
- }
- } else {
- rc = listen(sd, 5);
- if (rc == -1) {
- test_fail("listen");
- }
- /* we're ready for connections, time to tell the client
- * to start the test
- */
- kill(pid, SIGUSR1);
- client_sd = accept(sd, (struct sockaddr *) &addr, &addr_len);
- if (client_sd == -1) {
- test_fail("accept");
- }
- memset(buf, '\0', BUFSIZE);
- rc = read(client_sd, buf, BUFSIZE);
- if (rc == -1) {
- test_fail("read");
- }
- if (strcmp("Hello, My Name is Client.", buf) != 0) {
- test_fail("didn't read the correct string");
- }
- /* added for extra fun to make the client block on read() */
- sleep(1);
- bzero(buf, BUFSIZE);
- snprintf(buf, BUFSIZE-1, "Hello, My Name is Server.");
- rc = write(client_sd, buf, strlen(buf) + 1);
- if (rc == -1) {
- test_fail("write");
- }
- rc = close(client_sd);
- if (rc == -1) {
- test_fail("close");
- }
- }
- rc = close(sd);
- if (rc == -1) {
- test_fail("close");
- }
- /* wait for client to exit */
- do {
- errno = 0;
- rc = waitpid(pid, &status, 0);
- } while (rc == -1 && errno == EINTR);
- /* we use the exit status to get its error count */
- errct += WEXITSTATUS(status);
- }
- void test_simple_client_server(int type)
- {
- pid_t pid;
- debug("test_simple_client_server()");
- UNLINK(TEST_SUN_PATH);
- /* the signal handler is only used by the client, but we have to
- * install it now. if we don't the server may signal the client
- * before the handler is installed.
- */
- debug("installing signal handler");
- if (signal(SIGUSR1, test_xfer_sighdlr) == SIG_ERR) {
- test_fail("signal(SIGUSR1, test_xfer_sighdlr) failed");
- }
- debug("signal handler installed");
- server_ready = 0;
- pid = fork();
- if (pid == -1) {
- test_fail("fork() failed");
- return;
- } else if (pid == 0) {
- debug("child");
- test_simple_client(type);
- test_fail("we should never get here");
- exit(1);
- } else {
- debug("parent");
- test_simple_server(type, pid);
- debug("parent done");
- }
- UNLINK(TEST_SUN_PATH);
- }
- void test_vectorio(int type)
- {
- int sv[2];
- int rc;
- struct iovec iov[3];
- char buf1[BUFSIZE];
- char buf2[BUFSIZE];
- char buf3[BUFSIZE];
- char buf4[BUFSIZE*3];
- const struct iovec *iovp = iov;
- debug("begin vectorio tests");
- memset(buf1, '\0', BUFSIZE);
- strncpy(buf1, "HELLO ", BUFSIZE - 1);
- memset(buf2, '\0', BUFSIZE);
- strncpy(buf2, "WORLD", BUFSIZE - 1);
- memset(buf3, '\0', BUFSIZE);
- rc = socketpair(PF_UNIX, type, 0, sv);
- if (rc == -1) {
- test_fail("socketpair");
- }
- iov[0].iov_base = buf1;
- iov[0].iov_len = strlen(buf1);
- iov[1].iov_base = buf2;
- iov[1].iov_len = strlen(buf2);
- iov[2].iov_base = buf3;
- iov[2].iov_len = 1;
- rc = writev(sv[0], iovp, 3);
- if (rc == -1) {
- test_fail("writev");
- }
- memset(buf4, '\0', BUFSIZE*3);
- rc = read(sv[1], buf4, BUFSIZE*3);
- if (rc == -1) {
- test_fail("read");
- }
- if (strncmp(buf4, "HELLO WORLD", strlen("HELLO WORLD"))) {
- test_fail("the string we read was not 'HELLO WORLD'");
- }
- memset(buf1, '\0', BUFSIZE);
- strncpy(buf1, "Unit Test Time", BUFSIZE - 1);
- rc = write(sv[1], buf1, strlen(buf1) + 1);
- if (rc == -1) {
- test_fail("write");
- }
- memset(buf2, '\0', BUFSIZE);
- memset(buf3, '\0', BUFSIZE);
- memset(buf4, '\0', BUFSIZE*3);
- iov[0].iov_base = buf2;
- iov[0].iov_len = 5;
- iov[1].iov_base = buf3;
- iov[1].iov_len = 5;
- iov[2].iov_base = buf4;
- iov[2].iov_len = 32;
- rc = readv(sv[0], iovp, 3);
- if (rc == -1) {
- test_fail("readv");
- }
- if (strncmp(buf2, "Unit ", 5) || strncmp(buf3, "Test ", 5) ||
- strncmp(buf4, "Time", 4)) {
- test_fail("readv");
- }
- rc = close(sv[0]);
- if (rc == -1) {
- test_fail("close");
- }
- rc = close(sv[1]);
- if (rc == -1) {
- test_fail("close");
- }
- debug("done vector io tests");
- }
- void test_msg(int type)
- {
- int sv[2];
- int rc;
- struct msghdr msg1;
- struct msghdr msg2;
- struct iovec iov[3];
- char buf1[BUFSIZE];
- char buf2[BUFSIZE];
- char buf3[BUFSIZE];
- char buf4[BUFSIZE*3];
- debug("begin sendmsg/recvmsg tests");
- memset(buf1, '\0', BUFSIZE);
- strncpy(buf1, "HELLO ", BUFSIZE - 1);
- memset(buf2, '\0', BUFSIZE);
- strncpy(buf2, "WORLD", BUFSIZE - 1);
- memset(buf3, '\0', BUFSIZE);
- rc = socketpair(PF_UNIX, type, 0, sv);
- if (rc == -1) {
- test_fail("socketpair");
- }
- iov[0].iov_base = buf1;
- iov[0].iov_len = strlen(buf1);
- iov[1].iov_base = buf2;
- iov[1].iov_len = strlen(buf2);
- iov[2].iov_base = buf3;
- iov[2].iov_len = 1;
- memset(&msg1, '\0', sizeof(struct msghdr));
- msg1.msg_name = NULL;
- msg1.msg_namelen = 0;
- msg1.msg_iov = iov;
- msg1.msg_iovlen = 3;
- msg1.msg_control = NULL;
- msg1.msg_controllen = 0;
- msg1.msg_flags = 0;
- rc = sendmsg(sv[0], &msg1, 0);
- if (rc == -1) {
- test_fail("writev");
- }
- memset(buf4, '\0', BUFSIZE*3);
- rc = read(sv[1], buf4, BUFSIZE*3);
- if (rc == -1) {
- test_fail("read");
- }
- if (strncmp(buf4, "HELLO WORLD", strlen("HELLO WORLD"))) {
- test_fail("the string we read was not 'HELLO WORLD'");
- }
- memset(buf1, '\0', BUFSIZE);
- strncpy(buf1, "Unit Test Time", BUFSIZE - 1);
- rc = write(sv[1], buf1, strlen(buf1) + 1);
- if (rc == -1) {
- test_fail("write");
- }
- memset(buf2, '\0', BUFSIZE);
- memset(buf3, '\0', BUFSIZE);
- memset(buf4, '\0', BUFSIZE*3);
- iov[0].iov_base = buf2;
- iov[0].iov_len = 5;
- iov[1].iov_base = buf3;
- iov[1].iov_len = 5;
- iov[2].iov_base = buf4;
- iov[2].iov_len = 32;
- memset(&msg2, '\0', sizeof(struct msghdr));
- msg2.msg_name = NULL;
- msg2.msg_namelen = 0;
- msg2.msg_iov = iov;
- msg2.msg_iovlen = 3;
- msg2.msg_control = NULL;
- msg2.msg_controllen = 0;
- msg2.msg_flags = 0;
- rc = recvmsg(sv[0], &msg2, 0);
- if (rc == -1) {
- test_fail("readv");
- }
- if (strncmp(buf2, "Unit ", 5) || strncmp(buf3, "Test ", 5) ||
- strncmp(buf4, "Time", 4)) {
- test_fail("readv");
- }
- rc = close(sv[0]);
- if (rc == -1) {
- test_fail("close");
- }
- rc = close(sv[1]);
- if (rc == -1) {
- test_fail("close");
- }
- }
- void test_msg_dgram(void)
- {
- int rc;
- int src;
- int dst;
- struct sockaddr_un addr;
- struct iovec iov[3];
- struct msghdr msg1;
- struct msghdr msg2;
- char buf1[BUFSIZE];
- char buf2[BUFSIZE];
- char buf3[BUFSIZE];
- socklen_t addrlen = sizeof(struct sockaddr_un);
- debug("test msg_dgram");
- UNLINK(TEST_SUN_PATH);
- UNLINK(TEST_SUN_PATHB);
- src = socket(PF_UNIX, SOCK_DGRAM, 0);
- if (src == -1) {
- test_fail("socket");
- }
- dst = socket(PF_UNIX, SOCK_DGRAM, 0);
- if (dst == -1) {
- test_fail("socket");
- }
- memset(&addr, '\0', sizeof(struct sockaddr_un));
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, TEST_SUN_PATHB, sizeof(addr.sun_path) - 1);
- rc = bind(src, (struct sockaddr *) &addr, addrlen);
- if (rc == -1) {
- test_fail("bind");
- }
- memset(&addr, '\0', sizeof(struct sockaddr_un));
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, TEST_SUN_PATH, sizeof(addr.sun_path) - 1);
- rc = bind(dst, (struct sockaddr *) &addr, addrlen);
- if (rc == -1) {
- test_fail("bind");
- }
- memset(&buf1, '\0', BUFSIZE);
- memset(&buf2, '\0', BUFSIZE);
- memset(&buf3, '\0', BUFSIZE);
- strncpy(buf1, "Minix ", BUFSIZE-1);
- strncpy(buf2, "is ", BUFSIZE-1);
- strncpy(buf3, "great!", BUFSIZE-1);
- iov[0].iov_base = buf1;
- iov[0].iov_len = 6;
- iov[1].iov_base = buf2;
- iov[1].iov_len = 3;
- iov[2].iov_base = buf3;
- iov[2].iov_len = 32;
- memset(&msg1, '\0', sizeof(struct msghdr));
- msg1.msg_name = &addr;
- msg1.msg_namelen = addrlen;
- msg1.msg_iov = iov;
- msg1.msg_iovlen = 3;
- msg1.msg_control = NULL;
- msg1.msg_controllen = 0;
- msg1.msg_flags = 0;
- rc = sendmsg(src, &msg1, 0);
- if (rc == -1) {
- test_fail("sendmsg");
- }
- memset(&buf1, '\0', BUFSIZE);
- memset(&buf2, '\0', BUFSIZE);
- iov[0].iov_base = buf1;
- iov[0].iov_len = 9;
- iov[1].iov_base = buf2;
- iov[1].iov_len = 32;
- memset(&addr, '\0', sizeof(struct sockaddr_un));
- memset(&msg2, '\0', sizeof(struct msghdr));
- msg2.msg_name = &addr;
- msg2.msg_namelen = sizeof(struct sockaddr_un);
- msg2.msg_iov = iov;
- msg2.msg_iovlen = 2;
- msg2.msg_control = NULL;
- msg2.msg_controllen = 0;
- msg2.msg_flags = 0;
- rc = recvmsg(dst, &msg2, 0);
- if (rc == -1) {
- test_fail("recvmsg");
- }
- if (strncmp(buf1, "Minix is ", 9) || strncmp(buf2, "great!", 6)) {
- test_fail("recvmsg");
- }
- /* we need to use the full path "/usr/src/test/DIR_56/testb.sock"
- * because that is what is returned by recvmsg().
- */
- if (addr.sun_family != AF_UNIX || strcmp(addr.sun_path,
- fullpath(TEST_SUN_PATHB))) {
- test_fail("recvmsg");
- }
- rc = close(dst);
- if (rc == -1) {
- test_fail("close");
- }
- rc = close(src);
- if (rc == -1) {
- test_fail("close");
- }
- UNLINK(TEST_SUN_PATH);
- UNLINK(TEST_SUN_PATHB);
- }
- void test_scm_credentials(void)
- {
- int rc;
- int src;
- int dst;
- struct ucred cred;
- struct cmsghdr *cmsg = NULL;
- struct sockaddr_un addr;
- struct iovec iov[3];
- struct msghdr msg1;
- struct msghdr msg2;
- char buf1[BUFSIZE];
- char buf2[BUFSIZE];
- char buf3[BUFSIZE];
- char ctrl[BUFSIZE];
- socklen_t addrlen = sizeof(struct sockaddr_un);
- debug("test_scm_credentials");
- UNLINK(TEST_SUN_PATH);
- UNLINK(TEST_SUN_PATHB);
- debug("creating src socket");
- src = socket(PF_UNIX, SOCK_DGRAM, 0);
- if (src == -1) {
- test_fail("socket");
- }
- debug("creating dst socket");
- dst = socket(PF_UNIX, SOCK_DGRAM, 0);
- if (dst == -1) {
- test_fail("socket");
- }
- debug("binding src socket");
- memset(&addr, '\0', sizeof(struct sockaddr_un));
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, TEST_SUN_PATHB, sizeof(addr.sun_path) - 1);
- rc = bind(src, (struct sockaddr *) &addr, addrlen);
- if (rc == -1) {
- test_fail("bind");
- }
- debug("binding dst socket");
- memset(&addr, '\0', sizeof(struct sockaddr_un));
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, TEST_SUN_PATH, sizeof(addr.sun_path) - 1);
- rc = bind(dst, (struct sockaddr *) &addr, addrlen);
- if (rc == -1) {
- test_fail("bind");
- }
- memset(&buf1, '\0', BUFSIZE);
- memset(&buf2, '\0', BUFSIZE);
- memset(&buf3, '\0', BUFSIZE);
- memset(&ctrl, '\0', BUFSIZE);
- strncpy(buf1, "Minix ", BUFSIZE-1);
- strncpy(buf2, "is ", BUFSIZE-1);
- strncpy(buf3, "great!", BUFSIZE-1);
- iov[0].iov_base = buf1;
- iov[0].iov_len = 6;
- iov[1].iov_base = buf2;
- iov[1].iov_len = 3;
- iov[2].iov_base = buf3;
- iov[2].iov_len = 32;
- memset(&msg1, '\0', sizeof(struct msghdr));
- msg1.msg_name = &addr;
- msg1.msg_namelen = addrlen;
- msg1.msg_iov = iov;
- msg1.msg_iovlen = 3;
- msg1.msg_control = NULL;
- msg1.msg_controllen = 0;
- msg1.msg_flags = 0;
- debug("sending msg1");
- rc = sendmsg(src, &msg1, 0);
- if (rc == -1) {
- test_fail("sendmsg");
- }
- memset(&buf1, '\0', BUFSIZE);
- memset(&buf2, '\0', BUFSIZE);
- memset(&buf3, '\0', BUFSIZE);
- memset(&ctrl, '\0', BUFSIZE);
- iov[0].iov_base = buf1;
- iov[0].iov_len = 9;
- iov[1].iov_base = buf2;
- iov[1].iov_len = 32;
- memset(&addr, '\0', sizeof(struct sockaddr_un));
- memset(&msg2, '\0', sizeof(struct msghdr));
- msg2.msg_name = &addr;
- msg2.msg_namelen = sizeof(struct sockaddr_un);
- msg2.msg_iov = iov;
- msg2.msg_iovlen = 2;
- msg2.msg_control = ctrl;
- msg2.msg_controllen = BUFSIZE;
- msg2.msg_flags = 0;
- debug("recv msg2");
- rc = recvmsg(dst, &msg2, 0);
- if (rc == -1) {
- test_fail("recvmsg");
- }
- debug("checking results");
- if (strncmp(buf1, "Minix is ", 9) || strncmp(buf2, "great!", 6)) {
- test_fail("recvmsg");
- }
- /* we need to use the full path "/usr/src/test/DIR_56/testb.sock"
- * because that is what is returned by recvmsg().
- */
- if (addr.sun_family != AF_UNIX || strcmp(addr.sun_path,
- fullpath(TEST_SUN_PATHB))) {
- test_fail("recvmsg");
- }
- debug("looking for credentials");
- memset(&cred, '\0', sizeof(struct ucred));
- for (cmsg = CMSG_FIRSTHDR(&msg2); cmsg != NULL;
- cmsg = CMSG_NXTHDR(&msg2, cmsg)) {
- if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_CREDENTIALS) {
- memcpy(&cred, CMSG_DATA(cmsg), sizeof(struct ucred));
- break;
- }
- }
- if (cred.pid != getpid() || cred.uid != geteuid() ||
- cred.gid != getegid()) {
- test_fail("did no receive the proper credentials");
- }
- rc = close(dst);
- if (rc == -1) {
- test_fail("close");
- }
- rc = close(src);
- if (rc == -1) {
- test_fail("close");
- }
- UNLINK(TEST_SUN_PATH);
- UNLINK(TEST_SUN_PATHB);
- }
- void test_connect(void)
- {
- int i, sd, sds[2], rc;
- /* connect() is already tested throughout test56, but
- * in most cases the client and server end up on /dev/uds
- * minor 0 and minor 1. This test opens some sockets first and
- * then calls test_simple_client_server(). This forces the
- * client and server minor numbers higher in the descriptor table.
- */
- debug("starting test_connect()");
- sd = socket(AF_UNIX, SOCK_DGRAM, 0);
- if (sd == -1) {
- test_fail("couldn't create a socket");
- }
- rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sds);
- if (rc == -1) {
- test_fail("couldn't create a socketpair");
- }
- for (i = 0; i < 3; i++) {
- test_simple_client_server(types[i]);
- }
- rc = close(sds[1]);
- if (rc == -1) {
- test_fail("close() failed");
- }
- rc = close(sds[0]);
- if (rc == -1) {
- test_fail("close() failed");
- }
- rc = close(sd);
- if (rc == -1) {
- test_fail("close() failed");
- }
- debug("exiting test_connect()");
- }
- int test_multiproc_read(void)
- {
- /* test that when we fork() a process with an open socket descriptor,
- * the descriptor in each process points to the same thing.
- */
- pid_t pid;
- int sds[2];
- int rc, status;
- char buf[3];
- debug("entering test_multiproc_read()");
- rc = socketpair(PF_UNIX, SOCK_STREAM, 0, sds);
- if (rc == -1) {
- test_fail("socketpair");
- return 1;
- }
- memset(buf, '\0', 3);
- /* the signal handler is only used by the client, but we have to
- * install it now. if we don't the server may signal the client
- * before the handler is installed.
- */
- debug("installing signal handler");
- if (signal(SIGUSR1, test_xfer_sighdlr) == SIG_ERR) {
- test_fail("signal(SIGUSR1, test_xfer_sighdlr) failed");
- return 1;
- }
- debug("signal handler installed");
- server_ready = 0;
- pid = fork();
- if (pid == -1) {
- test_fail("fork");
- return 1;
- } else if (pid == 0) {
- while (server_ready == 0) {
- debug("waiting for SIGUSR1 from parent");
- sleep(1);
- }
- rc = read(sds[1], buf, 2);
- if (rc == -1) {
- test_fail("read");
- exit(1);
- }
- if (!(buf[0] == 'X' && buf[1] == '3')) {
- test_fail("Didn't read X3");
- exit(1);
- }
- exit(0);
- } else {
- rc = write(sds[0], "MNX3", 4);
- if (rc == -1) {
- test_fail("write");
- }
- rc = read(sds[1], buf, 2);
- if (rc == -1) {
- test_fail("read");
- }
- if (!(buf[0] == 'M' && buf[1] == 'N')) {
- test_fail("Didn't read MN");
- }
- /* time to tell the client to start the test */
- kill(pid, SIGUSR1);
- do {
- rc = waitpid(pid, &status, 0);
- } while (rc == -1 && errno == EINTR);
- /* we use the exit status to get its error count */
- errct += WEXITSTATUS(status);
- }
- return 0;
- }
- int test_multiproc_write(void)
- {
- /* test that when we fork() a process with an open socket descriptor,
- * the descriptor in each process points to the same thing.
- */
- pid_t pid;
- int sds[2];
- int rc, status;
- char buf[7];
- debug("entering test_multiproc_write()");
- rc = socketpair(PF_UNIX, SOCK_STREAM, 0, sds);
- if (rc == -1) {
- test_fail("socketpair");
- return 1;
- }
- memset(buf, '\0', 7);
- /* the signal handler is only used by the client, but we have to
- * install it now. if we don't the server may signal the client
- * before the handler is installed.
- */
- debug("installing signal handler");
- if (signal(SIGUSR1, test_xfer_sighdlr) == SIG_ERR) {
- test_fail("signal(SIGUSR1, test_xfer_sighdlr) failed");
- return 1;
- }
- debug("signal handler installed");
- server_ready = 0;
- pid = fork();
- if (pid == -1) {
- test_fail("fork");
- return 1;
- } else if (pid == 0) {
- while (server_ready == 0) {
- debug("waiting for SIGUSR1 from paren…
Large files files are truncated, but you can click here to view the full file