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 "softbus_socket.h"
17 
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <ifaddrs.h>
21 #include <securec.h>
22 
23 #include "conn_log.h"
24 #include "softbus_adapter_socket.h"
25 #include "softbus_conn_common.h"
26 #include "softbus_def.h"
27 #include "softbus_errcode.h"
28 #include "softbus_tcp_socket.h"
29 
30 #define HML_IPV4_ADDR_PREFIX "172.30."
31 
32 #define MAX_SOCKET_TYPE 5
33 #define SEND_BUF_SIZE   0x200000 // 2M
34 #define RECV_BUF_SIZE   0x100000 // 1M
35 #define USER_TIMEOUT_US 5000000   // 5000000us
36 
37 static const SocketInterface *g_socketInterfaces[MAX_SOCKET_TYPE] = { 0 };
38 static SoftBusMutex g_socketsMutex;
39 
RegistSocketProtocol(const SocketInterface * interface)40 int32_t RegistSocketProtocol(const SocketInterface *interface)
41 {
42     if (interface == NULL || interface->GetSockPort == NULL || interface->OpenClientSocket == NULL ||
43         interface->OpenServerSocket == NULL || interface->AcceptClient == NULL) {
44         CONN_LOGW(CONN_COMMON, "Bad socket interface!");
45         return SOFTBUS_INVALID_PARAM;
46     }
47     int ret = SoftBusMutexLock(&g_socketsMutex);
48     if (ret != SOFTBUS_OK) {
49         CONN_LOGE(CONN_COMMON, "get lock failed! ret=%{public}" PRId32, ret);
50         return ret;
51     }
52 
53     ret = SOFTBUS_CONN_SOCKET_INTERNAL_ERR;
54     for (uint8_t i = 0; i < MAX_SOCKET_TYPE; i++) {
55         if (g_socketInterfaces[i] == NULL) {
56             g_socketInterfaces[i] = interface;
57             ret = SOFTBUS_OK;
58             break;
59         }
60     }
61     (void)SoftBusMutexUnlock(&g_socketsMutex);
62     if (ret != SOFTBUS_OK) {
63         CONN_LOGE(CONN_COMMON, "socket type list is full!");
64     }
65     return ret;
66 }
67 
GetSocketInterface(ProtocolType protocolType)68 const SocketInterface *GetSocketInterface(ProtocolType protocolType)
69 {
70     int ret = SoftBusMutexLock(&g_socketsMutex);
71     if (ret != SOFTBUS_OK) {
72         CONN_LOGE(CONN_COMMON, "get lock failed! ret=%{public}" PRId32, ret);
73         return NULL;
74     }
75     const SocketInterface *result = NULL;
76     for (uint8_t i = 0; i < MAX_SOCKET_TYPE; i++) {
77         if (g_socketInterfaces[i] != NULL && g_socketInterfaces[i]->type == protocolType) {
78             result = g_socketInterfaces[i];
79             break;
80         }
81     }
82     (void)SoftBusMutexUnlock(&g_socketsMutex);
83     return result;
84 }
85 
RegistNewIpSocket(void)86 int32_t __attribute__((weak)) RegistNewIpSocket(void)
87 {
88     CONN_LOGD(CONN_COMMON, "newip not deployed");
89     return SOFTBUS_OK;
90 }
91 
ConnInitSockets(void)92 int32_t ConnInitSockets(void)
93 {
94     int32_t ret = SoftBusMutexInit(&g_socketsMutex, NULL);
95     if (ret != SOFTBUS_OK) {
96         CONN_LOGE(CONN_INIT, "init mutex failed! ret=%{public}" PRId32, ret);
97         return ret;
98     }
99 
100     (void)memset_s(g_socketInterfaces, sizeof(g_socketInterfaces), 0, sizeof(g_socketInterfaces));
101 
102     ret = RegistSocketProtocol(GetTcpProtocol());
103     if (ret != SOFTBUS_OK) {
104         CONN_LOGE(CONN_INIT, "regist tcp failed!! ret=%{public}" PRId32, ret);
105         (void)SoftBusMutexDestroy(&g_socketsMutex);
106         return ret;
107     }
108     CONN_LOGD(CONN_INIT, "tcp registed!");
109 
110     ret = RegistNewIpSocket();
111     if (ret != SOFTBUS_OK) {
112         CONN_LOGE(CONN_INIT, "regist newip failed!! ret=%{public}" PRId32, ret);
113         (void)SoftBusMutexDestroy(&g_socketsMutex);
114         return ret;
115     }
116 
117     return ret;
118 }
119 
ConnDeinitSockets(void)120 void ConnDeinitSockets(void)
121 {
122     (void)memset_s(g_socketInterfaces, sizeof(g_socketInterfaces), 0, sizeof(g_socketInterfaces));
123     (void)SoftBusMutexDestroy(&g_socketsMutex);
124 }
125 
ConnOpenClientSocket(const ConnectOption * option,const char * bindAddr,bool isNonBlock)126 int32_t ConnOpenClientSocket(const ConnectOption *option, const char *bindAddr, bool isNonBlock)
127 {
128     if (option == NULL) {
129         return SOFTBUS_INVALID_PARAM;
130     }
131     const SocketInterface *socketInterface = GetSocketInterface(option->socketOption.protocol);
132     if (socketInterface == NULL) {
133         CONN_LOGE(CONN_COMMON, "protocol not supported! protocol=%{public}d", option->socketOption.protocol);
134         return SOFTBUS_CONN_SOCKET_GET_INTERFACE_ERR;
135     }
136     return socketInterface->OpenClientSocket(option, bindAddr, isNonBlock);
137 }
138 
WaitEvent(int fd,short events,int timeout)139 static int WaitEvent(int fd, short events, int timeout)
140 {
141     if (fd < 0) {
142         CONN_LOGE(CONN_COMMON, "invalid params. fd=%{public}d", fd);
143         return -1;
144     }
145     SoftBusSockTimeOut tv = { 0 };
146     tv.sec = 0;
147     tv.usec = timeout;
148     int rc = 0;
149     switch (events) {
150         case SOFTBUS_SOCKET_OUT: {
151             SoftBusFdSet writeSet;
152             SoftBusSocketFdZero(&writeSet);
153             SoftBusSocketFdSet(fd, &writeSet);
154             rc = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketSelect(fd + 1, NULL, &writeSet, NULL, &tv));
155             if (rc < 0) {
156                 break;
157             }
158             if (!SoftBusSocketFdIsset(fd, &writeSet)) {
159                 CONN_LOGE(CONN_COMMON, "Enter SoftBusSocketFdIsset.");
160                 rc = 0;
161             }
162             break;
163         }
164         case SOFTBUS_SOCKET_IN: {
165             SoftBusFdSet readSet;
166             SoftBusSocketFdZero(&readSet);
167             SoftBusSocketFdSet(fd, &readSet);
168             rc = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketSelect(fd + 1, &readSet, NULL, NULL, &tv));
169             if (rc < 0) {
170                 break;
171             }
172             if (!SoftBusSocketFdIsset(fd, &readSet)) {
173                 rc = 0;
174             }
175             break;
176         }
177         default:
178             break;
179     }
180     return rc;
181 }
ConnToggleNonBlockMode(int32_t fd,bool isNonBlock)182 int32_t ConnToggleNonBlockMode(int32_t fd, bool isNonBlock)
183 {
184     if (fd < 0) {
185         return SOFTBUS_INVALID_PARAM;
186     }
187     int32_t flags = fcntl(fd, F_GETFL, 0);
188     if (flags < 0) {
189         CONN_LOGE(CONN_COMMON, "fcntl get flag failed, fd=%{public}d, errno=%{public}d(%{public}s)",
190             fd, errno, strerror(errno));
191         return SOFTBUS_CONN_SOCKET_FCNTL_ERR;
192     }
193     if (isNonBlock && ((uint32_t)flags & O_NONBLOCK) == 0) {
194         flags = (int32_t)((uint32_t)flags | O_NONBLOCK);
195         CONN_LOGI(CONN_COMMON, "set to nonblock. fd=%{public}d", fd);
196     } else if (!isNonBlock && ((uint32_t)flags & O_NONBLOCK) != 0) {
197         flags = (int32_t)((uint32_t)flags & ~O_NONBLOCK);
198         CONN_LOGI(CONN_COMMON, "set to block. fd=%{public}d", fd);
199     } else {
200         CONN_LOGI(CONN_COMMON, "nonblock state is already ok. fd=%{public}d", fd);
201         return SOFTBUS_OK;
202     }
203     return fcntl(fd, F_SETFL, flags);
204 }
205 
ConnSendSocketData(int32_t fd,const char * buf,size_t len,int32_t timeout)206 ssize_t ConnSendSocketData(int32_t fd, const char *buf, size_t len, int32_t timeout)
207 {
208     if (fd < 0 || buf == NULL || len == 0) {
209         CONN_LOGE(CONN_COMMON, "invalid params. fd=%{public}d", fd);
210         return -1;
211     }
212 
213     if (timeout == 0) {
214         timeout = USER_TIMEOUT_US;
215     }
216 
217     int err = WaitEvent(fd, SOFTBUS_SOCKET_OUT, USER_TIMEOUT_US);
218     if (err <= 0) {
219         CONN_LOGE(CONN_COMMON, "wait event error. err=%{public}d", err);
220         return err;
221     }
222     ssize_t bytes = 0;
223     while (1) {
224         ssize_t rc = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketSend(fd, &buf[bytes], len - bytes, 0));
225         if (rc == SOFTBUS_ADAPTER_SOCKET_EAGAIN) {
226             continue;
227         } else if (rc <= 0) {
228             if (bytes == 0) {
229                 bytes = -1;
230             }
231             CONN_LOGE(CONN_COMMON, "tcp send fail. rc=%{public}zd, errno=%{public}d(%{public}s)",
232                 rc, errno, strerror(errno));
233             break;
234         }
235         bytes += rc;
236         if (bytes == (ssize_t)(len)) {
237             break;
238         }
239 
240         err = WaitEvent(fd, SOFTBUS_SOCKET_OUT, timeout);
241         if (err == 0) {
242             continue;
243         } else if (err < 0) {
244             if (bytes == 0) {
245                 CONN_LOGE(CONN_COMMON, "send data wait event fail. err=%{public}d", err);
246                 bytes = err;
247             }
248             break;
249         }
250     }
251     return bytes;
252 }
253 
OnRecvData(int32_t fd,char * buf,size_t len,int timeout,int flags)254 static ssize_t OnRecvData(int32_t fd, char *buf, size_t len, int timeout, int flags)
255 {
256     if (fd < 0 || buf == NULL || len == 0) {
257         CONN_LOGE(CONN_COMMON, "invalid params. fd=%{public}d, len=%{public}zu", fd, len);
258         return -1;
259     }
260 
261     if (timeout != 0) {
262         int err = WaitEvent(fd, SOFTBUS_SOCKET_IN, timeout);
263         if (err < 0) {
264             CONN_LOGE(CONN_COMMON, "recv data wait event err=%{public}d", err);
265             return err;
266         }
267     }
268 
269     ssize_t rc = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketRecv(fd, buf, len, flags));
270     if (rc == SOFTBUS_ADAPTER_SOCKET_EAGAIN) {
271         CONN_LOGW(CONN_COMMON, "recv data socket EAGAIN");
272         rc = 0;
273     } else if (rc == 0) {
274         CONN_LOGE(CONN_COMMON, "recv data fail, peer close connection, fd=%{public}d", fd);
275         rc = -1;
276     } else if (rc < 0) {
277         CONN_LOGE(CONN_COMMON, "recv data fail fd=%{public}d, errno=%{public}d(%{public}s), rc=%{public}zd",
278             fd, errno, strerror(errno), rc);
279         rc = -1;
280     }
281     return rc;
282 }
283 
ConnRecvSocketData(int32_t fd,char * buf,size_t len,int32_t timeout)284 ssize_t ConnRecvSocketData(int32_t fd, char *buf, size_t len, int32_t timeout)
285 {
286     return OnRecvData(fd, buf, len, timeout, 0);
287 }
288 
ConnCloseSocket(int32_t fd)289 void ConnCloseSocket(int32_t fd)
290 {
291     if (fd >= 0) {
292         CONN_LOGI(CONN_COMMON, "close fd=%{public}d", fd);
293         SoftBusSocketClose(fd);
294     }
295 }
296 
ConnShutdownSocket(int32_t fd)297 void ConnShutdownSocket(int32_t fd)
298 {
299     if (fd >= 0) {
300         CONN_LOGI(CONN_COMMON, "shutdown fd=%{public}d", fd);
301         SoftBusSocketShutDown(fd, SOFTBUS_SHUT_RDWR);
302         SoftBusSocketClose(fd);
303     }
304 }
305 
ConnGetSocketError(int32_t fd)306 int32_t ConnGetSocketError(int32_t fd)
307 {
308     return SoftBusSocketGetError(fd);
309 }
310 
ConnGetLocalSocketPort(int32_t fd)311 int32_t ConnGetLocalSocketPort(int32_t fd)
312 {
313     const SocketInterface *socketInterface = GetSocketInterface(LNN_PROTOCOL_IP);
314     if (socketInterface == NULL) {
315         CONN_LOGW(CONN_COMMON, "LNN_PROTOCOL_IP not supported!");
316         return SOFTBUS_CONN_SOCKET_GET_INTERFACE_ERR;
317     }
318     return socketInterface->GetSockPort(fd);
319 }
320 
ConnGetPeerSocketAddr(int32_t fd,SocketAddr * socketAddr)321 int32_t ConnGetPeerSocketAddr(int32_t fd, SocketAddr *socketAddr)
322 {
323     SoftBusSockAddr addr;
324     if (socketAddr == NULL) {
325         CONN_LOGW(CONN_COMMON, "invalid param");
326         return SOFTBUS_INVALID_PARAM;
327     }
328     int rc = SoftBusSocketGetPeerName(fd, &addr);
329     if (rc != 0) {
330         CONN_LOGE(CONN_COMMON, "GetPeerName fd=%{public}d, rc=%{public}d", fd, rc);
331         return SOFTBUS_TCP_SOCKET_ERR;
332     }
333     if (addr.saFamily == SOFTBUS_AF_INET6) {
334         rc = Ipv6AddrInToAddr((SoftBusSockAddrIn6 *)&addr, socketAddr->addr, sizeof(socketAddr->addr));
335         socketAddr->port = SoftBusNtoHs(((SoftBusSockAddrIn6 *)&addr)->sin6Port);
336         if (rc < 0) {
337             CONN_LOGE(CONN_COMMON, "Ipv6AddrInToAddr fail. fd=%{public}d", fd);
338             return SOFTBUS_SOCKET_ADDR_ERR;
339         }
340         return SOFTBUS_OK;
341     }
342     socketAddr->port = SoftBusNtoHs(((SoftBusSockAddrIn *)&addr)->sinPort);
343     if (SoftBusInetNtoP(SOFTBUS_AF_INET, (void *)&((SoftBusSockAddrIn *)&addr)->sinAddr,
344         socketAddr->addr, sizeof(socketAddr->addr)) == NULL) {
345         CONN_LOGE(CONN_COMMON, "InetNtoP fail. fd=%{public}d", fd);
346         return SOFTBUS_TCPCONNECTION_SOCKET_ERR;
347     }
348     return SOFTBUS_OK;
349 }
350 
ConnPreAssignPortBind(int32_t socketFd,int32_t domain)351 static int32_t ConnPreAssignPortBind(int32_t socketFd, int32_t domain)
352 {
353     int ret = SOFTBUS_TCPCONNECTION_SOCKET_ERR;
354     if (domain == SOFTBUS_AF_INET6) {
355         SoftBusSockAddrIn6 addrIn6 = {0};
356         ret = Ipv6AddrToAddrIn(&addrIn6, "::", 0);
357         if (ret != SOFTBUS_ADAPTER_OK) {
358             CONN_LOGE(CONN_COMMON, "convert address to net order failed");
359             return SOFTBUS_TCPCONNECTION_SOCKET_ERR;
360         }
361         return SoftBusSocketBind(socketFd, (SoftBusSockAddr *)&addrIn6, sizeof(SoftBusSockAddrIn6));
362     }
363     SoftBusSockAddrIn addrIn = {0};
364     ret = Ipv4AddrToAddrIn(&addrIn, "0.0.0.0", 0);
365     if (ret != SOFTBUS_ADAPTER_OK) {
366         CONN_LOGE(CONN_COMMON, "convert address to net order failed");
367         return SOFTBUS_TCPCONNECTION_SOCKET_ERR;
368     }
369     return SoftBusSocketBind(socketFd, (SoftBusSockAddr *)&addrIn, sizeof(SoftBusSockAddrIn));
370 }
371 
ConnPreAssignPort(int32_t domain)372 int32_t ConnPreAssignPort(int32_t domain)
373 {
374     int socketFd = -1;
375     int ret = SoftBusSocketCreate(domain, SOFTBUS_SOCK_STREAM, 0, &socketFd);
376     if (ret < 0) {
377         CONN_LOGE(CONN_COMMON, "create socket failed, ret=%{public}d", ret);
378         return SOFTBUS_TCPCONNECTION_SOCKET_ERR;
379     }
380     int reuse = 1;
381     ret = SoftBusSocketSetOpt(socketFd, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse));
382     if (ret != SOFTBUS_OK) {
383         CONN_LOGE(CONN_COMMON, "set reuse port option failed");
384         SoftBusSocketClose(socketFd);
385         return SOFTBUS_TCPCONNECTION_SOCKET_ERR;
386     }
387     ret = ConnPreAssignPortBind(socketFd, domain);
388     if (ret != SOFTBUS_ADAPTER_OK) {
389         SoftBusSocketClose(socketFd);
390         CONN_LOGE(CONN_COMMON, "bind address failed");
391         return SOFTBUS_TCPCONNECTION_SOCKET_ERR;
392     }
393     return socketFd;
394 }
395 
GetDomainByAddr(const char * addr)396 int32_t GetDomainByAddr(const char *addr)
397 {
398     CONN_CHECK_AND_RETURN_RET_LOGE(addr != NULL,
399         SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param!");
400     if (strchr(addr, ADDR_FEATURE_IPV6) != NULL) {
401         return SOFTBUS_AF_INET6;
402     }
403     return SOFTBUS_AF_INET;
404 }
405 
Ipv6AddrInToAddr(SoftBusSockAddrIn6 * addrIn6,char * addr,int32_t addrLen)406 int32_t Ipv6AddrInToAddr(SoftBusSockAddrIn6 *addrIn6, char *addr, int32_t addrLen)
407 {
408     CONN_CHECK_AND_RETURN_RET_LOGE(addrIn6 != NULL && addr != NULL && addrLen > 0,
409         SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param!");
410     char ip[IP_LEN] = {0};
411     if (SoftBusInetNtoP(SOFTBUS_AF_INET6, &addrIn6->sin6Addr, ip, addrLen) == NULL) {
412         CONN_LOGE(CONN_COMMON, "InetNtoP faild!");
413         return SOFTBUS_SOCKET_ADDR_ERR;
414     }
415     char ifname[IF_NAME_SIZE] = { 0 };
416     int32_t rc = SoftBusIndexToIfName(addrIn6->sin6ScopeId, ifname, IF_NAME_SIZE);
417     if (rc < 0) {
418         if (strcpy_s(addr, IP_LEN, ip) != SOFTBUS_OK) {
419             CONN_LOGE(CONN_COMMON, "strcpy faild!");
420             return SOFTBUS_STRCPY_ERR;
421         }
422         CONN_LOGW(CONN_COMMON, "no ifname or global addr");
423         return SOFTBUS_OK;
424     }
425     rc = sprintf_s(addr, addrLen, "%s%s%s", ip, ADDR_SPLIT_IPV6, ifname);
426     if (rc < 0) {
427         COMM_LOGE(CONN_COMMON, "sprintf_s addr fail");
428         return SOFTBUS_SOCKET_ADDR_ERR;
429     }
430     return SOFTBUS_OK;
431 }
432 
Ipv6AddrToAddrIn(SoftBusSockAddrIn6 * addrIn6,const char * ip,uint16_t port)433 int32_t Ipv6AddrToAddrIn(SoftBusSockAddrIn6 *addrIn6, const char *ip, uint16_t port)
434 {
435     CONN_CHECK_AND_RETURN_RET_LOGE(addrIn6 != NULL && ip != NULL, SOFTBUS_INVALID_PARAM,
436         CONN_COMMON, "invalid param!");
437     (void)memset_s(addrIn6, sizeof(*addrIn6), 0, sizeof(*addrIn6));
438     addrIn6->sin6Family = SOFTBUS_AF_INET6;
439     char *addr = NULL;
440     char *ifName = NULL;
441     char *nextToken = NULL;
442     char tmpIp[IP_LEN] = { 0 };
443     if (strcpy_s(tmpIp, sizeof(tmpIp), ip) != EOK) {
444         CONN_LOGE(CONN_COMMON, "copy local id failed");
445         return SOFTBUS_MEM_ERR;
446     }
447     addr = strtok_s(tmpIp, ADDR_SPLIT_IPV6, &nextToken);
448     if (addr == NULL) {
449         addr = "";
450     }
451     ifName = strtok_s(NULL, ADDR_SPLIT_IPV6, &nextToken);
452     if (ifName != NULL) {
453         addrIn6->sin6ScopeId = SoftBusIfNameToIndex(ifName);
454         if (addrIn6->sin6ScopeId == 0) {
455             CONN_LOGE(CONN_WIFI_DIRECT, "nameToIndex failed, errno=%{public}d(%{public}s)", errno, strerror(errno));
456             return SOFTBUS_SOCKET_ADDR_ERR;
457         }
458     }
459     int32_t rc = SoftBusInetPtoN(SOFTBUS_AF_INET6, addr, &addrIn6->sin6Addr);
460     if (rc != SOFTBUS_OK) {
461         CONN_LOGE(CONN_COMMON, "ipv6 SoftBusInetPtoN rc=%{public}d", rc);
462         return SOFTBUS_SOCKET_ADDR_ERR;
463     }
464     addrIn6->sin6Port = SoftBusHtoNs(port);
465     return SOFTBUS_OK;
466 }
467 
Ipv4AddrToAddrIn(SoftBusSockAddrIn * addrIn,const char * ip,uint16_t port)468 int32_t Ipv4AddrToAddrIn(SoftBusSockAddrIn *addrIn, const char *ip, uint16_t port)
469 {
470     CONN_CHECK_AND_RETURN_RET_LOGE(addrIn != NULL && ip != NULL, SOFTBUS_INVALID_PARAM,
471         CONN_COMMON, "invalid param!");
472     (void)memset_s(addrIn, sizeof(*addrIn), 0, sizeof(*addrIn));
473     addrIn->sinFamily = SOFTBUS_AF_INET;
474     int32_t rc = SoftBusInetPtoN(SOFTBUS_AF_INET, ip, &addrIn->sinAddr);
475     if (rc != SOFTBUS_OK) {
476         CONN_LOGE(CONN_COMMON, "ipv4 SoftBusInetPtoN rc=%{public}d", rc);
477         return SOFTBUS_SOCKET_ADDR_ERR;
478     }
479     addrIn->sinPort = SoftBusHtoNs(port);
480     return SOFTBUS_OK;
481 }
482 
IsHmlIpAddr(const char * ip)483 bool IsHmlIpAddr(const char *ip)
484 {
485     CONN_CHECK_AND_RETURN_RET_LOGE(ip != NULL, false, CONN_COMMON, "invalid param!");
486     if (GetDomainByAddr(ip) == SOFTBUS_AF_INET6) {
487         return true;
488     }
489 
490     return strncmp(ip, HML_IPV4_ADDR_PREFIX, strlen(HML_IPV4_ADDR_PREFIX)) == 0;
491 }
492 
GetIfNameByIp(const char * myIp,int32_t domain,char * ifName,int32_t ifNameMaxLen)493 static int32_t GetIfNameByIp(const char *myIp, int32_t domain, char *ifName, int32_t ifNameMaxLen)
494 {
495     if (myIp == NULL || ifName == NULL || strcmp(myIp, BIND_ADDR_ALL) == 0) {
496         COMM_LOGE(CONN_COMMON, "Invalid param.");
497         return SOFTBUS_INVALID_PARAM;
498     }
499 
500     struct ifaddrs *ifa = NULL;
501     struct ifaddrs *ifList = NULL;
502     struct in_addr inAddr = { 0 };
503     char animizedIp[IP_LEN] = { 0 };
504     ConvertAnonymizeIpAddress(animizedIp, IP_LEN, myIp, IP_LEN);
505 
506     int32_t ret = getifaddrs(&ifList);
507     if (ret != 0) {
508         COMM_LOGE(CONN_COMMON, "ip=%{public}s getifaddrs ifList failed, ret=%{public}d, errno=%{public}d(%{public}s)",
509             animizedIp, ret, errno, strerror(errno));
510         return SOFTBUS_SOCKET_ADDR_ERR;
511     }
512     if (inet_aton(myIp, &inAddr) == 0) {
513         COMM_LOGE(CONN_COMMON, "inet_aton ip=%{public}s failed.", animizedIp);
514         freeifaddrs(ifList);
515         return SOFTBUS_TCP_SOCKET_ERR;
516     }
517     for (ifa = ifList; ifa != NULL; ifa = ifa->ifa_next) {
518         if (ifa->ifa_addr == NULL) {
519             continue;
520         }
521         (void)memset_s(ifName, ifNameMaxLen, 0, ifNameMaxLen);
522         if (memcmp(&inAddr, &(((struct sockaddr_in *)ifa->ifa_addr)->sin_addr), sizeof(struct in_addr)) == 0) {
523             if (memcpy_s(ifName, ifNameMaxLen - 1, ifa->ifa_name, strlen(ifa->ifa_name)) != EOK) {
524                 COMM_LOGE(CONN_COMMON, "fail to memcpy_s ifName by ip=%{public}s", animizedIp);
525                 freeifaddrs(ifList);
526                 return SOFTBUS_MEM_ERR;
527             }
528             freeifaddrs(ifList);
529             return SOFTBUS_OK;
530         }
531     }
532     COMM_LOGW(CONN_COMMON, "not found ifName by ip=%{public}s", animizedIp);
533     freeifaddrs(ifList);
534     return SOFTBUS_CONN_NOT_FOUND_FAILED;
535 }
536 
537 // prevent the scenario of using VPN to produce virtual network cards.
BindToInterface(const char * myIp,int32_t domain,int fd,char * ifName,int32_t ifNameMaxLen)538 void BindToInterface(const char *myIp, int32_t domain, int fd, char *ifName, int32_t ifNameMaxLen)
539 {
540     // The IPv6 socket has already been bound to the network card, there is no need to bind it again.
541     CONN_CHECK_AND_RETURN_LOGW(domain != SOFTBUS_AF_INET6, CONN_COMMON, "Ipv6 addr no need to get ifName.");
542 
543     int32_t ret = GetIfNameByIp(myIp, domain, ifName, ifNameMaxLen);
544     CONN_CHECK_AND_RETURN_LOGW(ret == SOFTBUS_OK, CONN_COMMON, "cannot bind to interface.");
545 
546     ret = SoftBusSocketSetOpt(fd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_BINDTODEVICE, ifName, strlen(ifName));
547     if (ret < 0) {
548         COMM_LOGE(
549             CONN_COMMON, "socketSetOpt fail, fd=%{public}d, ifName=%{public}s, errno=%{public}d", fd, ifName, ret);
550         return;
551     }
552     return;
553 }
554