Fixed network port object to accept host name option of host-n-port writes. (#997)
This commit is contained in:
@@ -498,6 +498,35 @@ bool characterstring_ansi_copy(
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy a BACnetCharacterString into a buffer with null padding
|
||||
* @param dest Pointer to the destination buffer.
|
||||
* @param dest_max_len Size of the destination buffer.
|
||||
* @param src Pointer to the source BACnetCharacterString.
|
||||
* @return Length of the copied BACnetCharacterString, or 0 if the string
|
||||
* exceeds the destination buffer size.
|
||||
*/
|
||||
size_t characterstring_copy_value(
|
||||
char *dest, size_t dest_max_len, const BACNET_CHARACTER_STRING *src)
|
||||
{
|
||||
size_t i = 0, length = 0;
|
||||
|
||||
if (dest && src) {
|
||||
if (src->length < dest_max_len) {
|
||||
length = src->length;
|
||||
for (i = 0; i < dest_max_len; i++) {
|
||||
if (i < src->length) {
|
||||
dest[i] = src->value[i];
|
||||
} else {
|
||||
dest[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the character encoding and string
|
||||
* contents are the same.
|
||||
|
||||
@@ -89,6 +89,9 @@ BACNET_STACK_EXPORT
|
||||
bool characterstring_copy(
|
||||
BACNET_CHARACTER_STRING *dest, const BACNET_CHARACTER_STRING *src);
|
||||
BACNET_STACK_EXPORT
|
||||
size_t characterstring_copy_value(
|
||||
char *dest, size_t dest_max_len, const BACNET_CHARACTER_STRING *src);
|
||||
BACNET_STACK_EXPORT
|
||||
bool characterstring_ansi_copy(
|
||||
char *dest, size_t dest_max_len, const BACNET_CHARACTER_STRING *src);
|
||||
/* returns true if the strings are the same length, encoding, value */
|
||||
|
||||
+427
-113
@@ -18,6 +18,7 @@
|
||||
#include "bacnet/bacapp.h"
|
||||
#include "bacnet/bacint.h"
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/datetime.h"
|
||||
#include "bacnet/npdu.h"
|
||||
#include "bacnet/apdu.h"
|
||||
#include "bacnet/datalink/bvlc.h"
|
||||
@@ -33,26 +34,26 @@
|
||||
#define BBMD_ENABLED 1
|
||||
#endif
|
||||
|
||||
#define IPV4_ADDR_SIZE 4
|
||||
#define BIP_DNS_MAX 3
|
||||
struct bacnet_ipv4_port {
|
||||
uint8_t IP_Address[4];
|
||||
uint8_t IP_Address[IPV4_ADDR_SIZE];
|
||||
uint8_t IP_Subnet_Prefix;
|
||||
uint8_t IP_Gateway[4];
|
||||
uint8_t IP_DNS_Server[BIP_DNS_MAX][4];
|
||||
uint8_t IP_Gateway[IPV4_ADDR_SIZE];
|
||||
uint8_t IP_DNS_Server[BIP_DNS_MAX][IPV4_ADDR_SIZE];
|
||||
uint16_t Port;
|
||||
BACNET_IP_MODE Mode;
|
||||
bool IP_DHCP_Enable;
|
||||
uint32_t IP_DHCP_Lease_Seconds;
|
||||
uint32_t IP_DHCP_Lease_Seconds_Remaining;
|
||||
uint8_t IP_DHCP_Server[4];
|
||||
uint32_t IP_DHCP_Lease_Seconds_Start;
|
||||
uint8_t IP_DHCP_Server[IPV4_ADDR_SIZE];
|
||||
bool IP_NAT_Traversal;
|
||||
uint32_t IP_Global_Address[4];
|
||||
uint32_t IP_Global_Address[IPV4_ADDR_SIZE];
|
||||
bool BBMD_Accept_FD_Registrations;
|
||||
void *BBMD_BD_Table;
|
||||
void *BBMD_FD_Table;
|
||||
/* used for foreign device registration to remote BBMD */
|
||||
uint8_t BBMD_IP_Address[4];
|
||||
uint16_t BBMD_Port;
|
||||
BACNET_HOST_N_PORT_MINIMAL BBMD_Address;
|
||||
uint16_t BBMD_Lifetime;
|
||||
};
|
||||
|
||||
@@ -65,17 +66,18 @@ struct bacnet_ipv6_port {
|
||||
uint8_t IP_Gateway[IPV6_ADDR_SIZE];
|
||||
uint8_t IP_DNS_Server[BIP_DNS_MAX][IPV6_ADDR_SIZE];
|
||||
uint8_t IP_Multicast_Address[IPV6_ADDR_SIZE];
|
||||
bool IP_DHCP_Enable;
|
||||
uint8_t IP_DHCP_Server[IPV6_ADDR_SIZE];
|
||||
uint32_t IP_DHCP_Lease_Seconds;
|
||||
uint32_t IP_DHCP_Lease_Seconds_Start;
|
||||
uint16_t Port;
|
||||
BACNET_IP_MODE Mode;
|
||||
bool Auto_Addressing_Enable;
|
||||
char Zone_Index[ZONE_INDEX_SIZE];
|
||||
bool BBMD_Accept_FD_Registrations;
|
||||
void *BBMD_BD_Table;
|
||||
void *BBMD_FD_Table;
|
||||
/* used for foreign device registration to remote BBMD */
|
||||
uint8_t BBMD_IP_Address[16];
|
||||
uint16_t BBMD_Port;
|
||||
BACNET_HOST_N_PORT_MINIMAL BBMD_Address;
|
||||
uint16_t BBMD_Lifetime;
|
||||
};
|
||||
|
||||
@@ -184,6 +186,9 @@ static const int BIP_Port_Properties_Optional[] = {
|
||||
PROP_IP_DNS_SERVER,
|
||||
#if defined(BACDL_BIP) && (BACNET_NETWORK_PORT_IP_DHCP_ENABLED)
|
||||
PROP_IP_DHCP_ENABLE,
|
||||
PROP_IP_DHCP_LEASE_TIME,
|
||||
PROP_IP_DHCP_LEASE_TIME_REMAINING,
|
||||
PROP_IP_DHCP_SERVER,
|
||||
#endif
|
||||
#if defined(BACDL_BIP) && (BBMD_ENABLED)
|
||||
PROP_BBMD_ACCEPT_FD_REGISTRATIONS,
|
||||
@@ -214,10 +219,12 @@ static const int BIP6_Port_Properties_Optional[] = {
|
||||
PROP_IPV6_DEFAULT_GATEWAY,
|
||||
PROP_BACNET_IPV6_MULTICAST_ADDRESS,
|
||||
PROP_IPV6_DNS_SERVER,
|
||||
#if defined(BACDL_BIP6) && (BACNET_NETWORK_PORT_IP_DHCP_ENABLED)
|
||||
PROP_IPV6_AUTO_ADDRESSING_ENABLE,
|
||||
PROP_IPV6_DHCP_LEASE_TIME,
|
||||
PROP_IPV6_DHCP_LEASE_TIME_REMAINING,
|
||||
PROP_IPV6_DHCP_SERVER,
|
||||
#endif
|
||||
PROP_IPV6_ZONE_INDEX,
|
||||
#if defined(BACDL_BIP6) && (BBMD_ENABLED)
|
||||
PROP_BBMD_ACCEPT_FD_REGISTRATIONS,
|
||||
@@ -1487,6 +1494,8 @@ bool Network_Port_IP_DHCP_Enable(uint32_t object_instance)
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
if (Object_List[index].Network_Type == PORT_TYPE_BIP) {
|
||||
dhcp_enable = Object_List[index].Network.IPv4.IP_DHCP_Enable;
|
||||
} else if (Object_List[index].Network_Type == PORT_TYPE_BIP6) {
|
||||
dhcp_enable = Object_List[index].Network.IPv6.IP_DHCP_Enable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1509,8 +1518,17 @@ bool Network_Port_IP_DHCP_Enable_Set(uint32_t object_instance, bool value)
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
if (Object_List[index].Network_Type == PORT_TYPE_BIP) {
|
||||
if (Object_List[index].Network.IPv4.IP_DHCP_Enable != value) {
|
||||
Object_List[index].Changes_Pending = true;
|
||||
}
|
||||
Object_List[index].Network.IPv4.IP_DHCP_Enable = value;
|
||||
status = true;
|
||||
} else if (Object_List[index].Network_Type == PORT_TYPE_BIP6) {
|
||||
if (Object_List[index].Network.IPv6.IP_DHCP_Enable != value) {
|
||||
Object_List[index].Changes_Pending = true;
|
||||
}
|
||||
Object_List[index].Network.IPv6.IP_DHCP_Enable = value;
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1602,11 +1620,19 @@ bool Network_Port_IP_DNS_Server_Set(
|
||||
{
|
||||
unsigned index = 0; /* offset from instance lookup */
|
||||
bool status = false;
|
||||
uint8_t *dns_server = NULL;
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
if (Object_List[index].Network_Type == PORT_TYPE_BIP) {
|
||||
if (dns_index < BIP_DNS_MAX) {
|
||||
dns_server = &Object_List[index]
|
||||
.Network.IPv4.IP_DNS_Server[dns_index][0];
|
||||
if ((dns_server[0] != a) || (dns_server[1] != b) ||
|
||||
(dns_server[2] != c) || (dns_server[3] != d)) {
|
||||
/* octets are different, set changes pending */
|
||||
Object_List[index].Changes_Pending = true;
|
||||
}
|
||||
Object_List[index].Network.IPv4.IP_DNS_Server[dns_index][0] = a;
|
||||
Object_List[index].Network.IPv4.IP_DNS_Server[dns_index][1] = b;
|
||||
Object_List[index].Network.IPv4.IP_DNS_Server[dns_index][2] = c;
|
||||
@@ -1954,6 +1980,72 @@ static int BBMD_Foreign_Device_Table_Encode(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For a given object instance-number, gets the HostNPort
|
||||
* @note depends on Network_Type being set for this object
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param bbmd_address - BACNET_HOST_N_PORT structure
|
||||
* @return true if BBMD Address was copied
|
||||
*/
|
||||
bool Network_Port_Remote_BBMD_Address(
|
||||
uint32_t object_instance, BACNET_HOST_N_PORT *bbmd_address)
|
||||
{
|
||||
bool status = false;
|
||||
unsigned index;
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
if (Object_List[index].Network_Type == PORT_TYPE_BIP) {
|
||||
status = host_n_port_from_minimal(
|
||||
bbmd_address, &Object_List[index].Network.IPv4.BBMD_Address);
|
||||
} else if (Object_List[index].Network_Type == PORT_TYPE_BIP6) {
|
||||
status = host_n_port_from_minimal(
|
||||
bbmd_address, &Object_List[index].Network.IPv6.BBMD_Address);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For a given object instance-number, sets the FD BBMD Address:
|
||||
* either as IP address or a hostname.
|
||||
* @note depends on Network_Type being set for this object
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param bbmd_address - BACNET_HOST_N_PORT FD_BBMD_Address
|
||||
* @return true if BBMD Address was set
|
||||
*/
|
||||
bool Network_Port_Remote_BBMD_Address_Set(
|
||||
uint32_t object_instance, const BACNET_HOST_N_PORT *bbmd_address)
|
||||
{
|
||||
bool status = false;
|
||||
BACNET_HOST_N_PORT_MINIMAL bbmd_address_minimal = { 0 };
|
||||
BACNET_HOST_N_PORT_MINIMAL *dest_bbmd_address = NULL;
|
||||
unsigned index;
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
if (Object_List[index].Network_Type == PORT_TYPE_BIP) {
|
||||
dest_bbmd_address = &Object_List[index].Network.IPv4.BBMD_Address;
|
||||
} else if (Object_List[index].Network_Type == PORT_TYPE_BIP6) {
|
||||
dest_bbmd_address = &Object_List[index].Network.IPv6.BBMD_Address;
|
||||
}
|
||||
if (dest_bbmd_address) {
|
||||
status =
|
||||
host_n_port_to_minimal(&bbmd_address_minimal, bbmd_address);
|
||||
if (status) {
|
||||
if (!host_n_port_minimal_same(
|
||||
dest_bbmd_address, &bbmd_address_minimal)) {
|
||||
host_n_port_to_minimal(dest_bbmd_address, bbmd_address);
|
||||
Object_List[index].Changes_Pending = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given object instance-number, loads the ip-address into
|
||||
* an octet string.
|
||||
@@ -1972,23 +2064,27 @@ bool Network_Port_Remote_BBMD_IP_Address(
|
||||
{
|
||||
unsigned index = 0; /* offset from instance lookup */
|
||||
bool status = false;
|
||||
BACNET_HOST_N_PORT_MINIMAL *address;
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
if (Object_List[index].Network_Type == PORT_TYPE_BIP) {
|
||||
if (a) {
|
||||
*a = Object_List[index].Network.IPv4.BBMD_IP_Address[0];
|
||||
address = &Object_List[index].Network.IPv4.BBMD_Address;
|
||||
if (address->tag == BACNET_HOST_ADDRESS_TAG_IP_ADDRESS) {
|
||||
if (a) {
|
||||
*a = address->host.ip_address.address[0];
|
||||
}
|
||||
if (b) {
|
||||
*b = address->host.ip_address.address[1];
|
||||
}
|
||||
if (c) {
|
||||
*c = address->host.ip_address.address[2];
|
||||
}
|
||||
if (d) {
|
||||
*d = address->host.ip_address.address[3];
|
||||
}
|
||||
status = true;
|
||||
}
|
||||
if (b) {
|
||||
*b = Object_List[index].Network.IPv4.BBMD_IP_Address[1];
|
||||
}
|
||||
if (c) {
|
||||
*c = Object_List[index].Network.IPv4.BBMD_IP_Address[2];
|
||||
}
|
||||
if (d) {
|
||||
*d = Object_List[index].Network.IPv4.BBMD_IP_Address[3];
|
||||
}
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2012,21 +2108,25 @@ bool Network_Port_Remote_BBMD_IP_Address_Set(
|
||||
{
|
||||
unsigned index = 0; /* offset from instance lookup */
|
||||
bool status = false;
|
||||
BACNET_HOST_N_PORT_MINIMAL *address;
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
if (Object_List[index].Network_Type == PORT_TYPE_BIP) {
|
||||
if ((Object_List[index].Network.IPv4.BBMD_IP_Address[0] != a) ||
|
||||
(Object_List[index].Network.IPv4.BBMD_IP_Address[1] != b) ||
|
||||
(Object_List[index].Network.IPv4.BBMD_IP_Address[2] != c) ||
|
||||
(Object_List[index].Network.IPv4.BBMD_IP_Address[3] != d)) {
|
||||
address = &Object_List[index].Network.IPv4.BBMD_Address;
|
||||
if ((address->host.ip_address.address[0] != a) ||
|
||||
(address->host.ip_address.address[1] != b) ||
|
||||
(address->host.ip_address.address[2] != c) ||
|
||||
(address->host.ip_address.address[3] != d) ||
|
||||
(address->tag != BACNET_HOST_ADDRESS_TAG_IP_ADDRESS)) {
|
||||
Object_List[index].Changes_Pending = true;
|
||||
}
|
||||
Object_List[index].Network.IPv4.BBMD_IP_Address[0] = a;
|
||||
Object_List[index].Network.IPv4.BBMD_IP_Address[1] = b;
|
||||
Object_List[index].Network.IPv4.BBMD_IP_Address[2] = c;
|
||||
Object_List[index].Network.IPv4.BBMD_IP_Address[3] = d;
|
||||
|
||||
address->host.ip_address.address[0] = a;
|
||||
address->host.ip_address.address[1] = b;
|
||||
address->host.ip_address.address[2] = c;
|
||||
address->host.ip_address.address[3] = d;
|
||||
address->host.ip_address.length = 4;
|
||||
address->tag = BACNET_HOST_ADDRESS_TAG_IP_ADDRESS;
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
@@ -2050,7 +2150,7 @@ uint16_t Network_Port_Remote_BBMD_BIP_Port(uint32_t object_instance)
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
if (Object_List[index].Network_Type == PORT_TYPE_BIP) {
|
||||
value = Object_List[index].Network.IPv4.BBMD_Port;
|
||||
value = Object_List[index].Network.IPv4.BBMD_Address.port;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2075,10 +2175,10 @@ bool Network_Port_Remote_BBMD_BIP_Port_Set(
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
if (Object_List[index].Network_Type == PORT_TYPE_BIP) {
|
||||
if (Object_List[index].Network.IPv4.BBMD_Port != value) {
|
||||
if (Object_List[index].Network.IPv4.BBMD_Address.port != value) {
|
||||
Object_List[index].Changes_Pending = true;
|
||||
}
|
||||
Object_List[index].Network.IPv4.BBMD_Port = value;
|
||||
Object_List[index].Network.IPv4.BBMD_Address.port = value;
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
@@ -2139,9 +2239,9 @@ bool Network_Port_Remote_BBMD_BIP_Lifetime_Set(
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the foreign device subscription lifetime
|
||||
* @brief Get the foreign device subscription lifetime seconds
|
||||
* @param object_instance [in] BACnet network port object instance number
|
||||
* @return foreign device subscription lifetime
|
||||
* @return foreign device subscription BBMD lifetime seconds
|
||||
*/
|
||||
static uint16_t Foreign_Device_Subscription_Lifetime(uint32_t object_instance)
|
||||
{
|
||||
@@ -2200,21 +2300,7 @@ bool Network_Port_BBMD_IP6_Accept_FD_Registrations(uint32_t object_instance)
|
||||
bool Network_Port_BBMD_IP6_Accept_FD_Registrations_Set(
|
||||
uint32_t object_instance, bool flag)
|
||||
{
|
||||
bool status = false;
|
||||
unsigned index = 0;
|
||||
struct bacnet_ipv6_port *ipv6 = NULL;
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
ipv6 = &Object_List[index].Network.IPv6;
|
||||
if (flag != ipv6->BBMD_Accept_FD_Registrations) {
|
||||
ipv6->BBMD_Accept_FD_Registrations = flag;
|
||||
Object_List[index].Changes_Pending = true;
|
||||
}
|
||||
status = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
return Network_Port_BBMD_Accept_FD_Registrations_Set(object_instance, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2329,35 +2415,20 @@ bool Network_Port_BBMD_IP6_FD_Table_Set(
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param addr - holds the ip-address and port retrieved
|
||||
*
|
||||
* @return true if ip-address and port were retrieved
|
||||
* @return number of bytes encoded, or BACNET_STATUS_ERROR if error
|
||||
*/
|
||||
static int Foreign_Device_BBMD_Address_Encode(
|
||||
uint32_t object_instance, uint8_t *apdu, size_t apdu_size)
|
||||
{
|
||||
unsigned index = 0; /* offset from instance lookup */
|
||||
BACNET_IP_ADDRESS ip4_address;
|
||||
BACNET_IP6_ADDRESS ip6_address;
|
||||
int apdu_len = 0;
|
||||
BACNET_HOST_N_PORT bbmd_address = { 0 };
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
if (Object_List[index].Network_Type == PORT_TYPE_BIP) {
|
||||
bvlc_address_set(
|
||||
&ip4_address,
|
||||
Object_List[index].Network.IPv4.BBMD_IP_Address[0],
|
||||
Object_List[index].Network.IPv4.BBMD_IP_Address[1],
|
||||
Object_List[index].Network.IPv4.BBMD_IP_Address[2],
|
||||
Object_List[index].Network.IPv4.BBMD_IP_Address[3]);
|
||||
ip4_address.port = Object_List[index].Network.IPv4.BBMD_Port;
|
||||
apdu_len = bvlc_foreign_device_bbmd_host_address_encode(
|
||||
apdu, apdu_size, &ip4_address);
|
||||
} else if (Object_List[index].Network_Type == PORT_TYPE_BIP6) {
|
||||
bvlc6_address_n_port_set(
|
||||
&ip6_address, Object_List[index].Network.IPv6.BBMD_IP_Address,
|
||||
Object_List[index].Network.IPv6.BBMD_Port);
|
||||
apdu_len = bvlc6_foreign_device_bbmd_host_address_encode(
|
||||
apdu, apdu_size, &ip6_address);
|
||||
}
|
||||
Network_Port_Remote_BBMD_Address(object_instance, &bbmd_address);
|
||||
apdu_len = host_n_port_encode(NULL, &bbmd_address);
|
||||
if (apdu_len > apdu_size) {
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
} else {
|
||||
apdu_len = host_n_port_encode(apdu, &bbmd_address);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
@@ -2378,14 +2449,19 @@ bool Network_Port_Remote_BBMD_IP6_Address(
|
||||
{
|
||||
unsigned index = 0; /* offset from instance lookup */
|
||||
bool status = false;
|
||||
BACNET_HOST_N_PORT_MINIMAL *address;
|
||||
size_t i;
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
if (Object_List[index].Network_Type == PORT_TYPE_BIP6) {
|
||||
if (addr) {
|
||||
memcpy(
|
||||
addr, Object_List[index].Network.IPv6.BBMD_IP_Address,
|
||||
IP6_ADDRESS_MAX);
|
||||
address = &Object_List[index].Network.IPv6.BBMD_Address;
|
||||
if (address->tag == BACNET_HOST_ADDRESS_TAG_IP_ADDRESS) {
|
||||
if (addr) {
|
||||
for (i = 0; i < IP6_ADDRESS_MAX; i++) {
|
||||
addr[i] = address->host.ip_address.address[i];
|
||||
}
|
||||
}
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
@@ -2408,19 +2484,22 @@ bool Network_Port_Remote_BBMD_IP6_Address_Set(
|
||||
{
|
||||
unsigned index = 0; /* offset from instance lookup */
|
||||
bool status = false;
|
||||
BACNET_HOST_N_PORT_MINIMAL bbmd_address = { 0 };
|
||||
uint16_t port;
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
if (Object_List[index].Network_Type == PORT_TYPE_BIP6) {
|
||||
if (memcmp(
|
||||
Object_List[index].Network.IPv6.BBMD_IP_Address, addr,
|
||||
IP6_ADDRESS_MAX)) {
|
||||
memcpy(
|
||||
Object_List[index].Network.IPv6.BBMD_IP_Address, addr,
|
||||
IP6_ADDRESS_MAX);
|
||||
port = Object_List[index].Network.IPv6.BBMD_Address.port;
|
||||
host_n_port_minimal_ip_init(
|
||||
&bbmd_address, port, addr, IP6_ADDRESS_MAX);
|
||||
if (!host_n_port_minimal_same(
|
||||
&Object_List[index].Network.IPv6.BBMD_Address,
|
||||
&bbmd_address)) {
|
||||
Object_List[index].Changes_Pending = true;
|
||||
}
|
||||
status = true;
|
||||
status = host_n_port_minimal_copy(
|
||||
&Object_List[index].Network.IPv6.BBMD_Address, &bbmd_address);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2443,7 +2522,7 @@ uint16_t Network_Port_Remote_BBMD_BIP6_Port(uint32_t object_instance)
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
if (Object_List[index].Network_Type == PORT_TYPE_BIP6) {
|
||||
value = Object_List[index].Network.IPv6.BBMD_Port;
|
||||
value = Object_List[index].Network.IPv6.BBMD_Address.port;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2468,10 +2547,10 @@ bool Network_Port_Remote_BBMD_BIP6_Port_Set(
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
if (Object_List[index].Network_Type == PORT_TYPE_BIP6) {
|
||||
if (Object_List[index].Network.IPv6.BBMD_Port != value) {
|
||||
if (Object_List[index].Network.IPv6.BBMD_Address.port != value) {
|
||||
Object_List[index].Changes_Pending = true;
|
||||
}
|
||||
Object_List[index].Network.IPv6.BBMD_Port = value;
|
||||
Object_List[index].Network.IPv6.BBMD_Address.port = value;
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
@@ -2967,6 +3046,226 @@ bool Network_Port_IPv6_DHCP_Server_Set(
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current time from the Device object
|
||||
* @return current time in epoch seconds
|
||||
*/
|
||||
static bacnet_time_t Network_Port_Epoch_Seconds_Now(void)
|
||||
{
|
||||
BACNET_DATE_TIME bdatetime = { 0 };
|
||||
|
||||
datetime_local(&bdatetime.date, &bdatetime.time, NULL, NULL);
|
||||
return datetime_seconds_since_epoch(&bdatetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given object instance-number, sets the IPv4_DHCP_Lease_Time
|
||||
* or IPv6_DHCP_Lease_Time property value in seconds.
|
||||
*
|
||||
* @note depends on Network_Type being set to
|
||||
* PORT_TYPE_BIP or PORT_TYPE_BIP6 for this object
|
||||
*
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param value - 32 bit IPv4 DHCP Lease Time in seconds
|
||||
*
|
||||
* @return IPv4_DHCP_Lease_Time
|
||||
*/
|
||||
bool Network_Port_IP_DHCP_Lease_Time_Set(
|
||||
uint32_t object_instance, const uint32_t value)
|
||||
{
|
||||
bool status = false;
|
||||
unsigned index = 0;
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
switch (Object_List[index].Network_Type) {
|
||||
case PORT_TYPE_BIP:
|
||||
if (Object_List[index].Network.IPv4.IP_DHCP_Lease_Seconds !=
|
||||
value) {
|
||||
Object_List[index].Changes_Pending = true;
|
||||
}
|
||||
Object_List[index].Network.IPv4.IP_DHCP_Lease_Seconds = value;
|
||||
Object_List[index].Network.IPv4.IP_DHCP_Lease_Seconds_Start =
|
||||
Network_Port_Epoch_Seconds_Now();
|
||||
status = true;
|
||||
break;
|
||||
case PORT_TYPE_BIP6:
|
||||
if (Object_List[index].Network.IPv6.IP_DHCP_Lease_Seconds !=
|
||||
value) {
|
||||
Object_List[index].Changes_Pending = true;
|
||||
}
|
||||
Object_List[index].Network.IPv6.IP_DHCP_Lease_Seconds = value;
|
||||
Object_List[index].Network.IPv6.IP_DHCP_Lease_Seconds_Start =
|
||||
Network_Port_Epoch_Seconds_Now();
|
||||
status = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the DHCP lease time in seconds
|
||||
* @param object_instance [in] BACnet network port object instance number
|
||||
* @return DHCP lease time in seconds
|
||||
*/
|
||||
uint32_t Network_Port_IP_DHCP_Lease_Time(uint32_t object_instance)
|
||||
{
|
||||
uint16_t value = 0;
|
||||
unsigned index = 0;
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
switch (Object_List[index].Network_Type) {
|
||||
case PORT_TYPE_BIP:
|
||||
value = Object_List[index].Network.IPv4.IP_DHCP_Lease_Seconds;
|
||||
break;
|
||||
case PORT_TYPE_BIP6:
|
||||
value = Object_List[index].Network.IPv6.IP_DHCP_Lease_Seconds;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the DHCP lease time in seconds
|
||||
* @param object_instance [in] BACnet network port object instance number
|
||||
* @return DHCP lease time in seconds
|
||||
*/
|
||||
uint32_t Network_Port_IP_DHCP_Lease_Time_Remaining(uint32_t object_instance)
|
||||
{
|
||||
uint32_t value = 0, elapsed_seconds = 0, seconds = 0, start_seconds = 0;
|
||||
unsigned index = 0;
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
switch (Object_List[index].Network_Type) {
|
||||
case PORT_TYPE_BIP:
|
||||
seconds = Object_List[index].Network.IPv4.IP_DHCP_Lease_Seconds;
|
||||
if (seconds) {
|
||||
start_seconds =
|
||||
Object_List[index]
|
||||
.Network.IPv4.IP_DHCP_Lease_Seconds_Start;
|
||||
elapsed_seconds =
|
||||
Network_Port_Epoch_Seconds_Now() - start_seconds;
|
||||
if (elapsed_seconds < seconds) {
|
||||
value = seconds - elapsed_seconds;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PORT_TYPE_BIP6:
|
||||
seconds = Object_List[index].Network.IPv6.IP_DHCP_Lease_Seconds;
|
||||
if (seconds) {
|
||||
start_seconds =
|
||||
Object_List[index]
|
||||
.Network.IPv6.IP_DHCP_Lease_Seconds_Start;
|
||||
elapsed_seconds =
|
||||
Network_Port_Epoch_Seconds_Now() - start_seconds;
|
||||
if (elapsed_seconds < seconds) {
|
||||
value = seconds - elapsed_seconds;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the the address of the DHCP server from which the last DHCP
|
||||
* lease was obtained for the port. If the address of the DHCP server
|
||||
* cannot be determined, the value of this property shall be X'00000000'.
|
||||
* @param object_instance [in] BACnet network port object instance number
|
||||
* @param ip_address [out] pointer to the IP address
|
||||
*/
|
||||
void Network_Port_IP_DHCP_Server(
|
||||
uint32_t object_instance, BACNET_OCTET_STRING *ip_address)
|
||||
{
|
||||
unsigned index = 0;
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
switch (Object_List[index].Network_Type) {
|
||||
case PORT_TYPE_BIP:
|
||||
octetstring_init(
|
||||
ip_address,
|
||||
&Object_List[index].Network.IPv4.IP_DHCP_Server[0],
|
||||
IPV4_ADDR_SIZE);
|
||||
break;
|
||||
case PORT_TYPE_BIP6:
|
||||
octetstring_init(
|
||||
ip_address,
|
||||
&Object_List[index].Network.IPv6.IP_DHCP_Server[0],
|
||||
IPV6_ADDR_SIZE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For a given object instance-number, sets the DHCP server ip-address
|
||||
* @note depends on Network_Type being set for this object
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param ip_address - octet string of the DHCP server address
|
||||
* @return true if ip-address was set
|
||||
*/
|
||||
bool Network_Port_IP_DHCP_Server_Set(
|
||||
uint32_t object_instance, BACNET_OCTET_STRING *ip_address)
|
||||
{
|
||||
bool status = false;
|
||||
unsigned index = 0;
|
||||
BACNET_OCTET_STRING my_address = { 0 };
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
switch (Object_List[index].Network_Type) {
|
||||
case PORT_TYPE_BIP:
|
||||
/* check for changes */
|
||||
octetstring_init(
|
||||
&my_address,
|
||||
&Object_List[index].Network.IPv4.IP_DHCP_Server[0],
|
||||
IPV4_ADDR_SIZE);
|
||||
if (!octetstring_value_same(&my_address, ip_address)) {
|
||||
Object_List[index].Changes_Pending = true;
|
||||
}
|
||||
octetstring_copy_value(
|
||||
&Object_List[index].Network.IPv4.IP_DHCP_Server[0],
|
||||
IPV4_ADDR_SIZE, ip_address);
|
||||
status = true;
|
||||
break;
|
||||
case PORT_TYPE_BIP6:
|
||||
octetstring_init(
|
||||
&my_address,
|
||||
&Object_List[index].Network.IPv6.IP_DHCP_Server[0],
|
||||
IPV6_ADDR_SIZE);
|
||||
if (!octetstring_value_same(&my_address, ip_address)) {
|
||||
Object_List[index].Changes_Pending = true;
|
||||
}
|
||||
octetstring_copy_value(
|
||||
&Object_List[index].Network.IPv6.IP_DHCP_Server[0],
|
||||
IPV6_ADDR_SIZE, ip_address);
|
||||
status = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given object instance-number, gets the BACnet/IP UDP Port number
|
||||
* Note: depends on Network_Type being set to PORT_TYPE_BIP for this object
|
||||
@@ -3085,7 +3384,7 @@ bool Network_Port_IPv6_Auto_Addressing_Enable(uint32_t object_instance)
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
ipv6 = &Object_List[index].Network.IPv6;
|
||||
flag = ipv6->Auto_Addressing_Enable;
|
||||
flag = ipv6->IP_DHCP_Enable;
|
||||
}
|
||||
|
||||
return flag;
|
||||
@@ -3110,11 +3409,10 @@ bool Network_Port_IPv6_Auto_Addressing_Enable_Set(
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
if (Object_List[index].Network_Type == PORT_TYPE_BIP6) {
|
||||
if (Object_List[index].Network.IPv6.Auto_Addressing_Enable !=
|
||||
value) {
|
||||
if (Object_List[index].Network.IPv6.IP_DHCP_Enable != value) {
|
||||
Object_List[index].Changes_Pending = true;
|
||||
}
|
||||
Object_List[index].Network.IPv6.Auto_Addressing_Enable = value;
|
||||
Object_List[index].Network.IPv6.IP_DHCP_Enable = value;
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
@@ -3182,16 +3480,13 @@ static bool Network_Port_FD_BBMD_Address_Write(
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
break;
|
||||
} else if (value->host.ip_address.length == 4) {
|
||||
status = Network_Port_Remote_BBMD_IP_Address_Set(
|
||||
object_instance, value->host.ip_address.value[0],
|
||||
value->host.ip_address.value[1],
|
||||
value->host.ip_address.value[2],
|
||||
value->host.ip_address.value[3]);
|
||||
if (status) {
|
||||
status = Network_Port_Remote_BBMD_BIP_Port_Set(
|
||||
object_instance, value->port);
|
||||
}
|
||||
} else if (
|
||||
((value->host_ip_address) &&
|
||||
(value->host.ip_address.length == 4)) ||
|
||||
((value->host_name) &&
|
||||
(bacnet_is_valid_hostname(&value->host.name)))) {
|
||||
status = Network_Port_Remote_BBMD_Address_Set(
|
||||
object_instance, value);
|
||||
}
|
||||
if (!status) {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
@@ -3204,14 +3499,13 @@ static bool Network_Port_FD_BBMD_Address_Write(
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
break;
|
||||
} else if (value->host.ip_address.length == 16) {
|
||||
status = Network_Port_Remote_BBMD_IP6_Address_Set(
|
||||
object_instance, &value->host.ip_address.value[0]);
|
||||
|
||||
if (status) {
|
||||
status = Network_Port_Remote_BBMD_BIP6_Port_Set(
|
||||
object_instance, value->port);
|
||||
}
|
||||
} else if (
|
||||
((value->host_ip_address) &&
|
||||
(value->host.ip_address.length == 16)) ||
|
||||
((value->host_name) &&
|
||||
(bacnet_is_valid_hostname(&value->host.name)))) {
|
||||
status = Network_Port_Remote_BBMD_Address_Set(
|
||||
object_instance, value);
|
||||
}
|
||||
if (!status) {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
@@ -3489,6 +3783,21 @@ int Network_Port_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
apdu_len = encode_application_boolean(
|
||||
&apdu[0], Network_Port_IP_DHCP_Enable(rpdata->object_instance));
|
||||
break;
|
||||
case PROP_IP_DHCP_LEASE_TIME:
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0],
|
||||
Network_Port_IP_DHCP_Lease_Time(rpdata->object_instance));
|
||||
break;
|
||||
case PROP_IP_DHCP_LEASE_TIME_REMAINING:
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0],
|
||||
Network_Port_IP_DHCP_Lease_Time_Remaining(
|
||||
rpdata->object_instance));
|
||||
break;
|
||||
case PROP_IP_DHCP_SERVER:
|
||||
Network_Port_IP_DHCP_Server(rpdata->object_instance, &octet_string);
|
||||
apdu_len = encode_application_octet_string(&apdu[0], &octet_string);
|
||||
break;
|
||||
case PROP_IP_DNS_SERVER:
|
||||
apdu_len = bacnet_array_encode(
|
||||
rpdata->object_instance, rpdata->array_index,
|
||||
@@ -3575,10 +3884,15 @@ int Network_Port_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
rpdata->object_instance));
|
||||
break;
|
||||
case PROP_IPV6_DHCP_LEASE_TIME:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 0);
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0],
|
||||
Network_Port_IP_DHCP_Lease_Time(rpdata->object_instance));
|
||||
break;
|
||||
case PROP_IPV6_DHCP_LEASE_TIME_REMAINING:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 0);
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0],
|
||||
Network_Port_IP_DHCP_Lease_Time_Remaining(
|
||||
rpdata->object_instance));
|
||||
break;
|
||||
case PROP_IPV6_DHCP_SERVER:
|
||||
Network_Port_IPv6_DHCP_Server(
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "bacnet/bacdef.h"
|
||||
/* BACnet Stack API */
|
||||
#include "bacnet/apdu.h"
|
||||
#include "bacnet/hostnport.h"
|
||||
#include "bacnet/readrange.h"
|
||||
#include "bacnet/rp.h"
|
||||
#include "bacnet/wp.h"
|
||||
@@ -160,6 +161,19 @@ BACNET_STACK_EXPORT
|
||||
bool Network_Port_IP_DHCP_Enable(uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Network_Port_IP_DHCP_Enable_Set(uint32_t object_instance, bool value);
|
||||
BACNET_STACK_EXPORT
|
||||
void Network_Port_IP_DHCP_Server(
|
||||
uint32_t object_instance, BACNET_OCTET_STRING *ip_address);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Network_Port_IP_DHCP_Server_Set(
|
||||
uint32_t object_instance, BACNET_OCTET_STRING *ip_address);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Network_Port_IP_DHCP_Lease_Time_Set(
|
||||
uint32_t object_instance, const uint32_t value);
|
||||
BACNET_STACK_EXPORT
|
||||
uint32_t Network_Port_IP_DHCP_Lease_Time(uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
uint32_t Network_Port_IP_DHCP_Lease_Time_Remaining(uint32_t object_instance);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool Network_Port_IP_DNS_Server(
|
||||
@@ -217,6 +231,13 @@ uint16_t Network_Port_Remote_BBMD_BIP_Port(uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Network_Port_Remote_BBMD_BIP_Port_Set(
|
||||
uint32_t object_instance, uint16_t value);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool Network_Port_Remote_BBMD_Address(
|
||||
uint32_t object_instance, BACNET_HOST_N_PORT *bbmd_address);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Network_Port_Remote_BBMD_Address_Set(
|
||||
uint32_t object_instance, const BACNET_HOST_N_PORT *bbmd_address);
|
||||
BACNET_STACK_EXPORT
|
||||
uint16_t Network_Port_Remote_BBMD_BIP_Lifetime(uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
|
||||
@@ -374,6 +374,210 @@ bool host_n_port_copy(BACNET_HOST_N_PORT *dst, const BACNET_HOST_N_PORT *src)
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize a BACnetHostNPort_Minimal structure for IP address
|
||||
* @param host - BACnetHostNPort_Minimal structure
|
||||
* @param port - port number
|
||||
* @param address - BACnetHostAddress
|
||||
*/
|
||||
void host_n_port_minimal_ip_init(
|
||||
BACNET_HOST_N_PORT_MINIMAL *host,
|
||||
uint16_t port,
|
||||
const uint8_t *address,
|
||||
size_t address_len)
|
||||
{
|
||||
unsigned i, imax;
|
||||
|
||||
if (host) {
|
||||
host->tag = BACNET_HOST_ADDRESS_TAG_IP_ADDRESS;
|
||||
host->host.ip_address.length = address_len;
|
||||
imax = min(address_len, sizeof(host->host.ip_address.address));
|
||||
if (address) {
|
||||
for (i = 0; i < imax; i++) {
|
||||
host->host.ip_address.address[i] = address[i];
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < imax; i++) {
|
||||
host->host.ip_address.address[i] = 0;
|
||||
}
|
||||
}
|
||||
host->port = port;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief copy the BACnetHostNPort_Minimal complex data
|
||||
* @param dest - destination structure
|
||||
* @param src - source structure
|
||||
* @return true if successfully copied
|
||||
*/
|
||||
bool host_n_port_minimal_copy(
|
||||
BACNET_HOST_N_PORT_MINIMAL *dest, const BACNET_HOST_N_PORT_MINIMAL *src)
|
||||
{
|
||||
bool status = false;
|
||||
int i;
|
||||
|
||||
if (dest && src) {
|
||||
dest->tag = src->tag;
|
||||
dest->port = src->port;
|
||||
if (src->tag == BACNET_HOST_ADDRESS_TAG_IP_ADDRESS) {
|
||||
status = true;
|
||||
dest->host.ip_address.length = src->host.ip_address.length;
|
||||
for (i = 0; i < src->host.ip_address.length; i++) {
|
||||
if (i < sizeof(dest->host.ip_address.address)) {
|
||||
dest->host.ip_address.address[i] =
|
||||
src->host.ip_address.address[i];
|
||||
}
|
||||
}
|
||||
} else if (src->tag == BACNET_HOST_ADDRESS_TAG_NAME) {
|
||||
status = true;
|
||||
dest->host.name.length = src->host.name.length;
|
||||
for (i = 0; i < src->host.name.length; i++) {
|
||||
if (i < sizeof(dest->host.name.fqdn)) {
|
||||
dest->host.name.fqdn[i] = src->host.name.fqdn[i];
|
||||
}
|
||||
}
|
||||
} else if (src->tag == BACNET_HOST_ADDRESS_TAG_NONE) {
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy the BACnetHostNPort complex data from src to dst
|
||||
* @param dst - destination structure
|
||||
* @param src - source structure
|
||||
* @return true if successfully copied
|
||||
*/
|
||||
bool host_n_port_from_minimal(
|
||||
BACNET_HOST_N_PORT *dst, const BACNET_HOST_N_PORT_MINIMAL *src)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
if (dst && src) {
|
||||
switch (src->tag) {
|
||||
case BACNET_HOST_ADDRESS_TAG_NONE:
|
||||
dst->host_ip_address = false;
|
||||
dst->host_name = false;
|
||||
status = true;
|
||||
break;
|
||||
case BACNET_HOST_ADDRESS_TAG_IP_ADDRESS:
|
||||
dst->host_ip_address = true;
|
||||
dst->host_name = false;
|
||||
octetstring_init(
|
||||
&dst->host.ip_address, src->host.ip_address.address,
|
||||
src->host.ip_address.length);
|
||||
status = true;
|
||||
break;
|
||||
case BACNET_HOST_ADDRESS_TAG_NAME:
|
||||
dst->host_ip_address = false;
|
||||
dst->host_name = true;
|
||||
characterstring_init(
|
||||
&dst->host.name, CHARACTER_ANSI_X34, src->host.name.fqdn,
|
||||
src->host.name.length);
|
||||
status = true;
|
||||
break;
|
||||
default:
|
||||
return false; /* invalid tag number */
|
||||
}
|
||||
if (status) {
|
||||
dst->port = src->port;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy the BACnetHostNPort complex data from src to dst
|
||||
* @param dst - destination structure
|
||||
* @param src - source structure
|
||||
* @return true if successfully copied
|
||||
*/
|
||||
bool host_n_port_to_minimal(
|
||||
BACNET_HOST_N_PORT_MINIMAL *dst, const BACNET_HOST_N_PORT *src)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
if (dst && src) {
|
||||
if (src->host_ip_address) {
|
||||
dst->tag = BACNET_HOST_ADDRESS_TAG_IP_ADDRESS;
|
||||
dst->host.ip_address.length = octetstring_copy_value(
|
||||
dst->host.ip_address.address,
|
||||
sizeof(dst->host.ip_address.address), &src->host.ip_address);
|
||||
if (dst->host.ip_address.length > 0) {
|
||||
status = true;
|
||||
}
|
||||
} else if (src->host_name) {
|
||||
dst->tag = BACNET_HOST_ADDRESS_TAG_NAME;
|
||||
dst->host.name.length = characterstring_copy_value(
|
||||
dst->host.name.fqdn, sizeof(dst->host.name.fqdn),
|
||||
&src->host.name);
|
||||
if (dst->host.name.length > 0) {
|
||||
status = true;
|
||||
}
|
||||
} else {
|
||||
dst->tag = BACNET_HOST_ADDRESS_TAG_NONE;
|
||||
status = true;
|
||||
}
|
||||
dst->port = src->port;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool host_n_port_minimal_same(
|
||||
const BACNET_HOST_N_PORT_MINIMAL *dst,
|
||||
const BACNET_HOST_N_PORT_MINIMAL *src)
|
||||
{
|
||||
bool status = false;
|
||||
int i;
|
||||
|
||||
if (dst && src) {
|
||||
if (dst->tag == src->tag) {
|
||||
if (dst->tag == BACNET_HOST_ADDRESS_TAG_IP_ADDRESS) {
|
||||
if (dst->host.ip_address.length ==
|
||||
src->host.ip_address.length) {
|
||||
status = true;
|
||||
for (i = 0; i < dst->host.ip_address.length; i++) {
|
||||
if (i < sizeof(dst->host.ip_address.address)) {
|
||||
if (dst->host.ip_address.address[i] !=
|
||||
src->host.ip_address.address[i]) {
|
||||
status = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (dst->tag == BACNET_HOST_ADDRESS_TAG_NAME) {
|
||||
if (dst->host.name.length == src->host.name.length) {
|
||||
status = true;
|
||||
for (i = 0; i < dst->host.name.length; i++) {
|
||||
if (i < sizeof(dst->host.name.fqdn)) {
|
||||
if (dst->host.name.fqdn[i] !=
|
||||
src->host.name.fqdn[i]) {
|
||||
status = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (dst->tag == BACNET_HOST_ADDRESS_TAG_NONE) {
|
||||
status = true;
|
||||
}
|
||||
if (status) {
|
||||
if (dst->port != src->port) {
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare the BACnetHostNPort complex data of src and dst
|
||||
* @param host1 - host 1 structure
|
||||
@@ -1159,3 +1363,102 @@ int bacnet_fdt_entry_to_ascii(
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks conformance of a hostname with:
|
||||
* RFC 1123: Requirements for Internet Hosts – application and support
|
||||
* RFC 2181: Clarifications to the DNS specification
|
||||
*
|
||||
* Host software MUST handle host names of up to 63 characters and
|
||||
* SHOULD handle host names of up to 255 characters.
|
||||
*
|
||||
* Whenever a user inputs the identity of an Internet host, it SHOULD
|
||||
* be possible to enter either (1) a host domain name or (2) an IP
|
||||
* address in dotted-decimal ("#.#.#.#") form. The host SHOULD check
|
||||
* the string syntactically for a dotted-decimal number before
|
||||
* looking it up in the Domain Name System.
|
||||
*
|
||||
* The DNS itself places only one restriction on the particular labels
|
||||
* that can be used to identify resource records. That one restriction
|
||||
* relates to the length of the label and the full name. The length of
|
||||
* any one label is limited to between 1 and 63 octets. A full domain
|
||||
* name is limited to 255 octets (including the separators). The zero
|
||||
* length full name is defined as representing the root of the DNS tree,
|
||||
* and is typically written and displayed as ".". Those restrictions
|
||||
* aside, any binary string whatever can be used as the label of any
|
||||
* resource record. Similarly, any binary string can serve as the value
|
||||
* of any record that includes a domain name as some or all of its value
|
||||
* (SOA, NS, MX, PTR, CNAME, and any others that may be added).
|
||||
*
|
||||
* @param hostname - hostname as BACNET_CHARACTER_STRING
|
||||
* @return true if the host name conorms to RFC 1123, false otherwise
|
||||
*/
|
||||
bool bacnet_is_valid_hostname(const BACNET_CHARACTER_STRING *const hostname)
|
||||
{
|
||||
int len;
|
||||
const char *val;
|
||||
int dot_count = 0;
|
||||
int i = 0;
|
||||
char c;
|
||||
char fqdn_copy[255 + 1] = { 0 };
|
||||
char *label = NULL;
|
||||
|
||||
len = characterstring_length(hostname);
|
||||
/* Check length */
|
||||
if ((len == 0) || (len > sizeof(fqdn_copy) - 1)) {
|
||||
/* Invalid length */
|
||||
return false;
|
||||
}
|
||||
/* Check if it looks like an IP address (basic check) */
|
||||
val = characterstring_value(hostname);
|
||||
for (i = 0; i < len; i++) {
|
||||
if (val[i] == '.') {
|
||||
dot_count++;
|
||||
}
|
||||
}
|
||||
/* Check if it's a numeric pattern (like an incomplete IP) */
|
||||
if (dot_count > 0 && strspn(val, "0123456789.") == len) {
|
||||
/* Invalid: looks like an incomplete IP */
|
||||
return false;
|
||||
}
|
||||
/* Check each character */
|
||||
for (i = 0; i < len; i++) {
|
||||
c = val[i];
|
||||
if (!isalnum(c) && c != '-' && c != '.') {
|
||||
/* Invalid character */
|
||||
return false;
|
||||
}
|
||||
/* Check for starting and ending hyphens */
|
||||
if (i == 0 && c == '-') {
|
||||
/* Cannot start with a hyphen */
|
||||
return false;
|
||||
}
|
||||
if (i == len - 1 && c == '-') {
|
||||
/* Cannot end with a hyphen */
|
||||
return false;
|
||||
}
|
||||
/* Check for consecutive periods or hyphens */
|
||||
if (i > 0 &&
|
||||
((val[i] == '-' && val[i - 1] == '-') ||
|
||||
(val[i] == '.' && val[i - 1] == '.'))) {
|
||||
/* Invalid consecutive characters */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* Make a copy to manipulate when checking each label */
|
||||
strncpy(fqdn_copy, val, sizeof(fqdn_copy) - 1);
|
||||
/* Split FQDN by '.' */
|
||||
label = strtok(fqdn_copy, ".");
|
||||
while (label != NULL) {
|
||||
/* check for each label length not exceeding 63 characters */
|
||||
if (strlen(label) > 63) {
|
||||
/* Invalid label found */
|
||||
return false;
|
||||
}
|
||||
/* Move to the next label */
|
||||
label = strtok(NULL, ".");
|
||||
}
|
||||
|
||||
/* Valid hostname */
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
/* BACnet Stack API */
|
||||
#include "bacnet/bacstr.h"
|
||||
#include "bacnet/datalink/bvlc.h"
|
||||
#include "bacnet/datalink/bvlc6.h"
|
||||
|
||||
/**
|
||||
* BACnetHostNPort ::= SEQUENCE {
|
||||
@@ -38,6 +39,25 @@ typedef struct BACnetHostNPort {
|
||||
uint16_t port;
|
||||
} BACNET_HOST_N_PORT;
|
||||
|
||||
#define BACNET_HOST_ADDRESS_TAG_NONE 0
|
||||
#define BACNET_HOST_ADDRESS_TAG_IP_ADDRESS 1
|
||||
#define BACNET_HOST_ADDRESS_TAG_NAME 2
|
||||
/* BACnetHostNPort with smaller RAM footprint using C datatypes */
|
||||
typedef struct BACnetHostNPort_Minimal {
|
||||
uint8_t tag;
|
||||
union BACnetHostAddress_Minimal {
|
||||
struct BACnetHostOctetString {
|
||||
uint8_t address[IP6_ADDRESS_MAX];
|
||||
uint8_t length;
|
||||
} ip_address;
|
||||
struct BACnetHostCharacterString {
|
||||
char fqdn[256];
|
||||
uint8_t length;
|
||||
} name;
|
||||
} host;
|
||||
uint16_t port;
|
||||
} BACNET_HOST_N_PORT_MINIMAL;
|
||||
|
||||
/**
|
||||
* BACnetBDTEntry ::= SEQUENCE {
|
||||
* bbmd-address [0] BACnetHostNPort,
|
||||
@@ -99,6 +119,26 @@ int host_n_port_context_decode(
|
||||
BACNET_HOST_N_PORT *address);
|
||||
BACNET_STACK_EXPORT
|
||||
bool host_n_port_copy(BACNET_HOST_N_PORT *dst, const BACNET_HOST_N_PORT *src);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool host_n_port_from_minimal(
|
||||
BACNET_HOST_N_PORT *dst, const BACNET_HOST_N_PORT_MINIMAL *src);
|
||||
BACNET_STACK_EXPORT
|
||||
bool host_n_port_to_minimal(
|
||||
BACNET_HOST_N_PORT_MINIMAL *dst, const BACNET_HOST_N_PORT *src);
|
||||
BACNET_STACK_EXPORT
|
||||
bool host_n_port_minimal_copy(
|
||||
BACNET_HOST_N_PORT_MINIMAL *dst, const BACNET_HOST_N_PORT_MINIMAL *src);
|
||||
BACNET_STACK_EXPORT
|
||||
bool host_n_port_minimal_same(
|
||||
const BACNET_HOST_N_PORT_MINIMAL *dst,
|
||||
const BACNET_HOST_N_PORT_MINIMAL *src);
|
||||
void host_n_port_minimal_ip_init(
|
||||
BACNET_HOST_N_PORT_MINIMAL *host,
|
||||
uint16_t port,
|
||||
const uint8_t *address,
|
||||
size_t address_len);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool host_n_port_same(
|
||||
const BACNET_HOST_N_PORT *dst, const BACNET_HOST_N_PORT *src);
|
||||
@@ -162,6 +202,8 @@ bool bacnet_fdt_entry_from_ascii(BACNET_FDT_ENTRY *value, const char *argv);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_fdt_entry_to_ascii(
|
||||
char *str, size_t str_size, const BACNET_FDT_ENTRY *value);
|
||||
BACNET_STACK_EXPORT
|
||||
bool bacnet_is_valid_hostname(const BACNET_CHARACTER_STRING *const hostname);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ add_compile_definitions(
|
||||
BIG_ENDIAN=0
|
||||
CONFIG_ZTEST=1
|
||||
BACDL_ALL=1
|
||||
BACNET_NETWORK_PORT_IP_DHCP_ENABLED=1
|
||||
BACNET_SECURE_CONNECT_ROUTING_TABLE=1
|
||||
BSC_CONF_HUB_FUNCTIONS_NUM=1
|
||||
BSC_CONF_HUB_CONNECTORS_NUM=1
|
||||
|
||||
@@ -37,32 +37,51 @@ static void test_network_port(void)
|
||||
};
|
||||
uint8_t test_address[16] = { 0 };
|
||||
uint8_t mac_len;
|
||||
uint8_t max_master, max_info_frames;
|
||||
uint8_t ip_prefix;
|
||||
uint32_t object_instance = 0;
|
||||
uint32_t object_instance = 1234, test_object_instance = 0;
|
||||
unsigned object_index = 0, test_object_index = 0;
|
||||
BACNET_HOST_N_PORT host_n_port, test_host_n_port = { 0 };
|
||||
BACNET_OCTET_STRING ip_address;
|
||||
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY bdt[2] = {
|
||||
{ .valid = true,
|
||||
.dest_address = { .address = { 1, 2, 3, 4 }, .port = 47808 },
|
||||
.broadcast_mask = { .address = { 255, 255, 255, 255 } } },
|
||||
{ .valid = true,
|
||||
.dest_address = { .address = { 5, 6, 7, 8 }, .port = 47808 },
|
||||
.broadcast_mask = { .address = { 255, 255, 255, 0 } } }
|
||||
};
|
||||
BACNET_IP_BROADCAST_DISTRIBUTION_TABLE_ENTRY *test_bdt;
|
||||
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY fdt[2] = {
|
||||
{ .valid = true,
|
||||
.dest_address = { .address = { 1, 2, 3, 4 }, .port = 47808 },
|
||||
.ttl_seconds = 30,
|
||||
.ttl_seconds_remaining = 30 },
|
||||
{ .valid = true,
|
||||
.dest_address = { .address = { 5, 6, 7, 8 }, .port = 47808 },
|
||||
.ttl_seconds = 60,
|
||||
.ttl_seconds_remaining = 60 }
|
||||
};
|
||||
BACNET_IP_FOREIGN_DEVICE_TABLE_ENTRY *test_fdt;
|
||||
uint8_t port_type[] = { PORT_TYPE_ETHERNET, PORT_TYPE_ARCNET,
|
||||
PORT_TYPE_MSTP, PORT_TYPE_PTP,
|
||||
PORT_TYPE_LONTALK, PORT_TYPE_BIP,
|
||||
PORT_TYPE_ZIGBEE, PORT_TYPE_VIRTUAL,
|
||||
PORT_TYPE_NON_BACNET, PORT_TYPE_BIP6,
|
||||
PORT_TYPE_BSC, PORT_TYPE_MAX };
|
||||
const int known_fail_property_list[] = {
|
||||
PROP_IP_DNS_SERVER,
|
||||
PROP_BBMD_BROADCAST_DISTRIBUTION_TABLE,
|
||||
PROP_BBMD_FOREIGN_DEVICE_TABLE,
|
||||
PROP_FD_BBMD_ADDRESS,
|
||||
PROP_IPV6_DNS_SERVER,
|
||||
PROP_ISSUER_CERTIFICATE_FILES,
|
||||
PROP_SC_HUB_FUNCTION_CONNECTION_STATUS,
|
||||
PROP_SC_DIRECT_CONNECT_CONNECTION_STATUS,
|
||||
PROP_SC_FAILED_CONNECTION_REQUESTS,
|
||||
-1
|
||||
};
|
||||
const int known_fail_property_list[] = { -1 };
|
||||
|
||||
while (port_type[port] != PORT_TYPE_MAX) {
|
||||
Network_Port_Init();
|
||||
object_instance = 1234;
|
||||
status = Network_Port_Object_Instance_Number_Set(0, object_instance);
|
||||
status = Network_Port_Object_Instance_Number_Set(
|
||||
object_index, object_instance);
|
||||
zassert_true(status, NULL);
|
||||
test_object_index = Network_Port_Instance_To_Index(object_instance);
|
||||
zassert_equal(object_index, test_object_index, NULL);
|
||||
test_object_instance = Network_Port_Index_To_Instance(object_index);
|
||||
zassert_equal(object_instance, test_object_instance, NULL);
|
||||
test_object_instance = Network_Port_Index_To_Instance(UINT_MAX);
|
||||
zassert_equal(test_object_instance, BACNET_MAX_INSTANCE, NULL);
|
||||
status = Network_Port_Type_Set(object_instance, port_type[port]);
|
||||
zassert_true(status, NULL);
|
||||
count = Network_Port_Count();
|
||||
@@ -118,8 +137,18 @@ static void test_network_port(void)
|
||||
zassert_equal(address[0], 127, NULL);
|
||||
status = Network_Port_MSTP_Max_Info_Frames_Set(object_instance, 1);
|
||||
zassert_true(status, NULL);
|
||||
zassert_equal(
|
||||
Network_Port_MSTP_Max_Info_Frames(object_instance), 1, NULL);
|
||||
max_info_frames =
|
||||
Network_Port_MSTP_Max_Info_Frames(object_instance);
|
||||
zassert_equal(max_info_frames, 1, NULL);
|
||||
Network_Port_MSTP_Max_Master_Set(object_instance, 127);
|
||||
max_master = Network_Port_MSTP_Max_Master(object_instance);
|
||||
zassert_equal(max_master, 127, NULL);
|
||||
Network_Port_Changes_Pending_Set(object_instance, false);
|
||||
status = Network_Port_MSTP_Max_Master_Set(object_instance, 63);
|
||||
zassert_true(status, NULL);
|
||||
max_master = Network_Port_MSTP_Max_Master(object_instance);
|
||||
zassert_equal(max_master, 63, NULL);
|
||||
zassert_true(Network_Port_Changes_Pending(object_instance), NULL);
|
||||
}
|
||||
if (port_type[port] == PORT_TYPE_BIP) {
|
||||
status = Network_Port_IP_Address_Set(object_instance, 1, 2, 3, 4);
|
||||
@@ -134,6 +163,16 @@ static void test_network_port(void)
|
||||
zassert_true(status, NULL);
|
||||
status = Network_Port_IP_DHCP_Enable(object_instance);
|
||||
zassert_true(status, NULL);
|
||||
Network_Port_IP_DHCP_Lease_Time_Set(object_instance, 60);
|
||||
zassert_equal(
|
||||
Network_Port_IP_DHCP_Lease_Time(object_instance), 60, NULL);
|
||||
zassert_equal(
|
||||
Network_Port_IP_DHCP_Lease_Time_Remaining(object_instance), 60,
|
||||
NULL);
|
||||
octetstring_init_ascii_hex(&ip_address, "0x0A0B0C0D");
|
||||
status =
|
||||
Network_Port_IP_DHCP_Server_Set(object_instance, &ip_address);
|
||||
zassert_true(status, NULL);
|
||||
status = Network_Port_IP_DNS_Server_Set(
|
||||
object_instance, 0, 9, 10, 11, 12);
|
||||
zassert_true(status, NULL);
|
||||
@@ -151,21 +190,70 @@ static void test_network_port(void)
|
||||
status = Network_Port_BBMD_BD_Table_Set(object_instance, NULL);
|
||||
zassert_true(status, NULL);
|
||||
zassert_is_null(Network_Port_BBMD_BD_Table(object_instance), NULL);
|
||||
bvlc_broadcast_distribution_table_link_array(bdt, ARRAY_SIZE(bdt));
|
||||
status = Network_Port_BBMD_BD_Table_Set(object_instance, bdt);
|
||||
zassert_true(status, NULL);
|
||||
test_bdt = Network_Port_BBMD_BD_Table(object_instance);
|
||||
zassert_not_null(test_bdt, NULL);
|
||||
zassert_equal(
|
||||
test_bdt->dest_address.address[0],
|
||||
bdt[0].dest_address.address[0], NULL);
|
||||
status = Network_Port_BBMD_FD_Table_Set(object_instance, NULL);
|
||||
zassert_true(status, NULL);
|
||||
zassert_is_null(Network_Port_BBMD_FD_Table(object_instance), NULL);
|
||||
bvlc_foreign_device_table_link_array(fdt, ARRAY_SIZE(fdt));
|
||||
status = Network_Port_BBMD_FD_Table_Set(object_instance, &fdt[0]);
|
||||
zassert_true(status, NULL);
|
||||
test_fdt = Network_Port_BBMD_FD_Table(object_instance);
|
||||
zassert_not_null(test_fdt, NULL);
|
||||
zassert_equal(
|
||||
test_fdt->dest_address.address[0],
|
||||
fdt[0].dest_address.address[0], NULL);
|
||||
status = Network_Port_Remote_BBMD_IP_Address(
|
||||
object_instance, NULL, NULL, NULL, NULL);
|
||||
zassert_true(status, NULL);
|
||||
zassert_false(status, NULL);
|
||||
status = Network_Port_Remote_BBMD_IP_Address_Set(
|
||||
object_instance, 1, 2, 3, 4);
|
||||
zassert_true(status, NULL);
|
||||
status = Network_Port_Remote_BBMD_IP_Address(
|
||||
object_instance, &test_address[0], &test_address[1],
|
||||
&test_address[2], &test_address[3]);
|
||||
zassert_true(status, NULL);
|
||||
status = Network_Port_Remote_BBMD_IP_Address(
|
||||
object_instance, NULL, NULL, NULL, NULL);
|
||||
zassert_true(status, NULL);
|
||||
zassert_equal(test_address[0], 1, NULL);
|
||||
zassert_equal(test_address[1], 2, NULL);
|
||||
zassert_equal(test_address[2], 3, NULL);
|
||||
zassert_equal(test_address[3], 4, NULL);
|
||||
Network_Port_Changes_Pending_Set(object_instance, false);
|
||||
status = Network_Port_Remote_BBMD_IP_Address_Set(
|
||||
object_instance, 5, 6, 7, 8);
|
||||
zassert_true(status, NULL);
|
||||
zassert_true(Network_Port_Changes_Pending(object_instance), NULL);
|
||||
status =
|
||||
Network_Port_Remote_BBMD_BIP_Port_Set(object_instance, 47808);
|
||||
zassert_true(status, NULL);
|
||||
zassert_equal(
|
||||
Network_Port_Remote_BBMD_BIP_Port(object_instance), 47808,
|
||||
NULL);
|
||||
Network_Port_Remote_BBMD_Address(object_instance, &host_n_port);
|
||||
zassert_false(host_n_port.host_name, NULL);
|
||||
zassert_true(host_n_port.host_ip_address, NULL);
|
||||
zassert_equal(host_n_port.port, 47808, NULL);
|
||||
test_host_n_port.host_ip_address = false;
|
||||
test_host_n_port.host_name = true;
|
||||
characterstring_init_ansi(
|
||||
&test_host_n_port.host.name, "bbmd.example.com");
|
||||
test_host_n_port.port = 47808;
|
||||
Network_Port_Remote_BBMD_Address_Set(
|
||||
object_instance, &test_host_n_port);
|
||||
Network_Port_Remote_BBMD_Address(object_instance, &host_n_port);
|
||||
zassert_false(host_n_port.host_ip_address, NULL);
|
||||
zassert_true(host_n_port.host_name, NULL);
|
||||
zassert_equal(host_n_port.port, 47808, NULL);
|
||||
characterstring_ansi_same(
|
||||
&test_host_n_port.host.name, "bbmd.example.com");
|
||||
status =
|
||||
Network_Port_Remote_BBMD_BIP_Lifetime_Set(object_instance, 60);
|
||||
zassert_true(status, NULL);
|
||||
@@ -192,16 +280,33 @@ static void test_network_port(void)
|
||||
Network_Port_BBMD_IP6_FD_Table(object_instance), NULL);
|
||||
status =
|
||||
Network_Port_Remote_BBMD_IP6_Address(object_instance, address);
|
||||
zassert_true(status, NULL);
|
||||
zassert_false(status, NULL);
|
||||
status = Network_Port_Remote_BBMD_IP6_Address_Set(
|
||||
object_instance, address);
|
||||
zassert_true(status, NULL);
|
||||
status =
|
||||
Network_Port_Remote_BBMD_BIP6_Port_Set(object_instance, 47808);
|
||||
zassert_true(status, NULL);
|
||||
status =
|
||||
Network_Port_Remote_BBMD_IP6_Address(object_instance, address);
|
||||
zassert_true(status, NULL);
|
||||
zassert_equal(
|
||||
Network_Port_Remote_BBMD_BIP6_Port(object_instance), 47808,
|
||||
NULL);
|
||||
Network_Port_Remote_BBMD_Address(object_instance, &host_n_port);
|
||||
zassert_true(host_n_port.host_ip_address, NULL);
|
||||
zassert_equal(host_n_port.port, 47808, NULL);
|
||||
test_host_n_port.host_ip_address = false;
|
||||
test_host_n_port.host_name = true;
|
||||
characterstring_init_ansi(
|
||||
&test_host_n_port.host.name, "bbmd.example.com");
|
||||
test_host_n_port.port = 47808;
|
||||
Network_Port_Remote_BBMD_Address_Set(
|
||||
object_instance, &test_host_n_port);
|
||||
Network_Port_Remote_BBMD_Address(object_instance, &host_n_port);
|
||||
zassert_false(host_n_port.host_ip_address, NULL);
|
||||
zassert_true(host_n_port.host_name, NULL);
|
||||
zassert_equal(host_n_port.port, 47808, NULL);
|
||||
status =
|
||||
Network_Port_Remote_BBMD_BIP6_Lifetime_Set(object_instance, 60);
|
||||
zassert_true(status, NULL);
|
||||
@@ -226,8 +331,21 @@ static void test_network_port(void)
|
||||
status = Network_Port_IPv6_Multicast_Address_Set(
|
||||
object_instance, address);
|
||||
zassert_true(status, NULL);
|
||||
status = Network_Port_IP_DHCP_Enable_Set(object_instance, true);
|
||||
zassert_true(status, NULL);
|
||||
status = Network_Port_IP_DHCP_Enable(object_instance);
|
||||
zassert_true(status, NULL);
|
||||
Network_Port_IP_DHCP_Lease_Time_Set(object_instance, 60);
|
||||
zassert_equal(
|
||||
Network_Port_IP_DHCP_Lease_Time(object_instance), 60, NULL);
|
||||
zassert_equal(
|
||||
Network_Port_IP_DHCP_Lease_Time_Remaining(object_instance), 60,
|
||||
NULL);
|
||||
status =
|
||||
Network_Port_IPv6_DHCP_Server_Set(object_instance, address);
|
||||
octetstring_init(&ip_address, address, sizeof(address));
|
||||
status =
|
||||
Network_Port_IP_DHCP_Server_Set(object_instance, &ip_address);
|
||||
zassert_true(status, NULL);
|
||||
status = Network_Port_BIP6_Port_Set(object_instance, 47808);
|
||||
zassert_true(status, NULL);
|
||||
@@ -257,7 +375,10 @@ static void test_network_port(void)
|
||||
Network_Port_Object_Name_ASCII);
|
||||
port++;
|
||||
Network_Port_Changes_Activate();
|
||||
zassert_false(Network_Port_Changes_Pending(object_instance), NULL);
|
||||
Network_Port_Changes_Pending_Set(object_instance, true);
|
||||
Network_Port_Changes_Discard();
|
||||
zassert_false(Network_Port_Changes_Pending(object_instance), NULL);
|
||||
Network_Port_Cleanup();
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,43 @@
|
||||
#include <bacnet/bacdest.h>
|
||||
#include <bacnet/hostnport.h>
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST(create_object_tests, test_HostNPortMinimal_Init)
|
||||
#else
|
||||
static void test_HostNPortMinimal_Init(void)
|
||||
#endif
|
||||
{
|
||||
BACNET_HOST_N_PORT_MINIMAL test_data_1 = { 0 }, test_data_2 = { 0 };
|
||||
BACNET_HOST_N_PORT host_n_port = { 0 };
|
||||
uint8_t address[IP6_ADDRESS_MAX] = { 1, 2, 3, 4, 5, 6, 7, 8,
|
||||
9, 10, 11, 12, 13, 14, 15, 16 };
|
||||
uint16_t port = 0xBAC0;
|
||||
|
||||
/* test the init */
|
||||
host_n_port_minimal_ip_init(&test_data_1, port, address, sizeof(address));
|
||||
zassert_equal(test_data_1.tag, BACNET_HOST_ADDRESS_TAG_IP_ADDRESS, NULL);
|
||||
zassert_equal(test_data_1.port, port, NULL);
|
||||
zassert_equal(test_data_1.host.ip_address.length, sizeof(address), NULL);
|
||||
zassert_mem_equal(
|
||||
test_data_1.host.ip_address.address, address, sizeof(address), NULL);
|
||||
host_n_port_from_minimal(&host_n_port, &test_data_1);
|
||||
host_n_port_to_minimal(&test_data_2, &host_n_port);
|
||||
zassert_true(
|
||||
host_n_port_minimal_same(&test_data_1, &test_data_2),
|
||||
"test_data_1 != test_data_2");
|
||||
}
|
||||
|
||||
static void test_HostNPortMinimal_Copy(BACNET_HOST_N_PORT *data)
|
||||
{
|
||||
BACNET_HOST_N_PORT_MINIMAL test_data_1 = { 0 }, test_data_2 = { 0 };
|
||||
|
||||
host_n_port_to_minimal(&test_data_1, data);
|
||||
host_n_port_minimal_copy(&test_data_2, &test_data_1);
|
||||
zassert_true(
|
||||
host_n_port_minimal_same(&test_data_1, &test_data_2),
|
||||
"test_data_1 != test_data_2");
|
||||
}
|
||||
|
||||
static void test_HostNPortCodec(BACNET_HOST_N_PORT *data)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
@@ -72,12 +109,82 @@ static void test_HostNPort(void)
|
||||
data.host_name = false;
|
||||
data.port = 0xBAC0;
|
||||
test_HostNPortCodec(&data);
|
||||
test_HostNPortMinimal_Copy(&data);
|
||||
/* Host Name */
|
||||
characterstring_init_ansi(&data.host.name, "bacnet.org");
|
||||
data.host_ip_address = false;
|
||||
data.host_name = true;
|
||||
data.port = 0xBAC0;
|
||||
test_HostNPortCodec(&data);
|
||||
test_HostNPortMinimal_Copy(&data);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST(create_object_tests, test_is_valid_hostname)
|
||||
#else
|
||||
static void test_is_valid_hostname(void)
|
||||
#endif
|
||||
{
|
||||
bool status = false;
|
||||
BACNET_CHARACTER_STRING hostname;
|
||||
|
||||
status = characterstring_init_ansi(&hostname, "valid.host.name");
|
||||
zassert_true(status, NULL);
|
||||
status = bacnet_is_valid_hostname(&hostname);
|
||||
zassert_true(status, NULL);
|
||||
|
||||
status = characterstring_init_ansi(&hostname, "invalid..host.name");
|
||||
zassert_true(status, NULL);
|
||||
status = bacnet_is_valid_hostname(&hostname);
|
||||
zassert_false(status, NULL);
|
||||
|
||||
status = characterstring_init_ansi(&hostname, "-invalid.host.name");
|
||||
zassert_true(status, NULL);
|
||||
status = bacnet_is_valid_hostname(&hostname);
|
||||
zassert_false(status, NULL);
|
||||
|
||||
status = characterstring_init_ansi(&hostname, "valid.host-name");
|
||||
zassert_true(status, NULL);
|
||||
status = bacnet_is_valid_hostname(&hostname);
|
||||
zassert_true(status, NULL);
|
||||
|
||||
status = characterstring_init_ansi(&hostname, "invalid.host--name");
|
||||
zassert_true(status, NULL);
|
||||
status = bacnet_is_valid_hostname(&hostname);
|
||||
zassert_false(status, NULL);
|
||||
|
||||
status = characterstring_init_ansi(&hostname, "invalid.host name");
|
||||
zassert_true(status, NULL);
|
||||
status = bacnet_is_valid_hostname(&hostname);
|
||||
zassert_false(status, NULL);
|
||||
|
||||
status = characterstring_init_ansi(&hostname, "valid.host.123.name");
|
||||
zassert_true(status, NULL);
|
||||
status = bacnet_is_valid_hostname(&hostname);
|
||||
zassert_true(status, NULL);
|
||||
|
||||
{
|
||||
char too_long_label[65] = { 0 };
|
||||
memset(too_long_label, 'l', sizeof(too_long_label) - 1);
|
||||
status = characterstring_init_ansi(&hostname, too_long_label);
|
||||
zassert_true(status, NULL);
|
||||
status = bacnet_is_valid_hostname(&hostname);
|
||||
zassert_false(status, NULL);
|
||||
}
|
||||
|
||||
{
|
||||
char max_length_label[64] = { 0 };
|
||||
memset(max_length_label, 'l', sizeof(max_length_label) - 1);
|
||||
status = characterstring_init_ansi(&hostname, max_length_label);
|
||||
zassert_true(status, NULL);
|
||||
status = bacnet_is_valid_hostname(&hostname);
|
||||
zassert_true(status, NULL);
|
||||
}
|
||||
|
||||
status = characterstring_init_ansi(&hostname, "non-alpanumer!c.host name");
|
||||
zassert_true(status, NULL);
|
||||
status = bacnet_is_valid_hostname(&hostname);
|
||||
zassert_false(status, NULL);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
@@ -85,7 +192,10 @@ ZTEST_SUITE(host_n_port_tests, NULL, NULL, NULL, NULL, NULL);
|
||||
#else
|
||||
void test_main(void)
|
||||
{
|
||||
ztest_test_suite(host_n_port_tests, ztest_unit_test(test_HostNPort));
|
||||
ztest_test_suite(
|
||||
host_n_port_tests, ztest_unit_test(test_HostNPort),
|
||||
ztest_unit_test(test_HostNPortMinimal_Init),
|
||||
ztest_unit_test(test_is_valid_hostname));
|
||||
|
||||
ztest_run_test_suite(host_n_port_tests);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user