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