diff --git a/bacnet-stack/Makefile b/bacnet-stack/Makefile index 1f45235b..a7b43674 100644 --- a/bacnet-stack/Makefile +++ b/bacnet-stack/Makefile @@ -25,8 +25,13 @@ BACNET_DEFINES ?= $(MY_BACNET_DEFINES) #BACDL_DEFINE=-DBACDL_MSTP=1 BACDL_DEFINE?=-DBACDL_BIP=1 +# Declare your level of BBMD support +BBMD_DEFINE ?= +#BBMD_DEFINE ?= -DBBMD_ENABLE +#BBMD_DEFINE ?= -DBBMD_CLIENT_ENABLED + # Define WEAK_FUNC for [...somebody help here; I can't find any uses of it] -DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) -DWEAK_FUNC= +DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) $(BBMD_DEFINE) -DWEAK_FUNC= # directories BACNET_PORT = linux diff --git a/bacnet-stack/demo/handler/dlenv.c b/bacnet-stack/demo/handler/dlenv.c index 4a0e144e..e4af4ca4 100644 --- a/bacnet-stack/demo/handler/dlenv.c +++ b/bacnet-stack/demo/handler/dlenv.c @@ -38,7 +38,7 @@ /** @file dlenv.c Initialize the DataLink configuration. */ -#if defined(BACDL_BIP) && BBMD_ENABLED +#if defined(BACDL_BIP) /* timer used to renew Foreign Device Registration */ static uint16_t BBMD_Timer_Seconds; /* BBMD variables */ @@ -95,7 +95,7 @@ int dlenv_bbmd_result( void ) * internal variables or Environment variables. * If no address for the BBMD is provided, no BBMD registration will occur. * - * The Environment Variables depend on defines BACDL_BIP and BBMD_ENABLED: + * The Environment Variables depend on define of BACDL_BIP: * - BACNET_BBMD_PORT - 0..65534, defaults to 47808 * - BACNET_BBMD_TIMETOLIVE - 0..65535 seconds, defaults to 60000 * - BACNET_BBMD_ADDRESS - dotted IPv4 address @@ -107,7 +107,7 @@ int dlenv_register_as_foreign_device( void) { int retval = 0; -#if defined(BACDL_BIP) && BBMD_ENABLED +#if defined(BACDL_BIP) char *pEnv = NULL; pEnv = getenv("BACNET_BBMD_PORT"); @@ -152,12 +152,13 @@ int dlenv_register_as_foreign_device( /** Datalink maintenance timer * @ingroup DataLink * - * Call this function to renew Foreign Device Registration + * Call this function to renew our Foreign Device Registration + * @param elapsed_seconds Number of seconds that have elapsed since last called. */ void dlenv_maintenance_timer( uint16_t elapsed_seconds) { -#if defined(BACDL_BIP) && BBMD_ENABLED +#if defined(BACDL_BIP) if (BBMD_Timer_Seconds) { if (BBMD_Timer_Seconds <= elapsed_seconds) { BBMD_Timer_Seconds = 0; @@ -167,10 +168,10 @@ void dlenv_maintenance_timer( if (BBMD_Timer_Seconds == 0) { int retval; retval = dlenv_register_as_foreign_device(); - /* If that failed, maybe just a network issue. - * Retry again later. */ - if ( retval < 0 ) - BBMD_Timer_Seconds = bbmd_timetolive_seconds; + /* If that failed (negative), maybe just a network issue. + * If nothing happened (0), may be un/misconfigured. + * Set up to try again later in all cases. */ + BBMD_Timer_Seconds = bbmd_timetolive_seconds; } } #endif @@ -203,12 +204,11 @@ void dlenv_maintenance_timer( * - BACDL_BIP: (BACnet/IP) * - BACNET_IP_PORT - UDP/IP port number (0..65534) used for BACnet/IP * communications. Default is 47808 (0xBAC0). - * - with BBMD_ENABLED also: - * - 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). - * - BACNET_BBMD_TIMETOLIVE - number of seconds used in Foreign Device + * - BACNET_BBMD_TIMETOLIVE - number of seconds used in Foreign Device * Registration (0..65535). Defaults to 60000 seconds. - * - BACNET_BBMD_ADDRESS - dotted IPv4 address of the BBMD or Foreign + * - BACNET_BBMD_ADDRESS - dotted IPv4 address of the BBMD or Foreign * Device Registrar. * - BACDL_MSTP: (BACnet MS/TP) * - BACNET_MAX_INFO_FRAMES diff --git a/bacnet-stack/demo/server/main.c b/bacnet-stack/demo/server/main.c index 1e05dc8a..9d7db810 100644 --- a/bacnet-stack/demo/server/main.c +++ b/bacnet-stack/demo/server/main.c @@ -229,6 +229,7 @@ int main( /* blink LEDs, Turn on or off outputs, etc */ } + return 0; } /* @} */ diff --git a/bacnet-stack/src/bvlc.c b/bacnet-stack/src/bvlc.c index 0bd0bce3..0ca7cd6d 100644 --- a/bacnet-stack/src/bvlc.c +++ b/bacnet-stack/src/bvlc.c @@ -51,6 +51,18 @@ * Foreign Device Registration. */ +/* if we are a foreign device, store the + remote BBMD address/port here in network byte order */ +static struct sockaddr_in Remote_BBMD; + + +/* Define BBMD_ENABLED to get the functions that a + * BBMD needs to handle its services. + * Separately, define BBMD_CLIENT_ENABLED to get the + * functions that allow a client to manage a BBMD. + */ +#if defined(BBMD_ENABLED) && BBMD_ENABLED + typedef struct { /* true if valid entry - false if not */ bool valid; @@ -62,7 +74,9 @@ typedef struct { struct in_addr broadcast_mask; /* in tework format */ } BBMD_TABLE_ENTRY; +#ifndef MAX_BBMD_ENTRIES #define MAX_BBMD_ENTRIES 128 +#endif static BBMD_TABLE_ENTRY BBMD_Table[MAX_BBMD_ENTRIES]; /*Each device that registers as a foreign device shall be placed @@ -86,17 +100,15 @@ typedef struct { time_t seconds_remaining; /* includes 30 second grace period */ } FD_TABLE_ENTRY; +#ifndef MAX_FD_ENTRIES #define MAX_FD_ENTRIES 128 +#endif static FD_TABLE_ENTRY FD_Table[MAX_FD_ENTRIES]; /* result from a client request */ BACNET_BVLC_RESULT BVLC_Result_Code = BVLC_RESULT_SUCCESSFUL_COMPLETION; -/* if we are a foreign device, store the - remote BBMD address/port here in network byte order */ -static struct sockaddr_in Remote_BBMD; -#if defined(BBMD_ENABLED) && BBMD_ENABLED void bvlc_maintenance_timer( time_t seconds) { @@ -117,7 +129,6 @@ void bvlc_maintenance_timer( } } } -#endif /* copy the source internet address to the BACnet address */ /* FIXME: IPv6? */ @@ -209,6 +220,7 @@ static int bvlc_encode_bvlc_result( return 6; } +#endif #if defined(BBMD_CLIENT_ENABLED) && BBMD_CLIENT_ENABLED int bvlc_encode_write_bdt_init( @@ -253,6 +265,8 @@ int bvlc_encode_read_bdt( } #endif + +#if defined(BBMD_ENABLED) && BBMD_ENABLED static int bvlc_encode_read_bdt_ack_init( uint8_t * pdu, unsigned entries) @@ -336,26 +350,7 @@ static int bvlc_encode_forwarded_npdu( return len; } - -static int bvlc_encode_register_foreign_device( - uint8_t * pdu, - uint16_t time_to_live_seconds) -{ - int len = 0; - - if (pdu) { - pdu[0] = BVLL_TYPE_BACNET_IP; - pdu[1] = BVLC_REGISTER_FOREIGN_DEVICE; - /* The 2-octet BVLC Length field is the length, in octets, - of the entire BVLL message, including the two octets of the - length field itself, most significant octet first. */ - encode_unsigned16(&pdu[2], 6); - encode_unsigned16(&pdu[4], time_to_live_seconds); - len = 6; - } - - return len; -} +#endif #if defined(BBMD_CLIENT_ENABLED) && BBMD_CLIENT_ENABLED int bvlc_encode_read_fdt( @@ -377,6 +372,8 @@ int bvlc_encode_read_fdt( } #endif + +#if defined(BBMD_ENABLED) && BBMD_ENABLED static int bvlc_encode_read_fdt_ack_init( uint8_t * pdu, unsigned entries) @@ -436,6 +433,8 @@ static int bvlc_encode_read_fdt_ack( return pdu_len; } +#endif + #if defined(BBMD_CLIENT_ENABLED) && BBMD_CLIENT_ENABLED int bvlc_encode_delete_fdt_entry( @@ -518,6 +517,8 @@ int bvlc_encode_original_broadcast_npdu( } #endif + +#if defined(BBMD_ENABLED) && BBMD_ENABLED static bool bvlc_create_bdt( uint8_t * npdu, uint16_t npdu_length) @@ -551,6 +552,7 @@ static bool bvlc_create_bdt( return status; } +/** Handle a foreign device registration. */ static bool bvlc_register_foreign_device( struct sockaddr_in *sin, /* source address in network order */ uint16_t time_to_live) @@ -614,7 +616,9 @@ static bool bvlc_delete_foreign_device( } return status; } +#endif +/** The common send function for bvlc functions, using b/ip. */ static int bvlc_send_mpdu( struct sockaddr_in *dest, /* the destination address */ uint8_t * mtu, /* the data */ @@ -636,6 +640,8 @@ static int bvlc_send_mpdu( (struct sockaddr *) &bvlc_dest, sizeof(struct sockaddr)); } + +#if defined(BBMD_ENABLED) && BBMD_ENABLED static void bvlc_bdt_forward_npdu( struct sockaddr_in *sin, /* source address in network order */ uint8_t * npdu, /* the NPDU */ @@ -734,38 +740,6 @@ static void bvlc_fdt_forward_npdu( } -/** Register as a foreign device with the indicated BBMD. - * @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. - * @return Positive number (of bytes sent) on success, - * 0 if no registration request is sent, or - * -1 if registration fails. - */ -int bvlc_register_with_bbmd( - uint32_t bbmd_address, - uint16_t bbmd_port, - uint16_t time_to_live_seconds) -{ - uint8_t mtu[MAX_MPDU] = { 0 }; - uint16_t mtu_len = 0; - int retval = 0; - - /* Store the BBMD address and port so that we - won't broadcast locally. */ - Remote_BBMD.sin_addr.s_addr = bbmd_address; - Remote_BBMD.sin_port = bbmd_port; - /* In order for their broadcasts to get here, - we need to register our address with the remote BBMD using - Write Broadcast Distribution Table, or - register with the BBMD as a Foreign Device */ - mtu_len = - (uint16_t) bvlc_encode_register_foreign_device(&mtu[0], - time_to_live_seconds); - retval = bvlc_send_mpdu(&Remote_BBMD, &mtu[0], mtu_len); - return retval; -} static void bvlc_send_result( struct sockaddr_in *dest, /* the destination address */ @@ -1194,6 +1168,68 @@ int bvlc_send_pdu( mtu_len += (uint16_t) pdu_len; return bvlc_send_mpdu(&bvlc_dest, mtu, mtu_len); } +#endif + + +/*********************************************** + * Functions to register us as a foreign device. + ********************************************* */ + +static int bvlc_encode_register_foreign_device( + uint8_t * pdu, + uint16_t time_to_live_seconds) +{ + int len = 0; + + if (pdu) { + pdu[0] = BVLL_TYPE_BACNET_IP; + pdu[1] = BVLC_REGISTER_FOREIGN_DEVICE; + /* The 2-octet BVLC Length field is the length, in octets, + of the entire BVLL message, including the two octets of the + length field itself, most significant octet first. */ + encode_unsigned16(&pdu[2], 6); + encode_unsigned16(&pdu[4], time_to_live_seconds); + len = 6; + } + + return len; +} + + +/** Register as a foreign device with the indicated BBMD. + * @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. + * @return Positive number (of bytes sent) on success, + * 0 if no registration request is sent, or + * -1 if registration fails. + */ +int bvlc_register_with_bbmd( + uint32_t bbmd_address, + uint16_t bbmd_port, + uint16_t time_to_live_seconds) +{ + uint8_t mtu[MAX_MPDU] = { 0 }; + uint16_t mtu_len = 0; + int retval = 0; + + /* Store the BBMD address and port so that we + won't broadcast locally. */ + Remote_BBMD.sin_addr.s_addr = bbmd_address; + Remote_BBMD.sin_port = bbmd_port; + /* In order for their broadcasts to get here, + we need to register our address with the remote BBMD using + Write Broadcast Distribution Table, or + register with the BBMD as a Foreign Device */ + mtu_len = + (uint16_t) bvlc_encode_register_foreign_device(&mtu[0], + time_to_live_seconds); + retval = bvlc_send_mpdu(&Remote_BBMD, &mtu[0], mtu_len); + return retval; +} + + #ifdef TEST #include