16d317723SGleb Smirnoff /*- 26d317723SGleb Smirnoff * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 36d317723SGleb Smirnoff * 46d317723SGleb Smirnoff * Copyright (c) 2022 Gleb Smirnoff <glebius@FreeBSD.org> 56d317723SGleb Smirnoff * 66d317723SGleb Smirnoff * Redistribution and use in source and binary forms, with or without 76d317723SGleb Smirnoff * modification, are permitted provided that the following conditions 86d317723SGleb Smirnoff * are met: 96d317723SGleb Smirnoff * 1. Redistributions of source code must retain the above copyright 106d317723SGleb Smirnoff * notice, this list of conditions and the following disclaimer. 116d317723SGleb Smirnoff * 2. Redistributions in binary form must reproduce the above copyright 126d317723SGleb Smirnoff * notice, this list of conditions and the following disclaimer in the 136d317723SGleb Smirnoff * documentation and/or other materials provided with the distribution. 146d317723SGleb Smirnoff * 156d317723SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 166d317723SGleb Smirnoff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 176d317723SGleb Smirnoff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 186d317723SGleb Smirnoff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 196d317723SGleb Smirnoff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 206d317723SGleb Smirnoff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 216d317723SGleb Smirnoff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 226d317723SGleb Smirnoff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 236d317723SGleb Smirnoff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 246d317723SGleb Smirnoff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 256d317723SGleb Smirnoff * SUCH DAMAGE. 266d317723SGleb Smirnoff */ 276d317723SGleb Smirnoff 286d317723SGleb Smirnoff #include <sys/time.h> 296d317723SGleb Smirnoff #include <sys/socket.h> 306d317723SGleb Smirnoff #include <sys/sysctl.h> 316d317723SGleb Smirnoff #include <sys/un.h> 326d317723SGleb Smirnoff #include <errno.h> 336d317723SGleb Smirnoff #include <fcntl.h> 346d317723SGleb Smirnoff #include <signal.h> 356d317723SGleb Smirnoff #include <stdlib.h> 366d317723SGleb Smirnoff 376d317723SGleb Smirnoff #include <atf-c.h> 386d317723SGleb Smirnoff 396d317723SGleb Smirnoff static struct itimerval itv = { 406d317723SGleb Smirnoff .it_interval = { 0, 0 }, 416d317723SGleb Smirnoff .it_value = { 1, 0 }, /* one second */ 426d317723SGleb Smirnoff }; 436d317723SGleb Smirnoff static sig_atomic_t timer_done = 0; 446d317723SGleb Smirnoff static void 456d317723SGleb Smirnoff sigalarm(int sig __unused) 466d317723SGleb Smirnoff { 476d317723SGleb Smirnoff 486d317723SGleb Smirnoff timer_done = 1; 496d317723SGleb Smirnoff } 506d317723SGleb Smirnoff 516d317723SGleb Smirnoff static struct sigaction sigact = { 526d317723SGleb Smirnoff .sa_handler = sigalarm, 536d317723SGleb Smirnoff }; 546d317723SGleb Smirnoff 556d317723SGleb Smirnoff /* 566d317723SGleb Smirnoff * Fill socket to a state when next send(len) would fail. 57*aa9f97afSGleb Smirnoff * 58*aa9f97afSGleb Smirnoff * Note that every datagram is prepended with sender address, 59*aa9f97afSGleb Smirnoff * size of struct sockaddr. 606d317723SGleb Smirnoff */ 616d317723SGleb Smirnoff static void 626d317723SGleb Smirnoff fill(int fd, void *buf, ssize_t len) 636d317723SGleb Smirnoff { 646d317723SGleb Smirnoff unsigned long recvspace; 656d317723SGleb Smirnoff size_t llen = sizeof(unsigned long); 666d317723SGleb Smirnoff ssize_t sent; 676d317723SGleb Smirnoff 686d317723SGleb Smirnoff ATF_REQUIRE(sysctlbyname("net.local.dgram.recvspace", &recvspace, 696d317723SGleb Smirnoff &llen, NULL, 0) == 0); 70*aa9f97afSGleb Smirnoff for (sent = 0; 71*aa9f97afSGleb Smirnoff sent + len + sizeof(struct sockaddr) < recvspace; 72*aa9f97afSGleb Smirnoff sent += len + sizeof(struct sockaddr)) 736d317723SGleb Smirnoff ATF_REQUIRE(send(fd, buf, len, 0) == len); 746d317723SGleb Smirnoff } 756d317723SGleb Smirnoff 766d317723SGleb Smirnoff ATF_TC_WITHOUT_HEAD(basic); 776d317723SGleb Smirnoff ATF_TC_BODY(basic, tc) 786d317723SGleb Smirnoff { 796d317723SGleb Smirnoff struct msghdr msg; 806d317723SGleb Smirnoff struct iovec iov[1]; 816d317723SGleb Smirnoff unsigned long maxdgram; 826d317723SGleb Smirnoff size_t llen = sizeof(unsigned long); 836d317723SGleb Smirnoff int fd[2]; 846d317723SGleb Smirnoff char *buf; 856d317723SGleb Smirnoff 866d317723SGleb Smirnoff /* Allocate and initialize: 876d317723SGleb Smirnoff * - fd[0] to send, fd[1] to receive 886d317723SGleb Smirnoff * - buf[maxdgram] for data 896d317723SGleb Smirnoff */ 906d317723SGleb Smirnoff ATF_REQUIRE(sysctlbyname("net.local.dgram.maxdgram", &maxdgram, 916d317723SGleb Smirnoff &llen, NULL, 0) == 0); 926d317723SGleb Smirnoff ATF_REQUIRE(socketpair(PF_UNIX, SOCK_DGRAM, 0, fd) != -1); 936d317723SGleb Smirnoff buf = malloc(maxdgram + 1); 946d317723SGleb Smirnoff ATF_REQUIRE(buf); 956d317723SGleb Smirnoff msg = (struct msghdr ){ 966d317723SGleb Smirnoff .msg_iov = iov, 976d317723SGleb Smirnoff .msg_iovlen = 1, 986d317723SGleb Smirnoff }; 996d317723SGleb Smirnoff iov[0] = (struct iovec ){ 1006d317723SGleb Smirnoff .iov_base = buf, 1016d317723SGleb Smirnoff }; 1026d317723SGleb Smirnoff 1036d317723SGleb Smirnoff /* Fail to send > maxdgram. */ 1046d317723SGleb Smirnoff ATF_REQUIRE(send(fd[0], buf, maxdgram + 1, 0) == -1); 1056d317723SGleb Smirnoff ATF_REQUIRE(errno == EMSGSIZE); 1066d317723SGleb Smirnoff 1076d317723SGleb Smirnoff /* Send maxdgram. */ 1086d317723SGleb Smirnoff ATF_REQUIRE(send(fd[0], buf, maxdgram, 0) == (ssize_t)maxdgram); 1096d317723SGleb Smirnoff 1106d317723SGleb Smirnoff /* Exercise MSG_PEEK, full and truncated.. */ 1116d317723SGleb Smirnoff ATF_REQUIRE(recv(fd[1], buf, maxdgram, MSG_PEEK) == (ssize_t)maxdgram); 1126d317723SGleb Smirnoff iov[0].iov_len = 42; 1136d317723SGleb Smirnoff ATF_REQUIRE(recvmsg(fd[1], &msg, MSG_PEEK) == 42); 1146d317723SGleb Smirnoff ATF_REQUIRE(msg.msg_flags == (MSG_PEEK | MSG_TRUNC)); 1156d317723SGleb Smirnoff 1166d317723SGleb Smirnoff /* Receive maxdgram. */ 1176d317723SGleb Smirnoff iov[0].iov_len = maxdgram; 1186d317723SGleb Smirnoff ATF_REQUIRE(recvmsg(fd[1], &msg, 0) == (ssize_t)maxdgram); 1196d317723SGleb Smirnoff ATF_REQUIRE(msg.msg_flags == 0); 1206d317723SGleb Smirnoff 1216d317723SGleb Smirnoff /* Receive truncated message. */ 1226d317723SGleb Smirnoff ATF_REQUIRE(send(fd[0], buf, maxdgram, 0) == (ssize_t)maxdgram); 1236d317723SGleb Smirnoff iov[0].iov_len = maxdgram / 2; 1246d317723SGleb Smirnoff ATF_REQUIRE(recvmsg(fd[1], &msg, 0) == (ssize_t)maxdgram / 2); 1256d317723SGleb Smirnoff ATF_REQUIRE(msg.msg_flags == MSG_TRUNC); 1266d317723SGleb Smirnoff 1276d317723SGleb Smirnoff /* Empty: block. */ 1286d317723SGleb Smirnoff ATF_REQUIRE(sigaction(SIGALRM, &sigact, NULL) == 0); 1296d317723SGleb Smirnoff ATF_REQUIRE(timer_done == 0); 1306d317723SGleb Smirnoff ATF_REQUIRE(setitimer(ITIMER_REAL, &itv, NULL) == 0); 1316d317723SGleb Smirnoff ATF_REQUIRE(recv(fd[1], buf, maxdgram, 0) == -1); 1326d317723SGleb Smirnoff ATF_REQUIRE(errno == EINTR); 1336d317723SGleb Smirnoff ATF_REQUIRE(timer_done == 1); 1346d317723SGleb Smirnoff 1356d317723SGleb Smirnoff /* Don't block with MSG_DONTWAIT. */ 1366d317723SGleb Smirnoff ATF_REQUIRE(recv(fd[1], buf, maxdgram, MSG_DONTWAIT) == -1); 1376d317723SGleb Smirnoff ATF_REQUIRE(errno == EAGAIN); 1386d317723SGleb Smirnoff 1396d317723SGleb Smirnoff /* Don't block with O_NONBLOCK. */ 1406d317723SGleb Smirnoff ATF_REQUIRE(fcntl(fd[1], F_SETFL, O_NONBLOCK) != -1); 1416d317723SGleb Smirnoff ATF_REQUIRE(recv(fd[1], buf, maxdgram, 0) == -1); 1426d317723SGleb Smirnoff ATF_REQUIRE(errno == EAGAIN); 1436d317723SGleb Smirnoff 1446d317723SGleb Smirnoff /* Fail with ENOBUFS on full socket. */ 1456d317723SGleb Smirnoff fill(fd[0], buf, maxdgram); 1466d317723SGleb Smirnoff ATF_REQUIRE(send(fd[0], buf, maxdgram, 0) == -1); 1476d317723SGleb Smirnoff ATF_REQUIRE(errno == ENOBUFS); 1486d317723SGleb Smirnoff 1496d317723SGleb Smirnoff /* Fail with EAGAIN with O_NONBLOCK set. */ 1506d317723SGleb Smirnoff ATF_REQUIRE(fcntl(fd[0], F_SETFL, O_NONBLOCK) != -1); 1516d317723SGleb Smirnoff ATF_REQUIRE(send(fd[0], buf, maxdgram, 0) == -1); 1526d317723SGleb Smirnoff ATF_REQUIRE(errno == EAGAIN); 1536d317723SGleb Smirnoff 1546d317723SGleb Smirnoff /* Remote side closed -> ECONNRESET. */ 1556d317723SGleb Smirnoff close(fd[1]); 1566d317723SGleb Smirnoff ATF_REQUIRE(send(fd[0], buf, maxdgram, 0) == -1); 1576d317723SGleb Smirnoff ATF_REQUIRE(errno == ECONNRESET); 1586d317723SGleb Smirnoff } 1596d317723SGleb Smirnoff 1606d317723SGleb Smirnoff ATF_TC_WITHOUT_HEAD(one2many); 1616d317723SGleb Smirnoff ATF_TC_BODY(one2many, tc) 1626d317723SGleb Smirnoff { 1636d317723SGleb Smirnoff struct sockaddr_un sun; 1646d317723SGleb Smirnoff const char *path = "unix_dgram_listener"; 1656d317723SGleb Smirnoff int one, many[2], two; 1666d317723SGleb Smirnoff char buf[1024]; 1676d317723SGleb Smirnoff 1686d317723SGleb Smirnoff /* Establish one to many connection. */ 1696d317723SGleb Smirnoff ATF_REQUIRE((one = socket(PF_UNIX, SOCK_DGRAM, 0)) > 0); 1706d317723SGleb Smirnoff bzero(&sun, sizeof(sun)); 1716d317723SGleb Smirnoff sun.sun_family = AF_LOCAL; 1726d317723SGleb Smirnoff sun.sun_len = sizeof(sun); 1736d317723SGleb Smirnoff strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); 1746d317723SGleb Smirnoff ATF_REQUIRE(bind(one, (struct sockaddr *)&sun, sizeof(sun)) == 0); 1756d317723SGleb Smirnoff /* listen(2) shall fail. */ 1766d317723SGleb Smirnoff ATF_REQUIRE(listen(one, -1) != 0); 1776d317723SGleb Smirnoff for (int i = 0; i < 2; i++) { 1786d317723SGleb Smirnoff ATF_REQUIRE((many[i] = socket(PF_UNIX, SOCK_DGRAM, 0)) > 0); 1796d317723SGleb Smirnoff ATF_REQUIRE(connect(many[i], (struct sockaddr *)&sun, 1806d317723SGleb Smirnoff sizeof(sun)) == 0); 1816d317723SGleb Smirnoff } 1826d317723SGleb Smirnoff 1836d317723SGleb Smirnoff /* accept() on UNIX/DGRAM is invalid. */ 1846d317723SGleb Smirnoff ATF_REQUIRE(accept(one, NULL, NULL) == -1); 1856d317723SGleb Smirnoff ATF_REQUIRE(errno == EINVAL); 1866d317723SGleb Smirnoff 1876d317723SGleb Smirnoff /* 1886d317723SGleb Smirnoff * Connecting a bound socket to self: a strange, useless, but 1896d317723SGleb Smirnoff * historically existing edge case that is not explicitly described 1906d317723SGleb Smirnoff * in SuS, neither is forbidden there. Works on FreeBSD and Linux. 1916d317723SGleb Smirnoff */ 1926d317723SGleb Smirnoff ATF_REQUIRE(connect(one, (struct sockaddr *)&sun, sizeof(sun)) == 0); 1936d317723SGleb Smirnoff ATF_REQUIRE(send(one, buf, 42, 0) == 42); 1946d317723SGleb Smirnoff ATF_REQUIRE(recv(one, buf, sizeof(buf), 0) == 42); 1956d317723SGleb Smirnoff 1966d317723SGleb Smirnoff /* 1976d317723SGleb Smirnoff * Sending from an unconnected socket to a bound socket. Connection is 1986d317723SGleb Smirnoff * created for the duration of the syscall. 1996d317723SGleb Smirnoff */ 2006d317723SGleb Smirnoff ATF_REQUIRE((two = socket(PF_UNIX, SOCK_DGRAM, 0)) > 0); 2016d317723SGleb Smirnoff ATF_REQUIRE(sendto(two, buf, 43, 0, (struct sockaddr *)&sun, 2026d317723SGleb Smirnoff sizeof(sun)) == 43); 2036d317723SGleb Smirnoff ATF_REQUIRE(recv(one, buf, sizeof(buf), 0) == 43); 2046d317723SGleb Smirnoff 2056d317723SGleb Smirnoff /* One sender can fill the receive side. 2066d317723SGleb Smirnoff * Current behavior which needs improvement. 2076d317723SGleb Smirnoff */ 2086d317723SGleb Smirnoff fill(many[0], buf, sizeof(buf)); 2096d317723SGleb Smirnoff ATF_REQUIRE(send(many[1], buf, sizeof(buf), 0) == -1); 2106d317723SGleb Smirnoff ATF_REQUIRE(errno == ENOBUFS); 2116d317723SGleb Smirnoff ATF_REQUIRE(recv(one, buf, sizeof(buf), 0) == sizeof(buf)); 2126d317723SGleb Smirnoff ATF_REQUIRE(send(many[1], buf, sizeof(buf), 0) == sizeof(buf)); 2136d317723SGleb Smirnoff } 2146d317723SGleb Smirnoff 2156d317723SGleb Smirnoff ATF_TP_ADD_TCS(tp) 2166d317723SGleb Smirnoff { 2176d317723SGleb Smirnoff 2186d317723SGleb Smirnoff ATF_TP_ADD_TC(tp, basic); 2196d317723SGleb Smirnoff ATF_TP_ADD_TC(tp, one2many); 2206d317723SGleb Smirnoff 2216d317723SGleb Smirnoff return (atf_no_error()); 2226d317723SGleb Smirnoff } 223