Feature/bacnet ipv6 foreign device registration (#355)
* Added IPv6 Foreign Device Registration for apps * Fix debug message in BACnet/IPv6 Linux port Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
+16
-1
@@ -422,7 +422,7 @@ bool bip6_init(char *ifname)
|
||||
if (BIP6_Addr.port == 0) {
|
||||
bip6_set_port(0xBAC0U);
|
||||
}
|
||||
PRINTF("BIP6: IPv6 UDP port: 0x%04X\n", htons(BIP6_Addr.port));
|
||||
PRINTF("BIP6: IPv6 UDP port: 0x%04X\n", BIP6_Addr.port);
|
||||
if (BIP6_Broadcast_Addr.address[0] == 0) {
|
||||
bvlc6_address_set(&BIP6_Broadcast_Addr, BIP6_MULTICAST_SITE_LOCAL, 0, 0,
|
||||
0, 0, 0, 0, BIP6_MULTICAST_GROUP_ID);
|
||||
@@ -464,8 +464,23 @@ bool bip6_init(char *ifname)
|
||||
|
||||
/* bind the socket to the local port number and IP address */
|
||||
server.sin6_family = AF_INET6;
|
||||
#if 0
|
||||
uint16_t addr16[8];
|
||||
bvlc6_address_get(&BIP6_Addr, &addr16[0], &addr16[1], &addr16[2],
|
||||
&addr16[3], &addr16[4], &addr16[5], &addr16[6], &addr16[7]);
|
||||
server.sin6_addr.s6_addr16[0] = htons(addr16[0]);
|
||||
server.sin6_addr.s6_addr16[1] = htons(addr16[1]);
|
||||
server.sin6_addr.s6_addr16[2] = htons(addr16[2]);
|
||||
server.sin6_addr.s6_addr16[3] = htons(addr16[3]);
|
||||
server.sin6_addr.s6_addr16[4] = htons(addr16[4]);
|
||||
server.sin6_addr.s6_addr16[5] = htons(addr16[5]);
|
||||
server.sin6_addr.s6_addr16[6] = htons(addr16[6]);
|
||||
server.sin6_addr.s6_addr16[7] = htons(addr16[7]);
|
||||
#else
|
||||
server.sin6_addr = in6addr_any;
|
||||
#endif
|
||||
server.sin6_port = htons(BIP6_Addr.port);
|
||||
debug_print_ipv6("Binding->", &server.sin6_addr);
|
||||
status = bind(BIP6_Socket, (const void *)&server, sizeof(server));
|
||||
if (status < 0) {
|
||||
perror("BIP: bind");
|
||||
|
||||
+1
-7
@@ -113,7 +113,6 @@ void bip6_set_interface(char *ifname)
|
||||
int i, RetVal;
|
||||
struct addrinfo Hints, *AddrInfo, *AI;
|
||||
struct sockaddr_in6 *sin;
|
||||
struct sockaddr_in6 server = {};
|
||||
struct in6_addr broadcast_address = {};
|
||||
struct ipv6_mreq join_request = {};
|
||||
SOCKET ServSock[FD_SETSIZE] = {};
|
||||
@@ -224,12 +223,7 @@ void bip6_set_interface(char *ifname)
|
||||
// the application is a server that has a well-known port
|
||||
// that clients know about in advance.
|
||||
//
|
||||
memset(&server, 0, sizeof(server));
|
||||
server.sin6_family = AF_INET6;
|
||||
server.sin6_port = htons(BIP6_Addr.port);
|
||||
server.sin6_addr = in6addr_any;
|
||||
if (bind(BIP6_Socket, (struct sockaddr *)&server, sizeof(server)) ==
|
||||
SOCKET_ERROR) {
|
||||
if (bind(BIP6_Socket, AI->ai_addr, AI->ai_addrlen) == SOCKET_ERROR) {
|
||||
fprintf(stderr, "BIP6: bind() failed with error %d: %s\n",
|
||||
WSAGetLastError(), PrintError(WSAGetLastError()));
|
||||
closesocket(ServSock[i]);
|
||||
|
||||
@@ -64,6 +64,8 @@ static uint8_t BVLC6_Function_Code = BVLC6_RESULT;
|
||||
|
||||
/** if we are a foreign device, store the remote BBMD address/port here */
|
||||
static BACNET_IP6_ADDRESS Remote_BBMD;
|
||||
/** if we are a foreign device, store the Time-To-Live Seconds here */
|
||||
static uint16_t Remote_BBMD_TTL_Seconds;
|
||||
#if defined(BACDL_BIP6) && BBMD6_ENABLED
|
||||
/* local buffer & length for sending */
|
||||
static uint8_t BVLC6_Buffer[BIP6_MPDU_MAX];
|
||||
@@ -1024,24 +1026,47 @@ int bvlc6_handler(BACNET_IP6_ADDRESS *addr,
|
||||
* @param bbmd_address - IPv4 address (long) of BBMD to register with,
|
||||
* in network byte order.
|
||||
* @param bbmd_port - Network port of BBMD, in network byte order
|
||||
* @param time_to_live_seconds - Lease time to use when registering.
|
||||
* @param ttl_seconds - Lease time to use when registering.
|
||||
* @return Positive number (of bytes sent) on success,
|
||||
* 0 if no registration request is sent, or
|
||||
* -1 if registration fails.
|
||||
*/
|
||||
int bvlc6_register_with_bbmd(BACNET_IP6_ADDRESS *bbmd_addr,
|
||||
uint32_t vmac_src,
|
||||
uint16_t time_to_live_seconds)
|
||||
uint16_t ttl_seconds)
|
||||
{
|
||||
uint8_t mtu[BIP6_MPDU_MAX] = { 0 };
|
||||
uint16_t mtu_len = 0;
|
||||
uint32_t vmac_src = 0;
|
||||
|
||||
/* Store the BBMD address and port so that we won't broadcast locally. */
|
||||
/* We are a foreign device! */
|
||||
bvlc6_address_copy(&Remote_BBMD, bbmd_addr);
|
||||
Remote_BBMD_TTL_Seconds = ttl_seconds;
|
||||
vmac_src = Device_Object_Instance_Number();
|
||||
mtu_len = bvlc6_encode_register_foreign_device(
|
||||
&mtu[0], sizeof(mtu), vmac_src, time_to_live_seconds);
|
||||
&mtu[0], sizeof(mtu), vmac_src, ttl_seconds);
|
||||
|
||||
return bip6_send_mpdu(bbmd_addr, &mtu[0], mtu_len);
|
||||
}
|
||||
|
||||
/** Get the remote BBMD address that was used to Register as a foreign device
|
||||
* @param bbmd_addr - IPv6 address of BBMD used to register
|
||||
*/
|
||||
void bvlc6_remote_bbmd_address(BACNET_IP6_ADDRESS *bbmd_addr)
|
||||
{
|
||||
bvlc6_address_copy(bbmd_addr, &Remote_BBMD);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the remote BBMD time-to-live seconds used to
|
||||
* Register Foreign Device
|
||||
* @return Lease time in seconds to use when registering.
|
||||
*/
|
||||
uint16_t bvlc6_remote_bbmd_lifetime(void)
|
||||
{
|
||||
return Remote_BBMD_TTL_Seconds;
|
||||
}
|
||||
|
||||
/** Returns the last BVLL Result we received, either as the result of a BBMD
|
||||
* request we sent, or (if not a BBMD or Client), from trying to register
|
||||
* as a foreign device.
|
||||
|
||||
@@ -69,9 +69,16 @@ extern "C" {
|
||||
BACNET_STACK_EXPORT
|
||||
int bvlc6_register_with_bbmd(
|
||||
BACNET_IP6_ADDRESS *bbmd_addr,
|
||||
uint32_t vmac_src,
|
||||
uint16_t time_to_live_seconds);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
void bvlc6_remote_bbmd_address(
|
||||
BACNET_IP6_ADDRESS *bbmd_addr);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
uint16_t bvlc6_remote_bbmd_lifetime(
|
||||
void);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
uint16_t bvlc6_get_last_result(
|
||||
void);
|
||||
|
||||
@@ -40,14 +40,17 @@
|
||||
#endif
|
||||
|
||||
/** @file dlenv.c Initialize the DataLink configuration. */
|
||||
/* timer used to renew Foreign Device Registration */
|
||||
#if defined(BACDL_BIP) || defined(BACDL_BIP6)
|
||||
static uint16_t BBMD_Timer_Seconds;
|
||||
static uint16_t BBMD_TTL_Seconds = 60000;
|
||||
#endif
|
||||
|
||||
#if defined(BACDL_BIP)
|
||||
#ifndef BBMD_ENABLED
|
||||
#define BBMD_ENABLED 1
|
||||
#endif
|
||||
/* timer used to renew Foreign Device Registration */
|
||||
static uint16_t BBMD_Timer_Seconds;
|
||||
/* BBMD variables */
|
||||
static uint16_t BBMD_TTL_Seconds = 60000;
|
||||
static BACNET_IP_ADDRESS BBMD_Address;
|
||||
static bool BBMD_Address_Valid;
|
||||
static uint16_t BBMD_Result = 0;
|
||||
@@ -120,6 +123,7 @@ int dlenv_bbmd_result(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BACDL_BIP) && BBMD_ENABLED
|
||||
/** Register as a Foreign Device with the designated BBMD.
|
||||
* @ingroup DataLink
|
||||
* The BBMD's address, port, and lease time must be provided by
|
||||
@@ -134,10 +138,9 @@ int dlenv_bbmd_result(void)
|
||||
* 0 if no registration request is sent, or
|
||||
* -1 if registration fails.
|
||||
*/
|
||||
int dlenv_register_as_foreign_device(void)
|
||||
static int bbmd_register_as_foreign_device(void)
|
||||
{
|
||||
int retval = 0;
|
||||
#if defined(BACDL_BIP) && BBMD_ENABLED
|
||||
bool bdt_entry_valid = false;
|
||||
uint16_t bdt_entry_port = 0;
|
||||
char *pEnv = NULL;
|
||||
@@ -187,7 +190,7 @@ int dlenv_register_as_foreign_device(void)
|
||||
(unsigned)BBMD_Address.address[2],
|
||||
(unsigned)BBMD_Address.address[3], (unsigned)BBMD_Address.port);
|
||||
}
|
||||
BBMD_Timer_Seconds = (uint16_t)BBMD_TTL_Seconds;
|
||||
BBMD_Timer_Seconds = BBMD_TTL_Seconds;
|
||||
} else {
|
||||
for (entry_number = 1; entry_number <= 128; entry_number++) {
|
||||
bdt_entry_valid = false;
|
||||
@@ -259,9 +262,94 @@ int dlenv_register_as_foreign_device(void)
|
||||
}
|
||||
}
|
||||
BBMD_Result = retval;
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BACDL_BIP6) && BBMD6_ENABLED
|
||||
/** Register as a Foreign Device with the designated BBMD.
|
||||
* @ingroup DataLink
|
||||
* The BBMD's address, port, and lease time must be provided by
|
||||
* internal variables or Environment variables.
|
||||
* If no address for the BBMD is provided, no BBMD registration will occur.
|
||||
*
|
||||
* The Environment Variables depend on define of BACDL_BIP:
|
||||
* - BACNET_BBMD6_PORT - 0..65534, defaults to 47808
|
||||
* - BACNET_BBMD6_TIMETOLIVE - 0..65535 seconds, defaults to 60000
|
||||
* - BACNET_BBMD6_ADDRESS - IPv6 address
|
||||
* @return Positive number (of bytes sent) on success,
|
||||
* 0 if no registration request is sent, or
|
||||
* -1 if registration fails.
|
||||
*/
|
||||
static int bbmd6_register_as_foreign_device(void)
|
||||
{
|
||||
int retval = 0;
|
||||
bool bdt_entry_valid = false;
|
||||
uint16_t bdt_entry_port = 0;
|
||||
char *pEnv = NULL;
|
||||
unsigned a[4] = { 0 };
|
||||
char bbmd_env[32] = "";
|
||||
unsigned entry_number = 0;
|
||||
long long_value = 0;
|
||||
int c;
|
||||
BACNET_IP6_ADDRESS bip6_addr = { 0 };
|
||||
uint16_t bip6_port = 0xBAC0;
|
||||
|
||||
pEnv = getenv("BACNET_BBMD6_PORT");
|
||||
if (pEnv) {
|
||||
long_value = strtol(pEnv, NULL, 0);
|
||||
if (long_value <= UINT16_MAX) {
|
||||
bip6_port = (uint16_t)long_value;
|
||||
}
|
||||
}
|
||||
pEnv = getenv("BACNET_BBMD6_TIMETOLIVE");
|
||||
if (pEnv) {
|
||||
long_value = strtol(pEnv, NULL, 0);
|
||||
if (long_value <= 60000) {
|
||||
BBMD_TTL_Seconds = (uint16_t)long_value;
|
||||
}
|
||||
}
|
||||
pEnv = getenv("BACNET_BBMD6_ADDRESS");
|
||||
if (bvlc6_address_from_ascii(pEnv, &bip6_addr)) {
|
||||
if (BIP_DL_Debug) {
|
||||
fprintf(stderr,
|
||||
"Registering with BBMD6 at %s for %u seconds\n",
|
||||
pEnv, (unsigned)bip6_port, (unsigned)BBMD_TTL_Seconds);
|
||||
}
|
||||
retval = bvlc6_register_with_bbmd(&bip6_addr, BBMD_TTL_Seconds);
|
||||
if (retval < 0) {
|
||||
fprintf(stderr, "FAILED to Register with BBMD6 at %s:%u\n",
|
||||
pEnv, (unsigned)BBMD_Address.port);
|
||||
}
|
||||
BBMD_Timer_Seconds = BBMD_TTL_Seconds;
|
||||
}
|
||||
BBMD_Result = retval;
|
||||
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Register as a Foreign Device with the designated BBMD.
|
||||
* @ingroup DataLink
|
||||
* The BBMD's address, port, and lease time must be provided by
|
||||
* internal variables or Environment variables.
|
||||
* If no address for the BBMD is provided, no BBMD registration will occur.
|
||||
*
|
||||
* @return Positive number (of bytes sent) on success,
|
||||
* 0 if no registration request is sent, or
|
||||
* -1 if registration fails.
|
||||
*/
|
||||
int dlenv_register_as_foreign_device(void)
|
||||
{
|
||||
#if defined(BACDL_BIP) && BBMD_ENABLED
|
||||
return bbmd_register_as_foreign_device();
|
||||
#elif defined(BACDL_BIP) && BBMD_ENABLED
|
||||
return bbmd6_register_as_foreign_device();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (BACNET_PROTOCOL_REVISION >= 17)
|
||||
#if defined(BACDL_BIP)
|
||||
@@ -381,7 +469,7 @@ void dlenv_network_port_init(void)
|
||||
*/
|
||||
void dlenv_maintenance_timer(uint16_t elapsed_seconds)
|
||||
{
|
||||
#if defined(BACDL_BIP)
|
||||
#if defined(BACDL_BIP) || defined(BACDL_BIP6)
|
||||
if (BBMD_Timer_Seconds) {
|
||||
if (BBMD_Timer_Seconds <= elapsed_seconds) {
|
||||
BBMD_Timer_Seconds = 0;
|
||||
|
||||
Reference in New Issue
Block a user