Skip to content

Commit

Permalink
emulation on host: fix binding from a particular interface (#7372)
Browse files Browse the repository at this point in the history
allows to effectively use virtual interfaces (ifconfig eth0:1) with a different IP address
  • Loading branch information
d-a-v committed Jun 13, 2020
1 parent a70e834 commit 89d0c78
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 15 deletions.
2 changes: 1 addition & 1 deletion tests/host/common/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#ifndef Arduino_h
#define Arduino_h

#define MOCK "mock: "
#define MOCK "(mock) "

#ifdef __cplusplus
extern "C" {
Expand Down
2 changes: 1 addition & 1 deletion tests/host/common/MockWiFiServerSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ void WiFiServer::begin ()

server.sin_family = AF_INET;
server.sin_port = htons(mockport);
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_addr.s_addr = htonl(global_source_address);
if (bind(sock, (struct sockaddr*)&server, sizeof(server)) == -1)
{
perror(MOCK "bind()");
Expand Down
6 changes: 2 additions & 4 deletions tests/host/common/UdpContextSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,8 @@ bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast)

// Filling server information
servaddr.sin_family = AF_INET;
//servaddr.sin_addr.s_addr = global_ipv4_netfmt?: dstaddr;
(void) dstaddr;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_addr.s_addr = htonl(global_source_address);
servaddr.sin_port = htons(mockport);

// Bind the socket with the server address
Expand All @@ -97,8 +96,7 @@ bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast)

struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = mcast;
//mreq.imr_interface.s_addr = global_ipv4_netfmt?: htonl(INADDR_ANY);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
mreq.imr_interface.s_addr = htonl(global_source_address);
if (global_ipv4_netfmt)
{
#if __APPLE__
Expand Down
1 change: 1 addition & 0 deletions tests/host/common/mock.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ extern const char* host_interface; // cmdline parameter
extern bool serial_timestamp;
extern int mock_port_shifter;
extern bool blocking_uart;
extern uint32_t global_source_address; // 0 = INADDR_ANY by default

#define NO_GLOBAL_BINDING 0xffffffff
extern uint32_t global_ipv4_netfmt; // selected interface addresse to bind to
Expand Down
31 changes: 22 additions & 9 deletions tests/host/common/user_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,41 +117,54 @@ void wifi_fpm_set_sleep_type (sleep_type_t type)
uint32_t global_ipv4_netfmt = 0; // global binding

netif netif0;
uint32_t global_source_address = INADDR_ANY;

bool wifi_get_ip_info (uint8 if_index, struct ip_info *info)
{
// emulate wifi_get_ip_info()
// ignore if_index
// use global option -i (host_interface) to select bound interface/address

struct ifaddrs * ifAddrStruct = NULL, * ifa = NULL;
uint32_t ipv4 = lwip_htonl(0x7f000001);
uint32_t mask = lwip_htonl(0xff000000);
global_source_address = INADDR_ANY; // =0

if (getifaddrs(&ifAddrStruct) != 0)
{
perror("getifaddrs");
exit(EXIT_FAILURE);
}
if (host_interface)
mockverbose("host: looking for interface '%s':\n", host_interface);
else
mockverbose("host: looking the first for non-local IPv4 interface:\n");
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)
{
mockverbose("host: interface: %s", ifa->ifa_name);
if ( ifa->ifa_addr
&& ifa->ifa_addr->sa_family == AF_INET // ip_info is IPv4 only
)
{
if (lwip_ntohl(*(uint32_t*)&((struct sockaddr_in*) ifa->ifa_netmask)->sin_addr) != 0xff000000)
auto test_ipv4 = lwip_ntohl(*(uint32_t*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr);
mockverbose(" IPV4 (0x%08lx)", test_ipv4);
if ((test_ipv4 & 0xff000000) == 0x7f000000)
// 127./8
mockverbose(" (local, ignored)");
else
{
if (ipv4 == lwip_htonl(0x7f000001))
{
// take the first by default
ipv4 = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr;
mask = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr;
}
if (host_interface && strcmp(ifa->ifa_name, host_interface) == 0)
if (!host_interface || (host_interface && strcmp(ifa->ifa_name, host_interface) == 0))
{
// .. or the one specified by user on cmdline
// use the first non-local interface, or, if specified, the one selected by user on cmdline
ipv4 = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr;
mask = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr;
mockverbose(" (selected)\n");
global_source_address = ntohl(ipv4);
break;
}
}
}
mockverbose("\n");
}
if (ifAddrStruct != NULL)
freeifaddrs(ifAddrStruct);
Expand Down

0 comments on commit 89d0c78

Please sign in to comment.