2 * Copyright (C) 2007 Tobias Brunner
3 * Copyright (C) 2005-2006 Martin Willi
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
21 #include "ike_header.h"
23 #include <encoding/payloads/encodings.h>
26 typedef struct private_ike_header_t private_ike_header_t
;
29 * Private data of an ike_header_t object.
31 struct private_ike_header_t
{
38 * SPI of the initiator.
40 u_int64_t initiator_spi
;
43 * SPI of the responder.
45 u_int64_t responder_spi
;
50 u_int8_t next_payload
;
64 u_int8_t exchange_type
;
67 * Flags of the Message.
71 * Sender is initiator of the associated IKE_SA_INIT-Exchange.
76 * Is protocol supporting higher version?
81 * TRUE, if this is a response, FALSE if its a Request.
86 * TRUE, if the packet is encrypted (IKEv1).
91 * TRUE, if the commit flag is set (IKEv1).
96 * TRUE, if the auth only flag is set (IKEv1).
102 * Reserved bits of IKE header
107 * Associated Message-ID.
109 u_int32_t message_id
;
112 * Length of the whole IKEv2-Message (header and all payloads).
117 ENUM_BEGIN(exchange_type_names
, ID_PROT
, INFORMATIONAL_V1
,
122 ENUM_NEXT(exchange_type_names
, QUICK_MODE
, IKE_SESSION_RESUME
, INFORMATIONAL_V1
,
129 "IKE_SESSION_RESUME");
131 ENUM_NEXT(exchange_type_names
, ME_CONNECT
, ME_CONNECT
, IKE_SESSION_RESUME
,
133 ENUM_NEXT(exchange_type_names
, EXCHANGE_TYPE_UNDEFINED
,
134 EXCHANGE_TYPE_UNDEFINED
, ME_CONNECT
,
135 "EXCHANGE_TYPE_UNDEFINED");
137 ENUM_NEXT(exchange_type_names
, EXCHANGE_TYPE_UNDEFINED
,
138 EXCHANGE_TYPE_UNDEFINED
, IKE_SESSION_RESUME
,
139 "EXCHANGE_TYPE_UNDEFINED");
141 ENUM_END(exchange_type_names
, EXCHANGE_TYPE_UNDEFINED
);
144 * Encoding rules to parse or generate a IKE-Header.
146 * The defined offsets are the positions in a object of type
149 encoding_rule_t ike_header_encodings
[] = {
150 /* 8 Byte SPI, stored in the field initiator_spi */
151 { IKE_SPI
, offsetof(private_ike_header_t
, initiator_spi
) },
152 /* 8 Byte SPI, stored in the field responder_spi */
153 { IKE_SPI
, offsetof(private_ike_header_t
, responder_spi
) },
154 /* 1 Byte next payload type, stored in the field next_payload */
155 { U_INT_8
, offsetof(private_ike_header_t
, next_payload
) },
156 /* 4 Bit major version, stored in the field maj_version */
157 { U_INT_4
, offsetof(private_ike_header_t
, maj_version
) },
158 /* 4 Bit minor version, stored in the field min_version */
159 { U_INT_4
, offsetof(private_ike_header_t
, min_version
) },
160 /* 8 Bit for the exchange type */
161 { U_INT_8
, offsetof(private_ike_header_t
, exchange_type
) },
162 /* 2 Bit reserved bits */
163 { RESERVED_BIT
, offsetof(private_ike_header_t
, reserved
[0]) },
164 { RESERVED_BIT
, offsetof(private_ike_header_t
, reserved
[1]) },
166 { FLAG
, offsetof(private_ike_header_t
, flags
.response
) },
167 { FLAG
, offsetof(private_ike_header_t
, flags
.version
) },
168 { FLAG
, offsetof(private_ike_header_t
, flags
.initiator
) },
169 { FLAG
, offsetof(private_ike_header_t
, flags
.authonly
) },
170 { FLAG
, offsetof(private_ike_header_t
, flags
.commit
) },
171 { FLAG
, offsetof(private_ike_header_t
, flags
.encryption
)},
172 /* 4 Byte message id, stored in the field message_id */
173 { U_INT_32
, offsetof(private_ike_header_t
, message_id
) },
174 /* 4 Byte length fied, stored in the field length */
175 { HEADER_LENGTH
,offsetof(private_ike_header_t
, length
) },
179 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
180 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
181 ! IKE_SA Initiator's SPI !
183 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
184 ! IKE_SA Responder's SPI !
186 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
187 ! Next Payload ! MjVer ! MnVer ! Exchange Type ! Flags !
188 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
190 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
192 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
195 METHOD(payload_t
, verify
, status_t
,
196 private_ike_header_t
*this)
198 switch (this->exchange_type
)
202 if (this->message_id
!= 0)
208 case INFORMATIONAL_V1
:
211 if (this->maj_version
!= IKEV1_MAJOR_VERSION
)
218 case CREATE_CHILD_SA
:
220 case IKE_SESSION_RESUME
:
224 if (this->maj_version
!= IKEV2_MAJOR_VERSION
)
230 /* unsupported exchange type */
233 if (this->initiator_spi
== 0)
236 if (this->exchange_type
!= INFORMATIONAL
)
237 /* we allow zero spi for INFORMATIONAL exchanges,
238 * to allow connectivity checks */
247 METHOD(payload_t
, get_encoding_rules
, void,
248 private_ike_header_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
250 *rules
= ike_header_encodings
;
251 *rule_count
= sizeof(ike_header_encodings
) / sizeof(encoding_rule_t
);
254 METHOD(payload_t
, get_type
, payload_type_t
,
255 private_ike_header_t
*this)
260 METHOD(payload_t
, get_next_type
, payload_type_t
,
261 private_ike_header_t
*this)
263 return this->next_payload
;
266 METHOD(payload_t
, set_next_type
, void,
267 private_ike_header_t
*this, payload_type_t type
)
269 this->next_payload
= type
;
272 METHOD(payload_t
, get_length
, size_t,
273 private_ike_header_t
*this)
278 METHOD(ike_header_t
, get_initiator_spi
, u_int64_t
,
279 private_ike_header_t
*this)
281 return this->initiator_spi
;
284 METHOD(ike_header_t
, set_initiator_spi
, void,
285 private_ike_header_t
*this, u_int64_t initiator_spi
)
287 this->initiator_spi
= initiator_spi
;
290 METHOD(ike_header_t
, get_responder_spi
, u_int64_t
,
291 private_ike_header_t
*this)
293 return this->responder_spi
;
296 METHOD(ike_header_t
, set_responder_spi
, void,
297 private_ike_header_t
*this, u_int64_t responder_spi
)
299 this->responder_spi
= responder_spi
;
302 METHOD(ike_header_t
, get_maj_version
, u_int8_t
,
303 private_ike_header_t
*this)
305 return this->maj_version
;
308 METHOD(ike_header_t
, set_maj_version
, void,
309 private_ike_header_t
*this, u_int8_t major
)
311 this->maj_version
= major
;
314 METHOD(ike_header_t
, get_min_version
, u_int8_t
,
315 private_ike_header_t
*this)
317 return this->min_version
;
320 METHOD(ike_header_t
, set_min_version
, void,
321 private_ike_header_t
*this, u_int8_t minor
)
323 this->min_version
= minor
;
326 METHOD(ike_header_t
, get_response_flag
, bool,
327 private_ike_header_t
*this)
329 return this->flags
.response
;
332 METHOD(ike_header_t
, set_response_flag
, void,
333 private_ike_header_t
*this, bool response
)
335 this->flags
.response
= response
;
338 METHOD(ike_header_t
, get_version_flag
, bool,
339 private_ike_header_t
*this)
341 return this->flags
.version
;
344 METHOD(ike_header_t
, set_version_flag
, void,
345 private_ike_header_t
*this, bool version
)
347 this->flags
.version
= version
;
350 METHOD(ike_header_t
, get_initiator_flag
, bool,
351 private_ike_header_t
*this)
353 return this->flags
.initiator
;
356 METHOD(ike_header_t
, set_initiator_flag
, void,
357 private_ike_header_t
*this, bool initiator
)
359 this->flags
.initiator
= initiator
;
362 METHOD(ike_header_t
, get_encryption_flag
, bool,
363 private_ike_header_t
*this)
365 return this->flags
.encryption
;
368 METHOD(ike_header_t
, set_encryption_flag
, void,
369 private_ike_header_t
*this, bool encryption
)
371 this->flags
.encryption
= encryption
;
375 METHOD(ike_header_t
, get_commit_flag
, bool,
376 private_ike_header_t
*this)
378 return this->flags
.commit
;
381 METHOD(ike_header_t
, set_commit_flag
, void,
382 private_ike_header_t
*this, bool commit
)
384 this->flags
.commit
= commit
;
387 METHOD(ike_header_t
, get_authonly_flag
, bool,
388 private_ike_header_t
*this)
390 return this->flags
.authonly
;
393 METHOD(ike_header_t
, set_authonly_flag
, void,
394 private_ike_header_t
*this, bool authonly
)
396 this->flags
.authonly
= authonly
;
399 METHOD(ike_header_t
, get_exchange_type
, u_int8_t
,
400 private_ike_header_t
*this)
402 return this->exchange_type
;
405 METHOD(ike_header_t
, set_exchange_type
, void,
406 private_ike_header_t
*this, u_int8_t exchange_type
)
408 this->exchange_type
= exchange_type
;
411 METHOD(ike_header_t
, get_message_id
, u_int32_t
,
412 private_ike_header_t
*this)
414 return this->message_id
;
417 METHOD(ike_header_t
, set_message_id
, void,
418 private_ike_header_t
*this, u_int32_t message_id
)
420 this->message_id
= message_id
;
423 METHOD2(payload_t
, ike_header_t
, destroy
, void,
424 private_ike_header_t
*this)
430 * Described in header.
432 ike_header_t
*ike_header_create()
434 private_ike_header_t
*this;
438 .payload_interface
= {
440 .get_encoding_rules
= _get_encoding_rules
,
441 .get_length
= _get_length
,
442 .get_next_type
= _get_next_type
,
443 .set_next_type
= _set_next_type
,
444 .get_type
= _get_type
,
447 .get_initiator_spi
= _get_initiator_spi
,
448 .set_initiator_spi
= _set_initiator_spi
,
449 .get_responder_spi
= _get_responder_spi
,
450 .set_responder_spi
= _set_responder_spi
,
451 .get_maj_version
= _get_maj_version
,
452 .set_maj_version
= _set_maj_version
,
453 .get_min_version
= _get_min_version
,
454 .set_min_version
= _set_min_version
,
455 .get_response_flag
= _get_response_flag
,
456 .set_response_flag
= _set_response_flag
,
457 .get_version_flag
= _get_version_flag
,
458 .set_version_flag
= _set_version_flag
,
459 .get_initiator_flag
= _get_initiator_flag
,
460 .set_initiator_flag
= _set_initiator_flag
,
461 .get_encryption_flag
= _get_encryption_flag
,
462 .set_encryption_flag
= _set_encryption_flag
,
463 .get_commit_flag
= _get_commit_flag
,
464 .set_commit_flag
= _set_commit_flag
,
465 .get_authonly_flag
= _get_authonly_flag
,
466 .set_authonly_flag
= _set_authonly_flag
,
467 .get_exchange_type
= _get_exchange_type
,
468 .set_exchange_type
= _set_exchange_type
,
469 .get_message_id
= _get_message_id
,
470 .set_message_id
= _set_message_id
,
473 .length
= IKE_HEADER_LENGTH
,
474 .exchange_type
= EXCHANGE_TYPE_UNDEFINED
,
477 return &this->public;
481 * Described in header.
483 ike_header_t
*ike_header_create_version(int major
, int minor
)
485 ike_header_t
*this = ike_header_create();
487 this->set_maj_version(this, major
);
488 this->set_min_version(this, minor
);
489 if (major
== IKEV2_MAJOR_VERSION
)
491 this->set_initiator_flag(this, TRUE
);