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 ret;
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 ret;
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     return fd;
87 }
88 
CreateServerSocketByIpv6(const char * ip,int port)89 static int CreateServerSocketByIpv6(const char *ip, int port)
90 {
91     SoftBusSockAddrIn6 addr;
92     int32_t ret = Ipv6AddrToAddrIn(&addr, ip, port);
93     if (ret != SOFTBUS_OK) {
94         TRANS_LOGE(TRANS_FILE, "init addr error, ret=%{public}d", ret);
95         return ret;
96     }
97 
98     int fd;
99     ret = SoftBusSocketCreate(SOFTBUS_AF_INET6, SOFTBUS_SOCK_STREAM | SOFTBUS_SOCK_NONBLOCK |
100         SOFTBUS_SOCK_CLOEXEC, 0, &fd);
101     if (ret != SOFTBUS_OK) {
102         TRANS_LOGE(TRANS_FILE, "create socket error, ret=%{public}d.", ret);
103         return ret;
104     }
105 
106     ret = SetReuseAddr(fd, 1);
107     if (ret != SOFTBUS_OK) {
108         TRANS_LOGE(TRANS_FILE, "reuse addr error, ret=%{public}d.", ret);
109         ConnShutdownSocket(fd);
110         return ret;
111     }
112 
113     ret = SetReusePort(fd, 1);
114     if (ret != SOFTBUS_OK) {
115         TRANS_LOGE(TRANS_FILE, "reuse port error, ret=%{public}d.", ret);
116         ConnShutdownSocket(fd);
117         return ret;
118     }
119 
120     ret = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketBind(fd, (SoftBusSockAddr *)&addr, sizeof(addr)));
121     TRANS_LOGI(TRANS_FILE, "bind addr port=%{public}#x", addr.sin6Port);
122     if (ret != SOFTBUS_ADAPTER_OK) {
123         TRANS_LOGE(TRANS_FILE, "bind error, ret=%{public}d.", ret);
124         ConnShutdownSocket(fd);
125         return ret;
126     }
127     return fd;
128 }
129 
CreateServerSocket(const char * ip,int32_t * fd,int32_t * port)130 static int32_t CreateServerSocket(const char *ip, int32_t *fd, int32_t *port)
131 {
132     if (ip == NULL || fd == NULL || port == NULL) {
133         TRANS_LOGE(TRANS_FILE, "invalid param.");
134         return SOFTBUS_INVALID_PARAM;
135     }
136 
137     int32_t socketFd = -1;
138     if (GetDomainByAddr(ip) == SOFTBUS_AF_INET6) {
139         socketFd = CreateServerSocketByIpv6(ip, 0);
140     } else {
141         socketFd = CreateServerSocketByIpv4(ip, 0);
142     }
143 
144     if (socketFd < 0) {
145         TRANS_LOGE(TRANS_FILE, "failed to start tcp server for getting port");
146         return SOFTBUS_FILE_ERR;
147     }
148     const SocketInterface *interface = GetSocketInterface(LNN_PROTOCOL_IP);
149     if (interface == NULL) {
150         TRANS_LOGE(TRANS_FILE, "no ip supportted");
151         ConnShutdownSocket(socketFd);
152         return SOFTBUS_NOT_FIND;
153     }
154     int32_t socketPort = interface->GetSockPort(socketFd);
155     if (socketPort < 0) {
156         TRANS_LOGE(TRANS_FILE, "failed to get port from tcp socket");
157         ConnShutdownSocket(socketFd);
158         return SOFTBUS_INVALID_PORT;
159     }
160     *fd = socketFd;
161     *port = socketPort;
162     TRANS_LOGI(TRANS_FILE, "create socket success, fd=%{public}d, port=%{public}d", socketFd, socketPort);
163     return SOFTBUS_OK;
164 }
165 
InitSockAddrInByIpPort(const char * ip,int32_t port,struct sockaddr_in * addr)166 static int32_t InitSockAddrInByIpPort(const char *ip, int32_t port, struct sockaddr_in *addr)
167 {
168     if (ip == NULL || port < 0 || addr == NULL) {
169         TRANS_LOGE(TRANS_FILE, "invalid param.");
170         return SOFTBUS_INVALID_PARAM;
171     }
172     addr->sin_family = AF_INET;
173     addr->sin_port = port;
174     addr->sin_addr.s_addr = SoftBusNtoHl(SoftBusInetAddr(ip));
175     return SOFTBUS_OK;
176 }
177 
InitSockAddrIn6ByIpPort(const char * ip,int32_t port,struct sockaddr_in6 * addr)178 static int32_t InitSockAddrIn6ByIpPort(const char *ip, int32_t port, struct sockaddr_in6 *addr)
179 {
180     if (ip == NULL || port < 0 || addr == NULL) {
181         TRANS_LOGE(TRANS_FILE, "invalid param.");
182         return SOFTBUS_INVALID_PARAM;
183     }
184 
185     SoftBusSockAddrIn6 addrIn6;
186     int32_t ret = Ipv6AddrToAddrIn(&addrIn6, ip, port);
187     addrIn6.sin6Port = port;
188     if (ret != SOFTBUS_OK) {
189         TRANS_LOGE(TRANS_FILE, "init addr error, ret=%{public}d", ret);
190         return ret;
191     }
192     addr->sin6_family = AF_INET6;
193     addr->sin6_port = addrIn6.sin6Port;
194     addr->sin6_scope_id = addrIn6.sin6ScopeId;
195     if (memcpy_s(&addr->sin6_addr, sizeof(addr->sin6_addr), &addrIn6.sin6Addr, sizeof(addrIn6.sin6Addr)) != EOK) {
196         TRANS_LOGE(TRANS_FILE, "failed to get ip, ret=%{public}d", ret);
197         return SOFTBUS_MEM_ERR;
198     }
199     return SOFTBUS_OK;
200 }
201 
StartNStackXDFileServer(const char * myIp,const uint8_t * key,uint32_t keyLen,DFileMsgReceiver msgReceiver,int32_t * filePort)202 int32_t StartNStackXDFileServer(
203     const char *myIp, const uint8_t *key, uint32_t keyLen, DFileMsgReceiver msgReceiver, int32_t *filePort)
204 {
205     if (myIp == NULL || filePort == NULL) {
206         TRANS_LOGE(TRANS_FILE, "invalid param.");
207         return SOFTBUS_INVALID_PARAM;
208     }
209     int32_t port = -1;
210     int32_t fd = -1;
211     int32_t ret = CreateServerSocket(myIp, &fd, &port);
212     if (ret != SOFTBUS_OK) {
213         TRANS_LOGE(TRANS_FILE, "failed to start tcp server for getting port");
214         return ret;
215     }
216     int sessionId = -1;
217     if (GetDomainByAddr(myIp) == SOFTBUS_AF_INET6) {
218         struct sockaddr_in6 localAddr = { 0 };
219         ret = InitSockAddrIn6ByIpPort(myIp, port, &localAddr);
220         if (ret != SOFTBUS_OK) {
221             ConnShutdownSocket(fd);
222             TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in6, ret=%{public}d", ret);
223             return ret;
224         }
225         socklen_t addrLen = sizeof(struct sockaddr_in6);
226         sessionId = NSTACKX_DFileServer((struct sockaddr_in *)&localAddr, addrLen, key, keyLen, msgReceiver);
227     } else {
228         struct sockaddr_in localAddr = { 0 };
229         ret = InitSockAddrInByIpPort(myIp, port, &localAddr);
230         if (ret != SOFTBUS_OK) {
231             ConnShutdownSocket(fd);
232             TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in, ret=%{public}d", ret);
233             return ret;
234         }
235         socklen_t addrLen = sizeof(struct sockaddr_in);
236         sessionId = NSTACKX_DFileServer(&localAddr, addrLen, key, keyLen, msgReceiver);
237     }
238     *filePort = port;
239     ConnShutdownSocket(fd);
240     if (sessionId < 0) {
241         TRANS_LOGE(TRANS_FILE, "failed to start dfile server.");
242         return SOFTBUS_TRANS_INVALID_SESSION_ID;
243     }
244 
245     char animizedIp[IP_LEN] = { 0 };
246     ConvertAnonymizeIpAddress(animizedIp, IP_LEN, myIp, IP_LEN);
247     TRANS_LOGI(TRANS_FILE, "start dfile server, ip=%{public}s, port=%{public}d", animizedIp, port);
248     return sessionId;
249 }
250 
StartNStackXDFileClient(const char * peerIp,int32_t peerPort,const uint8_t * key,uint32_t keyLen,DFileMsgReceiver msgReceiver)251 int32_t StartNStackXDFileClient(
252     const char *peerIp, int32_t peerPort, const uint8_t *key, uint32_t keyLen, DFileMsgReceiver msgReceiver)
253 {
254     if (peerIp == NULL) {
255         TRANS_LOGW(TRANS_FILE, "invalid param.");
256         return SOFTBUS_INVALID_PARAM;
257     }
258 
259     int32_t sessionId = -1;
260     if (GetDomainByAddr(peerIp) == SOFTBUS_AF_INET6) {
261         struct sockaddr_in6 localAddr = { 0 };
262         int32_t ret = InitSockAddrIn6ByIpPort(peerIp, peerPort, &localAddr);
263         if (ret != SOFTBUS_OK) {
264             TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in6, ret=%{public}d", ret);
265             return ret;
266         }
267         socklen_t addrLen = sizeof(struct sockaddr_in6);
268         sessionId = NSTACKX_DFileClient((struct sockaddr_in *)&localAddr, addrLen, key, keyLen, msgReceiver);
269     } else {
270         struct sockaddr_in localAddr = { 0 };
271         int32_t ret = InitSockAddrInByIpPort(peerIp, peerPort, &localAddr);
272         if (ret != SOFTBUS_OK) {
273             TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in, ret=%{public}d", ret);
274             return ret;
275         }
276         socklen_t addrLen = sizeof(struct sockaddr_in);
277         sessionId = NSTACKX_DFileClient(&localAddr, addrLen, key, keyLen, msgReceiver);
278     }
279 
280     if (sessionId < 0) {
281         TRANS_LOGE(TRANS_FILE, "failed to start dfile client");
282         return SOFTBUS_TRANS_INVALID_SESSION_ID;
283     }
284 
285     char animizedIp[IP_LEN] = { 0 };
286     ConvertAnonymizeIpAddress(animizedIp, IP_LEN, peerIp, IP_LEN);
287     TRANS_LOGI(TRANS_FILE, "start dfile client, peerIp=%{public}s, peerPort=%{public}d", animizedIp, peerPort);
288     return sessionId;
289 }
290