bip: decouple broadcast destination port from bind port (#1311)

Co-authored-by: Leunar Kalludra <Leunar.Kalludra@de.bosch.com>
This commit is contained in:
Leunar Kalludra
2026-04-24 13:40:32 +02:00
committed by GitHub
parent 8607b241e9
commit f616a8cc68
22 changed files with 469 additions and 17 deletions
+1
View File
@@ -141,6 +141,7 @@ void bip_cleanup(void)
close_func(sock_fd); close_func(sock_fd);
} }
bip_set_socket(MAX_SOCK_NUM); bip_set_socket(MAX_SOCK_NUM);
bip_set_broadcast_port(0);
return; return;
} }
+19 -2
View File
@@ -24,6 +24,8 @@
static uint8_t BIP_Socket = MAX_SOCK_NUM; static uint8_t BIP_Socket = MAX_SOCK_NUM;
/* port to use - stored in network byte order */ /* port to use - stored in network byte order */
static uint16_t BIP_Port = 0; /* this will force initialization in demos */ static uint16_t BIP_Port = 0; /* this will force initialization in demos */
/* broadcast destination port to use */
static uint16_t BIP_Broadcast_Port;
/* IP Address - stored in network byte order */ /* IP Address - stored in network byte order */
// static struct in_addr BIP_Address; // static struct in_addr BIP_Address;
static uint8_t BIP_Address[4] = { 0, 0, 0, 0 }; static uint8_t BIP_Address[4] = { 0, 0, 0, 0 };
@@ -105,12 +107,26 @@ void bip_set_port(uint16_t port)
BIP_Port = htons(port); BIP_Port = htons(port);
} }
void bip_set_broadcast_port(uint16_t port)
{ /* in network byte order */
BIP_Broadcast_Port = htons(port);
}
/* returns network byte order */ /* returns network byte order */
uint16_t bip_get_port(void) uint16_t bip_get_port(void)
{ {
return ntohs(BIP_Port); return ntohs(BIP_Port);
} }
uint16_t bip_get_broadcast_port(void)
{
if (BIP_Broadcast_Port) {
return ntohs(BIP_Broadcast_Port);
}
return ntohs(BIP_Port);
}
static int bip_decode_bip_address( static int bip_decode_bip_address(
const BACNET_ADDRESS *bac_addr, const BACNET_ADDRESS *bac_addr,
uint8_t *address, /* in network format */ uint8_t *address, /* in network format */
@@ -166,7 +182,7 @@ int bip_send_pdu(
for (uint8_t i = 0; i < 4; i++) { for (uint8_t i = 0; i < 4; i++) {
address[i] = BIP_Broadcast_Address[i]; address[i] = BIP_Broadcast_Address[i];
} }
port = BIP_Port; port = htons(bip_get_broadcast_port());
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU; mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
#ifdef DEBUG #ifdef DEBUG
fprintf( fprintf(
@@ -386,11 +402,12 @@ void bip_get_my_address(BACNET_ADDRESS *my_address)
void bip_get_broadcast_address(BACNET_ADDRESS *dest) void bip_get_broadcast_address(BACNET_ADDRESS *dest)
{ /* destination address */ { /* destination address */
int i = 0; /* counter */ int i = 0; /* counter */
uint16_t port = htons(bip_get_broadcast_port());
if (dest) { if (dest) {
dest->mac_len = 6; dest->mac_len = 6;
memcpy(&dest->mac[0], &BIP_Broadcast_Address, 4); memcpy(&dest->mac[0], &BIP_Broadcast_Address, 4);
memcpy(&dest->mac[4], &BIP_Port, 2); memcpy(&dest->mac[4], &port, 2);
dest->net = BACNET_BROADCAST_NETWORK; dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* no SLEN */ dest->len = 0; /* no SLEN */
for (i = 0; i < MAX_MAC_LEN; i++) { for (i = 0; i < MAX_MAC_LEN; i++) {
+2
View File
@@ -65,8 +65,10 @@ uint16_t bip_receive(
/* use host byte order for setting */ /* use host byte order for setting */
void bip_set_port(uint16_t port); void bip_set_port(uint16_t port);
void bip_set_broadcast_port(uint16_t port);
/* returns host byte order */ /* returns host byte order */
uint16_t bip_get_port(void); uint16_t bip_get_port(void);
uint16_t bip_get_broadcast_port(void);
/* use network byte order for setting */ /* use network byte order for setting */
void bip_set_addr(const uint8_t *net_address); void bip_set_addr(const uint8_t *net_address);
+28 -2
View File
@@ -25,6 +25,8 @@ static int BIP_Broadcast_Socket = -1;
/* port to use - stored here in network byte order */ /* port to use - stored here in network byte order */
/* Initialize to 0 - this will force initialization in demo apps */ /* Initialize to 0 - this will force initialization in demo apps */
static uint16_t BIP_Port; static uint16_t BIP_Port;
/* broadcast destination port to use */
static uint16_t BIP_Broadcast_Port;
/* IP address - stored here in network byte order */ /* IP address - stored here in network byte order */
static struct in_addr BIP_Address; static struct in_addr BIP_Address;
/* IP broadcast address - stored here in network byte order */ /* IP broadcast address - stored here in network byte order */
@@ -103,6 +105,15 @@ void bip_set_port(uint16_t port)
BIP_Port = htons(port); BIP_Port = htons(port);
} }
/**
* @brief Set the BACnet IPv4 UDP broadcast destination port number
* @param port - IPv4 UDP port number - in host byte order
*/
void bip_set_broadcast_port(uint16_t port)
{
BIP_Broadcast_Port = htons(port);
}
/** /**
* @brief Get the BACnet IPv4 UDP port number * @brief Get the BACnet IPv4 UDP port number
* @return IPv4 UDP port number - in host byte order * @return IPv4 UDP port number - in host byte order
@@ -112,6 +123,19 @@ uint16_t bip_get_port(void)
return ntohs(BIP_Port); return ntohs(BIP_Port);
} }
/**
* @brief Get the BACnet IPv4 UDP broadcast destination port number
* @return IPv4 UDP port number - in host byte order
*/
uint16_t bip_get_broadcast_port(void)
{
if (BIP_Broadcast_Port) {
return ntohs(BIP_Broadcast_Port);
}
return ntohs(BIP_Port);
}
/** /**
* @brief Get the IPv4 address for my interface. Used for sending src address. * @brief Get the IPv4 address for my interface. Used for sending src address.
* @param addr - BACnet datalink address * @param addr - BACnet datalink address
@@ -143,11 +167,12 @@ void bip_get_my_address(BACNET_ADDRESS *addr)
void bip_get_broadcast_address(BACNET_ADDRESS *dest) void bip_get_broadcast_address(BACNET_ADDRESS *dest)
{ {
int i = 0; /* counter */ int i = 0; /* counter */
uint16_t port = htons(bip_get_broadcast_port());
if (dest) { if (dest) {
dest->mac_len = 6; dest->mac_len = 6;
memcpy(&dest->mac[0], &BIP_Broadcast_Addr.s_addr, 4); memcpy(&dest->mac[0], &BIP_Broadcast_Addr.s_addr, 4);
memcpy(&dest->mac[4], &BIP_Port, 2); memcpy(&dest->mac[4], &port, 2);
dest->net = BACNET_BROADCAST_NETWORK; dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* no SLEN */ dest->len = 0; /* no SLEN */
for (i = 0; i < MAX_MAC_LEN; i++) { for (i = 0; i < MAX_MAC_LEN; i++) {
@@ -207,7 +232,7 @@ bool bip_get_broadcast_addr(BACNET_IP_ADDRESS *addr)
{ {
if (addr) { if (addr) {
memcpy(&addr->address[0], &BIP_Broadcast_Addr.s_addr, 4); memcpy(&addr->address[0], &BIP_Broadcast_Addr.s_addr, 4);
addr->port = ntohs(BIP_Port); addr->port = bip_get_broadcast_port();
} }
return true; return true;
@@ -814,6 +839,7 @@ void bip_cleanup(void)
/* these were set non-zero during interface configuration */ /* these were set non-zero during interface configuration */
BIP_Address.s_addr = 0; BIP_Address.s_addr = 0;
BIP_Broadcast_Addr.s_addr = 0; BIP_Broadcast_Addr.s_addr = 0;
BIP_Broadcast_Port = 0;
return; return;
} }
+30 -2
View File
@@ -23,6 +23,8 @@
static uint8_t BIP_Socket = MAX_SOCK_NUM; static uint8_t BIP_Socket = MAX_SOCK_NUM;
static uint16_t BIP_Port = 0; static uint16_t BIP_Port = 0;
/* broadcast destination port to use */
static uint16_t BIP_Broadcast_Port = 0;
static uint8_t BIP_Address[4] = { 0, 0, 0, 0 }; static uint8_t BIP_Address[4] = { 0, 0, 0, 0 };
static uint8_t BIP_Broadcast_Address[4] = { 0, 0, 0, 0 }; static uint8_t BIP_Broadcast_Address[4] = { 0, 0, 0, 0 };
@@ -130,6 +132,15 @@ void bip_set_port(uint16_t port)
BIP_Port = port; BIP_Port = port;
} }
/**
* @brief Store the UDP broadcast destination port used by BACnet/IP
* @param port UDP port number
*/
void bip_set_broadcast_port(uint16_t port)
{
BIP_Broadcast_Port = port;
}
/** /**
* @brief Get the UDP port used by BACnet/IP * @brief Get the UDP port used by BACnet/IP
* @return UDP port number * @return UDP port number
@@ -139,6 +150,19 @@ uint16_t bip_get_port(void)
return BIP_Port; return BIP_Port;
} }
/**
* @brief Get the UDP broadcast destination port used by BACnet/IP
* @return UDP port number
*/
uint16_t bip_get_broadcast_port(void)
{
if (BIP_Broadcast_Port) {
return BIP_Broadcast_Port;
}
return BIP_Port;
}
/** /**
* @brief Decode a BACnet/IP MAC address into IPv4 address and port parts * @brief Decode a BACnet/IP MAC address into IPv4 address and port parts
* @param bac_addr source BACnet address * @param bac_addr source BACnet address
@@ -193,7 +217,7 @@ int bip_send_pdu(
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
address[i] = BIP_Broadcast_Address[i]; address[i] = BIP_Broadcast_Address[i];
} }
port = BIP_Port; port = bip_get_broadcast_port();
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU; mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
} else if (dest->mac_len == 6) { } else if (dest->mac_len == 6) {
bip_decode_bip_address(dest, address, &port); bip_decode_bip_address(dest, address, &port);
@@ -330,7 +354,11 @@ void bip_get_broadcast_address(BACNET_ADDRESS *dest)
if (dest) { if (dest) {
dest->mac_len = 6; dest->mac_len = 6;
memcpy(&dest->mac[0], &BIP_Broadcast_Address[0], 4); memcpy(&dest->mac[0], &BIP_Broadcast_Address[0], 4);
memcpy(&dest->mac[4], &BIP_Port, 2); {
uint16_t port = bip_get_broadcast_port();
memcpy(&dest->mac[4], &port, 2);
}
dest->net = BACNET_BROADCAST_NETWORK; dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; dest->len = 0;
} }
+12
View File
@@ -172,12 +172,24 @@ uint16_t bip_receive(
*/ */
void bip_set_port(uint16_t port); void bip_set_port(uint16_t port);
/**
* @brief Store the UDP broadcast destination port used by BACnet/IP
* @param port UDP port number
*/
void bip_set_broadcast_port(uint16_t port);
/** /**
* @brief Get the UDP port used by BACnet/IP * @brief Get the UDP port used by BACnet/IP
* @return UDP port number * @return UDP port number
*/ */
uint16_t bip_get_port(void); uint16_t bip_get_port(void);
/**
* @brief Get the UDP broadcast destination port used by BACnet/IP
* @return UDP port number
*/
uint16_t bip_get_broadcast_port(void);
/** /**
* @brief Store the local IPv4 address * @brief Store the local IPv4 address
* @param net_address pointer to the 4-byte address * @param net_address pointer to the 4-byte address
+2
View File
@@ -93,4 +93,6 @@ void bip_cleanup(void)
if (bip_valid()) { if (bip_valid()) {
bip_socket_cleanup(); bip_socket_cleanup();
} }
bip_set_broadcast_port(0);
} }
+28 -2
View File
@@ -41,6 +41,8 @@ static int BIP_Broadcast_Socket = -1;
/* port to use - stored here in network byte order */ /* port to use - stored here in network byte order */
/* Initialize to 0 - this will force initialization in demo apps */ /* Initialize to 0 - this will force initialization in demo apps */
static uint16_t BIP_Port; static uint16_t BIP_Port;
/* broadcast destination port to use */
static uint16_t BIP_Broadcast_Port;
/* IP address - stored here in network byte order */ /* IP address - stored here in network byte order */
static struct in_addr BIP_Address; static struct in_addr BIP_Address;
/* IP broadcast address - stored here in network byte order */ /* IP broadcast address - stored here in network byte order */
@@ -119,6 +121,15 @@ void bip_set_port(uint16_t port)
BIP_Port = htons(port); BIP_Port = htons(port);
} }
/**
* @brief Set the BACnet IPv4 UDP broadcast destination port number
* @param port - IPv4 UDP port number - in host byte order
*/
void bip_set_broadcast_port(uint16_t port)
{
BIP_Broadcast_Port = htons(port);
}
/** /**
* @brief Get the BACnet IPv4 UDP port number * @brief Get the BACnet IPv4 UDP port number
* @return IPv4 UDP port number - in host byte order * @return IPv4 UDP port number - in host byte order
@@ -128,6 +139,19 @@ uint16_t bip_get_port(void)
return ntohs(BIP_Port); return ntohs(BIP_Port);
} }
/**
* @brief Get the BACnet IPv4 UDP broadcast destination port number
* @return IPv4 UDP port number - in host byte order
*/
uint16_t bip_get_broadcast_port(void)
{
if (BIP_Broadcast_Port) {
return ntohs(BIP_Broadcast_Port);
}
return ntohs(BIP_Port);
}
/** /**
* @brief Get the IPv4 address for my interface. Used for sending src address. * @brief Get the IPv4 address for my interface. Used for sending src address.
* @param addr - BACnet datalink address * @param addr - BACnet datalink address
@@ -159,11 +183,12 @@ void bip_get_my_address(BACNET_ADDRESS *addr)
void bip_get_broadcast_address(BACNET_ADDRESS *dest) void bip_get_broadcast_address(BACNET_ADDRESS *dest)
{ {
int i = 0; /* counter */ int i = 0; /* counter */
uint16_t port = htons(bip_get_broadcast_port());
if (dest) { if (dest) {
dest->mac_len = 6; dest->mac_len = 6;
memcpy(&dest->mac[0], &BIP_Broadcast_Addr.s_addr, 4); memcpy(&dest->mac[0], &BIP_Broadcast_Addr.s_addr, 4);
memcpy(&dest->mac[4], &BIP_Port, 2); memcpy(&dest->mac[4], &port, 2);
dest->net = BACNET_BROADCAST_NETWORK; dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* no SLEN */ dest->len = 0; /* no SLEN */
for (i = 0; i < MAX_MAC_LEN; i++) { for (i = 0; i < MAX_MAC_LEN; i++) {
@@ -223,7 +248,7 @@ bool bip_get_broadcast_addr(BACNET_IP_ADDRESS *addr)
{ {
if (addr) { if (addr) {
memcpy(&addr->address[0], &BIP_Broadcast_Addr.s_addr, 4); memcpy(&addr->address[0], &BIP_Broadcast_Addr.s_addr, 4);
addr->port = ntohs(BIP_Port); addr->port = bip_get_broadcast_port();
} }
return true; return true;
@@ -1007,6 +1032,7 @@ void bip_cleanup(void)
BIP_Address.s_addr = 0; BIP_Address.s_addr = 0;
BIP_Broadcast_Addr.s_addr = 0; BIP_Broadcast_Addr.s_addr = 0;
BIP_Netmask.s_addr = 0; BIP_Netmask.s_addr = 0;
BIP_Broadcast_Port = 0;
return; return;
} }
+43 -3
View File
@@ -24,6 +24,8 @@ static bool BIP_Port_Changed;
static BACNET_IP_ADDRESS BIP_Address; static BACNET_IP_ADDRESS BIP_Address;
/* Broadcast Address */ /* Broadcast Address */
static BACNET_IP_ADDRESS BIP_Broadcast_Address; static BACNET_IP_ADDRESS BIP_Broadcast_Address;
/* broadcast destination port to use */
static uint16_t BIP_Broadcast_Port;
/* lwIP socket, of sorts */ /* lwIP socket, of sorts */
static struct udp_pcb *Server_upcb; static struct udp_pcb *Server_upcb;
/* track packets for diagnostics */ /* track packets for diagnostics */
@@ -89,7 +91,14 @@ bool bip_get_addr(BACNET_IP_ADDRESS *addr)
*/ */
bool bip_set_broadcast_addr(const BACNET_IP_ADDRESS *addr) bool bip_set_broadcast_addr(const BACNET_IP_ADDRESS *addr)
{ {
return bvlc_address_copy(&BIP_Broadcast_Address, addr); bool status = false;
status = bvlc_address_copy(&BIP_Broadcast_Address, addr);
if (status) {
BIP_Broadcast_Port = htons(addr->port);
}
return status;
} }
/** /**
@@ -99,7 +108,14 @@ bool bip_set_broadcast_addr(const BACNET_IP_ADDRESS *addr)
*/ */
bool bip_get_broadcast_addr(BACNET_IP_ADDRESS *addr) bool bip_get_broadcast_addr(BACNET_IP_ADDRESS *addr)
{ {
return bvlc_address_copy(addr, &BIP_Broadcast_Address); bool status = false;
status = bvlc_address_copy(addr, &BIP_Broadcast_Address);
if (status && addr) {
addr->port = ntohs(BIP_Broadcast_Port);
}
return status;
} }
/** /**
@@ -114,6 +130,16 @@ void bip_set_port(uint16_t port)
} }
} }
/**
* @brief Set the BACnet IPv4 UDP broadcast destination port number
* @param port - IPv4 UDP port number - in host byte order
*/
void bip_set_broadcast_port(uint16_t port)
{
BIP_Broadcast_Port = htons(port);
BIP_Broadcast_Address.port = BIP_Broadcast_Port;
}
/** /**
* @brief Determine if the BACnet IPv4 UDP port number changed * @brief Determine if the BACnet IPv4 UDP port number changed
* @return true of the BACnet IPv4 UDP port number changed * @return true of the BACnet IPv4 UDP port number changed
@@ -132,6 +158,19 @@ uint16_t bip_get_port(void)
return ntohs(BIP_Address.port); return ntohs(BIP_Address.port);
} }
/**
* @brief Get the BACnet IPv4 UDP broadcast destination port number
* @return IPv4 UDP port number - in host byte order
*/
uint16_t bip_get_broadcast_port(void)
{
if (BIP_Broadcast_Port) {
return ntohs(BIP_Broadcast_Port);
}
return ntohs(BIP_Address.port);
}
/** /**
* @brief Convert the BACnet IPv4 address * @brief Convert the BACnet IPv4 address
* @param address - IPv4 address from LwIP * @param address - IPv4 address from LwIP
@@ -321,11 +360,12 @@ void bip_get_my_address(BACNET_ADDRESS *my_address)
void bip_get_broadcast_address(BACNET_ADDRESS *dest) void bip_get_broadcast_address(BACNET_ADDRESS *dest)
{ {
int i = 0; /* counter */ int i = 0; /* counter */
uint16_t port = htons(bip_get_broadcast_port());
if (dest) { if (dest) {
dest->mac_len = 6; dest->mac_len = 6;
memcpy(&dest->mac[0], &BIP_Broadcast_Address.address, 4); memcpy(&dest->mac[0], &BIP_Broadcast_Address.address, 4);
memcpy(&dest->mac[4], &BIP_Address.port, 2); memcpy(&dest->mac[4], &port, 2);
dest->net = BACNET_BROADCAST_NETWORK; dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* no SLEN */ dest->len = 0; /* no SLEN */
for (i = 0; i < MAX_MAC_LEN; i++) { for (i = 0; i < MAX_MAC_LEN; i++) {
+2
View File
@@ -112,5 +112,7 @@ void bip_cleanup(void)
bip_socket_cleanup(); bip_socket_cleanup();
} }
bip_set_broadcast_port(0);
return; return;
} }
+22 -2
View File
@@ -26,6 +26,8 @@
static uint8_t BIP_Socket = MAX_SOCK_NUM; static uint8_t BIP_Socket = MAX_SOCK_NUM;
/* port to use - stored in network byte order */ /* port to use - stored in network byte order */
static uint16_t BIP_Port = 0; static uint16_t BIP_Port = 0;
/* broadcast destination port to use */
static uint16_t BIP_Broadcast_Port = 0;
/* IP Address - stored in network byte order */ /* IP Address - stored in network byte order */
static uint8_t BIP_Address[4] = { 0, 0, 0, 0 }; static uint8_t BIP_Address[4] = { 0, 0, 0, 0 };
/* Broadcast Address - stored in network byte order */ /* Broadcast Address - stored in network byte order */
@@ -106,12 +108,26 @@ void bip_set_port(uint16_t port)
BIP_Port = port; BIP_Port = port;
} }
void bip_set_broadcast_port(uint16_t port)
{
BIP_Broadcast_Port = port;
}
/* returns network byte order */ /* returns network byte order */
uint16_t bip_get_port(void) uint16_t bip_get_port(void)
{ {
return BIP_Port; return BIP_Port;
} }
uint16_t bip_get_broadcast_port(void)
{
if (BIP_Broadcast_Port) {
return BIP_Broadcast_Port;
}
return BIP_Port;
}
static int bip_decode_bip_address( static int bip_decode_bip_address(
const BACNET_ADDRESS *bac_addr, uint8_t *address, uint16_t *port) const BACNET_ADDRESS *bac_addr, uint8_t *address, uint16_t *port)
{ {
@@ -161,7 +177,7 @@ int bip_send_pdu(
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
address[i] = BIP_Broadcast_Address[i]; address[i] = BIP_Broadcast_Address[i];
} }
port = BIP_Port; port = bip_get_broadcast_port();
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU; mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
#ifdef DEBUG #ifdef DEBUG
fprintf( fprintf(
@@ -349,7 +365,11 @@ void bip_get_broadcast_address(BACNET_ADDRESS *dest)
if (dest) { if (dest) {
dest->mac_len = 6; dest->mac_len = 6;
memcpy(&dest->mac[0], &BIP_Broadcast_Address, 4); memcpy(&dest->mac[0], &BIP_Broadcast_Address, 4);
memcpy(&dest->mac[4], &BIP_Port, 2); {
uint16_t port = bip_get_broadcast_port();
memcpy(&dest->mac[4], &port, 2);
}
dest->net = BACNET_BROADCAST_NETWORK; dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* no SLEN */ dest->len = 0; /* no SLEN */
for (i = 0; i < MAX_MAC_LEN; i++) { for (i = 0; i < MAX_MAC_LEN; i++) {
+2
View File
@@ -108,7 +108,9 @@ uint16_t bip_receive(
/* use host byte order for setting */ /* use host byte order for setting */
void bip_set_port(uint16_t port); void bip_set_port(uint16_t port);
void bip_set_broadcast_port(uint16_t port);
uint16_t bip_get_port(void); uint16_t bip_get_port(void);
uint16_t bip_get_broadcast_port(void);
/* use network byte order for setting */ /* use network byte order for setting */
void bip_set_addr(const uint8_t *net_address); void bip_set_addr(const uint8_t *net_address);
+22 -2
View File
@@ -15,6 +15,8 @@
static int BIP_Socket = -1; static int BIP_Socket = -1;
/* port to use - stored in host byte order */ /* port to use - stored in host byte order */
static uint16_t BIP_Port = 0xBAC0U; static uint16_t BIP_Port = 0xBAC0U;
/* broadcast destination port to use */
static uint16_t BIP_Broadcast_Port;
/* IP Address - stored in host byte order */ /* IP Address - stored in host byte order */
static struct in_addr BIP_Address; static struct in_addr BIP_Address;
/* Broadcast Address - stored in host byte order */ /* Broadcast Address - stored in host byte order */
@@ -40,6 +42,7 @@ void bip_cleanup(void)
/* if (bip_valid()) */ /* if (bip_valid()) */
/* close(BIP_Socket); */ /* close(BIP_Socket); */
BIP_Socket = -1; BIP_Socket = -1;
BIP_Broadcast_Port = 0;
return; return;
} }
@@ -76,12 +79,28 @@ void bip_set_port(uint16_t port)
BIP_Port = port; BIP_Port = port;
} }
/* set using host byte order */
void bip_set_broadcast_port(uint16_t port)
{
BIP_Broadcast_Port = port;
}
/* returns host byte order */ /* returns host byte order */
uint16_t bip_get_port(void) uint16_t bip_get_port(void)
{ {
return BIP_Port; return BIP_Port;
} }
/* returns host byte order */
uint16_t bip_get_broadcast_port(void)
{
if (BIP_Broadcast_Port) {
return BIP_Broadcast_Port;
}
return BIP_Port;
}
/* function to send a packet out the BACnet/IP socket (Annex J) */ /* function to send a packet out the BACnet/IP socket (Annex J) */
/* returns number of bytes sent on success, negative number on failure */ /* returns number of bytes sent on success, negative number on failure */
int bip_send_pdu(BACNET_ADDRESS *dest, /* destination address */ int bip_send_pdu(BACNET_ADDRESS *dest, /* destination address */
@@ -116,7 +135,7 @@ int bip_send_pdu(BACNET_ADDRESS *dest, /* destination address */
/* broadcast */ /* broadcast */
else if (dest->mac_len == 0) { else if (dest->mac_len == 0) {
bip_dest.sin_addr.s_addr = BIP_Broadcast_Address.s_addr; bip_dest.sin_addr.s_addr = BIP_Broadcast_Address.s_addr;
bip_dest.sin_port = htons(BIP_Port); bip_dest.sin_port = htons(bip_get_broadcast_port());
memset(&(bip_dest.sin_zero), '\0', 8); memset(&(bip_dest.sin_zero), '\0', 8);
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU; mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
} else } else
@@ -197,7 +216,8 @@ void bip_get_broadcast_address(BACNET_ADDRESS *dest)
dest->mac_len = 6; dest->mac_len = 6;
(void)encode_unsigned32( (void)encode_unsigned32(
&dest->mac[0], htonl(BIP_Broadcast_Address.s_addr)); &dest->mac[0], htonl(BIP_Broadcast_Address.s_addr));
(void)encode_unsigned16(&dest->mac[4], htons(BIP_Port)); (void)encode_unsigned16(
&dest->mac[4], htons(bip_get_broadcast_port()));
dest->net = BACNET_BROADCAST_NETWORK; dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* no SLEN */ dest->len = 0; /* no SLEN */
for (i = 0; i < MAX_MAC_LEN; i++) { for (i = 0; i < MAX_MAC_LEN; i++) {
+29 -2
View File
@@ -29,6 +29,9 @@ static bool BIP_Initialized;
/* port to use - stored here in network byte order */ /* port to use - stored here in network byte order */
/* Initialize to 0 - this will force initialization in demo apps */ /* Initialize to 0 - this will force initialization in demo apps */
static uint16_t BIP_Port; static uint16_t BIP_Port;
/* broadcast destination port to use */
/* Initialize to 0 - this will force initialization in demo apps */
static uint16_t BIP_Broadcast_Port;
/* IP address - stored here in network byte order */ /* IP address - stored here in network byte order */
static struct in_addr BIP_Address; static struct in_addr BIP_Address;
/* IP broadcast address - stored here in network byte order */ /* IP broadcast address - stored here in network byte order */
@@ -259,6 +262,15 @@ void bip_set_port(uint16_t port)
BIP_Port = htons(port); BIP_Port = htons(port);
} }
/**
* @brief Set the BACnet IPv4 UDP broadcast destination port number
* @param port - IPv4 UDP port number - in host byte order
*/
void bip_set_broadcast_port(uint16_t port)
{
BIP_Broadcast_Port = htons(port);
}
/** /**
* @brief Get the BACnet IPv4 UDP port number * @brief Get the BACnet IPv4 UDP port number
* @return IPv4 UDP port number - in host byte order * @return IPv4 UDP port number - in host byte order
@@ -268,6 +280,19 @@ uint16_t bip_get_port(void)
return ntohs(BIP_Port); return ntohs(BIP_Port);
} }
/**
* @brief Get the BACnet IPv4 UDP broadcast destination port number
* @return IPv4 UDP port number - in host byte order
*/
uint16_t bip_get_broadcast_port(void)
{
if (BIP_Broadcast_Port) {
return ntohs(BIP_Broadcast_Port);
}
return ntohs(BIP_Port);
}
/** /**
* @brief Get the IPv4 address for my interface. Used for sending src address. * @brief Get the IPv4 address for my interface. Used for sending src address.
* @param addr - BACnet datalink address * @param addr - BACnet datalink address
@@ -299,11 +324,12 @@ void bip_get_my_address(BACNET_ADDRESS *addr)
void bip_get_broadcast_address(BACNET_ADDRESS *dest) void bip_get_broadcast_address(BACNET_ADDRESS *dest)
{ {
int i = 0; /* counter */ int i = 0; /* counter */
uint16_t port = htons(bip_get_broadcast_port());
if (dest) { if (dest) {
dest->mac_len = 6; dest->mac_len = 6;
memcpy(&dest->mac[0], &BIP_Broadcast_Addr.s_addr, 4); memcpy(&dest->mac[0], &BIP_Broadcast_Addr.s_addr, 4);
memcpy(&dest->mac[4], &BIP_Port, 2); memcpy(&dest->mac[4], &port, 2);
dest->net = BACNET_BROADCAST_NETWORK; dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* no SLEN */ dest->len = 0; /* no SLEN */
for (i = 0; i < MAX_MAC_LEN; i++) { for (i = 0; i < MAX_MAC_LEN; i++) {
@@ -363,7 +389,7 @@ bool bip_get_broadcast_addr(BACNET_IP_ADDRESS *addr)
{ {
if (addr) { if (addr) {
memcpy(&addr->address[0], &BIP_Broadcast_Addr.s_addr, 4); memcpy(&addr->address[0], &BIP_Broadcast_Addr.s_addr, 4);
addr->port = ntohs(BIP_Port); addr->port = bip_get_broadcast_port();
} }
return true; return true;
@@ -940,6 +966,7 @@ void bip_cleanup(void)
/* these were set non-zero during interface configuration */ /* these were set non-zero during interface configuration */
BIP_Address.s_addr = 0; BIP_Address.s_addr = 0;
BIP_Broadcast_Addr.s_addr = 0; BIP_Broadcast_Addr.s_addr = 0;
BIP_Broadcast_Port = 0;
return; return;
} }
+6
View File
@@ -71,6 +71,9 @@ uint16_t bip_receive(
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
void bip_set_port(uint16_t port); void bip_set_port(uint16_t port);
BACNET_STACK_EXPORT
void bip_set_broadcast_port(uint16_t port);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
bool bip_port_changed(void); bool bip_port_changed(void);
@@ -78,6 +81,9 @@ bool bip_port_changed(void);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
uint16_t bip_get_port(void); uint16_t bip_get_port(void);
BACNET_STACK_EXPORT
uint16_t bip_get_broadcast_port(void);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
bool bip_set_addr(const BACNET_IP_ADDRESS *addr); bool bip_set_addr(const BACNET_IP_ADDRESS *addr);
+6
View File
@@ -404,6 +404,10 @@ static void dlenv_network_port_bip_init(uint32_t instance)
bip_set_port(0xBAC0); bip_set_port(0xBAC0);
} }
} }
pEnv = getenv("BACNET_IP_BROADCAST_PORT");
if (pEnv) {
bip_set_broadcast_port((uint16_t)strtol(pEnv, NULL, 0));
}
pEnv = getenv("BACNET_IP_BROADCAST_BIND_ADDR"); pEnv = getenv("BACNET_IP_BROADCAST_BIND_ADDR");
if (pEnv) { if (pEnv) {
bip_set_broadcast_binding(pEnv); bip_set_broadcast_binding(pEnv);
@@ -1168,6 +1172,8 @@ bool dlenv_register_device(uint8_t port_type, bool wait_until_connected)
* - BACDL_BIP: (BACnet/IP) * - BACDL_BIP: (BACnet/IP)
* - BACNET_IP_PORT - UDP/IP port number (0..65534) used for BACnet/IP * - BACNET_IP_PORT - UDP/IP port number (0..65534) used for BACnet/IP
* communications. Default is 47808 (0xBAC0). * communications. Default is 47808 (0xBAC0).
* - BACNET_IP_BROADCAST_PORT - UDP/IP destination port number (0..65534)
* used for BACnet/IP broadcasts. Default is BACNET_IP_PORT.
* - BACNET_BBMD_PORT - UDP/IP port number (0..65534) used for Foreign * - BACNET_BBMD_PORT - UDP/IP port number (0..65534) used for Foreign
* Device Registration. Defaults to 47808 (0xBAC0). * Device Registration. Defaults to 47808 (0xBAC0).
* - BACNET_BBMD_TIMETOLIVE - number of seconds used in Foreign Device * - BACNET_BBMD_TIMETOLIVE - number of seconds used in Foreign Device
+3
View File
@@ -243,6 +243,7 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
list(APPEND testdirs list(APPEND testdirs
ports/linux/bsc_event ports/linux/bsc_event
ports/linux/bip_subnet ports/linux/bip_subnet
ports/bip_broadcast_port
) )
elseif(WIN32) elseif(WIN32)
@@ -250,12 +251,14 @@ elseif(WIN32)
list(APPEND testdirs list(APPEND testdirs
ports/win32/bsc_event ports/win32/bsc_event
ports/bip_broadcast_port
) )
elseif(APPLE) elseif(APPLE)
message(STATUS "Added ports specific tests for APPLE") message(STATUS "Added ports specific tests for APPLE")
list(APPEND testdirs list(APPEND testdirs
ports/bsd/bsc_event ports/bsd/bsc_event
ports/bip_broadcast_port
) )
endif() endif()
+29
View File
@@ -186,6 +186,34 @@ static void test_Initiate_Original_Broadcast_NPDU(void)
test_cleanup(); test_cleanup();
} }
static void test_Initiate_Original_Broadcast_NPDU_Uses_Broadcast_Port(void)
{
uint8_t pdu[MAX_APDU] = { 0 };
int npdu_len = 0;
int apdu_len = 0;
int pdu_len = 0;
BACNET_ADDRESS dest = { 0 };
BACNET_NPDU_DATA npdu_data = { 0 };
test_setup();
IUT.BIP_Addr.port = 0xBAC1U;
IUT.BIP_Broadcast_Addr.port = 0xBAC2U;
dest.net = BACNET_BROADCAST_NETWORK;
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
npdu_len = npdu_encode_pdu(&pdu[0], &dest, &IUT.BACnet_Address, &npdu_data);
apdu_len = iam_encode_apdu(
&pdu[npdu_len], IUT.Device_ID, MAX_APDU, SEGMENTATION_NONE,
BACNET_VENDOR_ID);
pdu_len = npdu_len + apdu_len;
bvlc_send_pdu(&dest, &npdu_data, pdu, pdu_len);
assert(Test_Sent_Message_Type == BVLC_ORIGINAL_BROADCAST_NPDU);
assert(Test_Sent_Message_Dest.port == IUT.BIP_Broadcast_Addr.port);
assert(Test_Sent_Message_Dest.port != IUT.BIP_Addr.port);
test_cleanup();
}
static void test_BBMD_Result(void) static void test_BBMD_Result(void)
{ {
int result = 0; int result = 0;
@@ -232,6 +260,7 @@ int main(void)
/* individual tests */ /* individual tests */
test_BBMD_Result(); test_BBMD_Result();
test_Initiate_Original_Broadcast_NPDU(); test_Initiate_Original_Broadcast_NPDU();
test_Initiate_Original_Broadcast_NPDU_Uses_Broadcast_Port();
return 0; return 0;
} }
+10
View File
@@ -80,6 +80,11 @@ void bip_set_port(uint16_t port)
ztest_check_expected_value(port); ztest_check_expected_value(port);
} }
void bip_set_broadcast_port(uint16_t port)
{
ztest_check_expected_value(port);
}
bool bip_port_changed(void) bool bip_port_changed(void)
{ {
return ztest_get_return_value(); return ztest_get_return_value();
@@ -90,6 +95,11 @@ uint16_t bip_get_port(void)
return ztest_get_return_value(); return ztest_get_return_value();
} }
uint16_t bip_get_broadcast_port(void)
{
return ztest_get_return_value();
}
bool bip_set_addr(const BACNET_IP_ADDRESS *addr) bool bip_set_addr(const BACNET_IP_ADDRESS *addr)
{ {
ztest_check_expected_data(addr, sizeof(BACNET_IP_ADDRESS)); ztest_check_expected_data(addr, sizeof(BACNET_IP_ADDRESS));
@@ -0,0 +1,63 @@
# SPDX-License-Identifier: MIT
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
get_filename_component(basename ${CMAKE_CURRENT_SOURCE_DIR} NAME)
project(test_${basename}
VERSION 1.0.0
LANGUAGES C)
string(REGEX REPLACE
"/test/ports/[a-zA-Z_/-]*$"
"/src"
SRC_DIR
${CMAKE_CURRENT_SOURCE_DIR})
string(REGEX REPLACE
"/test/ports/[a-zA-Z_/-]*$"
"/ports"
PORTS_DIR
${CMAKE_CURRENT_SOURCE_DIR})
string(REGEX REPLACE
"/test/ports/[a-zA-Z_/-]*$"
"/test"
TST_DIR
${CMAKE_CURRENT_SOURCE_DIR})
set(ZTST_DIR "${TST_DIR}/ztest/src")
add_compile_definitions(
BACNET_BIG_ENDIAN=0
CONFIG_ZTEST=1
BACNET_STACK_DEPRECATED_DISABLE=1
)
include_directories(
${SRC_DIR}
${TST_DIR}/ztest/include
)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(PORT_BIP_SOURCE ${PORTS_DIR}/linux/bip-init.c)
find_package(Threads REQUIRED)
elseif(WIN32)
set(PORT_BIP_SOURCE ${PORTS_DIR}/win32/bip-init.c)
add_compile_definitions(BACNET_PORT=win32)
elseif(APPLE)
set(PORT_BIP_SOURCE ${PORTS_DIR}/bsd/bip-init.c)
else()
message(FATAL_ERROR "bip_broadcast_port test is only supported on Linux, macOS, and Windows")
endif()
add_executable(${PROJECT_NAME}
${PORT_BIP_SOURCE}
${SRC_DIR}/bacnet/basic/sys/debug.c
./src/bvlc_stubs.c
./src/main.c
${ZTST_DIR}/ztest_mock.c
${ZTST_DIR}/ztest.c
)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
target_link_libraries(${PROJECT_NAME} Threads::Threads)
elseif(WIN32)
target_link_libraries(${PROJECT_NAME} ws2_32)
endif()
@@ -0,0 +1,48 @@
/* SPDX-License-Identifier: MIT */
#include "bacnet/basic/bbmd/h_bbmd.h"
int bvlc_handler(
BACNET_IP_ADDRESS *addr,
BACNET_ADDRESS *src,
uint8_t *npdu,
uint16_t npdu_len)
{
(void)addr;
(void)src;
(void)npdu;
(void)npdu_len;
return 0;
}
int bvlc_broadcast_handler(
BACNET_IP_ADDRESS *addr,
BACNET_ADDRESS *src,
uint8_t *npdu,
uint16_t npdu_len)
{
(void)addr;
(void)src;
(void)npdu;
(void)npdu_len;
return 0;
}
int bvlc_send_pdu(
const BACNET_ADDRESS *dest,
const BACNET_NPDU_DATA *npdu_data,
const uint8_t *pdu,
unsigned pdu_len)
{
(void)dest;
(void)npdu_data;
(void)pdu;
(void)pdu_len;
return 0;
}
void bvlc_init(void)
{
}
+62
View File
@@ -0,0 +1,62 @@
/**
* @file
* @brief Tests for separating BACnet/IP bind and broadcast destination ports
* @copyright SPDX-License-Identifier: MIT
*/
#include <zephyr/ztest.h>
#include <bacnet/datalink/bip.h>
static uint16_t bip_address_port(const BACNET_ADDRESS *address)
{
return ((uint16_t)address->mac[4] << 8) | address->mac[5];
}
static void test_broadcast_port_defaults_to_bind_port(void)
{
BACNET_ADDRESS broadcast = { 0 };
BACNET_IP_ADDRESS broadcast_addr = { 0 };
bip_cleanup();
bip_set_port(0xBAC1U);
zassert_equal(bip_get_port(), 0xBAC1U, NULL);
zassert_equal(bip_get_broadcast_port(), 0xBAC1U, NULL);
bip_get_broadcast_address(&broadcast);
zassert_equal(bip_address_port(&broadcast), 0xBAC1U, NULL);
zassert_true(bip_get_broadcast_addr(&broadcast_addr), NULL);
zassert_equal(broadcast_addr.port, 0xBAC1U, NULL);
}
static void test_broadcast_port_can_differ_from_bind_port(void)
{
BACNET_ADDRESS local = { 0 };
BACNET_ADDRESS broadcast = { 0 };
BACNET_IP_ADDRESS broadcast_addr = { 0 };
bip_cleanup();
bip_set_port(0xBAC1U);
bip_set_broadcast_port(0xBAC2U);
zassert_equal(bip_get_port(), 0xBAC1U, NULL);
zassert_equal(bip_get_broadcast_port(), 0xBAC2U, NULL);
bip_get_my_address(&local);
zassert_equal(bip_address_port(&local), 0xBAC1U, NULL);
bip_get_broadcast_address(&broadcast);
zassert_equal(bip_address_port(&broadcast), 0xBAC2U, NULL);
zassert_true(bip_get_broadcast_addr(&broadcast_addr), NULL);
zassert_equal(broadcast_addr.port, 0xBAC2U, NULL);
}
void test_main(void)
{
ztest_test_suite(
bip_broadcast_port_test,
ztest_unit_test(test_broadcast_port_defaults_to_bind_port),
ztest_unit_test(test_broadcast_port_can_differ_from_bind_port));
ztest_run_test_suite(bip_broadcast_port_test);
}