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 { PAYLOAD_LIST
+ TRANSFORM_ATTRIBUTE
,
99 offsetof(private_transform_substructure_t
, attributes
) }
103 * Encoding rules for TRANSFORM_SUBSTRUCTURE_V1
105 static encoding_rule_t encodings_v1
[] = {
106 /* 1 Byte next payload type, stored in the field next_payload */
107 { U_INT_8
, offsetof(private_transform_substructure_t
, next_payload
) },
108 /* 1 Reserved Byte */
109 { RESERVED_BYTE
, offsetof(private_transform_substructure_t
, reserved
[0]) },
110 /* Length of the whole transform substructure*/
111 { PAYLOAD_LENGTH
, offsetof(private_transform_substructure_t
, transform_length
)},
112 /* transform number */
113 { U_INT_8
, offsetof(private_transform_substructure_t
, transform_ton
)},
114 /* transform identifier, as used by IKEv1 */
115 { U_INT_8
, offsetof(private_transform_substructure_t
, transform_id_v1
) },
116 /* transform identifier, as used by IKEv2 */
117 { RESERVED_BYTE
, offsetof(private_transform_substructure_t
, reserved
[1]) },
118 { RESERVED_BYTE
, offsetof(private_transform_substructure_t
, reserved
[2]) },
119 /* Attributes in a transform attribute list */
120 { PAYLOAD_LIST
+ TRANSFORM_ATTRIBUTE_V1
,
121 offsetof(private_transform_substructure_t
, attributes
) }
126 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
127 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
128 ! 0 (last) or 3 ! RESERVED ! Transform Length !
129 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
130 ! Tfrm Typ or # ! Tfrm ID IKEv1 ! Transform ID IKEv2 !
131 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133 ~ Transform Attributes ~
135 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
138 METHOD(payload_t
, verify
, status_t
,
139 private_transform_substructure_t
*this)
141 status_t status
= SUCCESS
;
142 enumerator_t
*enumerator
;
143 payload_t
*attribute
;
145 if (this->next_payload
!= NO_PAYLOAD
&& this->next_payload
!= 3)
147 DBG1(DBG_ENC
, "inconsistent next payload");
151 enumerator
= this->attributes
->create_enumerator(this->attributes
);
152 while (enumerator
->enumerate(enumerator
, &attribute
))
154 status
= attribute
->verify(attribute
);
155 if (status
!= SUCCESS
)
157 DBG1(DBG_ENC
, "TRANSFORM_ATTRIBUTE verification failed");
161 enumerator
->destroy(enumerator
);
163 /* proposal number is checked in SA payload */
167 METHOD(payload_t
, get_encoding_rules
, int,
168 private_transform_substructure_t
*this, encoding_rule_t
**rules
)
170 if (this->type
== TRANSFORM_ATTRIBUTE
)
172 *rules
= encodings_v2
;
173 return countof(encodings_v2
);
175 *rules
= encodings_v1
;
176 return countof(encodings_v1
);
179 METHOD(payload_t
, get_header_length
, int,
180 private_transform_substructure_t
*this)
185 METHOD(payload_t
, get_type
, payload_type_t
,
186 private_transform_substructure_t
*this)
191 METHOD(payload_t
, get_next_type
, payload_type_t
,
192 private_transform_substructure_t
*this)
194 return this->next_payload
;
198 * recompute the length of the payload.
200 static void compute_length(private_transform_substructure_t
*this)
202 enumerator_t
*enumerator
;
203 payload_t
*attribute
;
205 this->transform_length
= get_header_length(this);
206 enumerator
= this->attributes
->create_enumerator(this->attributes
);
207 while (enumerator
->enumerate(enumerator
, &attribute
))
209 this->transform_length
+= attribute
->get_length(attribute
);
211 enumerator
->destroy(enumerator
);
214 METHOD(payload_t
, get_length
, size_t,
215 private_transform_substructure_t
*this)
217 return this->transform_length
;
220 METHOD(transform_substructure_t
, add_transform_attribute
, void,
221 private_transform_substructure_t
*this, transform_attribute_t
*attribute
)
223 this->attributes
->insert_last(this->attributes
, attribute
);
224 compute_length(this);
227 METHOD(transform_substructure_t
, set_is_last_transform
, void,
228 private_transform_substructure_t
*this, bool is_last
)
230 this->next_payload
= is_last ?
0: TRANSFORM_TYPE_VALUE
;
233 METHOD(payload_t
, set_next_type
, void,
234 private_transform_substructure_t
*this,payload_type_t type
)
238 METHOD(transform_substructure_t
, get_transform_type_or_number
, u_int8_t
,
239 private_transform_substructure_t
*this)
241 return this->transform_ton
;
244 METHOD(transform_substructure_t
, get_transform_id
, u_int16_t
,
245 private_transform_substructure_t
*this)
247 if (this->type
== TRANSFORM_SUBSTRUCTURE
)
249 return this->transform_id_v2
;
251 return this->transform_id_v1
;
254 METHOD(transform_substructure_t
, create_attribute_enumerator
, enumerator_t
*,
255 private_transform_substructure_t
*this)
257 return this->attributes
->create_enumerator(this->attributes
);
260 METHOD2(payload_t
, transform_substructure_t
, destroy
, void,
261 private_transform_substructure_t
*this)
263 this->attributes
->destroy_offset(this->attributes
,
264 offsetof(payload_t
, destroy
));
269 * Described in header.
271 transform_substructure_t
*transform_substructure_create(payload_type_t type
)
273 private_transform_substructure_t
*this;
277 .payload_interface
= {
279 .get_encoding_rules
= _get_encoding_rules
,
280 .get_header_length
= _get_header_length
,
281 .get_length
= _get_length
,
282 .get_next_type
= _get_next_type
,
283 .set_next_type
= _set_next_type
,
284 .get_type
= _get_type
,
287 .add_transform_attribute
= _add_transform_attribute
,
288 .set_is_last_transform
= _set_is_last_transform
,
289 .get_transform_type_or_number
= _get_transform_type_or_number
,
290 .get_transform_id
= _get_transform_id
,
291 .create_attribute_enumerator
= _create_attribute_enumerator
,
294 .next_payload
= NO_PAYLOAD
,
295 .transform_length
= get_header_length(this),
296 .attributes
= linked_list_create(),
299 return &this->public;
303 * Described in header
305 transform_substructure_t
*transform_substructure_create_type(payload_type_t type
,
306 u_int8_t type_or_number
, u_int16_t id
)
308 private_transform_substructure_t
*this;
310 this = (private_transform_substructure_t
*)transform_substructure_create(type
);
312 this->transform_ton
= type_or_number
;
313 if (type
== TRANSFORM_SUBSTRUCTURE
)
315 this->transform_id_v2
= id
;
319 this->transform_id_v1
= id
;
321 return &this->public;