aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2012-05-24 13:31:53 +0200
committerTobias Brunner <tobias@strongswan.org>2012-05-24 15:32:28 +0200
commit647cd741e8b72d7ba4ef8e2cfe5f0b704df0d1ad (patch)
tree4313bcdd0c89211bbf0a4b9f99d3d1341aaeb466 /src
parent7a75cae8566dbf1a42f12c9e7521aa59866f240d (diff)
downloadstrongswan-647cd741e8b72d7ba4ef8e2cfe5f0b704df0d1ad.tar.bz2
strongswan-647cd741e8b72d7ba4ef8e2cfe5f0b704df0d1ad.tar.xz
Added support for IKEv1 IPComp proposals in SA payload.
Diffstat (limited to 'src')
-rw-r--r--src/libcharon/encoding/payloads/sa_payload.c81
-rw-r--r--src/libcharon/encoding/payloads/sa_payload.h19
-rw-r--r--src/libcharon/sa/ikev1/tasks/aggressive_mode.c4
-rw-r--r--src/libcharon/sa/ikev1/tasks/main_mode.c4
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.c4
5 files changed, 98 insertions, 14 deletions
diff --git a/src/libcharon/encoding/payloads/sa_payload.c b/src/libcharon/encoding/payloads/sa_payload.c
index 18b1dc7b6..4fb1bc63a 100644
--- a/src/libcharon/encoding/payloads/sa_payload.c
+++ b/src/libcharon/encoding/payloads/sa_payload.c
@@ -336,6 +336,60 @@ METHOD(sa_payload_t, get_proposals, linked_list_t*,
return list;
}
+METHOD(sa_payload_t, get_ipcomp_proposals, linked_list_t*,
+ private_sa_payload_t *this, u_int16_t *cpi)
+{
+ int current_proposal = -1, unsupported_proposal = -1;
+ enumerator_t *enumerator;
+ proposal_substructure_t *substruct, *esp = NULL, *ipcomp = NULL;
+ linked_list_t *list;
+
+ /* we currently only support the combination ESP+IPComp, find the first */
+ enumerator = this->proposals->create_enumerator(this->proposals);
+ while (enumerator->enumerate(enumerator, &substruct))
+ {
+ u_int8_t proposal_number = substruct->get_proposal_number(substruct);
+ u_int8_t protocol_id = substruct->get_protocol_id(substruct);
+
+ if (proposal_number == unsupported_proposal)
+ {
+ continue;
+ }
+ if (protocol_id != PROTO_ESP && protocol_id != PROTO_IPCOMP)
+ { /* unsupported combination */
+ esp = ipcomp = NULL;
+ unsupported_proposal = current_proposal;
+ continue;
+ }
+ if (proposal_number != current_proposal)
+ { /* start of a new proposal */
+ if (esp && ipcomp)
+ { /* previous proposal is valid */
+ break;
+ }
+ esp = ipcomp = NULL;
+ current_proposal = proposal_number;
+ }
+ switch (protocol_id)
+ {
+ case PROTO_ESP:
+ esp = substruct;
+ break;
+ case PROTO_IPCOMP:
+ ipcomp = substruct;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ list = linked_list_create();
+ if (esp && ipcomp && ipcomp->get_cpi(ipcomp, cpi))
+ {
+ esp->get_proposals(esp, list);
+ }
+ return list;
+}
+
METHOD(sa_payload_t, create_substructure_enumerator, enumerator_t*,
private_sa_payload_t *this)
{
@@ -438,6 +492,7 @@ sa_payload_t *sa_payload_create(payload_type_t type)
.destroy = _destroy,
},
.get_proposals = _get_proposals,
+ .get_ipcomp_proposals = _get_ipcomp_proposals,
.create_substructure_enumerator = _create_substructure_enumerator,
.get_lifetime = _get_lifetime,
.get_lifebytes = _get_lifebytes,
@@ -497,7 +552,8 @@ sa_payload_t *sa_payload_create_from_proposal_v2(proposal_t *proposal)
*/
sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals,
u_int32_t lifetime, u_int64_t lifebytes,
- auth_method_t auth, ipsec_mode_t mode, bool udp)
+ auth_method_t auth, ipsec_mode_t mode, bool udp,
+ u_int16_t cpi)
{
proposal_substructure_t *substruct;
private_sa_payload_t *this;
@@ -505,11 +561,18 @@ sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals,
this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION_V1);
/* IKEv1 encodes multiple proposals in a single substructure
- * TODO-IKEv1: Encode ESP+AH proposals in two different substructs */
+ * TODO-IKEv1: Encode ESP+AH proposals in two substructs with same num */
substruct = proposal_substructure_create_from_proposals_v1(proposals,
lifetime, lifebytes, auth, mode, udp);
- substruct->set_is_last_proposal(substruct, TRUE);
this->proposals->insert_last(this->proposals, substruct);
+ substruct->set_is_last_proposal(substruct, FALSE);
+ if (cpi)
+ {
+ substruct = proposal_substructure_create_for_ipcomp_v1(lifetime,
+ lifebytes, cpi, substruct->get_proposal_number(substruct));
+ this->proposals->insert_last(this->proposals, substruct);
+ }
+ substruct->set_is_last_proposal(substruct, TRUE);
compute_length(this);
return &this->public;
@@ -520,7 +583,8 @@ sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals,
*/
sa_payload_t *sa_payload_create_from_proposal_v1(proposal_t *proposal,
u_int32_t lifetime, u_int64_t lifebytes,
- auth_method_t auth, ipsec_mode_t mode, bool udp)
+ auth_method_t auth, ipsec_mode_t mode, bool udp,
+ u_int16_t cpi)
{
proposal_substructure_t *substruct;
private_sa_payload_t *this;
@@ -529,8 +593,15 @@ sa_payload_t *sa_payload_create_from_proposal_v1(proposal_t *proposal,
substruct = proposal_substructure_create_from_proposal_v1(proposal,
lifetime, lifebytes, auth, mode, udp);
- substruct->set_is_last_proposal(substruct, TRUE);
this->proposals->insert_last(this->proposals, substruct);
+ substruct->set_is_last_proposal(substruct, FALSE);
+ if (cpi)
+ {
+ substruct = proposal_substructure_create_for_ipcomp_v1(lifetime,
+ lifebytes, cpi, substruct->get_proposal_number(substruct));
+ this->proposals->insert_last(this->proposals, substruct);
+ }
+ substruct->set_is_last_proposal(substruct, TRUE);
compute_length(this);
return &this->public;
diff --git a/src/libcharon/encoding/payloads/sa_payload.h b/src/libcharon/encoding/payloads/sa_payload.h
index 6dfbd5180..9a88cccd5 100644
--- a/src/libcharon/encoding/payloads/sa_payload.h
+++ b/src/libcharon/encoding/payloads/sa_payload.h
@@ -46,11 +46,20 @@ struct sa_payload_t {
/**
* Gets the proposals in this payload as a list.
*
- * @return a list containing proposal_t s
+ * @return a list containing proposal_ts
*/
linked_list_t *(*get_proposals) (sa_payload_t *this);
/**
+ * Gets the proposals from the first proposal in this payload with IPComp
+ * enabled (IKEv1 only).
+ *
+ * @param cpi the CPI of the first IPComp (sub)proposal
+ * @return a list containing proposal_ts
+ */
+ linked_list_t *(*get_ipcomp_proposals) (sa_payload_t *this, u_int16_t *cpi);
+
+ /**
* Get the (shortest) lifetime of a proposal (IKEv1 only).
*
* @return lifetime, in seconds
@@ -125,11 +134,13 @@ sa_payload_t *sa_payload_create_from_proposal_v2(proposal_t *proposal);
* @param auth authentication method to use, or AUTH_NONE
* @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL
* @param udp TRUE to use UDP encapsulation
+ * @param cpi CPI in case IPComp should be used
* @return sa_payload_t object
*/
sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals,
u_int32_t lifetime, u_int64_t lifebytes,
- auth_method_t auth, ipsec_mode_t mode, bool udp);
+ auth_method_t auth, ipsec_mode_t mode, bool udp,
+ u_int16_t cpi);
/**
* Creates an IKEv1 sa_payload_t object from a single proposal.
@@ -140,10 +151,12 @@ sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals,
* @param auth authentication method to use, or AUTH_NONE
* @param mode IPsec encapsulation mode, TRANSPORT or TUNNEL
* @param udp TRUE to use UDP encapsulation
+ * @param cpi CPI in case IPComp should be used
* @return sa_payload_t object
*/
sa_payload_t *sa_payload_create_from_proposal_v1(proposal_t *proposal,
u_int32_t lifetime, u_int64_t lifebytes,
- auth_method_t auth, ipsec_mode_t mode, bool udp);
+ auth_method_t auth, ipsec_mode_t mode, bool udp,
+ u_int16_t cpi);
#endif /** SA_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
index 664fce918..db27ae12f 100644
--- a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
@@ -235,7 +235,7 @@ METHOD(task_t, build_i, status_t,
this->lifetime += this->peer_cfg->get_over_time(this->peer_cfg);
proposals = this->ike_cfg->get_proposals(this->ike_cfg);
sa_payload = sa_payload_create_from_proposals_v1(proposals,
- this->lifetime, 0, this->method, MODE_NONE, FALSE);
+ this->lifetime, 0, this->method, MODE_NONE, FALSE, 0);
proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
message->add_payload(message, &sa_payload->payload_interface);
@@ -480,7 +480,7 @@ METHOD(task_t, build_r, status_t,
identification_t *id;
sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
- this->lifetime, 0, this->method, MODE_NONE, FALSE);
+ this->lifetime, 0, this->method, MODE_NONE, FALSE, 0);
message->add_payload(message, &sa_payload->payload_interface);
if (!this->ph1->add_nonce_ke(this->ph1, message))
diff --git a/src/libcharon/sa/ikev1/tasks/main_mode.c b/src/libcharon/sa/ikev1/tasks/main_mode.c
index ce047df16..23c90ba6b 100644
--- a/src/libcharon/sa/ikev1/tasks/main_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/main_mode.c
@@ -241,7 +241,7 @@ METHOD(task_t, build_i, status_t,
this->lifetime += this->peer_cfg->get_over_time(this->peer_cfg);
proposals = this->ike_cfg->get_proposals(this->ike_cfg);
sa_payload = sa_payload_create_from_proposals_v1(proposals,
- this->lifetime, 0, this->method, MODE_NONE, FALSE);
+ this->lifetime, 0, this->method, MODE_NONE, FALSE, 0);
proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
message->add_payload(message, &sa_payload->payload_interface);
@@ -455,7 +455,7 @@ METHOD(task_t, build_r, status_t,
sa_payload_t *sa_payload;
sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
- this->lifetime, 0, this->method, MODE_NONE, FALSE);
+ this->lifetime, 0, this->method, MODE_NONE, FALSE, 0);
message->add_payload(message, &sa_payload->payload_interface);
return NEED_MORE;
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index cc3ac6720..6fa0752b0 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -654,7 +654,7 @@ METHOD(task_t, build_i, status_t,
get_lifetimes(this);
sa_payload = sa_payload_create_from_proposals_v1(list,
this->lifetime, this->lifebytes, AUTH_NONE,
- this->mode, this->udp);
+ this->mode, this->udp, 0);
list->destroy_offset(list, offsetof(proposal_t, destroy));
message->add_payload(message, &sa_payload->payload_interface);
@@ -933,7 +933,7 @@ METHOD(task_t, build_r, status_t,
sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
this->lifetime, this->lifebytes, AUTH_NONE,
- this->mode, this->udp);
+ this->mode, this->udp, 0);
message->add_payload(message, &sa_payload->payload_interface);
if (!add_nonce(this, &this->nonce_r, message))