diff --git a/conf/options/charon.opt b/conf/options/charon.opt index 369a11df58..dc9eb067c0 100644 --- a/conf/options/charon.opt +++ b/conf/options/charon.opt @@ -154,8 +154,16 @@ charon.fragment_size = 1280 Maximum size (complete IP datagram size in bytes) of a sent IKE fragment when using proprietary IKEv1 or standardized IKEv2 fragmentation, defaults to 1280 (use 0 for address family specific default values, which uses a - lower value for IPv4). If specified this limit is used for both IPv4 and - IPv6. + lower value for IPv4). Unless overridden, this limit is used for both IPv4 + and IPv6 if specified. + +charon.fragment_size_v4 = charon.fragment_size + Maximum size (complete IPv4 datagram size in bytes) of a sent IKE fragment + when using proprietary IKEv1 or standardized IKEv2 fragmentation. + +charon.fragment_size_v6 = charon.fragment_size + Maximum size (complete IPv6 datagram size in bytes) of a sent IKE fragment + when using proprietary IKEv1 or standardized IKEv2 fragmentation. charon.group Name of the group the daemon changes to after startup. diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 1686baeae1..ba0c174334 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1999,10 +1999,6 @@ METHOD(message_t, fragment, status_t, src = this->packet->get_source(this->packet); dst = this->packet->get_destination(this->packet); - if (!frag_len) - { - frag_len = (src->get_family(src) == AF_INET) ? 576 : 1280; - } /* frag_len is the complete IP datagram length, account for overhead (we * assume no IP options/extension headers are used) */ REDUCE_FRAG_LEN(frag_len, (src->get_family(src) == AF_INET) ? 20 : 40); diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index c9b2a6c082..83865635d9 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -327,6 +327,30 @@ struct attribute_entry_t { chunk_t data; }; +/** + * Determine the fragment size based on the address family of the remote host. + */ +static void determine_fragment_size(private_ike_sa_t *this) +{ + int family; + + family = this->other_host->get_family(this->other_host); + + this->fragment_size = lib->settings->get_int(lib->settings, + "%s.fragment_size_v%hhu", 0, lib->ns, (family == AF_INET ? 4 : 6)); + + if (!this->fragment_size) + { + this->fragment_size = lib->settings->get_int(lib->settings, + "%s.fragment_size", 1280, lib->ns); + } + + if (!this->fragment_size) + { + this->fragment_size = (family == AF_INET) ? 576 : 1280; + } +} + /** * get the time of the latest traffic processed by the kernel */ @@ -415,6 +439,7 @@ METHOD(ike_sa_t, set_other_host, void, { DESTROY_IF(this->other_host); this->other_host = other; + determine_fragment_size(this); } METHOD(ike_sa_t, get_redirected_from, host_t*, @@ -2908,14 +2933,10 @@ METHOD(ike_sa_t, inherit_post, void, host_t *vip; /* apply hosts and ids */ - this->my_host->destroy(this->my_host); - this->other_host->destroy(this->other_host); - this->my_id->destroy(this->my_id); - this->other_id->destroy(this->other_id); - this->my_host = other->my_host->clone(other->my_host); - this->other_host = other->other_host->clone(other->other_host); - this->my_id = other->my_id->clone(other->my_id); - this->other_id = other->other_id->clone(other->other_id); + set_my_host(this, other->my_host->clone(other->my_host)); + set_other_host(this, other->other_host->clone(other->other_host)); + set_my_id(this, other->my_id->clone(other->my_id)); + set_other_id(this, other->other_id->clone(other->other_id)); this->if_id_in = other->if_id_in; this->if_id_out = other->if_id_out; @@ -3228,8 +3249,6 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator, "%s.retry_initiate_interval", 0, lib->ns), .flush_auth_cfg = lib->settings->get_bool(lib->settings, "%s.flush_auth_cfg", FALSE, lib->ns), - .fragment_size = lib->settings->get_int(lib->settings, - "%s.fragment_size", 1280, lib->ns), .follow_redirects = lib->settings->get_bool(lib->settings, "%s.follow_redirects", TRUE, lib->ns), );