Index: stable/11/tools/regression/sockets/unix_cmsg/Makefile =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/Makefile (revision 339065) +++ stable/11/tools/regression/sockets/unix_cmsg/Makefile (revision 339066) @@ -1,32 +1,37 @@ # $FreeBSD$ PROG= unix_cmsg +SRCS= ${AUTOSRCS} unix_cmsg.c uc_common.h uc_common.c \ + t_generic.h t_generic.c t_peercred.h t_peercred.c \ + t_cmsgcred.h t_cmsgcred.c t_sockcred.h t_sockcred.c \ + t_cmsgcred_sockcred.h t_cmsgcred_sockcred.c t_cmsg_len.h t_cmsg_len.c +CLEANFILES+= ${AUTOSRCS} MAN= WARNS?= 3 REXP_bintime= 's|%%TTYPE%%|bintime|g ; s|%%DTYPE%%|bintime|g ; \ s|%%SCM_TTYPE%%|SCM_BINTIME|g ; \ s|%%MAJ_MEMB%%|sec|g ; s|%%MIN_MEMB%%|frac|g' REXP_timeval= 's|%%TTYPE%%|timeval|g ; s|%%DTYPE%%|timeval|g ; \ s|%%SCM_TTYPE%%|SCM_TIMESTAMP|g ; \ s|%%MAJ_MEMB%%|tv_sec|g ; s|%%MIN_MEMB%%|tv_usec|g' REXP_timespec_real= 's|%%TTYPE%%|timespec_real|g ; s|%%DTYPE%%|timespec|g ; \ s|%%SCM_TTYPE%%|SCM_REALTIME|g ; \ s|%%MAJ_MEMB%%|tv_sec|g ; s|%%MIN_MEMB%%|tv_nsec|g' REXP_timespec_mono= 's|%%TTYPE%%|timespec_mono|g ; s|%%DTYPE%%|timespec|g ; \ s|%%SCM_TTYPE%%|SCM_MONOTONIC|g ; \ s|%%MAJ_MEMB%%|tv_sec|g ; s|%%MIN_MEMB%%|tv_nsec|g' .for ttype in bintime timeval timespec_real timespec_mono AUTOSRCS+= t_${ttype}.h t_${ttype}.c t_${ttype}.o: t_${ttype}.c t_${ttype}.h t_${ttype}.c: t_xxxtime.c.in sed ${REXP_${ttype}} < ${.ALLSRC} > ${.TARGET} t_${ttype}.h: t_xxxtime.h.in sed ${REXP_${ttype}} < ${.ALLSRC} > ${.TARGET} .endfor .include Index: stable/11/tools/regression/sockets/unix_cmsg/t_cmsg_len.c =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/t_cmsg_len.c (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/t_cmsg_len.c (revision 339066) @@ -0,0 +1,138 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uc_common.h" +#include "t_generic.h" +#include "t_cmsg_len.h" + +#ifndef __LP64__ +static int +t_cmsg_len_client(int fd) +{ + struct msghdr msghdr; + struct iovec iov[1]; + struct cmsghdr *cmsghdr; + void *cmsg_data; + size_t size, cmsg_size; + socklen_t socklen; + int rv; + + if (uc_sync_recv() < 0) + return (-2); + + rv = -2; + + cmsg_size = CMSG_SPACE(sizeof(struct cmsgcred)); + cmsg_data = malloc(cmsg_size); + if (cmsg_data == NULL) { + uc_logmsg("malloc"); + goto done; + } + uc_msghdr_init_client(&msghdr, iov, cmsg_data, cmsg_size, + SCM_CREDS, sizeof(struct cmsgcred)); + cmsghdr = CMSG_FIRSTHDR(&msghdr); + + if (uc_socket_connect(fd) < 0) + goto done; + + size = msghdr.msg_iov != NULL ? msghdr.msg_iov->iov_len : 0; + rv = -1; + for (socklen = 0; socklen < CMSG_LEN(0); ++socklen) { + cmsghdr->cmsg_len = socklen; + uc_dbgmsg("send: data size %zu", size); + uc_dbgmsg("send: msghdr.msg_controllen %u", + (u_int)msghdr.msg_controllen); + uc_dbgmsg("send: cmsghdr.cmsg_len %u", + (u_int)cmsghdr->cmsg_len); + if (sendmsg(fd, &msghdr, 0) < 0) { + uc_dbgmsg("sendmsg(2) failed: %s; retrying", + strerror(errno)); + continue; + } + uc_logmsgx("sent message with cmsghdr.cmsg_len %u < %u", + (u_int)cmsghdr->cmsg_len, (u_int)CMSG_LEN(0)); + break; + } + if (socklen == CMSG_LEN(0)) + rv = 0; + + if (uc_sync_send() < 0) { + rv = -2; + goto done; + } +done: + free(cmsg_data); + return (rv); +} + +static int +t_cmsg_len_server(int fd1) +{ + int fd2, rv; + + if (uc_sync_send() < 0) + return (-2); + + rv = -2; + + if (uc_cfg.sock_type == SOCK_STREAM) { + fd2 = uc_socket_accept(fd1); + if (fd2 < 0) + goto done; + } else + fd2 = fd1; + + if (uc_sync_recv() < 0) + goto done; + + rv = 0; +done: + if (uc_cfg.sock_type == SOCK_STREAM && fd2 >= 0) + if (uc_socket_close(fd2) < 0) + rv = -2; + return (rv); +} + +int +t_cmsg_len(void) +{ + return (t_generic(t_cmsg_len_client, t_cmsg_len_server)); +} +#endif Property changes on: stable/11/tools/regression/sockets/unix_cmsg/t_cmsg_len.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/t_cmsg_len.h =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/t_cmsg_len.h (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/t_cmsg_len.h (revision 339066) @@ -0,0 +1,32 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * Copyright (c) 2016 Maksym Sobolyev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __LP64__ +int t_cmsg_len(void); +#endif Property changes on: stable/11/tools/regression/sockets/unix_cmsg/t_cmsg_len.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred.c =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred.c (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred.c (revision 339066) @@ -0,0 +1,139 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include "uc_common.h" +#include "t_generic.h" +#include "t_cmsgcred.h" + +int +t_cmsgcred_client(int fd) +{ + struct msghdr msghdr; + struct iovec iov[1]; + void *cmsg_data; + size_t cmsg_size; + int rv; + + if (uc_sync_recv() < 0) + return (-2); + + rv = -2; + + cmsg_size = CMSG_SPACE(sizeof(struct cmsgcred)); + cmsg_data = malloc(cmsg_size); + if (cmsg_data == NULL) { + uc_logmsg("malloc"); + goto done; + } + uc_msghdr_init_client(&msghdr, iov, cmsg_data, cmsg_size, + SCM_CREDS, sizeof(struct cmsgcred)); + + if (uc_socket_connect(fd) < 0) + goto done; + + if (uc_message_sendn(fd, &msghdr) < 0) + goto done; + + rv = 0; +done: + free(cmsg_data); + return (rv); +} + +static int +t_cmsgcred_server(int fd1) +{ + struct msghdr msghdr; + struct iovec iov[1]; + struct cmsghdr *cmsghdr; + void *cmsg_data; + size_t cmsg_size; + u_int i; + int fd2, rv; + + if (uc_sync_send() < 0) + return (-2); + + fd2 = -1; + rv = -2; + + cmsg_size = CMSG_SPACE(sizeof(struct cmsgcred)); + cmsg_data = malloc(cmsg_size); + if (cmsg_data == NULL) { + uc_logmsg("malloc"); + goto done; + } + + if (uc_cfg.sock_type == SOCK_STREAM) { + fd2 = uc_socket_accept(fd1); + if (fd2 < 0) + goto done; + } else + fd2 = fd1; + + rv = -1; + for (i = 1; i <= uc_cfg.ipc_msg.msg_num; ++i) { + uc_dbgmsg("message #%u", i); + + uc_msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); + if (uc_message_recv(fd2, &msghdr) < 0) { + rv = -2; + break; + } + + if (uc_check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) + break; + + cmsghdr = CMSG_FIRSTHDR(&msghdr); + if (uc_check_scm_creds_cmsgcred(cmsghdr) < 0) + break; + } + if (i > uc_cfg.ipc_msg.msg_num) + rv = 0; +done: + free(cmsg_data); + if (uc_cfg.sock_type == SOCK_STREAM && fd2 >= 0) + if (uc_socket_close(fd2) < 0) + rv = -2; + return (rv); +} + +int +t_cmsgcred(void) +{ + return (t_generic(t_cmsgcred_client, t_cmsgcred_server)); +} Property changes on: stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred.h =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred.h (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred.h (revision 339066) @@ -0,0 +1,30 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +int t_cmsgcred_client(int fd); +int t_cmsgcred(void); Property changes on: stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred_sockcred.c =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred_sockcred.c (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred_sockcred.c (revision 339066) @@ -0,0 +1,125 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include "uc_common.h" +#include "t_generic.h" +#include "t_cmsgcred.h" +#include "t_cmsgcred_sockcred.h" + +static int +t_cmsgcred_sockcred_server(int fd1) +{ + struct msghdr msghdr; + struct iovec iov[1]; + struct cmsghdr *cmsghdr; + void *cmsg_data, *cmsg1_data, *cmsg2_data; + size_t cmsg_size, cmsg1_size, cmsg2_size; + u_int i; + int fd2, rv, val; + + fd2 = -1; + rv = -2; + + cmsg1_size = CMSG_SPACE(SOCKCREDSIZE(uc_cfg.proc_cred.gid_num)); + cmsg2_size = CMSG_SPACE(sizeof(struct cmsgcred)); + cmsg1_data = malloc(cmsg1_size); + cmsg2_data = malloc(cmsg2_size); + if (cmsg1_data == NULL || cmsg2_data == NULL) { + uc_logmsg("malloc"); + goto done; + } + + uc_dbgmsg("setting LOCAL_CREDS"); + val = 1; + if (setsockopt(fd1, 0, LOCAL_CREDS, &val, sizeof(val)) < 0) { + uc_logmsg("setsockopt(LOCAL_CREDS)"); + goto done; + } + + if (uc_sync_send() < 0) + goto done; + + if (uc_cfg.sock_type == SOCK_STREAM) { + fd2 = uc_socket_accept(fd1); + if (fd2 < 0) + goto done; + } else + fd2 = fd1; + + cmsg_data = cmsg1_data; + cmsg_size = cmsg1_size; + rv = -1; + for (i = 1; i <= uc_cfg.ipc_msg.msg_num; ++i) { + uc_dbgmsg("message #%u", i); + + uc_msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); + if (uc_message_recv(fd2, &msghdr) < 0) { + rv = -2; + break; + } + + if (uc_check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) + break; + + cmsghdr = CMSG_FIRSTHDR(&msghdr); + if (i == 1 || uc_cfg.sock_type == SOCK_DGRAM) { + if (uc_check_scm_creds_sockcred(cmsghdr) < 0) + break; + } else { + if (uc_check_scm_creds_cmsgcred(cmsghdr) < 0) + break; + } + + cmsg_data = cmsg2_data; + cmsg_size = cmsg2_size; + } + if (i > uc_cfg.ipc_msg.msg_num) + rv = 0; +done: + free(cmsg1_data); + free(cmsg2_data); + if (uc_cfg.sock_type == SOCK_STREAM && fd2 >= 0) + if (uc_socket_close(fd2) < 0) + rv = -2; + return (rv); +} + +int +t_cmsgcred_sockcred(void) +{ + return (t_generic(t_cmsgcred_client, t_cmsgcred_sockcred_server)); +} Property changes on: stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred_sockcred.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred_sockcred.h =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred_sockcred.h (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred_sockcred.h (revision 339066) @@ -0,0 +1,30 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * Copyright (c) 2016 Maksym Sobolyev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +int t_cmsgcred_sockcred(void); Property changes on: stable/11/tools/regression/sockets/unix_cmsg/t_cmsgcred_sockcred.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/t_generic.c =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/t_generic.c (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/t_generic.c (revision 339066) @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include "uc_common.h" +#include "t_generic.h" + +int +t_generic(int (*client_func)(int), int (*server_func)(int)) +{ + int fd, rv, rv_client; + + switch (uc_client_fork()) { + case 0: + fd = uc_socket_create(); + if (fd < 0) + rv = -2; + else { + rv = client_func(fd); + if (uc_socket_close(fd) < 0) + rv = -2; + } + uc_client_exit(rv); + break; + case 1: + fd = uc_socket_create(); + if (fd < 0) + rv = -2; + else { + rv = server_func(fd); + rv_client = uc_client_wait(); + if (rv == 0 || (rv == -2 && rv_client != 0)) + rv = rv_client; + if (uc_socket_close(fd) < 0) + rv = -2; + } + break; + default: + rv = -2; + } + return (rv); +} Property changes on: stable/11/tools/regression/sockets/unix_cmsg/t_generic.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/t_generic.h =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/t_generic.h (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/t_generic.h (revision 339066) @@ -0,0 +1,30 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * Copyright (c) 2016 Maksym Sobolyev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +int t_generic(int (*client_func)(int), int (*server_func)(int)); Property changes on: stable/11/tools/regression/sockets/unix_cmsg/t_generic.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/t_peercred.c =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/t_peercred.c (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/t_peercred.c (revision 339066) @@ -0,0 +1,153 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include "uc_common.h" +#include "t_generic.h" +#include "t_peercred.h" + +static int +check_xucred(const struct xucred *xucred, socklen_t len) +{ + int rc; + + if (len != sizeof(*xucred)) { + uc_logmsgx("option value size %zu != %zu", + (size_t)len, sizeof(*xucred)); + return (-1); + } + + uc_dbgmsg("xucred.cr_version %u", xucred->cr_version); + uc_dbgmsg("xucred.cr_uid %lu", (u_long)xucred->cr_uid); + uc_dbgmsg("xucred.cr_ngroups %d", xucred->cr_ngroups); + + rc = 0; + + if (xucred->cr_version != XUCRED_VERSION) { + uc_logmsgx("xucred.cr_version %u != %d", + xucred->cr_version, XUCRED_VERSION); + rc = -1; + } + if (xucred->cr_uid != uc_cfg.proc_cred.euid) { + uc_logmsgx("xucred.cr_uid %lu != %lu (EUID)", + (u_long)xucred->cr_uid, (u_long)uc_cfg.proc_cred.euid); + rc = -1; + } + if (xucred->cr_ngroups == 0) { + uc_logmsgx("xucred.cr_ngroups == 0"); + rc = -1; + } + if (xucred->cr_ngroups < 0) { + uc_logmsgx("xucred.cr_ngroups < 0"); + rc = -1; + } + if (xucred->cr_ngroups > XU_NGROUPS) { + uc_logmsgx("xucred.cr_ngroups %hu > %u (max)", + xucred->cr_ngroups, XU_NGROUPS); + rc = -1; + } + if (xucred->cr_groups[0] != uc_cfg.proc_cred.egid) { + uc_logmsgx("xucred.cr_groups[0] %lu != %lu (EGID)", + (u_long)xucred->cr_groups[0], (u_long)uc_cfg.proc_cred.egid); + rc = -1; + } + if (uc_check_groups("xucred.cr_groups", xucred->cr_groups, + "xucred.cr_ngroups", xucred->cr_ngroups, false) < 0) + rc = -1; + return (rc); +} + +static int +t_peercred_client(int fd) +{ + struct xucred xucred; + socklen_t len; + + if (uc_sync_recv() < 0) + return (-1); + + if (uc_socket_connect(fd) < 0) + return (-1); + + len = sizeof(xucred); + if (getsockopt(fd, 0, LOCAL_PEERCRED, &xucred, &len) < 0) { + uc_logmsg("getsockopt(LOCAL_PEERCRED)"); + return (-1); + } + + if (check_xucred(&xucred, len) < 0) + return (-1); + + return (0); +} + +static int +t_peercred_server(int fd1) +{ + struct xucred xucred; + socklen_t len; + int fd2, rv; + + if (uc_sync_send() < 0) + return (-2); + + fd2 = uc_socket_accept(fd1); + if (fd2 < 0) + return (-2); + + len = sizeof(xucred); + if (getsockopt(fd2, 0, LOCAL_PEERCRED, &xucred, &len) < 0) { + uc_logmsg("getsockopt(LOCAL_PEERCRED)"); + rv = -2; + goto done; + } + + if (check_xucred(&xucred, len) < 0) { + rv = -1; + goto done; + } + + rv = 0; +done: + if (uc_socket_close(fd2) < 0) + rv = -2; + return (rv); +} + +int +t_peercred(void) +{ + return (t_generic(t_peercred_client, t_peercred_server)); +} Property changes on: stable/11/tools/regression/sockets/unix_cmsg/t_peercred.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/t_peercred.h =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/t_peercred.h (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/t_peercred.h (revision 339066) @@ -0,0 +1,29 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +int t_peercred(void); Property changes on: stable/11/tools/regression/sockets/unix_cmsg/t_peercred.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/t_sockcred.c =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/t_sockcred.c (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/t_sockcred.c (revision 339066) @@ -0,0 +1,215 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include "uc_common.h" +#include "t_generic.h" +#include "t_sockcred.h" + +static int +t_sockcred_client(int type, int fd) +{ + struct msghdr msghdr; + struct iovec iov[1]; + int rv; + + if (uc_sync_recv() < 0) + return (-2); + + rv = -2; + + uc_msghdr_init_client(&msghdr, iov, NULL, 0, 0, 0); + + if (uc_socket_connect(fd) < 0) + goto done; + + if (type == 2) + if (uc_sync_recv() < 0) + goto done; + + if (uc_message_sendn(fd, &msghdr) < 0) + goto done; + + rv = 0; +done: + return (rv); +} + +static int +t_sockcred_server(int type, int fd1) +{ + struct msghdr msghdr; + struct iovec iov[1]; + struct cmsghdr *cmsghdr; + void *cmsg_data; + size_t cmsg_size; + u_int i; + int fd2, rv, val; + + fd2 = -1; + rv = -2; + + cmsg_size = CMSG_SPACE(SOCKCREDSIZE(uc_cfg.proc_cred.gid_num)); + cmsg_data = malloc(cmsg_size); + if (cmsg_data == NULL) { + uc_logmsg("malloc"); + goto done; + } + + if (type == 1) { + uc_dbgmsg("setting LOCAL_CREDS"); + val = 1; + if (setsockopt(fd1, 0, LOCAL_CREDS, &val, sizeof(val)) < 0) { + uc_logmsg("setsockopt(LOCAL_CREDS)"); + goto done; + } + } + + if (uc_sync_send() < 0) + goto done; + + if (uc_cfg.sock_type == SOCK_STREAM) { + fd2 = uc_socket_accept(fd1); + if (fd2 < 0) + goto done; + } else + fd2 = fd1; + + if (type == 2) { + uc_dbgmsg("setting LOCAL_CREDS"); + val = 1; + if (setsockopt(fd2, 0, LOCAL_CREDS, &val, sizeof(val)) < 0) { + uc_logmsg("setsockopt(LOCAL_CREDS)"); + goto done; + } + if (uc_sync_send() < 0) + goto done; + } + + rv = -1; + for (i = 1; i <= uc_cfg.ipc_msg.msg_num; ++i) { + uc_dbgmsg("message #%u", i); + + uc_msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); + if (uc_message_recv(fd2, &msghdr) < 0) { + rv = -2; + break; + } + + if (i > 1 && uc_cfg.sock_type == SOCK_STREAM) { + if (uc_check_msghdr(&msghdr, 0) < 0) + break; + } else { + if (uc_check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) + break; + + cmsghdr = CMSG_FIRSTHDR(&msghdr); + if (uc_check_scm_creds_sockcred(cmsghdr) < 0) + break; + } + } + if (i > uc_cfg.ipc_msg.msg_num) + rv = 0; +done: + free(cmsg_data); + if (uc_cfg.sock_type == SOCK_STREAM && fd2 >= 0) + if (uc_socket_close(fd2) < 0) + rv = -2; + return (rv); +} + +int +t_sockcred_1(void) +{ + u_int i; + int fd, rv, rv_client; + + switch (uc_client_fork()) { + case 0: + for (i = 1; i <= 2; ++i) { + uc_dbgmsg("client #%u", i); + fd = uc_socket_create(); + if (fd < 0) + rv = -2; + else { + rv = t_sockcred_client(1, fd); + if (uc_socket_close(fd) < 0) + rv = -2; + } + if (rv != 0) + break; + } + uc_client_exit(rv); + break; + case 1: + fd = uc_socket_create(); + if (fd < 0) + rv = -2; + else { + rv = t_sockcred_server(1, fd); + if (rv == 0) + rv = t_sockcred_server(3, fd); + rv_client = uc_client_wait(); + if (rv == 0 || (rv == -2 && rv_client != 0)) + rv = rv_client; + if (uc_socket_close(fd) < 0) + rv = -2; + } + break; + default: + rv = -2; + } + + return (rv); +} + +static int +t_sockcred_2_client(int fd) +{ + return (t_sockcred_client(2, fd)); +} + +static int +t_sockcred_2_server(int fd) +{ + return (t_sockcred_server(2, fd)); +} + +int +t_sockcred_2(void) +{ + return (t_generic(t_sockcred_2_client, t_sockcred_2_server)); +} Property changes on: stable/11/tools/regression/sockets/unix_cmsg/t_sockcred.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/t_sockcred.h =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/t_sockcred.h (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/t_sockcred.h (revision 339066) @@ -0,0 +1,31 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * Copyright (c) 2016 Maksym Sobolyev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +int t_sockcred_1(void); +int t_sockcred_2(void); Property changes on: stable/11/tools/regression/sockets/unix_cmsg/t_sockcred.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/t_xxxtime.c.in =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/t_xxxtime.c.in (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/t_xxxtime.c.in (revision 339066) @@ -0,0 +1,158 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "t_%%TTYPE%%.h" +#include "t_generic.h" +#include "uc_common.h" + +#if defined(%%SCM_TTYPE%%) +static int +check_scm_%%TTYPE%%(struct cmsghdr *cmsghdr) +{ + const struct %%DTYPE%% *bt; + + if (uc_check_cmsghdr(cmsghdr, %%SCM_TTYPE%%, sizeof(struct %%DTYPE%%)) < 0) + return (-1); + + bt = (struct %%DTYPE%% *)CMSG_DATA(cmsghdr); + + uc_dbgmsg("%%DTYPE%%.%%MAJ_MEMB%% %"PRIdMAX", %%DTYPE%%.%%MIN_MEMB%% %"PRIuMAX, + (intmax_t)bt->%%MAJ_MEMB%%, (uintmax_t)bt->%%MIN_MEMB%%); + + return (0); +} + +static int +t_%%TTYPE%%_client(int fd) +{ + struct msghdr msghdr; + struct iovec iov[1]; + void *cmsg_data; + size_t cmsg_size; + int rv; + + if (uc_sync_recv() < 0) + return (-2); + + rv = -2; + + cmsg_size = CMSG_SPACE(sizeof(struct %%DTYPE%%)); + cmsg_data = malloc(cmsg_size); + if (cmsg_data == NULL) { + uc_logmsg("malloc"); + goto done; + } + uc_msghdr_init_client(&msghdr, iov, cmsg_data, cmsg_size, + %%SCM_TTYPE%%, sizeof(struct %%DTYPE%%)); + + if (uc_socket_connect(fd) < 0) + goto done; + + if (uc_message_sendn(fd, &msghdr) < 0) + goto done; + + rv = 0; +done: + free(cmsg_data); + return (rv); +} + +static int +t_%%TTYPE%%_server(int fd1) +{ + struct msghdr msghdr; + struct iovec iov[1]; + struct cmsghdr *cmsghdr; + void *cmsg_data; + size_t cmsg_size; + u_int i; + int fd2, rv; + + if (uc_sync_send() < 0) + return (-2); + + fd2 = -1; + rv = -2; + + cmsg_size = CMSG_SPACE(sizeof(struct %%DTYPE%%)); + cmsg_data = malloc(cmsg_size); + if (cmsg_data == NULL) { + uc_logmsg("malloc"); + goto done; + } + + if (uc_cfg.sock_type == SOCK_STREAM) { + fd2 = uc_socket_accept(fd1); + if (fd2 < 0) + goto done; + } else + fd2 = fd1; + + rv = -1; + for (i = 1; i <= uc_cfg.ipc_msg.msg_num; ++i) { + uc_dbgmsg("message #%u", i); + + uc_msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); + if (uc_message_recv(fd2, &msghdr) < 0) { + rv = -2; + break; + } + + if (uc_check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) + break; + + cmsghdr = CMSG_FIRSTHDR(&msghdr); + if (check_scm_%%TTYPE%%(cmsghdr) < 0) + break; + } + if (i > uc_cfg.ipc_msg.msg_num) + rv = 0; +done: + free(cmsg_data); + if (uc_cfg.sock_type == SOCK_STREAM && fd2 >= 0) + if (uc_socket_close(fd2) < 0) + rv = -2; + return (rv); +} + +int +t_%%TTYPE%%(void) +{ + return (t_generic(t_%%TTYPE%%_client, t_%%TTYPE%%_server)); +} +#endif /* %%SCM_TTYPE%% */ Property changes on: stable/11/tools/regression/sockets/unix_cmsg/t_xxxtime.c.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/t_xxxtime.h.in =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/t_xxxtime.h.in (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/t_xxxtime.h.in (revision 339066) @@ -0,0 +1,32 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * Copyright (c) 2016 Maksym Sobolyev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#if defined(%%SCM_TTYPE%%) +int t_%%TTYPE%%(void); +#endif Property changes on: stable/11/tools/regression/sockets/unix_cmsg/t_xxxtime.h.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/uc_common.c =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/uc_common.c (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/uc_common.c (revision 339066) @@ -0,0 +1,744 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uc_common.h" + +#ifndef LISTENQ +# define LISTENQ 1 +#endif + +#ifndef TIMEOUT +# define TIMEOUT 2 +#endif + +#define SYNC_SERVER 0 +#define SYNC_CLIENT 1 +#define SYNC_RECV 0 +#define SYNC_SEND 1 + +#define LOGMSG_SIZE 128 + +void +uc_output(const char *format, ...) +{ + char buf[LOGMSG_SIZE]; + va_list ap; + + va_start(ap, format); + if (vsnprintf(buf, sizeof(buf), format, ap) < 0) + err(EXIT_FAILURE, "output: vsnprintf failed"); + write(STDOUT_FILENO, buf, strlen(buf)); + va_end(ap); +} + +void +uc_logmsg(const char *format, ...) +{ + char buf[LOGMSG_SIZE]; + va_list ap; + int errno_save; + + errno_save = errno; + va_start(ap, format); + if (vsnprintf(buf, sizeof(buf), format, ap) < 0) + err(EXIT_FAILURE, "logmsg: vsnprintf failed"); + if (errno_save == 0) + uc_output("%s: %s\n", uc_cfg.proc_name, buf); + else + uc_output("%s: %s: %s\n", uc_cfg.proc_name, buf, + strerror(errno_save)); + va_end(ap); + errno = errno_save; +} + +void +uc_vlogmsgx(const char *format, va_list ap) +{ + char buf[LOGMSG_SIZE]; + + if (vsnprintf(buf, sizeof(buf), format, ap) < 0) + err(EXIT_FAILURE, "uc_logmsgx: vsnprintf failed"); + uc_output("%s: %s\n", uc_cfg.proc_name, buf); +} + +void +uc_logmsgx(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + uc_vlogmsgx(format, ap); + va_end(ap); +} + +void +uc_dbgmsg(const char *format, ...) +{ + va_list ap; + + if (uc_cfg.debug) { + va_start(ap, format); + uc_vlogmsgx(format, ap); + va_end(ap); + } +} + +int +uc_socket_create(void) +{ + struct timeval tv; + int fd; + + fd = socket(PF_LOCAL, uc_cfg.sock_type, 0); + if (fd < 0) { + uc_logmsg("socket_create: socket(PF_LOCAL, %s, 0)", uc_cfg.sock_type_str); + return (-1); + } + if (uc_cfg.server_flag) + uc_cfg.serv_sock_fd = fd; + + 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) { + uc_logmsg("socket_create: setsockopt(SO_RCVTIMEO/SO_SNDTIMEO)"); + goto failed; + } + + if (uc_cfg.server_flag) { + if (bind(fd, (struct sockaddr *)&uc_cfg.serv_addr_sun, + uc_cfg.serv_addr_sun.sun_len) < 0) { + uc_logmsg("socket_create: bind(%s)", + uc_cfg.serv_addr_sun.sun_path); + goto failed; + } + if (uc_cfg.sock_type == SOCK_STREAM) { + int val; + + if (listen(fd, LISTENQ) < 0) { + uc_logmsg("socket_create: listen"); + goto failed; + } + val = fcntl(fd, F_GETFL, 0); + if (val < 0) { + uc_logmsg("socket_create: fcntl(F_GETFL)"); + goto failed; + } + if (fcntl(fd, F_SETFL, val | O_NONBLOCK) < 0) { + uc_logmsg("socket_create: fcntl(F_SETFL)"); + goto failed; + } + } + } + + return (fd); + +failed: + if (close(fd) < 0) + uc_logmsg("socket_create: close"); + if (uc_cfg.server_flag) + if (unlink(uc_cfg.serv_addr_sun.sun_path) < 0) + uc_logmsg("socket_close: unlink(%s)", + uc_cfg.serv_addr_sun.sun_path); + return (-1); +} + +int +uc_socket_close(int fd) +{ + int rv; + + rv = 0; + if (close(fd) < 0) { + uc_logmsg("socket_close: close"); + rv = -1; + } + if (uc_cfg.server_flag && fd == uc_cfg.serv_sock_fd) + if (unlink(uc_cfg.serv_addr_sun.sun_path) < 0) { + uc_logmsg("socket_close: unlink(%s)", + uc_cfg.serv_addr_sun.sun_path); + rv = -1; + } + return (rv); +} + +int +uc_socket_connect(int fd) +{ + uc_dbgmsg("connect"); + + if (connect(fd, (struct sockaddr *)&uc_cfg.serv_addr_sun, + uc_cfg.serv_addr_sun.sun_len) < 0) { + uc_logmsg("socket_connect: connect(%s)", uc_cfg.serv_addr_sun.sun_path); + return (-1); + } + return (0); +} + +int +uc_sync_recv(void) +{ + ssize_t ssize; + int fd; + char buf; + + uc_dbgmsg("sync: wait"); + + fd = uc_cfg.sync_fd[uc_cfg.server_flag ? SYNC_SERVER : SYNC_CLIENT][SYNC_RECV]; + + ssize = read(fd, &buf, 1); + if (ssize < 0) { + uc_logmsg("sync_recv: read"); + return (-1); + } + if (ssize < 1) { + uc_logmsgx("sync_recv: read %zd of 1 byte", ssize); + return (-1); + } + + uc_dbgmsg("sync: received"); + + return (0); +} + +int +uc_sync_send(void) +{ + ssize_t ssize; + int fd; + + uc_dbgmsg("sync: send"); + + fd = uc_cfg.sync_fd[uc_cfg.server_flag ? SYNC_CLIENT : SYNC_SERVER][SYNC_SEND]; + + ssize = write(fd, "", 1); + if (ssize < 0) { + uc_logmsg("uc_sync_send: write"); + return (-1); + } + if (ssize < 1) { + uc_logmsgx("uc_sync_send: sent %zd of 1 byte", ssize); + return (-1); + } + + return (0); +} + +int +uc_message_send(int fd, const struct msghdr *msghdr) +{ + const struct cmsghdr *cmsghdr; + size_t size; + ssize_t ssize; + + size = msghdr->msg_iov != 0 ? msghdr->msg_iov->iov_len : 0; + uc_dbgmsg("send: data size %zu", size); + uc_dbgmsg("send: msghdr.msg_controllen %u", + (u_int)msghdr->msg_controllen); + cmsghdr = CMSG_FIRSTHDR(msghdr); + if (cmsghdr != NULL) + uc_dbgmsg("send: cmsghdr.cmsg_len %u", + (u_int)cmsghdr->cmsg_len); + + ssize = sendmsg(fd, msghdr, 0); + if (ssize < 0) { + uc_logmsg("message_send: sendmsg"); + return (-1); + } + if ((size_t)ssize != size) { + uc_logmsgx("message_send: sendmsg: sent %zd of %zu bytes", + ssize, size); + return (-1); + } + + if (!uc_cfg.send_data_flag) + if (uc_sync_send() < 0) + return (-1); + + return (0); +} + +int +uc_message_sendn(int fd, struct msghdr *msghdr) +{ + u_int i; + + for (i = 1; i <= uc_cfg.ipc_msg.msg_num; ++i) { + uc_dbgmsg("message #%u", i); + if (uc_message_send(fd, msghdr) < 0) + return (-1); + } + return (0); +} + +int +uc_message_recv(int fd, struct msghdr *msghdr) +{ + const struct cmsghdr *cmsghdr; + size_t size; + ssize_t ssize; + + if (!uc_cfg.send_data_flag) + if (uc_sync_recv() < 0) + return (-1); + + size = msghdr->msg_iov != NULL ? msghdr->msg_iov->iov_len : 0; + ssize = recvmsg(fd, msghdr, MSG_WAITALL); + if (ssize < 0) { + uc_logmsg("message_recv: recvmsg"); + return (-1); + } + if ((size_t)ssize != size) { + uc_logmsgx("message_recv: recvmsg: received %zd of %zu bytes", + ssize, size); + return (-1); + } + + uc_dbgmsg("recv: data size %zd", ssize); + uc_dbgmsg("recv: msghdr.msg_controllen %u", + (u_int)msghdr->msg_controllen); + cmsghdr = CMSG_FIRSTHDR(msghdr); + if (cmsghdr != NULL) + uc_dbgmsg("recv: cmsghdr.cmsg_len %u", + (u_int)cmsghdr->cmsg_len); + + if (memcmp(uc_cfg.ipc_msg.buf_recv, uc_cfg.ipc_msg.buf_send, size) != 0) { + uc_logmsgx("message_recv: received message has wrong content"); + return (-1); + } + + return (0); +} + +int +uc_socket_accept(int listenfd) +{ + fd_set rset; + struct timeval tv; + int fd, rv, val; + + uc_dbgmsg("accept"); + + 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) { + uc_logmsg("socket_accept: select"); + return (-1); + } + if (rv == 0) { + uc_logmsgx("socket_accept: select timeout"); + return (-1); + } + + fd = accept(listenfd, (struct sockaddr *)NULL, (socklen_t *)NULL); + if (fd < 0) { + uc_logmsg("socket_accept: accept"); + return (-1); + } + + val = fcntl(fd, F_GETFL, 0); + if (val < 0) { + uc_logmsg("socket_accept: fcntl(F_GETFL)"); + goto failed; + } + if (fcntl(fd, F_SETFL, val & ~O_NONBLOCK) < 0) { + uc_logmsg("socket_accept: fcntl(F_SETFL)"); + goto failed; + } + + return (fd); + +failed: + if (close(fd) < 0) + uc_logmsg("socket_accept: close"); + return (-1); +} + +int +uc_check_msghdr(const struct msghdr *msghdr, size_t size) +{ + if (msghdr->msg_flags & MSG_TRUNC) { + uc_logmsgx("msghdr.msg_flags has MSG_TRUNC"); + return (-1); + } + if (msghdr->msg_flags & MSG_CTRUNC) { + uc_logmsgx("msghdr.msg_flags has MSG_CTRUNC"); + return (-1); + } + if (msghdr->msg_controllen < size) { + uc_logmsgx("msghdr.msg_controllen %u < %zu", + (u_int)msghdr->msg_controllen, size); + return (-1); + } + if (msghdr->msg_controllen > 0 && size == 0) { + uc_logmsgx("msghdr.msg_controllen %u > 0", + (u_int)msghdr->msg_controllen); + return (-1); + } + return (0); +} + +int +uc_check_cmsghdr(const struct cmsghdr *cmsghdr, int type, size_t size) +{ + if (cmsghdr == NULL) { + uc_logmsgx("cmsghdr is NULL"); + return (-1); + } + if (cmsghdr->cmsg_level != SOL_SOCKET) { + uc_logmsgx("cmsghdr.cmsg_level %d != SOL_SOCKET", + cmsghdr->cmsg_level); + return (-1); + } + if (cmsghdr->cmsg_type != type) { + uc_logmsgx("cmsghdr.cmsg_type %d != %d", + cmsghdr->cmsg_type, type); + return (-1); + } + if (cmsghdr->cmsg_len != CMSG_LEN(size)) { + uc_logmsgx("cmsghdr.cmsg_len %u != %zu", + (u_int)cmsghdr->cmsg_len, CMSG_LEN(size)); + return (-1); + } + return (0); +} + +static void +uc_msghdr_init_generic(struct msghdr *msghdr, struct iovec *iov, void *cmsg_data) +{ + msghdr->msg_name = NULL; + msghdr->msg_namelen = 0; + if (uc_cfg.send_data_flag) { + iov->iov_base = uc_cfg.server_flag ? + uc_cfg.ipc_msg.buf_recv : uc_cfg.ipc_msg.buf_send; + iov->iov_len = uc_cfg.ipc_msg.buf_size; + msghdr->msg_iov = iov; + msghdr->msg_iovlen = 1; + } else { + msghdr->msg_iov = NULL; + msghdr->msg_iovlen = 0; + } + msghdr->msg_control = cmsg_data; + msghdr->msg_flags = 0; +} + +void +uc_msghdr_init_server(struct msghdr *msghdr, struct iovec *iov, + void *cmsg_data, size_t cmsg_size) +{ + uc_msghdr_init_generic(msghdr, iov, cmsg_data); + msghdr->msg_controllen = cmsg_size; + uc_dbgmsg("init: data size %zu", msghdr->msg_iov != NULL ? + msghdr->msg_iov->iov_len : (size_t)0); + uc_dbgmsg("init: msghdr.msg_controllen %u", + (u_int)msghdr->msg_controllen); +} + +void +uc_msghdr_init_client(struct msghdr *msghdr, struct iovec *iov, + void *cmsg_data, size_t cmsg_size, int type, size_t arr_size) +{ + struct cmsghdr *cmsghdr; + + uc_msghdr_init_generic(msghdr, iov, cmsg_data); + if (cmsg_data != NULL) { + if (uc_cfg.send_array_flag) + uc_dbgmsg("sending an array"); + else + uc_dbgmsg("sending a scalar"); + msghdr->msg_controllen = uc_cfg.send_array_flag ? + cmsg_size : CMSG_SPACE(0); + cmsghdr = CMSG_FIRSTHDR(msghdr); + cmsghdr->cmsg_level = SOL_SOCKET; + cmsghdr->cmsg_type = type; + cmsghdr->cmsg_len = CMSG_LEN(uc_cfg.send_array_flag ? arr_size : 0); + } else + msghdr->msg_controllen = 0; +} + +int +uc_client_fork(void) +{ + int fd1, fd2; + + if (pipe(uc_cfg.sync_fd[SYNC_SERVER]) < 0 || + pipe(uc_cfg.sync_fd[SYNC_CLIENT]) < 0) { + uc_logmsg("client_fork: pipe"); + return (-1); + } + uc_cfg.client_pid = fork(); + if (uc_cfg.client_pid == (pid_t)-1) { + uc_logmsg("client_fork: fork"); + return (-1); + } + if (uc_cfg.client_pid == 0) { + uc_cfg.proc_name = "CLIENT"; + uc_cfg.server_flag = false; + fd1 = uc_cfg.sync_fd[SYNC_SERVER][SYNC_RECV]; + fd2 = uc_cfg.sync_fd[SYNC_CLIENT][SYNC_SEND]; + } else { + fd1 = uc_cfg.sync_fd[SYNC_SERVER][SYNC_SEND]; + fd2 = uc_cfg.sync_fd[SYNC_CLIENT][SYNC_RECV]; + } + if (close(fd1) < 0 || close(fd2) < 0) { + uc_logmsg("client_fork: close"); + return (-1); + } + return (uc_cfg.client_pid != 0); +} + +void +uc_client_exit(int rv) +{ + if (close(uc_cfg.sync_fd[SYNC_SERVER][SYNC_SEND]) < 0 || + close(uc_cfg.sync_fd[SYNC_CLIENT][SYNC_RECV]) < 0) { + uc_logmsg("client_exit: close"); + rv = -1; + } + rv = rv == 0 ? EXIT_SUCCESS : -rv; + uc_dbgmsg("exit: code %d", rv); + _exit(rv); +} + +int +uc_client_wait(void) +{ + int status; + pid_t pid; + + uc_dbgmsg("waiting for client"); + + if (close(uc_cfg.sync_fd[SYNC_SERVER][SYNC_RECV]) < 0 || + close(uc_cfg.sync_fd[SYNC_CLIENT][SYNC_SEND]) < 0) { + uc_logmsg("client_wait: close"); + return (-1); + } + + pid = waitpid(uc_cfg.client_pid, &status, 0); + if (pid == (pid_t)-1) { + uc_logmsg("client_wait: waitpid"); + return (-1); + } + + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != EXIT_SUCCESS) { + uc_logmsgx("client exit status is %d", + WEXITSTATUS(status)); + return (-WEXITSTATUS(status)); + } + } else { + if (WIFSIGNALED(status)) + uc_logmsgx("abnormal termination of client, signal %d%s", + WTERMSIG(status), WCOREDUMP(status) ? + " (core file generated)" : ""); + else + uc_logmsgx("termination of client, unknown status"); + return (-1); + } + + return (0); +} + +int +uc_check_groups(const char *gid_arr_str, const gid_t *gid_arr, + const char *gid_num_str, int gid_num, bool all_gids) +{ + int i; + + for (i = 0; i < gid_num; ++i) + uc_dbgmsg("%s[%d] %lu", gid_arr_str, i, (u_long)gid_arr[i]); + + if (all_gids) { + if (gid_num != uc_cfg.proc_cred.gid_num) { + uc_logmsgx("%s %d != %d", gid_num_str, gid_num, + uc_cfg.proc_cred.gid_num); + return (-1); + } + } else { + if (gid_num > uc_cfg.proc_cred.gid_num) { + uc_logmsgx("%s %d > %d", gid_num_str, gid_num, + uc_cfg.proc_cred.gid_num); + return (-1); + } + } + if (memcmp(gid_arr, uc_cfg.proc_cred.gid_arr, + gid_num * sizeof(*gid_arr)) != 0) { + uc_logmsgx("%s content is wrong", gid_arr_str); + for (i = 0; i < gid_num; ++i) + if (gid_arr[i] != uc_cfg.proc_cred.gid_arr[i]) { + uc_logmsgx("%s[%d] %lu != %lu", + gid_arr_str, i, (u_long)gid_arr[i], + (u_long)uc_cfg.proc_cred.gid_arr[i]); + break; + } + return (-1); + } + return (0); +} + +int +uc_check_scm_creds_cmsgcred(struct cmsghdr *cmsghdr) +{ + const struct cmsgcred *cmcred; + int rc; + + if (uc_check_cmsghdr(cmsghdr, SCM_CREDS, sizeof(struct cmsgcred)) < 0) + return (-1); + + cmcred = (struct cmsgcred *)CMSG_DATA(cmsghdr); + + uc_dbgmsg("cmsgcred.cmcred_pid %ld", (long)cmcred->cmcred_pid); + uc_dbgmsg("cmsgcred.cmcred_uid %lu", (u_long)cmcred->cmcred_uid); + uc_dbgmsg("cmsgcred.cmcred_euid %lu", (u_long)cmcred->cmcred_euid); + uc_dbgmsg("cmsgcred.cmcred_gid %lu", (u_long)cmcred->cmcred_gid); + uc_dbgmsg("cmsgcred.cmcred_ngroups %d", cmcred->cmcred_ngroups); + + rc = 0; + + if (cmcred->cmcred_pid != uc_cfg.client_pid) { + uc_logmsgx("cmsgcred.cmcred_pid %ld != %ld", + (long)cmcred->cmcred_pid, (long)uc_cfg.client_pid); + rc = -1; + } + if (cmcred->cmcred_uid != uc_cfg.proc_cred.uid) { + uc_logmsgx("cmsgcred.cmcred_uid %lu != %lu", + (u_long)cmcred->cmcred_uid, (u_long)uc_cfg.proc_cred.uid); + rc = -1; + } + if (cmcred->cmcred_euid != uc_cfg.proc_cred.euid) { + uc_logmsgx("cmsgcred.cmcred_euid %lu != %lu", + (u_long)cmcred->cmcred_euid, (u_long)uc_cfg.proc_cred.euid); + rc = -1; + } + if (cmcred->cmcred_gid != uc_cfg.proc_cred.gid) { + uc_logmsgx("cmsgcred.cmcred_gid %lu != %lu", + (u_long)cmcred->cmcred_gid, (u_long)uc_cfg.proc_cred.gid); + rc = -1; + } + if (cmcred->cmcred_ngroups == 0) { + uc_logmsgx("cmsgcred.cmcred_ngroups == 0"); + rc = -1; + } + if (cmcred->cmcred_ngroups < 0) { + uc_logmsgx("cmsgcred.cmcred_ngroups %d < 0", + cmcred->cmcred_ngroups); + rc = -1; + } + if (cmcred->cmcred_ngroups > CMGROUP_MAX) { + uc_logmsgx("cmsgcred.cmcred_ngroups %d > %d", + cmcred->cmcred_ngroups, CMGROUP_MAX); + rc = -1; + } + if (cmcred->cmcred_groups[0] != uc_cfg.proc_cred.egid) { + uc_logmsgx("cmsgcred.cmcred_groups[0] %lu != %lu (EGID)", + (u_long)cmcred->cmcred_groups[0], (u_long)uc_cfg.proc_cred.egid); + rc = -1; + } + if (uc_check_groups("cmsgcred.cmcred_groups", cmcred->cmcred_groups, + "cmsgcred.cmcred_ngroups", cmcred->cmcred_ngroups, false) < 0) + rc = -1; + return (rc); +} + +int +uc_check_scm_creds_sockcred(struct cmsghdr *cmsghdr) +{ + const struct sockcred *sc; + int rc; + + if (uc_check_cmsghdr(cmsghdr, SCM_CREDS, + SOCKCREDSIZE(uc_cfg.proc_cred.gid_num)) < 0) + return (-1); + + sc = (struct sockcred *)CMSG_DATA(cmsghdr); + + rc = 0; + + uc_dbgmsg("sockcred.sc_uid %lu", (u_long)sc->sc_uid); + uc_dbgmsg("sockcred.sc_euid %lu", (u_long)sc->sc_euid); + uc_dbgmsg("sockcred.sc_gid %lu", (u_long)sc->sc_gid); + uc_dbgmsg("sockcred.sc_egid %lu", (u_long)sc->sc_egid); + uc_dbgmsg("sockcred.sc_ngroups %d", sc->sc_ngroups); + + if (sc->sc_uid != uc_cfg.proc_cred.uid) { + uc_logmsgx("sockcred.sc_uid %lu != %lu", + (u_long)sc->sc_uid, (u_long)uc_cfg.proc_cred.uid); + rc = -1; + } + if (sc->sc_euid != uc_cfg.proc_cred.euid) { + uc_logmsgx("sockcred.sc_euid %lu != %lu", + (u_long)sc->sc_euid, (u_long)uc_cfg.proc_cred.euid); + rc = -1; + } + if (sc->sc_gid != uc_cfg.proc_cred.gid) { + uc_logmsgx("sockcred.sc_gid %lu != %lu", + (u_long)sc->sc_gid, (u_long)uc_cfg.proc_cred.gid); + rc = -1; + } + if (sc->sc_egid != uc_cfg.proc_cred.egid) { + uc_logmsgx("sockcred.sc_egid %lu != %lu", + (u_long)sc->sc_egid, (u_long)uc_cfg.proc_cred.egid); + rc = -1; + } + if (sc->sc_ngroups == 0) { + uc_logmsgx("sockcred.sc_ngroups == 0"); + rc = -1; + } + if (sc->sc_ngroups < 0) { + uc_logmsgx("sockcred.sc_ngroups %d < 0", + sc->sc_ngroups); + rc = -1; + } + if (sc->sc_ngroups != uc_cfg.proc_cred.gid_num) { + uc_logmsgx("sockcred.sc_ngroups %d != %u", + sc->sc_ngroups, uc_cfg.proc_cred.gid_num); + rc = -1; + } + if (uc_check_groups("sockcred.sc_groups", sc->sc_groups, + "sockcred.sc_ngroups", sc->sc_ngroups, true) < 0) + rc = -1; + return (rc); +} Property changes on: stable/11/tools/regression/sockets/unix_cmsg/uc_common.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/uc_common.h =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/uc_common.h (nonexistent) +++ stable/11/tools/regression/sockets/unix_cmsg/uc_common.h (revision 339066) @@ -0,0 +1,86 @@ +/*- + * Copyright (c) 2005 Andrey Simonenko + * Copyright (c) 2016 Maksym Sobolyev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +struct uc_cfg { + int sock_type; + const char *sock_type_str; + bool debug; + const char *proc_name; + int sync_fd[2][2]; + int serv_sock_fd; + bool server_flag; + bool send_data_flag; + struct sockaddr_un serv_addr_sun; + bool send_array_flag; + pid_t client_pid; + struct { + char *buf_send; + char *buf_recv; + size_t buf_size; + u_int msg_num; + } ipc_msg; + struct { + uid_t uid; + uid_t euid; + gid_t gid; + gid_t egid; + gid_t *gid_arr; + int gid_num; + } proc_cred; +}; + +extern struct uc_cfg uc_cfg; + +int uc_check_msghdr(const struct msghdr *msghdr, size_t size); +int uc_check_cmsghdr(const struct cmsghdr *cmsghdr, int type, size_t size); +void uc_output(const char *format, ...) __printflike(1, 2); +void uc_logmsgx(const char *format, ...) __printflike(1, 2); +void uc_dbgmsg(const char *format, ...) __printflike(1, 2); +void uc_logmsg(const char *format, ...) __printflike(1, 2); +void uc_vlogmsgx(const char *format, va_list ap); +int uc_message_recv(int fd, struct msghdr *msghdr); +int uc_message_send(int fd, const struct msghdr *msghdr); +int uc_message_sendn(int fd, struct msghdr *msghdr); +void uc_msghdr_init_server(struct msghdr *msghdr, struct iovec *iov, + void *cmsg_data, size_t cmsg_size); +void uc_msghdr_init_client(struct msghdr *msghdr, struct iovec *iov, + void *cmsg_data, size_t cmsg_size, int type, size_t arr_size); +int uc_socket_create(void); +int uc_socket_accept(int listenfd); +int uc_socket_close(int fd); +int uc_socket_connect(int fd); +int uc_sync_recv(void); +int uc_sync_send(void); +int uc_client_fork(void); +void uc_client_exit(int rv); +int uc_client_wait(void); +int uc_check_groups(const char *gid_arr_str, const gid_t *gid_arr, + const char *gid_num_str, int gid_num, bool all_gids); +int uc_check_scm_creds_cmsgcred(struct cmsghdr *cmsghdr); +int uc_check_scm_creds_sockcred(struct cmsghdr *cmsghdr); Property changes on: stable/11/tools/regression/sockets/unix_cmsg/uc_common.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/tools/regression/sockets/unix_cmsg/unix_cmsg.c =================================================================== --- stable/11/tools/regression/sockets/unix_cmsg/unix_cmsg.c (revision 339065) +++ stable/11/tools/regression/sockets/unix_cmsg/unix_cmsg.c (revision 339066) @@ -1,2034 +1,452 @@ /*- * Copyright (c) 2005 Andrey Simonenko * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); -#include -#include -#include -#include +#include +#include #include -#include #include -#include -#include #include -#include -#include #include -#include #include #include #include #include -#include #include #include #include #include #include "uc_common.h" #include "t_cmsgcred.h" #include "t_bintime.h" #include "t_generic.h" #include "t_peercred.h" #include "t_timeval.h" #include "t_sockcred.h" #include "t_cmsgcred_sockcred.h" #include "t_cmsg_len.h" #include "t_timespec_real.h" #include "t_timespec_mono.h" /* * There are tables with tests descriptions and pointers to test * functions. Each t_*() function returns 0 if its test passed, * -1 if its test failed, -2 if some system error occurred. * If a test function returns -2, then a program exits. * * If a test function forks a client process, then it waits for its * termination. If a return code of a client process is not equal * to zero, or if a client process was terminated by a signal, then * a test function returns -1 or -2 depending on exit status of * a client process. * * Each function which can block, is run under TIMEOUT. If timeout * occurs, then a test function returns -2 or a client process exits * with a non-zero return code. */ -#ifndef LISTENQ -# define LISTENQ 1 -#endif - -#ifndef TIMEOUT -# define TIMEOUT 2 -#endif - -static int t_cmsgcred(void); -static int t_sockcred_1(void); -static int t_sockcred_2(void); -static int t_cmsgcred_sockcred(void); -static int t_timeval(void); -static int t_bintime(void); -/* - * The testcase fails on 64-bit architectures (amd64), but passes on 32-bit - * architectures (i386); see bug 206543 - */ -#ifndef __LP64__ -static int t_cmsg_len(void); -#endif -static int t_peercred(void); - struct test_func { int (*func)(void); const char *desc; }; static const struct test_func test_stream_tbl[] = { { .func = NULL, .desc = "All tests" }, { .func = t_cmsgcred, .desc = "Sending, receiving cmsgcred" }, { .func = t_sockcred_1, .desc = "Receiving sockcred (listening socket)" }, { .func = t_sockcred_2, .desc = "Receiving sockcred (accepted socket)" }, { .func = t_cmsgcred_sockcred, .desc = "Sending cmsgcred, receiving sockcred" }, { .func = t_timeval, .desc = "Sending, receiving timeval" }, { .func = t_bintime, .desc = "Sending, receiving bintime" }, +/* + * The testcase fails on 64-bit architectures (amd64), but passes on 32-bit + * architectures (i386); see bug 206543 + */ #ifndef __LP64__ { .func = t_cmsg_len, .desc = "Check cmsghdr.cmsg_len" }, #endif { .func = t_peercred, .desc = "Check LOCAL_PEERCRED socket option" }, #if defined(SCM_REALTIME) { .func = t_timespec_real, .desc = "Sending, receiving realtime" }, #endif #if defined(SCM_MONOTONIC) { .func = t_timespec_mono, .desc = "Sending, receiving monotonic time (uptime)" } #endif }; #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_2, .desc = "Receiving sockcred" }, { .func = t_cmsgcred_sockcred, .desc = "Sending cmsgcred, receiving sockcred" }, { .func = t_timeval, .desc = "Sending, receiving timeval" }, { .func = t_bintime, .desc = "Sending, receiving bintime" }, #ifndef __LP64__ { .func = t_cmsg_len, .desc = "Check cmsghdr.cmsg_len" }, #endif #if defined(SCM_REALTIME) { .func = t_timespec_real, .desc = "Sending, receiving realtime" }, #endif #if defined(SCM_MONOTONIC) { .func = t_timespec_mono, .desc = "Sending, receiving monotonic time (uptime)" } #endif }; #define TEST_DGRAM_TBL_SIZE \ (sizeof(test_dgram_tbl) / sizeof(test_dgram_tbl[0])) -static bool debug = false; -static bool server_flag = true; -static bool send_data_flag = true; -static bool send_array_flag = true; static bool failed_flag = false; -static int sock_type; -static const char *sock_type_str; +struct uc_cfg uc_cfg; -static const char *proc_name; - static char work_dir[] = _PATH_TMP "unix_cmsg.XXXXXXX"; -static int serv_sock_fd; -static struct sockaddr_un serv_addr_sun; -static struct { - char *buf_send; - char *buf_recv; - size_t buf_size; - u_int msg_num; -} ipc_msg; - #define IPC_MSG_NUM_DEF 5 #define IPC_MSG_NUM_MAX 10 #define IPC_MSG_SIZE_DEF 7 #define IPC_MSG_SIZE_MAX 128 -static struct { - uid_t uid; - uid_t euid; - gid_t gid; - gid_t egid; - gid_t *gid_arr; - int gid_num; -} proc_cred; - -static pid_t client_pid; - -#define SYNC_SERVER 0 -#define SYNC_CLIENT 1 -#define SYNC_RECV 0 -#define SYNC_SEND 1 - -static int sync_fd[2][2]; - -#define LOGMSG_SIZE 128 - -static void logmsg(const char *, ...) __printflike(1, 2); -static void logmsgx(const char *, ...) __printflike(1, 2); -static void dbgmsg(const char *, ...) __printflike(1, 2); -static void output(const char *, ...) __printflike(1, 2); - static void usage(bool verbose) { u_int i; printf("usage: %s [-dh] [-n num] [-s size] [-t type] " "[-z value] [testno]\n", getprogname()); if (!verbose) return; printf("\n Options are:\n\ -d Output debugging information\n\ -h Output the help message and exit\n\ -n num Number of messages to send\n\ -s size Specify size of data for IPC\n\ -t type Specify socket type (stream, dgram) for tests\n\ -z value Do not send data in a message (bit 0x1), do not send\n\ data array associated with a cmsghdr structure (bit 0x2)\n\ testno Run one test by its number (require the -t option)\n\n"); printf(" Available tests for stream sockets:\n"); for (i = 0; i < TEST_STREAM_TBL_SIZE; ++i) printf(" %u: %s\n", i, test_stream_tbl[i].desc); printf("\n Available tests for datagram sockets:\n"); for (i = 0; i < TEST_DGRAM_TBL_SIZE; ++i) printf(" %u: %s\n", i, test_dgram_tbl[i].desc); } -static void -output(const char *format, ...) -{ - char buf[LOGMSG_SIZE]; - va_list ap; - - va_start(ap, format); - if (vsnprintf(buf, sizeof(buf), format, ap) < 0) - err(EXIT_FAILURE, "output: vsnprintf failed"); - write(STDOUT_FILENO, buf, strlen(buf)); - va_end(ap); -} - -static void -logmsg(const char *format, ...) -{ - char buf[LOGMSG_SIZE]; - va_list ap; - int errno_save; - - errno_save = errno; - va_start(ap, format); - if (vsnprintf(buf, sizeof(buf), format, ap) < 0) - err(EXIT_FAILURE, "logmsg: vsnprintf failed"); - if (errno_save == 0) - output("%s: %s\n", proc_name, buf); - else - output("%s: %s: %s\n", proc_name, buf, strerror(errno_save)); - va_end(ap); - errno = errno_save; -} - -static void -vlogmsgx(const char *format, va_list ap) -{ - char buf[LOGMSG_SIZE]; - - if (vsnprintf(buf, sizeof(buf), format, ap) < 0) - err(EXIT_FAILURE, "logmsgx: vsnprintf failed"); - output("%s: %s\n", proc_name, buf); - -} - -static void -logmsgx(const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - vlogmsgx(format, ap); - va_end(ap); -} - -static void -dbgmsg(const char *format, ...) -{ - va_list ap; - - if (debug) { - va_start(ap, format); - vlogmsgx(format, ap); - va_end(ap); - } -} - static int run_tests(int type, u_int testno1) { const struct test_func *tf; u_int i, testno2, failed_num; - sock_type = type; + uc_cfg.sock_type = type; if (type == SOCK_STREAM) { - sock_type_str = "SOCK_STREAM"; + uc_cfg.sock_type_str = "SOCK_STREAM"; tf = test_stream_tbl; i = TEST_STREAM_TBL_SIZE - 1; } else { - sock_type_str = "SOCK_DGRAM"; + uc_cfg.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); + uc_output("Running tests for %s sockets:\n", uc_cfg.sock_type_str); failed_num = 0; for (i = testno1, tf += testno1; i <= testno2; ++tf, ++i) { - output(" %u: %s\n", i, tf->desc); + uc_output(" %u: %s\n", i, tf->desc); switch (tf->func()) { case -1: ++failed_num; break; case -2: - logmsgx("some system error or timeout occurred"); + uc_logmsgx("some system error or timeout occurred"); return (-1); } } if (failed_num != 0) failed_flag = true; if (testno1 != testno2) { if (failed_num == 0) - output("-- all tests passed!\n"); + uc_output("-- all tests passed!\n"); else - output("-- %u test%s failed!\n", + uc_output("-- %u test%s failed!\n", failed_num, failed_num == 1 ? "" : "s"); } else { if (failed_num == 0) - output("-- test passed!\n"); + uc_output("-- test passed!\n"); else - output("-- test failed!\n"); + uc_output("-- test failed!\n"); } return (0); } static int init(void) { struct sigaction sigact; size_t idx; int rv; - proc_name = "SERVER"; + uc_cfg.proc_name = "SERVER"; sigact.sa_handler = SIG_IGN; sigact.sa_flags = 0; sigemptyset(&sigact.sa_mask); if (sigaction(SIGPIPE, &sigact, (struct sigaction *)NULL) < 0) { - logmsg("init: sigaction"); + uc_logmsg("init: sigaction"); return (-1); } - if (ipc_msg.buf_size == 0) - ipc_msg.buf_send = ipc_msg.buf_recv = NULL; + if (uc_cfg.ipc_msg.buf_size == 0) + uc_cfg.ipc_msg.buf_send = uc_cfg.ipc_msg.buf_recv = NULL; else { - ipc_msg.buf_send = malloc(ipc_msg.buf_size); - ipc_msg.buf_recv = malloc(ipc_msg.buf_size); - if (ipc_msg.buf_send == NULL || ipc_msg.buf_recv == NULL) { - logmsg("init: malloc"); + uc_cfg.ipc_msg.buf_send = malloc(uc_cfg.ipc_msg.buf_size); + uc_cfg.ipc_msg.buf_recv = malloc(uc_cfg.ipc_msg.buf_size); + if (uc_cfg.ipc_msg.buf_send == NULL || uc_cfg.ipc_msg.buf_recv == NULL) { + uc_logmsg("init: malloc"); return (-1); } - for (idx = 0; idx < ipc_msg.buf_size; ++idx) - ipc_msg.buf_send[idx] = (char)idx; + for (idx = 0; idx < uc_cfg.ipc_msg.buf_size; ++idx) + uc_cfg.ipc_msg.buf_send[idx] = (char)idx; } - proc_cred.uid = getuid(); - proc_cred.euid = geteuid(); - proc_cred.gid = getgid(); - proc_cred.egid = getegid(); - proc_cred.gid_num = getgroups(0, (gid_t *)NULL); - if (proc_cred.gid_num < 0) { - logmsg("init: getgroups"); + uc_cfg.proc_cred.uid = getuid(); + uc_cfg.proc_cred.euid = geteuid(); + uc_cfg.proc_cred.gid = getgid(); + uc_cfg.proc_cred.egid = getegid(); + uc_cfg.proc_cred.gid_num = getgroups(0, (gid_t *)NULL); + if (uc_cfg.proc_cred.gid_num < 0) { + uc_logmsg("init: getgroups"); return (-1); } - proc_cred.gid_arr = malloc(proc_cred.gid_num * - sizeof(*proc_cred.gid_arr)); - if (proc_cred.gid_arr == NULL) { - logmsg("init: malloc"); + uc_cfg.proc_cred.gid_arr = malloc(uc_cfg.proc_cred.gid_num * + sizeof(*uc_cfg.proc_cred.gid_arr)); + if (uc_cfg.proc_cred.gid_arr == NULL) { + uc_logmsg("init: malloc"); return (-1); } - if (getgroups(proc_cred.gid_num, proc_cred.gid_arr) < 0) { - logmsg("init: getgroups"); + if (getgroups(uc_cfg.proc_cred.gid_num, uc_cfg.proc_cred.gid_arr) < 0) { + uc_logmsg("init: getgroups"); return (-1); } - memset(&serv_addr_sun, 0, sizeof(serv_addr_sun)); - rv = snprintf(serv_addr_sun.sun_path, sizeof(serv_addr_sun.sun_path), - "%s/%s", work_dir, proc_name); + memset(&uc_cfg.serv_addr_sun, 0, sizeof(uc_cfg.serv_addr_sun)); + rv = snprintf(uc_cfg.serv_addr_sun.sun_path, sizeof(uc_cfg.serv_addr_sun.sun_path), + "%s/%s", work_dir, uc_cfg.proc_name); if (rv < 0) { - logmsg("init: snprintf"); + uc_logmsg("init: snprintf"); return (-1); } - if ((size_t)rv >= sizeof(serv_addr_sun.sun_path)) { - logmsgx("init: not enough space for socket pathname"); + if ((size_t)rv >= sizeof(uc_cfg.serv_addr_sun.sun_path)) { + uc_logmsgx("init: not enough space for socket pathname"); return (-1); } - serv_addr_sun.sun_family = PF_LOCAL; - serv_addr_sun.sun_len = SUN_LEN(&serv_addr_sun); + uc_cfg.serv_addr_sun.sun_family = PF_LOCAL; + uc_cfg.serv_addr_sun.sun_len = SUN_LEN(&uc_cfg.serv_addr_sun); return (0); } -static int -client_fork(void) -{ - int fd1, fd2; - - if (pipe(sync_fd[SYNC_SERVER]) < 0 || - pipe(sync_fd[SYNC_CLIENT]) < 0) { - logmsg("client_fork: pipe"); - return (-1); - } - client_pid = fork(); - if (client_pid == (pid_t)-1) { - logmsg("client_fork: fork"); - return (-1); - } - if (client_pid == 0) { - proc_name = "CLIENT"; - server_flag = false; - fd1 = sync_fd[SYNC_SERVER][SYNC_RECV]; - fd2 = sync_fd[SYNC_CLIENT][SYNC_SEND]; - } else { - fd1 = sync_fd[SYNC_SERVER][SYNC_SEND]; - fd2 = sync_fd[SYNC_CLIENT][SYNC_RECV]; - } - if (close(fd1) < 0 || close(fd2) < 0) { - logmsg("client_fork: close"); - return (-1); - } - return (client_pid != 0); -} - -static void -client_exit(int rv) -{ - if (close(sync_fd[SYNC_SERVER][SYNC_SEND]) < 0 || - close(sync_fd[SYNC_CLIENT][SYNC_RECV]) < 0) { - logmsg("client_exit: close"); - rv = -1; - } - rv = rv == 0 ? EXIT_SUCCESS : -rv; - dbgmsg("exit: code %d", rv); - _exit(rv); -} - -static int -client_wait(void) -{ - int status; - pid_t pid; - - dbgmsg("waiting for client"); - - if (close(sync_fd[SYNC_SERVER][SYNC_RECV]) < 0 || - close(sync_fd[SYNC_CLIENT][SYNC_SEND]) < 0) { - logmsg("client_wait: close"); - return (-1); - } - - pid = waitpid(client_pid, &status, 0); - if (pid == (pid_t)-1) { - logmsg("client_wait: waitpid"); - return (-1); - } - - if (WIFEXITED(status)) { - if (WEXITSTATUS(status) != EXIT_SUCCESS) { - logmsgx("client exit status is %d", - WEXITSTATUS(status)); - return (-WEXITSTATUS(status)); - } - } else { - if (WIFSIGNALED(status)) - logmsgx("abnormal termination of client, signal %d%s", - WTERMSIG(status), WCOREDUMP(status) ? - " (core file generated)" : ""); - else - logmsgx("termination of client, unknown status"); - return (-1); - } - - return (0); -} - int main(int argc, char *argv[]) { const char *errstr; u_int testno, zvalue; int opt, rv; bool dgram_flag, stream_flag; - ipc_msg.buf_size = IPC_MSG_SIZE_DEF; - ipc_msg.msg_num = IPC_MSG_NUM_DEF; + memset(&uc_cfg, '\0', sizeof(uc_cfg)); + uc_cfg.debug = false; + uc_cfg.server_flag = true; + uc_cfg.send_data_flag = true; + uc_cfg.send_array_flag = true; + uc_cfg.ipc_msg.buf_size = IPC_MSG_SIZE_DEF; + uc_cfg.ipc_msg.msg_num = IPC_MSG_NUM_DEF; dgram_flag = stream_flag = false; while ((opt = getopt(argc, argv, "dhn:s:t:z:")) != -1) switch (opt) { case 'd': - debug = true; + uc_cfg.debug = true; break; case 'h': usage(true); return (EXIT_SUCCESS); case 'n': - ipc_msg.msg_num = strtonum(optarg, 1, + uc_cfg.ipc_msg.msg_num = strtonum(optarg, 1, IPC_MSG_NUM_MAX, &errstr); if (errstr != NULL) errx(EXIT_FAILURE, "option -n: number is %s", errstr); break; case 's': - ipc_msg.buf_size = strtonum(optarg, 0, + uc_cfg.ipc_msg.buf_size = strtonum(optarg, 0, IPC_MSG_SIZE_MAX, &errstr); if (errstr != NULL) errx(EXIT_FAILURE, "option -s: number is %s", errstr); break; case 't': if (strcmp(optarg, "stream") == 0) stream_flag = true; else if (strcmp(optarg, "dgram") == 0) dgram_flag = true; else errx(EXIT_FAILURE, "option -t: " "wrong socket type"); break; case 'z': zvalue = strtonum(optarg, 0, 3, &errstr); if (errstr != NULL) errx(EXIT_FAILURE, "option -z: number is %s", errstr); if (zvalue & 0x1) - send_data_flag = false; + uc_cfg.send_data_flag = false; if (zvalue & 0x2) - send_array_flag = false; + uc_cfg.send_array_flag = false; break; default: usage(false); return (EXIT_FAILURE); } if (optind < argc) { if (optind + 1 != argc) errx(EXIT_FAILURE, "too many arguments"); testno = strtonum(argv[optind], 0, UINT_MAX, &errstr); if (errstr != NULL) errx(EXIT_FAILURE, "test number is %s", errstr); if (stream_flag && testno >= TEST_STREAM_TBL_SIZE) errx(EXIT_FAILURE, "given test %u for stream " "sockets does not exist", testno); if (dgram_flag && testno >= TEST_DGRAM_TBL_SIZE) errx(EXIT_FAILURE, "given test %u for datagram " "sockets does not exist", testno); } else testno = 0; if (!dgram_flag && !stream_flag) { if (testno != 0) errx(EXIT_FAILURE, "particular test number " "can be used with the -t option only"); dgram_flag = stream_flag = true; } if (mkdtemp(work_dir) == NULL) err(EXIT_FAILURE, "mkdtemp(%s)", work_dir); rv = EXIT_FAILURE; if (init() < 0) goto done; if (stream_flag) if (run_tests(SOCK_STREAM, testno) < 0) goto done; if (dgram_flag) if (run_tests(SOCK_DGRAM, testno) < 0) goto done; rv = EXIT_SUCCESS; done: if (rmdir(work_dir) < 0) { - logmsg("rmdir(%s)", work_dir); + uc_logmsg("rmdir(%s)", work_dir); rv = EXIT_FAILURE; } return (failed_flag ? EXIT_FAILURE : rv); -} - -static int -socket_close(int fd) -{ - int rv; - - rv = 0; - if (close(fd) < 0) { - logmsg("socket_close: close"); - rv = -1; - } - if (server_flag && fd == serv_sock_fd) - if (unlink(serv_addr_sun.sun_path) < 0) { - logmsg("socket_close: unlink(%s)", - serv_addr_sun.sun_path); - rv = -1; - } - return (rv); -} - -static int -socket_create(void) -{ - struct timeval tv; - int fd; - - fd = socket(PF_LOCAL, sock_type, 0); - if (fd < 0) { - logmsg("socket_create: socket(PF_LOCAL, %s, 0)", sock_type_str); - return (-1); - } - if (server_flag) - serv_sock_fd = fd; - - 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("socket_create: setsockopt(SO_RCVTIMEO/SO_SNDTIMEO)"); - goto failed; - } - - if (server_flag) { - if (bind(fd, (struct sockaddr *)&serv_addr_sun, - serv_addr_sun.sun_len) < 0) { - logmsg("socket_create: bind(%s)", - serv_addr_sun.sun_path); - goto failed; - } - if (sock_type == SOCK_STREAM) { - int val; - - if (listen(fd, LISTENQ) < 0) { - logmsg("socket_create: listen"); - goto failed; - } - val = fcntl(fd, F_GETFL, 0); - if (val < 0) { - logmsg("socket_create: fcntl(F_GETFL)"); - goto failed; - } - if (fcntl(fd, F_SETFL, val | O_NONBLOCK) < 0) { - logmsg("socket_create: fcntl(F_SETFL)"); - goto failed; - } - } - } - - return (fd); - -failed: - if (close(fd) < 0) - logmsg("socket_create: close"); - if (server_flag) - if (unlink(serv_addr_sun.sun_path) < 0) - logmsg("socket_close: unlink(%s)", - serv_addr_sun.sun_path); - return (-1); -} - -static int -socket_connect(int fd) -{ - dbgmsg("connect"); - - if (connect(fd, (struct sockaddr *)&serv_addr_sun, - serv_addr_sun.sun_len) < 0) { - logmsg("socket_connect: connect(%s)", serv_addr_sun.sun_path); - return (-1); - } - return (0); -} - -static int -sync_recv(void) -{ - ssize_t ssize; - int fd; - char buf; - - dbgmsg("sync: wait"); - - fd = sync_fd[server_flag ? SYNC_SERVER : SYNC_CLIENT][SYNC_RECV]; - - ssize = read(fd, &buf, 1); - if (ssize < 0) { - logmsg("sync_recv: read"); - return (-1); - } - if (ssize < 1) { - logmsgx("sync_recv: read %zd of 1 byte", ssize); - return (-1); - } - - dbgmsg("sync: received"); - - return (0); -} - -static int -sync_send(void) -{ - ssize_t ssize; - int fd; - - dbgmsg("sync: send"); - - fd = sync_fd[server_flag ? SYNC_CLIENT : SYNC_SERVER][SYNC_SEND]; - - ssize = write(fd, "", 1); - if (ssize < 0) { - logmsg("sync_send: write"); - return (-1); - } - if (ssize < 1) { - logmsgx("sync_send: sent %zd of 1 byte", ssize); - return (-1); - } - - return (0); -} - -static int -message_send(int fd, const struct msghdr *msghdr) -{ - const struct cmsghdr *cmsghdr; - size_t size; - ssize_t ssize; - - size = msghdr->msg_iov != 0 ? msghdr->msg_iov->iov_len : 0; - dbgmsg("send: data size %zu", size); - dbgmsg("send: msghdr.msg_controllen %u", - (u_int)msghdr->msg_controllen); - cmsghdr = CMSG_FIRSTHDR(msghdr); - if (cmsghdr != NULL) - dbgmsg("send: cmsghdr.cmsg_len %u", - (u_int)cmsghdr->cmsg_len); - - ssize = sendmsg(fd, msghdr, 0); - if (ssize < 0) { - logmsg("message_send: sendmsg"); - return (-1); - } - if ((size_t)ssize != size) { - logmsgx("message_send: sendmsg: sent %zd of %zu bytes", - ssize, size); - return (-1); - } - - if (!send_data_flag) - if (sync_send() < 0) - return (-1); - - return (0); -} - -static int -message_sendn(int fd, struct msghdr *msghdr) -{ - u_int i; - - for (i = 1; i <= ipc_msg.msg_num; ++i) { - dbgmsg("message #%u", i); - if (message_send(fd, msghdr) < 0) - return (-1); - } - return (0); -} - -static int -message_recv(int fd, struct msghdr *msghdr) -{ - const struct cmsghdr *cmsghdr; - size_t size; - ssize_t ssize; - - if (!send_data_flag) - if (sync_recv() < 0) - return (-1); - - size = msghdr->msg_iov != NULL ? msghdr->msg_iov->iov_len : 0; - ssize = recvmsg(fd, msghdr, MSG_WAITALL); - if (ssize < 0) { - logmsg("message_recv: recvmsg"); - return (-1); - } - if ((size_t)ssize != size) { - logmsgx("message_recv: recvmsg: received %zd of %zu bytes", - ssize, size); - return (-1); - } - - dbgmsg("recv: data size %zd", ssize); - dbgmsg("recv: msghdr.msg_controllen %u", - (u_int)msghdr->msg_controllen); - cmsghdr = CMSG_FIRSTHDR(msghdr); - if (cmsghdr != NULL) - dbgmsg("recv: cmsghdr.cmsg_len %u", - (u_int)cmsghdr->cmsg_len); - - if (memcmp(ipc_msg.buf_recv, ipc_msg.buf_send, size) != 0) { - logmsgx("message_recv: received message has wrong content"); - return (-1); - } - - return (0); -} - -static int -socket_accept(int listenfd) -{ - fd_set rset; - struct timeval tv; - int fd, rv, val; - - dbgmsg("accept"); - - 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("socket_accept: select"); - return (-1); - } - if (rv == 0) { - logmsgx("socket_accept: select timeout"); - return (-1); - } - - fd = accept(listenfd, (struct sockaddr *)NULL, (socklen_t *)NULL); - if (fd < 0) { - logmsg("socket_accept: accept"); - return (-1); - } - - val = fcntl(fd, F_GETFL, 0); - if (val < 0) { - logmsg("socket_accept: fcntl(F_GETFL)"); - goto failed; - } - if (fcntl(fd, F_SETFL, val & ~O_NONBLOCK) < 0) { - logmsg("socket_accept: fcntl(F_SETFL)"); - goto failed; - } - - return (fd); - -failed: - if (close(fd) < 0) - logmsg("socket_accept: close"); - return (-1); -} - -static int -check_msghdr(const struct msghdr *msghdr, size_t size) -{ - if (msghdr->msg_flags & MSG_TRUNC) { - logmsgx("msghdr.msg_flags has MSG_TRUNC"); - return (-1); - } - if (msghdr->msg_flags & MSG_CTRUNC) { - logmsgx("msghdr.msg_flags has MSG_CTRUNC"); - return (-1); - } - if (msghdr->msg_controllen < size) { - logmsgx("msghdr.msg_controllen %u < %zu", - (u_int)msghdr->msg_controllen, size); - return (-1); - } - if (msghdr->msg_controllen > 0 && size == 0) { - logmsgx("msghdr.msg_controllen %u > 0", - (u_int)msghdr->msg_controllen); - return (-1); - } - return (0); -} - -static int -check_cmsghdr(const struct cmsghdr *cmsghdr, int type, size_t size) -{ - if (cmsghdr == NULL) { - logmsgx("cmsghdr is NULL"); - return (-1); - } - if (cmsghdr->cmsg_level != SOL_SOCKET) { - logmsgx("cmsghdr.cmsg_level %d != SOL_SOCKET", - cmsghdr->cmsg_level); - return (-1); - } - if (cmsghdr->cmsg_type != type) { - logmsgx("cmsghdr.cmsg_type %d != %d", - cmsghdr->cmsg_type, type); - return (-1); - } - if (cmsghdr->cmsg_len != CMSG_LEN(size)) { - logmsgx("cmsghdr.cmsg_len %u != %zu", - (u_int)cmsghdr->cmsg_len, CMSG_LEN(size)); - return (-1); - } - return (0); -} - -static int -check_groups(const char *gid_arr_str, const gid_t *gid_arr, - const char *gid_num_str, int gid_num, bool all_gids) -{ - int i; - - for (i = 0; i < gid_num; ++i) - dbgmsg("%s[%d] %lu", gid_arr_str, i, (u_long)gid_arr[i]); - - if (all_gids) { - if (gid_num != proc_cred.gid_num) { - logmsgx("%s %d != %d", gid_num_str, gid_num, - proc_cred.gid_num); - return (-1); - } - } else { - if (gid_num > proc_cred.gid_num) { - logmsgx("%s %d > %d", gid_num_str, gid_num, - proc_cred.gid_num); - return (-1); - } - } - if (memcmp(gid_arr, proc_cred.gid_arr, - gid_num * sizeof(*gid_arr)) != 0) { - logmsgx("%s content is wrong", gid_arr_str); - for (i = 0; i < gid_num; ++i) - if (gid_arr[i] != proc_cred.gid_arr[i]) { - logmsgx("%s[%d] %lu != %lu", - gid_arr_str, i, (u_long)gid_arr[i], - (u_long)proc_cred.gid_arr[i]); - break; - } - return (-1); - } - return (0); -} - -static int -check_xucred(const struct xucred *xucred, socklen_t len) -{ - int rc; - - if (len != sizeof(*xucred)) { - logmsgx("option value size %zu != %zu", - (size_t)len, sizeof(*xucred)); - return (-1); - } - - dbgmsg("xucred.cr_version %u", xucred->cr_version); - dbgmsg("xucred.cr_uid %lu", (u_long)xucred->cr_uid); - dbgmsg("xucred.cr_ngroups %d", xucred->cr_ngroups); - - rc = 0; - - if (xucred->cr_version != XUCRED_VERSION) { - logmsgx("xucred.cr_version %u != %d", - xucred->cr_version, XUCRED_VERSION); - rc = -1; - } - if (xucred->cr_uid != proc_cred.euid) { - logmsgx("xucred.cr_uid %lu != %lu (EUID)", - (u_long)xucred->cr_uid, (u_long)proc_cred.euid); - rc = -1; - } - if (xucred->cr_ngroups == 0) { - logmsgx("xucred.cr_ngroups == 0"); - rc = -1; - } - if (xucred->cr_ngroups < 0) { - logmsgx("xucred.cr_ngroups < 0"); - rc = -1; - } - if (xucred->cr_ngroups > XU_NGROUPS) { - logmsgx("xucred.cr_ngroups %hu > %u (max)", - xucred->cr_ngroups, XU_NGROUPS); - rc = -1; - } - if (xucred->cr_groups[0] != proc_cred.egid) { - logmsgx("xucred.cr_groups[0] %lu != %lu (EGID)", - (u_long)xucred->cr_groups[0], (u_long)proc_cred.egid); - rc = -1; - } - if (check_groups("xucred.cr_groups", xucred->cr_groups, - "xucred.cr_ngroups", xucred->cr_ngroups, false) < 0) - rc = -1; - return (rc); -} - -static int -check_scm_creds_cmsgcred(struct cmsghdr *cmsghdr) -{ - const struct cmsgcred *cmcred; - int rc; - - if (check_cmsghdr(cmsghdr, SCM_CREDS, sizeof(struct cmsgcred)) < 0) - return (-1); - - cmcred = (struct cmsgcred *)CMSG_DATA(cmsghdr); - - dbgmsg("cmsgcred.cmcred_pid %ld", (long)cmcred->cmcred_pid); - dbgmsg("cmsgcred.cmcred_uid %lu", (u_long)cmcred->cmcred_uid); - dbgmsg("cmsgcred.cmcred_euid %lu", (u_long)cmcred->cmcred_euid); - dbgmsg("cmsgcred.cmcred_gid %lu", (u_long)cmcred->cmcred_gid); - dbgmsg("cmsgcred.cmcred_ngroups %d", cmcred->cmcred_ngroups); - - rc = 0; - - if (cmcred->cmcred_pid != client_pid) { - logmsgx("cmsgcred.cmcred_pid %ld != %ld", - (long)cmcred->cmcred_pid, (long)client_pid); - rc = -1; - } - if (cmcred->cmcred_uid != proc_cred.uid) { - logmsgx("cmsgcred.cmcred_uid %lu != %lu", - (u_long)cmcred->cmcred_uid, (u_long)proc_cred.uid); - rc = -1; - } - if (cmcred->cmcred_euid != proc_cred.euid) { - logmsgx("cmsgcred.cmcred_euid %lu != %lu", - (u_long)cmcred->cmcred_euid, (u_long)proc_cred.euid); - rc = -1; - } - if (cmcred->cmcred_gid != proc_cred.gid) { - logmsgx("cmsgcred.cmcred_gid %lu != %lu", - (u_long)cmcred->cmcred_gid, (u_long)proc_cred.gid); - rc = -1; - } - if (cmcred->cmcred_ngroups == 0) { - logmsgx("cmsgcred.cmcred_ngroups == 0"); - rc = -1; - } - if (cmcred->cmcred_ngroups < 0) { - logmsgx("cmsgcred.cmcred_ngroups %d < 0", - cmcred->cmcred_ngroups); - rc = -1; - } - if (cmcred->cmcred_ngroups > CMGROUP_MAX) { - logmsgx("cmsgcred.cmcred_ngroups %d > %d", - cmcred->cmcred_ngroups, CMGROUP_MAX); - rc = -1; - } - if (cmcred->cmcred_groups[0] != proc_cred.egid) { - logmsgx("cmsgcred.cmcred_groups[0] %lu != %lu (EGID)", - (u_long)cmcred->cmcred_groups[0], (u_long)proc_cred.egid); - rc = -1; - } - if (check_groups("cmsgcred.cmcred_groups", cmcred->cmcred_groups, - "cmsgcred.cmcred_ngroups", cmcred->cmcred_ngroups, false) < 0) - rc = -1; - return (rc); -} - -static int -check_scm_creds_sockcred(struct cmsghdr *cmsghdr) -{ - const struct sockcred *sc; - int rc; - - if (check_cmsghdr(cmsghdr, SCM_CREDS, - SOCKCREDSIZE(proc_cred.gid_num)) < 0) - return (-1); - - sc = (struct sockcred *)CMSG_DATA(cmsghdr); - - rc = 0; - - dbgmsg("sockcred.sc_uid %lu", (u_long)sc->sc_uid); - dbgmsg("sockcred.sc_euid %lu", (u_long)sc->sc_euid); - dbgmsg("sockcred.sc_gid %lu", (u_long)sc->sc_gid); - dbgmsg("sockcred.sc_egid %lu", (u_long)sc->sc_egid); - dbgmsg("sockcred.sc_ngroups %d", sc->sc_ngroups); - - if (sc->sc_uid != proc_cred.uid) { - logmsgx("sockcred.sc_uid %lu != %lu", - (u_long)sc->sc_uid, (u_long)proc_cred.uid); - rc = -1; - } - if (sc->sc_euid != proc_cred.euid) { - logmsgx("sockcred.sc_euid %lu != %lu", - (u_long)sc->sc_euid, (u_long)proc_cred.euid); - rc = -1; - } - if (sc->sc_gid != proc_cred.gid) { - logmsgx("sockcred.sc_gid %lu != %lu", - (u_long)sc->sc_gid, (u_long)proc_cred.gid); - rc = -1; - } - if (sc->sc_egid != proc_cred.egid) { - logmsgx("sockcred.sc_egid %lu != %lu", - (u_long)sc->sc_egid, (u_long)proc_cred.egid); - rc = -1; - } - if (sc->sc_ngroups == 0) { - logmsgx("sockcred.sc_ngroups == 0"); - rc = -1; - } - if (sc->sc_ngroups < 0) { - logmsgx("sockcred.sc_ngroups %d < 0", - sc->sc_ngroups); - rc = -1; - } - if (sc->sc_ngroups != proc_cred.gid_num) { - logmsgx("sockcred.sc_ngroups %d != %u", - sc->sc_ngroups, proc_cred.gid_num); - rc = -1; - } - if (check_groups("sockcred.sc_groups", sc->sc_groups, - "sockcred.sc_ngroups", sc->sc_ngroups, true) < 0) - rc = -1; - return (rc); -} - -static int -check_scm_timestamp(struct cmsghdr *cmsghdr) -{ - const struct timeval *tv; - - if (check_cmsghdr(cmsghdr, SCM_TIMESTAMP, sizeof(struct timeval)) < 0) - return (-1); - - tv = (struct timeval *)CMSG_DATA(cmsghdr); - - dbgmsg("timeval.tv_sec %"PRIdMAX", timeval.tv_usec %"PRIdMAX, - (intmax_t)tv->tv_sec, (intmax_t)tv->tv_usec); - - return (0); -} - -static int -check_scm_bintime(struct cmsghdr *cmsghdr) -{ - const struct bintime *bt; - - if (check_cmsghdr(cmsghdr, SCM_BINTIME, sizeof(struct bintime)) < 0) - return (-1); - - bt = (struct bintime *)CMSG_DATA(cmsghdr); - - dbgmsg("bintime.sec %"PRIdMAX", bintime.frac %"PRIu64, - (intmax_t)bt->sec, bt->frac); - - return (0); -} - -static void -msghdr_init_generic(struct msghdr *msghdr, struct iovec *iov, void *cmsg_data) -{ - msghdr->msg_name = NULL; - msghdr->msg_namelen = 0; - if (send_data_flag) { - iov->iov_base = server_flag ? - ipc_msg.buf_recv : ipc_msg.buf_send; - iov->iov_len = ipc_msg.buf_size; - msghdr->msg_iov = iov; - msghdr->msg_iovlen = 1; - } else { - msghdr->msg_iov = NULL; - msghdr->msg_iovlen = 0; - } - msghdr->msg_control = cmsg_data; - msghdr->msg_flags = 0; -} - -static void -msghdr_init_server(struct msghdr *msghdr, struct iovec *iov, - void *cmsg_data, size_t cmsg_size) -{ - msghdr_init_generic(msghdr, iov, cmsg_data); - msghdr->msg_controllen = cmsg_size; - dbgmsg("init: data size %zu", msghdr->msg_iov != NULL ? - msghdr->msg_iov->iov_len : (size_t)0); - dbgmsg("init: msghdr.msg_controllen %u", - (u_int)msghdr->msg_controllen); -} - -static void -msghdr_init_client(struct msghdr *msghdr, struct iovec *iov, - void *cmsg_data, size_t cmsg_size, int type, size_t arr_size) -{ - struct cmsghdr *cmsghdr; - - msghdr_init_generic(msghdr, iov, cmsg_data); - if (cmsg_data != NULL) { - if (send_array_flag) - dbgmsg("sending an array"); - else - dbgmsg("sending a scalar"); - msghdr->msg_controllen = send_array_flag ? - cmsg_size : CMSG_SPACE(0); - cmsghdr = CMSG_FIRSTHDR(msghdr); - cmsghdr->cmsg_level = SOL_SOCKET; - cmsghdr->cmsg_type = type; - cmsghdr->cmsg_len = CMSG_LEN(send_array_flag ? arr_size : 0); - } else - msghdr->msg_controllen = 0; -} - -static int -t_generic(int (*client_func)(int), int (*server_func)(int)) -{ - int fd, rv, rv_client; - - switch (client_fork()) { - case 0: - fd = socket_create(); - if (fd < 0) - rv = -2; - else { - rv = client_func(fd); - if (socket_close(fd) < 0) - rv = -2; - } - client_exit(rv); - break; - case 1: - fd = socket_create(); - if (fd < 0) - rv = -2; - else { - rv = server_func(fd); - rv_client = client_wait(); - if (rv == 0 || (rv == -2 && rv_client != 0)) - rv = rv_client; - if (socket_close(fd) < 0) - rv = -2; - } - break; - default: - rv = -2; - } - return (rv); -} - -static int -t_cmsgcred_client(int fd) -{ - struct msghdr msghdr; - struct iovec iov[1]; - void *cmsg_data; - size_t cmsg_size; - int rv; - - if (sync_recv() < 0) - return (-2); - - rv = -2; - - cmsg_size = CMSG_SPACE(sizeof(struct cmsgcred)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - msghdr_init_client(&msghdr, iov, cmsg_data, cmsg_size, - SCM_CREDS, sizeof(struct cmsgcred)); - - if (socket_connect(fd) < 0) - goto done; - - if (message_sendn(fd, &msghdr) < 0) - goto done; - - rv = 0; -done: - free(cmsg_data); - return (rv); -} - -static int -t_cmsgcred_server(int fd1) -{ - struct msghdr msghdr; - struct iovec iov[1]; - struct cmsghdr *cmsghdr; - void *cmsg_data; - size_t cmsg_size; - u_int i; - int fd2, rv; - - if (sync_send() < 0) - return (-2); - - fd2 = -1; - rv = -2; - - cmsg_size = CMSG_SPACE(sizeof(struct cmsgcred)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - - if (sock_type == SOCK_STREAM) { - fd2 = socket_accept(fd1); - if (fd2 < 0) - goto done; - } else - fd2 = fd1; - - rv = -1; - for (i = 1; i <= ipc_msg.msg_num; ++i) { - dbgmsg("message #%u", i); - - msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); - if (message_recv(fd2, &msghdr) < 0) { - rv = -2; - break; - } - - if (check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) - break; - - cmsghdr = CMSG_FIRSTHDR(&msghdr); - if (check_scm_creds_cmsgcred(cmsghdr) < 0) - break; - } - if (i > ipc_msg.msg_num) - rv = 0; -done: - free(cmsg_data); - if (sock_type == SOCK_STREAM && fd2 >= 0) - if (socket_close(fd2) < 0) - rv = -2; - return (rv); -} - -static int -t_cmsgcred(void) -{ - return (t_generic(t_cmsgcred_client, t_cmsgcred_server)); -} - -static int -t_sockcred_client(int type, int fd) -{ - struct msghdr msghdr; - struct iovec iov[1]; - int rv; - - if (sync_recv() < 0) - return (-2); - - rv = -2; - - msghdr_init_client(&msghdr, iov, NULL, 0, 0, 0); - - if (socket_connect(fd) < 0) - goto done; - - if (type == 2) - if (sync_recv() < 0) - goto done; - - if (message_sendn(fd, &msghdr) < 0) - goto done; - - rv = 0; -done: - return (rv); -} - -static int -t_sockcred_server(int type, int fd1) -{ - struct msghdr msghdr; - struct iovec iov[1]; - struct cmsghdr *cmsghdr; - void *cmsg_data; - size_t cmsg_size; - u_int i; - int fd2, rv, val; - - fd2 = -1; - rv = -2; - - cmsg_size = CMSG_SPACE(SOCKCREDSIZE(proc_cred.gid_num)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - - if (type == 1) { - dbgmsg("setting LOCAL_CREDS"); - val = 1; - if (setsockopt(fd1, 0, LOCAL_CREDS, &val, sizeof(val)) < 0) { - logmsg("setsockopt(LOCAL_CREDS)"); - goto done; - } - } - - if (sync_send() < 0) - goto done; - - if (sock_type == SOCK_STREAM) { - fd2 = socket_accept(fd1); - if (fd2 < 0) - goto done; - } else - fd2 = fd1; - - if (type == 2) { - dbgmsg("setting LOCAL_CREDS"); - val = 1; - if (setsockopt(fd2, 0, LOCAL_CREDS, &val, sizeof(val)) < 0) { - logmsg("setsockopt(LOCAL_CREDS)"); - goto done; - } - if (sync_send() < 0) - goto done; - } - - rv = -1; - for (i = 1; i <= ipc_msg.msg_num; ++i) { - dbgmsg("message #%u", i); - - msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); - if (message_recv(fd2, &msghdr) < 0) { - rv = -2; - break; - } - - if (i > 1 && sock_type == SOCK_STREAM) { - if (check_msghdr(&msghdr, 0) < 0) - break; - } else { - if (check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) - break; - - cmsghdr = CMSG_FIRSTHDR(&msghdr); - if (check_scm_creds_sockcred(cmsghdr) < 0) - break; - } - } - if (i > ipc_msg.msg_num) - rv = 0; -done: - free(cmsg_data); - if (sock_type == SOCK_STREAM && fd2 >= 0) - if (socket_close(fd2) < 0) - rv = -2; - return (rv); -} - -static int -t_sockcred_1(void) -{ - u_int i; - int fd, rv, rv_client; - - switch (client_fork()) { - case 0: - for (i = 1; i <= 2; ++i) { - dbgmsg("client #%u", i); - fd = socket_create(); - if (fd < 0) - rv = -2; - else { - rv = t_sockcred_client(1, fd); - if (socket_close(fd) < 0) - rv = -2; - } - if (rv != 0) - break; - } - client_exit(rv); - break; - case 1: - fd = socket_create(); - if (fd < 0) - rv = -2; - else { - rv = t_sockcred_server(1, fd); - if (rv == 0) - rv = t_sockcred_server(3, fd); - rv_client = client_wait(); - if (rv == 0 || (rv == -2 && rv_client != 0)) - rv = rv_client; - if (socket_close(fd) < 0) - rv = -2; - } - break; - default: - rv = -2; - } - - return (rv); -} - -static int -t_sockcred_2_client(int fd) -{ - return (t_sockcred_client(2, fd)); -} - -static int -t_sockcred_2_server(int fd) -{ - return (t_sockcred_server(2, fd)); -} - -static int -t_sockcred_2(void) -{ - return (t_generic(t_sockcred_2_client, t_sockcred_2_server)); -} - -static int -t_cmsgcred_sockcred_server(int fd1) -{ - struct msghdr msghdr; - struct iovec iov[1]; - struct cmsghdr *cmsghdr; - void *cmsg_data, *cmsg1_data, *cmsg2_data; - size_t cmsg_size, cmsg1_size, cmsg2_size; - u_int i; - int fd2, rv, val; - - fd2 = -1; - rv = -2; - - cmsg1_size = CMSG_SPACE(SOCKCREDSIZE(proc_cred.gid_num)); - cmsg2_size = CMSG_SPACE(sizeof(struct cmsgcred)); - cmsg1_data = malloc(cmsg1_size); - cmsg2_data = malloc(cmsg2_size); - if (cmsg1_data == NULL || cmsg2_data == NULL) { - logmsg("malloc"); - goto done; - } - - dbgmsg("setting LOCAL_CREDS"); - val = 1; - if (setsockopt(fd1, 0, LOCAL_CREDS, &val, sizeof(val)) < 0) { - logmsg("setsockopt(LOCAL_CREDS)"); - goto done; - } - - if (sync_send() < 0) - goto done; - - if (sock_type == SOCK_STREAM) { - fd2 = socket_accept(fd1); - if (fd2 < 0) - goto done; - } else - fd2 = fd1; - - cmsg_data = cmsg1_data; - cmsg_size = cmsg1_size; - rv = -1; - for (i = 1; i <= ipc_msg.msg_num; ++i) { - dbgmsg("message #%u", i); - - msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); - if (message_recv(fd2, &msghdr) < 0) { - rv = -2; - break; - } - - if (check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) - break; - - cmsghdr = CMSG_FIRSTHDR(&msghdr); - if (i == 1 || sock_type == SOCK_DGRAM) { - if (check_scm_creds_sockcred(cmsghdr) < 0) - break; - } else { - if (check_scm_creds_cmsgcred(cmsghdr) < 0) - break; - } - - cmsg_data = cmsg2_data; - cmsg_size = cmsg2_size; - } - if (i > ipc_msg.msg_num) - rv = 0; -done: - free(cmsg1_data); - free(cmsg2_data); - if (sock_type == SOCK_STREAM && fd2 >= 0) - if (socket_close(fd2) < 0) - rv = -2; - return (rv); -} - -static int -t_cmsgcred_sockcred(void) -{ - return (t_generic(t_cmsgcred_client, t_cmsgcred_sockcred_server)); -} - -static int -t_timeval_client(int fd) -{ - struct msghdr msghdr; - struct iovec iov[1]; - void *cmsg_data; - size_t cmsg_size; - int rv; - - if (sync_recv() < 0) - return (-2); - - rv = -2; - - cmsg_size = CMSG_SPACE(sizeof(struct timeval)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - msghdr_init_client(&msghdr, iov, cmsg_data, cmsg_size, - SCM_TIMESTAMP, sizeof(struct timeval)); - - if (socket_connect(fd) < 0) - goto done; - - if (message_sendn(fd, &msghdr) < 0) - goto done; - - rv = 0; -done: - free(cmsg_data); - return (rv); -} - -static int -t_timeval_server(int fd1) -{ - struct msghdr msghdr; - struct iovec iov[1]; - struct cmsghdr *cmsghdr; - void *cmsg_data; - size_t cmsg_size; - u_int i; - int fd2, rv; - - if (sync_send() < 0) - return (-2); - - fd2 = -1; - rv = -2; - - cmsg_size = CMSG_SPACE(sizeof(struct timeval)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - - if (sock_type == SOCK_STREAM) { - fd2 = socket_accept(fd1); - if (fd2 < 0) - goto done; - } else - fd2 = fd1; - - rv = -1; - for (i = 1; i <= ipc_msg.msg_num; ++i) { - dbgmsg("message #%u", i); - - msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); - if (message_recv(fd2, &msghdr) < 0) { - rv = -2; - break; - } - - if (check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) - break; - - cmsghdr = CMSG_FIRSTHDR(&msghdr); - if (check_scm_timestamp(cmsghdr) < 0) - break; - } - if (i > ipc_msg.msg_num) - rv = 0; -done: - free(cmsg_data); - if (sock_type == SOCK_STREAM && fd2 >= 0) - if (socket_close(fd2) < 0) - rv = -2; - return (rv); -} - -static int -t_timeval(void) -{ - return (t_generic(t_timeval_client, t_timeval_server)); -} - -static int -t_bintime_client(int fd) -{ - struct msghdr msghdr; - struct iovec iov[1]; - void *cmsg_data; - size_t cmsg_size; - int rv; - - if (sync_recv() < 0) - return (-2); - - rv = -2; - - cmsg_size = CMSG_SPACE(sizeof(struct bintime)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - msghdr_init_client(&msghdr, iov, cmsg_data, cmsg_size, - SCM_BINTIME, sizeof(struct bintime)); - - if (socket_connect(fd) < 0) - goto done; - - if (message_sendn(fd, &msghdr) < 0) - goto done; - - rv = 0; -done: - free(cmsg_data); - return (rv); -} - -static int -t_bintime_server(int fd1) -{ - struct msghdr msghdr; - struct iovec iov[1]; - struct cmsghdr *cmsghdr; - void *cmsg_data; - size_t cmsg_size; - u_int i; - int fd2, rv; - - if (sync_send() < 0) - return (-2); - - fd2 = -1; - rv = -2; - - cmsg_size = CMSG_SPACE(sizeof(struct bintime)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - - if (sock_type == SOCK_STREAM) { - fd2 = socket_accept(fd1); - if (fd2 < 0) - goto done; - } else - fd2 = fd1; - - rv = -1; - for (i = 1; i <= ipc_msg.msg_num; ++i) { - dbgmsg("message #%u", i); - - msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); - if (message_recv(fd2, &msghdr) < 0) { - rv = -2; - break; - } - - if (check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) - break; - - cmsghdr = CMSG_FIRSTHDR(&msghdr); - if (check_scm_bintime(cmsghdr) < 0) - break; - } - if (i > ipc_msg.msg_num) - rv = 0; -done: - free(cmsg_data); - if (sock_type == SOCK_STREAM && fd2 >= 0) - if (socket_close(fd2) < 0) - rv = -2; - return (rv); -} - -static int -t_bintime(void) -{ - return (t_generic(t_bintime_client, t_bintime_server)); -} - -#ifndef __LP64__ -static int -t_cmsg_len_client(int fd) -{ - struct msghdr msghdr; - struct iovec iov[1]; - struct cmsghdr *cmsghdr; - void *cmsg_data; - size_t size, cmsg_size; - socklen_t socklen; - int rv; - - if (sync_recv() < 0) - return (-2); - - rv = -2; - - cmsg_size = CMSG_SPACE(sizeof(struct cmsgcred)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - msghdr_init_client(&msghdr, iov, cmsg_data, cmsg_size, - SCM_CREDS, sizeof(struct cmsgcred)); - cmsghdr = CMSG_FIRSTHDR(&msghdr); - - if (socket_connect(fd) < 0) - goto done; - - size = msghdr.msg_iov != NULL ? msghdr.msg_iov->iov_len : 0; - rv = -1; - for (socklen = 0; socklen < CMSG_LEN(0); ++socklen) { - cmsghdr->cmsg_len = socklen; - dbgmsg("send: data size %zu", size); - dbgmsg("send: msghdr.msg_controllen %u", - (u_int)msghdr.msg_controllen); - dbgmsg("send: cmsghdr.cmsg_len %u", - (u_int)cmsghdr->cmsg_len); - if (sendmsg(fd, &msghdr, 0) < 0) { - dbgmsg("sendmsg(2) failed: %s; retrying", - strerror(errno)); - continue; - } - logmsgx("sent message with cmsghdr.cmsg_len %u < %u", - (u_int)cmsghdr->cmsg_len, (u_int)CMSG_LEN(0)); - break; - } - if (socklen == CMSG_LEN(0)) - rv = 0; - - if (sync_send() < 0) { - rv = -2; - goto done; - } -done: - free(cmsg_data); - return (rv); -} - -static int -t_cmsg_len_server(int fd1) -{ - int fd2, rv; - - if (sync_send() < 0) - return (-2); - - rv = -2; - - if (sock_type == SOCK_STREAM) { - fd2 = socket_accept(fd1); - if (fd2 < 0) - goto done; - } else - fd2 = fd1; - - if (sync_recv() < 0) - goto done; - - rv = 0; -done: - if (sock_type == SOCK_STREAM && fd2 >= 0) - if (socket_close(fd2) < 0) - rv = -2; - return (rv); -} - -static int -t_cmsg_len(void) -{ - return (t_generic(t_cmsg_len_client, t_cmsg_len_server)); -} -#endif - -static int -t_peercred_client(int fd) -{ - struct xucred xucred; - socklen_t len; - - if (sync_recv() < 0) - return (-1); - - if (socket_connect(fd) < 0) - return (-1); - - len = sizeof(xucred); - if (getsockopt(fd, 0, LOCAL_PEERCRED, &xucred, &len) < 0) { - logmsg("getsockopt(LOCAL_PEERCRED)"); - return (-1); - } - - if (check_xucred(&xucred, len) < 0) - return (-1); - - return (0); -} - -static int -t_peercred_server(int fd1) -{ - struct xucred xucred; - socklen_t len; - int fd2, rv; - - if (sync_send() < 0) - return (-2); - - fd2 = socket_accept(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 (socket_close(fd2) < 0) - rv = -2; - return (rv); -} - -static int -t_peercred(void) -{ - return (t_generic(t_peercred_client, t_peercred_server)); }