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