1*539ef4ccSclaudio /* $OpenBSD: t_sendrecv.c,v 1.4 2024/07/30 13:28:27 claudio Exp $ */ 2cf0fd932Sbluhm /* $NetBSD: t_sendrecv.c,v 1.8 2021/03/28 17:30:01 christos Exp $ */ 3a545a52cSbluhm 4a545a52cSbluhm /*- 5a545a52cSbluhm * Copyright (c) 2018 The NetBSD Foundation, Inc. 6a545a52cSbluhm * All rights reserved. 7a545a52cSbluhm * 8a545a52cSbluhm * This code is derived from software contributed to The NetBSD Foundation 9a545a52cSbluhm * by Christos Zoulas. 10a545a52cSbluhm * 11a545a52cSbluhm * Redistribution and use in source and binary forms, with or without 12a545a52cSbluhm * modification, are permitted provided that the following conditions 13a545a52cSbluhm * are met: 14a545a52cSbluhm * 1. Redistributions of source code must retain the above copyright 15a545a52cSbluhm * notice, this list of conditions and the following disclaimer. 16a545a52cSbluhm * 2. Redistributions in binary form must reproduce the above copyright 17a545a52cSbluhm * notice, this list of conditions and the following disclaimer in the 18a545a52cSbluhm * documentation and/or other materials provided with the distribution. 19a545a52cSbluhm * 20a545a52cSbluhm * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21a545a52cSbluhm * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22a545a52cSbluhm * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23a545a52cSbluhm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24a545a52cSbluhm * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25a545a52cSbluhm * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26a545a52cSbluhm * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27a545a52cSbluhm * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28a545a52cSbluhm * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29a545a52cSbluhm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30a545a52cSbluhm * POSSIBILITY OF SUCH DAMAGE. 31a545a52cSbluhm */ 32a545a52cSbluhm 33a545a52cSbluhm #include "macros.h" 34a545a52cSbluhm 35a545a52cSbluhm #include "atf-c.h" 36a545a52cSbluhm #include <sys/types.h> 37a545a52cSbluhm #include <sys/socket.h> 38a545a52cSbluhm 39a545a52cSbluhm #include <string.h> 40a545a52cSbluhm #include <stdint.h> 41a545a52cSbluhm #include <errno.h> 42a545a52cSbluhm #include <stdio.h> 43a545a52cSbluhm #include <stdlib.h> 44a545a52cSbluhm #include <sched.h> 45cf0fd932Sbluhm #include <unistd.h> 46a545a52cSbluhm #include <signal.h> 47a545a52cSbluhm 48a545a52cSbluhm 49a545a52cSbluhm #define COUNT 100 50a545a52cSbluhm 51a545a52cSbluhm union packet { 52a545a52cSbluhm uint8_t buf[1316]; 53a545a52cSbluhm uintmax_t seq; 54a545a52cSbluhm }; 55a545a52cSbluhm 56a545a52cSbluhm static volatile sig_atomic_t rdied; 57a545a52cSbluhm 58a545a52cSbluhm static void 59a545a52cSbluhm handle_sigchld(__unused int pid) 60a545a52cSbluhm { 61a545a52cSbluhm 62a545a52cSbluhm rdied = 1; 63a545a52cSbluhm } 64a545a52cSbluhm 65a545a52cSbluhm static void 66cf0fd932Sbluhm sender(int sd) 67a545a52cSbluhm { 68a545a52cSbluhm union packet p; 69a545a52cSbluhm ssize_t n; 70a545a52cSbluhm p.seq = 0; 71a545a52cSbluhm for (size_t i = 0; i < COUNT; i++) { 72cf0fd932Sbluhm for (; (n = send(sd, &p, sizeof(p), 0)) == sizeof(p); 73a545a52cSbluhm p.seq++) 74a545a52cSbluhm continue; 75cf0fd932Sbluhm // printf(">>%zd %d %ju\n", n, errno, p.seq); 76a545a52cSbluhm ATF_REQUIRE_MSG(errno == ENOBUFS, "send %s", strerror(errno)); 77a545a52cSbluhm } 78cf0fd932Sbluhm close(sd); 79cf0fd932Sbluhm // printf("sender done\n"); 80a545a52cSbluhm } 81a545a52cSbluhm 82a545a52cSbluhm static void 83cf0fd932Sbluhm receiver(int sd) 84a545a52cSbluhm { 85a545a52cSbluhm union packet p; 86a545a52cSbluhm ssize_t n; 87a545a52cSbluhm uintmax_t seq = 0; 88a545a52cSbluhm 89cf0fd932Sbluhm for (size_t i = 0; i < COUNT; i++) { 90a545a52cSbluhm if (rdied) 91a545a52cSbluhm return; 92cf0fd932Sbluhm while ((n = recv(sd, &p, sizeof(p), 0), sizeof(p)) 93a545a52cSbluhm == sizeof(p)) 94a545a52cSbluhm { 95a545a52cSbluhm if (rdied) 96a545a52cSbluhm return; 97a545a52cSbluhm if (p.seq != seq) 98a545a52cSbluhm printf("%ju != %ju\n", p.seq, seq); 99cf0fd932Sbluhm if (seq % 10 == 0) 100*539ef4ccSclaudio usleep(100); 101a545a52cSbluhm seq = p.seq + 1; 102a545a52cSbluhm } 103cf0fd932Sbluhm // printf("<<%zd %d %ju\n", n, errno, seq); 104a545a52cSbluhm if (n == 0) 105a545a52cSbluhm return; 106a545a52cSbluhm ATF_REQUIRE_EQ(n, -1); 107a545a52cSbluhm ATF_REQUIRE_MSG(errno == ENOBUFS, "recv %s", strerror(errno)); 108cf0fd932Sbluhm } 109cf0fd932Sbluhm close(sd); 110a545a52cSbluhm } 111a545a52cSbluhm 112a545a52cSbluhm static void 113a545a52cSbluhm sendrecv(int rerror) 114a545a52cSbluhm { 115cf0fd932Sbluhm int fd[2], sd[2], error; 116cf0fd932Sbluhm char c = 0; 117a545a52cSbluhm struct sigaction sa; 118a545a52cSbluhm 119cf0fd932Sbluhm error = socketpair(AF_UNIX, SOCK_DGRAM, 0, sd); 120a545a52cSbluhm ATF_REQUIRE_MSG(error != -1, "socketpair failed (%s)", strerror(errno)); 121cf0fd932Sbluhm error = pipe(fd); 122cf0fd932Sbluhm ATF_REQUIRE_MSG(error != -1, "pipe failed (%s)", strerror(errno)); 123a545a52cSbluhm 124cf0fd932Sbluhm for (size_t i = 0; i < __arraycount(sd); i++) { 125cf0fd932Sbluhm error = setsockopt(sd[i], SOL_SOCKET, SO_RERROR, &rerror, 126a545a52cSbluhm sizeof(rerror)); 127a545a52cSbluhm ATF_REQUIRE_MSG(error != -1, 128a545a52cSbluhm "setsockopt(SO_RERROR) failed (%s)", strerror(errno)); 129a545a52cSbluhm } 130a545a52cSbluhm 131a545a52cSbluhm memset(&sa, 0, sizeof(sa)); 132a545a52cSbluhm sa.sa_flags = 0; 133a545a52cSbluhm sa.sa_handler = &handle_sigchld; 134a545a52cSbluhm sigemptyset(&sa.sa_mask); 135a545a52cSbluhm error = sigaction(SIGCHLD, &sa, 0); 136a545a52cSbluhm ATF_REQUIRE_MSG(error != -1, "sigaction failed (%s)", 137a545a52cSbluhm strerror(errno)); 138a545a52cSbluhm 139a545a52cSbluhm switch (fork()) { 140a545a52cSbluhm case -1: 141a545a52cSbluhm ATF_REQUIRE_MSG(errno == 0, 142cf0fd932Sbluhm "fork failed (%s)", strerror(errno)); 143a545a52cSbluhm __unreachable(); 144a545a52cSbluhm /*NOTREACHED*/ 145a545a52cSbluhm case 0: 146cf0fd932Sbluhm read(fd[1], &c, sizeof(c)); 147cf0fd932Sbluhm sender(sd[0]); 148cf0fd932Sbluhm close(sd[0]); 149a545a52cSbluhm exit(EXIT_SUCCESS); 150a545a52cSbluhm /*NOTREACHED*/ 151a545a52cSbluhm default: 152cf0fd932Sbluhm write(fd[0], &c, sizeof(c)); 153cf0fd932Sbluhm receiver(sd[1]); 154a545a52cSbluhm return; 155a545a52cSbluhm } 156a545a52cSbluhm } 157a545a52cSbluhm 158a545a52cSbluhm ATF_TC(sendrecv_basic); 159a545a52cSbluhm 160a545a52cSbluhm ATF_TC_HEAD(sendrecv_basic, tc) 161a545a52cSbluhm { 162a545a52cSbluhm atf_tc_set_md_var(tc, "descr", "A basic test of send/recv(2)"); 163a545a52cSbluhm } 164a545a52cSbluhm 165a545a52cSbluhm ATF_TC_BODY(sendrecv_basic, tc) 166a545a52cSbluhm { 167a545a52cSbluhm sendrecv(0); 168a545a52cSbluhm } 169a545a52cSbluhm 170a545a52cSbluhm ATF_TC(sendrecv_rerror); 171a545a52cSbluhm 172a545a52cSbluhm ATF_TC_HEAD(sendrecv_rerror, tc) 173a545a52cSbluhm { 174a545a52cSbluhm atf_tc_set_md_var(tc, "descr", "Test send/recv(2) with receiver error"); 175a545a52cSbluhm } 176a545a52cSbluhm 177a545a52cSbluhm ATF_TC_BODY(sendrecv_rerror, tc) 178a545a52cSbluhm { 179a545a52cSbluhm sendrecv(1); 180a545a52cSbluhm } 181a545a52cSbluhm 182a545a52cSbluhm ATF_TP_ADD_TCS(tp) 183a545a52cSbluhm { 184a545a52cSbluhm 185a545a52cSbluhm ATF_TP_ADD_TC(tp, sendrecv_basic); 186a545a52cSbluhm ATF_TP_ADD_TC(tp, sendrecv_rerror); 187a545a52cSbluhm 188a545a52cSbluhm return atf_no_error(); 189a545a52cSbluhm } 190