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/stat.h>
26 #include <sys/un.h>
27 #include <unistd.h>
28
29 #include "le_utils.h"
30
CreatePipeServerSocket_(const char * server,int maxClient)31 static int CreatePipeServerSocket_(const char *server, int maxClient)
32 {
33 int listenfd = socket(PF_UNIX, SOCK_STREAM, 0);
34 LE_CHECK(listenfd > 0, return listenfd, "Failed to create socket errno %d", errno);
35
36 unlink(server);
37 struct sockaddr_un serverAddr;
38 int ret = memset_s(&serverAddr, sizeof(serverAddr), 0, sizeof(serverAddr));
39 LE_CHECK(ret == 0, close(listenfd);
40 return ret, "Failed to memory set. error: %d", errno);
41 serverAddr.sun_family = AF_UNIX;
42 ret = strcpy_s(serverAddr.sun_path, sizeof(serverAddr.sun_path), server);
43 LE_CHECK(ret == 0, close(listenfd);
44 return ret, "Failed to copy. error: %d", errno);
45 uint32_t size = offsetof(struct sockaddr_un, sun_path) + strlen(server);
46 ret = bind(listenfd, (struct sockaddr *)&serverAddr, size);
47 LE_CHECK(ret >= 0, close(listenfd);
48 return ret, "Failed to bind socket. error: %d", errno);
49
50 SetNoBlock(listenfd);
51 ret = listen(listenfd, maxClient);
52 LE_CHECK(ret >= 0, close(listenfd);
53 return ret, "Failed to listen socket error: %d", errno);
54 ret = chmod(server, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
55 LE_CHECK(ret == 0, return -1, "Failed to chmod %s, err %d. ", server, errno);
56 LE_LOGV("CreatePipeSocket listen fd: %d server:%s ", listenfd, serverAddr.sun_path);
57 return listenfd;
58 }
59
CreatePipeSocket_(const char * server)60 static int CreatePipeSocket_(const char *server)
61 {
62 int fd = socket(PF_UNIX, SOCK_STREAM, 0);
63 LE_CHECK(fd > 0, return fd, "Failed to create socket");
64 SetNoBlock(fd);
65
66 int on = 1;
67 int ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
68 LE_CHECK(ret == 0, return ret, "Failed to set socket option");
69
70 struct sockaddr_un serverAddr;
71 ret = memset_s(&serverAddr, sizeof(serverAddr), 0, sizeof(serverAddr));
72 LE_CHECK(ret == 0, close(fd);
73 return ret, "Failed to memset_s serverAddr");
74 serverAddr.sun_family = AF_UNIX;
75 ret = strcpy_s(serverAddr.sun_path, sizeof(serverAddr.sun_path), server);
76 LE_CHECK(ret == 0, close(fd);
77 return ret, "Failed to strcpy_s sun_path");
78 uint32_t size = offsetof(struct sockaddr_un, sun_path) + strlen(serverAddr.sun_path);
79 ret = connect(fd, (struct sockaddr *)&serverAddr, size);
80 LE_CHECK(ret >= 0, close(fd);
81 return ret, "Failed to connect socket");
82 LE_LOGV("CreatePipeSocket connect fd: %d server: %s ", fd, serverAddr.sun_path);
83 return fd;
84 }
85
GetSockaddrFromServer_(const char * server,struct sockaddr_in * addr)86 static LE_STATUS GetSockaddrFromServer_(const char *server, struct sockaddr_in *addr)
87 {
88 int ret = memset_s(addr, sizeof(struct sockaddr_in), 0, sizeof(struct sockaddr_in));
89 LE_CHECK(ret == 0, return ret, "Failed to memory set. error: %s", strerror(errno));
90 addr->sin_family = AF_INET;
91 const char *portStr = strstr(server, ":");
92 LE_CHECK(portStr != NULL, return LE_FAILURE, "Failed to get addr %s", server);
93 uint16_t port = atoi(portStr + 1);
94 addr->sin_port = htons(port);
95 ret = inet_pton(AF_INET, server, &addr->sin_addr);
96 LE_CHECK(ret >= 0, return LE_FAILURE, "Failed to inet_pton addr %s", server);
97 LE_LOGV("CreateTcpSocket server: %s port: %d", server, port);
98 return LE_SUCCESS;
99 }
100
CreateTcpServerSocket_(const char * server,int maxClient)101 static int CreateTcpServerSocket_(const char *server, int maxClient)
102 {
103 int listenfd = socket(AF_INET, SOCK_STREAM, 0);
104 LE_CHECK(listenfd > 0, return listenfd, "Failed to create socket");
105
106 struct sockaddr_in serverAddr;
107 GetSockaddrFromServer_(server, &serverAddr);
108 int ret = bind(listenfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
109 LE_CHECK(ret >= 0, close(listenfd);
110 return ret, "Failed to bind socket");
111 SetNoBlock(listenfd);
112
113 ret = listen(listenfd, maxClient);
114 LE_CHECK(ret >= 0, close(listenfd);
115 return ret, "Failed to listen socket");
116 return listenfd;
117 }
118
CreateTcpSocket_(const char * server)119 static int CreateTcpSocket_(const char *server)
120 {
121 int fd = socket(AF_INET, SOCK_STREAM, 0);
122 LE_CHECK(fd > 0, return fd, "Failed to create socket");
123 SetNoBlock(fd);
124
125 int on = 1;
126 int ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
127 LE_CHECK(ret == 0, return ret, "Failed to set socket option");
128
129 struct sockaddr_in serverAddr;
130 GetSockaddrFromServer_(server, &serverAddr);
131 ret = connect(fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
132 LE_CHECK(ret >= 0, close(fd);
133 return ret, "Failed to connect socket errno:%d", errno);
134 return fd;
135 }
136
AcceptPipeSocket_(int serverFd)137 static int AcceptPipeSocket_(int serverFd)
138 {
139 struct sockaddr_un clientAddr;
140 socklen_t addrlen = sizeof(clientAddr);
141 bzero(&clientAddr, addrlen);
142 int fd = accept(serverFd, (struct sockaddr *)&clientAddr, &addrlen);
143 LE_CHECK(fd >= 0, return fd, "Failed to accept socket");
144 LE_LOGV("AcceptPipeSocket client fd %d %s ", fd, clientAddr.sun_path);
145 return fd;
146 }
147
AcceptTcpSocket_(int serverFd)148 static int AcceptTcpSocket_(int serverFd)
149 {
150 struct sockaddr_in clientAddr;
151 socklen_t addrlen = sizeof(clientAddr);
152 bzero(&clientAddr, addrlen);
153 int fd = accept(serverFd, (struct sockaddr *)&clientAddr, &addrlen);
154 LE_CHECK(fd >= 0, return fd, "Failed to accept socket");
155 LE_LOGV("AcceptTcpSocket_ client: %s ", inet_ntoa(clientAddr.sin_addr));
156 return fd;
157 }
158 INIT_LOCAL_API
CreateSocket(int flags,const char * server)159 int CreateSocket(int flags, const char *server)
160 {
161 int fd = -1;
162 int type = flags & 0x0000ff00;
163 LE_LOGV("CreateSocket flags %x type %x server %s", flags, type, server);
164 if (type == TASK_TCP) {
165 if (LE_TEST_FLAGS(flags, TASK_SERVER)) {
166 fd = CreateTcpServerSocket_(server, LOOP_MAX_CLIENT);
167 } else if (LE_TEST_FLAGS(flags, TASK_CONNECT)) {
168 fd = CreateTcpSocket_(server);
169 }
170 } else if (type == TASK_PIPE) {
171 if (LE_TEST_FLAGS(flags, TASK_SERVER)) {
172 fd = CreatePipeServerSocket_(server, LOOP_MAX_CLIENT);
173 } else if (LE_TEST_FLAGS(flags, TASK_CONNECT)) {
174 fd = CreatePipeSocket_(server);
175 }
176 }
177 if (fd <= 0) {
178 LE_LOGE("Invalid flags 0x%08x for server %s", flags, server);
179 return -1;
180 }
181 return fd;
182 }
183 INIT_LOCAL_API
AcceptSocket(int fd,int flags)184 int AcceptSocket(int fd, int flags)
185 {
186 int clientFd = -1;
187 int type = flags & 0x0000ff00;
188 if (type == TASK_TCP) {
189 clientFd = AcceptTcpSocket_(fd);
190 } else if (type == TASK_PIPE) {
191 clientFd = AcceptPipeSocket_(fd);
192 } else {
193 LE_LOGE("AcceptSocket invalid flags %#8x ", flags);
194 return -1;
195 }
196 SetNoBlock(clientFd);
197 return clientFd;
198 }
199