Fix point-to-point VPN tunnel sockets for BACnet/IP by using IFF_POINTTOPOINT flag when getting the broadcast address. (#1066)

This commit is contained in:
Steve Karg
2025-08-12 08:50:30 -05:00
committed by GitHub
parent 6b6dfab10e
commit 3a3d7fcc13
+72 -42
View File
@@ -32,6 +32,8 @@ static struct in_addr BIP_Broadcast_Addr;
/* broadcast binding mechanism */
static bool BIP_Broadcast_Binding_Address_Override;
static struct in_addr BIP_Broadcast_Binding_Address;
/* point-to-point interface flag - uses the unicast socket for broadcast */
static bool BIP_Point_To_Point = false;
/* enable debugging */
static bool BIP_Debug = false;
/* interface name */
@@ -449,11 +451,15 @@ bool bip_get_addr_by_name(const char *host_name, BACNET_IP_ADDRESS *addr)
static void *get_addr_ptr(struct sockaddr *sockaddr_ptr)
{
void *addr_ptr = NULL;
if (sockaddr_ptr->sa_family == AF_INET) {
addr_ptr = &((struct sockaddr_in *)sockaddr_ptr)->sin_addr;
} else if (sockaddr_ptr->sa_family == AF_INET6) {
addr_ptr = &((struct sockaddr_in6 *)sockaddr_ptr)->sin6_addr;
if (sockaddr_ptr) {
if (sockaddr_ptr->sa_family == AF_INET) {
addr_ptr = &((struct sockaddr_in *)sockaddr_ptr)->sin_addr;
} else if (sockaddr_ptr->sa_family == AF_INET6) {
addr_ptr = &((struct sockaddr_in6 *)sockaddr_ptr)->sin6_addr;
}
}
return addr_ptr;
}
@@ -492,7 +498,9 @@ int bip_get_local_address_ioctl(
char rv = '\0'; /* return value */
struct ifaddrs *ifaddrs_ptr;
void *addr_ptr = NULL;
int status;
status = getifaddrs(&ifaddrs_ptr);
if (status == -1) {
fprintf(
@@ -500,17 +508,25 @@ int bip_get_local_address_ioctl(
}
while (ifaddrs_ptr) {
if ((ifaddrs_ptr->ifa_addr->sa_family == AF_INET) &&
(strcmp(ifaddrs_ptr->ifa_name, ifname) == 0)) {
void *addr_ptr = NULL;
if (!ifaddrs_ptr->ifa_addr) {
return rv;
}
(ifname && strcmp(ifaddrs_ptr->ifa_name, ifname) == 0)) {
switch (request) {
case SIOCGIFADDR:
addr_ptr = get_addr_ptr(ifaddrs_ptr->ifa_addr);
break;
case SIOCGIFBRDADDR:
addr_ptr = get_addr_ptr(ifaddrs_ptr->ifa_broadaddr);
/* Depending on whether the bit
IFF_BROADCAST or IFF_POINTOPOINT is set
in ifa_flags (only one can be set at a time),
either ifa_broadaddr will contain the broadcast
address associated with ifa_addr or ifa_dstaddr
will contain the destination address of the
point-to-point interface.*/
if (ifaddrs_ptr->ifa_flags & IFF_POINTOPOINT) {
BIP_Point_To_Point = true;
addr_ptr = get_addr_ptr(ifaddrs_ptr->ifa_dstaddr);
} else {
addr_ptr = get_addr_ptr(ifaddrs_ptr->ifa_broadaddr);
}
break;
case SIOCGIFNETMASK:
addr_ptr = get_addr_ptr(ifaddrs_ptr->ifa_netmask);
@@ -525,6 +541,7 @@ int bip_get_local_address_ioctl(
ifaddrs_ptr = ifaddrs_ptr->ifa_next;
}
freeifaddrs(ifaddrs_ptr);
return rv;
}
@@ -571,6 +588,9 @@ void bip_set_interface(const char *ifname)
struct in_addr broadcast_address;
int rv = 0;
local_address.s_addr = 0;
broadcast_address.s_addr = 0;
BIP_Point_To_Point = false;
/* setup local address */
rv = bip_get_local_address_ioctl(ifname, &local_address, SIOCGIFADDR);
if (rv < 0) {
@@ -611,8 +631,11 @@ void bip_set_interface(const char *ifname)
if (rv < 0) {
BIP_Broadcast_Addr.s_addr = ~0;
} else {
BIP_Broadcast_Addr = local_address;
BIP_Broadcast_Addr.s_addr = broadcast_address.s_addr;
if (BIP_Point_To_Point) {
BIP_Broadcast_Addr.s_addr = local_address.s_addr;
} else {
BIP_Broadcast_Addr.s_addr = broadcast_address.s_addr;
}
}
#endif
if (BIP_Debug) {
@@ -626,6 +649,11 @@ void bip_set_interface(const char *ifname)
}
}
const char *bip_get_interface(void)
{
return BIP_Interface_Name;
}
static int createSocket(const struct sockaddr_in *sin)
{
int status = 0; /* return from socket lib calls */
@@ -710,49 +738,51 @@ bool bip_init(char *ifname)
fflush(stderr);
return false;
}
sin.sin_family = AF_INET;
sin.sin_port = BIP_Port;
memset(&(sin.sin_zero), '\0', sizeof(sin.sin_zero));
sin.sin_addr.s_addr = BIP_Address.s_addr;
sock_fd = createSocket(&sin);
BIP_Socket = sock_fd;
if (sock_fd < 0) {
return false;
}
broadcast_sin_config.sin_family = AF_INET;
broadcast_sin_config.sin_port = BIP_Port;
memset(
&(broadcast_sin_config.sin_zero), '\0',
sizeof(broadcast_sin_config.sin_zero));
if (BIP_Broadcast_Binding_Address_Override) {
broadcast_sin_config.sin_addr.s_addr =
BIP_Broadcast_Binding_Address.s_addr;
} else {
#if defined(BACNET_IP_BROADCAST_USE_INADDR_ANY)
broadcast_sin_config.sin_addr.s_addr = htonl(INADDR_ANY);
#elif defined(BACNET_IP_BROADCAST_USE_INADDR_BROADCAST)
broadcast_sin_config.sin_addr.s_addr = htonl(INADDR_BROADCAST);
#else
broadcast_sin_config.sin_addr.s_addr = BIP_Broadcast_Addr.s_addr;
#endif
}
if (broadcast_sin_config.sin_addr.s_addr == BIP_Address.s_addr) {
/* handle the case when a network interface on the system
reports the interface's unicast IP address as being
the same as its broadcast IP address */
if (BIP_Point_To_Point) {
/* point-to-point interface flag
uses the unicast socket for broadcast */
BIP_Broadcast_Socket = BIP_Socket;
} else {
broadcast_sock_fd = createSocket(&broadcast_sin_config);
BIP_Broadcast_Socket = broadcast_sock_fd;
if (broadcast_sock_fd < 0) {
bip_cleanup();
return false;
broadcast_sin_config.sin_family = AF_INET;
broadcast_sin_config.sin_port = BIP_Port;
memset(
&(broadcast_sin_config.sin_zero), '\0',
sizeof(broadcast_sin_config.sin_zero));
if (BIP_Broadcast_Binding_Address_Override) {
broadcast_sin_config.sin_addr.s_addr =
BIP_Broadcast_Binding_Address.s_addr;
} else {
#if defined(BACNET_IP_BROADCAST_USE_INADDR_ANY)
broadcast_sin_config.sin_addr.s_addr = htonl(INADDR_ANY);
#elif defined(BACNET_IP_BROADCAST_USE_INADDR_BROADCAST)
broadcast_sin_config.sin_addr.s_addr = htonl(INADDR_BROADCAST);
#else
broadcast_sin_config.sin_addr.s_addr = BIP_Broadcast_Addr.s_addr;
#endif
}
if (broadcast_sin_config.sin_addr.s_addr == BIP_Address.s_addr) {
/* handle the case when a network interface on the system
reports the interface's unicast IP address as being
the same as its broadcast IP address */
BIP_Broadcast_Socket = BIP_Socket;
} else {
broadcast_sock_fd = createSocket(&broadcast_sin_config);
BIP_Broadcast_Socket = broadcast_sock_fd;
if (broadcast_sock_fd < 0) {
bip_cleanup();
return false;
}
}
}
bvlc_init();
return true;