fixed CHILD_SA rekeying/delete bug on 64bit machines
[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.get_protocol_id.
200 */
201 static protocol_id_t get_protocol_id (private_delete_payload_t *this)
202 {
203 return (this->protocol_id);
204 }
205
206 /**
207 * Implementation of delete_payload_t.add_spi.
208 */
209 static void add_spi(private_delete_payload_t *this, u_int32_t spi)
210 {
211 /* only add SPIs if AH|ESP, ignore others */
212 if (this->protocol_id == PROTO_AH || this->protocol_id == PROTO_ESP)
213 {
214 this->spi_count += 1;
215 this->spis.len += this->spi_size;
216 this->spis.ptr = realloc(this->spis.ptr, this->spis.len);
217 *(u_int32_t*)(this->spis.ptr + (this->spis.len / this->spi_size - 1)) = spi;
218 if (this->spi_list)
219 {
220 /* reset SPI iterator list */
221 this->spi_list->destroy(this->spi_list);
222 this->spi_list = NULL;
223 }
224 }
225 }
226
227 /**
228 * Implementation of delete_payload_t.create_spi_iterator.
229 */
230 static iterator_t* create_spi_iterator(private_delete_payload_t *this)
231 {
232 int i;
233
234 if (this->spi_list == NULL)
235 {
236 this->spi_list = linked_list_create();
237 /* only parse SPIs if AH|ESP */
238 if (this->protocol_id == PROTO_AH || this->protocol_id == PROTO_ESP)
239 {
240 for (i = 0; i < this->spi_count; i++)
241 {
242 this->spi_list->insert_last(this->spi_list, this->spis.ptr + i *
243 this->spi_size);
244 }
245 }
246 }
247 return this->spi_list->create_iterator(this->spi_list, TRUE);
248 }
249
250 /**
251 * Implementation of payload_t.destroy and delete_payload_t.destroy.
252 */
253 static void destroy(private_delete_payload_t *this)
254 {
255 if (this->spis.ptr != NULL)
256 {
257 chunk_free(&this->spis);
258 }
259 if (this->spi_list)
260 {
261 this->spi_list->destroy(this->spi_list);
262 }
263 free(this);
264 }
265
266 /*
267 * Described in header
268 */
269 delete_payload_t *delete_payload_create(protocol_id_t protocol_id)
270 {
271 private_delete_payload_t *this = malloc_thing(private_delete_payload_t);
272
273 /* interface functions */
274 this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
275 this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
276 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
277 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
278 this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
279 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
280 this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
281
282 /* public functions */
283 this->public.destroy = (void (*) (delete_payload_t *)) destroy;
284 this->public.get_protocol_id = (protocol_id_t (*) (delete_payload_t *)) get_protocol_id;
285 this->public.add_spi = (void (*) (delete_payload_t *,u_int32_t))add_spi;
286 this->public.create_spi_iterator = (iterator_t* (*) (delete_payload_t *)) create_spi_iterator;
287
288 /* private variables */
289 this->critical = FALSE;
290 this->next_payload = NO_PAYLOAD;
291 this->payload_length = DELETE_PAYLOAD_HEADER_LENGTH;
292 this->protocol_id = protocol_id;
293 this->spi_size = protocol_id == PROTO_AH || protocol_id == PROTO_ESP ? 4 : 0;
294 this->spi_count = 0;
295 this->spis = chunk_empty;
296 this->spi_list = NULL;
297
298 return (&this->public);
299 }