Path: blob/main/tests/sys/kern/socket_msg_waitall.c
39536 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2023 The FreeBSD Foundation4*5* This software was developed by Mark Johnston under sponsorship from6* the FreeBSD Foundation.7*/89#include <sys/types.h>10#include <sys/socket.h>11#include <sys/un.h>1213#include <netinet/in.h>1415#include <errno.h>16#include <pthread.h>17#include <stdlib.h>18#include <unistd.h>1920#include <atf-c.h>2122struct close_test_params {23struct sockaddr_storage sa;24size_t msglen;25int count;26int af, type, proto;27};2829static void *30close_test_client(void *arg)31{32struct close_test_params *p = arg;33char *buf;34size_t buflen;3536buflen = p->msglen + 1;37buf = malloc(buflen);38ATF_REQUIRE(buf != NULL);3940while (p->count-- > 0) {41ssize_t n;42int error, s;4344s = socket(p->af, p->type, p->proto);45ATF_REQUIRE_MSG(s >= 0, "socket: %s", strerror(errno));4647error = connect(s, (struct sockaddr *)&p->sa, p->sa.ss_len);48ATF_REQUIRE_MSG(error == 0, "connect: %s", strerror(errno));4950n = recv(s, buf, buflen, MSG_WAITALL);51ATF_REQUIRE_MSG(n == (ssize_t)p->msglen,52"recv: got %zd expected %zd", n, (ssize_t)p->msglen);5354ATF_REQUIRE(close(s) == 0);55}56free(buf);5758return (NULL);59}6061static void62close_test(struct sockaddr *sa, unsigned int count, int af, int type, int proto)63{64struct close_test_params p;65const char *msg;66pthread_t t;67size_t msglen;68int error, s;6970s = socket(af, type, proto);71ATF_REQUIRE_MSG(s >= 0, "socket %s", strerror(errno));7273ATF_REQUIRE_MSG(bind(s, sa, sa->sa_len) == 0,74"bind: %s", strerror(errno));75ATF_REQUIRE_MSG(listen(s, 1) == 0,76"listen: %s", strerror(errno));77ATF_REQUIRE_MSG(getsockname(s, sa, &(socklen_t){ sa->sa_len }) == 0,78"getsockname: %s", strerror(errno));7980msg = "hello bonjour";81msglen = strlen(msg) + 1;82p = (struct close_test_params){83.count = count,84.msglen = msglen,85.af = af,86.type = type,87.proto = proto,88};89memcpy(&p.sa, sa, sa->sa_len);90error = pthread_create(&t, NULL, close_test_client, &p);91ATF_REQUIRE_MSG(error == 0, "pthread_create: %s", strerror(error));9293while (count-- > 0) {94ssize_t n;95int cs;9697cs = accept(s, NULL, NULL);98ATF_REQUIRE_MSG(cs >= 0, "accept: %s", strerror(errno));99100n = send(cs, msg, msglen, 0);101ATF_REQUIRE_MSG(n == (ssize_t)msglen,102"send: %s", strerror(errno));103104ATF_REQUIRE(close(cs) == 0);105}106107ATF_REQUIRE(close(s) == 0);108ATF_REQUIRE(pthread_join(t, NULL) == 0);109}110111/*112* Make sure that closing a connection kicks a MSG_WAITALL recv() out of the113* syscall. See bugzilla PR 212716.114*/115ATF_TC(close_tcp);116ATF_TC_HEAD(close_tcp, tc)117{118atf_tc_set_md_var(tc, "timeout", "10");119}120ATF_TC_BODY(close_tcp, tc)121{122struct sockaddr_in sin;123124sin = (struct sockaddr_in){125.sin_len = sizeof(sin),126.sin_family = AF_INET,127.sin_addr = { htonl(INADDR_LOOPBACK) },128.sin_port = htons(0),129};130close_test((struct sockaddr *)&sin, 1000, AF_INET, SOCK_STREAM,131IPPROTO_TCP);132}133134/* A variant of the above test for UNIX domain stream sockets. */135ATF_TC(close_unix_stream);136ATF_TC_HEAD(close_unix_stream, tc)137{138atf_tc_set_md_var(tc, "timeout", "10");139}140ATF_TC_BODY(close_unix_stream, tc)141{142struct sockaddr_un sun;143144sun = (struct sockaddr_un){145.sun_len = sizeof(sun),146.sun_family = AF_UNIX,147.sun_path = "socket_msg_waitall_unix",148};149close_test((struct sockaddr *)&sun, 1000, AF_UNIX, SOCK_STREAM, 0);150ATF_REQUIRE_MSG(unlink(sun.sun_path) == 0,151"unlink: %s", strerror(errno));152}153154/* A variant of the above test for UNIX domain seqpacket sockets. */155ATF_TC(close_unix_seqpacket);156ATF_TC_HEAD(close_unix_seqpacket, tc)157{158atf_tc_set_md_var(tc, "timeout", "10");159}160ATF_TC_BODY(close_unix_seqpacket, tc)161{162struct sockaddr_un sun;163164sun = (struct sockaddr_un){165.sun_len = sizeof(sun),166.sun_family = AF_UNIX,167.sun_path = "socket_msg_waitall_unix",168};169close_test((struct sockaddr *)&sun, 1000, AF_UNIX, SOCK_SEQPACKET, 0);170ATF_REQUIRE_MSG(unlink(sun.sun_path) == 0,171"unlink: %s", strerror(errno));172}173174ATF_TP_ADD_TCS(tp)175{176ATF_TP_ADD_TC(tp, close_tcp);177ATF_TP_ADD_TC(tp, close_unix_stream);178ATF_TP_ADD_TC(tp, close_unix_seqpacket);179180return (atf_no_error());181}182183184