1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "le_socket.h"
17
18 #include <arpa/inet.h>
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <netinet/in.h>
22 #include <stddef.h>
23 #include <string.h>
24 #include <sys/socket.h>
25 #include <sys/time.h>
26 #include <sys/stat.h>
27 #include <sys/un.h>
28 #include <unistd.h>
29
30 #include "le_utils.h"
31
SetSocketTimeout(int fd)32 static int SetSocketTimeout(int fd)
33 {
34 struct timeval timeout;
35 timeout.tv_sec = SOCKET_TIMEOUT;
36 timeout.tv_usec = 0;
37 int ret = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
38 LE_CHECK(ret == 0, return ret, "Failed to set socket option");
39
40 ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
41 LE_CHECK(ret == 0, return ret, "Failed to set socket option");
42 return ret;
43 }
44
CreatePipeServerSocket_(const char * server,int maxClient,int public)45 static int CreatePipeServerSocket_(const char *server, int maxClient, int public)
46 {
47 int listenfd = socket(PF_UNIX, SOCK_STREAM, 0);
48 LE_CHECK(listenfd > 0, return listenfd, "Failed to create socket errno %d", errno);
49
50 int ret = SetSocketTimeout(listenfd);
51 LE_CHECK(ret == 0, return ret, "Failed to set socket timeout");
52
53 unlink(server);
54 struct sockaddr_un serverAddr;
55 ret = memset_s(&serverAddr, sizeof(serverAddr), 0, sizeof(serverAddr));
56 LE_CHECK(ret == 0, close(listenfd);
57 return ret, "Failed to memory set. error: %d", errno);
58 serverAddr.sun_family = AF_UNIX;
59 ret = strcpy_s(serverAddr.sun_path, sizeof(serverAddr.sun_path), server);
60 LE_CHECK(ret == 0, close(listenfd);
61 return ret, "Failed to copy. error: %d", errno);
62 uint32_t size = offsetof(struct sockaddr_un, sun_path) + strlen(server);
63 ret = bind(listenfd, (struct sockaddr *)&serverAddr, size);
64 LE_CHECK(ret >= 0, close(listenfd);
65 return ret, "Failed to bind socket. error: %d", errno);
66
67 SetNoBlock(listenfd);
68 ret = listen(listenfd, maxClient);
69 LE_CHECK(ret >= 0, close(listenfd);
70 return ret, "Failed to listen socket error: %d", errno);
71 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
72 if (public) {
73 mode |= S_IROTH | S_IWOTH;
74 }
75 ret = chmod(server, mode);
76 LE_CHECK(ret == 0, return -1, "Failed to chmod %s, err %d. ", server, errno);
77 LE_LOGV("CreatePipeSocket listen fd: %d server:%s ", listenfd, serverAddr.sun_path);
78 return listenfd;
79 }
80
CreatePipeSocket_(const char * server)81 static int CreatePipeSocket_(const char *server)
82 {
83 int fd = socket(PF_UNIX, SOCK_STREAM, 0);
84 LE_CHECK(fd > 0, return fd, "Failed to create socket");
85 SetNoBlock(fd);
86
87 int on = 1;
88 int ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
89 LE_CHECK(ret == 0, return ret, "Failed to set socket option");
90
91 ret = SetSocketTimeout(fd);
92 LE_CHECK(ret == 0, return ret, "Failed to set socket timeout");
93
94 struct sockaddr_un serverAddr;
95 ret = memset_s(&serverAddr, sizeof(serverAddr), 0, sizeof(serverAddr));
96 LE_CHECK(ret == 0, close(fd);
97 return ret, "Failed to memset_s serverAddr");
98 serverAddr.sun_family = AF_UNIX;
99 ret = strcpy_s(serverAddr.sun_path, sizeof(serverAddr.sun_path), server);
100 LE_CHECK(ret == 0, close(fd);
101 return ret, "Failed to strcpy_s sun_path");
102 uint32_t size = offsetof(struct sockaddr_un, sun_path) + strlen(serverAddr.sun_path);
103 ret = connect(fd, (struct sockaddr *)&serverAddr, size);
104 LE_CHECK(ret >= 0, close(fd);
105 return ret, "Failed to connect socket");
106 LE_LOGV("CreatePipeSocket connect fd: %d server: %s ", fd, serverAddr.sun_path);
107 return fd;
108 }
109
GetSockaddrFromServer_(const char * server,struct sockaddr_in * addr)110 static LE_STATUS GetSockaddrFromServer_(const char *server, struct sockaddr_in *addr)
111 {
112 int ret = memset_s(addr, sizeof(struct sockaddr_in), 0, sizeof(struct sockaddr_in));
113 LE_CHECK(ret == 0, return ret, "Failed to memory set. error: %s", strerror(errno));
114 addr->sin_family = AF_INET;
115 const char *portStr = strstr(server, ":");
116 LE_CHECK(portStr != NULL, return LE_FAILURE, "Failed to get addr %s", server);
117 uint16_t port = atoi(portStr + 1);
118 addr->sin_port = htons(port);
119 ret = inet_pton(AF_INET, server, &addr->sin_addr);
120 LE_CHECK(ret >= 0, return LE_FAILURE, "Failed to inet_pton addr %s", server);
121 LE_LOGV("CreateTcpSocket server: %s port: %d", server, port);
122 return LE_SUCCESS;
123 }
124
CreateTcpServerSocket_(const char * server,int maxClient)125 static int CreateTcpServerSocket_(const char *server, int maxClient)
126 {
127 int listenfd = socket(AF_INET, SOCK_STREAM, 0);
128 LE_CHECK(listenfd > 0, return listenfd, "Failed to create socket");
129
130 int ret = SetSocketTimeout(listenfd);
131 LE_CHECK(ret == 0, return ret, "Failed to set socket timeout");
132
133 struct sockaddr_in serverAddr;
134 GetSockaddrFromServer_(server, &serverAddr);
135 ret = bind(listenfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
136 LE_CHECK(ret >= 0, close(listenfd);
137 return ret, "Failed to bind socket");
138 SetNoBlock(listenfd);
139
140 ret = listen(listenfd, maxClient);
141 LE_CHECK(ret >= 0, close(listenfd);
142 return ret, "Failed to listen socket");
143 return listenfd;
144 }
145
CreateTcpSocket_(const char * server)146 static int CreateTcpSocket_(const char *server)
147 {
148 int fd = socket(AF_INET, SOCK_STREAM, 0);
149 LE_CHECK(fd > 0, return fd, "Failed to create socket");
150 SetNoBlock(fd);
151
152 int on = 1;
153 int ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
154 LE_CHECK(ret == 0, return ret, "Failed to set socket option");
155
156 ret = SetSocketTimeout(fd);
157 LE_CHECK(ret == 0, return ret, "Failed to set socket timeout");
158
159 struct sockaddr_in serverAddr;
160 GetSockaddrFromServer_(server, &serverAddr);
161 ret = connect(fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
162 LE_CHECK(ret >= 0, close(fd);
163 return ret, "Failed to connect socket errno:%d", errno);
164 return fd;
165 }
166
AcceptPipeSocket_(int serverFd)167 static int AcceptPipeSocket_(int serverFd)
168 {
169 struct sockaddr_un clientAddr;
170 socklen_t addrlen = sizeof(clientAddr);
171 bzero(&clientAddr, addrlen);
172 int fd = accept(serverFd, (struct sockaddr *)&clientAddr, &addrlen);
173 LE_CHECK(fd >= 0, return fd, "Failed to accept socket");
174 LE_LOGV("AcceptPipeSocket client fd %d %s ", fd, clientAddr.sun_path);
175 return fd;
176 }
177
AcceptTcpSocket_(int serverFd)178 static int AcceptTcpSocket_(int serverFd)
179 {
180 struct sockaddr_in clientAddr;
181 socklen_t addrlen = sizeof(clientAddr);
182 bzero(&clientAddr, addrlen);
183 int fd = accept(serverFd, (struct sockaddr *)&clientAddr, &addrlen);
184 LE_CHECK(fd >= 0, return fd, "Failed to accept socket");
185 LE_LOGV("AcceptTcpSocket_ client: %s ", inet_ntoa(clientAddr.sin_addr));
186 return fd;
187 }
188 INIT_LOCAL_API
CreateSocket(int flags,const char * server)189 int CreateSocket(int flags, const char *server)
190 {
191 int fd = -1;
192 int type = flags & 0x0000ff00;
193 LE_LOGV("CreateSocket flags %x type %x server %s", flags, type, server);
194 if (type == TASK_TCP) {
195 if (LE_TEST_FLAGS(flags, TASK_SERVER)) {
196 fd = CreateTcpServerSocket_(server, LOOP_MAX_CLIENT);
197 } else if (LE_TEST_FLAGS(flags, TASK_CONNECT)) {
198 fd = CreateTcpSocket_(server);
199 }
200 } else if (type == TASK_PIPE) {
201 if (LE_TEST_FLAGS(flags, TASK_SERVER)) {
202 fd = CreatePipeServerSocket_(server, LOOP_MAX_CLIENT,
203 (int)LE_TEST_FLAGS(flags, TASK_PUBLIC));
204 } else if (LE_TEST_FLAGS(flags, TASK_CONNECT)) {
205 fd = CreatePipeSocket_(server);
206 }
207 }
208 if (fd <= 0) {
209 LE_LOGE("Invalid flags 0x%08x for server %s", flags, server);
210 return -1;
211 }
212 return fd;
213 }
214 INIT_LOCAL_API
AcceptSocket(int fd,int flags)215 int AcceptSocket(int fd, int flags)
216 {
217 int clientFd = -1;
218 int type = flags & 0x0000ff00;
219 if (type == TASK_TCP) {
220 clientFd = AcceptTcpSocket_(fd);
221 } else if (type == TASK_PIPE) {
222 clientFd = AcceptPipeSocket_(fd);
223 } else {
224 LE_LOGE("AcceptSocket invalid flags %#8x ", flags);
225 return -1;
226 }
227 SetNoBlock(clientFd);
228 return clientFd;
229 }
230
231 INIT_LOCAL_API
listenSocket(int fd,uint32_t flags,const char * server)232 int listenSocket(int fd, uint32_t flags, const char *server)
233 {
234 unsigned int type = flags & 0x0000ff00;
235 LE_LOGV("listenSocket flags %x type %x server %s", flags, type, server);
236 SetNoBlock(fd);
237 if (!LE_TEST_FLAGS(flags, TASK_SERVER)) {
238 return 0;
239 }
240 if (type == TASK_TCP) {
241 int ret = listen(fd, LOOP_MAX_CLIENT);
242 LE_CHECK(ret >= 0, close(fd);
243 return ret, "Failed to listen socket");
244 } else if (type == TASK_PIPE) {
245 int ret = listen(fd, LOOP_MAX_CLIENT);
246 LE_CHECK(ret >= 0, close(fd);
247 return ret, "Failed to listen socket error: %d", errno);
248 ret = chmod(server, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
249 LE_CHECK(ret == 0, return -1, "Failed to chmod %s, err %d. ", server, errno);
250 }
251 return 0;
252 }
253