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,
*/
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;
/* 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));
/* 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),
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);
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");
/** 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;
};
/**
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;
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;
if (chunk_equals(addr, half_open->other))
{
- half_open->count++;
break;
}
item = item->next;
{
INIT(half_open,
.other = chunk_clone(addr),
- .count = 1,
);
INIT(item,
.value = half_open,
);
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);
}
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;
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)
free(item);
}
this->half_open_segments[segment].count--;
- ignore_result(ref_put(&this->half_open_count));
break;
}
prev = item;
}
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;
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;
}
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;
}
* 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.