]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
ike: Move fragmentation to ike_sa_t
authorTobias Brunner <tobias@strongswan.org>
Thu, 12 Jun 2014 14:28:27 +0000 (16:28 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 10 Oct 2014 07:30:26 +0000 (09:30 +0200)
The message() hook on bus_t is now called exactly once before (plain) and
once after fragmenting (!plain), not twice for the complete message and again
for each individual fragment, as was the case in earlier iterations.

For inbound messages the hook is called once for each fragment (!plain)
and twice for the reassembled message.

src/libcharon/sa/ike_sa.c
src/libcharon/sa/ike_sa.h
src/libcharon/sa/ikev1/task_manager_v1.c

index 516b2435bd565c6f628d7c75f8d2180a948b1a30..6f4ffb845915c9336586e1962c3b0fed79a2b0eb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2013 Tobias Brunner
+ * Copyright (C) 2006-2014 Tobias Brunner
  * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
@@ -251,6 +251,11 @@ struct private_ike_sa_t {
         * Flush auth configs once established?
         */
        bool flush_auth_cfg;
+
+       /**
+        * Maximum length of a single fragment, 0 for address-specific defaults
+        */
+       size_t fragment_size;
 };
 
 /**
@@ -994,6 +999,61 @@ METHOD(ike_sa_t, generate_message, status_t,
        return status;
 }
 
+static bool filter_fragments(private_ike_sa_t *this, packet_t **fragment,
+                                                        packet_t **packet)
+{
+       *packet = (*fragment)->clone(*fragment);
+       set_dscp(this, *packet);
+       return TRUE;
+}
+
+METHOD(ike_sa_t, generate_message_fragmented, status_t,
+       private_ike_sa_t *this, message_t *message, enumerator_t **packets)
+{
+       enumerator_t *fragments;
+       packet_t *packet;
+       status_t status;
+       bool use_frags = FALSE;
+
+       if (this->ike_cfg && this->version == IKEV1)
+       {
+               switch (this->ike_cfg->fragmentation(this->ike_cfg))
+               {
+                       case FRAGMENTATION_FORCE:
+                               use_frags = TRUE;
+                               break;
+                       case FRAGMENTATION_YES:
+                               use_frags = supports_extension(this, EXT_IKE_FRAGMENTATION);
+                               break;
+                       default:
+                               break;
+               }
+       }
+       if (!use_frags)
+       {
+               status = generate_message(this, message, &packet);
+               if (status != SUCCESS)
+               {
+                       return status;
+               }
+               *packets = enumerator_create_single(packet, NULL);
+               return SUCCESS;
+       }
+
+       this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
+       message->set_ike_sa_id(message, this->ike_sa_id);
+       charon->bus->message(charon->bus, message, FALSE, TRUE);
+       status = message->fragment(message, this->keymat, this->fragment_size,
+                                                          &fragments);
+       if (status == SUCCESS)
+       {
+               charon->bus->message(charon->bus, message, FALSE, FALSE);
+               *packets = enumerator_create_filter(fragments, (void*)filter_fragments,
+                                                                                       this, NULL);
+       }
+       return status;
+}
+
 METHOD(ike_sa_t, set_kmaddress, void,
        private_ike_sa_t *this, host_t *local, host_t *remote)
 {
@@ -2362,6 +2422,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
                        .inherit_pre = _inherit_pre,
                        .inherit_post = _inherit_post,
                        .generate_message = _generate_message,
+                       .generate_message_fragmented = _generate_message_fragmented,
                        .reset = _reset,
                        .get_unique_id = _get_unique_id,
                        .add_virtual_ip = _add_virtual_ip,
@@ -2407,6 +2468,8 @@ 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", 0, lib->ns),
        );
 
        if (version == IKEV2)
index 15fb474842f44b7b60c694ba16c9348d39a4562e..7926301a73f8d82222e2f373f9fe777f19775b0e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2012 Tobias Brunner
+ * Copyright (C) 2006-2014 Tobias Brunner
  * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
@@ -756,7 +756,7 @@ struct ike_sa_t {
        status_t (*roam)(ike_sa_t *this, bool address);
 
        /**
-        * Processes a incoming IKEv2-Message.
+        * Processes an incoming IKE message.
         *
         * Message processing may fail. If a critical failure occurs,
         * process_message() return DESTROY_ME. Then the caller must
@@ -768,10 +768,10 @@ struct ike_sa_t {
         *                                              - FAILED
         *                                              - DESTROY_ME if this IKE_SA MUST be deleted
         */
-       status_t (*process_message) (ike_sa_t *this, message_t *message);
+       status_t (*process_message)(ike_sa_t *this, message_t *message);
 
        /**
-        * Generate a IKE message to send it to the peer.
+        * Generate an IKE message to send it to the peer.
         *
         * This method generates all payloads in the message and encrypts/signs
         * the packet.
@@ -783,8 +783,26 @@ struct ike_sa_t {
         *                                              - FAILED
         *                                              - DESTROY_ME if this IKE_SA MUST be deleted
         */
-       status_t (*generate_message) (ike_sa_t *this, message_t *message,
-                                                                 packet_t **packet);
+       status_t (*generate_message)(ike_sa_t *this, message_t *message,
+                                                                packet_t **packet);
+
+       /**
+        * Generate an IKE message to send it to the peer. If enabled and supported
+        * it will be fragmented.
+        *
+        * This method generates all payloads in the message and encrypts/signs
+        * the packet/fragments.
+        *
+        * @param message               message to generate
+        * @param packets               enumerator of generated packet_t* (are not destroyed
+        *                                              with the enumerator)
+        * @return
+        *                                              - SUCCESS
+        *                                              - FAILED
+        *                                              - DESTROY_ME if this IKE_SA MUST be deleted
+        */
+       status_t (*generate_message_fragmented)(ike_sa_t *this, message_t *message,
+                                                                                       enumerator_t **packets);
 
        /**
         * Retransmits a request.
index 4e3511858e26da7cd8431937196fa9de9942e9e1..498d6c47abe35413767918a3c831d20c5500877c 100644 (file)
@@ -208,18 +208,6 @@ struct private_task_manager_t {
                 */
                size_t max_packet;
 
-               /**
-                * Maximum length of a single fragment (when sending)
-                */
-               size_t size;
-
-               /**
-                * The exchange type we use for fragments. Always the initial type even
-                * for fragmented quick mode or transaction messages (i.e. either
-                * ID_PROT or AGGRESSIVE)
-                */
-               exchange_type_t exchange;
-
        } frag;
 
        /**
@@ -398,52 +386,20 @@ static void send_packets(private_task_manager_t *this, array_t *packets)
 static bool generate_message(private_task_manager_t *this, message_t *message,
                                                         array_t **packets)
 {
-       bool use_frags = FALSE, result = TRUE;
-       ike_cfg_t *ike_cfg;
        enumerator_t *fragments;
-       packet_t *packet;
-       status_t status;
+       packet_t *fragment;
 
-       ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
-       if (ike_cfg)
-       {
-               switch (ike_cfg->fragmentation(ike_cfg))
-               {
-                       case FRAGMENTATION_FORCE:
-                               use_frags = TRUE;
-                               break;
-                       case FRAGMENTATION_YES:
-                               use_frags = this->ike_sa->supports_extension(this->ike_sa,
-                                                                                                       EXT_IKE_FRAGMENTATION);
-                               break;
-                       default:
-                               break;
-               }
-       }
-
-       if (!use_frags)
-       {
-               if (this->ike_sa->generate_message(this->ike_sa, message,
-                                                                                  &packet) != SUCCESS)
-               {
-                       return FALSE;
-               }
-               array_insert_create(packets, ARRAY_TAIL, packet);
-               return TRUE;
-       }
-       message->set_ike_sa_id(message, this->ike_sa->get_id(this->ike_sa));
-       status = message->fragment(message, this->ike_sa->get_keymat(this->ike_sa),
-                                                          this->frag.size, &fragments);
-       if (status != SUCCESS)
+       if (this->ike_sa->generate_message_fragmented(this->ike_sa, message,
+                                                                                                 &fragments) != SUCCESS)
        {
                return FALSE;
        }
-       while (fragments->enumerate(fragments, &packet))
+       while (fragments->enumerate(fragments, &fragment))
        {
-               array_insert_create(packets, ARRAY_TAIL, packet->clone(packet));
+               array_insert_create(packets, ARRAY_TAIL, fragment);
        }
        fragments->destroy(fragments);
-       return result;
+       return TRUE;
 }
 
 /**
@@ -1046,7 +1002,6 @@ static status_t process_request(private_task_manager_t *this,
                                this->passive_tasks->insert_last(this->passive_tasks, task);
                                task = (task_t *)isakmp_natd_create(this->ike_sa, FALSE);
                                this->passive_tasks->insert_last(this->passive_tasks, task);
-                               this->frag.exchange = AGGRESSIVE;
                                break;
                        case QUICK_MODE:
                                if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
@@ -1623,7 +1578,6 @@ METHOD(task_manager_t, queue_ike, void,
                {
                        queue_task(this, (task_t*)aggressive_mode_create(this->ike_sa, TRUE));
                }
-               this->frag.exchange = AGGRESSIVE;
        }
        else
        {
@@ -2061,11 +2015,8 @@ task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
                        .seqnr = RESPONDING_SEQ,
                },
                .frag = {
-                       .exchange = ID_PROT,
                        .max_packet = lib->settings->get_int(lib->settings,
                                                "%s.max_packet", MAX_PACKET, lib->ns),
-                       .size = lib->settings->get_int(lib->settings,
-                                               "%s.fragment_size", 0, lib->ns),
                },
                .ike_sa = ike_sa,
                .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),