Merge branch 'libipsec-usestats'
Brings SA usage statistics and volume based expiration to libipsec and the associated kernel-libipsec plugin. Additionally removes any ESPv3 style TFC padding found in incoming packets.
This commit is contained in:
@@ -217,7 +217,7 @@ sad_failure:
|
|||||||
METHOD(kernel_ipsec_t, query_sa, status_t,
|
METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||||
private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
|
private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
|
||||||
u_int32_t spi, u_int8_t protocol, mark_t mark, u_int64_t *bytes,
|
u_int32_t spi, u_int8_t protocol, mark_t mark, u_int64_t *bytes,
|
||||||
u_int64_t *packets, u_int32_t *time)
|
u_int64_t *packets, time_t *time)
|
||||||
{
|
{
|
||||||
return NOT_SUPPORTED;
|
return NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
@@ -271,7 +271,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
|||||||
METHOD(kernel_ipsec_t, query_policy, status_t,
|
METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||||
private_tkm_kernel_ipsec_t *this, traffic_selector_t *src_ts,
|
private_tkm_kernel_ipsec_t *this, traffic_selector_t *src_ts,
|
||||||
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
||||||
u_int32_t *use_time)
|
time_t *use_time)
|
||||||
{
|
{
|
||||||
return NOT_SUPPORTED;
|
return NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
|||||||
METHOD(kernel_ipsec_t, query_sa, status_t,
|
METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||||
private_kernel_android_ipsec_t *this, host_t *src, host_t *dst,
|
private_kernel_android_ipsec_t *this, host_t *src, host_t *dst,
|
||||||
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
||||||
u_int64_t *bytes, u_int64_t *packets, u_int32_t *time)
|
u_int64_t *bytes, u_int64_t *packets, time_t *time)
|
||||||
{
|
{
|
||||||
return NOT_SUPPORTED;
|
return NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
@@ -118,7 +118,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
|||||||
METHOD(kernel_ipsec_t, query_policy, status_t,
|
METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||||
private_kernel_android_ipsec_t *this, traffic_selector_t *src_ts,
|
private_kernel_android_ipsec_t *this, traffic_selector_t *src_ts,
|
||||||
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
||||||
u_int32_t *use_time)
|
time_t *use_time)
|
||||||
{
|
{
|
||||||
return NOT_SUPPORTED;
|
return NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ static void expire(u_int32_t reqid, u_int8_t protocol, u_int32_t spi, bool hard)
|
|||||||
METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
|
METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
|
||||||
private_kernel_libipsec_ipsec_t *this)
|
private_kernel_libipsec_ipsec_t *this)
|
||||||
{
|
{
|
||||||
return KERNEL_REQUIRE_UDP_ENCAPSULATION;
|
return KERNEL_REQUIRE_UDP_ENCAPSULATION | KERNEL_ESP_V3_TFC;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(kernel_ipsec_t, get_spi, status_t,
|
METHOD(kernel_ipsec_t, get_spi, status_t,
|
||||||
@@ -268,9 +268,10 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
|||||||
METHOD(kernel_ipsec_t, query_sa, status_t,
|
METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||||
private_kernel_libipsec_ipsec_t *this, host_t *src, host_t *dst,
|
private_kernel_libipsec_ipsec_t *this, host_t *src, host_t *dst,
|
||||||
u_int32_t spi, u_int8_t protocol, mark_t mark, u_int64_t *bytes,
|
u_int32_t spi, u_int8_t protocol, mark_t mark, u_int64_t *bytes,
|
||||||
u_int64_t *packets, u_int32_t *time)
|
u_int64_t *packets, time_t *time)
|
||||||
{
|
{
|
||||||
return NOT_SUPPORTED;
|
return ipsec->sas->query_sa(ipsec->sas, src, dst, spi, protocol, mark,
|
||||||
|
bytes, packets, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(kernel_ipsec_t, del_sa, status_t,
|
METHOD(kernel_ipsec_t, del_sa, status_t,
|
||||||
@@ -555,7 +556,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
|||||||
METHOD(kernel_ipsec_t, query_policy, status_t,
|
METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||||
private_kernel_libipsec_ipsec_t *this, traffic_selector_t *src_ts,
|
private_kernel_libipsec_ipsec_t *this, traffic_selector_t *src_ts,
|
||||||
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
||||||
u_int32_t *use_time)
|
time_t *use_time)
|
||||||
{
|
{
|
||||||
return NOT_SUPPORTED;
|
return NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
|||||||
METHOD(kernel_ipsec_t, query_sa, status_t,
|
METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||||
private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
|
private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
|
||||||
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
||||||
u_int64_t *bytes, u_int64_t *packets, u_int32_t *time)
|
u_int64_t *bytes, u_int64_t *packets, time_t *time)
|
||||||
{
|
{
|
||||||
return NOT_SUPPORTED;
|
return NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
@@ -95,7 +95,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
|||||||
METHOD(kernel_ipsec_t, query_policy, status_t,
|
METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||||
private_load_tester_ipsec_t *this, traffic_selector_t *src_ts,
|
private_load_tester_ipsec_t *this, traffic_selector_t *src_ts,
|
||||||
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
||||||
u_int32_t *use_time)
|
time_t *use_time)
|
||||||
{
|
{
|
||||||
*use_time = 1;
|
*use_time = 1;
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
|||||||
@@ -167,12 +167,12 @@ struct private_child_sa_t {
|
|||||||
/**
|
/**
|
||||||
* time of last use in seconds (inbound)
|
* time of last use in seconds (inbound)
|
||||||
*/
|
*/
|
||||||
u_int32_t my_usetime;
|
time_t my_usetime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* time of last use in seconds (outbound)
|
* time of last use in seconds (outbound)
|
||||||
*/
|
*/
|
||||||
u_int32_t other_usetime;
|
time_t other_usetime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* last number of inbound bytes
|
* last number of inbound bytes
|
||||||
@@ -429,7 +429,7 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
|
|||||||
{
|
{
|
||||||
status_t status = FAILED;
|
status_t status = FAILED;
|
||||||
u_int64_t bytes, packets;
|
u_int64_t bytes, packets;
|
||||||
u_int32_t time;
|
time_t time;
|
||||||
|
|
||||||
if (inbound)
|
if (inbound)
|
||||||
{
|
{
|
||||||
@@ -489,12 +489,12 @@ static bool update_usetime(private_child_sa_t *this, bool inbound)
|
|||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
traffic_selector_t *my_ts, *other_ts;
|
traffic_selector_t *my_ts, *other_ts;
|
||||||
u_int32_t last_use = 0;
|
time_t last_use = 0;
|
||||||
|
|
||||||
enumerator = create_policy_enumerator(this);
|
enumerator = create_policy_enumerator(this);
|
||||||
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
|
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
|
||||||
{
|
{
|
||||||
u_int32_t in, out, fwd;
|
time_t in, out, fwd;
|
||||||
|
|
||||||
if (inbound)
|
if (inbound)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ METHOD(kernel_interface_t, update_sa, status_t,
|
|||||||
METHOD(kernel_interface_t, query_sa, status_t,
|
METHOD(kernel_interface_t, query_sa, status_t,
|
||||||
private_kernel_interface_t *this, host_t *src, host_t *dst,
|
private_kernel_interface_t *this, host_t *src, host_t *dst,
|
||||||
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
||||||
u_int64_t *bytes, u_int64_t *packets, u_int32_t *time)
|
u_int64_t *bytes, u_int64_t *packets, time_t *time)
|
||||||
{
|
{
|
||||||
if (!this->ipsec)
|
if (!this->ipsec)
|
||||||
{
|
{
|
||||||
@@ -256,7 +256,7 @@ METHOD(kernel_interface_t, add_policy, status_t,
|
|||||||
METHOD(kernel_interface_t, query_policy, status_t,
|
METHOD(kernel_interface_t, query_policy, status_t,
|
||||||
private_kernel_interface_t *this, traffic_selector_t *src_ts,
|
private_kernel_interface_t *this, traffic_selector_t *src_ts,
|
||||||
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
||||||
u_int32_t *use_time)
|
time_t *use_time)
|
||||||
{
|
{
|
||||||
if (!this->ipsec)
|
if (!this->ipsec)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -200,12 +200,12 @@ struct kernel_interface_t {
|
|||||||
* @param mark optional mark for this SA
|
* @param mark optional mark for this SA
|
||||||
* @param[out] bytes the number of bytes processed by SA
|
* @param[out] bytes the number of bytes processed by SA
|
||||||
* @param[out] packets number of packets processed by SA
|
* @param[out] packets number of packets processed by SA
|
||||||
* @param[out] time last time of SA use
|
* @param[out] time last (monotonic) time of SA use
|
||||||
* @return SUCCESS if operation completed
|
* @return SUCCESS if operation completed
|
||||||
*/
|
*/
|
||||||
status_t (*query_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
|
status_t (*query_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
|
||||||
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
||||||
u_int64_t *bytes, u_int64_t *packets, u_int32_t *time);
|
u_int64_t *bytes, u_int64_t *packets, time_t *time);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a previously installed SA from the SAD.
|
* Delete a previously installed SA from the SAD.
|
||||||
@@ -264,14 +264,14 @@ struct kernel_interface_t {
|
|||||||
* @param dst_ts traffic selector to match traffic dest
|
* @param dst_ts traffic selector to match traffic dest
|
||||||
* @param direction direction of traffic, POLICY_(IN|OUT|FWD)
|
* @param direction direction of traffic, POLICY_(IN|OUT|FWD)
|
||||||
* @param mark optional mark
|
* @param mark optional mark
|
||||||
* @param[out] use_time the time of this SA's last use
|
* @param[out] use_time the (monotonic) time of this SA's last use
|
||||||
* @return SUCCESS if operation completed
|
* @return SUCCESS if operation completed
|
||||||
*/
|
*/
|
||||||
status_t (*query_policy) (kernel_interface_t *this,
|
status_t (*query_policy) (kernel_interface_t *this,
|
||||||
traffic_selector_t *src_ts,
|
traffic_selector_t *src_ts,
|
||||||
traffic_selector_t *dst_ts,
|
traffic_selector_t *dst_ts,
|
||||||
policy_dir_t direction, mark_t mark,
|
policy_dir_t direction, mark_t mark,
|
||||||
u_int32_t *use_time);
|
time_t *use_time);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a policy from the SPD.
|
* Remove a policy from the SPD.
|
||||||
|
|||||||
@@ -156,12 +156,12 @@ struct kernel_ipsec_t {
|
|||||||
* @param mark optional mark for this SA
|
* @param mark optional mark for this SA
|
||||||
* @param[out] bytes the number of bytes processed by SA
|
* @param[out] bytes the number of bytes processed by SA
|
||||||
* @param[out] packets number of packets processed by SA
|
* @param[out] packets number of packets processed by SA
|
||||||
* @param[out] time last time of SA use
|
* @param[out] time last (monotonic) time of SA use
|
||||||
* @return SUCCESS if operation completed
|
* @return SUCCESS if operation completed
|
||||||
*/
|
*/
|
||||||
status_t (*query_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
|
status_t (*query_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
|
||||||
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
||||||
u_int64_t *bytes, u_int64_t *packets, u_int32_t *time);
|
u_int64_t *bytes, u_int64_t *packets, time_t *time);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a previusly installed SA from the SAD.
|
* Delete a previusly installed SA from the SAD.
|
||||||
@@ -228,7 +228,7 @@ struct kernel_ipsec_t {
|
|||||||
traffic_selector_t *src_ts,
|
traffic_selector_t *src_ts,
|
||||||
traffic_selector_t *dst_ts,
|
traffic_selector_t *dst_ts,
|
||||||
policy_dir_t direction, mark_t mark,
|
policy_dir_t direction, mark_t mark,
|
||||||
u_int32_t *use_time);
|
time_t *use_time);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a policy from the SPD.
|
* Remove a policy from the SPD.
|
||||||
|
|||||||
@@ -1911,7 +1911,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
|||||||
METHOD(kernel_ipsec_t, query_sa, status_t,
|
METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||||
private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
|
private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
|
||||||
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
||||||
u_int64_t *bytes, u_int64_t *packets, u_int32_t *time)
|
u_int64_t *bytes, u_int64_t *packets, time_t *time)
|
||||||
{
|
{
|
||||||
return NOT_SUPPORTED; /* TODO */
|
return NOT_SUPPORTED; /* TODO */
|
||||||
}
|
}
|
||||||
@@ -2207,7 +2207,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
|||||||
METHOD(kernel_ipsec_t, query_policy, status_t,
|
METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||||
private_kernel_klips_ipsec_t *this, traffic_selector_t *src_ts,
|
private_kernel_klips_ipsec_t *this, traffic_selector_t *src_ts,
|
||||||
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
||||||
u_int32_t *use_time)
|
time_t *use_time)
|
||||||
{
|
{
|
||||||
#define IDLE_PREFIX "idle="
|
#define IDLE_PREFIX "idle="
|
||||||
static const char *path_eroute = "/proc/net/ipsec_eroute";
|
static const char *path_eroute = "/proc/net/ipsec_eroute";
|
||||||
|
|||||||
@@ -1611,7 +1611,7 @@ static void get_replay_state(private_kernel_netlink_ipsec_t *this,
|
|||||||
METHOD(kernel_ipsec_t, query_sa, status_t,
|
METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||||
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
|
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
|
||||||
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
||||||
u_int64_t *bytes, u_int64_t *packets, u_int32_t *time)
|
u_int64_t *bytes, u_int64_t *packets, time_t *time)
|
||||||
{
|
{
|
||||||
netlink_buf_t request;
|
netlink_buf_t request;
|
||||||
struct nlmsghdr *out = NULL, *hdr;
|
struct nlmsghdr *out = NULL, *hdr;
|
||||||
@@ -2302,7 +2302,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
|||||||
METHOD(kernel_ipsec_t, query_policy, status_t,
|
METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||||
private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts,
|
private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts,
|
||||||
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
||||||
u_int32_t *use_time)
|
time_t *use_time)
|
||||||
{
|
{
|
||||||
netlink_buf_t request;
|
netlink_buf_t request;
|
||||||
struct nlmsghdr *out = NULL, *hdr;
|
struct nlmsghdr *out = NULL, *hdr;
|
||||||
|
|||||||
@@ -1802,7 +1802,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
|||||||
METHOD(kernel_ipsec_t, query_sa, status_t,
|
METHOD(kernel_ipsec_t, query_sa, status_t,
|
||||||
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
|
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
|
||||||
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
||||||
u_int64_t *bytes, u_int64_t *packets, u_int32_t *time)
|
u_int64_t *bytes, u_int64_t *packets, time_t *time)
|
||||||
{
|
{
|
||||||
unsigned char request[PFKEY_BUFFER_SIZE];
|
unsigned char request[PFKEY_BUFFER_SIZE];
|
||||||
struct sadb_msg *msg, *out;
|
struct sadb_msg *msg, *out;
|
||||||
@@ -2382,7 +2382,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
|||||||
METHOD(kernel_ipsec_t, query_policy, status_t,
|
METHOD(kernel_ipsec_t, query_policy, status_t,
|
||||||
private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
|
private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
|
||||||
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
|
||||||
u_int32_t *use_time)
|
time_t *use_time)
|
||||||
{
|
{
|
||||||
unsigned char request[PFKEY_BUFFER_SIZE];
|
unsigned char request[PFKEY_BUFFER_SIZE];
|
||||||
struct sadb_msg *msg, *out;
|
struct sadb_msg *msg, *out;
|
||||||
|
|||||||
@@ -139,6 +139,9 @@ ip_packet_t *ip_packet_create(chunk_t packet)
|
|||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
ip = (struct ip*)packet.ptr;
|
ip = (struct ip*)packet.ptr;
|
||||||
|
/* remove any RFC 4303 TFC extra padding */
|
||||||
|
packet.len = min(packet.len, untoh16(&ip->ip_len));
|
||||||
|
|
||||||
src = host_create_from_chunk(AF_INET,
|
src = host_create_from_chunk(AF_INET,
|
||||||
chunk_from_thing(ip->ip_src), 0);
|
chunk_from_thing(ip->ip_src), 0);
|
||||||
dst = host_create_from_chunk(AF_INET,
|
dst = host_create_from_chunk(AF_INET,
|
||||||
@@ -157,6 +160,9 @@ ip_packet_t *ip_packet_create(chunk_t packet)
|
|||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
ip = (struct ip6_hdr*)packet.ptr;
|
ip = (struct ip6_hdr*)packet.ptr;
|
||||||
|
/* remove any RFC 4303 TFC extra padding */
|
||||||
|
packet.len = min(packet.len, untoh16(&ip->ip6_plen));
|
||||||
|
|
||||||
src = host_create_from_chunk(AF_INET6,
|
src = host_create_from_chunk(AF_INET6,
|
||||||
chunk_from_thing(ip->ip6_src), 0);
|
chunk_from_thing(ip->ip6_src), 0);
|
||||||
dst = host_create_from_chunk(AF_INET6,
|
dst = host_create_from_chunk(AF_INET6,
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ static void deliver_inbound(private_ipsec_processor_t *this,
|
|||||||
static job_requeue_t process_inbound(private_ipsec_processor_t *this)
|
static job_requeue_t process_inbound(private_ipsec_processor_t *this)
|
||||||
{
|
{
|
||||||
esp_packet_t *packet;
|
esp_packet_t *packet;
|
||||||
|
ip_packet_t *ip_packet;
|
||||||
ipsec_sa_t *sa;
|
ipsec_sa_t *sa;
|
||||||
u_int8_t next_header;
|
u_int8_t next_header;
|
||||||
u_int32_t spi, reqid;
|
u_int32_t spi, reqid;
|
||||||
@@ -126,6 +127,8 @@ static job_requeue_t process_inbound(private_ipsec_processor_t *this)
|
|||||||
packet->destroy(packet);
|
packet->destroy(packet);
|
||||||
return JOB_REQUEUE_DIRECT;
|
return JOB_REQUEUE_DIRECT;
|
||||||
}
|
}
|
||||||
|
ip_packet = packet->get_payload(packet);
|
||||||
|
sa->update_usestats(sa, ip_packet->get_encoding(ip_packet).len);
|
||||||
reqid = sa->get_reqid(sa);
|
reqid = sa->get_reqid(sa);
|
||||||
ipsec->sas->checkin(ipsec->sas, sa);
|
ipsec->sas->checkin(ipsec->sas, sa);
|
||||||
|
|
||||||
@@ -136,13 +139,11 @@ static job_requeue_t process_inbound(private_ipsec_processor_t *this)
|
|||||||
case IPPROTO_IPV6:
|
case IPPROTO_IPV6:
|
||||||
{
|
{
|
||||||
ipsec_policy_t *policy;
|
ipsec_policy_t *policy;
|
||||||
ip_packet_t *ip_packet;
|
|
||||||
|
|
||||||
ip_packet = packet->get_payload(packet);
|
|
||||||
policy = ipsec->policies->find_by_packet(ipsec->policies,
|
policy = ipsec->policies->find_by_packet(ipsec->policies,
|
||||||
ip_packet, TRUE, reqid);
|
ip_packet, TRUE, reqid);
|
||||||
if (policy)
|
if (policy)
|
||||||
{ /* TODO-IPSEC: update policy/sa stats? */
|
{
|
||||||
deliver_inbound(this, packet);
|
deliver_inbound(this, packet);
|
||||||
policy->destroy(policy);
|
policy->destroy(policy);
|
||||||
break;
|
break;
|
||||||
@@ -225,7 +226,7 @@ static job_requeue_t process_outbound(private_ipsec_processor_t *this)
|
|||||||
policy->destroy(policy);
|
policy->destroy(policy);
|
||||||
return JOB_REQUEUE_DIRECT;
|
return JOB_REQUEUE_DIRECT;
|
||||||
}
|
}
|
||||||
/* TODO-IPSEC: update policy/sa counters? */
|
sa->update_usestats(sa, packet->get_encoding(packet).len);
|
||||||
ipsec->sas->checkin(ipsec->sas, sa);
|
ipsec->sas->checkin(ipsec->sas, sa);
|
||||||
policy->destroy(policy);
|
policy->destroy(policy);
|
||||||
send_outbound(this, esp_packet);
|
send_outbound(this, esp_packet);
|
||||||
|
|||||||
+100
-2
@@ -15,6 +15,7 @@
|
|||||||
* for more details.
|
* for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "ipsec.h"
|
||||||
#include "ipsec_sa.h"
|
#include "ipsec_sa.h"
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
@@ -81,6 +82,28 @@ struct private_ipsec_sa_t {
|
|||||||
* ESP context
|
* ESP context
|
||||||
*/
|
*/
|
||||||
esp_context_t *esp_context;
|
esp_context_t *esp_context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Usage statistics
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
/** last time of use */
|
||||||
|
time_t time;
|
||||||
|
/** number of packets processed */
|
||||||
|
u_int64_t packets;
|
||||||
|
/** number of bytes processed */
|
||||||
|
u_int64_t bytes;
|
||||||
|
} use;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has the SA soft-expired?
|
||||||
|
*/
|
||||||
|
bool soft_expired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has the SA hard-expired?
|
||||||
|
*/
|
||||||
|
bool hard_expired;
|
||||||
};
|
};
|
||||||
|
|
||||||
METHOD(ipsec_sa_t, get_source, host_t*,
|
METHOD(ipsec_sa_t, get_source, host_t*,
|
||||||
@@ -145,10 +168,81 @@ METHOD(ipsec_sa_t, get_esp_context, esp_context_t*,
|
|||||||
return this->esp_context;
|
return this->esp_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(ipsec_sa_t, get_usestats, void,
|
||||||
|
private_ipsec_sa_t *this, u_int64_t *bytes, u_int64_t *packets,
|
||||||
|
time_t *time)
|
||||||
|
{
|
||||||
|
if (bytes)
|
||||||
|
{
|
||||||
|
*bytes = this->use.bytes;
|
||||||
|
}
|
||||||
|
if (packets)
|
||||||
|
{
|
||||||
|
*packets = this->use.packets;
|
||||||
|
}
|
||||||
|
if (time)
|
||||||
|
{
|
||||||
|
*time = this->use.time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(ipsec_sa_t, expire, void,
|
||||||
|
private_ipsec_sa_t *this, bool hard)
|
||||||
|
{
|
||||||
|
if (hard)
|
||||||
|
{
|
||||||
|
if (!this->hard_expired)
|
||||||
|
{
|
||||||
|
this->hard_expired = TRUE;
|
||||||
|
ipsec->events->expire(ipsec->events, this->reqid, this->protocol,
|
||||||
|
this->spi, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!this->hard_expired && !this->soft_expired)
|
||||||
|
{
|
||||||
|
this->soft_expired = TRUE;
|
||||||
|
ipsec->events->expire(ipsec->events, this->reqid, this->protocol,
|
||||||
|
this->spi, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(ipsec_sa_t, update_usestats, void,
|
||||||
|
private_ipsec_sa_t *this, u_int32_t bytes)
|
||||||
|
{
|
||||||
|
this->use.time = time_monotonic(NULL);
|
||||||
|
this->use.packets++;
|
||||||
|
this->use.bytes += bytes;
|
||||||
|
|
||||||
|
if (this->lifetime.packets.life &&
|
||||||
|
this->use.packets >= this->lifetime.packets.life)
|
||||||
|
{
|
||||||
|
return expire(this, TRUE);
|
||||||
|
}
|
||||||
|
if (this->lifetime.bytes.life &&
|
||||||
|
this->use.bytes >= this->lifetime.bytes.life)
|
||||||
|
{
|
||||||
|
return expire(this, TRUE);
|
||||||
|
}
|
||||||
|
if (this->lifetime.packets.rekey &&
|
||||||
|
this->use.packets >= this->lifetime.packets.rekey)
|
||||||
|
{
|
||||||
|
return expire(this, FALSE);
|
||||||
|
}
|
||||||
|
if (this->lifetime.bytes.rekey &&
|
||||||
|
this->use.bytes >= this->lifetime.bytes.rekey)
|
||||||
|
{
|
||||||
|
return expire(this, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(ipsec_sa_t, match_by_spi_dst, bool,
|
METHOD(ipsec_sa_t, match_by_spi_dst, bool,
|
||||||
private_ipsec_sa_t *this, u_int32_t spi, host_t *dst)
|
private_ipsec_sa_t *this, u_int32_t spi, host_t *dst)
|
||||||
{
|
{
|
||||||
return this->spi == spi && this->dst->ip_equals(this->dst, dst);
|
return this->spi == spi && this->dst->ip_equals(this->dst, dst) &&
|
||||||
|
!this->hard_expired;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(ipsec_sa_t, match_by_spi_src_dst, bool,
|
METHOD(ipsec_sa_t, match_by_spi_src_dst, bool,
|
||||||
@@ -161,7 +255,8 @@ METHOD(ipsec_sa_t, match_by_spi_src_dst, bool,
|
|||||||
METHOD(ipsec_sa_t, match_by_reqid, bool,
|
METHOD(ipsec_sa_t, match_by_reqid, bool,
|
||||||
private_ipsec_sa_t *this, u_int32_t reqid, bool inbound)
|
private_ipsec_sa_t *this, u_int32_t reqid, bool inbound)
|
||||||
{
|
{
|
||||||
return this->reqid == reqid && this->inbound == inbound;
|
return this->reqid == reqid && this->inbound == inbound &&
|
||||||
|
!this->hard_expired;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(ipsec_sa_t, destroy, void,
|
METHOD(ipsec_sa_t, destroy, void,
|
||||||
@@ -227,6 +322,9 @@ ipsec_sa_t *ipsec_sa_create(u_int32_t spi, host_t *src, host_t *dst,
|
|||||||
.match_by_spi_src_dst = _match_by_spi_src_dst,
|
.match_by_spi_src_dst = _match_by_spi_src_dst,
|
||||||
.match_by_reqid = _match_by_reqid,
|
.match_by_reqid = _match_by_reqid,
|
||||||
.get_esp_context = _get_esp_context,
|
.get_esp_context = _get_esp_context,
|
||||||
|
.get_usestats = _get_usestats,
|
||||||
|
.update_usestats = _update_usestats,
|
||||||
|
.expire = _expire,
|
||||||
},
|
},
|
||||||
.spi = spi,
|
.spi = spi,
|
||||||
.src = src->clone(src),
|
.src = src->clone(src),
|
||||||
|
|||||||
@@ -109,9 +109,38 @@ struct ipsec_sa_t {
|
|||||||
*/
|
*/
|
||||||
esp_context_t *(*get_esp_context)(ipsec_sa_t *this);
|
esp_context_t *(*get_esp_context)(ipsec_sa_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get usage statistics for this SA.
|
||||||
|
*
|
||||||
|
* @param bytes receives number of processed bytes, or NULL
|
||||||
|
* @param packets receives number of processed packets, or NULL
|
||||||
|
* @param time receives last use time of this SA, or NULL
|
||||||
|
*/
|
||||||
|
void (*get_usestats)(ipsec_sa_t *this, u_int64_t *bytes, u_int64_t *packets,
|
||||||
|
time_t *time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record en/decryption of a packet to update usage statistics.
|
||||||
|
*
|
||||||
|
* @param bytes length of packet processed
|
||||||
|
*/
|
||||||
|
void (*update_usestats)(ipsec_sa_t *this, u_int32_t bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expire this SA, soft or hard.
|
||||||
|
*
|
||||||
|
* A soft expire triggers a rekey, a hard expire blocks the SA and
|
||||||
|
* triggers a delete for the SA.
|
||||||
|
*
|
||||||
|
* @param hard TRUE for hard, FALSE for soft
|
||||||
|
*/
|
||||||
|
void (*expire)(ipsec_sa_t *this, bool hard);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if this SA matches all given parameters
|
* Check if this SA matches all given parameters
|
||||||
*
|
*
|
||||||
|
* Only matches if the SA has not yet expired.
|
||||||
|
*
|
||||||
* @param spi SPI
|
* @param spi SPI
|
||||||
* @param dst destination address
|
* @param dst destination address
|
||||||
* @return TRUE if this SA matches all parameters, FALSE otherwise
|
* @return TRUE if this SA matches all parameters, FALSE otherwise
|
||||||
@@ -132,6 +161,8 @@ struct ipsec_sa_t {
|
|||||||
/**
|
/**
|
||||||
* Check if this SA matches all given parameters
|
* Check if this SA matches all given parameters
|
||||||
*
|
*
|
||||||
|
* Only matches if the SA has not yet expired.
|
||||||
|
*
|
||||||
* @param reqid reqid
|
* @param reqid reqid
|
||||||
* @param inbound TRUE for inbound SA, FALSE for outbound
|
* @param inbound TRUE for inbound SA, FALSE for outbound
|
||||||
* @return TRUE if this SA matches all parameters, FALSE otherwise
|
* @return TRUE if this SA matches all parameters, FALSE otherwise
|
||||||
|
|||||||
@@ -299,12 +299,10 @@ static job_requeue_t sa_expired(ipsec_sa_expired_t *expired)
|
|||||||
if (this->sas->find_first(this->sas, (void*)match_entry_by_ptr,
|
if (this->sas->find_first(this->sas, (void*)match_entry_by_ptr,
|
||||||
NULL, expired->entry) == SUCCESS)
|
NULL, expired->entry) == SUCCESS)
|
||||||
{
|
{
|
||||||
u_int32_t hard_offset = expired->hard_offset;
|
u_int32_t hard_offset;
|
||||||
ipsec_sa_t *sa = expired->entry->sa;
|
|
||||||
|
|
||||||
ipsec->events->expire(ipsec->events, sa->get_reqid(sa),
|
hard_offset = expired->hard_offset;
|
||||||
sa->get_protocol(sa), sa->get_spi(sa),
|
expired->entry->sa->expire(expired->entry->sa, hard_offset == 0);
|
||||||
hard_offset == 0);
|
|
||||||
if (hard_offset)
|
if (hard_offset)
|
||||||
{ /* soft limit reached, schedule hard expire */
|
{ /* soft limit reached, schedule hard expire */
|
||||||
expired->hard_offset = 0;
|
expired->hard_offset = 0;
|
||||||
@@ -530,6 +528,28 @@ METHOD(ipsec_sa_mgr_t, update_sa, status_t,
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(ipsec_sa_mgr_t, query_sa, status_t,
|
||||||
|
private_ipsec_sa_mgr_t *this, host_t *src, host_t *dst,
|
||||||
|
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
||||||
|
u_int64_t *bytes, u_int64_t *packets, time_t *time)
|
||||||
|
{
|
||||||
|
ipsec_sa_entry_t *entry = NULL;
|
||||||
|
|
||||||
|
this->mutex->lock(this->mutex);
|
||||||
|
if (this->sas->find_first(this->sas, (void*)match_entry_by_spi_src_dst,
|
||||||
|
(void**)&entry, &spi, src, dst) == SUCCESS &&
|
||||||
|
wait_for_entry(this, entry))
|
||||||
|
{
|
||||||
|
entry->sa->get_usestats(entry->sa, bytes, packets, time);
|
||||||
|
/* checkin the entry */
|
||||||
|
entry->locked = FALSE;
|
||||||
|
entry->condvar->signal(entry->condvar);
|
||||||
|
}
|
||||||
|
this->mutex->unlock(this->mutex);
|
||||||
|
|
||||||
|
return entry ? SUCCESS : NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(ipsec_sa_mgr_t, del_sa, status_t,
|
METHOD(ipsec_sa_mgr_t, del_sa, status_t,
|
||||||
private_ipsec_sa_mgr_t *this, host_t *src, host_t *dst, u_int32_t spi,
|
private_ipsec_sa_mgr_t *this, host_t *src, host_t *dst, u_int32_t spi,
|
||||||
u_int8_t protocol, u_int16_t cpi, mark_t mark)
|
u_int8_t protocol, u_int16_t cpi, mark_t mark)
|
||||||
@@ -653,6 +673,7 @@ ipsec_sa_mgr_t *ipsec_sa_mgr_create()
|
|||||||
.get_spi = _get_spi,
|
.get_spi = _get_spi,
|
||||||
.add_sa = _add_sa,
|
.add_sa = _add_sa,
|
||||||
.update_sa = _update_sa,
|
.update_sa = _update_sa,
|
||||||
|
.query_sa = _query_sa,
|
||||||
.del_sa = _del_sa,
|
.del_sa = _del_sa,
|
||||||
.checkout_by_spi = _checkout_by_spi,
|
.checkout_by_spi = _checkout_by_spi,
|
||||||
.checkout_by_reqid = _checkout_by_reqid,
|
.checkout_by_reqid = _checkout_by_reqid,
|
||||||
|
|||||||
@@ -108,6 +108,23 @@ struct ipsec_sa_mgr_t {
|
|||||||
host_t *new_src, host_t *new_dst,
|
host_t *new_src, host_t *new_dst,
|
||||||
bool encap, bool new_encap, mark_t mark);
|
bool encap, bool new_encap, mark_t mark);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query the number of bytes processed by an SA from the SAD.
|
||||||
|
*
|
||||||
|
* @param src source address for this SA
|
||||||
|
* @param dst destination address for this SA
|
||||||
|
* @param spi SPI allocated by us or remote peer
|
||||||
|
* @param protocol protocol for this SA (ESP/AH)
|
||||||
|
* @param mark optional mark for this SA
|
||||||
|
* @param[out] bytes the number of bytes processed by SA
|
||||||
|
* @param[out] packets number of packets processed by SA
|
||||||
|
* @param[out] time last (monotonic) time of SA use
|
||||||
|
* @return SUCCESS if operation completed
|
||||||
|
*/
|
||||||
|
status_t (*query_sa)(ipsec_sa_mgr_t *this, host_t *src, host_t *dst,
|
||||||
|
u_int32_t spi, u_int8_t protocol, mark_t mark,
|
||||||
|
u_int64_t *bytes, u_int64_t *packets, time_t *time);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a previously added SA
|
* Delete a previously added SA
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user