Skip to content

Commit c3a2c5c

Browse files
author
Mika Leppänen
committed
Added limit to BR supplicant entries
Limit is set by application (default 1000 supplicants). Added garbage collecting of 5 supplicant entries on each critical garbage collection call. Both operations affect only inactive supplicant entries.
1 parent 21de90d commit c3a2c5c

File tree

11 files changed

+215
-6
lines changed

11 files changed

+215
-6
lines changed

nanostack/ws_bbr_api.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,24 @@ int ws_bbr_node_keys_remove(int8_t interface_id, uint8_t *eui64);
120120
*/
121121
int ws_bbr_node_access_revoke_start(int8_t interface_id);
122122

123+
/**
124+
* Set EAPOL node limit
125+
*
126+
* Border router stores EAPOL key information for each authenticated node.
127+
* Sets the maximum number of EAPOL nodes stored by border router. If count
128+
* of node's exceed the limit, border router deletes the node information
129+
* starting from oldest node (node that has authenticated longest time
130+
* ago), to make room for new nodes. When network keys are updated, nodes
131+
* which have been removed from storage, must make full authentication again.
132+
* Value for this parameter should be set to be more than maximum amount of
133+
* nodes that are expected to be connected to border router.
134+
*
135+
* \param interface_id Network interface ID.
136+
* \param limit Limit for nodes
137+
*
138+
* \return 0, Node limit set
139+
* \return <0 Node limit set failed.
140+
*/
141+
int ws_bbr_eapol_node_limit_set(int8_t interface_id, uint16_t limit);
142+
123143
#endif /* WS_BBR_API_H_ */

