2 * @file notify_payload.c
4 * @brief Implementation of notify_payload_t.
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 #include "notify_payload.h"
28 #include <encoding/payloads/encodings.h>
29 #include <utils/allocator.h>
32 * String mappings for notify_message_type_t.
34 mapping_t notify_message_type_m
[] = {
35 {UNSUPPORTED_CRITICAL_PAYLOAD
, "UNSUPPORTED_CRITICAL_PAYLOAD"},
36 {INVALID_IKE_SPI
, "INVALID_IKE_SPI"},
37 {INVALID_MAJOR_VERSION
, "INVALID_MAJOR_VERSION"},
38 {INVALID_SYNTAX
, "INVALID_SYNTAX"},
39 {INVALID_MESSAGE_ID
, "MODP_2048_BIT"},
40 {INVALID_SPI
, "INVALID_SPI"},
41 {NO_PROPOSAL_CHOSEN
, "NO_PROPOSAL_CHOSEN"},
42 {INVALID_KE_PAYLOAD
, "INVALID_KE_PAYLOAD"},
43 {AUTHENTICATION_FAILED
, "AUTHENTICATION_FAILED"},
44 {SINGLE_PAIR_REQUIRED
, "SINGLE_PAIR_REQUIRED"},
45 {NO_ADDITIONAL_SAS
, "NO_ADDITIONAL_SAS"},
46 {INTERNAL_ADDRESS_FAILURE
, "INTERNAL_ADDRESS_FAILURE"},
47 {FAILED_CP_REQUIRED
, "FAILED_CP_REQUIRED"},
48 {TS_UACCEPTABLE
, "TS_UACCEPTABLE"},
49 {INVALID_SELECTORS
, "INVALID_SELECTORS"},
53 typedef struct private_notify_payload_t private_notify_payload_t
;
56 * Private data of an notify_payload_t object.
59 struct private_notify_payload_t
{
61 * Public notify_payload_t interface.
63 notify_payload_t
public;
68 u_int8_t next_payload
;
76 * Length of this payload.
78 u_int16_t payload_length
;
91 * Notify message type.
93 u_int16_t notify_message_type
;
96 * Security parameter index (spi).
103 chunk_t notification_data
;
106 * @brief Computes the length of this payload.
108 * @param this calling private_ke_payload_t object
110 void (*compute_length
) (private_notify_payload_t
*this);
114 * Encoding rules to parse or generate a IKEv2-Notify Payload.
116 * The defined offsets are the positions in a object of type
117 * private_notify_payload_t.
120 encoding_rule_t notify_payload_encodings
[] = {
121 /* 1 Byte next payload type, stored in the field next_payload */
122 { U_INT_8
, offsetof(private_notify_payload_t
, next_payload
) },
123 /* the critical bit */
124 { FLAG
, offsetof(private_notify_payload_t
, critical
) },
125 /* 7 Bit reserved bits, nowhere stored */
133 /* Length of the whole payload*/
134 { PAYLOAD_LENGTH
, offsetof(private_notify_payload_t
, payload_length
) },
135 /* Protocol ID as 8 bit field*/
136 { U_INT_8
, offsetof(private_notify_payload_t
, protocol_id
) },
137 /* SPI Size as 8 bit field*/
138 { SPI_SIZE
, offsetof(private_notify_payload_t
, spi_size
) },
139 /* Notify message type as 16 bit field*/
140 { U_INT_16
, offsetof(private_notify_payload_t
, notify_message_type
) },
141 /* SPI as variable length field*/
142 { SPI
, offsetof(private_notify_payload_t
, spi
) },
143 /* Key Exchange Data is from variable size */
144 { NOTIFICATION_DATA
, offsetof(private_notify_payload_t
, notification_data
) }
149 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
150 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
151 ! Next Payload !C! RESERVED ! Payload Length !
152 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
153 ! Protocol ID ! SPI Size ! Notify Message Type !
154 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
156 ~ Security Parameter Index (SPI) ~
158 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
160 ~ Notification Data ~
162 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
166 * Implementation of payload_t.verify.
168 static status_t
verify(private_notify_payload_t
*this)
172 /* critical bit is set! */
175 if (this->protocol_id
> 3)
177 /* reserved for future use */
181 /* notify message types and data is not getting checked in here */
187 * Implementation of payload_t.get_encoding_rules.
189 static void get_encoding_rules(private_notify_payload_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
191 *rules
= notify_payload_encodings
;
192 *rule_count
= sizeof(notify_payload_encodings
) / sizeof(encoding_rule_t
);
196 * Implementation of payload_t.get_type.
198 static payload_type_t
get_type(private_notify_payload_t
*this)
204 * Implementation of payload_t.get_next_type.
206 static payload_type_t
get_next_type(private_notify_payload_t
*this)
208 return (this->next_payload
);
212 * Implementation of payload_t.set_next_type.
214 static void set_next_type(private_notify_payload_t
*this,payload_type_t type
)
216 this->next_payload
= type
;
220 * Implementation of payload_t.get_length.
222 static size_t get_length(private_notify_payload_t
*this)
224 this->compute_length(this);
225 return this->payload_length
;
229 * Implementation of private_notify_payload_t.compute_length.
231 static void compute_length (private_notify_payload_t
*this)
233 size_t length
= NOTIFY_PAYLOAD_HEADER_LENGTH
;
234 if (this->notification_data
.ptr
!= NULL
)
236 length
+= this->notification_data
.len
;
238 if (this->spi
.ptr
!= NULL
)
240 length
+= this->spi
.len
;
243 this->payload_length
= length
;
248 * Implementation of notify_payload_t.get_protocol_id.
250 static u_int8_t
get_protocol_id(private_notify_payload_t
*this)
252 return this->protocol_id
;
256 * Implementation of notify_payload_t.set_protocol_id.
258 static void set_protocol_id(private_notify_payload_t
*this, u_int8_t protocol_id
)
260 this->protocol_id
= protocol_id
;
264 * Implementation of notify_payload_t.get_notify_message_type.
266 static u_int16_t
get_notify_message_type(private_notify_payload_t
*this)
268 return this->notify_message_type
;
272 * Implementation of notify_payload_t.set_notify_message_type.
274 static void set_notify_message_type(private_notify_payload_t
*this, u_int16_t notify_message_type
)
276 this->notify_message_type
= notify_message_type
;
280 * Implementation of notify_payload_t.get_spi.
282 static chunk_t
get_spi(private_notify_payload_t
*this)
288 * Implementation of notify_payload_t.set_spi.
290 static void set_spi(private_notify_payload_t
*this, chunk_t spi
)
292 /* destroy existing data first */
293 if (this->spi
.ptr
!= NULL
)
295 /* free existing value */
296 allocator_free(this->spi
.ptr
);
297 this->spi
.ptr
= NULL
;
302 this->spi
.ptr
= allocator_clone_bytes(spi
.ptr
,spi
.len
);
304 this->spi
.len
= spi
.len
;
305 this->spi_size
= spi
.len
;
306 this->compute_length(this);
311 * Implementation of notify_payload_t.get_notification_data.
313 static chunk_t
get_notification_data(private_notify_payload_t
*this)
315 return (this->notification_data
);
319 * Implementation of notify_payload_t.set_notification_data.
321 static status_t
set_notification_data(private_notify_payload_t
*this, chunk_t notification_data
)
323 /* destroy existing data first */
324 if (this->notification_data
.ptr
!= NULL
)
326 /* free existing value */
327 allocator_free(this->notification_data
.ptr
);
328 this->notification_data
.ptr
= NULL
;
329 this->notification_data
.len
= 0;
333 this->notification_data
.ptr
= allocator_clone_bytes(notification_data
.ptr
,notification_data
.len
);
334 this->notification_data
.len
= notification_data
.len
;
335 this->compute_length(this);
341 * Implementation of notify_payload_t.destroy and notify_payload_t.destroy.
343 static status_t
destroy(private_notify_payload_t
*this)
345 if (this->notification_data
.ptr
!= NULL
)
347 allocator_free(this->notification_data
.ptr
);
349 if (this->spi
.ptr
!= NULL
)
351 allocator_free(this->spi
.ptr
);
354 allocator_free(this);
359 * Described in header
361 notify_payload_t
*notify_payload_create()
363 private_notify_payload_t
*this = allocator_alloc_thing(private_notify_payload_t
);
365 /* interface functions */
366 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
367 this->public.payload_interface
.get_encoding_rules
= (void (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
368 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
369 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
370 this->public.payload_interface
.set_next_type
= (void (*) (payload_t
*,payload_type_t
)) set_next_type
;
371 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
372 this->public.payload_interface
.destroy
= (void (*) (payload_t
*))destroy
;
374 /* public functions */
375 this->public.get_protocol_id
= (u_int8_t (*) (notify_payload_t
*)) get_protocol_id
;
376 this->public.set_protocol_id
= (void (*) (notify_payload_t
*,u_int8_t
)) set_protocol_id
;
377 this->public.get_notify_message_type
= (u_int16_t (*) (notify_payload_t
*)) get_notify_message_type
;
378 this->public.set_notify_message_type
= (void (*) (notify_payload_t
*,u_int16_t
)) set_notify_message_type
;
379 this->public.get_spi
= (chunk_t (*) (notify_payload_t
*)) get_spi
;
380 this->public.set_spi
= (void (*) (notify_payload_t
*,chunk_t
)) set_spi
;
381 this->public.get_notification_data
= (chunk_t (*) (notify_payload_t
*)) get_notification_data
;
382 this->public.set_notification_data
= (void (*) (notify_payload_t
*,chunk_t
)) set_notification_data
;
383 this->public.destroy
= (void (*) (notify_payload_t
*)) destroy
;
385 /* private functions */
386 this->compute_length
= compute_length
;
388 /* set default values of the fields */
389 this->critical
= NOTIFY_PAYLOAD_CRITICAL_FLAG
;
390 this->next_payload
= NO_PAYLOAD
;
391 this->payload_length
= NOTIFY_PAYLOAD_HEADER_LENGTH
;
392 this->protocol_id
= 0;
393 this->notify_message_type
= 0;
394 this->spi
.ptr
= NULL
;
396 this->notification_data
.ptr
= NULL
;
397 this->notification_data
.len
= 0;
399 return (&(this->public));
403 * Described in header.
405 notify_payload_t
*notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id
, notify_message_type_t notify_message_type
)
407 notify_payload_t
*notify
= notify_payload_create();
409 notify
->set_notify_message_type(notify
,notify_message_type
);
410 notify
->set_protocol_id(notify
,protocol_id
);