xref: /aosp_15_r20/bionic/tests/sys_socket_test.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  *
4*8d67ca89SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker  *
8*8d67ca89SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker  *
10*8d67ca89SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker  * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker  */
16*8d67ca89SAndroid Build Coastguard Worker 
17*8d67ca89SAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*8d67ca89SAndroid Build Coastguard Worker 
19*8d67ca89SAndroid Build Coastguard Worker #include <errno.h>
20*8d67ca89SAndroid Build Coastguard Worker #include <sys/types.h>
21*8d67ca89SAndroid Build Coastguard Worker #include <sys/socket.h>
22*8d67ca89SAndroid Build Coastguard Worker #include <sys/un.h>
23*8d67ca89SAndroid Build Coastguard Worker #include <fcntl.h>
24*8d67ca89SAndroid Build Coastguard Worker 
25*8d67ca89SAndroid Build Coastguard Worker #include "utils.h"
26*8d67ca89SAndroid Build Coastguard Worker 
27*8d67ca89SAndroid Build Coastguard Worker struct ConnectData {
28*8d67ca89SAndroid Build Coastguard Worker   bool (*callback_fn)(int);
29*8d67ca89SAndroid Build Coastguard Worker   const char* sock_path;
ConnectDataConnectData30*8d67ca89SAndroid Build Coastguard Worker   ConnectData(bool (*callback_func)(int), const char* socket_path)
31*8d67ca89SAndroid Build Coastguard Worker    : callback_fn(callback_func), sock_path(socket_path) {}
32*8d67ca89SAndroid Build Coastguard Worker };
33*8d67ca89SAndroid Build Coastguard Worker 
ConnectFn(void * data)34*8d67ca89SAndroid Build Coastguard Worker static void* ConnectFn(void* data) {
35*8d67ca89SAndroid Build Coastguard Worker   ConnectData* pdata = reinterpret_cast<ConnectData*>(data);
36*8d67ca89SAndroid Build Coastguard Worker   bool (*callback_fn)(int) = pdata->callback_fn;
37*8d67ca89SAndroid Build Coastguard Worker   void* return_value = nullptr;
38*8d67ca89SAndroid Build Coastguard Worker 
39*8d67ca89SAndroid Build Coastguard Worker   int fd = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
40*8d67ca89SAndroid Build Coastguard Worker   if (fd < 0) {
41*8d67ca89SAndroid Build Coastguard Worker     GTEST_LOG_(ERROR) << "socket call failed: " << strerror(errno);
42*8d67ca89SAndroid Build Coastguard Worker     return reinterpret_cast<void*>(-1);
43*8d67ca89SAndroid Build Coastguard Worker   }
44*8d67ca89SAndroid Build Coastguard Worker 
45*8d67ca89SAndroid Build Coastguard Worker   struct sockaddr_un addr;
46*8d67ca89SAndroid Build Coastguard Worker   memset(&addr, 0, sizeof(addr));
47*8d67ca89SAndroid Build Coastguard Worker   addr.sun_family = AF_UNIX;
48*8d67ca89SAndroid Build Coastguard Worker   addr.sun_path[0] = '\0';
49*8d67ca89SAndroid Build Coastguard Worker   strcpy(addr.sun_path + 1, pdata->sock_path);
50*8d67ca89SAndroid Build Coastguard Worker 
51*8d67ca89SAndroid Build Coastguard Worker   if (connect(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
52*8d67ca89SAndroid Build Coastguard Worker     GTEST_LOG_(ERROR) << "connect call failed: " << strerror(errno);
53*8d67ca89SAndroid Build Coastguard Worker     return_value = reinterpret_cast<void*>(-1);
54*8d67ca89SAndroid Build Coastguard Worker   }
55*8d67ca89SAndroid Build Coastguard Worker   else if (callback_fn != nullptr && !callback_fn(fd)) {
56*8d67ca89SAndroid Build Coastguard Worker     return_value = reinterpret_cast<void*>(-1);
57*8d67ca89SAndroid Build Coastguard Worker   }
58*8d67ca89SAndroid Build Coastguard Worker 
59*8d67ca89SAndroid Build Coastguard Worker   close(fd);
60*8d67ca89SAndroid Build Coastguard Worker 
61*8d67ca89SAndroid Build Coastguard Worker   return return_value;
62*8d67ca89SAndroid Build Coastguard Worker }
63*8d67ca89SAndroid Build Coastguard Worker 
RunTest(void (* test_fn)(struct sockaddr_un *,int),bool (* callback_fn)(int fd),const char * sock_path)64*8d67ca89SAndroid Build Coastguard Worker static void RunTest(void (*test_fn)(struct sockaddr_un*, int),
65*8d67ca89SAndroid Build Coastguard Worker                     bool (*callback_fn)(int fd), const char* sock_path) {
66*8d67ca89SAndroid Build Coastguard Worker   int fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
67*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(fd, -1) << strerror(errno);
68*8d67ca89SAndroid Build Coastguard Worker 
69*8d67ca89SAndroid Build Coastguard Worker   struct sockaddr_un addr;
70*8d67ca89SAndroid Build Coastguard Worker   memset(&addr, 0, sizeof(addr));
71*8d67ca89SAndroid Build Coastguard Worker   addr.sun_family = AF_UNIX;
72*8d67ca89SAndroid Build Coastguard Worker   addr.sun_path[0] = '\0';
73*8d67ca89SAndroid Build Coastguard Worker   strcpy(addr.sun_path + 1, sock_path);
74*8d67ca89SAndroid Build Coastguard Worker 
75*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(-1, bind(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))) << strerror(errno);
76*8d67ca89SAndroid Build Coastguard Worker 
77*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(-1, listen(fd, 1)) << strerror(errno);
78*8d67ca89SAndroid Build Coastguard Worker 
79*8d67ca89SAndroid Build Coastguard Worker   ConnectData connect_data(callback_fn, sock_path);
80*8d67ca89SAndroid Build Coastguard Worker 
81*8d67ca89SAndroid Build Coastguard Worker   pthread_t thread;
82*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, pthread_create(&thread, nullptr, ConnectFn, &connect_data));
83*8d67ca89SAndroid Build Coastguard Worker 
84*8d67ca89SAndroid Build Coastguard Worker   fd_set read_set;
85*8d67ca89SAndroid Build Coastguard Worker   FD_ZERO(&read_set);
86*8d67ca89SAndroid Build Coastguard Worker   FD_SET(fd, &read_set);
87*8d67ca89SAndroid Build Coastguard Worker   timeval tv;
88*8d67ca89SAndroid Build Coastguard Worker   tv.tv_sec = 5;
89*8d67ca89SAndroid Build Coastguard Worker   tv.tv_usec = 0;
90*8d67ca89SAndroid Build Coastguard Worker   ASSERT_LT(0, select(fd+1, &read_set, nullptr, nullptr, &tv));
91*8d67ca89SAndroid Build Coastguard Worker 
92*8d67ca89SAndroid Build Coastguard Worker   test_fn(&addr, fd);
93*8d67ca89SAndroid Build Coastguard Worker 
94*8d67ca89SAndroid Build Coastguard Worker   void* ret_val;
95*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, pthread_join(thread, &ret_val));
96*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(nullptr, ret_val);
97*8d67ca89SAndroid Build Coastguard Worker 
98*8d67ca89SAndroid Build Coastguard Worker   close(fd);
99*8d67ca89SAndroid Build Coastguard Worker }
100*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_socket,accept4_error)101*8d67ca89SAndroid Build Coastguard Worker TEST(sys_socket, accept4_error) {
102*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, accept4(-1, nullptr, nullptr, 0));
103*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EBADF);
104*8d67ca89SAndroid Build Coastguard Worker }
105*8d67ca89SAndroid Build Coastguard Worker 
TestAccept4(struct sockaddr_un * addr,int fd)106*8d67ca89SAndroid Build Coastguard Worker static void TestAccept4(struct sockaddr_un* addr, int fd) {
107*8d67ca89SAndroid Build Coastguard Worker   socklen_t len = sizeof(*addr);
108*8d67ca89SAndroid Build Coastguard Worker   int fd_acc = accept4(fd, reinterpret_cast<struct sockaddr*>(addr), &len, SOCK_CLOEXEC);
109*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(fd_acc, -1) << strerror(errno);
110*8d67ca89SAndroid Build Coastguard Worker 
111*8d67ca89SAndroid Build Coastguard Worker   // Check that SOCK_CLOEXEC was set properly.
112*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(CloseOnExec(fd_acc));
113*8d67ca89SAndroid Build Coastguard Worker 
114*8d67ca89SAndroid Build Coastguard Worker   close(fd_acc);
115*8d67ca89SAndroid Build Coastguard Worker }
116*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_socket,accept4_smoke)117*8d67ca89SAndroid Build Coastguard Worker TEST(sys_socket, accept4_smoke) {
118*8d67ca89SAndroid Build Coastguard Worker   RunTest(TestAccept4, nullptr, "test_accept");
119*8d67ca89SAndroid Build Coastguard Worker }
120*8d67ca89SAndroid Build Coastguard Worker 
121*8d67ca89SAndroid Build Coastguard Worker const char* g_RecvMsgs[] = {
122*8d67ca89SAndroid Build Coastguard Worker   "RECVMMSG_ONE",
123*8d67ca89SAndroid Build Coastguard Worker   "RECVMMSG_TWO",
124*8d67ca89SAndroid Build Coastguard Worker   "RECVMMSG_THREE",
125*8d67ca89SAndroid Build Coastguard Worker };
126*8d67ca89SAndroid Build Coastguard Worker #define NUM_RECV_MSGS (sizeof(g_RecvMsgs)/sizeof(const char*))
127*8d67ca89SAndroid Build Coastguard Worker 
SendMultiple(int fd)128*8d67ca89SAndroid Build Coastguard Worker static bool SendMultiple(int fd) {
129*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
130*8d67ca89SAndroid Build Coastguard Worker     if (send(fd, g_RecvMsgs[i], strlen(g_RecvMsgs[i]) + 1, 0) < 0) {
131*8d67ca89SAndroid Build Coastguard Worker       GTEST_LOG_(ERROR) << "send call failed: " << strerror(errno);
132*8d67ca89SAndroid Build Coastguard Worker       return false;
133*8d67ca89SAndroid Build Coastguard Worker     }
134*8d67ca89SAndroid Build Coastguard Worker   }
135*8d67ca89SAndroid Build Coastguard Worker 
136*8d67ca89SAndroid Build Coastguard Worker   return true;
137*8d67ca89SAndroid Build Coastguard Worker }
138*8d67ca89SAndroid Build Coastguard Worker 
TestRecvMMsg(struct sockaddr_un * addr,int fd)139*8d67ca89SAndroid Build Coastguard Worker static void TestRecvMMsg(struct sockaddr_un *addr, int fd) {
140*8d67ca89SAndroid Build Coastguard Worker   socklen_t len = sizeof(*addr);
141*8d67ca89SAndroid Build Coastguard Worker   int fd_acc = accept(fd, reinterpret_cast<struct sockaddr*>(addr), &len);
142*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(fd_acc, -1) << strerror(errno);
143*8d67ca89SAndroid Build Coastguard Worker 
144*8d67ca89SAndroid Build Coastguard Worker   struct mmsghdr msgs[NUM_RECV_MSGS];
145*8d67ca89SAndroid Build Coastguard Worker   memset(msgs, 0, sizeof(struct mmsghdr)*NUM_RECV_MSGS);
146*8d67ca89SAndroid Build Coastguard Worker 
147*8d67ca89SAndroid Build Coastguard Worker   struct iovec io[NUM_RECV_MSGS];
148*8d67ca89SAndroid Build Coastguard Worker   char bufs[NUM_RECV_MSGS][100];
149*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
150*8d67ca89SAndroid Build Coastguard Worker     io[i].iov_base = reinterpret_cast<void*>(bufs[i]);
151*8d67ca89SAndroid Build Coastguard Worker     io[i].iov_len = strlen(g_RecvMsgs[i]) + 1;
152*8d67ca89SAndroid Build Coastguard Worker 
153*8d67ca89SAndroid Build Coastguard Worker     msgs[i].msg_hdr.msg_iov = &io[i];
154*8d67ca89SAndroid Build Coastguard Worker     msgs[i].msg_hdr.msg_iovlen = 1;
155*8d67ca89SAndroid Build Coastguard Worker     msgs[i].msg_len = sizeof(struct msghdr);
156*8d67ca89SAndroid Build Coastguard Worker   }
157*8d67ca89SAndroid Build Coastguard Worker 
158*8d67ca89SAndroid Build Coastguard Worker   struct timespec ts;
159*8d67ca89SAndroid Build Coastguard Worker   memset(&ts, 0, sizeof(ts));
160*8d67ca89SAndroid Build Coastguard Worker   ts.tv_sec = 5;
161*8d67ca89SAndroid Build Coastguard Worker   ts.tv_nsec = 0;
162*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(NUM_RECV_MSGS,
163*8d67ca89SAndroid Build Coastguard Worker             static_cast<size_t>(recvmmsg(fd_acc, msgs, NUM_RECV_MSGS, 0, &ts)))
164*8d67ca89SAndroid Build Coastguard Worker            << strerror(errno);
165*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
166*8d67ca89SAndroid Build Coastguard Worker     ASSERT_STREQ(g_RecvMsgs[i], bufs[i]);
167*8d67ca89SAndroid Build Coastguard Worker   }
168*8d67ca89SAndroid Build Coastguard Worker 
169*8d67ca89SAndroid Build Coastguard Worker   close(fd_acc);
170*8d67ca89SAndroid Build Coastguard Worker }
171*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_socket,recvmmsg_smoke)172*8d67ca89SAndroid Build Coastguard Worker TEST(sys_socket, recvmmsg_smoke) {
173*8d67ca89SAndroid Build Coastguard Worker   RunTest(TestRecvMMsg, SendMultiple, "test_revmmsg");
174*8d67ca89SAndroid Build Coastguard Worker }
175*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_socket,recvmmsg_error)176*8d67ca89SAndroid Build Coastguard Worker TEST(sys_socket, recvmmsg_error) {
177*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic push
178*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wnonnull"
179*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, recvmmsg(-1, nullptr, 0, 0, nullptr));
180*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EBADF);
181*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic pop
182*8d67ca89SAndroid Build Coastguard Worker }
183*8d67ca89SAndroid Build Coastguard Worker 
184*8d67ca89SAndroid Build Coastguard Worker const char* g_SendMsgs[] = {
185*8d67ca89SAndroid Build Coastguard Worker   "MSG_ONE",
186*8d67ca89SAndroid Build Coastguard Worker   "MSG_TWO",
187*8d67ca89SAndroid Build Coastguard Worker   "MSG_THREE"
188*8d67ca89SAndroid Build Coastguard Worker };
189*8d67ca89SAndroid Build Coastguard Worker #define NUM_SEND_MSGS (sizeof(g_SendMsgs)/sizeof(const char*))
190*8d67ca89SAndroid Build Coastguard Worker 
SendMMsg(int fd)191*8d67ca89SAndroid Build Coastguard Worker static bool SendMMsg(int fd) {
192*8d67ca89SAndroid Build Coastguard Worker   struct mmsghdr msgs[NUM_SEND_MSGS];
193*8d67ca89SAndroid Build Coastguard Worker   memset(msgs, 0, sizeof(struct mmsghdr)*NUM_SEND_MSGS);
194*8d67ca89SAndroid Build Coastguard Worker   struct iovec io[NUM_SEND_MSGS];
195*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < NUM_SEND_MSGS; i++) {
196*8d67ca89SAndroid Build Coastguard Worker     io[i].iov_base = reinterpret_cast<void*>(const_cast<char*>(g_SendMsgs[i]));
197*8d67ca89SAndroid Build Coastguard Worker     io[i].iov_len = strlen(g_SendMsgs[i]) + 1;
198*8d67ca89SAndroid Build Coastguard Worker     msgs[i].msg_hdr.msg_iov = &io[i];
199*8d67ca89SAndroid Build Coastguard Worker     msgs[i].msg_hdr.msg_iovlen = 1;
200*8d67ca89SAndroid Build Coastguard Worker     msgs[i].msg_len = sizeof(struct msghdr);
201*8d67ca89SAndroid Build Coastguard Worker   }
202*8d67ca89SAndroid Build Coastguard Worker 
203*8d67ca89SAndroid Build Coastguard Worker   if (sendmmsg(fd, msgs, NUM_SEND_MSGS, 0) < 0) {
204*8d67ca89SAndroid Build Coastguard Worker     GTEST_LOG_(ERROR) << "sendmmsg call failed: " << strerror(errno);
205*8d67ca89SAndroid Build Coastguard Worker     return false;
206*8d67ca89SAndroid Build Coastguard Worker   }
207*8d67ca89SAndroid Build Coastguard Worker   return true;
208*8d67ca89SAndroid Build Coastguard Worker }
209*8d67ca89SAndroid Build Coastguard Worker 
TestSendMMsg(struct sockaddr_un * addr,int fd)210*8d67ca89SAndroid Build Coastguard Worker static void TestSendMMsg(struct sockaddr_un *addr, int fd) {
211*8d67ca89SAndroid Build Coastguard Worker   socklen_t len = sizeof(*addr);
212*8d67ca89SAndroid Build Coastguard Worker   int fd_acc = accept(fd, reinterpret_cast<struct sockaddr*>(addr), &len);
213*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(fd_acc, -1) << strerror(errno);
214*8d67ca89SAndroid Build Coastguard Worker 
215*8d67ca89SAndroid Build Coastguard Worker   fd_set read_set;
216*8d67ca89SAndroid Build Coastguard Worker   FD_ZERO(&read_set);
217*8d67ca89SAndroid Build Coastguard Worker   FD_SET(fd_acc, &read_set);
218*8d67ca89SAndroid Build Coastguard Worker 
219*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < NUM_SEND_MSGS; i++) {
220*8d67ca89SAndroid Build Coastguard Worker     timeval tv;
221*8d67ca89SAndroid Build Coastguard Worker     tv.tv_sec = 5;
222*8d67ca89SAndroid Build Coastguard Worker     tv.tv_usec = 0;
223*8d67ca89SAndroid Build Coastguard Worker     ASSERT_LT(0, select(fd_acc+1, &read_set, nullptr, nullptr, &tv));
224*8d67ca89SAndroid Build Coastguard Worker     char buffer[100];
225*8d67ca89SAndroid Build Coastguard Worker     ASSERT_EQ(strlen(g_SendMsgs[i]) + 1,
226*8d67ca89SAndroid Build Coastguard Worker               static_cast<size_t>(recv(fd_acc, buffer, sizeof(buffer), 0)));
227*8d67ca89SAndroid Build Coastguard Worker     ASSERT_STREQ(g_SendMsgs[i], buffer);
228*8d67ca89SAndroid Build Coastguard Worker   }
229*8d67ca89SAndroid Build Coastguard Worker 
230*8d67ca89SAndroid Build Coastguard Worker   close(fd_acc);
231*8d67ca89SAndroid Build Coastguard Worker }
232*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_socket,sendmmsg_smoke)233*8d67ca89SAndroid Build Coastguard Worker TEST(sys_socket, sendmmsg_smoke) {
234*8d67ca89SAndroid Build Coastguard Worker   RunTest(TestSendMMsg, SendMMsg, "test_sendmmsg");
235*8d67ca89SAndroid Build Coastguard Worker }
236*8d67ca89SAndroid Build Coastguard Worker 
TEST(sys_socket,sendmmsg_error)237*8d67ca89SAndroid Build Coastguard Worker TEST(sys_socket, sendmmsg_error) {
238*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic push
239*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wnonnull"
240*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, sendmmsg(-1, nullptr, 0, 0));
241*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EBADF);
242*8d67ca89SAndroid Build Coastguard Worker #pragma clang diagnostic pop
243*8d67ca89SAndroid Build Coastguard Worker }
244