Fixed network port object to accept host name option of host-n-port writes. (#997)

This commit is contained in:
Steve Karg
2025-05-20 15:44:47 -05:00
committed by GitHub
parent 524fd162f9
commit b3fd374c84
9 changed files with 1077 additions and 133 deletions
+427 -113
View File
@@ -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(
+21
View File
@@ -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