payload: Use common prefixes for all payload type identifiers
[strongswan.git] / src / libcharon / encoding / payloads / delete_payload.c
1 /*
2 * Copyright (C) 2005-2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
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 #include <stddef.h>
19
20 #include "delete_payload.h"
21
22
23 typedef struct private_delete_payload_t private_delete_payload_t;
24
25 /**
26 * Private data of an delete_payload_t object.
27 */
28 struct private_delete_payload_t {
29
30 /**
31 * Public delete_payload_t interface.
32 */
33 delete_payload_t public;
34
35 /**
36 * Next payload type.
37 */
38 u_int8_t next_payload;
39
40 /**
41 * Critical flag.
42 */
43 bool critical;
44
45 /**
46 * reserved bits
47 */
48 bool reserved[8];
49
50 /**
51 * Length of this payload.
52 */
53 u_int16_t payload_length;
54
55 /**
56 * IKEv1 Domain of Interpretation
57 */
58 u_int32_t doi;
59
60 /**
61 * Protocol ID.
62 */
63 u_int8_t protocol_id;
64
65 /**
66 * SPI Size.
67 */
68 u_int8_t spi_size;
69
70 /**
71 * Number of SPI's.
72 */
73 u_int16_t spi_count;
74
75 /**
76 * The contained SPI's.
77 */
78 chunk_t spis;
79
80 /**
81 * Payload type, PLV2_DELETE or PLV1_DELETE
82 */
83 payload_type_t type;
84 };
85
86 /**
87 * Encoding rules for an IKEv2 delete payload.
88 */
89 static encoding_rule_t encodings_v2[] = {
90 /* 1 Byte next payload type, stored in the field next_payload */
91 { U_INT_8, offsetof(private_delete_payload_t, next_payload) },
92 /* the critical bit */
93 { FLAG, offsetof(private_delete_payload_t, critical) },
94 /* 7 Bit reserved bits */
95 { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[0]) },
96 { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[1]) },
97 { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[2]) },
98 { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[3]) },
99 { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[4]) },
100 { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[5]) },
101 { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[6]) },
102 /* Length of the whole payload*/
103 { PAYLOAD_LENGTH, offsetof(private_delete_payload_t, payload_length) },
104 { U_INT_8, offsetof(private_delete_payload_t, protocol_id) },
105 { U_INT_8, offsetof(private_delete_payload_t, spi_size) },
106 { U_INT_16, offsetof(private_delete_payload_t, spi_count) },
107 /* some delete data bytes, length is defined in PAYLOAD_LENGTH */
108 { CHUNK_DATA, offsetof(private_delete_payload_t, spis) },
109 };
110
111 /*
112 1 2 3
113 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
114 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115 ! Next Payload !C! RESERVED ! Payload Length !
116 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
117 ! Protocol ID ! SPI Size ! # of SPIs !
118 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119 ! !
120 ~ Security Parameter Index(es) (SPI) ~
121 ! !
122 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
123 */
124
125 /**
126 * Encoding rules for an IKEv1 delete payload.
127 */
128 static encoding_rule_t encodings_v1[] = {
129 /* 1 Byte next payload type, stored in the field next_payload */
130 { U_INT_8, offsetof(private_delete_payload_t, next_payload) },
131 /* 8 Bit reserved bits */
132 { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[0]) },
133 { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[1]) },
134 { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[2]) },
135 { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[3]) },
136 { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[4]) },
137 { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[5]) },
138 { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[6]) },
139 { RESERVED_BIT, offsetof(private_delete_payload_t, reserved[7]) },
140 /* Length of the whole payload*/
141 { PAYLOAD_LENGTH, offsetof(private_delete_payload_t, payload_length) },
142 /* Domain of interpretation */
143 { U_INT_32, offsetof(private_delete_payload_t, doi) },
144 { U_INT_8, offsetof(private_delete_payload_t, protocol_id) },
145 { U_INT_8, offsetof(private_delete_payload_t, spi_size) },
146 { U_INT_16, offsetof(private_delete_payload_t, spi_count) },
147 /* some delete data bytes, length is defined in PAYLOAD_LENGTH */
148 { CHUNK_DATA, offsetof(private_delete_payload_t, spis) },
149 };
150
151 /*
152 1 2 3
153 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
154 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
155 ! Next Payload !C! RESERVED ! Payload Length !
156 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
157 ! DOI !
158 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
159 ! Protocol ID ! SPI Size ! # of SPIs !
160 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161 ! !
162 ~ Security Parameter Index(es) (SPI) ~
163 ! !
164 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
165 */
166
167 METHOD(payload_t, verify, status_t,
168 private_delete_payload_t *this)
169 {
170 switch (this->protocol_id)
171 {
172 case PROTO_AH:
173 case PROTO_ESP:
174 if (this->spi_size != 4)
175 {
176 return FAILED;
177 }
178 break;
179 case PROTO_IKE:
180 case 0:
181 if (this->type == PLV2_DELETE)
182 { /* IKEv2 deletion has no spi assigned! */
183 if (this->spi_size != 0)
184 {
185 return FAILED;
186 }
187 }
188 else
189 { /* IKEv1 uses the two concatenated ISAKMP cookies as SPI */
190 if (this->spi_size != 16)
191 {
192 return FAILED;
193 }
194 }
195 break;
196 default:
197 return FAILED;
198 }
199 if (this->spis.len != (this->spi_count * this->spi_size))
200 {
201 return FAILED;
202 }
203 return SUCCESS;
204 }
205
206 METHOD(payload_t, get_encoding_rules, int,
207 private_delete_payload_t *this, encoding_rule_t **rules)
208 {
209 if (this->type == PLV2_DELETE)
210 {
211 *rules = encodings_v2;
212 return countof(encodings_v2);
213 }
214 *rules = encodings_v1;
215 return countof(encodings_v1);
216 }
217
218 METHOD(payload_t, get_header_length, int,
219 private_delete_payload_t *this)
220 {
221 if (this->type == PLV2_DELETE)
222 {
223 return 8;
224 }
225 return 12;
226 }
227
228 METHOD(payload_t, get_payload_type, payload_type_t,
229 private_delete_payload_t *this)
230 {
231 return this->type;
232 }
233
234 METHOD(payload_t, get_next_type, payload_type_t,
235 private_delete_payload_t *this)
236 {
237 return this->next_payload;
238 }
239
240 METHOD(payload_t, set_next_type, void,
241 private_delete_payload_t *this,payload_type_t type)
242 {
243 this->next_payload = type;
244 }
245
246 METHOD(payload_t, get_length, size_t,
247 private_delete_payload_t *this)
248 {
249 return this->payload_length;
250 }
251
252 METHOD(delete_payload_t, get_protocol_id, protocol_id_t,
253 private_delete_payload_t *this)
254 {
255 return this->protocol_id;
256 }
257
258 METHOD(delete_payload_t, add_spi, void,
259 private_delete_payload_t *this, u_int32_t spi)
260 {
261 switch (this->protocol_id)
262 {
263 case PROTO_AH:
264 case PROTO_ESP:
265 this->spi_count++;
266 this->payload_length += sizeof(spi);
267 this->spis = chunk_cat("mc", this->spis, chunk_from_thing(spi));
268 break;
269 default:
270 break;
271 }
272 }
273
274 METHOD(delete_payload_t, set_ike_spi, void,
275 private_delete_payload_t *this, u_int64_t spi_i, u_int64_t spi_r)
276 {
277 free(this->spis.ptr);
278 this->spis = chunk_cat("cc", chunk_from_thing(spi_i),
279 chunk_from_thing(spi_r));
280 this->spi_count = 1;
281 this->payload_length = get_header_length(this) + this->spi_size;
282 }
283
284 /**
285 * SPI enumerator implementation
286 */
287 typedef struct {
288 /** implements enumerator_t */
289 enumerator_t public;
290 /** remaining SPIs */
291 chunk_t spis;
292 } spi_enumerator_t;
293
294 METHOD(enumerator_t, spis_enumerate, bool,
295 spi_enumerator_t *this, u_int32_t *spi)
296 {
297 if (this->spis.len >= sizeof(*spi))
298 {
299 memcpy(spi, this->spis.ptr, sizeof(*spi));
300 this->spis = chunk_skip(this->spis, sizeof(*spi));
301 return TRUE;
302 }
303 return FALSE;
304 }
305
306 METHOD(delete_payload_t, create_spi_enumerator, enumerator_t*,
307 private_delete_payload_t *this)
308 {
309 spi_enumerator_t *e;
310
311 if (this->spi_size != sizeof(u_int32_t))
312 {
313 return enumerator_create_empty();
314 }
315 INIT(e,
316 .public = {
317 .enumerate = (void*)_spis_enumerate,
318 .destroy = (void*)free,
319 },
320 .spis = this->spis,
321 );
322 return &e->public;
323 }
324
325 METHOD2(payload_t, delete_payload_t, destroy, void,
326 private_delete_payload_t *this)
327 {
328 free(this->spis.ptr);
329 free(this);
330 }
331
332 /*
333 * Described in header
334 */
335 delete_payload_t *delete_payload_create(payload_type_t type,
336 protocol_id_t protocol_id)
337 {
338 private_delete_payload_t *this;
339
340 INIT(this,
341 .public = {
342 .payload_interface = {
343 .verify = _verify,
344 .get_encoding_rules = _get_encoding_rules,
345 .get_header_length = _get_header_length,
346 .get_length = _get_length,
347 .get_next_type = _get_next_type,
348 .set_next_type = _set_next_type,
349 .get_type = _get_payload_type,
350 .destroy = _destroy,
351 },
352 .get_protocol_id = _get_protocol_id,
353 .add_spi = _add_spi,
354 .set_ike_spi = _set_ike_spi,
355 .create_spi_enumerator = _create_spi_enumerator,
356 .destroy = _destroy,
357 },
358 .next_payload = PL_NONE,
359 .protocol_id = protocol_id,
360 .doi = IKEV1_DOI_IPSEC,
361 .type = type,
362 );
363 this->payload_length = get_header_length(this);
364
365 if (protocol_id == PROTO_IKE)
366 {
367 if (type == PLV1_DELETE)
368 {
369 this->spi_size = 16;
370 }
371 }
372 else
373 {
374 this->spi_size = 4;
375 }
376 return &this->public;
377 }