Added setters for IKE major/minor version to ike_header
[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 * Associated Message-ID.
88 */
89 u_int32_t message_id;
90
91 /**
92 * Length of the whole IKEv2-Message (header and all payloads).
93 */
94 u_int32_t length;
95 };
96
97 ENUM_BEGIN(exchange_type_names, EXCHANGE_TYPE_UNDEFINED, EXCHANGE_TYPE_UNDEFINED,
98 "EXCHANGE_TYPE_UNDEFINED");
99 ENUM_NEXT(exchange_type_names, IKE_SA_INIT, INFORMATIONAL, EXCHANGE_TYPE_UNDEFINED,
100 "IKE_SA_INIT",
101 "IKE_AUTH",
102 "CREATE_CHILD_SA",
103 "INFORMATIONAL");
104 #ifdef ME
105 ENUM_NEXT(exchange_type_names, ME_CONNECT, ME_CONNECT, INFORMATIONAL,
106 "ME_CONNECT");
107 ENUM_END(exchange_type_names, ME_CONNECT);
108 #else
109 ENUM_END(exchange_type_names, INFORMATIONAL);
110 #endif /* ME */
111
112 /**
113 * Encoding rules to parse or generate a IKEv2-Header.
114 *
115 * The defined offsets are the positions in a object of type
116 * ike_header_t.
117 */
118 encoding_rule_t ike_header_encodings[] = {
119 /* 8 Byte SPI, stored in the field initiator_spi */
120 { IKE_SPI, offsetof(private_ike_header_t, initiator_spi) },
121 /* 8 Byte SPI, stored in the field responder_spi */
122 { IKE_SPI, offsetof(private_ike_header_t, responder_spi) },
123 /* 1 Byte next payload type, stored in the field next_payload */
124 { U_INT_8, offsetof(private_ike_header_t, next_payload) },
125 /* 4 Bit major version, stored in the field maj_version */
126 { U_INT_4, offsetof(private_ike_header_t, maj_version) },
127 /* 4 Bit minor version, stored in the field min_version */
128 { U_INT_4, offsetof(private_ike_header_t, min_version) },
129 /* 8 Bit for the exchange type */
130 { U_INT_8, offsetof(private_ike_header_t, exchange_type) },
131 /* 2 Bit reserved bits, nowhere stored */
132 { RESERVED_BIT, 0 },
133 { RESERVED_BIT, 0 },
134 /* 3 Bit flags, stored in the fields response, version and initiator */
135 { FLAG, offsetof(private_ike_header_t, flags.response) },
136 { FLAG, offsetof(private_ike_header_t, flags.version) },
137 { FLAG, offsetof(private_ike_header_t, flags.initiator) },
138 /* 3 Bit reserved bits, nowhere stored */
139 { RESERVED_BIT, 0 },
140 { RESERVED_BIT, 0 },
141 { RESERVED_BIT, 0 },
142 /* 4 Byte message id, stored in the field message_id */
143 { U_INT_32, offsetof(private_ike_header_t, message_id) },
144 /* 4 Byte length fied, stored in the field length */
145 { HEADER_LENGTH,offsetof(private_ike_header_t, length) },
146 };
147
148
149 /* 1 2 3
150 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
151 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
152 ! IKE_SA Initiator's SPI !
153 ! !
154 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
155 ! IKE_SA Responder's SPI !
156 ! !
157 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
158 ! Next Payload ! MjVer ! MnVer ! Exchange Type ! Flags !
159 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
160 ! Message ID !
161 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
162 ! Length !
163 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
164 */
165
166 METHOD(payload_t, verify, status_t,
167 private_ike_header_t *this)
168 {
169 if ((this->exchange_type < IKE_SA_INIT) ||
170 ((this->exchange_type > INFORMATIONAL)
171 #ifdef ME
172 && (this->exchange_type != ME_CONNECT)
173 #endif /* ME */
174 ))
175 {
176 /* unsupported exchange type */
177 return FAILED;
178 }
179 if (this->initiator_spi == 0
180 #ifdef ME
181 /* we allow zero spi for INFORMATIONAL exchanges,
182 * to allow connectivity checks */
183 && this->exchange_type != INFORMATIONAL
184 #endif /* ME */
185 )
186 {
187 /* initiator spi not set */
188 return FAILED;
189 }
190 return SUCCESS;
191 }
192
193 METHOD(payload_t, get_encoding_rules, void,
194 private_ike_header_t *this, encoding_rule_t **rules, size_t *rule_count)
195 {
196 *rules = ike_header_encodings;
197 *rule_count = sizeof(ike_header_encodings) / sizeof(encoding_rule_t);
198 }
199
200 METHOD(payload_t, get_type, payload_type_t,
201 private_ike_header_t *this)
202 {
203 return HEADER;
204 }
205
206 METHOD(payload_t, get_next_type, payload_type_t,
207 private_ike_header_t *this)
208 {
209 return this->next_payload;
210 }
211
212 METHOD(payload_t, set_next_type, void,
213 private_ike_header_t *this, payload_type_t type)
214 {
215 this->next_payload = type;
216 }
217
218 METHOD(payload_t, get_length, size_t,
219 private_ike_header_t *this)
220 {
221 return this->length;
222 }
223
224 METHOD(ike_header_t, get_initiator_spi, u_int64_t,
225 private_ike_header_t *this)
226 {
227 return this->initiator_spi;
228 }
229
230 METHOD(ike_header_t, set_initiator_spi, void,
231 private_ike_header_t *this, u_int64_t initiator_spi)
232 {
233 this->initiator_spi = initiator_spi;
234 }
235
236 METHOD(ike_header_t, get_responder_spi, u_int64_t,
237 private_ike_header_t *this)
238 {
239 return this->responder_spi;
240 }
241
242 METHOD(ike_header_t, set_responder_spi, void,
243 private_ike_header_t *this, u_int64_t responder_spi)
244 {
245 this->responder_spi = responder_spi;
246 }
247
248 METHOD(ike_header_t, get_maj_version, u_int8_t,
249 private_ike_header_t *this)
250 {
251 return this->maj_version;
252 }
253
254 METHOD(ike_header_t, set_maj_version, void,
255 private_ike_header_t *this, u_int8_t major)
256 {
257 this->maj_version = major;
258 }
259
260 METHOD(ike_header_t, get_min_version, u_int8_t,
261 private_ike_header_t *this)
262 {
263 return this->min_version;
264 }
265
266 METHOD(ike_header_t, set_min_version, void,
267 private_ike_header_t *this, u_int8_t minor)
268 {
269 this->min_version = minor;
270 }
271
272 METHOD(ike_header_t, get_response_flag, bool,
273 private_ike_header_t *this)
274 {
275 return this->flags.response;
276 }
277
278 METHOD(ike_header_t, set_response_flag, void,
279 private_ike_header_t *this, bool response)
280 {
281 this->flags.response = response;
282 }
283
284 METHOD(ike_header_t, get_version_flag, bool,
285 private_ike_header_t *this)
286 {
287 return this->flags.version;
288 }
289
290 METHOD(ike_header_t, get_initiator_flag, bool,
291 private_ike_header_t *this)
292 {
293 return this->flags.initiator;
294 }
295
296 METHOD(ike_header_t, set_initiator_flag, void,
297 private_ike_header_t *this, bool initiator)
298 {
299 this->flags.initiator = initiator;
300 }
301
302 METHOD(ike_header_t, get_exchange_type, u_int8_t,
303 private_ike_header_t *this)
304 {
305 return this->exchange_type;
306 }
307
308 METHOD(ike_header_t, set_exchange_type, void,
309 private_ike_header_t *this, u_int8_t exchange_type)
310 {
311 this->exchange_type = exchange_type;
312 }
313
314 METHOD(ike_header_t, get_message_id, u_int32_t,
315 private_ike_header_t *this)
316 {
317 return this->message_id;
318 }
319
320 METHOD(ike_header_t, set_message_id, void,
321 private_ike_header_t *this, u_int32_t message_id)
322 {
323 this->message_id = message_id;
324 }
325
326 METHOD2(payload_t, ike_header_t, destroy, void,
327 private_ike_header_t *this)
328 {
329 free(this);
330 }
331
332 /*
333 * Described in header.
334 */
335 ike_header_t *ike_header_create()
336 {
337 private_ike_header_t *this;
338
339 INIT(this,
340 .public = {
341 .payload_interface = {
342 .verify = _verify,
343 .get_encoding_rules = _get_encoding_rules,
344 .get_length = _get_length,
345 .get_next_type = _get_next_type,
346 .set_next_type = _set_next_type,
347 .get_type = _get_type,
348 .destroy = _destroy,
349 },
350 .get_initiator_spi = _get_initiator_spi,
351 .set_initiator_spi = _set_initiator_spi,
352 .get_responder_spi = _get_responder_spi,
353 .set_responder_spi = _set_responder_spi,
354 .get_maj_version = _get_maj_version,
355 .set_maj_version = _set_maj_version,
356 .get_min_version = _get_min_version,
357 .set_min_version = _set_min_version,
358 .get_response_flag = _get_response_flag,
359 .set_response_flag = _set_response_flag,
360 .get_version_flag = _get_version_flag,
361 .get_initiator_flag = _get_initiator_flag,
362 .set_initiator_flag = _set_initiator_flag,
363 .get_exchange_type = _get_exchange_type,
364 .set_exchange_type = _set_exchange_type,
365 .get_message_id = _get_message_id,
366 .set_message_id = _set_message_id,
367 .destroy = _destroy,
368 },
369 .maj_version = IKE_MAJOR_VERSION,
370 .min_version = IKE_MINOR_VERSION,
371 .exchange_type = EXCHANGE_TYPE_UNDEFINED,
372 .flags.initiator = TRUE,
373 .flags.version = HIGHER_VERSION_SUPPORTED_FLAG,
374 .length = IKE_HEADER_LENGTH,
375 );
376
377 return &this->public;
378 }