updated copyright information
[strongswan.git] / src / charon / encoding / payloads / delete_payload.c
1 /**
2 * @file delete_payload.c
3 *
4 * @brief Implementation of delete_payload_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include <stddef.h>
25
26 #include "delete_payload.h"
27
28
29 typedef struct private_delete_payload_t private_delete_payload_t;
30
31 /**
32 * Private data of an delete_payload_t object.
33 *
34 */
35 struct private_delete_payload_t {
36 /**
37 * Public delete_payload_t interface.
38 */
39 delete_payload_t public;
40
41 /**
42 * Next payload type.
43 */
44 u_int8_t next_payload;
45
46 /**
47 * Critical flag.
48 */
49 bool critical;
50
51 /**
52 * Length of this payload.
53 */
54 u_int16_t payload_length;
55
56 /**
57 * Protocol ID.
58 */
59 u_int8_t protocol_id;
60
61 /**
62 * SPI Size.
63 */
64 u_int8_t spi_size;
65
66 /**
67 * Number of SPI's.
68 */
69 u_int16_t spi_count;
70
71 /**
72 * The contained SPI's.
73 */
74 chunk_t spis;
75
76 /**
77 * List containing u_int32_t spis
78 */
79 linked_list_t *spi_list;
80 };
81
82 /**
83 * Encoding rules to parse or generate a DELETE payload
84 *
85 * The defined offsets are the positions in a object of type
86 * private_delete_payload_t.
87 *
88 */
89 encoding_rule_t delete_payload_encodings[] = {
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, nowhere stored */
95 { RESERVED_BIT, 0 },
96 { RESERVED_BIT, 0 },
97 { RESERVED_BIT, 0 },
98 { RESERVED_BIT, 0 },
99 { RESERVED_BIT, 0 },
100 { RESERVED_BIT, 0 },
101 { RESERVED_BIT, 0 },
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 { SPIS, 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 * Implementation of payload_t.verify.
127 */
128 static status_t verify(private_delete_payload_t *this)
129 {
130 switch (this->protocol_id)
131 {
132 case PROTO_AH:
133 case PROTO_ESP:
134 if (this->spi_size != 4)
135 {
136 return FAILED;
137 }
138 break;
139 case PROTO_IKE:
140 case 0:
141 /* IKE deletion has no spi assigned! */
142 if (this->spi_size != 0)
143 {
144 return FAILED;
145 }
146 break;
147 default:
148 return FAILED;
149 }
150 if (this->spis.len != (this->spi_count * this->spi_size))
151 {
152 return FAILED;
153 }
154 return SUCCESS;
155 }
156
157 /**
158 * Implementation of delete_payload_t.get_encoding_rules.
159 */
160 static void get_encoding_rules(private_delete_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
161 {
162 *rules = delete_payload_encodings;
163 *rule_count = sizeof(delete_payload_encodings) / sizeof(encoding_rule_t);
164 }
165
166 /**
167 * Implementation of payload_t.get_type.
168 */
169 static payload_type_t get_payload_type(private_delete_payload_t *this)
170 {
171 return DELETE;
172 }
173
174 /**
175 * Implementation of payload_t.get_next_type.
176 */
177 static payload_type_t get_next_type(private_delete_payload_t *this)
178 {
179 return (this->next_payload);
180 }
181
182 /**
183 * Implementation of payload_t.set_next_type.
184 */
185 static void set_next_type(private_delete_payload_t *this,payload_type_t type)
186 {
187 this->next_payload = type;
188 }
189
190 /**
191 * Implementation of payload_t.get_length.
192 */
193 static size_t get_length(private_delete_payload_t *this)
194 {
195 return this->payload_length;
196 }
197
198 /**
199 * Implementation of delete_payload_t.set_protocol_id.
200 */
201 static void set_protocol_id (private_delete_payload_t *this, protocol_id_t protocol_id)
202 {
203 this->protocol_id = protocol_id;
204 }
205
206 /**
207 * Implementation of delete_payload_t.get_protocol_id.
208 */
209 static protocol_id_t get_protocol_id (private_delete_payload_t *this)
210 {
211 return (this->protocol_id);
212 }
213
214 /**
215 * Implementation of delete_payload_t.set_spi_size.
216 */
217 static void set_spi_size (private_delete_payload_t *this, u_int8_t spi_size)
218 {
219 this->spi_size = spi_size;
220 }
221
222 /**
223 * Implementation of delete_payload_t.get_spi_size.
224 */
225 static u_int8_t get_spi_size (private_delete_payload_t *this)
226 {
227 return (this->spi_size);
228 }
229
230 /**
231 * Implementation of delete_payload_t.set_spi_count.
232 */
233 static void set_spi_count (private_delete_payload_t *this, u_int16_t spi_count)
234 {
235 this->spi_count = spi_count;
236 }
237
238 /**
239 * Implementation of delete_payload_t.get_spi_count.
240 */
241 static u_int16_t get_spi_count(private_delete_payload_t *this)
242 {
243 return (this->spi_count);
244 }
245
246 /**
247 * Implementation of delete_payload_t.set_spis.
248 */
249 static void set_spis(private_delete_payload_t *this, chunk_t spis)
250 {
251 if (this->spis.ptr != NULL)
252 {
253 chunk_free(&(this->spis));
254 }
255 this->spis.ptr = clalloc(spis.ptr,spis.len);
256 this->spis.len = spis.len;
257 this->payload_length = DELETE_PAYLOAD_HEADER_LENGTH + this->spis.len;
258 }
259
260 /**
261 * Implementation of delete_payload_t.get_spis.
262 */
263 static chunk_t get_spis (private_delete_payload_t *this)
264 {
265 return (this->spis);
266 }
267
268 /**
269 * Implementation of delete_payload_t.add_spi.
270 */
271 static void add_spi(private_delete_payload_t *this, u_int32_t spi)
272 {
273 /* only add SPIs if AH|ESP, ignore others */
274 if (this->protocol_id == PROTO_AH || this->protocol_id == PROTO_ESP)
275 {
276 this->spi_count += 1;
277 this->spis.len += this->spi_size;
278 this->spis.ptr = realloc(this->spis.ptr, this->spis.len);
279 *(u_int32_t*)(this->spis.ptr + (this->spis.len / this->spi_size - 1)) = spi;
280 }
281 }
282
283 /**
284 * Implementation of delete_payload_t.create_spi_iterator.
285 */
286 static iterator_t* create_spi_iterator(private_delete_payload_t *this)
287 {
288 int i;
289
290 if (this->spi_list == NULL)
291 {
292 this->spi_list = linked_list_create();
293 /* only parse SPIs if AH|ESP */
294 if (this->protocol_id == PROTO_AH || this->protocol_id == PROTO_ESP)
295 {
296 for (i = 0; i < this->spi_count; i++)
297 {
298 u_int32_t spi = *(u_int32_t*)(this->spis.ptr + i * this->spi_size);
299 this->spi_list->insert_last(this->spi_list, (void*)spi);
300 }
301 }
302 }
303 return this->spi_list->create_iterator(this->spi_list, TRUE);
304 }
305
306 /**
307 * Implementation of payload_t.destroy and delete_payload_t.destroy.
308 */
309 static void destroy(private_delete_payload_t *this)
310 {
311 if (this->spis.ptr != NULL)
312 {
313 chunk_free(&this->spis);
314 }
315 if (this->spi_list)
316 {
317 this->spi_list->destroy(this->spi_list);
318 }
319 free(this);
320 }
321
322 /*
323 * Described in header
324 */
325 delete_payload_t *delete_payload_create(protocol_id_t protocol_id)
326 {
327 private_delete_payload_t *this = malloc_thing(private_delete_payload_t);
328
329 /* interface functions */
330 this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
331 this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
332 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
333 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
334 this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
335 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
336 this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
337
338 /* public functions */
339 this->public.destroy = (void (*) (delete_payload_t *)) destroy;
340 this->public.set_protocol_id = (void (*) (delete_payload_t *,protocol_id_t)) set_protocol_id;
341 this->public.get_protocol_id = (protocol_id_t (*) (delete_payload_t *)) get_protocol_id;
342 this->public.set_spi_size = (void (*) (delete_payload_t *,u_int8_t)) set_spi_size;
343 this->public.get_spi_size = (u_int8_t (*) (delete_payload_t *)) get_spi_size;
344 this->public.set_spi_count = (void (*) (delete_payload_t *,u_int16_t)) set_spi_count;
345 this->public.get_spi_count = (u_int16_t (*) (delete_payload_t *)) get_spi_count;
346 this->public.set_spis = (void (*) (delete_payload_t *,chunk_t)) set_spis;
347 this->public.get_spis = (chunk_t (*) (delete_payload_t *)) get_spis;
348 this->public.add_spi = (void (*) (delete_payload_t *,u_int32_t))add_spi;
349 this->public.create_spi_iterator = (iterator_t* (*) (delete_payload_t *)) create_spi_iterator;
350
351 /* private variables */
352 this->critical = FALSE;
353 this->next_payload = NO_PAYLOAD;
354 this->payload_length = DELETE_PAYLOAD_HEADER_LENGTH;
355 this->protocol_id = protocol_id;
356 this->spi_size = protocol_id == PROTO_AH || protocol_id == PROTO_ESP ? 4 : 0;
357 this->spi_count = 0;
358 this->spis = CHUNK_INITIALIZER;
359 this->spi_list = NULL;
360
361 return (&this->public);
362 }