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 "file_adapter.h"
17 
18 #include <securec.h>
19 #include <unistd.h>
20 
21 #include "softbus_adapter_errcode.h"
22 #include "softbus_adapter_socket.h"
23 #include "softbus_conn_common.h"
24 #include "softbus_errcode.h"
25 #include "softbus_socket.h"
26 #include "trans_log.h"
27 
SetReuseAddr(int fd, int on)28 static int SetReuseAddr(int fd, int on)
29 {
30     int rc = SoftBusSocketSetOpt(fd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_REUSEADDR, &on, sizeof(on));
31     if (rc != SOFTBUS_OK) {
32         TRANS_LOGE(TRANS_FILE, "set SO_REUSEADDR error. fd=%{public}d", fd);
33         return SOFTBUS_INVALID_FD;
34     }
35     return SOFTBUS_OK;
36 }
37 
SetReusePort(int fd, int on)38 static int SetReusePort(int fd, int on)
39 {
40     int rc = SoftBusSocketSetOpt(fd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_REUSEPORT, &on, sizeof(on));
41     if (rc != SOFTBUS_OK) {
42         TRANS_LOGE(TRANS_FILE, "set SO_REUSEPORT error. fd=%{public}d", fd);
43         return SOFTBUS_INVALID_FD;
44     }
45     return SOFTBUS_OK;
46 }
47 
CreateServerSocketByIpv4(const char *ip, int port)48 static int CreateServerSocketByIpv4(const char *ip, int port)
49 {
50     SoftBusSockAddrIn addr;
51     int32_t ret = Ipv4AddrToAddrIn(&addr, ip, port);
52     if (ret != SOFTBUS_OK) {
53         TRANS_LOGE(TRANS_FILE, "init addr error, ret=%{public}d", ret);
54         return ret;
55     }
56 
57     int fd;
58 
59     ret = SoftBusSocketCreate(SOFTBUS_AF_INET, SOFTBUS_SOCK_STREAM | SOFTBUS_SOCK_NONBLOCK |
60         SOFTBUS_SOCK_CLOEXEC, 0, &fd);
61     if (ret != SOFTBUS_OK) {
62         TRANS_LOGE(TRANS_FILE, "create socket error, ret=%{public}d.", ret);
63         return ret;
64     }
65 
66     ret = SetReuseAddr(fd, 1);
67     if (ret != SOFTBUS_OK) {
68         TRANS_LOGE(TRANS_FILE, "reuse addr error, ret=%{public}d.", ret);
69         ConnShutdownSocket(fd);
70         return SOFTBUS_SOCKET_BIND_ERR;
71     }
72 
73     ret = SetReusePort(fd, 1);
74     if (ret != SOFTBUS_OK) {
75         TRANS_LOGE(TRANS_FILE, "reuse port error, ret=%{public}d.", ret);
76         ConnShutdownSocket(fd);
77         return SOFTBUS_SOCKET_BIND_ERR;
78     }
79 
80     ret = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketBind(fd, (SoftBusSockAddr *)&addr, sizeof(addr)));
81     if (ret != SOFTBUS_ADAPTER_OK) {
82         TRANS_LOGE(TRANS_FILE, "bind error, ret=%{public}d.", ret);
83         ConnShutdownSocket(fd);
84         return ret;
85     }
86 
87     return fd;
88 }
89 
CreateServerSocketByIpv6(const char *ip, int port)90 static int CreateServerSocketByIpv6(const char *ip, int port)
91 {
92     SoftBusSockAddrIn6 addr;
93     int32_t ret = Ipv6AddrToAddrIn(&addr, ip, port);
94     if (ret != SOFTBUS_OK) {
95         TRANS_LOGE(TRANS_FILE, "init addr error, ret=%{public}d", ret);
96         return ret;
97     }
98 
99     int fd;
100     ret = SoftBusSocketCreate(SOFTBUS_AF_INET6, SOFTBUS_SOCK_STREAM | SOFTBUS_SOCK_NONBLOCK |
101         SOFTBUS_SOCK_CLOEXEC, 0, &fd);
102     if (ret != SOFTBUS_OK) {
103         TRANS_LOGE(TRANS_FILE, "create socket error, ret=%{public}d.", ret);
104         return ret;
105     }
106 
107     ret = SetReuseAddr(fd, 1);
108     if (ret != SOFTBUS_OK) {
109         TRANS_LOGE(TRANS_FILE, "reuse addr error, ret=%{public}d.", ret);
110         ConnShutdownSocket(fd);
111         return ret;
112     }
113 
114     ret = SetReusePort(fd, 1);
115     if (ret != SOFTBUS_OK) {
116         TRANS_LOGE(TRANS_FILE, "reuse port error, ret=%{public}d.", ret);
117         ConnShutdownSocket(fd);
118         return ret;
119     }
120 
121     ret = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketBind(fd, (SoftBusSockAddr *)&addr, sizeof(addr)));
122     TRANS_LOGI(TRANS_FILE, "bind addr port=%{public}#x", addr.sin6Port);
123     if (ret != SOFTBUS_ADAPTER_OK) {
124         TRANS_LOGE(TRANS_FILE, "bind error, ret=%{public}d.", ret);
125         ConnShutdownSocket(fd);
126         return ret;
127     }
128     return fd;
129 }
130 
CreateServerSocket(const char *ip, int32_t *fd, int32_t *port)131 static int32_t CreateServerSocket(const char *ip, int32_t *fd, int32_t *port)
132 {
133     if (ip == NULL || fd == NULL || port == NULL) {
134         TRANS_LOGE(TRANS_FILE, "invalid param.");
135         return SOFTBUS_INVALID_PARAM;
136     }
137 
138     int32_t socketFd = -1;
139     if (GetDomainByAddr(ip) == SOFTBUS_AF_INET6) {
140         socketFd = CreateServerSocketByIpv6(ip, 0);
141     } else {
142         socketFd = CreateServerSocketByIpv4(ip, 0);
143     }
144 
145     if (socketFd < 0) {
146         TRANS_LOGE(TRANS_FILE, "failed to start tcp server for getting port");
147         return SOFTBUS_FILE_ERR;
148     }
149     const SocketInterface *interface = GetSocketInterface(LNN_PROTOCOL_IP);
150     if (interface == NULL) {
151         TRANS_LOGE(TRANS_FILE, "no ip supportted");
152         ConnShutdownSocket(socketFd);
153         return SOFTBUS_NOT_FIND;
154     }
155     int32_t socketPort = interface->GetSockPort(socketFd);
156     if (socketPort < 0) {
157         TRANS_LOGE(TRANS_FILE, "failed to get port from tcp socket");
158         ConnShutdownSocket(socketFd);
159         return SOFTBUS_INVALID_PORT;
160     }
161     *fd = socketFd;
162     *port = socketPort;
163     TRANS_LOGI(TRANS_FILE, "create socket success, fd=%{public}d, port=%{public}d", socketFd, socketPort);
164     return SOFTBUS_OK;
165 }
166 
InitSockAddrInByIpPort(const char *ip, int32_t port, struct sockaddr_in *addr)167 static int32_t InitSockAddrInByIpPort(const char *ip, int32_t port, struct sockaddr_in *addr)
168 {
169     if (ip == NULL || port < 0 || addr == NULL) {
170         TRANS_LOGE(TRANS_FILE, "invalid param.");
171         return SOFTBUS_INVALID_PARAM;
172     }
173     addr->sin_family = AF_INET;
174     addr->sin_port = port;
175     addr->sin_addr.s_addr = SoftBusNtoHl(SoftBusInetAddr(ip));
176     return SOFTBUS_OK;
177 }
178 
InitSockAddrIn6ByIpPort(const char *ip, int32_t port, struct sockaddr_in6 *addr)179 static int32_t InitSockAddrIn6ByIpPort(const char *ip, int32_t port, struct sockaddr_in6 *addr)
180 {
181     if (ip == NULL || port < 0 || addr == NULL) {
182         TRANS_LOGE(TRANS_FILE, "invalid param.");
183         return SOFTBUS_INVALID_PARAM;
184     }
185 
186     SoftBusSockAddrIn6 addrIn6;
187     int32_t ret = Ipv6AddrToAddrIn(&addrIn6, ip, port);
188     addrIn6.sin6Port = port;
189     if (ret != SOFTBUS_OK) {
190         TRANS_LOGE(TRANS_FILE, "init addr error, ret=%{public}d", ret);
191         return ret;
192     }
193     addr->sin6_family = AF_INET6;
194     addr->sin6_port = addrIn6.sin6Port;
195     addr->sin6_scope_id = addrIn6.sin6ScopeId;
196     if (memcpy_s(&addr->sin6_addr, sizeof(addr->sin6_addr), &addrIn6.sin6Addr, sizeof(addrIn6.sin6Addr)) != EOK) {
197         TRANS_LOGE(TRANS_FILE, "failed to get ip, ret=%{public}d", ret);
198         return SOFTBUS_MEM_ERR;
199     }
200     return SOFTBUS_OK;
201 }
202 
StartNStackXDFileServer( const char *myIp, const uint8_t *key, uint32_t keyLen, DFileMsgReceiver msgReceiver, int32_t *filePort)203 int32_t StartNStackXDFileServer(
204     const char *myIp, const uint8_t *key, uint32_t keyLen, DFileMsgReceiver msgReceiver, int32_t *filePort)
205 {
206     if (myIp == NULL || filePort == NULL) {
207         TRANS_LOGE(TRANS_FILE, "invalid param.");
208         return SOFTBUS_INVALID_PARAM;
209     }
210     int32_t port = -1;
211     int32_t fd = -1;
212     int32_t ret = CreateServerSocket(myIp, &fd, &port);
213     if (ret != SOFTBUS_OK) {
214         TRANS_LOGE(TRANS_FILE, "failed to start tcp server for getting port");
215         return ret;
216     }
217     int sessionId = -1;
218     if (GetDomainByAddr(myIp) == SOFTBUS_AF_INET6) {
219         struct sockaddr_in6 localAddr = { 0 };
220         ret = InitSockAddrIn6ByIpPort(myIp, port, &localAddr);
221         if (ret != SOFTBUS_OK) {
222             ConnShutdownSocket(fd);
223             TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in6, ret=%{public}d", ret);
224             return ret;
225         }
226         socklen_t addrLen = sizeof(struct sockaddr_in6);
227         sessionId = NSTACKX_DFileServer((struct sockaddr_in *)&localAddr, addrLen, key, keyLen, msgReceiver);
228     } else {
229         struct sockaddr_in localAddr = { 0 };
230         ret = InitSockAddrInByIpPort(myIp, port, &localAddr);
231         if (ret != SOFTBUS_OK) {
232             ConnShutdownSocket(fd);
233             TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in, ret=%{public}d", ret);
234             return ret;
235         }
236         socklen_t addrLen = sizeof(struct sockaddr_in);
237         sessionId = NSTACKX_DFileServer(&localAddr, addrLen, key, keyLen, msgReceiver);
238     }
239     *filePort = port;
240     ConnShutdownSocket(fd);
241     if (sessionId < 0) {
242         TRANS_LOGE(TRANS_FILE, "failed to start dfile server.");
243         return SOFTBUS_TRANS_INVALID_SESSION_ID;
244     }
245 
246     char animizedIp[IP_LEN] = { 0 };
247     ConvertAnonymizeIpAddress(animizedIp, IP_LEN, myIp, IP_LEN);
248     TRANS_LOGI(TRANS_FILE, "start dfile server, ip=%{public}s, port=%{public}d", animizedIp, port);
249     return sessionId;
250 }
251 
StartNStackXDFileClient( const char *peerIp, int32_t peerPort, const uint8_t *key, uint32_t keyLen, DFileMsgReceiver msgReceiver)252 int32_t StartNStackXDFileClient(
253     const char *peerIp, int32_t peerPort, const uint8_t *key, uint32_t keyLen, DFileMsgReceiver msgReceiver)
254 {
255     if (peerIp == NULL) {
256         TRANS_LOGW(TRANS_FILE, "invalid param.");
257         return SOFTBUS_INVALID_PARAM;
258     }
259 
260     int32_t sessionId = -1;
261     if (GetDomainByAddr(peerIp) == SOFTBUS_AF_INET6) {
262         struct sockaddr_in6 localAddr = { 0 };
263         int32_t ret = InitSockAddrIn6ByIpPort(peerIp, peerPort, &localAddr);
264         if (ret != SOFTBUS_OK) {
265             TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in6, ret=%{public}d", ret);
266             return ret;
267         }
268         socklen_t addrLen = sizeof(struct sockaddr_in6);
269         sessionId = NSTACKX_DFileClient((struct sockaddr_in *)&localAddr, addrLen, key, keyLen, msgReceiver);
270     } else {
271         struct sockaddr_in localAddr = { 0 };
272         int32_t ret = InitSockAddrInByIpPort(peerIp, peerPort, &localAddr);
273         if (ret != SOFTBUS_OK) {
274             TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in, ret=%{public}d", ret);
275             return ret;
276         }
277         socklen_t addrLen = sizeof(struct sockaddr_in);
278         sessionId = NSTACKX_DFileClient(&localAddr, addrLen, key, keyLen, msgReceiver);
279     }
280 
281     if (sessionId < 0) {
282         TRANS_LOGE(TRANS_FILE, "failed to start dfile client");
283         return SOFTBUS_TRANS_INVALID_SESSION_ID;
284     }
285 
286     char animizedIp[IP_LEN] = { 0 };
287     ConvertAnonymizeIpAddress(animizedIp, IP_LEN, peerIp, IP_LEN);
288     TRANS_LOGI(TRANS_FILE, "start dfile client, peerIp=%{public}s, peerPort=%{public}d", animizedIp, peerPort);
289     return sessionId;
290 }
291