BIP: add option - listen to broadcast on a separate socket (#293)
* BIP: add socket to listen to broadcast packets for Linux/Windows/BSD/Zephyr * BIP: added BVLC broadcast handler to drop a packet when confirmed broadcast request is sent. * https://sourceforge.net/p/bacnet/bugs/65/
This commit is contained in:
@@ -13,7 +13,6 @@ BACDL_BIP=1 - chooses BACnet/IP for the datalink layer
|
|||||||
BACDL_ETHERNET=0 - chooses BACnet Ethernet for the datalink layer
|
BACDL_ETHERNET=0 - chooses BACnet Ethernet for the datalink layer
|
||||||
BACDL_ARCNET=0 - chooses BACnet ARCNET for the datalink layer
|
BACDL_ARCNET=0 - chooses BACnet ARCNET for the datalink layer
|
||||||
BACDL_MSTP=0 - chooses BACnet MS/TP for the datalink layer
|
BACDL_MSTP=0 - chooses BACnet MS/TP for the datalink layer
|
||||||
USE_INADDR=1 - uses INADDR_BROADCAST for broadcast rather than CLASSx
|
|
||||||
TSM_ENABLED=1 - enables the Transaction State Machine for clients
|
TSM_ENABLED=1 - enables the Transaction State Machine for clients
|
||||||
BIP_DEBUG=1 - enables print statements for debugging
|
BIP_DEBUG=1 - enables print statements for debugging
|
||||||
In Visual C++, add a Preprocessor Definition by:
|
In Visual C++, add a Preprocessor Definition by:
|
||||||
|
|||||||
+73
-36
@@ -47,8 +47,9 @@
|
|||||||
* @brief Initializes BACnet/IP interface (BSD/MAC OS X).
|
* @brief Initializes BACnet/IP interface (BSD/MAC OS X).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* unix socket */
|
/* unix sockets */
|
||||||
static int BIP_Socket = -1;
|
static int BIP_Socket = -1;
|
||||||
|
static int BIP_Broadcast_Socket = -1;
|
||||||
|
|
||||||
/* NOTE: we store address and port in network byte order
|
/* NOTE: we store address and port in network byte order
|
||||||
since BACnet/IP uses network byte order for all address byte arrays
|
since BACnet/IP uses network byte order for all address byte arrays
|
||||||
@@ -315,6 +316,7 @@ uint16_t bip_receive(
|
|||||||
int received_bytes = 0;
|
int received_bytes = 0;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
uint16_t i = 0;
|
uint16_t i = 0;
|
||||||
|
int socket;
|
||||||
|
|
||||||
/* Make sure the socket is open */
|
/* Make sure the socket is open */
|
||||||
if (BIP_Socket < 0) {
|
if (BIP_Socket < 0) {
|
||||||
@@ -333,10 +335,15 @@ uint16_t bip_receive(
|
|||||||
}
|
}
|
||||||
FD_ZERO(&read_fds);
|
FD_ZERO(&read_fds);
|
||||||
FD_SET(BIP_Socket, &read_fds);
|
FD_SET(BIP_Socket, &read_fds);
|
||||||
max = BIP_Socket;
|
FD_SET(BIP_Broadcast_Socket, &read_fds);
|
||||||
|
|
||||||
|
max = BIP_Socket > BIP_Broadcast_Socket ? BIP_Socket : BIP_Broadcast_Socket;
|
||||||
|
|
||||||
/* see if there is a packet for us */
|
/* see if there is a packet for us */
|
||||||
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
|
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
|
||||||
received_bytes = recvfrom(max, (char *)&npdu[0], max_npdu, 0,
|
socket = FD_ISSET(BIP_Socket, &read_fds) ? BIP_Socket :
|
||||||
|
BIP_Broadcast_Socket;
|
||||||
|
received_bytes = recvfrom(socket, (char *)&npdu[0], max_npdu, 0,
|
||||||
(struct sockaddr *)&sin, &sin_len);
|
(struct sockaddr *)&sin, &sin_len);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -374,7 +381,9 @@ uint16_t bip_receive(
|
|||||||
debug_print_ipv4(
|
debug_print_ipv4(
|
||||||
"Received MPDU->", &sin.sin_addr, sin.sin_port, received_bytes);
|
"Received MPDU->", &sin.sin_addr, sin.sin_port, received_bytes);
|
||||||
/* pass the packet into the BBMD handler */
|
/* pass the packet into the BBMD handler */
|
||||||
offset = bvlc_handler(&addr, src, npdu, received_bytes);
|
offset = socket == BIP_Socket ?
|
||||||
|
bvlc_handler(&addr, src, npdu, received_bytes) :
|
||||||
|
bvlc_broadcast_handler(&addr, src, npdu, received_bytes);
|
||||||
if (offset > 0) {
|
if (offset > 0) {
|
||||||
npdu_len = received_bytes - offset;
|
npdu_len = received_bytes - offset;
|
||||||
debug_print_ipv4(
|
debug_print_ipv4(
|
||||||
@@ -556,6 +565,45 @@ void bip_set_interface(char *ifname)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int createSocket(struct sockaddr_in *sin)
|
||||||
|
{
|
||||||
|
int status = 0; /* return from socket lib calls */
|
||||||
|
int sockopt = 0;
|
||||||
|
int sock_fd = -1;
|
||||||
|
|
||||||
|
/* assumes that the driver has already been initialized */
|
||||||
|
sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (sock_fd < 0) {
|
||||||
|
return sock_fd;
|
||||||
|
}
|
||||||
|
/* Allow us to use the same socket for sending and receiving */
|
||||||
|
/* This makes sure that the src port is correct when sending */
|
||||||
|
sockopt = 1;
|
||||||
|
status = setsockopt(
|
||||||
|
sock_fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
|
||||||
|
if (status < 0) {
|
||||||
|
close(sock_fd);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/* allow us to send a broadcast */
|
||||||
|
status = setsockopt(
|
||||||
|
sock_fd, SOL_SOCKET, SO_BROADCAST, &sockopt, sizeof(sockopt));
|
||||||
|
if (status < 0) {
|
||||||
|
close(sock_fd);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bind the socket to the local port number and IP address */
|
||||||
|
status =
|
||||||
|
bind(sock_fd, (const struct sockaddr *)sin, sizeof(struct sockaddr));
|
||||||
|
if (status < 0) {
|
||||||
|
close(sock_fd);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock_fd;
|
||||||
|
}
|
||||||
|
|
||||||
/** Initialize the BACnet/IP services at the given interface.
|
/** Initialize the BACnet/IP services at the given interface.
|
||||||
* @ingroup DLBIP
|
* @ingroup DLBIP
|
||||||
* -# Gets the local IP address and local broadcast address from the system,
|
* -# Gets the local IP address and local broadcast address from the system,
|
||||||
@@ -575,9 +623,7 @@ void bip_set_interface(char *ifname)
|
|||||||
*/
|
*/
|
||||||
bool bip_init(char *ifname)
|
bool bip_init(char *ifname)
|
||||||
{
|
{
|
||||||
int status = 0; /* return from socket lib calls */
|
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
int sockopt = 0;
|
|
||||||
int sock_fd = -1;
|
int sock_fd = -1;
|
||||||
|
|
||||||
if (ifname) {
|
if (ifname) {
|
||||||
@@ -586,42 +632,28 @@ bool bip_init(char *ifname)
|
|||||||
} else {
|
} else {
|
||||||
bip_set_interface("en0");
|
bip_set_interface("en0");
|
||||||
}
|
}
|
||||||
/* assumes that the driver has already been initialized */
|
|
||||||
sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
BIP_Socket = sock_fd;
|
|
||||||
if (sock_fd < 0)
|
|
||||||
return false;
|
|
||||||
/* Allow us to use the same socket for sending and receiving */
|
|
||||||
/* This makes sure that the src port is correct when sending */
|
|
||||||
sockopt = 1;
|
|
||||||
status = setsockopt(
|
|
||||||
sock_fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
|
|
||||||
if (status < 0) {
|
|
||||||
close(sock_fd);
|
|
||||||
BIP_Socket = -1;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
/* allow us to send a broadcast */
|
|
||||||
status = setsockopt(
|
|
||||||
sock_fd, SOL_SOCKET, SO_BROADCAST, &sockopt, sizeof(sockopt));
|
|
||||||
if (status < 0) {
|
|
||||||
close(sock_fd);
|
|
||||||
BIP_Socket = -1;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* bind the socket to the local port number and IP address */
|
|
||||||
sin.sin_family = AF_INET;
|
sin.sin_family = AF_INET;
|
||||||
sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
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));
|
||||||
status =
|
|
||||||
bind(sock_fd, (const struct sockaddr *)&sin, sizeof(struct sockaddr));
|
|
||||||
if (status < 0) {
|
sin.sin_addr.s_addr = BIP_Address.s_addr;
|
||||||
close(sock_fd);
|
sock_fd = createSocket(&sin);
|
||||||
BIP_Socket = -1;
|
BIP_Socket = sock_fd;
|
||||||
|
if (sock_fd < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
sock_fd = createSocket(&sin);
|
||||||
|
BIP_Broadcast_Socket = sock_fd;
|
||||||
|
if (sock_fd < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bvlc_init();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,5 +678,10 @@ void bip_cleanup(void)
|
|||||||
}
|
}
|
||||||
BIP_Socket = -1;
|
BIP_Socket = -1;
|
||||||
|
|
||||||
|
if (BIP_Broadcast_Socket != -1) {
|
||||||
|
close(BIP_Broadcast_Socket);
|
||||||
|
}
|
||||||
|
BIP_Broadcast_Socket = -1;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,5 +111,4 @@ extern int bip_get_local_address_ioctl(
|
|||||||
char *ifname,
|
char *ifname,
|
||||||
struct in_addr *addr,
|
struct in_addr *addr,
|
||||||
int request);
|
int request);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+72
-38
@@ -59,8 +59,9 @@
|
|||||||
|
|
||||||
/** @file linux/bip-init.c Initializes BACnet/IP interface (Linux). */
|
/** @file linux/bip-init.c Initializes BACnet/IP interface (Linux). */
|
||||||
|
|
||||||
/* unix socket */
|
/* unix sockets */
|
||||||
static int BIP_Socket = -1;
|
static int BIP_Socket = -1;
|
||||||
|
static int BIP_Broadcast_Socket = -1;
|
||||||
|
|
||||||
/* NOTE: we store address and port in network byte order
|
/* NOTE: we store address and port in network byte order
|
||||||
since BACnet/IP uses network byte order for all address byte arrays
|
since BACnet/IP uses network byte order for all address byte arrays
|
||||||
@@ -331,6 +332,7 @@ uint16_t bip_receive(
|
|||||||
int received_bytes = 0;
|
int received_bytes = 0;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
uint16_t i = 0;
|
uint16_t i = 0;
|
||||||
|
int socket;
|
||||||
|
|
||||||
/* Make sure the socket is open */
|
/* Make sure the socket is open */
|
||||||
if (BIP_Socket < 0) {
|
if (BIP_Socket < 0) {
|
||||||
@@ -349,10 +351,15 @@ uint16_t bip_receive(
|
|||||||
}
|
}
|
||||||
FD_ZERO(&read_fds);
|
FD_ZERO(&read_fds);
|
||||||
FD_SET(BIP_Socket, &read_fds);
|
FD_SET(BIP_Socket, &read_fds);
|
||||||
max = BIP_Socket;
|
FD_SET(BIP_Broadcast_Socket, &read_fds);
|
||||||
|
|
||||||
|
max = BIP_Socket > BIP_Broadcast_Socket ? BIP_Socket : BIP_Broadcast_Socket;
|
||||||
|
|
||||||
/* see if there is a packet for us */
|
/* see if there is a packet for us */
|
||||||
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
|
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
|
||||||
received_bytes = recvfrom(max, (char *)&npdu[0], max_npdu, 0,
|
socket = FD_ISSET(BIP_Socket, &read_fds) ? BIP_Socket :
|
||||||
|
BIP_Broadcast_Socket;
|
||||||
|
received_bytes = recvfrom(socket, (char *)&npdu[0], max_npdu, 0,
|
||||||
(struct sockaddr *)&sin, &sin_len);
|
(struct sockaddr *)&sin, &sin_len);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -390,7 +397,9 @@ uint16_t bip_receive(
|
|||||||
debug_print_ipv4(
|
debug_print_ipv4(
|
||||||
"Received MPDU->", &sin.sin_addr, sin.sin_port, received_bytes);
|
"Received MPDU->", &sin.sin_addr, sin.sin_port, received_bytes);
|
||||||
/* pass the packet into the BBMD handler */
|
/* pass the packet into the BBMD handler */
|
||||||
offset = bvlc_handler(&addr, src, npdu, received_bytes);
|
offset = socket == BIP_Socket ?
|
||||||
|
bvlc_handler(&addr, src, npdu, received_bytes) :
|
||||||
|
bvlc_broadcast_handler(&addr, src, npdu, received_bytes);
|
||||||
if (offset > 0) {
|
if (offset > 0) {
|
||||||
npdu_len = received_bytes - offset;
|
npdu_len = received_bytes - offset;
|
||||||
debug_print_ipv4(
|
debug_print_ipv4(
|
||||||
@@ -736,6 +745,7 @@ void bip_set_interface(char *ifname)
|
|||||||
{
|
{
|
||||||
struct in_addr local_address;
|
struct in_addr local_address;
|
||||||
struct in_addr netmask;
|
struct in_addr netmask;
|
||||||
|
short flags;
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
|
||||||
/* setup local address */
|
/* setup local address */
|
||||||
@@ -766,6 +776,48 @@ void bip_set_interface(char *ifname)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int createSocket(struct sockaddr_in *sin)
|
||||||
|
{
|
||||||
|
int status = 0; /* return from socket lib calls */
|
||||||
|
int sockopt = 0;
|
||||||
|
int sock_fd = -1;
|
||||||
|
|
||||||
|
/* assumes that the driver has already been initialized */
|
||||||
|
sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (sock_fd < 0) {
|
||||||
|
return sock_fd;
|
||||||
|
}
|
||||||
|
/* Allow us to use the same socket for sending and receiving */
|
||||||
|
/* This makes sure that the src port is correct when sending */
|
||||||
|
sockopt = 1;
|
||||||
|
status = setsockopt(
|
||||||
|
sock_fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
|
||||||
|
if (status < 0) {
|
||||||
|
close(sock_fd);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/* allow us to send a broadcast */
|
||||||
|
status = setsockopt(
|
||||||
|
sock_fd, SOL_SOCKET, SO_BROADCAST, &sockopt, sizeof(sockopt));
|
||||||
|
if (status < 0) {
|
||||||
|
close(sock_fd);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/* Bind to the proper interface to send without default gateway */
|
||||||
|
setsockopt(sock_fd, SOL_SOCKET, SO_BINDTODEVICE, BIP_Interface_Name,
|
||||||
|
strlen(BIP_Interface_Name));
|
||||||
|
|
||||||
|
/* bind the socket to the local port number and IP address */
|
||||||
|
status =
|
||||||
|
bind(sock_fd, (const struct sockaddr *)sin, sizeof(struct sockaddr));
|
||||||
|
if (status < 0) {
|
||||||
|
close(sock_fd);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock_fd;
|
||||||
|
}
|
||||||
|
|
||||||
/** Initialize the BACnet/IP services at the given interface.
|
/** Initialize the BACnet/IP services at the given interface.
|
||||||
* @ingroup DLBIP
|
* @ingroup DLBIP
|
||||||
* -# Gets the local IP address and local broadcast address from the system,
|
* -# Gets the local IP address and local broadcast address from the system,
|
||||||
@@ -785,9 +837,7 @@ void bip_set_interface(char *ifname)
|
|||||||
*/
|
*/
|
||||||
bool bip_init(char *ifname)
|
bool bip_init(char *ifname)
|
||||||
{
|
{
|
||||||
int status = 0; /* return from socket lib calls */
|
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
int sockopt = 0;
|
|
||||||
int sock_fd = -1;
|
int sock_fd = -1;
|
||||||
|
|
||||||
if (ifname) {
|
if (ifname) {
|
||||||
@@ -802,46 +852,25 @@ bool bip_init(char *ifname)
|
|||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* assumes that the driver has already been initialized */
|
|
||||||
sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
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;
|
BIP_Socket = sock_fd;
|
||||||
if (sock_fd < 0) {
|
if (sock_fd < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* Allow us to use the same socket for sending and receiving */
|
|
||||||
/* This makes sure that the src port is correct when sending */
|
|
||||||
sockopt = 1;
|
|
||||||
status = setsockopt(
|
|
||||||
sock_fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
|
|
||||||
if (status < 0) {
|
|
||||||
close(sock_fd);
|
|
||||||
BIP_Socket = -1;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
/* allow us to send a broadcast */
|
|
||||||
status = setsockopt(
|
|
||||||
sock_fd, SOL_SOCKET, SO_BROADCAST, &sockopt, sizeof(sockopt));
|
|
||||||
if (status < 0) {
|
|
||||||
close(sock_fd);
|
|
||||||
BIP_Socket = -1;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* Bind to the proper interface to send without default gateway */
|
|
||||||
setsockopt(sock_fd, SOL_SOCKET, SO_BINDTODEVICE, BIP_Interface_Name,
|
|
||||||
sizeof(BIP_Interface_Name));
|
|
||||||
|
|
||||||
/* bind the socket to the local port number and IP address */
|
|
||||||
sin.sin_family = AF_INET;
|
|
||||||
sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
sin.sin_port = BIP_Port;
|
sock_fd = createSocket(&sin);
|
||||||
memset(&(sin.sin_zero), '\0', sizeof(sin.sin_zero));
|
BIP_Broadcast_Socket = sock_fd;
|
||||||
status =
|
if (sock_fd < 0) {
|
||||||
bind(sock_fd, (const struct sockaddr *)&sin, sizeof(struct sockaddr));
|
|
||||||
if (status < 0) {
|
|
||||||
close(sock_fd);
|
|
||||||
BIP_Socket = -1;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bvlc_init();
|
bvlc_init();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -866,5 +895,10 @@ void bip_cleanup(void)
|
|||||||
}
|
}
|
||||||
BIP_Socket = -1;
|
BIP_Socket = -1;
|
||||||
|
|
||||||
|
if (BIP_Broadcast_Socket != -1) {
|
||||||
|
close(BIP_Broadcast_Socket);
|
||||||
|
}
|
||||||
|
BIP_Broadcast_Socket = -1;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,8 +39,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#if (!defined(USE_INADDR) || (USE_INADDR == 0)) && \
|
#if (!defined(USE_CLASSADDR) || (USE_CLASSADDR == 0))
|
||||||
(!defined(USE_CLASSADDR) || (USE_CLASSADDR == 0))
|
|
||||||
#include <iphlpapi.h>
|
#include <iphlpapi.h>
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#pragma comment(lib, "IPHLPAPI.lib")
|
#pragma comment(lib, "IPHLPAPI.lib")
|
||||||
|
|||||||
+82
-69
@@ -45,16 +45,13 @@
|
|||||||
#include "bacnet/basic/bbmd/h_bbmd.h"
|
#include "bacnet/basic/bbmd/h_bbmd.h"
|
||||||
#include "bacport.h"
|
#include "bacport.h"
|
||||||
|
|
||||||
/* alternate methods of choosing broadcast address */
|
|
||||||
#ifndef USE_INADDR
|
|
||||||
#define USE_INADDR 0
|
|
||||||
#endif
|
|
||||||
#ifndef USE_CLASSADDR
|
#ifndef USE_CLASSADDR
|
||||||
#define USE_CLASSADDR 0
|
#define USE_CLASSADDR 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Windows socket */
|
/* Windows sockets */
|
||||||
static SOCKET BIP_Socket = INVALID_SOCKET;
|
static SOCKET BIP_Socket = INVALID_SOCKET;
|
||||||
|
static SOCKET BIP_Broadcast_Socket = INVALID_SOCKET;
|
||||||
|
|
||||||
/* NOTE: we store address and port in network byte order
|
/* NOTE: we store address and port in network byte order
|
||||||
since BACnet/IP uses network byte order for all address byte arrays
|
since BACnet/IP uses network byte order for all address byte arrays
|
||||||
@@ -482,6 +479,7 @@ uint16_t bip_receive(
|
|||||||
int received_bytes = 0;
|
int received_bytes = 0;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
uint16_t i = 0;
|
uint16_t i = 0;
|
||||||
|
SOCKET socket;
|
||||||
|
|
||||||
/* Make sure the socket is open */
|
/* Make sure the socket is open */
|
||||||
if (BIP_Socket == INVALID_SOCKET) {
|
if (BIP_Socket == INVALID_SOCKET) {
|
||||||
@@ -500,10 +498,15 @@ uint16_t bip_receive(
|
|||||||
}
|
}
|
||||||
FD_ZERO(&read_fds);
|
FD_ZERO(&read_fds);
|
||||||
FD_SET(BIP_Socket, &read_fds);
|
FD_SET(BIP_Socket, &read_fds);
|
||||||
max = BIP_Socket;
|
FD_SET(BIP_Broadcast_Socket, &read_fds);
|
||||||
|
|
||||||
|
max = BIP_Socket > BIP_Broadcast_Socket ? BIP_Socket : BIP_Broadcast_Socket;
|
||||||
|
|
||||||
/* see if there is a packet for us */
|
/* see if there is a packet for us */
|
||||||
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
|
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
|
||||||
received_bytes = recvfrom(max, (char *)&npdu[0], max_npdu, 0,
|
socket = FD_ISSET(BIP_Socket, &read_fds) ? BIP_Socket :
|
||||||
|
BIP_Broadcast_Socket;
|
||||||
|
received_bytes = recvfrom(socket, (char *)&npdu[0], max_npdu, 0,
|
||||||
(struct sockaddr *)&sin, &sin_len);
|
(struct sockaddr *)&sin, &sin_len);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -541,7 +544,9 @@ uint16_t bip_receive(
|
|||||||
debug_print_ipv4(
|
debug_print_ipv4(
|
||||||
"Received MPDU->", &sin.sin_addr, sin.sin_port, received_bytes);
|
"Received MPDU->", &sin.sin_addr, sin.sin_port, received_bytes);
|
||||||
/* pass the packet into the BBMD handler */
|
/* pass the packet into the BBMD handler */
|
||||||
offset = bvlc_handler(&addr, src, npdu, received_bytes);
|
offset = socket == BIP_Socket ?
|
||||||
|
bvlc_handler(&addr, src, npdu, received_bytes) :
|
||||||
|
bvlc_broadcast_handler(&addr, src, npdu, received_bytes);
|
||||||
if (offset > 0) {
|
if (offset > 0) {
|
||||||
npdu_len = received_bytes - offset;
|
npdu_len = received_bytes - offset;
|
||||||
if (npdu_len <= max_npdu) {
|
if (npdu_len <= max_npdu) {
|
||||||
@@ -632,7 +637,7 @@ static long gethostaddr(void)
|
|||||||
return *(long *)host_ent->h_addr;
|
return *(long *)host_ent->h_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ((USE_INADDR == 0) || (USE_CLASSADDR == 0))
|
#if (USE_CLASSADDR == 0)
|
||||||
/* returns the subnet mask in network byte order */
|
/* returns the subnet mask in network byte order */
|
||||||
static uint32_t getIpMaskForIpAddress(uint32_t ipAddress)
|
static uint32_t getIpMaskForIpAddress(uint32_t ipAddress)
|
||||||
{
|
{
|
||||||
@@ -679,12 +684,7 @@ static uint32_t getIpMaskForIpAddress(uint32_t ipAddress)
|
|||||||
|
|
||||||
static void set_broadcast_address(uint32_t net_address)
|
static void set_broadcast_address(uint32_t net_address)
|
||||||
{
|
{
|
||||||
#if USE_INADDR
|
#if USE_CLASSADDR
|
||||||
/* Note: sometimes INADDR_BROADCAST does not let me get
|
|
||||||
any unicast messages. Not sure why... */
|
|
||||||
(void)net_address;
|
|
||||||
BIP_Broadcast_Address.s_addr = INADDR_BROADCAST;
|
|
||||||
#elif USE_CLASSADDR
|
|
||||||
long broadcast_address = 0;
|
long broadcast_address = 0;
|
||||||
|
|
||||||
if (IN_CLASSA(ntohl(net_address)))
|
if (IN_CLASSA(ntohl(net_address)))
|
||||||
@@ -701,7 +701,7 @@ static void set_broadcast_address(uint32_t net_address)
|
|||||||
(ntohl(net_address) & ~IN_CLASSD_HOST) | IN_CLASSD_HOST;
|
(ntohl(net_address) & ~IN_CLASSD_HOST) | IN_CLASSD_HOST;
|
||||||
else
|
else
|
||||||
broadcast_address = INADDR_BROADCAST;
|
broadcast_address = INADDR_BROADCAST;
|
||||||
BIP_Broadcast_Address.s_addr = htonl(broadcast_address));
|
BIP_Broadcast_Address.s_addr = htonl(broadcast_address);
|
||||||
#else
|
#else
|
||||||
/* these are network byte order variables */
|
/* these are network byte order variables */
|
||||||
long broadcast_address = 0;
|
long broadcast_address = 0;
|
||||||
@@ -728,7 +728,6 @@ static void set_broadcast_address(uint32_t net_address)
|
|||||||
*/
|
*/
|
||||||
void bip_set_interface(char *ifname)
|
void bip_set_interface(char *ifname)
|
||||||
{
|
{
|
||||||
bip_init_windows();
|
|
||||||
/* setup local address */
|
/* setup local address */
|
||||||
if (BIP_Address.s_addr == 0) {
|
if (BIP_Address.s_addr == 0) {
|
||||||
BIP_Address.s_addr = inet_addr(ifname);
|
BIP_Address.s_addr = inet_addr(ifname);
|
||||||
@@ -744,6 +743,45 @@ void bip_set_interface(char *ifname)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int createSocket(struct sockaddr_in *sin)
|
||||||
|
{
|
||||||
|
int rv = 0; /* return from socket lib calls */
|
||||||
|
int value = 1;
|
||||||
|
SOCKET sock_fd = INVALID_SOCKET;
|
||||||
|
|
||||||
|
/* assumes that the driver has already been initialized */
|
||||||
|
sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (sock_fd < 0) {
|
||||||
|
print_last_error("failed to allocate a socket");
|
||||||
|
return sock_fd;
|
||||||
|
}
|
||||||
|
/* Allow us to use the same socket for sending and receiving */
|
||||||
|
/* This makes sure that the src port is correct when sending */
|
||||||
|
rv = setsockopt(
|
||||||
|
sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&value, sizeof(value));
|
||||||
|
if (rv < 0) {
|
||||||
|
print_last_error("failed to set REUSEADDR socket option");
|
||||||
|
closesocket(sock_fd);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
/* Enables transmission and receipt of broadcast messages on the socket. */
|
||||||
|
rv = setsockopt(
|
||||||
|
sock_fd, SOL_SOCKET, SO_BROADCAST, (char *)&value, sizeof(value));
|
||||||
|
if (rv < 0) {
|
||||||
|
print_last_error("failed to set BROADCAST socket option");
|
||||||
|
closesocket(sock_fd);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = bind(sock_fd, (const struct sockaddr *)sin, sizeof(struct sockaddr));
|
||||||
|
if (rv < 0) {
|
||||||
|
print_last_error("failed to bind");
|
||||||
|
closesocket(sock_fd);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
return sock_fd;
|
||||||
|
}
|
||||||
|
|
||||||
/** Initialize the BACnet/IP services at the given interface.
|
/** Initialize the BACnet/IP services at the given interface.
|
||||||
* @ingroup DLBIP
|
* @ingroup DLBIP
|
||||||
* -# Gets the local IP address and local broadcast address from the system,
|
* -# Gets the local IP address and local broadcast address from the system,
|
||||||
@@ -763,9 +801,7 @@ void bip_set_interface(char *ifname)
|
|||||||
*/
|
*/
|
||||||
bool bip_init(char *ifname)
|
bool bip_init(char *ifname)
|
||||||
{
|
{
|
||||||
int rv = 0; /* return from socket lib calls */
|
|
||||||
struct sockaddr_in sin = { -1 };
|
struct sockaddr_in sin = { -1 };
|
||||||
int value = 1;
|
|
||||||
SOCKET sock_fd = INVALID_SOCKET;
|
SOCKET sock_fd = INVALID_SOCKET;
|
||||||
|
|
||||||
bip_init_windows();
|
bip_init_windows();
|
||||||
@@ -788,68 +824,38 @@ bool bip_init(char *ifname)
|
|||||||
ntohs(BIP_Port));
|
ntohs(BIP_Port));
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
/* assumes that the driver has already been initialized */
|
|
||||||
sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
BIP_Socket = sock_fd;
|
|
||||||
if (sock_fd < 0) {
|
|
||||||
print_last_error("failed to allocate a socket");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* Allow us to use the same socket for sending and receiving */
|
|
||||||
/* This makes sure that the src port is correct when sending */
|
|
||||||
rv = setsockopt(
|
|
||||||
sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&value, sizeof(value));
|
|
||||||
if (rv < 0) {
|
|
||||||
print_last_error("failed to set REUSEADDR socket option");
|
|
||||||
closesocket(sock_fd);
|
|
||||||
BIP_Socket = INVALID_SOCKET;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* Enables transmission and receipt of broadcast messages on the socket. */
|
|
||||||
rv = setsockopt(
|
|
||||||
sock_fd, SOL_SOCKET, SO_BROADCAST, (char *)&value, sizeof(value));
|
|
||||||
if (rv < 0) {
|
|
||||||
print_last_error("failed to set BROADCAST socket option");
|
|
||||||
closesocket(sock_fd);
|
|
||||||
BIP_Socket = INVALID_SOCKET;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* bind the socket to the local port number and IP address */
|
/* bind the socket to the local port number and IP address */
|
||||||
sin.sin_family = AF_INET;
|
sin.sin_family = AF_INET;
|
||||||
#if USE_INADDR
|
|
||||||
/* by setting sin.sin_addr.s_addr to INADDR_ANY,
|
|
||||||
I am telling the IP stack to automatically fill
|
|
||||||
in the IP address of the machine the process
|
|
||||||
is running on.
|
|
||||||
|
|
||||||
Some server computers have multiple IP addresses.
|
|
||||||
A socket bound to one of these will not accept
|
|
||||||
connections to another address. Frequently you prefer
|
|
||||||
to allow any one of the computer's IP addresses
|
|
||||||
to be used for connections. Use INADDR_ANY (0L) to
|
|
||||||
allow clients to connect using any one of the host's
|
|
||||||
IP addresses. */
|
|
||||||
sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
#else
|
|
||||||
/* or we could use the specific adapter address
|
|
||||||
note: already in network byte order */
|
|
||||||
sin.sin_addr.s_addr = BIP_Address.s_addr;
|
|
||||||
#endif
|
|
||||||
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;
|
||||||
if (BIP_Debug) {
|
if (BIP_Debug) {
|
||||||
fprintf(stderr, "BIP: bind %s:%hu\n", inet_ntoa(sin.sin_addr),
|
fprintf(stderr, "BIP: bind %s:%hu\n", inet_ntoa(sin.sin_addr),
|
||||||
ntohs(sin.sin_port));
|
ntohs(sin.sin_port));
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
rv = bind(sock_fd, (const struct sockaddr *)&sin, sizeof(struct sockaddr));
|
sock_fd = createSocket(&sin);
|
||||||
if (rv < 0) {
|
BIP_Socket = sock_fd;
|
||||||
print_last_error("failed to bind");
|
if (sock_fd < 0) {
|
||||||
closesocket(sock_fd);
|
|
||||||
BIP_Socket = INVALID_SOCKET;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
if (BIP_Debug) {
|
||||||
|
fprintf(stderr, "BIP: broadcast bind %s:%hu\n", inet_ntoa(sin.sin_addr),
|
||||||
|
ntohs(sin.sin_port));
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
sock_fd = createSocket(&sin);
|
||||||
|
BIP_Broadcast_Socket = sock_fd;
|
||||||
|
if (sock_fd < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bvlc_init();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -874,6 +880,13 @@ void bip_cleanup(void)
|
|||||||
closesocket(sock_fd);
|
closesocket(sock_fd);
|
||||||
}
|
}
|
||||||
BIP_Socket = INVALID_SOCKET;
|
BIP_Socket = INVALID_SOCKET;
|
||||||
|
|
||||||
|
if (BIP_Broadcast_Socket != INVALID_SOCKET) {
|
||||||
|
sock_fd = BIP_Broadcast_Socket;
|
||||||
|
closesocket(sock_fd);
|
||||||
|
}
|
||||||
|
BIP_Broadcast_Socket = INVALID_SOCKET;
|
||||||
|
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
+64
-38
@@ -55,8 +55,9 @@ LOG_MODULE_DECLARE(bacnet, CONFIG_BACNETSTACK_LOG_LEVEL);
|
|||||||
|
|
||||||
#define THIS_FILE "bip-init.c"
|
#define THIS_FILE "bip-init.c"
|
||||||
|
|
||||||
/* zephyr socket */
|
/* zephyr sockets */
|
||||||
static int BIP_Socket = -1;
|
static int BIP_Socket = -1;
|
||||||
|
static int BIP_Broadcast_Socket = -1;
|
||||||
|
|
||||||
/* NOTE: we store address and port in network byte order
|
/* NOTE: we store address and port in network byte order
|
||||||
since BACnet/IP uses network byte order for all address byte arrays
|
since BACnet/IP uses network byte order for all address byte arrays
|
||||||
@@ -320,6 +321,7 @@ uint16_t bip_receive(
|
|||||||
int received_bytes = 0;
|
int received_bytes = 0;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
uint16_t i = 0;
|
uint16_t i = 0;
|
||||||
|
int socket;
|
||||||
|
|
||||||
/* Make sure the socket is open */
|
/* Make sure the socket is open */
|
||||||
if (BIP_Socket < 0) {
|
if (BIP_Socket < 0) {
|
||||||
@@ -339,11 +341,15 @@ uint16_t bip_receive(
|
|||||||
}
|
}
|
||||||
ZSOCK_FD_ZERO(&read_fds);
|
ZSOCK_FD_ZERO(&read_fds);
|
||||||
ZSOCK_FD_SET(BIP_Socket, &read_fds);
|
ZSOCK_FD_SET(BIP_Socket, &read_fds);
|
||||||
max = BIP_Socket;
|
FD_SET(BIP_Broadcast_Socket, &read_fds);
|
||||||
|
|
||||||
|
max = BIP_Socket > BIP_Broadcast_Socket ? BIP_Socket : BIP_Broadcast_Socket;
|
||||||
|
|
||||||
/* see if there is a packet for us */
|
/* see if there is a packet for us */
|
||||||
if (zsock_select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
|
if (zsock_select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
|
||||||
received_bytes = zsock_recvfrom(BIP_Socket, (char *)&npdu[0], max_npdu,
|
socket = FD_ISSET(BIP_Socket, &read_fds) ? BIP_Socket :
|
||||||
|
BIP_Broadcast_Socket;
|
||||||
|
received_bytes = zsock_recvfrom(socket, (char *)&npdu[0], max_npdu,
|
||||||
0, (struct sockaddr *)&sin, &sin_len);
|
0, (struct sockaddr *)&sin, &sin_len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -378,7 +384,9 @@ uint16_t bip_receive(
|
|||||||
debug_print_ipv4("Received MPDU->", &sin.sin_addr, sin.sin_port,
|
debug_print_ipv4("Received MPDU->", &sin.sin_addr, sin.sin_port,
|
||||||
received_bytes);
|
received_bytes);
|
||||||
/* pass the packet into the BBMD handler */
|
/* pass the packet into the BBMD handler */
|
||||||
offset = bvlc_handler(&addr, src, npdu, received_bytes);
|
offset = socket == BIP_Socket ?
|
||||||
|
bvlc_handler(&addr, src, npdu, received_bytes) :
|
||||||
|
bvlc_broadcast_handler(&addr, src, npdu, received_bytes);
|
||||||
if (offset > 0) {
|
if (offset > 0) {
|
||||||
npdu_len = received_bytes - offset;
|
npdu_len = received_bytes - offset;
|
||||||
debug_print_ipv4("Received NPDU->", &sin.sin_addr, sin.sin_port,
|
debug_print_ipv4("Received NPDU->", &sin.sin_addr, sin.sin_port,
|
||||||
@@ -504,6 +512,48 @@ void bip_set_interface(char *ifname)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int createSocket(struct sockaddr_in *sin)
|
||||||
|
{
|
||||||
|
int sock_fd = -1;
|
||||||
|
const int sockopt = 1;
|
||||||
|
int status = -1;
|
||||||
|
|
||||||
|
/* assumes that the driver has already been initialized */
|
||||||
|
sock_fd = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (sock_fd < 0) {
|
||||||
|
LOG_ERR("%s:%d - Failed to create socket", THIS_FILE, __LINE__);
|
||||||
|
return sock_fd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_DBG("Socket created");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow us to use the same socket for sending and receiving */
|
||||||
|
/* This makes sure that the src port is correct when sending */
|
||||||
|
status = zsock_setsockopt(
|
||||||
|
sock_fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
|
||||||
|
if (status < 0) {
|
||||||
|
zsock_close(sock_fd);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bind the socket to the local port number and IP address */
|
||||||
|
status =
|
||||||
|
zsock_bind(sock_fd, (const struct sockaddr *)sin, sizeof(struct sockaddr));
|
||||||
|
if (status < 0) {
|
||||||
|
zsock_close(sock_fd);
|
||||||
|
LOG_ERR("%s:%d - zsock_bind() failure", THIS_FILE, __LINE__);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_DBG("Socket bound");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock_fd;
|
||||||
|
}
|
||||||
|
|
||||||
/** Initialize the BACnet/IP services at the given interface.
|
/** Initialize the BACnet/IP services at the given interface.
|
||||||
* @ingroup DLBIP
|
* @ingroup DLBIP
|
||||||
* -# Gets the local IP address and local broadcast address from the system,
|
* -# Gets the local IP address and local broadcast address from the system,
|
||||||
@@ -523,8 +573,6 @@ void bip_set_interface(char *ifname)
|
|||||||
*/
|
*/
|
||||||
bool bip_init(char *ifname)
|
bool bip_init(char *ifname)
|
||||||
{
|
{
|
||||||
int sock_fd = -1;
|
|
||||||
const int sockopt = 1;
|
|
||||||
int status = -1;
|
int status = -1;
|
||||||
struct sockaddr_in sin = { 0 };
|
struct sockaddr_in sin = { 0 };
|
||||||
|
|
||||||
@@ -535,44 +583,22 @@ bool bip_init(char *ifname)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* assumes that the driver has already been initialized */
|
|
||||||
sock_fd = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
BIP_Socket = sock_fd;
|
|
||||||
if (sock_fd < 0) {
|
|
||||||
LOG_ERR("%s:%d - Failed to create socket", THIS_FILE, __LINE__);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_DBG("Socket created");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allow us to use the same socket for sending and receiving */
|
|
||||||
/* This makes sure that the src port is correct when sending */
|
|
||||||
status = zsock_setsockopt(
|
|
||||||
sock_fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
|
|
||||||
if (status < 0) {
|
|
||||||
zsock_close(sock_fd);
|
|
||||||
BIP_Socket = -1;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* bind the socket to the local port number and IP address */
|
/* bind the socket to the local port number and IP address */
|
||||||
sin.sin_family = AF_INET;
|
sin.sin_family = AF_INET;
|
||||||
sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
sin.sin_port = BIP_Port;
|
sin.sin_port = BIP_Port;
|
||||||
|
|
||||||
status =
|
sin.sin_addr.s_addr = BIP_Address.s_addr;
|
||||||
zsock_bind(sock_fd, (const struct sockaddr *)&sin, sizeof(struct sockaddr));
|
sock_fd = createSocket(&sin);
|
||||||
if (status < 0) {
|
BIP_Socket = sock_fd;
|
||||||
zsock_close(sock_fd);
|
if (sock_fd < 0) {
|
||||||
BIP_Socket = -1;
|
|
||||||
LOG_ERR("%s:%d - zsock_bind() failure", THIS_FILE, __LINE__);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
sin.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
LOG_DBG("Socket bound");
|
sock_fd = createSocket(&sin);
|
||||||
|
BIP_Broadcast_Socket = sock_fd;
|
||||||
|
if (sock_fd < 0) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bvlc_init();
|
bvlc_init();
|
||||||
|
|||||||
@@ -1159,6 +1159,32 @@ int bvlc_handler(BACNET_IP_ADDRESS *addr,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bvlc_broadcast_handler(BACNET_IP_ADDRESS *addr,
|
||||||
|
BACNET_ADDRESS *src,
|
||||||
|
uint8_t *npdu,
|
||||||
|
uint16_t npdu_len)
|
||||||
|
{
|
||||||
|
int offset = 0;
|
||||||
|
uint8_t message_type = 0;
|
||||||
|
uint16_t message_length = 0;
|
||||||
|
int header_len = 0;
|
||||||
|
|
||||||
|
header_len =
|
||||||
|
bvlc_decode_header(npdu, npdu_len, &message_type, &message_length);
|
||||||
|
if (header_len == 4) {
|
||||||
|
switch (message_type) {
|
||||||
|
case BVLC_ORIGINAL_UNICAST_NPDU:
|
||||||
|
/* drop unicast when sent as a broadcast */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
offset = bvlc_handler(addr, src, npdu, npdu_len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
#if BBMD_CLIENT_ENABLED
|
#if BBMD_CLIENT_ENABLED
|
||||||
/** Register as a foreign device with the indicated BBMD.
|
/** Register as a foreign device with the indicated BBMD.
|
||||||
* @param bbmd_addr - IPv4 address of BBMD with which to register
|
* @param bbmd_addr - IPv4 address of BBMD with which to register
|
||||||
|
|||||||
@@ -47,6 +47,12 @@ int bvlc_handler(BACNET_IP_ADDRESS *addr,
|
|||||||
uint8_t *npdu,
|
uint8_t *npdu,
|
||||||
uint16_t npdu_len);
|
uint16_t npdu_len);
|
||||||
|
|
||||||
|
BACNET_STACK_EXPORT
|
||||||
|
int bvlc_broadcast_handler(BACNET_IP_ADDRESS *addr,
|
||||||
|
BACNET_ADDRESS *src,
|
||||||
|
uint8_t *npdu,
|
||||||
|
uint16_t npdu_len);
|
||||||
|
|
||||||
BACNET_STACK_EXPORT
|
BACNET_STACK_EXPORT
|
||||||
int bvlc_bbmd_enabled_handler(BACNET_IP_ADDRESS *addr,
|
int bvlc_bbmd_enabled_handler(BACNET_IP_ADDRESS *addr,
|
||||||
BACNET_ADDRESS *src,
|
BACNET_ADDRESS *src,
|
||||||
|
|||||||
Reference in New Issue
Block a user