source/6LoWPAN/ws/ws_bbr_api.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,6 @@ int ws_bbr_node_keys_remove(int8_t interface_id, uint8_t *eui64)
609609
{
610610
(void) interface_id;
611611
(void) eui64;
612-
613612
#ifdef HAVE_WS_BORDER_ROUTER
614613
return ws_pae_controller_node_keys_remove(interface_id, eui64);
615614
#else
@@ -620,11 +619,20 @@ int ws_bbr_node_keys_remove(int8_t interface_id, uint8_t *eui64)
620619
int ws_bbr_node_access_revoke_start(int8_t interface_id)
621620
{
622621
(void) interface_id;
623-
624622
#ifdef HAVE_WS_BORDER_ROUTER
625623
return ws_pae_controller_node_access_revoke_start(interface_id);
626624
#else
627625
return -1;
628626
#endif
629627
}
630628

629+
int ws_bbr_eapol_node_limit_set(int8_t interface_id, uint16_t limit)
630+
{
631+
(void) interface_id;
632+
#ifdef HAVE_WS_BORDER_ROUTER
633+
return ws_pae_controller_node_limit_set(interface_id, limit);
634+
#else
635+
(void) limit;
636+
return -1;
637+
#endif
638+
}

source/6LoWPAN/ws/ws_pae_auth.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@
6363
long to wait for previous negotiation to complete */
6464
#define EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT 60 * 10 // 60 seconds
6565

66+
// Default for maximum number of supplicants
67+
#define SUPPLICANT_MAX_NUMBER 1000
68+
69+
/* Default for number of supplicants to purge per garbage collect call from
70+
nanostack monitor */
71+
#define SUPPLICANT_NUMBER_TO_PURGE 5
72+
6673
typedef struct {
6774
ns_list_link_t link; /**< Link */
6875
kmp_service_t *kmp_service; /**< KMP service */
@@ -77,6 +84,7 @@ typedef struct {
7784
sec_prot_gtk_keys_t *next_gtks; /**< Next GTKs */
7885
const sec_prot_certs_t *certs; /**< Certificates */
7986
timer_settings_t *timer_settings; /**< Timer settings */
87+
uint16_t supp_max_number; /**< Max number of stored supplicants */
8088
uint16_t slow_timer_seconds; /**< Slow timer seconds */
8189
bool timer_running : 1; /**< Timer is running */
8290
bool gtk_new_inst_req_exp : 1; /**< GTK new install required timer expired */
@@ -140,6 +148,8 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot
140148
pae_auth->next_gtks = next_gtks;
141149
pae_auth->certs = certs;
142150
pae_auth->timer_settings = timer_settings;
151+
pae_auth->supp_max_number = SUPPLICANT_MAX_NUMBER;
152+
143153
pae_auth->slow_timer_seconds = 0;
144154
pae_auth->gtk_new_inst_req_exp = false;
145155
pae_auth->gtk_new_act_time_exp = false;
@@ -407,6 +417,38 @@ int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *int
407417
return 0;
408418
}
409419

420+
int8_t ws_pae_auth_node_limit_set(protocol_interface_info_entry_t *interface_ptr, uint16_t limit)
421+
{
422+
if (!interface_ptr) {
423+
return -1;
424+
}
425+
426+
pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr);
427+
if (!pae_auth) {
428+
return -1;
429+
}
430+
431+
pae_auth->supp_max_number = limit;
432+
433+
return 0;
434+
}
435+
436+
void ws_pae_auth_forced_gc(protocol_interface_info_entry_t *interface_ptr)
437+
{
438+
if (!interface_ptr) {
439+
return;
440+
}
441+
442+
pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr);
443+
if (!pae_auth) {
444+
return;
445+
}
446+
447+
/* Purge in maximum five entries from supplicant list (starting from oldest one)
448+
per call to the function (called by nanostack monitor) */
449+
ws_pae_lib_supp_list_purge(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, 0, SUPPLICANT_NUMBER_TO_PURGE);
450+
}
451+
410452
static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth)
411453
{
412454
// Authenticator keys are always fresh
@@ -758,6 +800,9 @@ static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, kmp_type_
758800

759801
// If does not exists add it to list
760802
if (!supp_entry) {
803+
// Checks if maximum number of supplicants is reached and purge supplicant list (starting from oldest one)
804+
ws_pae_lib_supp_list_purge(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, pae_auth->supp_max_number, 0);
805+
761806
supp_entry = ws_pae_lib_supp_list_add(&pae_auth->active_supp_list, addr);
762807
if (!supp_entry) {
763808
return 0;

source/6LoWPAN/ws/ws_pae_auth.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,26 @@ int8_t ws_pae_auth_node_keys_remove(protocol_interface_info_entry_t *interface_p
146146
*/
147147
int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *interface_ptr);
148148

149+
/**
150+
* ws_pae_auth_node_limit_set set node limit
151+
*
152+
* \param interface_ptr interface
153+
* \param limit limit for nodes
154+
*
155+
* \return < 0 failure
156+
* \return >= 0 success
157+
*
158+
*/
159+
int8_t ws_pae_auth_node_limit_set(protocol_interface_info_entry_t *interface_ptr, uint16_t limit);
160+
161+
/**
162+
* ws_pae_auth_forced_gc garbage cleanup call
163+
*
164+
* \param interface_ptr interface
165+
*
166+
*/
167+
void ws_pae_auth_forced_gc(protocol_interface_info_entry_t *interface_ptr);
168+
149169
/**
150170
* ws_pae_auth_gtk_hash_set GTK hash set callback
151171
*
@@ -198,6 +218,8 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_
198218
#define ws_pae_auth_nw_key_index_update NULL
199219
#define ws_pae_auth_node_keys_remove(interface_ptr, eui64) -1
200220
#define ws_pae_auth_node_access_revoke_start(interface_ptr)
221+
#define ws_pae_auth_node_limit_set(interface_ptr, limit)
222+
#define ws_pae_auth_forced_gc(interface_ptr)
201223
#define ws_pae_auth_fast_timer NULL
202224
#define ws_pae_auth_slow_timer NULL
203225

source/6LoWPAN/ws/ws_pae_controller.c

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ typedef struct {
9797
bool key_index_set : 1; /**< NW key index is set */
9898
} pae_controller_t;
9999

100+
typedef struct {
101+
uint16_t node_limit; /**< Max number of stored supplicants */
102+
bool node_limit_set : 1; /**< Node limit set */
103+
} pae_controller_config_t;
104+
100105
static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr);
101106
static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controller_t *entry);
102107
static void ws_pae_controller_frame_counter_store(pae_controller_t *entry);
@@ -119,6 +124,11 @@ static const char *FRAME_COUNTER_FILE = FRAME_COUNTER_FILE_NAME;
119124

120125
static NS_LIST_DEFINE(pae_controller_list, pae_controller_t, link);
121126

127+
pae_controller_config_t pae_controller_config = {
128+
.node_limit = 0,
129+
.node_limit_set = false
130+
};
131+
122132
#if !defined(HAVE_PAE_SUPP) && !defined(HAVE_PAE_AUTH)
123133

