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 */
|
/* broadcast binding mechanism */
|
||||||
static bool BIP_Broadcast_Binding_Address_Override;
|
static bool BIP_Broadcast_Binding_Address_Override;
|
||||||
static struct in_addr BIP_Broadcast_Binding_Address;
|
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 */
|
/* enable debugging */
|
||||||
static bool BIP_Debug = false;
|
static bool BIP_Debug = false;
|
||||||
/* interface name */
|
/* 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)
|
static void *get_addr_ptr(struct sockaddr *sockaddr_ptr)
|
||||||
{
|
{
|
||||||
void *addr_ptr = NULL;
|
void *addr_ptr = NULL;
|
||||||
if (sockaddr_ptr->sa_family == AF_INET) {
|
|
||||||
addr_ptr = &((struct sockaddr_in *)sockaddr_ptr)->sin_addr;
|
if (sockaddr_ptr) {
|
||||||
} else if (sockaddr_ptr->sa_family == AF_INET6) {
|
if (sockaddr_ptr->sa_family == AF_INET) {
|
||||||
addr_ptr = &((struct sockaddr_in6 *)sockaddr_ptr)->sin6_addr;
|
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;
|
return addr_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,7 +498,9 @@ int bip_get_local_address_ioctl(
|
|||||||
char rv = '\0'; /* return value */
|
char rv = '\0'; /* return value */
|
||||||
|
|
||||||
struct ifaddrs *ifaddrs_ptr;
|
struct ifaddrs *ifaddrs_ptr;
|
||||||
|
void *addr_ptr = NULL;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
status = getifaddrs(&ifaddrs_ptr);
|
status = getifaddrs(&ifaddrs_ptr);
|
||||||
if (status == -1) {
|
if (status == -1) {
|
||||||
fprintf(
|
fprintf(
|
||||||
@@ -500,17 +508,25 @@ int bip_get_local_address_ioctl(
|
|||||||
}
|
}
|
||||||
while (ifaddrs_ptr) {
|
while (ifaddrs_ptr) {
|
||||||
if ((ifaddrs_ptr->ifa_addr->sa_family == AF_INET) &&
|
if ((ifaddrs_ptr->ifa_addr->sa_family == AF_INET) &&
|
||||||
(strcmp(ifaddrs_ptr->ifa_name, ifname) == 0)) {
|
(ifname && strcmp(ifaddrs_ptr->ifa_name, ifname) == 0)) {
|
||||||
void *addr_ptr = NULL;
|
|
||||||
if (!ifaddrs_ptr->ifa_addr) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
switch (request) {
|
switch (request) {
|
||||||
case SIOCGIFADDR:
|
case SIOCGIFADDR:
|
||||||
addr_ptr = get_addr_ptr(ifaddrs_ptr->ifa_addr);
|
addr_ptr = get_addr_ptr(ifaddrs_ptr->ifa_addr);
|
||||||
break;
|
break;
|
||||||
case SIOCGIFBRDADDR:
|
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;
|
break;
|
||||||
case SIOCGIFNETMASK:
|
case SIOCGIFNETMASK:
|
||||||
addr_ptr = get_addr_ptr(ifaddrs_ptr->ifa_netmask);
|
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;
|
ifaddrs_ptr = ifaddrs_ptr->ifa_next;
|
||||||
}
|
}
|
||||||
freeifaddrs(ifaddrs_ptr);
|
freeifaddrs(ifaddrs_ptr);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -571,6 +588,9 @@ void bip_set_interface(const char *ifname)
|
|||||||
struct in_addr broadcast_address;
|
struct in_addr broadcast_address;
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
|
||||||
|
local_address.s_addr = 0;
|
||||||
|
broadcast_address.s_addr = 0;
|
||||||
|
BIP_Point_To_Point = false;
|
||||||
/* setup local address */
|
/* setup local address */
|
||||||
rv = bip_get_local_address_ioctl(ifname, &local_address, SIOCGIFADDR);
|
rv = bip_get_local_address_ioctl(ifname, &local_address, SIOCGIFADDR);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
@@ -611,8 +631,11 @@ void bip_set_interface(const char *ifname)
|
|||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
BIP_Broadcast_Addr.s_addr = ~0;
|
BIP_Broadcast_Addr.s_addr = ~0;
|
||||||
} else {
|
} else {
|
||||||
BIP_Broadcast_Addr = local_address;
|
if (BIP_Point_To_Point) {
|
||||||
BIP_Broadcast_Addr.s_addr = broadcast_address.s_addr;
|
BIP_Broadcast_Addr.s_addr = local_address.s_addr;
|
||||||
|
} else {
|
||||||
|
BIP_Broadcast_Addr.s_addr = broadcast_address.s_addr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (BIP_Debug) {
|
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)
|
static int createSocket(const struct sockaddr_in *sin)
|
||||||
{
|
{
|
||||||
int status = 0; /* return from socket lib calls */
|
int status = 0; /* return from socket lib calls */
|
||||||
@@ -710,49 +738,51 @@ bool bip_init(char *ifname)
|
|||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sin.sin_family = AF_INET;
|
sin.sin_family = AF_INET;
|
||||||
sin.sin_port = BIP_Port;
|
sin.sin_port = BIP_Port;
|
||||||
memset(&(sin.sin_zero), '\0', sizeof(sin.sin_zero));
|
memset(&(sin.sin_zero), '\0', sizeof(sin.sin_zero));
|
||||||
|
|
||||||
sin.sin_addr.s_addr = BIP_Address.s_addr;
|
sin.sin_addr.s_addr = BIP_Address.s_addr;
|
||||||
sock_fd = createSocket(&sin);
|
sock_fd = createSocket(&sin);
|
||||||
BIP_Socket = sock_fd;
|
BIP_Socket = sock_fd;
|
||||||
if (sock_fd < 0) {
|
if (sock_fd < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (BIP_Point_To_Point) {
|
||||||
broadcast_sin_config.sin_family = AF_INET;
|
/* point-to-point interface flag
|
||||||
broadcast_sin_config.sin_port = BIP_Port;
|
uses the unicast socket for broadcast */
|
||||||
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;
|
BIP_Broadcast_Socket = BIP_Socket;
|
||||||
} else {
|
} else {
|
||||||
broadcast_sock_fd = createSocket(&broadcast_sin_config);
|
broadcast_sin_config.sin_family = AF_INET;
|
||||||
BIP_Broadcast_Socket = broadcast_sock_fd;
|
broadcast_sin_config.sin_port = BIP_Port;
|
||||||
if (broadcast_sock_fd < 0) {
|
memset(
|
||||||
bip_cleanup();
|
&(broadcast_sin_config.sin_zero), '\0',
|
||||||
return false;
|
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();
|
bvlc_init();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user