/*
- * 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
* Flush auth configs once established?
*/
bool flush_auth_cfg;
+
+ /**
+ * Maximum length of a single fragment, 0 for address-specific defaults
+ */
+ size_t fragment_size;
};
/**
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)
{
.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,
"%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)
/*
- * 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
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
* - 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.
* - 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.
*/
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;
/**
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;
}
/**
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)
{
queue_task(this, (task_t*)aggressive_mode_create(this->ike_sa, TRUE));
}
- this->frag.exchange = AGGRESSIVE;
}
else
{
.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),