fix BACnet/IP on OS to bind broadcast to specific port (#489)

* Fixes #346 by binding the broadcast socket to the port specific broadcast address rather than INADDR_ANY or INADDR_BROADCAST. Added additional compile and environment options for those who might need them. 

* Changed the define USE_CLASSADDR to BACNET_IP_BROADCAST_USE_CLASSADDR to help manage namespaces.

* Added BACNET_IP_BROADCAST_BIND_ADDR environment variable to override the default broadcast binding address.

---------

Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
Steve Karg
2023-09-10 10:24:18 -05:00
committed by GitHub
parent 0001f85f29
commit 55b8b3d93c
18 changed files with 231 additions and 58 deletions
+2
View File
@@ -88,10 +88,12 @@
#include <sys/un.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include "bacnet/bacnet_stack_exports.h"
/** @file bsd/net.h Includes BSD network headers. */
/* Local helper functions for this port */
BACNET_STACK_EXPORT
extern int bip_get_local_netmask(
struct in_addr *netmask);
+56 -3
View File
@@ -58,6 +58,9 @@ static uint16_t BIP_Port;
static struct in_addr BIP_Address;
/* IP broadcast address - stored here in network byte order */
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;
/* enable debugging */
static bool BIP_Debug = false;
/* interface name */
@@ -188,6 +191,7 @@ void bip_get_broadcast_address(BACNET_ADDRESS *dest)
*/
bool bip_set_addr(BACNET_IP_ADDRESS *addr)
{
(void)addr;
/* not something we do within this driver */
return false;
}
@@ -214,6 +218,7 @@ bool bip_get_addr(BACNET_IP_ADDRESS *addr)
*/
bool bip_set_broadcast_addr(BACNET_IP_ADDRESS *addr)
{
(void)addr;
/* not something we do within this driver */
return false;
}
@@ -239,6 +244,7 @@ bool bip_get_broadcast_addr(BACNET_IP_ADDRESS *addr)
*/
bool bip_set_subnet_prefix(uint8_t prefix)
{
(void)prefix;
/* not something we do within this driver */
return false;
}
@@ -321,7 +327,7 @@ uint16_t bip_receive(
int max = 0;
struct timeval select_timeout;
struct sockaddr_in sin = { 0 };
BACNET_IP_ADDRESS addr = { { 0 } };
BACNET_IP_ADDRESS addr = { 0 };
socklen_t sin_len = sizeof(sin);
int received_bytes = 0;
int offset = 0;
@@ -547,6 +553,20 @@ int bip_get_local_netmask(struct in_addr *netmask)
return rv;
}
/**
* @brief Set the broadcast socket binding address
* @param baddr The broadcast socket binding address, in host order.
* @return 0 on success
*/
int bip_set_broadcast_binding(
const char *ip4_broadcast)
{
BIP_Broadcast_Binding_Address.s_addr = inet_addr(ip4_broadcast);
BIP_Broadcast_Binding_Address_Override = true;
return 0;
}
/** Gets the local IP address and local broadcast address from the system,
* and saves it into the BACnet/IP data structures.
*
@@ -572,6 +592,29 @@ void bip_set_interface(char *ifname)
fflush(stderr);
}
/* setup local broadcast address */
#ifdef BACNET_IP_BROADCAST_USE_CLASSADDR
long broadcast_address;
long net_address;
broadcast_address = 0;
net_address = local_address.s_addr;
if (IN_CLASSA(ntohl(net_address))) {
broadcast_address =
(ntohl(net_address) & ~IN_CLASSA_HOST) | IN_CLASSA_HOST;
} else if (IN_CLASSB(ntohl(net_address))) {
broadcast_address =
(ntohl(net_address) & ~IN_CLASSB_HOST) | IN_CLASSB_HOST;
} else if (IN_CLASSC(ntohl(net_address))) {
broadcast_address =
(ntohl(net_address) & ~IN_CLASSC_HOST) | IN_CLASSC_HOST;
} else if (IN_CLASSD(ntohl(net_address))) {
broadcast_address =
(ntohl(net_address) & ~IN_CLASSD_HOST) | IN_CLASSD_HOST;
} else {
broadcast_address = INADDR_BROADCAST;
}
BIP_Broadcast_Addr.s_addr = htonl(broadcast_address);
#else
request = "broadaddr";
rv = get_local_address(ifname, &broadcast_address, request);
if (rv < 0) {
@@ -579,6 +622,7 @@ void bip_set_interface(char *ifname)
} else {
BIP_Broadcast_Addr.s_addr = broadcast_address.s_addr;
}
#endif
if (BIP_Debug) {
fprintf(stderr, "BIP: Broadcast Address: %s\n",
inet_ntoa(BIP_Broadcast_Addr));
@@ -672,8 +716,17 @@ bool bip_init(char *ifname)
if (sock_fd < 0) {
return false;
}
sin.sin_addr.s_addr = htonl(INADDR_ANY);
if (BIP_Broadcast_Binding_Address_Override) {
sin.sin_addr.s_addr = BIP_Broadcast_Binding_Address.s_addr;
} else {
#if defined(BACNET_IP_BROADCAST_USE_INADDR_ANY)
sin.sin_addr.s_addr = htonl(INADDR_ANY);
#elif defined(BACNET_IP_BROADCAST_USE_INADDR_BROADCAST)
sin.sin_addr.s_addr = htonl(INADDR_BROADCAST);
#else
sin.sin_addr.s_addr = BIP_Broadcast_Addr.s_addr;
#endif
}
sock_fd = createSocket(&sin);
BIP_Broadcast_Socket = sock_fd;
if (sock_fd < 0) {