1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-13 13:01:55 +03:00

emulation on host: fix binding from a particular interface (#7372)

allows to effectively use virtual interfaces (ifconfig eth0:1) with a different IP address
This commit is contained in:
david gauchard
2020-06-13 14:04:28 +02:00
committed by GitHub
parent a70e834d1e
commit 89d0c78703
5 changed files with 27 additions and 15 deletions

View File

@ -20,7 +20,7 @@
#ifndef Arduino_h #ifndef Arduino_h
#define Arduino_h #define Arduino_h
#define MOCK "mock: " #define MOCK "(mock) "
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -101,7 +101,7 @@ void WiFiServer::begin ()
server.sin_family = AF_INET; server.sin_family = AF_INET;
server.sin_port = htons(mockport); 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) if (bind(sock, (struct sockaddr*)&server, sizeof(server)) == -1)
{ {
perror(MOCK "bind()"); perror(MOCK "bind()");

View File

@ -76,9 +76,8 @@ bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast)
// Filling server information // Filling server information
servaddr.sin_family = AF_INET; servaddr.sin_family = AF_INET;
//servaddr.sin_addr.s_addr = global_ipv4_netfmt?: dstaddr;
(void) 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); servaddr.sin_port = htons(mockport);
// Bind the socket with the server address // Bind the socket with the server address
@ -97,8 +96,7 @@ bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast)
struct ip_mreq mreq; struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = mcast; mreq.imr_multiaddr.s_addr = mcast;
//mreq.imr_interface.s_addr = global_ipv4_netfmt?: htonl(INADDR_ANY); mreq.imr_interface.s_addr = htonl(global_source_address);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (global_ipv4_netfmt) if (global_ipv4_netfmt)
{ {
#if __APPLE__ #if __APPLE__

View File

@ -112,6 +112,7 @@ extern const char* host_interface; // cmdline parameter
extern bool serial_timestamp; extern bool serial_timestamp;
extern int mock_port_shifter; extern int mock_port_shifter;
extern bool blocking_uart; extern bool blocking_uart;
extern uint32_t global_source_address; // 0 = INADDR_ANY by default
#define NO_GLOBAL_BINDING 0xffffffff #define NO_GLOBAL_BINDING 0xffffffff
extern uint32_t global_ipv4_netfmt; // selected interface addresse to bind to extern uint32_t global_ipv4_netfmt; // selected interface addresse to bind to

View File

@ -117,41 +117,54 @@ void wifi_fpm_set_sleep_type (sleep_type_t type)
uint32_t global_ipv4_netfmt = 0; // global binding uint32_t global_ipv4_netfmt = 0; // global binding
netif netif0; netif netif0;
uint32_t global_source_address = INADDR_ANY;
bool wifi_get_ip_info (uint8 if_index, struct ip_info *info) 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; struct ifaddrs * ifAddrStruct = NULL, * ifa = NULL;
uint32_t ipv4 = lwip_htonl(0x7f000001); uint32_t ipv4 = lwip_htonl(0x7f000001);
uint32_t mask = lwip_htonl(0xff000000); uint32_t mask = lwip_htonl(0xff000000);
global_source_address = INADDR_ANY; // =0
if (getifaddrs(&ifAddrStruct) != 0) if (getifaddrs(&ifAddrStruct) != 0)
{ {
perror("getifaddrs"); perror("getifaddrs");
exit(EXIT_FAILURE); 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) for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)
{ {
mockverbose("host: interface: %s", ifa->ifa_name);
if ( ifa->ifa_addr if ( ifa->ifa_addr
&& ifa->ifa_addr->sa_family == AF_INET // ip_info is IPv4 only && 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)) if (!host_interface || (host_interface && strcmp(ifa->ifa_name, host_interface) == 0))
{ {
// take the first by default // 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;
}
if (host_interface && strcmp(ifa->ifa_name, host_interface) == 0)
{
// .. or the one specified by user on cmdline
ipv4 = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr; ipv4 = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr;
mask = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr; mask = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr;
mockverbose(" (selected)\n");
global_source_address = ntohl(ipv4);
break; break;
} }
} }
} }
mockverbose("\n");
} }
if (ifAddrStruct != NULL) if (ifAddrStruct != NULL)
freeifaddrs(ifAddrStruct); freeifaddrs(ifAddrStruct);