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:
+72
-42
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user