• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,int public)31 static int CreatePipeServerSocket_(const char *server, int maxClient, int public)
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     mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
55     if (public) {
56         mode |= S_IROTH | S_IWOTH;
57     }
58     ret = chmod(server, mode);
59     LE_CHECK(ret == 0, return -1, "Failed to chmod %s, err %d. ", server, errno);
60     LE_LOGV("CreatePipeSocket listen fd: %d server:%s ", listenfd, serverAddr.sun_path);
61     return listenfd;
62 }
63 
CreatePipeSocket_(const char * server)64 static int CreatePipeSocket_(const char *server)
65 {
66     int fd = socket(PF_UNIX, SOCK_STREAM, 0);
67     LE_CHECK(fd > 0, return fd, "Failed to create socket");
68     SetNoBlock(fd);
69 
70     int on = 1;
71     int ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
72     LE_CHECK(ret == 0, return ret, "Failed to set socket option");
73 
74     struct sockaddr_un serverAddr;
75     ret = memset_s(&serverAddr, sizeof(serverAddr), 0, sizeof(serverAddr));
76     LE_CHECK(ret == 0, close(fd);
77         return ret, "Failed to memset_s serverAddr");
78     serverAddr.sun_family = AF_UNIX;
79     ret = strcpy_s(serverAddr.sun_path, sizeof(serverAddr.sun_path), server);
80     LE_CHECK(ret == 0, close(fd);
81         return ret, "Failed to strcpy_s sun_path");
82     uint32_t size = offsetof(struct sockaddr_un, sun_path) + strlen(serverAddr.sun_path);
83     ret = connect(fd, (struct sockaddr *)&serverAddr, size);
84     LE_CHECK(ret >= 0, close(fd);
85         return ret, "Failed to connect socket");
86     LE_LOGV("CreatePipeSocket connect fd: %d server: %s ", fd, serverAddr.sun_path);
87     return fd;
88 }
89 
GetSockaddrFromServer_(const char * server,struct sockaddr_in * addr)90 static LE_STATUS GetSockaddrFromServer_(const char *server, struct sockaddr_in *addr)
91 {
92     int ret = memset_s(addr, sizeof(struct sockaddr_in), 0, sizeof(struct sockaddr_in));
93     LE_CHECK(ret == 0, return ret, "Failed to memory set. error: %s", strerror(errno));
94     addr->sin_family = AF_INET;
95     const char *portStr = strstr(server, ":");
96     LE_CHECK(portStr != NULL, return LE_FAILURE, "Failed to get addr %s", server);
97     uint16_t port = atoi(portStr + 1);
98     addr->sin_port = htons(port);
99     ret = inet_pton(AF_INET, server, &addr->sin_addr);
100     LE_CHECK(ret >= 0, return LE_FAILURE, "Failed to inet_pton addr %s", server);
101     LE_LOGV("CreateTcpSocket server: %s port: %d", server, port);
102     return LE_SUCCESS;
103 }
104 
CreateTcpServerSocket_(const char * server,int maxClient)105 static int CreateTcpServerSocket_(const char *server, int maxClient)
106 {
107     int listenfd = socket(AF_INET, SOCK_STREAM, 0);
108     LE_CHECK(listenfd > 0, return listenfd, "Failed to create socket");
109 
110     struct sockaddr_in serverAddr;
111     GetSockaddrFromServer_(server, &serverAddr);
112     int ret = bind(listenfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
113     LE_CHECK(ret >= 0, close(listenfd);
114         return ret, "Failed to bind socket");
115     SetNoBlock(listenfd);
116 
117     ret = listen(listenfd, maxClient);
118     LE_CHECK(ret >= 0, close(listenfd);
119         return ret, "Failed to listen socket");
120     return listenfd;
121 }
122 
CreateTcpSocket_(const char * server)123 static int CreateTcpSocket_(const char *server)
124 {
125     int fd = socket(AF_INET, SOCK_STREAM, 0);
126     LE_CHECK(fd > 0, return fd, "Failed to create socket");
127     SetNoBlock(fd);
128 
129     int on = 1;
130     int ret = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
131     LE_CHECK(ret == 0, return ret, "Failed to set socket option");
132 
133     struct sockaddr_in serverAddr;
134     GetSockaddrFromServer_(server, &serverAddr);
135     ret = connect(fd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
136     LE_CHECK(ret >= 0, close(fd);
137         return ret, "Failed to connect socket errno:%d", errno);
138     return fd;
139 }
140 
AcceptPipeSocket_(int serverFd)141 static int AcceptPipeSocket_(int serverFd)
142 {
143     struct sockaddr_un clientAddr;
144     socklen_t addrlen = sizeof(clientAddr);
145     bzero(&clientAddr, addrlen);
146     int fd = accept(serverFd, (struct sockaddr *)&clientAddr, &addrlen);
147     LE_CHECK(fd >= 0, return fd, "Failed to accept socket");
148     LE_LOGV("AcceptPipeSocket client fd %d %s ", fd, clientAddr.sun_path);
149     return fd;
150 }
151 
AcceptTcpSocket_(int serverFd)152 static int AcceptTcpSocket_(int serverFd)
153 {
154     struct sockaddr_in clientAddr;
155     socklen_t addrlen = sizeof(clientAddr);
156     bzero(&clientAddr, addrlen);
157     int fd = accept(serverFd, (struct sockaddr *)&clientAddr, &addrlen);
158     LE_CHECK(fd >= 0, return fd, "Failed to accept socket");
159     LE_LOGV("AcceptTcpSocket_ client: %s ", inet_ntoa(clientAddr.sin_addr));
160     return fd;
161 }
162 INIT_LOCAL_API
CreateSocket(int flags,const char * server)163 int CreateSocket(int flags, const char *server)
164 {
165     int fd = -1;
166     int type = flags & 0x0000ff00;
167     LE_LOGV("CreateSocket flags %x type %x server %s", flags, type, server);
168     if (type == TASK_TCP) {
169         if (LE_TEST_FLAGS(flags, TASK_SERVER)) {
170             fd = CreateTcpServerSocket_(server, LOOP_MAX_CLIENT);
171         } else if (LE_TEST_FLAGS(flags, TASK_CONNECT)) {
172             fd = CreateTcpSocket_(server);
173         }
174     } else if (type == TASK_PIPE) {
175         if (LE_TEST_FLAGS(flags, TASK_SERVER)) {
176             fd = CreatePipeServerSocket_(server, LOOP_MAX_CLIENT,
177                 (int)LE_TEST_FLAGS(flags, TASK_PUBLIC));
178         } else if (LE_TEST_FLAGS(flags, TASK_CONNECT)) {
179             fd = CreatePipeSocket_(server);
180         }
181     }
182     if (fd <= 0) {
183         LE_LOGE("Invalid flags 0x%08x for server %s", flags, server);
184         return -1;
185     }
186     return fd;
187 }
188 INIT_LOCAL_API
AcceptSocket(int fd,int flags)189 int AcceptSocket(int fd, int flags)
190 {
191     int clientFd = -1;
192     int type = flags & 0x0000ff00;
193     if (type == TASK_TCP) {
194         clientFd = AcceptTcpSocket_(fd);
195     } else if (type == TASK_PIPE) {
196         clientFd = AcceptPipeSocket_(fd);
197     } else {
198         LE_LOGE("AcceptSocket invalid flags %#8x ", flags);
199         return -1;
200     }
201     SetNoBlock(clientFd);
202     return clientFd;
203 }
204 
205 INIT_LOCAL_API
listenSocket(int fd,int flags,const char * server)206 int listenSocket(int fd, int flags, const char *server)
207 {
208     int type = flags & 0x0000ff00;
209     LE_LOGV("listenSocket flags %x type %x server %s", flags, type, server);
210     SetNoBlock(fd);
211     if (!LE_TEST_FLAGS(flags, TASK_SERVER)) {
212         return 0;
213     }
214     if (type == TASK_TCP) {
215         int ret = listen(fd, LOOP_MAX_CLIENT);
216         LE_CHECK(ret >= 0, close(fd);
217             return ret, "Failed to listen socket");
218     } else if (type == TASK_PIPE) {
219         int ret = listen(fd, LOOP_MAX_CLIENT);
220         LE_CHECK(ret >= 0, close(fd);
221             return ret, "Failed to listen socket error: %d", errno);
222         ret = chmod(server, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
223         LE_CHECK(ret == 0, return -1, "Failed to chmod %s, err %d. ", server, errno);
224     }
225     return 0;
226 }
227