3526038d7ab9264f09b4154b7ba9ee668e7bddad
[strongswan.git] / Source / charon / payloads / notify_payload.c
1 /**
2 * @file notify_payload.c
3 *
4 * @brief Declaration of the class notify_payload_t.
5 *
6 * An object of this type represents an IKEv2 Notify-Payload.
7 *
8 * See section 3.10 of Draft for details of this payload type.
9 *
10 */
11
12 /*
13 * Copyright (C) 2005 Jan Hutter, Martin Willi
14 * Hochschule fuer Technik Rapperswil
15 *
16 * This program is free software; you can redistribute it and/or modify it
17 * under the terms of the GNU General Public License as published by the
18 * Free Software Foundation; either version 2 of the License, or (at your
19 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
20 *
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * for more details.
25 */
26
27 /* offsetof macro */
28 #include <stddef.h>
29
30 #include "notify_payload.h"
31
32 #include "encodings.h"
33 #include "../utils/allocator.h"
34
35 /**
36 * Private data of an notify_payload_t Object
37 *
38 */
39 typedef struct private_notify_payload_s private_notify_payload_t;
40
41 struct private_notify_payload_s {
42 /**
43 * public notify_payload_t interface
44 */
45 notify_payload_t public;
46
47 /**
48 * next payload type
49 */
50 u_int8_t next_payload;
51
52 /**
53 * Critical flag
54 */
55 bool critical;
56
57 /**
58 * Length of this payload
59 */
60 u_int16_t payload_length;
61
62 /**
63 * protocol id
64 */
65 u_int8_t protocol_id;
66
67 /**
68 * spi size
69 */
70 u_int8_t spi_size;
71
72 /**
73 * notify message type
74 */
75 u_int16_t notify_message_type;
76
77 /**
78 * Security parameter index (spi)
79 */
80 chunk_t spi;
81
82 /**
83 * Notification data
84 */
85 chunk_t notification_data;
86
87 /**
88 * @brief Computes the length of this payload.
89 *
90 * @param this calling private_ke_payload_t object
91 * @return
92 * SUCCESS in any case
93 */
94 status_t (*compute_length) (private_notify_payload_t *this);
95 };
96
97 /**
98 * Encoding rules to parse or generate a IKEv2-Notify Payload
99 *
100 * The defined offsets are the positions in a object of type
101 * private_notify_payload_t.
102 *
103 */
104 encoding_rule_t notify_payload_encodings[] = {
105 /* 1 Byte next payload type, stored in the field next_payload */
106 { U_INT_8, offsetof(private_notify_payload_t, next_payload) },
107 /* the critical bit */
108 { FLAG, offsetof(private_notify_payload_t, critical) },
109 /* 7 Bit reserved bits, nowhere stored */
110 { RESERVED_BIT, 0 },
111 { RESERVED_BIT, 0 },
112 { RESERVED_BIT, 0 },
113 { RESERVED_BIT, 0 },
114 { RESERVED_BIT, 0 },
115 { RESERVED_BIT, 0 },
116 { RESERVED_BIT, 0 },
117 /* Length of the whole payload*/
118 { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
119 /* Protocol ID as 8 bit field*/
120 { U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
121 /* SPI Size as 8 bit field*/
122 { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
123 /* Notify message type as 16 bit field*/
124 { U_INT_16, offsetof(private_notify_payload_t, notify_message_type) },
125 /* SPI as variable length field*/
126 { SPI, offsetof(private_notify_payload_t, spi) },
127 /* Key Exchange Data is from variable size */
128 { NOTIFICATION_DATA, offsetof(private_notify_payload_t, notification_data) }
129 };
130
131 /**
132 * Implements payload_t's and notify_payload_t's destroy function.
133 * See #payload_s.destroy or notify_payload_s.destroy for description.
134 */
135 static status_t destroy(private_notify_payload_t *this)
136 {
137 if (this->notification_data.ptr != NULL)
138 {
139 allocator_free(this->notification_data.ptr);
140 }
141 if (this->spi.ptr != NULL)
142 {
143 allocator_free(this->spi.ptr);
144 }
145
146 allocator_free(this);
147 return SUCCESS;
148 }
149
150 /**
151 * Implements payload_t's get_encoding_rules function.
152 * See #payload_s.get_encoding_rules for description.
153 */
154 static status_t get_encoding_rules(private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
155 {
156 *rules = notify_payload_encodings;
157 *rule_count = sizeof(notify_payload_encodings) / sizeof(encoding_rule_t);
158 return SUCCESS;
159 }
160
161 /**
162 * Implements payload_t's get_type function.
163 * See #payload_s.get_type for description.
164 */
165 static payload_type_t get_type(private_notify_payload_t *this)
166 {
167 return KEY_EXCHANGE;
168 }
169
170 /**
171 * Implements payload_t's get_next_type function.
172 * See #payload_s.get_next_type for description.
173 */
174 static payload_type_t get_next_type(private_notify_payload_t *this)
175 {
176 return (this->next_payload);
177 }
178
179 /**
180 * Implements payload_t's set_next_type function.
181 * See #payload_s.set_next_type for description.
182 */
183 static status_t set_next_type(private_notify_payload_t *this,payload_type_t type)
184 {
185 this->next_payload = type;
186 return SUCCESS;
187 }
188
189 /**
190 * Implements payload_t's get_length function.
191 * See #payload_s.get_length for description.
192 */
193 static size_t get_length(private_notify_payload_t *this)
194 {
195 this->compute_length(this);
196 return this->payload_length;
197 }
198
199 /**
200 * Implements private_ke_payload_t's compute_length function.
201 * See #private_ke_payload_s.compute_length for description.
202 */
203 static status_t compute_length (private_notify_payload_t *this)
204 {
205 size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH;
206 if (this->notification_data.ptr != NULL)
207 {
208 length += this->notification_data.len;
209 }
210 if (this->spi.ptr != NULL)
211 {
212 length += this->spi.len;
213 }
214
215 this->payload_length = length;
216
217 return SUCCESS;
218 }
219
220
221 /**
222 * Implements notify_payload_t's get_protocol_id function.
223 * See #notify_payload_s.get_protocol_id for description.
224 */
225 u_int8_t get_protocol_id(private_notify_payload_t *this)
226 {
227 return this->protocol_id;
228 }
229
230 /**
231 * Implements notify_payload_t's set_protocol_id function.
232 * See #notify_payload_s.set_protocol_id for description.
233 */
234 status_t set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id)
235 {
236 this->protocol_id = protocol_id;
237 return SUCCESS;
238 }
239
240 /**
241 * Implements notify_payload_t's get_notification_data function.
242 * See #notify_payload_s.get_notification_data for description.
243 */
244 u_int16_t get_notify_message_type(private_notify_payload_t *this)
245 {
246 return this->notify_message_type;
247 }
248
249 /**
250 * Implements notify_payload_t's get_notification_data function.
251 * See #notify_payload_s.get_notification_data for description.
252 */
253 status_t set_notify_message_type(private_notify_payload_t *this, u_int16_t notify_message_type)
254 {
255 this->notify_message_type = notify_message_type;
256 return SUCCESS;
257 }
258
259 /**
260 * Implements notify_payload_t's get_spi function.
261 * See #notify_payload_s.get_spi for description.
262 */
263 chunk_t get_spi(private_notify_payload_t *this)
264 {
265 return (this->spi);
266 }
267
268 /**
269 * Implements notify_payload_t's set_spi function.
270 * See #notify_payload_s.set_spi for description.
271 */
272 status_t set_spi(private_notify_payload_t *this, chunk_t spi)
273 {
274 /* destroy existing data first */
275 if (this->spi.ptr != NULL)
276 {
277 /* free existing value */
278 allocator_free(this->spi.ptr);
279 this->spi.ptr = NULL;
280 this->spi.len = 0;
281
282 }
283
284 this->spi.ptr = allocator_clone_bytes(spi.ptr,spi.len);
285 if (this->spi.ptr == NULL)
286 {
287 return OUT_OF_RES;
288 }
289 this->spi.len = spi.len;
290 this->spi_size = spi.len;
291 this->compute_length(this);
292
293 return SUCCESS;
294 }
295
296
297 /**
298 * Implements notify_payload_t's get_notification_data function.
299 * See #notify_payload_s.get_notification_data for description.
300 */
301 chunk_t get_notification_data(private_notify_payload_t *this)
302 {
303 return (this->notification_data);
304 }
305
306 /**
307 * Implements notify_payload_t's get_notification_data function.
308 * See #notify_payload_s.get_notification_data for description.
309 */
310 status_t set_notification_data(private_notify_payload_t *this, chunk_t notification_data)
311 {
312 /* destroy existing data first */
313 if (this->notification_data.ptr != NULL)
314 {
315 /* free existing value */
316 allocator_free(this->notification_data.ptr);
317 this->notification_data.ptr = NULL;
318 this->notification_data.len = 0;
319
320 }
321
322 this->notification_data.ptr = allocator_clone_bytes(notification_data.ptr,notification_data.len);
323 if (this->notification_data.ptr == NULL)
324 {
325 return OUT_OF_RES;
326 }
327 this->notification_data.len = notification_data.len;
328 this->compute_length(this);
329
330 return SUCCESS;
331 }
332
333 /*
334 * Described in header
335 */
336 notify_payload_t *notify_payload_create()
337 {
338 private_notify_payload_t *this = allocator_alloc_thing(private_notify_payload_t);
339 if (this == NULL)
340 {
341 return NULL;
342 }
343 /* interface functions */
344 this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
345 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
346 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
347 this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_next_type;
348 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
349 this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
350
351 /* public functions */
352 this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id;
353 this->public.set_protocol_id = (status_t (*) (notify_payload_t *,u_int8_t)) set_protocol_id;
354 this->public.get_notify_message_type = (u_int16_t (*) (notify_payload_t *)) get_notify_message_type;
355 this->public.set_notify_message_type = (status_t (*) (notify_payload_t *,u_int16_t)) set_notify_message_type;
356 this->public.get_spi = (chunk_t (*) (notify_payload_t *)) get_spi;
357 this->public.set_spi = (status_t (*) (notify_payload_t *,chunk_t)) set_spi;
358 this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data;
359 this->public.set_notification_data = (status_t (*) (notify_payload_t *,chunk_t)) set_notification_data;
360 this->public.destroy = (status_t (*) (notify_payload_t *)) destroy;
361
362 /* private functions */
363 this->compute_length = compute_length;
364
365 /* set default values of the fields */
366 this->critical = NOTIFY_PAYLOAD_CRITICAL_FLAG;
367 this->next_payload = NO_PAYLOAD;
368 this->payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH;
369 this->protocol_id = 0;
370 this->notify_message_type = 0;
371 this->spi.ptr = NULL;
372 this->spi.len = 0;
373 this->notification_data.ptr = NULL;
374 this->notification_data.len = 0;
375
376 return (&(this->public));
377 }
378