bin/131567: Update for regression/sockets/unix_cmsg
Andrey Simonenko
simon at comsys.ntu-kpi.kiev.ua
Mon Oct 1 11:30:10 UTC 2012
The following reply was made to PR bin/131567; it has been noted by GNATS.
From: Andrey Simonenko <simon at comsys.ntu-kpi.kiev.ua>
To: bug-followup at freebsd.org
Cc:
Subject: Re: bin/131567: Update for regression/sockets/unix_cmsg
Date: Mon, 1 Oct 2012 14:20:11 +0300
Updated unix_cmsg: all assert() were removed.
Verified correctness of unix_cmsg on 9.1-PRERELEASE and 10-CURRENT.
diff -ruNp unix_cmsg.orig/README unix_cmsg/README
--- unix_cmsg.orig/README 2006-05-29 21:40:55.000000000 +0300
+++ unix_cmsg/README 2012-10-01 13:47:51.000000000 +0300
@@ -1,7 +1,7 @@
$FreeBSD: src/tools/regression/sockets/unix_cmsg/README,v 1.1 2006/05/29 18:40:55 maxim Exp $
About unix_cmsg
-================
+===============
This program is a collection of regression tests for ancillary (control)
data for PF_LOCAL sockets (local domain or Unix domain sockets). There
@@ -13,8 +13,8 @@ is correct in received message. Sometim
messages to Server.
It is better to change the owner of unix_cmsg to some safe user
-(eg. nobody:nogroup) and set SUID and SGID bits, else some tests
-can give correct results for wrong implementation.
+(eg. nobody:nogroup) and set SUID and SGID bits, else some tests that
+check credentials can give correct results for wrong implementation.
Available options
=================
@@ -24,13 +24,13 @@ Available options
-h Output help message and exit.
--t <socktype>
+-t socktype
Run tests only for the given socket type: "stream" or "dgram".
With this option it is possible to run only particular test,
not all of them.
-z Do not send real control data if possible. Struct cmsghdr{}
- should be followed by real control data. It is not clear if
+ should be followed by real control data. It is not clear whether
a sender should give control data in all cases (this is not
documented and an arbitrary application can choose anything).
@@ -90,6 +90,13 @@ For SOCK_STREAM sockets:
message with data and control message with SCM_TIMESTAMP type
followed by struct timeval{}.
+ 6: Check LOCAL_PEERCRED socket option
+
+ This test does not use control data for PF_LOCAL sockets, but can be
+ implemented here. Client connects to Server. Both Client and Server
+ verify that credentials of the peer are correct using LOCAL_PEERCRED
+ socket option.
+
For SOCK_DGRAM sockets:
----------------------
@@ -110,7 +117,7 @@ For SOCK_DGRAM sockets:
structure should contain correct information.
3: Sending cmsgcred, receiving sockcred
-
+
Server creates datagram socket and set socket option LOCAL_CREDS
for it. Client sends one message with data and control message with
SOCK_CREDS type to Server. Server should receive one message with
@@ -124,4 +131,4 @@ For SOCK_DGRAM sockets:
message with SCM_TIMESTAMP type followed by struct timeval{}.
- Andrey Simonenko
-simon at comsys.ntu-kpi.kiev.ua
+andreysimonenko at users.sourceforge.net
diff -ruNp unix_cmsg.orig/unix_cmsg.c unix_cmsg/unix_cmsg.c
--- unix_cmsg.orig/unix_cmsg.c 2006-05-31 11:10:34.000000000 +0300
+++ unix_cmsg/unix_cmsg.c 2012-10-01 13:49:59.000000000 +0300
@@ -27,27 +27,28 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/tools/regression/sockets/unix_cmsg/unix_cmsg.c,v 1.2 2006/05/31 08:10:34 maxim Exp $");
-#include <sys/types.h>
+#include <sys/param.h>
#include <sys/resource.h>
#include <sys/time.h>
+#include <sys/select.h>
#include <sys/socket.h>
+#include <sys/ucred.h>
#include <sys/un.h>
#include <sys/wait.h>
-#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
+#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
-#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sysexits.h>
#include <unistd.h>
/*
@@ -68,7 +69,7 @@ __FBSDID("$FreeBSD: src/tools/regression
*
* Each function which can block, is run under TIMEOUT, if timeout
* occurs, then test function returns -2 or a client process exits
- * with nonzero return code.
+ * with non-zero return code.
*/
#ifndef LISTENQ
@@ -76,46 +77,88 @@ __FBSDID("$FreeBSD: src/tools/regression
#endif
#ifndef TIMEOUT
-# define TIMEOUT 60
+# define TIMEOUT 5
#endif
#define EXTRA_CMSG_SPACE 512 /* Memory for not expected control data. */
-static int t_cmsgcred(void), t_sockcred_stream1(void);
-static int t_sockcred_stream2(void), t_cmsgcred_sockcred(void);
-static int t_sockcred_dgram(void), t_timestamp(void);
+static int t_cmsgcred(void);
+static int t_sockcred_stream1(void);
+static int t_sockcred_stream2(void);
+static int t_cmsgcred_sockcred(void);
+static int t_sockcred_dgram(void);
+static int t_timestamp(void);
+static int t_peercred(void);
struct test_func {
- int (*func)(void); /* Pointer to function. */
- const char *desc; /* Test description. */
+ int (*func)(void); /* Pointer to function. */
+ const char *desc; /* Test description. */
};
-static struct test_func test_stream_tbl[] = {
- { NULL, " 0: All tests" },
- { t_cmsgcred, " 1: Sending, receiving cmsgcred" },
- { t_sockcred_stream1, " 2: Receiving sockcred (listening socket has LOCAL_CREDS)" },
- { t_sockcred_stream2, " 3: Receiving sockcred (accepted socket has LOCAL_CREDS)" },
- { t_cmsgcred_sockcred, " 4: Sending cmsgcred, receiving sockcred" },
- { t_timestamp, " 5: Sending, receiving timestamp" },
- { NULL, NULL }
+static const struct test_func test_stream_tbl[] = {
+ {
+ .func = NULL,
+ .desc = "All tests"
+ },
+ {
+ .func = t_cmsgcred,
+ .desc = "Sending, receiving cmsgcred"
+ },
+ {
+ .func = t_sockcred_stream1,
+ .desc = "Receiving sockcred (listening socket has LOCAL_CREDS)"
+ },
+ {
+ .func = t_sockcred_stream2,
+ .desc = "Receiving sockcred (accepted socket has LOCAL_CREDS)"
+ },
+ {
+ .func = t_cmsgcred_sockcred,
+ .desc = "Sending cmsgcred, receiving sockcred"
+ },
+ {
+ .func = t_timestamp,
+ .desc = "Sending, receiving timestamp"
+ },
+ {
+ .func = t_peercred,
+ .desc = "Check LOCAL_PEERCRED socket option"
+ }
};
-static struct test_func test_dgram_tbl[] = {
- { NULL, " 0: All tests" },
- { t_cmsgcred, " 1: Sending, receiving cmsgcred" },
- { t_sockcred_dgram, " 2: Receiving sockcred" },
- { t_cmsgcred_sockcred, " 3: Sending cmsgcred, receiving sockcred" },
- { t_timestamp, " 4: Sending, receiving timestamp" },
- { NULL, NULL }
+#define TEST_STREAM_TBL_SIZE \
+ (sizeof(test_stream_tbl) / sizeof(test_stream_tbl[0]))
+
+static const struct test_func test_dgram_tbl[] = {
+ {
+ .func = NULL,
+ .desc = "All tests"
+ },
+ {
+ .func = t_cmsgcred,
+ .desc = "Sending, receiving cmsgcred"
+ },
+ {
+ .func = t_sockcred_dgram,
+ .desc = "Receiving sockcred"
+ },
+ {
+ .func = t_cmsgcred_sockcred,
+ .desc = "Sending cmsgcred, receiving sockcred"
+ },
+ {
+ .func = t_timestamp,
+ .desc = "Sending, receiving timestamp"
+ }
};
-#define TEST_STREAM_NO_MAX (sizeof(test_stream_tbl) / sizeof(struct test_func) - 2)
-#define TEST_DGRAM_NO_MAX (sizeof(test_dgram_tbl) / sizeof(struct test_func) - 2)
+#define TEST_DGRAM_TBL_SIZE \
+ (sizeof(test_dgram_tbl) / sizeof(test_dgram_tbl[0]))
-static const char *myname = "SERVER"; /* "SERVER" or "CLIENT" */
+static const char *myname; /* "SERVER" or "CLIENT" */
-static int debug = 0; /* 1, if -d. */
-static int no_control_data = 0; /* 1, if -z. */
+static bool debug = false; /* -d */
+static bool no_control_data = false;/* -z */
static u_int nfailed = 0; /* Number of failed tests. */
@@ -131,17 +174,11 @@ static char ipc_message[] = "hello";
static struct sockaddr_un servaddr; /* Server address. */
-static sigjmp_buf env_alrm;
-
static uid_t my_uid;
static uid_t my_euid;
static gid_t my_gid;
static gid_t my_egid;
-/*
- * my_gids[0] is EGID, next items are supplementary GIDs,
- * my_ngids determines valid items in my_gids array.
- */
static gid_t my_gids[NGROUPS_MAX];
static int my_ngids;
@@ -150,38 +187,35 @@ static pid_t client_pid; /* PID of fork
#define dbgmsg(x) do { \
if (debug) \
logmsgx x ; \
-} while (/* CONSTCOND */0)
+} while (0)
static void logmsg(const char *, ...) __printflike(1, 2);
static void logmsgx(const char *, ...) __printflike(1, 2);
static void output(const char *, ...) __printflike(1, 2);
-extern char *__progname; /* The name of program. */
-
/*
* Output the help message (-h switch).
*/
static void
-usage(int quick)
+usage(bool verbose)
{
- const struct test_func *test_func;
+ u_int i;
- fprintf(stderr, "Usage: %s [-dhz] [-t <socktype>] [testno]\n",
- __progname);
- if (quick)
+ fprintf(stderr, "usage: %s [-dhz] [-t socktype] [testno]\n",
+ getprogname());
+ if (!verbose)
return;
fprintf(stderr, "\n Options are:\n\
-d\t\t\tOutput debugging information\n\
-h\t\t\tOutput this help message and exit\n\
- -t <socktype>\t\tRun test only for the given socket type:\n\
-\t\t\tstream or dgram\n\
+ -t socktype\t\tRun test only for socket type: stream or dgram\n\
-z\t\t\tDo not send real control data if possible\n\n");
fprintf(stderr, " Available tests for stream sockets:\n");
- for (test_func = test_stream_tbl; test_func->desc != NULL; ++test_func)
- fprintf(stderr, " %s\n", test_func->desc);
+ for (i = 0; i < TEST_STREAM_TBL_SIZE; ++i)
+ fprintf(stderr, " %u: %s\n", i, test_stream_tbl[i].desc);
fprintf(stderr, "\n Available tests for datagram sockets:\n");
- for (test_func = test_dgram_tbl; test_func->desc != NULL; ++test_func)
- fprintf(stderr, " %s\n", test_func->desc);
+ for (i = 0; i < TEST_DGRAM_TBL_SIZE; ++i)
+ fprintf(stderr, " %u: %s\n", i, test_dgram_tbl[i].desc);
}
/*
@@ -195,7 +229,7 @@ output(const char *format, ...)
va_start(ap, format);
if (vsnprintf(buf, sizeof(buf), format, ap) < 0)
- err(EX_SOFTWARE, "output: vsnprintf failed");
+ err(EXIT_FAILURE, "output: vsnprintf failed");
write(STDOUT_FILENO, buf, strlen(buf));
va_end(ap);
}
@@ -210,18 +244,16 @@ logmsg(const char *format, ...)
va_list ap;
int errno_save;
- errno_save = errno; /* Save errno. */
-
+ errno_save = errno;
va_start(ap, format);
if (vsnprintf(buf, sizeof(buf), format, ap) < 0)
- err(EX_SOFTWARE, "logmsg: vsnprintf failed");
+ err(EXIT_FAILURE, "logmsg: vsnprintf failed");
if (errno_save == 0)
output("%s: %s\n", myname, buf);
else
output("%s: %s: %s\n", myname, buf, strerror(errno_save));
va_end(ap);
-
- errno = errno_save; /* Restore errno. */
+ errno = errno_save;
}
/*
@@ -235,33 +267,47 @@ logmsgx(const char *format, ...)
va_start(ap, format);
if (vsnprintf(buf, sizeof(buf), format, ap) < 0)
- err(EX_SOFTWARE, "logmsgx: vsnprintf failed");
+ err(EXIT_FAILURE, "logmsgx: vsnprintf failed");
output("%s: %s\n", myname, buf);
va_end(ap);
}
/*
- * Run tests from testno1 to testno2.
+ * Run tests for the given socket type.
*/
static int
-run_tests(u_int testno1, u_int testno2)
+run_tests(int type, u_int testno1)
{
- const struct test_func *test_func;
- u_int i, nfailed1;
+ const struct test_func *tf;
+ u_int i, nfailed1, testno2;
- output("Running tests for %s sockets:\n", sock_type_str);
- test_func = (sock_type == SOCK_STREAM ?
- test_stream_tbl : test_dgram_tbl) + testno1;
+ sock_type = type;
+ if (type == SOCK_STREAM) {
+ sock_type_str = "SOCK_STREAM";
+ tf = test_stream_tbl;
+ i = TEST_STREAM_TBL_SIZE - 1;
+ } else {
+ sock_type_str = "SOCK_DGRAM";
+ tf = test_dgram_tbl;
+ i = TEST_DGRAM_TBL_SIZE - 1;
+ }
+ if (testno1 == 0) {
+ testno1 = 1;
+ testno2 = i;
+ } else
+ testno2 = testno1;
+ output("Running tests for %s sockets:\n", sock_type_str);
nfailed1 = 0;
- for (i = testno1; i <= testno2; ++test_func, ++i) {
- output(" %s\n", test_func->desc);
- switch (test_func->func()) {
+ for (i = testno1, tf += testno1; i <= testno2; ++tf, ++i) {
+ output(" %u: %s\n", i, tf->desc);
+ switch (tf->func()) {
case -1:
++nfailed1;
break;
case -2:
- logmsgx("some system error occurred, exiting");
+ logmsgx("some system error or timeout occurred, "
+ "exiting");
return (-1);
}
}
@@ -284,181 +330,222 @@ run_tests(u_int testno1, u_int testno2)
return (0);
}
-/* ARGSUSED */
+/*
+ * Initialize signals handlers.
+ */
static void
-sig_alrm(int signo __unused)
+sig_init(void)
{
- siglongjmp(env_alrm, 1);
+ struct sigaction sigact;
+
+ sigact.sa_handler = SIG_IGN;
+ sigact.sa_flags = 0;
+ sigemptyset(&sigact.sa_mask);
+ if (sigaction(SIGPIPE, &sigact, (struct sigaction *)NULL) < 0)
+ err(EXIT_FAILURE, "sigaction(SIGPIPE)");
}
/*
- * Initialize signals handlers.
+ * Output this process UID, GID, groups from getgroups(), EUID and EGID.
*/
static void
-sig_init(void)
+show_my_id(void)
{
- struct sigaction sa;
+ int i;
- sa.sa_handler = SIG_IGN;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- if (sigaction(SIGPIPE, &sa, (struct sigaction *)NULL) < 0)
- err(EX_OSERR, "sigaction(SIGPIPE)");
-
- sa.sa_handler = sig_alrm;
- if (sigaction(SIGALRM, &sa, (struct sigaction *)NULL) < 0)
- err(EX_OSERR, "sigaction(SIGALRM)");
+ if (!debug)
+ return;
+ logmsgx("UID %lu, GID %lu, groups from getgroups():",
+ (u_long)my_uid, (u_long)my_gid);
+ for (i = 0; i < my_ngids; ++i)
+ logmsgx(" GID %lu", (u_long)my_gids[i]);
+ logmsgx("EUID %lu, EGID %lu", (u_long)my_euid, (u_long)my_egid);
+}
+
+static int
+fork_client(void)
+{
+ client_pid = fork();
+ if (client_pid == 0)
+ myname = "CLIENT";
+ else if (client_pid == (pid_t)-1) {
+ logmsg("fork");
+ return (-1);
+ }
+ return (0);
}
int
main(int argc, char *argv[])
{
const char *errstr;
- int opt, dgramflag, streamflag;
- u_int testno1, testno2;
+ u_int testno;
+ int opt, rv;
+ bool dgramflag, streamflag;
- dgramflag = streamflag = 0;
+ dgramflag = streamflag = false;
while ((opt = getopt(argc, argv, "dht:z")) != -1)
switch (opt) {
case 'd':
- debug = 1;
+ debug = true;
break;
case 'h':
- usage(0);
- return (EX_OK);
+ usage(true);
+ return (EXIT_SUCCESS);
case 't':
if (strcmp(optarg, "stream") == 0)
- streamflag = 1;
+ streamflag = true;
else if (strcmp(optarg, "dgram") == 0)
- dgramflag = 1;
+ dgramflag = true;
else
- errx(EX_USAGE, "wrong socket type in -t option");
+ errx(EXIT_FAILURE, "option -t: "
+ "wrong socket type");
break;
case 'z':
- no_control_data = 1;
+ no_control_data = true;
break;
case '?':
default:
- usage(1);
- return (EX_USAGE);
+ usage(false);
+ return (EXIT_FAILURE);
}
if (optind < argc) {
if (optind + 1 != argc)
- errx(EX_USAGE, "too many arguments");
- testno1 = strtonum(argv[optind], 0, UINT_MAX, &errstr);
+ errx(EXIT_FAILURE, "too many arguments");
+ testno = strtonum(argv[optind], 0, UINT_MAX, &errstr);
if (errstr != NULL)
- errx(EX_USAGE, "wrong test number: %s", errstr);
+ errx(EXIT_FAILURE, "wrong test number: %s", errstr);
} else
- testno1 = 0;
+ testno = 0;
- if (dgramflag == 0 && streamflag == 0)
- dgramflag = streamflag = 1;
+ if (!dgramflag && !streamflag)
+ dgramflag = streamflag = true;
- if (dgramflag && streamflag && testno1 != 0)
- errx(EX_USAGE, "you can use particular test, only with datagram or stream sockets");
+ if (dgramflag && streamflag && testno != 0)
+ errx(EXIT_FAILURE, "you can use particular test, only "
+ "with datagram or stream sockets");
if (streamflag) {
- if (testno1 > TEST_STREAM_NO_MAX)
- errx(EX_USAGE, "given test %u for stream sockets does not exist",
- testno1);
+ if (testno >= TEST_STREAM_TBL_SIZE)
+ errx(EXIT_FAILURE, "given test %u for stream "
+ "sockets does not exist", testno);
} else {
- if (testno1 > TEST_DGRAM_NO_MAX)
- errx(EX_USAGE, "given test %u for datagram sockets does not exist",
- testno1);
+ if (testno >= TEST_DGRAM_TBL_SIZE)
+ errx(EXIT_FAILURE, "given test %u for datagram "
+ "sockets does not exist", testno);
}
my_uid = getuid();
my_euid = geteuid();
my_gid = getgid();
my_egid = getegid();
- switch (my_ngids = getgroups(sizeof(my_gids) / sizeof(my_gids[0]), my_gids)) {
+ my_ngids = getgroups(sizeof(my_gids) / sizeof(my_gids[0]), my_gids);
+ switch (my_ngids) {
case -1:
- err(EX_SOFTWARE, "getgroups");
+ err(EXIT_FAILURE, "getgroups");
/* NOTREACHED */
case 0:
- errx(EX_OSERR, "getgroups returned 0 groups");
+ errx(EXIT_FAILURE, "getgroups returned no groups");
}
sig_init();
if (mkdtemp(tempdir) == NULL)
- err(EX_OSERR, "mkdtemp");
+ err(EXIT_FAILURE, "mkdtemp");
- if (streamflag) {
- sock_type = SOCK_STREAM;
- sock_type_str = "SOCK_STREAM";
- if (testno1 == 0) {
- testno1 = 1;
- testno2 = TEST_STREAM_NO_MAX;
- } else
- testno2 = testno1;
- if (run_tests(testno1, testno2) < 0)
- goto failed;
- testno1 = 0;
- }
-
- if (dgramflag) {
- sock_type = SOCK_DGRAM;
- sock_type_str = "SOCK_DGRAM";
- if (testno1 == 0) {
- testno1 = 1;
- testno2 = TEST_DGRAM_NO_MAX;
- } else
- testno2 = testno1;
- if (run_tests(testno1, testno2) < 0)
- goto failed;
- }
+ myname = "SERVER";
+ rv = EXIT_SUCCESS;
+ show_my_id();
+ if (streamflag)
+ if (run_tests(SOCK_STREAM, testno) < 0)
+ rv = EXIT_FAILURE;
+ if (dgramflag && rv == EXIT_SUCCESS)
+ if (run_tests(SOCK_DGRAM, testno) < 0)
+ rv = EXIT_FAILURE;
if (rmdir(tempdir) < 0) {
logmsg("rmdir(%s)", tempdir);
- return (EX_OSERR);
+ rv = EXIT_FAILURE;
}
- return (nfailed ? EX_OSERR : EX_OK);
+ return (nfailed > 0 ? EXIT_FAILURE : rv);
+}
-failed:
- if (rmdir(tempdir) < 0)
- logmsg("rmdir(%s)", tempdir);
- return (EX_OSERR);
+/*
+ * Close socket descriptor, if sock_path is not equal to NULL,
+ * then unlink the given path.
+ */
+static int
+close_socket(const char *sock_path, int fd)
+{
+ int rv;
+
+ if (close(fd) < 0) {
+ logmsg("close_socket: close");
+ rv = -1;
+ } else
+ rv = 0;
+ if (sock_path != NULL)
+ if (unlink(sock_path) < 0) {
+ logmsg("close_socket: unlink(%s)", sock_path);
+ rv = -1;
+ }
+ return (rv);
}
/*
* Create PF_LOCAL socket, if sock_path is not equal to NULL, then
- * bind() it. Return socket address in addr. Return file descriptor
+ * bind() it. Return socket address in *un. Return file descriptor
* or -1 if some error occurred.
*/
static int
-create_socket(char *sock_path, size_t sock_path_len, struct sockaddr_un *addr)
+create_socket(char *sock_path, size_t sock_path_len, struct sockaddr_un *un)
{
- int rv, fd;
+ struct timeval tv;
+ int fd;
- if ((fd = socket(PF_LOCAL, sock_type, 0)) < 0) {
- logmsg("create_socket: socket(PF_LOCAL, %s, 0)", sock_type_str);
+ fd = socket(PF_LOCAL, sock_type, 0);
+ if (fd < 0) {
+ logmsg("create_socket: socket(PF_LOCAL, %s, 0)",
+ sock_type_str);
return (-1);
}
+ tv.tv_sec = TIMEOUT;
+ tv.tv_usec = 0;
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0 ||
+ setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) {
+ logmsg("create_socket: setsockopt(SO_RCVTIMEO/SO_SNDTIMEO)");
+ goto failed;
+ }
+
if (sock_path != NULL) {
- if ((rv = snprintf(sock_path, sock_path_len, "%s/%s",
- tempdir, myname)) < 0) {
+ int rv;
+
+ rv = snprintf(sock_path, sock_path_len, "%s/%s", tempdir,
+ myname);
+ if (rv < 0) {
logmsg("create_socket: snprintf failed");
goto failed;
}
if ((size_t)rv >= sock_path_len) {
- logmsgx("create_socket: too long path name for given buffer");
+ logmsgx("create_socket: too long path name for "
+ "given buffer");
goto failed;
}
-
- memset(addr, 0, sizeof(addr));
- addr->sun_family = AF_LOCAL;
- if (strlen(sock_path) >= sizeof(addr->sun_path)) {
- logmsgx("create_socket: too long path name (>= %lu) for local domain socket",
- (u_long)sizeof(addr->sun_path));
+ if (strlen(sock_path) >= sizeof(un->sun_path)) {
+ logmsgx("create_socket: too long path name (>= %zu) "
+ "for local domain socket", sizeof(un->sun_path));
goto failed;
}
- strcpy(addr->sun_path, sock_path);
- if (bind(fd, (struct sockaddr *)addr, SUN_LEN(addr)) < 0) {
+ memset(un, 0, sizeof(un));
+ un->sun_family = PF_LOCAL;
+ strcpy(un->sun_path, sock_path);
+ un->sun_len = SUN_LEN(un);
+
+ if (bind(fd, (struct sockaddr *)un, un->sun_len) < 0) {
logmsg("create_socket: bind(%s)", sock_path);
goto failed;
}
@@ -473,43 +560,49 @@ failed:
}
/*
- * Call create_socket() for server listening socket.
- * Return socket descriptor or -1 if some error occurred.
+ * Create server socket.
*/
static int
create_server_socket(void)
{
- return (create_socket(serv_sock_path, sizeof(serv_sock_path), &servaddr));
-}
+ int fd;
-/*
- * Create unbound socket.
- */
-static int
-create_unbound_socket(void)
-{
- return (create_socket((char *)NULL, 0, (struct sockaddr_un *)NULL));
+ fd = create_socket(serv_sock_path, sizeof(serv_sock_path), &servaddr);
+ if (fd < 0)
+ return (-1);
+
+ if (sock_type == SOCK_STREAM) {
+ int val;
+
+ if (listen(fd, LISTENQ) < 0) {
+ logmsg("create_server_socket: listen");
+ goto failed;
+ }
+ val = fcntl(fd, F_GETFL, 0);
+ if (val < 0) {
+ logmsg("create_server_socket: fcntl(F_GETFL)");
+ goto failed;
+ }
+ if (fcntl(fd, F_SETFL, val | O_NONBLOCK) < 0) {
+ logmsg("create_server_socket: fcntl(F_SETFL)");
+ goto failed;
+ }
+ }
+
+ return (fd);
+
+failed:
+ (void)close_socket(serv_sock_path, fd);
+ return (-1);
}
/*
- * Close socket descriptor, if sock_path is not equal to NULL,
- * then unlink the given path.
+ * Create client socket.
*/
static int
-close_socket(const char *sock_path, int fd)
+create_client_socket(void)
{
- int error = 0;
-
- if (close(fd) < 0) {
- logmsg("close_socket: close");
- error = -1;
- }
- if (sock_path != NULL)
- if (unlink(sock_path) < 0) {
- logmsg("close_socket: unlink(%s)", sock_path);
- error = -1;
- }
- return (error);
+ return (create_socket((char *)NULL, 0, (struct sockaddr_un *)NULL));
}
/*
@@ -524,7 +617,7 @@ connect_server(int fd)
* If PF_LOCAL listening socket's queue is full, then connect()
* returns ECONNREFUSED immediately, do not need timeout.
*/
- if (connect(fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
+ if (connect(fd, (struct sockaddr *)&servaddr, servaddr.sun_len) < 0) {
logmsg("connect_server: connect(%s)", serv_sock_path);
return (-1);
}
@@ -533,34 +626,23 @@ connect_server(int fd)
}
/*
- * sendmsg() with timeout.
+ * sendmsg() wrapper.
*/
static int
-sendmsg_timeout(int fd, struct msghdr *msg, size_t n)
+send_message(int fd, const struct msghdr *msg, size_t n)
{
ssize_t nsent;
- dbgmsg(("sending %lu bytes", (u_long)n));
-
- if (sigsetjmp(env_alrm, 1) != 0) {
- logmsgx("sendmsg_timeout: cannot send message to %s (timeout)", serv_sock_path);
- return (-1);
- }
-
- (void)alarm(TIMEOUT);
+ dbgmsg(("sending %zu bytes", n));
nsent = sendmsg(fd, msg, 0);
-
- (void)alarm(0);
-
if (nsent < 0) {
- logmsg("sendmsg_timeout: sendmsg");
+ logmsg("send_message: sendmsg");
return (-1);
}
-
if ((size_t)nsent != n) {
- logmsgx("sendmsg_timeout: sendmsg: short send: %ld of %lu bytes",
- (long)nsent, (u_long)n);
+ logmsgx("send_message: sendmsg: short send: "
+ "%zd of %zu bytes", nsent, n);
return (-1);
}
@@ -568,63 +650,73 @@ sendmsg_timeout(int fd, struct msghdr *m
}
/*
- * accept() with timeout.
+ * accept() wrapper.
*/
static int
-accept_timeout(int listenfd)
+accept_connection(int listenfd)
{
- int fd;
+ fd_set rset;
+ struct timeval tv;
+ int fd, rv, val;
dbgmsg(("accepting connection"));
- if (sigsetjmp(env_alrm, 1) != 0) {
- logmsgx("accept_timeout: cannot accept connection (timeout)");
+ FD_ZERO(&rset);
+ FD_SET(listenfd, &rset);
+ tv.tv_sec = TIMEOUT;
+ tv.tv_usec = 0;
+ rv = select(listenfd + 1, &rset, (fd_set *)NULL, (fd_set *)NULL, &tv);
+ if (rv < 0) {
+ logmsg("accept_connection: select");
+ return (-1);
+ }
+ if (rv == 0) {
+ logmsgx("accept_connection: select timeout");
return (-1);
}
-
- (void)alarm(TIMEOUT);
fd = accept(listenfd, (struct sockaddr *)NULL, (socklen_t *)NULL);
-
- (void)alarm(0);
-
if (fd < 0) {
- logmsg("accept_timeout: accept");
+ logmsg("accept_connection: accept");
return (-1);
}
+ val = fcntl(fd, F_GETFL, 0);
+ if (val < 0) {
+ logmsg("accept_connection: fcntl(F_GETFL)");
+ goto failed;
+ }
+ if (fcntl(fd, F_SETFL, val & ~O_NONBLOCK) < 0) {
+ logmsg("accept_connection: fcntl(F_SETFL)");
+ goto failed;
+ }
+
return (fd);
+
+failed:
+ if (close(fd) < 0)
+ logmsg("accept_connection: close");
+ return (-1);
}
/*
- * recvmsg() with timeout.
+ * recvmsg() wrapper.
*/
static int
-recvmsg_timeout(int fd, struct msghdr *msg, size_t n)
+recv_message(int fd, struct msghdr *msg, size_t n)
{
ssize_t nread;
- dbgmsg(("receiving %lu bytes", (u_long)n));
-
- if (sigsetjmp(env_alrm, 1) != 0) {
- logmsgx("recvmsg_timeout: cannot receive message (timeout)");
- return (-1);
- }
-
- (void)alarm(TIMEOUT);
+ dbgmsg(("receiving %zu bytes", n));
nread = recvmsg(fd, msg, MSG_WAITALL);
-
- (void)alarm(0);
-
if (nread < 0) {
- logmsg("recvmsg_timeout: recvmsg");
+ logmsg("recv_message: recvmsg");
return (-1);
}
-
if ((size_t)nread != n) {
- logmsgx("recvmsg_timeout: recvmsg: short read: %ld of %lu bytes",
- (long)nread, (u_long)n);
+ logmsgx("recv_message: recvmsg: short read: "
+ "%zd of %zu bytes", nread, n);
return (-1);
}
@@ -632,7 +724,7 @@ recvmsg_timeout(int fd, struct msghdr *m
}
/*
- * Wait for synchronization message (1 byte) with timeout.
+ * Wait for synchronization message (1 byte).
*/
static int
sync_recv(int fd)
@@ -642,25 +734,13 @@ sync_recv(int fd)
dbgmsg(("waiting for sync message"));
- if (sigsetjmp(env_alrm, 1) != 0) {
- logmsgx("sync_recv: cannot receive sync message (timeout)");
- return (-1);
- }
-
- (void)alarm(TIMEOUT);
-
nread = read(fd, &buf, 1);
-
- (void)alarm(0);
-
if (nread < 0) {
logmsg("sync_recv: read");
return (-1);
}
-
if (nread != 1) {
- logmsgx("sync_recv: read: short read: %ld of 1 byte",
- (long)nread);
+ logmsgx("sync_recv: read: short read: %zd of 1 byte", nread);
return (-1);
}
@@ -668,7 +748,7 @@ sync_recv(int fd)
}
/*
- * Send synchronization message (1 byte) with timeout.
+ * Send synchronization message (1 byte).
*/
static int
sync_send(int fd)
@@ -677,25 +757,13 @@ sync_send(int fd)
dbgmsg(("sending sync message"));
- if (sigsetjmp(env_alrm, 1) != 0) {
- logmsgx("sync_send: cannot send sync message (timeout)");
- return (-1);
- }
-
- (void)alarm(TIMEOUT);
-
nsent = write(fd, "", 1);
-
- (void)alarm(0);
-
if (nsent < 0) {
logmsg("sync_send: write");
return (-1);
}
-
if (nsent != 1) {
- logmsgx("sync_send: write: short write: %ld of 1 byte",
- (long)nsent);
+ logmsgx("sync_send: write: short write: %zd of 1 byte", nsent);
return (-1);
}
@@ -711,36 +779,29 @@ wait_client(void)
int status;
pid_t pid;
- if (sigsetjmp(env_alrm, 1) != 0) {
- logmsgx("wait_client: cannot get exit status of client PID %ld (timeout)",
- (long)client_pid);
- return (-1);
- }
-
- (void)alarm(TIMEOUT);
+ dbgmsg(("waiting for a client"));
pid = waitpid(client_pid, &status, 0);
-
- (void)alarm(0);
-
if (pid == (pid_t)-1) {
logmsg("wait_client: waitpid");
return (-1);
}
if (WIFEXITED(status)) {
- if (WEXITSTATUS(status) != 0) {
- logmsgx("wait_client: exit status of client PID %ld is %d",
- (long)client_pid, WEXITSTATUS(status));
+ if (WEXITSTATUS(status) != EXIT_SUCCESS) {
+ logmsgx("wait_client: exit status of client PID %ld "
+ "is %d", (long)client_pid, WEXITSTATUS(status));
return (-1);
}
} else {
if (WIFSIGNALED(status))
- logmsgx("wait_client: abnormal termination of client PID %ld, signal %d%s",
- (long)client_pid, WTERMSIG(status), WCOREDUMP(status) ? " (core file generated)" : "");
+ logmsgx("wait_client: abnormal termination of client "
+ "PID %ld, signal %d%s", (long)client_pid,
+ WTERMSIG(status), WCOREDUMP(status) ?
+ " (core file generated)" : "");
else
- logmsgx("wait_client: termination of client PID %ld, unknown status",
- (long)client_pid);
+ logmsgx("wait_client: termination of client PID %ld, "
+ "unknown status", (long)client_pid);
return (-1);
}
@@ -748,28 +809,27 @@ wait_client(void)
}
/*
- * Check if n supplementary GIDs in gids are correct. (my_gids + 1)
- * has (my_ngids - 1) supplementary GIDs of current process.
+ * Check whether n GIDs in gids are correct.
*/
static int
check_groups(const gid_t *gids, int n)
{
+ int i, j, rv;
char match[NGROUPS_MAX] = { 0 };
- int error, i, j;
- if (n != my_ngids - 1) {
- logmsgx("wrong number of groups %d != %d (returned from getgroups() - 1)",
- n, my_ngids - 1);
- error = -1;
+ if (n != my_ngids) {
+ logmsgx("wrong number of groups %d != %d (returned from "
+ "getgroups())", n, my_ngids);
+ rv = -1;
} else
- error = 0;
+ rv = 0;
for (i = 0; i < n; ++i) {
- for (j = 1; j < my_ngids; ++j) {
+ for (j = 0; j < my_ngids; ++j) {
if (gids[i] == my_gids[j]) {
if (match[j]) {
logmsgx("duplicated GID %lu",
(u_long)gids[i]);
- error = -1;
+ rv = -1;
} else
match[j] = 1;
break;
@@ -777,15 +837,15 @@ check_groups(const gid_t *gids, int n)
}
if (j == my_ngids) {
logmsgx("unexpected GID %lu", (u_long)gids[i]);
- error = -1;
+ rv = -1;
}
}
- for (j = 1; j < my_ngids; ++j)
+ for (j = 0; j < my_ngids; ++j)
if (match[j] == 0) {
- logmsgx("did not receive supplementary GID %u", my_gids[j]);
- error = -1;
+ logmsgx("did not receive GID %lu", (u_long)my_gids[j]);
+ rv = -1;
}
- return (error);
+ return (rv);
}
/*
@@ -802,16 +862,17 @@ t_cmsgcred_client(u_int n)
struct msghdr msg;
struct iovec iov[1];
struct cmsghdr *cmptr;
- int fd;
u_int i;
+ int fd, rv;
- assert(n == 1 || n == 2);
+ rv = EXIT_FAILURE;
- if ((fd = create_unbound_socket()) < 0)
+ fd = create_client_socket();
+ if (fd < 0)
goto failed;
if (connect_server(fd) < 0)
- goto failed_close;
+ goto done;
iov[0].iov_base = ipc_message;
iov[0].iov_len = IPC_MESSAGE_SIZE;
@@ -834,20 +895,16 @@ t_cmsgcred_client(u_int n)
for (i = 0; i < n; ++i) {
dbgmsg(("#%u msg_controllen = %u, cmsg_len = %u", i,
(u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len));
- if (sendmsg_timeout(fd, &msg, IPC_MESSAGE_SIZE) < 0)
- goto failed_close;
+ if (send_message(fd, &msg, IPC_MESSAGE_SIZE) < 0)
+ goto done;
}
- if (close_socket((const char *)NULL, fd) < 0)
- goto failed;
-
- _exit(0);
-
-failed_close:
- (void)close_socket((const char *)NULL, fd);
-
+ rv = EXIT_SUCCESS;
+done:
+ if (close_socket((char *)NULL, fd))
+ rv = EXIT_FAILURE;
failed:
- _exit(1);
+ _exit(rv);
}
/*
@@ -858,28 +915,27 @@ failed:
static int
t_cmsgcred_server(int fd1)
{
- char buf[IPC_MESSAGE_SIZE];
union {
struct cmsghdr cm;
- char control[CMSG_SPACE(sizeof(struct cmsgcred)) + EXTRA_CMSG_SPACE];
+ char control[CMSG_SPACE(sizeof(struct cmsgcred)) +
+ EXTRA_CMSG_SPACE];
} control_un;
struct msghdr msg;
struct iovec iov[1];
struct cmsghdr *cmptr;
- const struct cmsgcred *cmcredptr;
- socklen_t controllen;
- int error, error2, fd2;
+ const struct cmsgcred *cmcred;
u_int i;
+ int fd2, rv;
+ char buf[IPC_MESSAGE_SIZE];
if (sock_type == SOCK_STREAM) {
- if ((fd2 = accept_timeout(fd1)) < 0)
+ fd2 = accept_connection(fd1);
+ if (fd2 < 0)
return (-2);
} else
fd2 = fd1;
- error = 0;
-
- controllen = sizeof(control_un.control);
+ rv = 0;
for (i = 0; i < 2; ++i) {
iov[0].iov_base = buf;
@@ -890,29 +946,31 @@ t_cmsgcred_server(int fd1)
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control = control_un.control;
- msg.msg_controllen = controllen;
+ msg.msg_controllen = sizeof(control_un.control);
msg.msg_flags = 0;
- controllen = CMSG_SPACE(sizeof(struct cmsgcred));
-
- if (recvmsg_timeout(fd2, &msg, sizeof(buf)) < 0)
- goto failed;
+ if (recv_message(fd2, &msg, sizeof(buf)) < 0) {
+ rv = -2;
+ break;
+ }
if (msg.msg_flags & MSG_CTRUNC) {
- logmsgx("#%u control data was truncated, MSG_CTRUNC flag is on",
- i);
- goto next_error;
+ logmsgx("#%u control data was truncated, MSG_CTRUNC "
+ "flag is on", i);
+ goto next;
}
if (msg.msg_controllen < sizeof(struct cmsghdr)) {
- logmsgx("#%u msg_controllen %u < %lu (sizeof(struct cmsghdr))",
- i, (u_int)msg.msg_controllen, (u_long)sizeof(struct cmsghdr));
- goto next_error;
+ logmsgx("#%u msg_controllen %u < %zu "
+ "(sizeof(struct cmsghdr))", i,
+ (u_int)msg.msg_controllen, sizeof(struct cmsghdr));
+ goto next;
}
- if ((cmptr = CMSG_FIRSTHDR(&msg)) == NULL) {
+ cmptr = CMSG_FIRSTHDR(&msg);
+ if (cmptr == NULL) {
logmsgx("CMSG_FIRSTHDR is NULL");
- goto next_error;
+ goto next;
}
dbgmsg(("#%u msg_controllen = %u, cmsg_len = %u", i,
@@ -921,142 +979,120 @@ t_cmsgcred_server(int fd1)
if (cmptr->cmsg_level != SOL_SOCKET) {
logmsgx("#%u cmsg_level %d != SOL_SOCKET", i,
cmptr->cmsg_level);
- goto next_error;
+ goto next;
}
if (cmptr->cmsg_type != SCM_CREDS) {
logmsgx("#%u cmsg_type %d != SCM_CREDS", i,
cmptr->cmsg_type);
- goto next_error;
+ goto next;
}
if (cmptr->cmsg_len != CMSG_LEN(sizeof(struct cmsgcred))) {
- logmsgx("#%u cmsg_len %u != %lu (CMSG_LEN(sizeof(struct cmsgcred))",
- i, (u_int)cmptr->cmsg_len, (u_long)CMSG_LEN(sizeof(struct cmsgcred)));
- goto next_error;
+ logmsgx("#%u cmsg_len %u != %zu "
+ "(CMSG_LEN(sizeof(struct cmsgcred))", i,
+ (u_int)cmptr->cmsg_len,
+ CMSG_LEN(sizeof(struct cmsgcred)));
+ goto next;
}
- cmcredptr = (const struct cmsgcred *)CMSG_DATA(cmptr);
+ cmcred = (struct cmsgcred *)CMSG_DATA(cmptr);
- error2 = 0;
- if (cmcredptr->cmcred_pid != client_pid) {
+ if (cmcred->cmcred_pid != client_pid) {
logmsgx("#%u cmcred_pid %ld != %ld (PID of client)",
- i, (long)cmcredptr->cmcred_pid, (long)client_pid);
- error2 = 1;
+ i, (long)cmcred->cmcred_pid, (long)client_pid);
+ goto next;
}
- if (cmcredptr->cmcred_uid != my_uid) {
- logmsgx("#%u cmcred_uid %lu != %lu (UID of current process)",
- i, (u_long)cmcredptr->cmcred_uid, (u_long)my_uid);
- error2 = 1;
- }
- if (cmcredptr->cmcred_euid != my_euid) {
- logmsgx("#%u cmcred_euid %lu != %lu (EUID of current process)",
- i, (u_long)cmcredptr->cmcred_euid, (u_long)my_euid);
- error2 = 1;
- }
- if (cmcredptr->cmcred_gid != my_gid) {
- logmsgx("#%u cmcred_gid %lu != %lu (GID of current process)",
- i, (u_long)cmcredptr->cmcred_gid, (u_long)my_gid);
- error2 = 1;
+ if (cmcred->cmcred_uid != my_uid) {
+ logmsgx("#%u cmcred_uid %lu != %lu (UID of current "
+ "process)", i, (u_long)cmcred->cmcred_uid,
+ (u_long)my_uid);
+ goto next;
+ }
+ if (cmcred->cmcred_euid != my_euid) {
+ logmsgx("#%u cmcred_euid %lu != %lu (EUID of current "
+ "process)", i, (u_long)cmcred->cmcred_euid,
+ (u_long)my_euid);
+ goto next;
+ }
+ if (cmcred->cmcred_gid != my_gid) {
+ logmsgx("#%u cmcred_gid %lu != %lu (GID of current "
+ "process)", i, (u_long)cmcred->cmcred_gid,
+ (u_long)my_gid);
+ goto next;
}
- if (cmcredptr->cmcred_ngroups == 0) {
+ if (cmcred->cmcred_ngroups == 0) {
logmsgx("#%u cmcred_ngroups = 0, this is wrong", i);
- error2 = 1;
- } else {
- if (cmcredptr->cmcred_ngroups > NGROUPS_MAX) {
- logmsgx("#%u cmcred_ngroups %d > %u (NGROUPS_MAX)",
- i, cmcredptr->cmcred_ngroups, NGROUPS_MAX);
- error2 = 1;
- } else if (cmcredptr->cmcred_ngroups < 0) {
- logmsgx("#%u cmcred_ngroups %d < 0",
- i, cmcredptr->cmcred_ngroups);
- error2 = 1;
- } else {
- dbgmsg(("#%u cmcred_ngroups = %d", i,
- cmcredptr->cmcred_ngroups));
- if (cmcredptr->cmcred_groups[0] != my_egid) {
- logmsgx("#%u cmcred_groups[0] %lu != %lu (EGID of current process)",
- i, (u_long)cmcredptr->cmcred_groups[0], (u_long)my_egid);
- error2 = 1;
- }
- if (check_groups(cmcredptr->cmcred_groups + 1, cmcredptr->cmcred_ngroups - 1) < 0) {
- logmsgx("#%u cmcred_groups has wrong GIDs", i);
- error2 = 1;
- }
- }
+ goto next;
}
-
- if (error2)
- goto next_error;
-
- if ((cmptr = CMSG_NXTHDR(&msg, cmptr)) != NULL) {
- logmsgx("#%u control data has extra header", i);
- goto next_error;
+ if (cmcred->cmcred_ngroups < 0) {
+ logmsgx("#%u cmcred_ngroups %d < 0",
+ i, cmcred->cmcred_ngroups);
+ goto next;
+ }
+ if (cmcred->cmcred_ngroups > NGROUPS_MAX) {
+ logmsgx("#%u cmcred_ngroups %d > %u (NGROUPS_MAX)",
+ i, cmcred->cmcred_ngroups, NGROUPS_MAX);
+ goto next;
+ }
+
+ dbgmsg(("#%u cmcred_ngroups = %d", i, cmcred->cmcred_ngroups));
+ if (cmcred->cmcred_groups[0] != my_egid) {
+ logmsgx("#%u cmcred_groups[0] %lu != %lu (EGID of "
+ "current process)", i,
+ (u_long)cmcred->cmcred_groups[0], (u_long)my_egid);
+ goto next;
+ }
+ if (check_groups(cmcred->cmcred_groups,
+ cmcred->cmcred_ngroups) < 0) {
+ logmsgx("#%u cmcred_groups has wrong GIDs", i);
+ goto next;
+ }
+
+ if (CMSG_NXTHDR(&msg, cmptr) != NULL) {
+ logmsgx("#%u control data has extra header, "
+ "this is wrong", i);
+ goto next;
}
-
continue;
-next_error:
- error = -1;
+next:
+ rv = -1;
}
if (sock_type == SOCK_STREAM)
- if (close(fd2) < 0) {
- logmsg("close");
- return (-2);
- }
- return (error);
-
-failed:
- if (sock_type == SOCK_STREAM)
- if (close(fd2) < 0)
- logmsg("close");
- return (-2);
+ if (close_socket((char *)NULL, fd2) < 0)
+ rv = -2;
+ return (rv);
}
static int
t_cmsgcred(void)
{
- int error, fd;
+ int fd, rv;
- if ((fd = create_server_socket()) < 0)
+ fd = create_server_socket();
+ if (fd < 0)
return (-2);
- if (sock_type == SOCK_STREAM)
- if (listen(fd, LISTENQ) < 0) {
- logmsg("listen");
- goto failed;
- }
+ rv = -2;
- if ((client_pid = fork()) == (pid_t)-1) {
- logmsg("fork");
- goto failed;
- }
+ if (fork_client() < 0)
+ goto done;
if (client_pid == 0) {
- myname = "CLIENT";
- if (close_socket((const char *)NULL, fd) < 0)
- _exit(1);
+ if (close_socket((char *)NULL, fd) < 0)
+ _exit(EXIT_FAILURE);
t_cmsgcred_client(2);
}
- if ((error = t_cmsgcred_server(fd)) == -2) {
- (void)wait_client();
- goto failed;
- }
+ rv = t_cmsgcred_server(fd);
if (wait_client() < 0)
- goto failed;
-
- if (close_socket(serv_sock_path, fd) < 0) {
- logmsgx("close_socket failed");
- return (-2);
- }
- return (error);
-
-failed:
+ rv = -2;
+done:
if (close_socket(serv_sock_path, fd) < 0)
- logmsgx("close_socket failed");
- return (-2);
+ rv = -2;
+ return (rv);
}
/*
@@ -1067,20 +1103,21 @@ t_sockcred_client(int type)
{
struct msghdr msg;
struct iovec iov[1];
- int fd;
u_int i;
+ int fd, rv;
- assert(type == 0 || type == 1);
+ rv = EXIT_FAILURE;
- if ((fd = create_unbound_socket()) < 0)
+ fd = create_client_socket();
+ if (fd < 0)
goto failed;
if (connect_server(fd) < 0)
- goto failed_close;
+ goto done;
if (type == 1)
if (sync_recv(fd) < 0)
- goto failed_close;
+ goto done;
iov[0].iov_base = ipc_message;
iov[0].iov_len = IPC_MESSAGE_SIZE;
@@ -1094,19 +1131,15 @@ t_sockcred_client(int type)
msg.msg_flags = 0;
for (i = 0; i < 2; ++i)
- if (sendmsg_timeout(fd, &msg, IPC_MESSAGE_SIZE) < 0)
- goto failed_close;
-
- if (close_socket((const char *)NULL, fd) < 0)
- goto failed;
-
- _exit(0);
-
-failed_close:
- (void)close_socket((const char *)NULL, fd);
+ if (send_message(fd, &msg, IPC_MESSAGE_SIZE) < 0)
+ goto done;
+ rv = EXIT_SUCCESS;
+done:
+ if (close_socket((char *)NULL, fd) < 0)
+ rv = EXIT_FAILURE;
failed:
- _exit(1);
+ _exit(rv);
}
/*
@@ -1119,232 +1152,217 @@ failed:
static int
t_sockcred_server(int type, int fd1, u_int n)
{
- char buf[IPC_MESSAGE_SIZE];
union {
struct cmsghdr cm;
- char control[CMSG_SPACE(SOCKCREDSIZE(NGROUPS_MAX)) + EXTRA_CMSG_SPACE];
+ char control[CMSG_SPACE(SOCKCREDSIZE(NGROUPS_MAX)) +
+ EXTRA_CMSG_SPACE];
} control_un;
struct msghdr msg;
struct iovec iov[1];
struct cmsghdr *cmptr;
const struct sockcred *sockcred;
- int error, error2, fd2, optval;
u_int i;
+ int fd2, rv, optval;
+ char buf[IPC_MESSAGE_SIZE];
- assert(n == 1 || n == 2);
- assert(type == 0 || type == 1);
+ rv = -2;
if (sock_type == SOCK_STREAM) {
- if ((fd2 = accept_timeout(fd1)) < 0)
+ fd2 = accept_connection(fd1);
+ if (fd2 < 0)
return (-2);
if (type == 1) {
optval = 1;
- if (setsockopt(fd2, 0, LOCAL_CREDS, &optval, sizeof optval) < 0) {
- logmsg("setsockopt(LOCAL_CREDS) for accepted socket");
- if (errno == ENOPROTOOPT) {
- error = -1;
- goto done_close;
- }
- goto failed;
+ if (setsockopt(fd2, 0, LOCAL_CREDS, &optval,
+ sizeof(optval)) < 0) {
+ logmsg("setsockopt(LOCAL_CREDS) for accepted "
+ "socket");
+ if (errno == ENOPROTOOPT)
+ rv = -1;
+ goto done;
}
if (sync_send(fd2) < 0)
- goto failed;
+ goto done;
}
} else
fd2 = fd1;
- error = 0;
+ rv = 0;
for (i = 0; i < n; ++i) {
iov[0].iov_base = buf;
- iov[0].iov_len = sizeof buf;
+ iov[0].iov_len = sizeof(buf);
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control = control_un.control;
- msg.msg_controllen = sizeof control_un.control;
+ msg.msg_controllen = sizeof(control_un.control);
msg.msg_flags = 0;
- if (recvmsg_timeout(fd2, &msg, sizeof buf) < 0)
- goto failed;
+ if (recv_message(fd2, &msg, sizeof(buf)) < 0) {
+ rv = -2;
+ break;
+ }
if (msg.msg_flags & MSG_CTRUNC) {
- logmsgx("control data was truncated, MSG_CTRUNC flag is on");
- goto next_error;
+ logmsgx("control data was truncated, MSG_CTRUNC flag "
+ "is on");
+ goto next;
}
+ dbgmsg(("#%u msg_controllen = %u", i,
+ (u_int)msg.msg_controllen));
+
if (i != 0 && sock_type == SOCK_STREAM) {
if (msg.msg_controllen != 0) {
- logmsgx("second message has control data, this is wrong for stream sockets");
- goto next_error;
+ logmsgx("second message has control data, "
+ "this is wrong for stream sockets");
+ goto next;
}
- dbgmsg(("#%u msg_controllen = %u", i,
- (u_int)msg.msg_controllen));
continue;
}
if (msg.msg_controllen < sizeof(struct cmsghdr)) {
- logmsgx("#%u msg_controllen %u < %lu (sizeof(struct cmsghdr))",
- i, (u_int)msg.msg_controllen, (u_long)sizeof(struct cmsghdr));
- goto next_error;
+ logmsgx("#%u msg_controllen %u < %zu "
+ "(sizeof(struct cmsghdr))", i,
+ (u_int)msg.msg_controllen, sizeof(struct cmsghdr));
+ goto next;
}
- if ((cmptr = CMSG_FIRSTHDR(&msg)) == NULL) {
+ cmptr = CMSG_FIRSTHDR(&msg);
+ if (cmptr == NULL) {
logmsgx("CMSG_FIRSTHDR is NULL");
- goto next_error;
+ goto next;
}
- dbgmsg(("#%u msg_controllen = %u, cmsg_len = %u", i,
- (u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len));
+ dbgmsg(("#%u cmsg_len = %u", i, (u_int)cmptr->cmsg_len));
if (cmptr->cmsg_level != SOL_SOCKET) {
logmsgx("#%u cmsg_level %d != SOL_SOCKET", i,
cmptr->cmsg_level);
- goto next_error;
+ goto next;
}
if (cmptr->cmsg_type != SCM_CREDS) {
logmsgx("#%u cmsg_type %d != SCM_CREDS", i,
cmptr->cmsg_type);
- goto next_error;
+ goto next;
}
if (cmptr->cmsg_len < CMSG_LEN(SOCKCREDSIZE(1))) {
- logmsgx("#%u cmsg_len %u != %lu (CMSG_LEN(SOCKCREDSIZE(1)))",
- i, (u_int)cmptr->cmsg_len, (u_long)CMSG_LEN(SOCKCREDSIZE(1)));
- goto next_error;
+ logmsgx("#%u cmsg_len %u != %zu "
+ "(CMSG_LEN(SOCKCREDSIZE(1)))", i,
+ (u_int)cmptr->cmsg_len, CMSG_LEN(SOCKCREDSIZE(1)));
+ goto next;
}
- sockcred = (const struct sockcred *)CMSG_DATA(cmptr);
+ sockcred = (struct sockcred *)CMSG_DATA(cmptr);
- error2 = 0;
if (sockcred->sc_uid != my_uid) {
- logmsgx("#%u sc_uid %lu != %lu (UID of current process)",
- i, (u_long)sockcred->sc_uid, (u_long)my_uid);
- error2 = 1;
+ logmsgx("#%u sc_uid %lu != %lu (UID of current "
+ "process)", i, (u_long)sockcred->sc_uid,
+ (u_long)my_uid);
+ goto next;
}
if (sockcred->sc_euid != my_euid) {
- logmsgx("#%u sc_euid %lu != %lu (EUID of current process)",
- i, (u_long)sockcred->sc_euid, (u_long)my_euid);
- error2 = 1;
+ logmsgx("#%u sc_euid %lu != %lu (EUID of current "
+ "process)", i, (u_long)sockcred->sc_euid,
+ (u_long)my_euid);
+ goto next;
}
if (sockcred->sc_gid != my_gid) {
- logmsgx("#%u sc_gid %lu != %lu (GID of current process)",
- i, (u_long)sockcred->sc_gid, (u_long)my_gid);
- error2 = 1;
+ logmsgx("#%u sc_gid %lu != %lu (GID of current "
+ "process)", i, (u_long)sockcred->sc_gid,
+ (u_long)my_gid);
+ goto next;
}
if (sockcred->sc_egid != my_egid) {
- logmsgx("#%u sc_egid %lu != %lu (EGID of current process)",
- i, (u_long)sockcred->sc_gid, (u_long)my_egid);
- error2 = 1;
+ logmsgx("#%u sc_egid %lu != %lu (EGID of current "
+ "process)", i, (u_long)sockcred->sc_gid,
+ (u_long)my_egid);
+ goto next;
+ }
+ if (sockcred->sc_ngroups == 0) {
+ logmsgx("#%u sc_ngroups %d = 0, this is wrong",
+ i, sockcred->sc_ngroups);
+ goto next;
+ }
+ if (sockcred->sc_ngroups < 0) {
+ logmsgx("#%u sc_ngroups %d < 0",
+ i, sockcred->sc_ngroups);
+ goto next;
}
if (sockcred->sc_ngroups > NGROUPS_MAX) {
logmsgx("#%u sc_ngroups %d > %u (NGROUPS_MAX)",
i, sockcred->sc_ngroups, NGROUPS_MAX);
- error2 = 1;
- } else if (sockcred->sc_ngroups < 0) {
- logmsgx("#%u sc_ngroups %d < 0",
- i, sockcred->sc_ngroups);
- error2 = 1;
- } else {
- dbgmsg(("#%u sc_ngroups = %d", i, sockcred->sc_ngroups));
- if (check_groups(sockcred->sc_groups, sockcred->sc_ngroups) < 0) {
- logmsgx("#%u sc_groups has wrong GIDs", i);
- error2 = 1;
- }
+ goto next;
}
- if (error2)
- goto next_error;
-
- if ((cmptr = CMSG_NXTHDR(&msg, cmptr)) != NULL) {
- logmsgx("#%u control data has extra header, this is wrong",
- i);
- goto next_error;
+ dbgmsg(("#%u sc_ngroups = %d", i, sockcred->sc_ngroups));
+ if (check_groups(sockcred->sc_groups,
+ sockcred->sc_ngroups) < 0) {
+ logmsgx("#%u sc_groups has wrong GIDs", i);
+ goto next;
}
+ if (CMSG_NXTHDR(&msg, cmptr) != NULL) {
+ logmsgx("#%u control data has extra header, "
+ "this is wrong", i);
+ goto next;
+ }
continue;
-next_error:
- error = -1;
+next:
+ rv = -1;
}
-
-done_close:
- if (sock_type == SOCK_STREAM)
- if (close(fd2) < 0) {
- logmsg("close");
- return (-2);
- }
- return (error);
-
-failed:
+done:
if (sock_type == SOCK_STREAM)
- if (close(fd2) < 0)
- logmsg("close");
- return (-2);
+ if (close_socket((char *)NULL, fd2) < 0)
+ rv = -2;
+ return (rv);
}
static int
t_sockcred(int type)
{
- int error, fd, optval;
+ int fd, rv, optval;
- assert(type == 0 || type == 1);
-
- if ((fd = create_server_socket()) < 0)
+ fd = create_server_socket();
+ if (fd < 0)
return (-2);
- if (sock_type == SOCK_STREAM)
- if (listen(fd, LISTENQ) < 0) {
- logmsg("listen");
- goto failed;
- }
+ rv = -2;
if (type == 0) {
optval = 1;
- if (setsockopt(fd, 0, LOCAL_CREDS, &optval, sizeof optval) < 0) {
+ if (setsockopt(fd, 0, LOCAL_CREDS, &optval,
+ sizeof(optval)) < 0) {
logmsg("setsockopt(LOCAL_CREDS) for %s socket",
- sock_type == SOCK_STREAM ? "stream listening" : "datagram");
- if (errno == ENOPROTOOPT) {
- error = -1;
- goto done_close;
- }
- goto failed;
+ sock_type_str);
+ if (errno == ENOPROTOOPT)
+ rv = -1;
+ goto done;
}
}
- if ((client_pid = fork()) == (pid_t)-1) {
- logmsg("fork");
- goto failed;
- }
+ if (fork_client() < 0)
+ goto done;
if (client_pid == 0) {
- myname = "CLIENT";
- if (close_socket((const char *)NULL, fd) < 0)
- _exit(1);
+ if (close_socket((char *)NULL, fd) < 0)
+ _exit(EXIT_FAILURE);
t_sockcred_client(type);
}
- if ((error = t_sockcred_server(type, fd, 2)) == -2) {
- (void)wait_client();
- goto failed;
- }
+ rv = t_sockcred_server(type, fd, 2);
if (wait_client() < 0)
- goto failed;
-
-done_close:
- if (close_socket(serv_sock_path, fd) < 0) {
- logmsgx("close_socket failed");
- return (-2);
- }
- return (error);
-
-failed:
+ rv = -2;
+done:
if (close_socket(serv_sock_path, fd) < 0)
- logmsgx("close_socket failed");
- return (-2);
+ rv = -2;
+ return (rv);
}
static int
@@ -1368,59 +1386,39 @@ t_sockcred_dgram(void)
static int
t_cmsgcred_sockcred(void)
{
- int error, fd, optval;
+ int fd, rv, optval;
- if ((fd = create_server_socket()) < 0)
+ fd = create_server_socket();
+ if (fd < 0)
return (-2);
- if (sock_type == SOCK_STREAM)
- if (listen(fd, LISTENQ) < 0) {
- logmsg("listen");
- goto failed;
- }
+ rv = -2;
optval = 1;
- if (setsockopt(fd, 0, LOCAL_CREDS, &optval, sizeof optval) < 0) {
- logmsg("setsockopt(LOCAL_CREDS) for %s socket",
- sock_type == SOCK_STREAM ? "stream listening" : "datagram");
- if (errno == ENOPROTOOPT) {
- error = -1;
- goto done_close;
- }
- goto failed;
+ if (setsockopt(fd, 0, LOCAL_CREDS, &optval, sizeof(optval)) < 0) {
+ logmsg("setsockopt(LOCAL_CREDS) for %s socket", sock_type_str);
+ if (errno == ENOPROTOOPT)
+ rv = -1;
+ goto done;
}
- if ((client_pid = fork()) == (pid_t)-1) {
- logmsg("fork");
- goto failed;
- }
+ if (fork_client() < 0)
+ goto done;
if (client_pid == 0) {
- myname = "CLIENT";
- if (close_socket((const char *)NULL, fd) < 0)
- _exit(1);
+ if (close_socket((char *)NULL, fd) < 0)
+ _exit(EXIT_FAILURE);
t_cmsgcred_client(1);
}
- if ((error = t_sockcred_server(0, fd, 1)) == -2) {
- (void)wait_client();
- goto failed;
- }
+ rv = t_sockcred_server(0, fd, 1);
if (wait_client() < 0)
- goto failed;
-
-done_close:
- if (close_socket(serv_sock_path, fd) < 0) {
- logmsgx("close_socket failed");
- return (-2);
- }
- return (error);
-
-failed:
+ rv = -2;
+done:
if (close_socket(serv_sock_path, fd) < 0)
- logmsgx("close_socket failed");
- return (-2);
+ rv = -2;
+ return (rv);
}
/*
@@ -1437,13 +1435,16 @@ t_timestamp_client(void)
struct msghdr msg;
struct iovec iov[1];
struct cmsghdr *cmptr;
- int fd;
+ int fd, rv;
+
+ rv = EXIT_FAILURE;
- if ((fd = create_unbound_socket()) < 0)
+ fd = create_client_socket();
+ if (fd < 0)
goto failed;
if (connect_server(fd) < 0)
- goto failed_close;
+ goto done;
iov[0].iov_base = ipc_message;
iov[0].iov_len = IPC_MESSAGE_SIZE;
@@ -1454,7 +1455,7 @@ t_timestamp_client(void)
msg.msg_iovlen = 1;
msg.msg_control = control_un.control;
msg.msg_controllen = no_control_data ?
- sizeof(struct cmsghdr) :sizeof control_un.control;
+ sizeof(struct cmsghdr) : sizeof(control_un.control);
msg.msg_flags = 0;
cmptr = CMSG_FIRSTHDR(&msg);
@@ -1466,19 +1467,15 @@ t_timestamp_client(void)
dbgmsg(("msg_controllen = %u, cmsg_len = %u",
(u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len));
- if (sendmsg_timeout(fd, &msg, IPC_MESSAGE_SIZE) < 0)
- goto failed_close;
-
- if (close_socket((const char *)NULL, fd) < 0)
- goto failed;
-
- _exit(0);
-
-failed_close:
- (void)close_socket((const char *)NULL, fd);
+ if (send_message(fd, &msg, IPC_MESSAGE_SIZE) < 0)
+ goto done;
+ rv = EXIT_SUCCESS;
+done:
+ if (close_socket((char *)NULL, fd) < 0)
+ rv = EXIT_FAILURE;
failed:
- _exit(1);
+ _exit(rv);
}
/*
@@ -1490,36 +1487,40 @@ t_timestamp_server(int fd1)
{
union {
struct cmsghdr cm;
- char control[CMSG_SPACE(sizeof(struct timeval)) + EXTRA_CMSG_SPACE];
+ char control[CMSG_SPACE(sizeof(struct timeval)) +
+ EXTRA_CMSG_SPACE];
} control_un;
- char buf[IPC_MESSAGE_SIZE];
- int error, fd2;
struct msghdr msg;
struct iovec iov[1];
struct cmsghdr *cmptr;
const struct timeval *timeval;
+ int fd2, rv;
+ char buf[IPC_MESSAGE_SIZE];
if (sock_type == SOCK_STREAM) {
- if ((fd2 = accept_timeout(fd1)) < 0)
+ fd2 = accept_connection(fd1);
+ if (fd2 < 0)
return (-2);
} else
fd2 = fd1;
iov[0].iov_base = buf;
- iov[0].iov_len = sizeof buf;
+ iov[0].iov_len = sizeof(buf);
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control = control_un.control;
- msg.msg_controllen = sizeof control_un.control;;
+ msg.msg_controllen = sizeof(control_un.control);
msg.msg_flags = 0;
- if (recvmsg_timeout(fd2, &msg, sizeof buf) < 0)
- goto failed;
+ if (recv_message(fd2, &msg, sizeof(buf)) < 0) {
+ rv = -2;
+ goto done;
+ }
- error = -1;
+ rv = -1;
if (msg.msg_flags & MSG_CTRUNC) {
logmsgx("control data was truncated, MSG_CTRUNC flag is on");
@@ -1527,12 +1528,13 @@ t_timestamp_server(int fd1)
}
if (msg.msg_controllen < sizeof(struct cmsghdr)) {
- logmsgx("msg_controllen %u < %lu (sizeof(struct cmsghdr))",
- (u_int)msg.msg_controllen, (u_long)sizeof(struct cmsghdr));
+ logmsgx("msg_controllen %u < %zu (sizeof(struct cmsghdr))",
+ (u_int)msg.msg_controllen, sizeof(struct cmsghdr));
goto done;
}
- if ((cmptr = CMSG_FIRSTHDR(&msg)) == NULL) {
+ cmptr = CMSG_FIRSTHDR(&msg);
+ if (cmptr == NULL) {
logmsgx("CMSG_FIRSTHDR is NULL");
goto done;
}
@@ -1551,80 +1553,202 @@ t_timestamp_server(int fd1)
}
if (cmptr->cmsg_len != CMSG_LEN(sizeof(struct timeval))) {
- logmsgx("cmsg_len %u != %lu (CMSG_LEN(sizeof(struct timeval))",
- (u_int)cmptr->cmsg_len, (u_long)CMSG_LEN(sizeof(struct timeval)));
+ logmsgx("cmsg_len %u != %zu (CMSG_LEN(sizeof(struct timeval))",
+ (u_int)cmptr->cmsg_len, CMSG_LEN(sizeof(struct timeval)));
goto done;
}
- timeval = (const struct timeval *)CMSG_DATA(cmptr);
+ timeval = (struct timeval *)CMSG_DATA(cmptr);
- dbgmsg(("timeval tv_sec %jd, tv_usec %jd",
+ dbgmsg(("timeval tv_sec %"PRIdMAX", tv_usec %"PRIdMAX,
(intmax_t)timeval->tv_sec, (intmax_t)timeval->tv_usec));
- if ((cmptr = CMSG_NXTHDR(&msg, cmptr)) != NULL) {
- logmsgx("control data has extra header");
+ if (CMSG_NXTHDR(&msg, cmptr) != NULL) {
+ logmsgx("control data has extra header, this is wrong");
goto done;
}
- error = 0;
-
+ rv = 0;
done:
if (sock_type == SOCK_STREAM)
- if (close(fd2) < 0) {
- logmsg("close");
- return (-2);
- }
- return (error);
-
-failed:
- if (sock_type == SOCK_STREAM)
- if (close(fd2) < 0)
- logmsg("close");
- return (-2);
+ if (close_socket((char *)NULL, fd2) < 0)
+ rv = -2;
+ return (rv);
}
static int
t_timestamp(void)
{
- int error, fd;
+ int fd, rv;
- if ((fd = create_server_socket()) < 0)
+ fd = create_server_socket();
+ if (fd < 0)
return (-2);
- if (sock_type == SOCK_STREAM)
- if (listen(fd, LISTENQ) < 0) {
- logmsg("listen");
- goto failed;
- }
+ rv = -2;
- if ((client_pid = fork()) == (pid_t)-1) {
- logmsg("fork");
- goto failed;
- }
+ if (fork_client() < 0)
+ goto done;
if (client_pid == 0) {
- myname = "CLIENT";
- if (close_socket((const char *)NULL, fd) < 0)
- _exit(1);
+ if (close_socket((char *)NULL, fd) < 0)
+ _exit(EXIT_FAILURE);
t_timestamp_client();
}
- if ((error = t_timestamp_server(fd)) == -2) {
- (void)wait_client();
- goto failed;
- }
+ rv = t_timestamp_server(fd);
if (wait_client() < 0)
+ rv = -2;
+done:
+ if (close_socket(serv_sock_path, fd) < 0)
+ rv = -2;
+ return (rv);
+}
+
+/*
+ * Verify that xucred structure has correct credentials.
+ */
+static int
+check_xucred(const struct xucred *xucred, socklen_t len)
+{
+ if (len != sizeof(*xucred)) {
+ logmsgx("option value size %zu != %zu (sizeof(struct xucred))",
+ (size_t)len, sizeof(*xucred));
+ return (-1);
+ }
+ if (xucred->cr_version != XUCRED_VERSION) {
+ logmsgx("cr_version %u != %d (XUCRED_VERSION)",
+ xucred->cr_version, XUCRED_VERSION);
+ return (-1);
+ }
+ if (xucred->cr_uid != my_euid) {
+ logmsgx("cr_uid %lu != %lu (EUID of current process)",
+ (u_long)xucred->cr_uid, (u_long)my_euid);
+ return (-1);
+ }
+ if (xucred->cr_ngroups == 0) {
+ logmsgx("cr_ngroups = 0, this is wrong");
+ return (-1);
+ }
+ if (xucred->cr_ngroups < 0) {
+ logmsgx("cr_ngroups < 0, this is wrong");
+ return (-1);
+ }
+ if (xucred->cr_ngroups > NGROUPS_MAX) {
+ logmsgx("cr_ngroups %hu > %u (NGROUPS_MAX)",
+ xucred->cr_ngroups, NGROUPS_MAX);
+ return (-1);
+ }
+ if (xucred->cr_groups[0] != my_egid) {
+ logmsgx("cr_groups[0] %lu != %lu (EGID of current process)",
+ (u_long)xucred->cr_groups[0], (u_long)my_egid);
+ return (-1);
+ }
+ if (check_groups(xucred->cr_groups, xucred->cr_ngroups) < 0) {
+ logmsgx("cr_groups has wrong GIDs");
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Connect to server and set LOCAL_PEERCRED socket option for connected
+ * socket. Verify that credentials of the peer are correct.
+ */
+static void
+t_peercred_client(void)
+{
+ struct xucred xucred;
+ socklen_t len;
+ int fd, rv;
+
+ rv = EXIT_FAILURE;
+
+ fd = create_client_socket();
+ if (fd < 0)
goto failed;
- if (close_socket(serv_sock_path, fd) < 0) {
- logmsgx("close_socket failed");
- return (-2);
+ if (connect_server(fd) < 0)
+ goto done;
+
+ len = sizeof(xucred);
+ if (getsockopt(fd, 0, LOCAL_PEERCRED, &xucred, &len) < 0) {
+ logmsg("getsockopt(LOCAL_PEERCRED)");
+ goto done;
}
- return (error);
+ if (check_xucred(&xucred, len) < 0)
+ goto done;
+
+ rv = EXIT_SUCCESS;
+done:
+ if (close_socket((char *)NULL, fd) < 0)
+ rv = EXIT_FAILURE;
failed:
+ _exit(rv);
+}
+
+/*
+ * Accept connection from client and set LOCAL_PEERCRED socket option for
+ * connected socket. Verify that credentials of the peer are correct.
+ */
+static int
+t_peercred_server(int fd1)
+{
+ struct xucred xucred;
+ socklen_t len;
+ int fd2, rv;
+
+ fd2 = accept_connection(fd1);
+ if (fd2 < 0)
+ return (-2);
+
+ len = sizeof(xucred);
+ if (getsockopt(fd2, 0, LOCAL_PEERCRED, &xucred, &len) < 0) {
+ logmsg("getsockopt(LOCAL_PEERCRED)");
+ rv = -2;
+ goto done;
+ }
+
+ if (check_xucred(&xucred, len) < 0) {
+ rv = -1;
+ goto done;
+ }
+
+ rv = 0;
+done:
+ if (close_socket((char *)NULL, fd2) < 0)
+ rv = -2;
+ return (rv);
+}
+
+static int
+t_peercred(void)
+{
+ int fd, rv;
+
+ fd = create_server_socket();
+ if (fd < 0)
+ return (-2);
+
+ rv = -2;
+
+ if (fork_client() < 0)
+ goto done;
+
+ if (client_pid == 0) {
+ if (close_socket((char *)NULL, fd) < 0)
+ _exit(EXIT_FAILURE);
+ t_peercred_client();
+ }
+
+ rv = t_peercred_server(fd);
+
+ if (wait_client() < 0)
+ rv = -2;
+done:
if (close_socket(serv_sock_path, fd) < 0)
- logmsgx("close_socket failed");
- return (-2);
+ rv = -2;
+ return (rv);
}
diff -ruNp unix_cmsg.orig/unix_cmsg.t unix_cmsg/unix_cmsg.t
--- unix_cmsg.orig/unix_cmsg.t 2006-05-29 21:40:55.000000000 +0300
+++ unix_cmsg/unix_cmsg.t 2012-10-01 13:47:17.000000000 +0300
@@ -23,14 +23,15 @@ run()
done
}
-echo "1..15"
+echo "1..16"
for desc in \
"Sending, receiving cmsgcred" \
- "Receiving sockcred (listening socket has LOCAL_CREDS) # TODO" \
- "Receiving sockcred (accepted socket has LOCAL_CREDS) # TODO" \
- "Sending cmsgcred, receiving sockcred # TODO" \
- "Sending, receiving timestamp"
+ "Receiving sockcred (listening socket has LOCAL_CREDS)" \
+ "Receiving sockcred (accepted socket has LOCAL_CREDS)" \
+ "Sending cmsgcred, receiving sockcred" \
+ "Sending, receiving timestamp" \
+ "Check LOCAL_PEERCRED socket option"
do
n=`expr ${n} + 1`
run ${n} stream "" ${n} "STREAM ${desc}"
@@ -48,10 +49,10 @@ do
run ${n} dgram "" ${i} "DGRAM ${desc}"
done
-run 10 stream -z 1 "STREAM Sending, receiving cmsgcred (no control data)"
-run 11 stream -z 4 "STREAM Sending cmsgcred, receiving sockcred (no control data) # TODO"
-run 12 stream -z 5 "STREAM Sending, receiving timestamp (no control data)"
+run 11 stream -z 1 "STREAM Sending, receiving cmsgcred (no control data)"
+run 12 stream -z 4 "STREAM Sending cmsgcred, receiving sockcred (no control data) # TODO"
+run 13 stream -z 5 "STREAM Sending, receiving timestamp (no control data)"
-run 13 dgram -z 1 "DGRAM Sending, receiving cmsgcred (no control data)"
-run 14 dgram -z 3 "DGRAM Sending cmsgcred, receiving sockcred (no control data) # TODO"
-run 15 dgram -z 4 "DGRAM Sending, receiving timestamp (no control data)"
+run 14 dgram -z 1 "DGRAM Sending, receiving cmsgcred (no control data)"
+run 15 dgram -z 3 "DGRAM Sending cmsgcred, receiving sockcred (no control data) # TODO"
+run 16 dgram -z 4 "DGRAM Sending, receiving timestamp (no control data)"
More information about the freebsd-net
mailing list