diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libcharon/control/controller.c | 2 | ||||
-rw-r--r-- | src/libcharon/network/receiver.c | 12 | ||||
-rw-r--r-- | src/libcharon/plugins/stroke/stroke_list.c | 2 | ||||
-rw-r--r-- | src/libcharon/plugins/vici/vici_query.c | 2 | ||||
-rw-r--r-- | src/libcharon/sa/ike_sa_manager.c | 37 | ||||
-rw-r--r-- | src/libcharon/sa/ike_sa_manager.h | 9 |
6 files changed, 45 insertions, 19 deletions
diff --git a/src/libcharon/control/controller.c b/src/libcharon/control/controller.c index 097f5ac2e..6dd54b473 100644 --- a/src/libcharon/control/controller.c +++ b/src/libcharon/control/controller.c @@ -381,7 +381,7 @@ METHOD(job_t, initiate_execute, job_requeue_t, u_int half_open, limit_half_open, limit_job_load; half_open = charon->ike_sa_manager->get_half_open_count( - charon->ike_sa_manager, NULL); + charon->ike_sa_manager, NULL, FALSE); limit_half_open = lib->settings->get_int(lib->settings, "%s.init_limit_half_open", 0, lib->ns); limit_job_load = lib->settings->get_int(lib->settings, diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c index 076233260..a2f2016ff 100644 --- a/src/libcharon/network/receiver.c +++ b/src/libcharon/network/receiver.c @@ -322,16 +322,18 @@ static bool cookie_required(private_receiver_t *this, */ static bool drop_ike_sa_init(private_receiver_t *this, message_t *message) { - u_int half_open; + u_int half_open, half_open_r; u_int32_t now; now = time_monotonic(NULL); half_open = charon->ike_sa_manager->get_half_open_count( - charon->ike_sa_manager, NULL); + charon->ike_sa_manager, NULL, FALSE); + half_open_r = charon->ike_sa_manager->get_half_open_count( + charon->ike_sa_manager, NULL, TRUE); /* check for cookies in IKEv2 */ if (message->get_major_version(message) == IKEV2_MAJOR_VERSION && - cookie_required(this, half_open, now) && !check_cookie(this, message)) + cookie_required(this, half_open_r, now) && !check_cookie(this, message)) { chunk_t cookie; @@ -372,7 +374,7 @@ static bool drop_ike_sa_init(private_receiver_t *this, message_t *message) /* check if peer has too many IKE_SAs half open */ if (this->block_threshold && charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager, - message->get_source(message)) >= this->block_threshold) + message->get_source(message), TRUE) >= this->block_threshold) { DBG1(DBG_NET, "ignoring IKE_SA setup from %H, " "peer too aggressive", message->get_source(message)); @@ -381,7 +383,7 @@ static bool drop_ike_sa_init(private_receiver_t *this, message_t *message) /* check if global half open IKE_SA limit reached */ if (this->init_limit_half_open && - half_open >= this->init_limit_half_open) + half_open >= this->init_limit_half_open) { DBG1(DBG_NET, "ignoring IKE_SA setup from %H, half open IKE_SA " "count of %d exceeds limit of %d", message->get_source(message), diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c index 68b8232bc..c7e4c9c65 100644 --- a/src/libcharon/plugins/stroke/stroke_list.c +++ b/src/libcharon/plugins/stroke/stroke_list.c @@ -647,7 +647,7 @@ METHOD(stroke_list_t, status, void, enumerator->destroy(enumerator); half_open = charon->ike_sa_manager->get_half_open_count( - charon->ike_sa_manager, NULL); + charon->ike_sa_manager, NULL, FALSE); fprintf(out, "Security Associations (%u up, %u connecting):\n", charon->ike_sa_manager->get_count(charon->ike_sa_manager) - half_open, half_open); diff --git a/src/libcharon/plugins/vici/vici_query.c b/src/libcharon/plugins/vici/vici_query.c index e4d0d62f4..98d264fca 100644 --- a/src/libcharon/plugins/vici/vici_query.c +++ b/src/libcharon/plugins/vici/vici_query.c @@ -929,7 +929,7 @@ CALLBACK(stats, vici_message_t*, charon->ike_sa_manager->get_count(charon->ike_sa_manager)); b->add_kv(b, "half-open", "%u", charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager, - NULL)); + NULL, FALSE)); b->end_section(b); b->begin_list(b, "plugins"); diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c index 137920a96..9f4496a4e 100644 --- a/src/libcharon/sa/ike_sa_manager.c +++ b/src/libcharon/sa/ike_sa_manager.c @@ -206,6 +206,9 @@ struct half_open_t { /** the number of half-open IKE_SAs with that host */ u_int count; + + /** the number of half-open IKE_SAs we responded to with that host */ + u_int count_responder; }; /** @@ -361,6 +364,11 @@ struct private_ike_sa_manager_t { refcount_t half_open_count; /** + * Total number of half-open IKE_SAs as responder. + */ + refcount_t half_open_count_responder; + + /** * Hash table with connected_peers_t objects. */ table_item_t **connected_peers_table; @@ -737,9 +745,11 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry) table_item_t *item; u_int row, segment; rwlock_t *lock; + ike_sa_id_t *ike_id; half_open_t *half_open; chunk_t addr; + ike_id = entry->ike_sa_id; addr = entry->other->get_address(entry->other); row = chunk_hash(addr) & this->table_mask; segment = row & this->segment_mask; @@ -752,7 +762,6 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry) if (chunk_equals(addr, half_open->other)) { - half_open->count++; break; } item = item->next; @@ -762,7 +771,6 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry) { INIT(half_open, .other = chunk_clone(addr), - .count = 1, ); INIT(item, .value = half_open, @@ -770,8 +778,14 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry) ); this->half_open_table[row] = item; } - this->half_open_segments[segment].count++; + half_open->count++; ref_get(&this->half_open_count); + if (!ike_id->is_initiator(ike_id)) + { + half_open->count_responder++; + ref_get(&this->half_open_count_responder); + } + this->half_open_segments[segment].count++; lock->unlock(lock); } @@ -783,8 +797,10 @@ static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry) table_item_t *item, *prev = NULL; u_int row, segment; rwlock_t *lock; + ike_sa_id_t *ike_id; chunk_t addr; + ike_id = entry->ike_sa_id; addr = entry->other->get_address(entry->other); row = chunk_hash(addr) & this->table_mask; segment = row & this->segment_mask; @@ -797,6 +813,12 @@ static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry) if (chunk_equals(addr, half_open->other)) { + if (!ike_id->is_initiator(ike_id)) + { + half_open->count_responder--; + ignore_result(ref_put(&this->half_open_count_responder)); + } + ignore_result(ref_put(&this->half_open_count)); if (--half_open->count == 0) { if (prev) @@ -811,7 +833,6 @@ static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry) free(item); } this->half_open_segments[segment].count--; - ignore_result(ref_put(&this->half_open_count)); break; } prev = item; @@ -1945,7 +1966,7 @@ METHOD(ike_sa_manager_t, get_count, u_int, } METHOD(ike_sa_manager_t, get_half_open_count, u_int, - private_ike_sa_manager_t *this, host_t *ip) + private_ike_sa_manager_t *this, host_t *ip, bool responder_only) { table_item_t *item; u_int row, segment; @@ -1967,7 +1988,8 @@ METHOD(ike_sa_manager_t, get_half_open_count, u_int, if (chunk_equals(addr, half_open->other)) { - count = half_open->count; + count = responder_only ? half_open->count_responder + : half_open->count; break; } item = item->next; @@ -1976,7 +1998,8 @@ METHOD(ike_sa_manager_t, get_half_open_count, u_int, } else { - count = (u_int)ref_cur(&this->half_open_count); + count = responder_only ? (u_int)ref_cur(&this->half_open_count_responder) + : (u_int)ref_cur(&this->half_open_count); } return count; } diff --git a/src/libcharon/sa/ike_sa_manager.h b/src/libcharon/sa/ike_sa_manager.h index f259d8e56..3ea928ea5 100644 --- a/src/libcharon/sa/ike_sa_manager.h +++ b/src/libcharon/sa/ike_sa_manager.h @@ -216,14 +216,15 @@ struct ike_sa_manager_t { * To prevent the server from resource exhaustion, cookies and other * mechanisms are used. The number of half open IKE_SAs is a good * indicator to see if a peer is flooding the server. - * If a host is supplied, only the number of half open IKE_SAs initiated - * from this IP are counted. - * Only SAs for which we are the responder are counted. + * If a host is supplied, only the number of half open IKE_SAs with this IP + * are counted. * * @param ip NULL for all, IP for half open IKE_SAs with IP + * @param responder_only TRUE to return only the number of responding SAs * @return number of half open IKE_SAs */ - u_int (*get_half_open_count) (ike_sa_manager_t *this, host_t *ip); + u_int (*get_half_open_count)(ike_sa_manager_t *this, host_t *ip, + bool responder_only); /** * Delete all existing IKE_SAs and destroy them immediately. |