added IKEv2 exchange type IKE_SESSION_RESUME from RFC 5723
[strongswan.git] / src / libcharon / encoding / payloads / ike_header.c
1 /*
2 * Copyright (C) 2007 Tobias Brunner
3 * Copyright (C) 2005-2006 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
6 *
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>.
11 *
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
15 * for more details.
16 */
17
18 /* offsetof macro */
19 #include <stddef.h>
20
21 #include "ike_header.h"
22
23 #include <encoding/payloads/encodings.h>
24
25
26 typedef struct private_ike_header_t private_ike_header_t;
27
28 /**
29 * Private data of an ike_header_t object.
30 */
31 struct private_ike_header_t {
32 /**
33 * Public interface.
34 */
35 ike_header_t public;
36
37 /**
38 * SPI of the initiator.
39 */
40 u_int64_t initiator_spi;
41
42 /**
43 * SPI of the responder.
44 */
45 u_int64_t responder_spi;
46
47 /**
48 * Next payload type.
49 */
50 u_int8_t next_payload;
51 /**
52 * IKE major version.
53 */
54 u_int8_t maj_version;
55
56 /**
57 * IKE minor version.
58 */
59 u_int8_t min_version;
60
61 /**
62 * Exchange type .
63 */
64 u_int8_t exchange_type;
65
66 /**
67 * Flags of the Message.
68 */
69 struct {
70 /**
71 * Sender is initiator of the associated IKE_SA_INIT-Exchange.
72 */
73 bool initiator;
74
75 /**
76 * Is protocol supporting higher version?
77 */
78 bool version;
79
80 /**
81 * TRUE, if this is a response, FALSE if its a Request.
82 */
83 bool response;
84 } flags;
85
86 /**
87 * Reserved bits of IKE header
88 */
89 bool reserved[5];
90
91 /**
92 * Associated Message-ID.
93 */
94 u_int32_t message_id;
95
96 /**
97 * Length of the whole IKEv2-Message (header and all payloads).
98 */
99 u_int32_t length;
100 };
101
102 ENUM_BEGIN(exchange_type_names, EXCHANGE_TYPE_UNDEFINED, EXCHANGE_TYPE_UNDEFINED,
103 "EXCHANGE_TYPE_UNDEFINED");
104 ENUM_NEXT(exchange_type_names, IKE_SA_INIT, IKE_SESSION_RESUME, EXCHANGE_TYPE_UNDEFINED,
105 "IKE_SA_INIT",
106 "IKE_AUTH",
107 "CREATE_CHILD_SA",
108 "INFORMATIONAL",
109 "IKE_SESSION_RESUME");
110 #ifdef ME
111 ENUM_NEXT(exchange_type_names, ME_CONNECT, ME_CONNECT, IKE_SESSION_RESUME,
112 "ME_CONNECT");
113 ENUM_END(exchange_type_names, ME_CONNECT);
114 #else
115 ENUM_END(exchange_type_names, IKE_SESSION_RESUME);
116 #endif /* ME */
117
118 /**
119 * Encoding rules to parse or generate a IKEv2-Header.
120 *
121 * The defined offsets are the positions in a object of type
122 * ike_header_t.
123 */
124 encoding_rule_t ike_header_encodings[] = {
125 /* 8 Byte SPI, stored in the field initiator_spi */
126 { IKE_SPI, offsetof(private_ike_header_t, initiator_spi) },
127 /* 8 Byte SPI, stored in the field responder_spi */
128 { IKE_SPI, offsetof(private_ike_header_t, responder_spi) },
129 /* 1 Byte next payload type, stored in the field next_payload */
130 { U_INT_8, offsetof(private_ike_header_t, next_payload) },
131 /* 4 Bit major version, stored in the field maj_version */
132 { U_INT_4, offsetof(private_ike_header_t, maj_version) },
133 /* 4 Bit minor version, stored in the field min_version */
134 { U_INT_4, offsetof(private_ike_header_t, min_version) },
135 /* 8 Bit for the exchange type */
136 { U_INT_8, offsetof(private_ike_header_t, exchange_type) },
137 /* 2 Bit reserved bits */
138 { RESERVED_BIT, offsetof(private_ike_header_t, reserved[0]) },
139 { RESERVED_BIT, offsetof(private_ike_header_t, reserved[1]) },
140 /* 3 Bit flags, stored in the fields response, version and initiator */
141 { FLAG, offsetof(private_ike_header_t, flags.response) },
142 { FLAG, offsetof(private_ike_header_t, flags.version) },
143 { FLAG, offsetof(private_ike_header_t, flags.initiator) },
144 /* 3 Bit reserved bits */
145 { RESERVED_BIT, offsetof(private_ike_header_t, reserved[2]) },
146 { RESERVED_BIT, offsetof(private_ike_header_t, reserved[3]) },
147 { RESERVED_BIT, offsetof(private_ike_header_t, reserved[4]) },
148 /* 4 Byte message id, stored in the field message_id */
149 { U_INT_32, offsetof(private_ike_header_t, message_id) },
150 /* 4 Byte length fied, stored in the field length */
151 { HEADER_LENGTH,offsetof(private_ike_header_t, length) },
152 };
153
154
155 /* 1 2 3
156 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
157 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
158 ! IKE_SA Initiator's SPI !
159 ! !
160 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161 ! IKE_SA Responder's SPI !
162 ! !
163 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
164 ! Next Payload ! MjVer ! MnVer ! Exchange Type ! Flags !
165 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
166 ! Message ID !
167 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
168 ! Length !
169 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
170 */
171
172 METHOD(payload_t, verify, status_t,
173 private_ike_header_t *this)
174 {
175 if ((this->exchange_type < IKE_SA_INIT) ||
176 ((this->exchange_type > INFORMATIONAL)
177 #ifdef ME
178 && (this->exchange_type != ME_CONNECT)
179 #endif /* ME */
180 ))
181 {
182 /* unsupported exchange type */
183 return FAILED;
184 }
185 if (this->initiator_spi == 0
186 #ifdef ME
187 /* we allow zero spi for INFORMATIONAL exchanges,
188 * to allow connectivity checks */
189 && this->exchange_type != INFORMATIONAL
190 #endif /* ME */
191 )
192 {
193 /* initiator spi not set */
194 return FAILED;
195 }
196 return SUCCESS;
197 }
198
199 METHOD(payload_t, get_encoding_rules, void,
200 private_ike_header_t *this, encoding_rule_t **rules, size_t *rule_count)
201 {
202 *rules = ike_header_encodings;
203 *rule_count = sizeof(ike_header_encodings) / sizeof(encoding_rule_t);
204 }
205
206 METHOD(payload_t, get_type, payload_type_t,
207 private_ike_header_t *this)
208 {
209 return HEADER;
210 }
211
212 METHOD(payload_t, get_next_type, payload_type_t,
213 private_ike_header_t *this)
214 {
215 return this->next_payload;
216 }
217
218 METHOD(payload_t, set_next_type, void,
219 private_ike_header_t *this, payload_type_t type)
220 {
221 this->next_payload = type;
222 }
223
224 METHOD(payload_t, get_length, size_t,
225 private_ike_header_t *this)
226 {
227 return this->length;
228 }
229
230 METHOD(ike_header_t, get_initiator_spi, u_int64_t,
231 private_ike_header_t *this)
232 {
233 return this->initiator_spi;
234 }
235
236 METHOD(ike_header_t, set_initiator_spi, void,
237 private_ike_header_t *this, u_int64_t initiator_spi)
238 {
239 this->initiator_spi = initiator_spi;
240 }
241
242 METHOD(ike_header_t, get_responder_spi, u_int64_t,
243 private_ike_header_t *this)
244 {
245 return this->responder_spi;
246 }
247
248 METHOD(ike_header_t, set_responder_spi, void,
249 private_ike_header_t *this, u_int64_t responder_spi)
250 {
251 this->responder_spi = responder_spi;
252 }
253
254 METHOD(ike_header_t, get_maj_version, u_int8_t,
255 private_ike_header_t *this)
256 {
257 return this->maj_version;
258 }
259
260 METHOD(ike_header_t, set_maj_version, void,
261 private_ike_header_t *this, u_int8_t major)
262 {
263 this->maj_version = major;
264 }
265
266 METHOD(ike_header_t, get_min_version, u_int8_t,
267 private_ike_header_t *this)
268 {
269 return this->min_version;
270 }
271
272 METHOD(ike_header_t, set_min_version, void,
273 private_ike_header_t *this, u_int8_t minor)
274 {
275 this->min_version = minor;
276 }
277
278 METHOD(ike_header_t, get_response_flag, bool,
279 private_ike_header_t *this)
280 {
281 return this->flags.response;
282 }
283
284 METHOD(ike_header_t, set_response_flag, void,
285 private_ike_header_t *this, bool response)
286 {
287 this->flags.response = response;
288 }
289
290 METHOD(ike_header_t, get_version_flag, bool,
291 private_ike_header_t *this)
292 {
293 return this->flags.version;
294 }
295
296 METHOD(ike_header_t, set_version_flag, void,
297 private_ike_header_t *this, bool version)
298 {
299 this->flags.version = version;
300 }
301
302 METHOD(ike_header_t, get_initiator_flag, bool,
303 private_ike_header_t *this)
304 {
305 return this->flags.initiator;
306 }
307
308 METHOD(ike_header_t, set_initiator_flag, void,
309 private_ike_header_t *this, bool initiator)
310 {
311 this->flags.initiator = initiator;
312 }
313
314 METHOD(ike_header_t, get_exchange_type, u_int8_t,
315 private_ike_header_t *this)
316 {
317 return this->exchange_type;
318 }
319
320 METHOD(ike_header_t, set_exchange_type, void,
321 private_ike_header_t *this, u_int8_t exchange_type)
322 {
323 this->exchange_type = exchange_type;
324 }
325
326 METHOD(ike_header_t, get_message_id, u_int32_t,
327 private_ike_header_t *this)
328 {
329 return this->message_id;
330 }
331
332 METHOD(ike_header_t, set_message_id, void,
333 private_ike_header_t *this, u_int32_t message_id)
334 {
335 this->message_id = message_id;
336 }
337
338 METHOD2(payload_t, ike_header_t, destroy, void,
339 private_ike_header_t *this)
340 {
341 free(this);
342 }
343
344 /*
345 * Described in header.
346 */
347 ike_header_t *ike_header_create()
348 {
349 private_ike_header_t *this;
350
351 INIT(this,
352 .public = {
353 .payload_interface = {
354 .verify = _verify,
355 .get_encoding_rules = _get_encoding_rules,
356 .get_length = _get_length,
357 .get_next_type = _get_next_type,
358 .set_next_type = _set_next_type,
359 .get_type = _get_type,
360 .destroy = _destroy,
361 },
362 .get_initiator_spi = _get_initiator_spi,
363 .set_initiator_spi = _set_initiator_spi,
364 .get_responder_spi = _get_responder_spi,
365 .set_responder_spi = _set_responder_spi,
366 .get_maj_version = _get_maj_version,
367 .set_maj_version = _set_maj_version,
368 .get_min_version = _get_min_version,
369 .set_min_version = _set_min_version,
370 .get_response_flag = _get_response_flag,
371 .set_response_flag = _set_response_flag,
372 .get_version_flag = _get_version_flag,
373 .set_version_flag = _set_version_flag,
374 .get_initiator_flag = _get_initiator_flag,
375 .set_initiator_flag = _set_initiator_flag,
376 .get_exchange_type = _get_exchange_type,
377 .set_exchange_type = _set_exchange_type,
378 .get_message_id = _get_message_id,
379 .set_message_id = _set_message_id,
380 .destroy = _destroy,
381 },
382 .maj_version = IKE_MAJOR_VERSION,
383 .min_version = IKE_MINOR_VERSION,
384 .exchange_type = EXCHANGE_TYPE_UNDEFINED,
385 .flags = {
386 .initiator = TRUE,
387 .version = HIGHER_VERSION_SUPPORTED_FLAG,
388 },
389 .length = IKE_HEADER_LENGTH,
390 );
391
392 return &this->public;
393 }