]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/kern/socket_msg_trunc.c
socket tests: Clean up the MSG_TRUNC regression tests a bit
[FreeBSD/FreeBSD.git] / tests / sys / kern / socket_msg_trunc.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2022 Alexander V. Chernikov
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/param.h>
29 #include <sys/errno.h>
30 #include <sys/socket.h>
31 #include <sys/un.h>
32
33 #include <netinet/in.h>
34
35 #include <poll.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38
39 #include <atf-c.h>
40
41 static void
42 check_recvmsg(int cs, int ss, struct sockaddr *sa, const size_t sizes[],
43     size_t nsizes)
44 {
45         char buf[4096];
46
47         memset(buf, 0xFF, sizeof(buf));
48         for (size_t i = 0; i < nsizes; i++) {
49                 ssize_t rc;
50                 size_t sz = sizes[i];
51                 char tbuf[1];
52
53                 rc = sendto(cs, buf, sz, 0, sa, sa->sa_len);
54                 ATF_REQUIRE_MSG(rc != -1, "sendto failed: %s", strerror(errno));
55                 ATF_REQUIRE((size_t)rc == sz);
56
57                 rc = recv(ss, NULL, 0, MSG_PEEK | MSG_TRUNC);
58                 ATF_REQUIRE_MSG(rc >= 0, "recv failed: %s", strerror(errno));
59                 ATF_REQUIRE((size_t)rc == sz);
60
61                 rc = recv(ss, tbuf, sizeof(tbuf), MSG_PEEK | MSG_TRUNC);
62                 ATF_REQUIRE_MSG(rc >= 0, "recv failed: %s", strerror(errno));
63                 ATF_REQUIRE((size_t)rc == sz);
64
65                 rc = recv(ss, tbuf, sizeof(tbuf), MSG_TRUNC);
66                 ATF_REQUIRE_MSG(rc >= 0, "recv failed: %s", strerror(errno));
67                 ATF_REQUIRE((size_t)rc == sz);
68         }
69
70         ATF_REQUIRE(close(cs) == 0);
71         ATF_REQUIRE(close(ss) == 0);
72 }
73
74 ATF_TC_WITHOUT_HEAD(recv_trunc_afinet_udp);
75 ATF_TC_BODY(recv_trunc_afinet_udp, tc)
76 {
77         struct sockaddr_in sin;
78         struct sockaddr *sa;
79         int ss, cs, rc;
80
81         ss = socket(PF_INET, SOCK_DGRAM, 0);
82         ATF_REQUIRE(ss >= 0);
83
84         memset(&sin, 0, sizeof(sin));
85         sin.sin_family = AF_INET;
86         sin.sin_len = sizeof(sin);
87         sin.sin_port = htons(6666);
88         sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
89         sa = (struct sockaddr *)&sin;
90         rc = bind(ss, sa, sa->sa_len);
91         ATF_REQUIRE_MSG(rc == 0, "bind failed: %s", strerror(errno));
92
93         cs = socket(PF_INET, SOCK_DGRAM, 0);
94         ATF_REQUIRE(cs >= 0);
95
96         size_t sizes[] = {80, 255, 256, 1024, 4096, 9000};
97         check_recvmsg(cs, ss, sa, sizes, nitems(sizes));
98 }
99
100 ATF_TC_WITHOUT_HEAD(recv_trunc_afinet6_udp);
101 ATF_TC_BODY(recv_trunc_afinet6_udp, tc)
102 {
103         struct sockaddr_in6 sin6;
104         struct sockaddr *sa;
105         int cs, ss, rc;
106
107         ss = socket(PF_INET6, SOCK_DGRAM, 0);
108         ATF_REQUIRE(ss >= 0);
109
110         memset(&sin6, 0, sizeof(sin6));
111         sin6.sin6_family = AF_INET6;
112         sin6.sin6_len = sizeof(sin6);
113         sin6.sin6_port = htons(6666);
114         const struct in6_addr in6loopback = IN6ADDR_LOOPBACK_INIT;
115         sin6.sin6_addr = in6loopback;
116         sa = (struct sockaddr *)&sin6;
117         rc = bind(ss, sa, sa->sa_len);
118         ATF_REQUIRE_MSG(rc == 0, "bind failed: %s", strerror(errno));
119
120         cs = socket(PF_INET6, SOCK_DGRAM, 0);
121         ATF_REQUIRE(cs >= 0);
122
123         size_t sizes[] = {80, 255, 256, 1024, 4096, 9000};
124         check_recvmsg(cs, ss, sa, sizes, nitems(sizes));
125 }
126
127 ATF_TC_WITHOUT_HEAD(recv_trunc_afunix_dgram);
128 ATF_TC_BODY(recv_trunc_afunix_dgram, tc)
129 {
130         struct sockaddr_un sun;
131         struct sockaddr *sa;
132         int ss, cs, rc;
133
134         ss = socket(PF_UNIX, SOCK_DGRAM, 0);
135         ATF_REQUIRE(ss >= 0);
136
137         bzero(&sun, sizeof(sun));
138         sun.sun_family = AF_UNIX;
139         strlcpy(sun.sun_path, "test_check_recvmsg_socket", sizeof(sun.sun_path));
140         sun.sun_len = sizeof(sun);
141         sa = (struct sockaddr *)&sun;
142         rc = bind(ss, sa, sa->sa_len);
143         ATF_REQUIRE_MSG(rc == 0, "bind failed: %s", strerror(errno));
144
145         cs = socket(PF_UNIX, SOCK_DGRAM, 0);
146         ATF_REQUIRE(cs >= 0);
147
148         size_t sizes[] = {80, 255, 256, 1024, 2000};
149         check_recvmsg(cs, ss, sa, sizes, nitems(sizes));
150 }
151
152 ATF_TC_WITHOUT_HEAD(recv_trunc_afunix_seqpacket);
153 ATF_TC_BODY(recv_trunc_afunix_seqpacket, tc)
154 {
155         struct sockaddr_un sun;
156         struct sockaddr *sa;
157         int ss, nss, cs, rc;
158
159         ss = socket(PF_UNIX, SOCK_SEQPACKET, 0);
160         ATF_REQUIRE(ss >= 0);
161
162         bzero(&sun, sizeof(sun));
163         sun.sun_family = AF_UNIX;
164         strlcpy(sun.sun_path, "test_check_recvmsg_socket", sizeof(sun.sun_path));
165         sun.sun_len = sizeof(sun);
166         sa = (struct sockaddr *)&sun;
167         rc = bind(ss, sa, sa->sa_len);
168         ATF_REQUIRE_MSG(rc == 0, "bind failed: %s", strerror(errno));
169         rc = listen(ss, 1);
170         ATF_REQUIRE_MSG(rc == 0, "listen failed: %s", strerror(errno));
171
172         cs = socket(PF_UNIX, SOCK_SEQPACKET, 0);
173         ATF_REQUIRE(cs >= 0);
174         rc = connect(cs, sa, sa->sa_len);
175         ATF_REQUIRE_MSG(rc == 0, "connect failed: %s", strerror(errno));
176         nss = accept(ss, NULL, NULL);
177         ATF_REQUIRE(nss >= 0);
178
179         size_t sizes[] = {80, 255, 256, 1024, 2000};
180         check_recvmsg(cs, nss, sa, sizes, nitems(sizes));
181
182         ATF_REQUIRE(close(ss) == 0);
183 }
184
185 ATF_TP_ADD_TCS(tp)
186 {
187         ATF_TP_ADD_TC(tp, recv_trunc_afinet_udp);
188         ATF_TP_ADD_TC(tp, recv_trunc_afinet6_udp);
189         ATF_TP_ADD_TC(tp, recv_trunc_afunix_dgram);
190         ATF_TP_ADD_TC(tp, recv_trunc_afunix_seqpacket);
191
192         return (atf_no_error());
193 }