124134
static void ws_pae_controller_test_keys_set(sec_prot_gtk_keys_t *gtks)
@@ -204,6 +214,10 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in
204214
return -1;
205215
}
206216

217+
if (pae_controller_config.node_limit_set) {
218+
ws_pae_auth_node_limit_set(controller->interface_ptr, pae_controller_config.node_limit);
219+
}
220+
207221
ws_pae_auth_cb_register(interface_ptr, ws_pae_controller_gtk_hash_set, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_nw_key_index_check_and_set);
208222

209223
ws_pae_auth_start(interface_ptr);
@@ -990,6 +1004,41 @@ int8_t ws_pae_controller_node_access_revoke_start(int8_t interface_id)
9901004
return -1;
9911005
}
9921006

1007+
int8_t ws_pae_controller_node_limit_set(int8_t interface_id, uint16_t limit)
1008+
{
1009+
#ifdef HAVE_PAE_AUTH
1010+
pae_controller_config.node_limit = limit;
1011+
pae_controller_config.node_limit_set = true;
1012+
1013+
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
1014+
if (!controller) {
1015+
return -1;
1016+
}
1017+
1018+
ws_pae_auth_node_limit_set(controller->interface_ptr, limit);
1019+
1020+
return 0;
1021+
#else
1022+
(void) interface_id;
1023+
(void) limit;
1024+
return -1;
1025+
#endif
1026+
}
1027+
1028+
void ws_pae_controller_forced_gc(bool full_gc)
1029+
{
1030+
/* Purge only when on critical limit since node limit should handle limiting
1031+
of entries in normal case */
1032+
if (!full_gc) {
1033+
return;
1034+
}
1035+
1036+
// Purge authenticators for each interface
1037+
ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
1038+
ws_pae_auth_forced_gc(entry->interface_ptr);
1039+
}
1040+
}
1041+
9931042
static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash)
9941043
{
9951044
pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
@@ -1086,7 +1135,6 @@ static void ws_pae_controller_frame_counter_store(pae_controller_t *entry)
10861135
}
10871136
}
10881137

