/************************************************************************** * * Copyright (C) 2012 Steve Karg * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *********************************************************************/ #ifndef BVLC_H #define BVLC_H #include #include #include #include "bacnet/bacdef.h" #include "bacnet/npdu.h" /** * BVLL for BACnet/IPv4 * @{ */ #define BVLL_TYPE_BACNET_IP (0x81) /** @} */ /** * B/IPv4 BVLL Messages * @{ */ #define BVLC_RESULT 0 #define BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE 1 #define BVLC_READ_BROADCAST_DIST_TABLE 2 #define BVLC_READ_BROADCAST_DIST_TABLE_ACK 3 #define BVLC_FORWARDED_NPDU 4 #define BVLC_REGISTER_FOREIGN_DEVICE 5 #define BVLC_READ_FOREIGN_DEVICE_TABLE 6 #define BVLC_READ_FOREIGN_DEVICE_TABLE_ACK 7 #define BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY 8 #define BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK 9 #define BVLC_ORIGINAL_UNICAST_NPDU 10 #define BVLC_ORIGINAL_BROADCAST_NPDU 11 #define BVLC_SECURE_BVLL 12 #define BVLC_INVALID 255 /** @} */ /** * BVLC Result Code * @{ */ #define BVLC_RESULT_SUCCESSFUL_COMPLETION 0x0000 #define BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK 0x0010 #define BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK 0x0020 #define BVLC_RESULT_REGISTER_FOREIGN_DEVICE_NAK 0X0030 #define BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK 0x0040 #define BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK 0x0050 #define BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK 0x0060 #define BVLC_RESULT_INVALID 0xFFFF /* number of bytes in the IPv4 address */ #define IP_ADDRESS_MAX 4 /** * BACnet IPv4 Address * * Data link layer addressing between B/IPv4 nodes consists of a 32-bit * IPv4 address followed by a two-octet UDP port number (both of which * shall be transmitted with the most significant octet first). * This address shall be referred to as a B/IPv4 address. * @{ */ typedef struct BACnet_IP_Address { uint8_t address[IP_ADDRESS_MAX]; uint16_t port; } BACNET_IP_ADDRESS; /* number of bytes in the B/IPv4 address */ #define BIP_ADDRESS_MAX 6 /** * BACnet IPv4 Broadcast Distribution Mask * * The Broadcast Distribution Mask is a 4-octet field that * indicates how broadcast messages are to be distributed on * the IP subnet served by the BBMD. * @{ */ typedef struct BACnet_IP_Broadcast_Distribution_Mask { uint8_t address[IP_ADDRESS_MAX]; } BACNET_IP_BROADCAST_DISTRIBUTION_MASK; /* number of bytes in the B/IPv4 Broadcast Distribution Mask */ #define BACNET_IP_BDT_MASK_SIZE IP_ADDRESS_MAX /** @} */ /** * BACnet/IP Broadcast Distribution Table (BDT) * * The BDT consists of one entry for the address of the BBMD * for the local IP subnet and an entry for the BBMD on each * remote IP subnet to which broadcasts are to be forwarded. * Each entry consists of the 6-octet B/IP address with which * the BBMD is accessed and a 4-octet broadcast distribution mask. * @{ */ struct BACnet_IP_Broadcast_Distribution_Table_Entry; typedef struct BACnet_IP_Broadcast_Distribution_Table_Entry { /* true if valid entry - false if not */ bool valid; /* BACnet/IP address */ BACNET_IP_ADDRESS dest_address; /* Broadcast Distribution Mask */ BACNET_IP_BROADCAST_DISTRIBUTION_MASK broadcast_mask; struct BACnet_IP_Broadcast_Distribution_Table_Entry *next; } BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY; /* number of bytes in a B/IPv4 roadcast Distribution Table entry */ #define BACNET_IP_BDT_ENTRY_SIZE (BIP_ADDRESS_MAX + BACNET_IP_BDT_MASK_SIZE) /** @} */ /** * Foreign Device Table (FDT) * * Each device that registers as a foreign device shall be placed * in an entry in the BBMD's Foreign Device Table (FDT). Each * entry shall consist of the 6-octet B/IP address of the registrant; * the 2-octet Time-to-Live value supplied at the time of * registration; and a 2-octet value representing the number of * seconds remaining before the BBMD will purge the registrant's FDT * entry if no re-registration occurs. This value will be initialized * to the 2-octet Time-to-Live value supplied at the time of * registration. * @{ */ struct BACnet_IP_Foreign_Device_Table_Entry; typedef struct BACnet_IP_Foreign_Device_Table_Entry { bool valid; /* BACnet/IP address */ BACNET_IP_ADDRESS dest_address; /* requested time-to-live value */ uint16_t ttl_seconds; /* our counter - includes 30 second grace period */ uint16_t ttl_seconds_remaining; struct BACnet_IP_Foreign_Device_Table_Entry *next; } BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY; #define BACNET_IP_FDT_ENTRY_SIZE 10 /** @} */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ BACNET_STACK_EXPORT int bvlc_encode_address( uint8_t *pdu, uint16_t pdu_size, const BACNET_IP_ADDRESS *ip_address); BACNET_STACK_EXPORT int bvlc_decode_address( uint8_t *pdu, uint16_t pdu_len, BACNET_IP_ADDRESS *ip_address); BACNET_STACK_EXPORT bool bvlc_address_copy(BACNET_IP_ADDRESS *dst, const BACNET_IP_ADDRESS *src); BACNET_STACK_EXPORT bool bvlc_address_different( const BACNET_IP_ADDRESS *dst, const BACNET_IP_ADDRESS *src); BACNET_STACK_EXPORT bool bvlc_address_from_ascii(BACNET_IP_ADDRESS *dst, const char *addrstr); BACNET_STACK_EXPORT bool bvlc_address_port_from_ascii( BACNET_IP_ADDRESS *dst, const char *addrstr, const char *portstr); BACNET_STACK_EXPORT void bvlc_address_from_network(BACNET_IP_ADDRESS *dst, uint32_t addr); BACNET_STACK_EXPORT bool bvlc_address_set(BACNET_IP_ADDRESS *addr, uint8_t addr0, uint8_t addr1, uint8_t addr2, uint8_t addr3); BACNET_STACK_EXPORT bool bvlc_address_get(BACNET_IP_ADDRESS *addr, uint8_t *addr0, uint8_t *addr1, uint8_t *addr2, uint8_t *addr3); BACNET_STACK_EXPORT bool bvlc_ip_address_to_bacnet_local( BACNET_ADDRESS *addr, BACNET_IP_ADDRESS *ipaddr); BACNET_STACK_EXPORT bool bvlc_ip_address_from_bacnet_local( BACNET_IP_ADDRESS *ipaddr, BACNET_ADDRESS *addr); BACNET_STACK_EXPORT bool bvlc_ip_address_to_bacnet_remote( BACNET_ADDRESS *addr, uint16_t dnet, BACNET_IP_ADDRESS *ipaddr); BACNET_STACK_EXPORT bool bvlc_ip_address_from_bacnet_remote( BACNET_IP_ADDRESS *ipaddr, uint16_t *dnet, BACNET_ADDRESS *addr); BACNET_STACK_EXPORT int bvlc_encode_broadcast_distribution_mask(uint8_t *pdu, uint16_t pdu_size, BACNET_IP_BROADCAST_DISTRIBUTION_MASK *bd_mask); BACNET_STACK_EXPORT int bvlc_decode_broadcast_distribution_mask(uint8_t *pdu, uint16_t pdu_len, BACNET_IP_BROADCAST_DISTRIBUTION_MASK *bd_mask); BACNET_STACK_EXPORT int bvlc_encode_broadcast_distribution_table_entry(uint8_t *pdu, uint16_t pdu_size, BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_entry); BACNET_STACK_EXPORT int bvlc_decode_broadcast_distribution_table_entry(uint8_t *pdu, uint16_t pdu_len, BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_entry); BACNET_STACK_EXPORT void bvlc_broadcast_distribution_table_link_array( BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list, const size_t bdt_array_size); BACNET_STACK_EXPORT uint16_t bvlc_broadcast_distribution_table_count( BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list); BACNET_STACK_EXPORT uint16_t bvlc_broadcast_distribution_table_valid_count( BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list); BACNET_STACK_EXPORT void bvlc_broadcast_distribution_table_valid_clear( BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list); BACNET_STACK_EXPORT bool bvlc_broadcast_distribution_table_entry_different( BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *dst, BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *src); BACNET_STACK_EXPORT bool bvlc_broadcast_distribution_table_entry_copy( BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *dst, BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *src); BACNET_STACK_EXPORT bool bvlc_broadcast_distribution_mask_different( BACNET_IP_BROADCAST_DISTRIBUTION_MASK *dst, BACNET_IP_BROADCAST_DISTRIBUTION_MASK *src); BACNET_STACK_EXPORT bool bvlc_broadcast_distribution_mask_copy( BACNET_IP_BROADCAST_DISTRIBUTION_MASK *dst, BACNET_IP_BROADCAST_DISTRIBUTION_MASK *src); BACNET_STACK_EXPORT bool bvlc_broadcast_distribution_table_entry_append( BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list, BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_entry); BACNET_STACK_EXPORT bool bvlc_broadcast_distribution_table_entry_set( BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_entry, BACNET_IP_ADDRESS *addr, BACNET_IP_BROADCAST_DISTRIBUTION_MASK *mask); BACNET_STACK_EXPORT bool bvlc_broadcast_distribution_table_entry_forward_address( BACNET_IP_ADDRESS *addr, BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_entry); BACNET_STACK_EXPORT bool bvlc_address_mask( BACNET_IP_ADDRESS *dst, const BACNET_IP_ADDRESS *src, const BACNET_IP_BROADCAST_DISTRIBUTION_MASK *mask); BACNET_STACK_EXPORT bool bvlc_broadcast_distribution_mask_from_host( BACNET_IP_BROADCAST_DISTRIBUTION_MASK *mask, uint32_t broadcast_mask); BACNET_STACK_EXPORT bool bvlc_broadcast_distribution_mask_to_host( uint32_t *broadcast_mask, BACNET_IP_BROADCAST_DISTRIBUTION_MASK *mask); BACNET_STACK_EXPORT void bvlc_broadcast_distribution_mask_set( BACNET_IP_BROADCAST_DISTRIBUTION_MASK *mask, uint8_t addr0, uint8_t addr1, uint8_t addr2, uint8_t addr3); BACNET_STACK_EXPORT void bvlc_broadcast_distribution_mask_get( BACNET_IP_BROADCAST_DISTRIBUTION_MASK *mask, uint8_t *addr0, uint8_t *addr1, uint8_t *addr2, uint8_t *addr3); BACNET_STACK_EXPORT int bvlc_broadcast_distribution_table_decode(uint8_t *apdu, uint16_t apdu_len, BACNET_ERROR_CODE *error_code, BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_head); BACNET_STACK_EXPORT int bvlc_broadcast_distribution_table_encode(uint8_t *apdu, uint16_t apdu_size, BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_head); BACNET_STACK_EXPORT int bvlc_encode_write_broadcast_distribution_table(uint8_t *pdu, uint16_t pdu_size, BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list); BACNET_STACK_EXPORT int bvlc_decode_write_broadcast_distribution_table(uint8_t *pdu, uint16_t pdu_len, BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list); BACNET_STACK_EXPORT int bvlc_encode_read_broadcast_distribution_table( uint8_t *pdu, uint16_t pdu_size); BACNET_STACK_EXPORT int bvlc_encode_read_broadcast_distribution_table_ack(uint8_t *pdu, uint16_t pdu_size, BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list); BACNET_STACK_EXPORT int bvlc_decode_read_broadcast_distribution_table_ack(uint8_t *pdu, uint16_t pdu_len, BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *bdt_list); BACNET_STACK_EXPORT int bvlc_encode_header( uint8_t *pdu, uint16_t pdu_size, uint8_t message_type, uint16_t length); BACNET_STACK_EXPORT int bvlc_decode_header( uint8_t *pdu, uint16_t pdu_len, uint8_t *message_type, uint16_t *length); BACNET_STACK_EXPORT void bvlc_foreign_device_table_maintenance_timer( BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list, uint16_t seconds); BACNET_STACK_EXPORT uint16_t bvlc_foreign_device_table_valid_count( BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list); BACNET_STACK_EXPORT uint16_t bvlc_foreign_device_table_count( BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list); BACNET_STACK_EXPORT void bvlc_foreign_device_table_link_array( BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list, const size_t array_size); BACNET_STACK_EXPORT bool bvlc_foreign_device_table_entry_different( BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *dst, BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *src); BACNET_STACK_EXPORT bool bvlc_foreign_device_table_entry_copy( BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *dst, BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *src); BACNET_STACK_EXPORT bool bvlc_foreign_device_table_entry_delete( BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list, BACNET_IP_ADDRESS *ip_address); BACNET_STACK_EXPORT bool bvlc_foreign_device_table_entry_add( BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list, BACNET_IP_ADDRESS *ip_address, uint16_t ttl_seconds); BACNET_STACK_EXPORT int bvlc_encode_foreign_device_table_entry(uint8_t *pdu, uint16_t pdu_size, BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_entry); BACNET_STACK_EXPORT int bvlc_decode_foreign_device_table_entry(uint8_t *pdu, uint16_t pdu_len, BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_entry); BACNET_STACK_EXPORT int bvlc_foreign_device_table_encode(uint8_t *apdu, uint16_t apdu_size, BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_head); BACNET_STACK_EXPORT int bvlc_encode_read_foreign_device_table(uint8_t *pdu, uint16_t pdu_size); BACNET_STACK_EXPORT int bvlc_encode_read_foreign_device_table_ack(uint8_t *pdu, uint16_t pdu_size, BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list); BACNET_STACK_EXPORT int bvlc_decode_read_foreign_device_table_ack(uint8_t *pdu, uint16_t pdu_len, BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *fdt_list); BACNET_STACK_EXPORT int bvlc_encode_result(uint8_t *pdu, uint16_t pdu_size, uint16_t result_code); BACNET_STACK_EXPORT int bvlc_decode_result(uint8_t *pdu, uint16_t pdu_len, uint16_t *result_code); BACNET_STACK_EXPORT int bvlc_encode_original_unicast( uint8_t *pdu, uint16_t pdu_size, uint8_t *npdu, uint16_t npdu_len); BACNET_STACK_EXPORT int bvlc_decode_original_unicast(uint8_t *pdu, uint16_t pdu_len, uint8_t *npdu, uint16_t npdu_size, uint16_t *npdu_len); BACNET_STACK_EXPORT int bvlc_encode_original_broadcast( uint8_t *pdu, uint16_t pdu_size, uint8_t *npdu, uint16_t npdu_len); BACNET_STACK_EXPORT int bvlc_decode_original_broadcast(uint8_t *pdu, uint16_t pdu_len, uint8_t *npdu, uint16_t npdu_size, uint16_t *npdu_len); BACNET_STACK_EXPORT int bvlc_encode_forwarded_npdu(uint8_t *pdu, uint16_t pdu_size, BACNET_IP_ADDRESS *address, uint8_t *npdu, uint16_t npdu_len); BACNET_STACK_EXPORT int bvlc_decode_forwarded_npdu(uint8_t *pdu, uint16_t pdu_len, BACNET_IP_ADDRESS *address, uint8_t *npdu, uint16_t npdu_size, uint16_t *npdu_len); BACNET_STACK_EXPORT int bvlc_encode_register_foreign_device( uint8_t *pdu, uint16_t pdu_size, uint16_t ttl_seconds); BACNET_STACK_EXPORT int bvlc_decode_register_foreign_device( uint8_t *pdu, uint16_t pdu_len, uint16_t *ttl_seconds); BACNET_STACK_EXPORT int bvlc_encode_delete_foreign_device( uint8_t *pdu, uint16_t pdu_size, BACNET_IP_ADDRESS *ip_address); BACNET_STACK_EXPORT int bvlc_decode_delete_foreign_device( uint8_t *pdu, uint16_t pdu_len, BACNET_IP_ADDRESS *ip_address); BACNET_STACK_EXPORT int bvlc_encode_secure_bvll( uint8_t *pdu, uint16_t pdu_size, uint8_t *sbuf, uint16_t sbuf_len); BACNET_STACK_EXPORT int bvlc_decode_secure_bvll(uint8_t *pdu, uint16_t pdu_len, uint8_t *sbuf, uint16_t sbuf_size, uint16_t *sbuf_len); BACNET_STACK_EXPORT int bvlc_encode_distribute_broadcast_to_network( uint8_t *pdu, uint16_t pdu_size, uint8_t *npdu, uint16_t npdu_len); BACNET_STACK_EXPORT int bvlc_decode_distribute_broadcast_to_network(uint8_t *pdu, uint16_t pdu_len, uint8_t *npdu, uint16_t npdu_size, uint16_t *npdu_len); BACNET_STACK_EXPORT const char *bvlc_result_code_name(uint16_t result_code); #ifdef BAC_TEST #include "ctest.h" BACNET_STACK_EXPORT void test_BVLC(Test *pTest); #endif #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* */