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