2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2022 Alexander V. Chernikov
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
28 #include <sys/param.h>
29 #include <sys/errno.h>
30 #include <sys/socket.h>
33 #include <netinet/in.h>
42 check_recvmsg(int cs, int ss, struct sockaddr *sa, const size_t sizes[],
47 memset(buf, 0xFF, sizeof(buf));
48 for (size_t i = 0; i < nsizes; i++) {
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);
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);
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);
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);
70 ATF_REQUIRE(close(cs) == 0);
71 ATF_REQUIRE(close(ss) == 0);
74 ATF_TC_WITHOUT_HEAD(recv_trunc_afinet_udp);
75 ATF_TC_BODY(recv_trunc_afinet_udp, tc)
77 struct sockaddr_in sin;
81 ss = socket(PF_INET, SOCK_DGRAM, 0);
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));
93 cs = socket(PF_INET, SOCK_DGRAM, 0);
96 size_t sizes[] = {80, 255, 256, 1024, 4096, 9000};
97 check_recvmsg(cs, ss, sa, sizes, nitems(sizes));
100 ATF_TC_WITHOUT_HEAD(recv_trunc_afinet6_udp);
101 ATF_TC_BODY(recv_trunc_afinet6_udp, tc)
103 struct sockaddr_in6 sin6;
107 ss = socket(PF_INET6, SOCK_DGRAM, 0);
108 ATF_REQUIRE(ss >= 0);
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));
120 cs = socket(PF_INET6, SOCK_DGRAM, 0);
121 ATF_REQUIRE(cs >= 0);
123 size_t sizes[] = {80, 255, 256, 1024, 4096, 9000};
124 check_recvmsg(cs, ss, sa, sizes, nitems(sizes));
127 ATF_TC_WITHOUT_HEAD(recv_trunc_afunix_dgram);
128 ATF_TC_BODY(recv_trunc_afunix_dgram, tc)
130 struct sockaddr_un sun;
134 ss = socket(PF_UNIX, SOCK_DGRAM, 0);
135 ATF_REQUIRE(ss >= 0);
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));
145 cs = socket(PF_UNIX, SOCK_DGRAM, 0);
146 ATF_REQUIRE(cs >= 0);
148 size_t sizes[] = {80, 255, 256, 1024, 2000};
149 check_recvmsg(cs, ss, sa, sizes, nitems(sizes));
152 ATF_TC_WITHOUT_HEAD(recv_trunc_afunix_seqpacket);
153 ATF_TC_BODY(recv_trunc_afunix_seqpacket, tc)
155 struct sockaddr_un sun;
159 ss = socket(PF_UNIX, SOCK_SEQPACKET, 0);
160 ATF_REQUIRE(ss >= 0);
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));
170 ATF_REQUIRE_MSG(rc == 0, "listen failed: %s", strerror(errno));
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);
179 size_t sizes[] = {80, 255, 256, 1024, 2000};
180 check_recvmsg(cs, nss, sa, sizes, nitems(sizes));
182 ATF_REQUIRE(close(ss) == 0);
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);
192 return (atf_no_error());