fix: bind to interface

Signed-off-by: liangjunhao <liangjunhao10@huawei.com>
This commit is contained in:
liangjunhao 2024-08-16 19:05:46 +08:00
parent 9dffe78f6b
commit bf45a72ab5
11 changed files with 91 additions and 14 deletions

View File

@ -58,6 +58,7 @@ extern "C" {
#define SOFTBUS_SO_KEEPALIVE_ SO_KEEPALIVE
#define SOFTBUS_SO_REUSEPORT_ SO_REUSEPORT
#define SOFTBUS_SO_RCVBUFFORCE_ SO_RCVBUFFORCE
#define SOFTBUS_SO_BINDTODEVICE_ SO_BINDTODEVICE
#define SOFTBUS_TCP_KEEPIDLE_ TCP_KEEPIDLE
#define SOFTBUS_TCP_KEEPINTVL_ TCP_KEEPINTVL

View File

@ -65,6 +65,7 @@ extern "C" {
#define SOFTBUS_SO_KEEPALIVE SOFTBUS_SO_KEEPALIVE_
#define SOFTBUS_SO_REUSEPORT SOFTBUS_SO_REUSEPORT_
#define SOFTBUS_SO_RCVBUFFORCE SOFTBUS_SO_RCVBUFFORCE_
#define SOFTBUS_SO_BINDTODEVICE SOFTBUS_SO_BINDTODEVICE_
#define SOFTBUS_TCP_KEEPIDLE SOFTBUS_TCP_KEEPIDLE_
#define SOFTBUS_TCP_KEEPINTVL SOFTBUS_TCP_KEEPINTVL_

View File

@ -17,10 +17,12 @@
#include <errno.h>
#include <fcntl.h>
#include <ifaddrs.h>
#include <securec.h>
#include "conn_log.h"
#include "softbus_adapter_socket.h"
#include "softbus_conn_common.h"
#include "softbus_def.h"
#include "softbus_errcode.h"
#include "softbus_tcp_socket.h"
@ -483,4 +485,65 @@ bool IsHmlIpAddr(const char *ip)
}
return strncmp(ip, HML_IPV4_ADDR_PREFIX, strlen(HML_IPV4_ADDR_PREFIX)) == 0;
}
}
static int32_t GetIfNameByIp(const char *myIp, int32_t domain, char *ifName, int32_t ifNameMaxLen)
{
if (myIp == NULL || ifName == NULL) {
COMM_LOGE(CONN_COMMON, "Invalid param.");
return SOFTBUS_INVALID_PARAM;
}
struct ifaddrs *ifa = NULL;
struct ifaddrs *ifList = NULL;
struct in_addr inAddr = { 0 };
char animizedIp[IP_LEN] = { 0 };
ConvertAnonymizeIpAddress(animizedIp, IP_LEN, myIp, IP_LEN);
int32_t ret = getifaddrs(&ifList);
if (ret != 0) {
COMM_LOGE(CONN_COMMON, "ip=%{public}s getifaddrs ifList failed, ret=%{public}d", animizedIp, ret);
return SOFTBUS_SOCKET_ADDR_ERR;
}
if (inet_aton(myIp, &inAddr) == 0) {
COMM_LOGE(CONN_COMMON, "inet_aton ip=%{public}s failed.", animizedIp);
freeifaddrs(ifList);
return SOFTBUS_TCP_SOCKET_ERR;
}
for (ifa = ifList; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL) {
continue;
}
(void)memset_s(ifName, ifNameMaxLen, 0, ifNameMaxLen);
if (memcmp(&inAddr, &(((struct sockaddr_in *)ifa->ifa_addr)->sin_addr), sizeof(struct in_addr)) == 0) {
if (memcpy_s(ifName, ifNameMaxLen - 1, ifa->ifa_name, strlen(ifa->ifa_name)) != EOK) {
COMM_LOGE(CONN_COMMON, "fail to memcpy_s ifName by ip=%{public}s", animizedIp);
freeifaddrs(ifList);
return SOFTBUS_MEM_ERR;
}
freeifaddrs(ifList);
return SOFTBUS_OK;
}
}
COMM_LOGW(CONN_COMMON, "not found ifName by ip=%{public}s", animizedIp);
freeifaddrs(ifList);
return SOFTBUS_CONN_NOT_FOUND_FAILED;
}
// prevent the scenario of using VPN to produce virtual network cards.
void BindToInterface(const char *myIp, int32_t domain, int fd, char *ifName, int32_t ifNameMaxLen)
{
// The IPv6 socket has already been bound to the network card, there is no need to bind it again.
CONN_CHECK_AND_RETURN_LOGW(domain != SOFTBUS_AF_INET6, CONN_COMMON, "Ipv6 addr no need to get ifName.");
int32_t ret = GetIfNameByIp(myIp, domain, ifName, ifNameMaxLen);
CONN_CHECK_AND_RETURN_LOGW(ret == SOFTBUS_OK, CONN_COMMON, "cannot bind to interface.");
ret = SoftBusSocketSetOpt(fd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_BINDTODEVICE, ifName, strlen(ifName));
if (ret < 0) {
COMM_LOGE(
CONN_COMMON, "socketSetOpt fail, fd=%{public}d, ifName=%{public}s, errno=%{public}d", fd, ifName, ret);
return;
}
return;
}