1089-
10901138
static int8_t ws_pae_controller_nvm_frame_counter_read(uint8_t *index, uint8_t *hash, uint32_t *frame_counter)
10911139
{
10921140
nvm_tlv_list_t tlv_list;

source/6LoWPAN/ws/ws_pae_controller.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,18 @@ int8_t ws_pae_controller_node_keys_remove(int8_t interface_id, uint8_t *eui_64);
293293
*/
294294
int8_t ws_pae_controller_node_access_revoke_start(int8_t interface_id);
295295

296+
/**
297+
* ws_pae_controller_node_limit_set set node limit
298+
*
299+
* \param interface_id interface identifier
300+
* \param limit limit for nodes
301+
*
302+
* \return < 0 failure
303+
* \return >= 0 success
304+
*
305+
*/
306+
int8_t ws_pae_controller_node_limit_set(int8_t interface_id, uint16_t limit);
307+
296308
/**
297309
* ws_pae_controller_active_key_update update active key (test interface)
298310
*
@@ -437,7 +449,6 @@ int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_
437449
*/
438450
void ws_pae_controller_fast_timer(uint16_t ticks);
439451

440-
441452
/**
442453
* ws_pae_controller_slow_timer PAE controller slow timer call
443454
*
@@ -448,6 +459,14 @@ void ws_pae_controller_slow_timer(uint16_t seconds);
448459

449460
struct nvm_tlv_entry *ws_pae_controller_nvm_tlv_get(protocol_interface_info_entry_t *interface_ptr);
450461

462+
/**
463+
* ws_pae_controller_forced_gc PAE controller garbage cleanup callback
464+
*
465+
* \param full_gc Full cleanup (true for critical garbage cleanup)
466+
*
467+
*/
468+
void ws_pae_controller_forced_gc(bool full_gc);
469+
451470
#else
452471

453472
#define ws_pae_controller_set_target(interface_ptr, target_pan_id, target_dest_eui_64)
@@ -470,6 +489,8 @@ struct nvm_tlv_entry *ws_pae_controller_nvm_tlv_get(protocol_interface_info_entr
470489
#define ws_pae_controller_cb_register(interface_ptr, completed, nw_key_set, nw_key_clear, nw_send_key_index_set, pan_ver_increment) 1
471490
#define ws_pae_controller_nvm_tlv_get(interface_ptr) NULL
472491

492+
#define ws_pae_controller_forced_gc NULL
493+
473494
#endif
474495

475496
#endif /* WS_PAE_CONTROLLER_H_ */

source/6LoWPAN/ws/ws_pae_lib.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,30 @@ void ws_pae_lib_supp_list_to_inactive(supp_list_t *active_supp_list, supp_list_t
316316
memset(entry->addr.relay_address, 0, 16);
317317
}
318318

319+
void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, uint16_t max_number, uint8_t max_purge)
320+
{
321+
uint16_t active_supp = ns_list_count(active_supp_list);
322+
uint16_t inactive_supp = ns_list_count(inactive_supp_list);
323+
324+
if (active_supp + inactive_supp > max_number) {
325+
uint16_t remove_count = active_supp + inactive_supp - max_number;
326+
if (max_purge > 0 && remove_count > max_purge) {
327+
remove_count = max_purge;
328+
}
329+
330+
// Remove entries from inactive list
331+
ns_list_foreach_safe(supp_entry_t, entry, inactive_supp_list) {
332+
if (remove_count > 0) {
333+
tr_info("Inactive supplicant removed, eui-64: %s", trace_array(kmp_address_eui_64_get(&entry->addr), 8));
334+
ws_pae_lib_supp_list_remove(inactive_supp_list, entry);
335+
remove_count--;
336+
} else {
337+
break;
338+
}
339+
}
340+
}
341+
}
342+
319343
uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type)
320344
{
321345
uint16_t kmp_count = 0;

source/6LoWPAN/ws/ws_pae_lib.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ typedef NS_LIST_HEAD(kmp_entry_t, link) kmp_list_t;
3333

3434
typedef struct {
3535
kmp_list_t kmp_list; /**< Ongoing KMP negotiations */
36-
kmp_addr_t addr; /**< EUI-64 (Relay IP address, Relay port) */
36+
kmp_addr_t addr; /**< EUI-64 (Relay IP address, Relay port) */
3737
sec_prot_keys_t sec_keys; /**< Security keys */
3838
uint32_t ticks; /**< Ticks */
3939
uint16_t retry_ticks; /**< Retry ticks */
@@ -280,6 +280,18 @@ void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t *
280280
*/
281281
void ws_pae_lib_supp_list_to_inactive(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, supp_entry_t *entry);
282282

283+
/**
284+
* ws_pae_lib_supp_list_purge purge inactive supplicants list
285+
*
286+
* \param active_supp_list list of active supplicants
287+
* \param inactive_supp_list list of inactive supplicants
288+
* \param max_number maximum number of supplicant entries, can be set to 0 in combination with max_purge
289+
* to free list entries even when maximum number supplicant entries has not been reached
290+
* \param max_purge maximum number of supplicants to purge in one call, 0 means not limited
291+
*
292+
*/
293+
void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, uint16_t max_number, uint8_t max_purge);
294+
283295
/**
284296
* ws_pae_lib_supp_list_kmp_count counts the number of KMPs of a certain type in a list of supplicants
285297
*

source/Core/ns_monitor.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include "nsdynmemLIB.h"
3434
#include "ipv6_stack/ipv6_routing_table.h"
3535
#include "NWK_INTERFACE/Include/protocol.h"
36+
#include "6LoWPAN/ws/ws_pae_controller.h"
37+
#include "NWK_INTERFACE/Include/protocol.h"
3638

3739
#define TRACE_GROUP "mntr"
3840

@@ -68,7 +70,8 @@ typedef void (ns_maintenance_gc_cb)(bool full_gc);
6870
*
6971
*/
7072
static ns_maintenance_gc_cb *ns_maintenance_gc_functions[] = {
71-
ipv6_destination_cache_forced_gc
73+
ipv6_destination_cache_forced_gc,
74+
ws_pae_controller_forced_gc
7275
};
7376

7477
static void ns_monitor_heap_gc(bool full_gc)

test/nanostack/unittest/Core/monitor/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ TEST_SRC_FILES = \
2222
../../stub/ipv6_routing_table_stub.c \
2323
../../stub/protocol_core_stub.c \
2424
../../stub/ip6tos_stub.c \
25+
../../stub/ws_pae_controller_stub.c \
2526

2627
include ../../MakefileWorker.mk
2728

0 commit comments

Comments
 (0)