2 * Copyright (C) 2005-2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 #include "transform_substructure.h"
22 #include <encoding/payloads/transform_attribute.h>
23 #include <encoding/payloads/encodings.h>
25 #include <utils/linked_list.h>
28 typedef struct private_transform_substructure_t private_transform_substructure_t
;
31 * Private data of an transform_substructure_t object.
33 struct private_transform_substructure_t
{
36 * Public transform_substructure_t interface.
38 transform_substructure_t
public;
43 u_int8_t next_payload
;
51 * Length of this payload.
53 u_int16_t transform_length
;
56 * Type or number, Type of the transform in IKEv2, number in IKEv2.
58 u_int8_t transform_ton
;
61 * Transform ID, as encoded in IKEv1.
63 u_int8_t transform_id_v1
;
66 * Transform ID, as encoded in IKEv2.
68 u_int16_t transform_id_v2
;
71 * Transforms Attributes are stored in a linked_list_t.
73 linked_list_t
*attributes
;
76 * Payload type, TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1
82 * Encoding rules for TRANSFORM_SUBSTRUCTURE
84 static encoding_rule_t encodings_v2
[] = {
85 /* 1 Byte next payload type, stored in the field next_payload */
86 { U_INT_8
, offsetof(private_transform_substructure_t
, next_payload
) },
88 { RESERVED_BYTE
, offsetof(private_transform_substructure_t
, reserved
[0]) },
89 /* Length of the whole transform substructure*/
90 { PAYLOAD_LENGTH
, offsetof(private_transform_substructure_t
, transform_length
)},
92 { U_INT_8
, offsetof(private_transform_substructure_t
, transform_ton
) },
93 /* transform identifier, as used by IKEv1 */
94 { RESERVED_BYTE
, offsetof(private_transform_substructure_t
, reserved
[1]) },
95 /* transform identifier, as used by IKEv2 */
96 { U_INT_16
, offsetof(private_transform_substructure_t
, transform_id_v2
) },
97 /* Attributes in a transform attribute list */
98 { TRANSFORM_ATTRIBUTES
, offsetof(private_transform_substructure_t
, attributes
) }
102 * Encoding rules for TRANSFORM_SUBSTRUCTURE_V1
104 static encoding_rule_t encodings_v1
[] = {
105 /* 1 Byte next payload type, stored in the field next_payload */
106 { U_INT_8
, offsetof(private_transform_substructure_t
, next_payload
) },
107 /* 1 Reserved Byte */
108 { RESERVED_BYTE
, offsetof(private_transform_substructure_t
, reserved
[0]) },
109 /* Length of the whole transform substructure*/
110 { PAYLOAD_LENGTH
, offsetof(private_transform_substructure_t
, transform_length
)},
111 /* transform number */
112 { U_INT_8
, offsetof(private_transform_substructure_t
, transform_ton
)},
113 /* transform identifier, as used by IKEv1 */
114 { U_INT_8
, offsetof(private_transform_substructure_t
, transform_id_v1
) },
115 /* transform identifier, as used by IKEv2 */
116 { RESERVED_BYTE
, offsetof(private_transform_substructure_t
, reserved
[1]) },
117 { RESERVED_BYTE
, offsetof(private_transform_substructure_t
, reserved
[2]) },
118 /* Attributes in a transform attribute list */
119 { TRANSFORM_ATTRIBUTES_V1
, offsetof(private_transform_substructure_t
, attributes
) }
124 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
125 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
126 ! 0 (last) or 3 ! RESERVED ! Transform Length !
127 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
128 ! Tfrm Typ or # ! Tfrm ID IKEv1 ! Transform ID IKEv2 !
129 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
131 ~ Transform Attributes ~
133 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
136 METHOD(payload_t
, verify
, status_t
,
137 private_transform_substructure_t
*this)
139 status_t status
= SUCCESS
;
140 enumerator_t
*enumerator
;
141 payload_t
*attribute
;
143 if (this->next_payload
!= NO_PAYLOAD
&& this->next_payload
!= 3)
145 DBG1(DBG_ENC
, "inconsistent next payload");
149 enumerator
= this->attributes
->create_enumerator(this->attributes
);
150 while (enumerator
->enumerate(enumerator
, &attribute
))
152 status
= attribute
->verify(attribute
);
153 if (status
!= SUCCESS
)
155 DBG1(DBG_ENC
, "TRANSFORM_ATTRIBUTE verification failed");
159 enumerator
->destroy(enumerator
);
161 /* proposal number is checked in SA payload */
165 METHOD(payload_t
, get_encoding_rules
, void,
166 private_transform_substructure_t
*this, encoding_rule_t
**rules
,
169 if (this->type
== TRANSFORM_ATTRIBUTE
)
171 *rules
= encodings_v2
;
172 *rule_count
= countof(encodings_v2
);
176 *rules
= encodings_v1
;
177 *rule_count
= countof(encodings_v1
);
181 METHOD(payload_t
, get_type
, payload_type_t
,
182 private_transform_substructure_t
*this)
187 METHOD(payload_t
, get_next_type
, payload_type_t
,
188 private_transform_substructure_t
*this)
190 return this->next_payload
;
194 * recompute the length of the payload.
196 static void compute_length(private_transform_substructure_t
*this)
198 enumerator_t
*enumerator
;
199 payload_t
*attribute
;
201 this->transform_length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
;
202 enumerator
= this->attributes
->create_enumerator(this->attributes
);
203 while (enumerator
->enumerate(enumerator
, &attribute
))
205 this->transform_length
+= attribute
->get_length(attribute
);
207 enumerator
->destroy(enumerator
);
210 METHOD(payload_t
, get_length
, size_t,
211 private_transform_substructure_t
*this)
213 return this->transform_length
;
216 METHOD(transform_substructure_t
, set_is_last_transform
, void,
217 private_transform_substructure_t
*this, bool is_last
)
219 this->next_payload
= is_last ?
0: TRANSFORM_TYPE_VALUE
;
222 METHOD(payload_t
, set_next_type
, void,
223 private_transform_substructure_t
*this,payload_type_t type
)
227 METHOD(transform_substructure_t
, get_transform_type_or_number
, u_int8_t
,
228 private_transform_substructure_t
*this)
230 return this->transform_ton
;
233 METHOD(transform_substructure_t
, get_transform_id
, u_int16_t
,
234 private_transform_substructure_t
*this)
236 if (this->type
== TRANSFORM_SUBSTRUCTURE
)
238 return this->transform_id_v2
;
240 return this->transform_id_v1
;
243 METHOD(transform_substructure_t
, create_attribute_enumerator
, enumerator_t
*,
244 private_transform_substructure_t
*this)
246 return this->attributes
->create_enumerator(this->attributes
);
249 METHOD2(payload_t
, transform_substructure_t
, destroy
, void,
250 private_transform_substructure_t
*this)
252 this->attributes
->destroy_offset(this->attributes
,
253 offsetof(payload_t
, destroy
));
258 * Described in header.
260 transform_substructure_t
*transform_substructure_create(payload_type_t type
)
262 private_transform_substructure_t
*this;
266 .payload_interface
= {
268 .get_encoding_rules
= _get_encoding_rules
,
269 .get_length
= _get_length
,
270 .get_next_type
= _get_next_type
,
271 .set_next_type
= _set_next_type
,
272 .get_type
= _get_type
,
275 .set_is_last_transform
= _set_is_last_transform
,
276 .get_transform_type_or_number
= _get_transform_type_or_number
,
277 .get_transform_id
= _get_transform_id
,
278 .create_attribute_enumerator
= _create_attribute_enumerator
,
281 .next_payload
= NO_PAYLOAD
,
282 .transform_length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
,
283 .attributes
= linked_list_create(),
286 return &this->public;
290 * Described in header
292 transform_substructure_t
*transform_substructure_create_type(payload_type_t type
,
293 u_int8_t type_or_number
, u_int16_t id
, u_int16_t key_length
)
295 private_transform_substructure_t
*this;
297 this = (private_transform_substructure_t
*)transform_substructure_create(type
);
299 this->transform_ton
= type_or_number
;
300 if (type
== TRANSFORM_SUBSTRUCTURE
)
302 this->transform_id_v2
= id
;
306 this->transform_id_v1
= id
;
310 this->attributes
->insert_last(this->attributes
,
311 (void*)transform_attribute_create_key_length(key_length
));
312 compute_length(this);
314 return &this->public;