View File

@ -223,6 +223,8 @@ static int32_t OpenTcpServerSocket(const LocalListenerInfo *option)
ConnShutdownSocket(fd);
return SOFTBUS_SOCKET_BIND_ERR;
}
BindToInterface(option->socketOption.addr, domain, fd, (char *)(option->socketOption.ifName), IF_NAME_SIZE);
CONN_LOGI(CONN_COMMON, "server listen tcp socket, fd=%{public}d", fd);
return fd;
}
@ -272,8 +274,7 @@ static int32_t SocketConnect(int32_t fd, int32_t domain, const ConnectOption *op
static int32_t OpenTcpClientSocket(const ConnectOption *option, const char *myIp, bool isNonBlock)
{
CONN_CHECK_AND_RETURN_RET_LOGW(option != NULL, SOFTBUS_INVALID_PARAM, CONN_COMMON,
"invalid param, option is null");
CONN_CHECK_AND_RETURN_RET_LOGW(option != NULL, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param, null option");
CONN_CHECK_AND_RETURN_RET_LOGW(option->type == CONNECT_TCP || option->type == CONNECT_P2P ||
option->type == CONNECT_P2P_REUSE || option->type == CONNECT_HML, SOFTBUS_INVALID_PARAM, CONN_COMMON,
"invalid param, unsupport type=%{public}d", option->type);
@ -311,6 +312,8 @@ static int32_t OpenTcpClientSocket(const ConnectOption *option, const char *myIp
ConnShutdownSocket(fd);
return ret;
}
BindToInterface(myIp, domain, fd, (char *)(option->socketOption.ifName), IF_NAME_SIZE);
ret = SocketConnect(fd, domain, option);
if ((ret != SOFTBUS_ADAPTER_OK) && (ret != SOFTBUS_ADAPTER_SOCKET_EINPROGRESS) &&
(ret != SOFTBUS_ADAPTER_SOCKET_EAGAIN)) {

View File

@ -71,6 +71,7 @@ typedef enum {
#define CONN_INVALID_LISTENER_MODULE_ID 0xffff
#define CONN_DYNAMIC_LISTENER_MODULE_COUNT 32
#define DEVID_BUFF_LEN 65
#define NETIF_NAME_LEN 16
#define BT_LINK_TYPE_BR 1
#define BT_LINK_TYPE_BLE 2
@ -187,6 +188,7 @@ struct SocketOption {
int32_t moduleId; /* For details, see {@link ListenerModule}. */
ProtocolType protocol;
int32_t keepAlive;
char ifName[NETIF_NAME_LEN];
};
typedef struct {
@ -219,6 +221,7 @@ struct ListenerSocketOption {
int32_t port;
ListenerModule moduleId; /* For details, see {@link ListenerModule}. */
ProtocolType protocol;
char ifName[NETIF_NAME_LEN];
};
typedef struct {

View File

@ -90,6 +90,8 @@ int32_t Ipv6AddrInToAddr(SoftBusSockAddrIn6 *addrIn6, char *addr, int32_t addrLe
int32_t Ipv6AddrToAddrIn(SoftBusSockAddrIn6 *addrIn6, const char *ip, uint16_t port);
int32_t Ipv4AddrToAddrIn(SoftBusSockAddrIn *addrIn, const char *ip, uint16_t port);
void BindToInterface(const char *myIp, int32_t domain, int fd, char *ifName, int32_t ifNameMaxLen);
bool IsHmlIpAddr(const char *ip);
#ifdef __cplusplus

View File

@ -641,7 +641,7 @@ static int32_t OnVerifyP2pRequest(AuthHandle authHandle, int64_t seq, const cJSO
return SOFTBUS_OK;
}
static int32_t ConnectTcpDirectPeer(const char *addr, int port)
static int32_t ConnectTcpDirectPeer(const char *addr, int port, const char *myIp)
{
ConnectOption options;
if (IsHmlIpAddr(addr)) {
@ -660,7 +660,7 @@ static int32_t ConnectTcpDirectPeer(const char *addr, int port)
return SOFTBUS_STRCPY_ERR;
}
return ConnOpenClientSocket(&options, BIND_ADDR_ALL, true);
return ConnOpenClientSocket(&options, myIp, true);
}
static int32_t AddHmlTrigger(int32_t fd, const char *myAddr, int64_t seq)
@ -744,7 +744,7 @@ static int32_t OnVerifyP2pReply(int64_t authId, int64_t seq, const cJSON *json)
}
TRANS_LOGI(TRANS_CTRL, "peer wifi: peerPort=%{public}d", conn->appInfo.peerData.port);
fd = ConnectTcpDirectPeer(conn->appInfo.peerData.addr, conn->appInfo.peerData.port);
fd = ConnectTcpDirectPeer(conn->appInfo.peerData.addr, conn->appInfo.peerData.port, conn->appInfo.myData.addr);
if (fd <= 0) {
ReleaseSessionConnLock();
TRANS_LOGE(TRANS_CTRL, "conn fail: fd=%{public}d", fd);

View File

@ -156,7 +156,7 @@ int32_t OpenTcpDirectChannel(const AppInfo *appInfo, const ConnectOption *connIn
return SOFTBUS_TRANS_TCP_GET_AUTHID_FAILED;
}
int32_t fd = ConnOpenClientSocket(connInfo, BIND_ADDR_ALL, true);
int32_t fd = ConnOpenClientSocket(connInfo, newConn->appInfo.myData.addr, true);
if (fd < 0) {
FreeFastTransData(&(newConn->appInfo));
SoftBusFree(newConn);

View File

@ -39,10 +39,13 @@ group("unittest") {
"trans_channel/udp_negotiation:unittest",
]
if (has_enhance_test) {
deps += [ "$dsoftbus_root_path/dsoftbus_enhance/test/core/transmission/trans_channel:unittest" ]
deps += [ "$dsoftbus_root_path/dsoftbus_enhance/test/core/transmission/session:unittest" ]
deps += [ "$dsoftbus_root_path/dsoftbus_enhance/test/core/transmission/spe:unittest" ]
deps += [ "$dsoftbus_root_path/dsoftbus_enhance/test/core/transmission/manager:unittest" ]
deps += [
"$dsoftbus_root_path/dsoftbus_enhance/test/core/transmission/ipc:unittest",
"$dsoftbus_root_path/dsoftbus_enhance/test/core/transmission/manager:unittest",
"$dsoftbus_root_path/dsoftbus_enhance/test/core/transmission/session:unittest",
"$dsoftbus_root_path/dsoftbus_enhance/test/core/transmission/spe:unittest",
"$dsoftbus_root_path/dsoftbus_enhance/test/core/transmission/trans_channel:unittest",
]
}
}

View File

@ -44,6 +44,7 @@ using namespace testing::ext;
#define P2P_IP "P2P_IP"
#define ERR_CODE "ERR_CODE"
static const char *IP = "192.168.8.1";
static const char *MY_IP = "192.168.8.13";
static const char *DATA = "test_send_data";
static const char *SESSION_NAME = "com.test.trans.auth.demo";
static const char *PKGE_NAME = "dms";
@ -520,11 +521,11 @@ HWTEST_F(TransTcpDirectP2pMockTest, ConnectTcpDirectPeerTest001, TestSize.Level1
NiceMock<TransTcpDirectP2pInterfaceMock> TcpP2pDirectMock;
EXPECT_CALL(TcpP2pDirectMock, IsHmlIpAddr).WillOnce(Return(false));
EXPECT_CALL(TcpP2pDirectMock, ConnOpenClientSocket).WillOnce(Return(SOFTBUS_NO_INIT));
int32_t ret = ConnectTcpDirectPeer(IP, TEST_PORT);
int32_t ret = ConnectTcpDirectPeer(IP, TEST_PORT, MY_IP);
EXPECT_EQ(SOFTBUS_NO_INIT, ret);
EXPECT_CALL(TcpP2pDirectMock, IsHmlIpAddr).WillOnce(Return(true));
EXPECT_CALL(TcpP2pDirectMock, ConnOpenClientSocket).WillOnce(Return(SOFTBUS_OK));
ret = ConnectTcpDirectPeer(IP, TEST_PORT);
ret = ConnectTcpDirectPeer(IP, TEST_PORT, MY_IP);
EXPECT_EQ(SOFTBUS_OK, ret);
}

View File

@ -345,7 +345,7 @@ HWTEST_F(TransTcpDirectP2pTest, OnVerifyP2pRequestTest001, TestSize.Level1)
*/
HWTEST_F(TransTcpDirectP2pTest, ConnectTcpDirectPeerTest001, TestSize.Level1)
{
int32_t ret = ConnectTcpDirectPeer(g_addr, g_port);
int32_t ret = ConnectTcpDirectPeer(g_addr, g_port, g_ip);
EXPECT_EQ(ret, SOFTBUS_CONN_SOCKET_GET_INTERFACE_ERR);
}