Added enhancement to address cache: Top Protected Entry: entries from 0 to Top_Protected_Entry are not removed by address_remove_oldest()function. When I-am attack occurs only entries between Top_Protected_Entry and MAX_ADDRESS_CACHE can be removed.
This commit is contained in:
@@ -59,6 +59,13 @@ extern "C" {
|
|||||||
unsigned *max_apdu,
|
unsigned *max_apdu,
|
||||||
BACNET_ADDRESS * src);
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
|
bool address_device_get_by_index(
|
||||||
|
unsigned index,
|
||||||
|
uint32_t * device_id,
|
||||||
|
uint32_t * device_ttl,
|
||||||
|
unsigned *max_apdu,
|
||||||
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
bool address_get_device_id(
|
bool address_get_device_id(
|
||||||
BACNET_ADDRESS * src,
|
BACNET_ADDRESS * src,
|
||||||
uint32_t * device_id);
|
uint32_t * device_id);
|
||||||
@@ -75,6 +82,12 @@ extern "C" {
|
|||||||
unsigned *max_apdu,
|
unsigned *max_apdu,
|
||||||
BACNET_ADDRESS * src);
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
|
bool address_device_bind_request(
|
||||||
|
uint32_t device_id,
|
||||||
|
uint32_t * device_ttl,
|
||||||
|
unsigned *max_apdu,
|
||||||
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
void address_add_binding(
|
void address_add_binding(
|
||||||
uint32_t device_id,
|
uint32_t device_id,
|
||||||
unsigned max_apdu,
|
unsigned max_apdu,
|
||||||
@@ -105,6 +118,9 @@ extern "C" {
|
|||||||
BACNET_MAC_ADDRESS *mac,
|
BACNET_MAC_ADDRESS *mac,
|
||||||
char *arg);
|
char *arg);
|
||||||
|
|
||||||
|
void address_protected_entry_index_set(uint32_t top_protected_entry_index);
|
||||||
|
void address_own_device_id_set(uint32_t own_id);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@@ -49,6 +49,9 @@
|
|||||||
/* occurs in BACnet. A device id is bound to a MAC address. */
|
/* occurs in BACnet. A device id is bound to a MAC address. */
|
||||||
/* The normal method is using Who-Is, and using the data from I-Am */
|
/* The normal method is using Who-Is, and using the data from I-Am */
|
||||||
|
|
||||||
|
static uint32_t Top_Protected_Entry;
|
||||||
|
static uint32_t Own_Device_ID = 0xFFFFFFFF;
|
||||||
|
|
||||||
static struct Address_Cache_Entry {
|
static struct Address_Cache_Entry {
|
||||||
uint8_t Flags;
|
uint8_t Flags;
|
||||||
uint32_t device_id;
|
uint32_t device_id;
|
||||||
@@ -72,6 +75,17 @@ static struct Address_Cache_Entry {
|
|||||||
#define BAC_ADDR_SHORT_TIME BAC_ADDR_SECS_1HOUR
|
#define BAC_ADDR_SHORT_TIME BAC_ADDR_SECS_1HOUR
|
||||||
#define BAC_ADDR_FOREVER 0xFFFFFFFF /* Permenant entry */
|
#define BAC_ADDR_FOREVER 0xFFFFFFFF /* Permenant entry */
|
||||||
|
|
||||||
|
|
||||||
|
void address_protected_entry_index_set(uint32_t top_protected_entry_index)
|
||||||
|
{
|
||||||
|
Top_Protected_Entry = top_protected_entry_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void address_own_device_id_set(uint32_t own_id)
|
||||||
|
{
|
||||||
|
Own_Device_ID = own_id;
|
||||||
|
}
|
||||||
|
|
||||||
bool address_match(
|
bool address_match(
|
||||||
BACNET_ADDRESS * dest,
|
BACNET_ADDRESS * dest,
|
||||||
BACNET_ADDRESS * src)
|
BACNET_ADDRESS * src)
|
||||||
@@ -112,15 +126,20 @@ void address_remove_device(
|
|||||||
uint32_t device_id)
|
uint32_t device_id)
|
||||||
{
|
{
|
||||||
struct Address_Cache_Entry *pMatch;
|
struct Address_Cache_Entry *pMatch;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
pMatch = Address_Cache;
|
pMatch = Address_Cache;
|
||||||
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
|
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
|
||||||
if (((pMatch->Flags & BAC_ADDR_IN_USE) != 0) &&
|
if (((pMatch->Flags & BAC_ADDR_IN_USE) != 0) &&
|
||||||
(pMatch->device_id == device_id)) {
|
(pMatch->device_id == device_id)) {
|
||||||
pMatch->Flags = 0;
|
pMatch->Flags = 0;
|
||||||
|
if (index < Top_Protected_Entry) {
|
||||||
|
Top_Protected_Entry--;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pMatch++;
|
pMatch++;
|
||||||
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -143,11 +162,14 @@ static struct Address_Cache_Entry *address_remove_oldest(
|
|||||||
uint32_t ulTime;
|
uint32_t ulTime;
|
||||||
|
|
||||||
pCandidate = NULL;
|
pCandidate = NULL;
|
||||||
|
if (Top_Protected_Entry > (MAX_ADDRESS_CACHE - 1)) {
|
||||||
|
return pCandidate;
|
||||||
|
}
|
||||||
ulTime = BAC_ADDR_FOREVER - 1; /* Longest possible non static time to live */
|
ulTime = BAC_ADDR_FOREVER - 1; /* Longest possible non static time to live */
|
||||||
|
|
||||||
/* First pass - try only in use and bound entries */
|
/* First pass - try only in use and bound entries */
|
||||||
|
|
||||||
pMatch = Address_Cache;
|
pMatch = &Address_Cache[Top_Protected_Entry];
|
||||||
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
|
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
|
||||||
if ((pMatch->
|
if ((pMatch->
|
||||||
Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ |
|
Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ |
|
||||||
@@ -341,6 +363,8 @@ void address_init(
|
|||||||
{
|
{
|
||||||
struct Address_Cache_Entry *pMatch;
|
struct Address_Cache_Entry *pMatch;
|
||||||
|
|
||||||
|
Top_Protected_Entry = 0;
|
||||||
|
|
||||||
pMatch = Address_Cache;
|
pMatch = Address_Cache;
|
||||||
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
|
while (pMatch <= &Address_Cache[MAX_ADDRESS_CACHE - 1]) {
|
||||||
pMatch->Flags = 0;
|
pMatch->Flags = 0;
|
||||||
@@ -479,6 +503,10 @@ void address_add(
|
|||||||
bool found = false; /* return value */
|
bool found = false; /* return value */
|
||||||
struct Address_Cache_Entry *pMatch;
|
struct Address_Cache_Entry *pMatch;
|
||||||
|
|
||||||
|
if (Own_Device_ID == device_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Note: Previously this function would ignore bind request
|
/* Note: Previously this function would ignore bind request
|
||||||
marked entries and in fact would probably overwrite the first
|
marked entries and in fact would probably overwrite the first
|
||||||
bind request entry blindly with the device info which may
|
bind request entry blindly with the device info which may
|
||||||
@@ -544,8 +572,9 @@ void address_add(
|
|||||||
|
|
||||||
/* returns true if device is already bound */
|
/* returns true if device is already bound */
|
||||||
/* also returns the address and max apdu if already bound */
|
/* also returns the address and max apdu if already bound */
|
||||||
bool address_bind_request(
|
bool address_device_bind_request(
|
||||||
uint32_t device_id,
|
uint32_t device_id,
|
||||||
|
uint32_t * device_ttl,
|
||||||
unsigned *max_apdu,
|
unsigned *max_apdu,
|
||||||
BACNET_ADDRESS * src)
|
BACNET_ADDRESS * src)
|
||||||
{
|
{
|
||||||
@@ -559,8 +588,15 @@ bool address_bind_request(
|
|||||||
(pMatch->device_id == device_id)) {
|
(pMatch->device_id == device_id)) {
|
||||||
if ((pMatch->Flags & BAC_ADDR_BIND_REQ) == 0) { /* Already bound */
|
if ((pMatch->Flags & BAC_ADDR_BIND_REQ) == 0) { /* Already bound */
|
||||||
found = true;
|
found = true;
|
||||||
*src = pMatch->address;
|
if (src) {
|
||||||
*max_apdu = pMatch->max_apdu;
|
*src = pMatch->address;
|
||||||
|
}
|
||||||
|
if (max_apdu) {
|
||||||
|
*max_apdu = pMatch->max_apdu;
|
||||||
|
}
|
||||||
|
if (device_ttl) {
|
||||||
|
*device_ttl = pMatch->TimeToLive;
|
||||||
|
}
|
||||||
if ((pMatch->Flags & BAC_ADDR_SHORT_TTL) != 0) { /* Was picked up opportunistacilly */
|
if ((pMatch->Flags & BAC_ADDR_SHORT_TTL) != 0) { /* Was picked up opportunistacilly */
|
||||||
pMatch->Flags &= ~BAC_ADDR_SHORT_TTL; /* Convert to normal entry */
|
pMatch->Flags &= ~BAC_ADDR_SHORT_TTL; /* Convert to normal entry */
|
||||||
pMatch->TimeToLive = BAC_ADDR_LONG_TIME; /* And give it a decent time to live */
|
pMatch->TimeToLive = BAC_ADDR_LONG_TIME; /* And give it a decent time to live */
|
||||||
@@ -597,6 +633,15 @@ bool address_bind_request(
|
|||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* returns true if device is already bound */
|
||||||
|
/* also returns the address and max apdu if already bound */
|
||||||
|
bool address_bind_request(
|
||||||
|
uint32_t device_id,
|
||||||
|
unsigned *max_apdu,
|
||||||
|
BACNET_ADDRESS * src)
|
||||||
|
{
|
||||||
|
return address_device_bind_request(device_id, NULL, max_apdu, src);
|
||||||
|
}
|
||||||
|
|
||||||
void address_add_binding(
|
void address_add_binding(
|
||||||
uint32_t device_id,
|
uint32_t device_id,
|
||||||
@@ -626,9 +671,10 @@ void address_add_binding(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool address_get_by_index(
|
bool address_device_get_by_index(
|
||||||
unsigned index,
|
unsigned index,
|
||||||
uint32_t * device_id,
|
uint32_t * device_id,
|
||||||
|
uint32_t * device_ttl,
|
||||||
unsigned *max_apdu,
|
unsigned *max_apdu,
|
||||||
BACNET_ADDRESS * src)
|
BACNET_ADDRESS * src)
|
||||||
{
|
{
|
||||||
@@ -639,9 +685,18 @@ bool address_get_by_index(
|
|||||||
pMatch = &Address_Cache[index];
|
pMatch = &Address_Cache[index];
|
||||||
if ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ)) ==
|
if ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ)) ==
|
||||||
BAC_ADDR_IN_USE) {
|
BAC_ADDR_IN_USE) {
|
||||||
*src = pMatch->address;
|
if (src) {
|
||||||
*device_id = pMatch->device_id;
|
*src = pMatch->address;
|
||||||
*max_apdu = pMatch->max_apdu;
|
}
|
||||||
|
if (device_id) {
|
||||||
|
*device_id = pMatch->device_id;
|
||||||
|
}
|
||||||
|
if (max_apdu) {
|
||||||
|
*max_apdu = pMatch->max_apdu;
|
||||||
|
}
|
||||||
|
if (device_ttl) {
|
||||||
|
*device_ttl = pMatch->TimeToLive;
|
||||||
|
}
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -649,6 +704,15 @@ bool address_get_by_index(
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool address_get_by_index(
|
||||||
|
unsigned index,
|
||||||
|
uint32_t * device_id,
|
||||||
|
unsigned *max_apdu,
|
||||||
|
BACNET_ADDRESS * src)
|
||||||
|
{
|
||||||
|
return address_device_get_by_index(index, device_id, NULL, max_apdu, src);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned address_count(
|
unsigned address_count(
|
||||||
void)
|
void)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user