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
25 #include "notify_payload.h"
28 #include <encoding/payloads/encodings.h>
31 * String mappings for notify_message_type_t.
33 mapping_t notify_message_type_m
[] = {
34 {UNSUPPORTED_CRITICAL_PAYLOAD
, "UNSUPPORTED_CRITICAL_PAYLOAD"},
35 {INVALID_IKE_SPI
, "INVALID_IKE_SPI"},
36 {INVALID_MAJOR_VERSION
, "INVALID_MAJOR_VERSION"},
37 {INVALID_SYNTAX
, "INVALID_SYNTAX"},
38 {INVALID_MESSAGE_ID
, "INVALID_MESSAGE_ID"},
39 {INVALID_SPI
, "INVALID_SPI"},
40 {NO_PROPOSAL_CHOSEN
, "NO_PROPOSAL_CHOSEN"},
41 {INVALID_KE_PAYLOAD
, "INVALID_KE_PAYLOAD"},
42 {AUTHENTICATION_FAILED
, "AUTHENTICATION_FAILED"},
43 {SINGLE_PAIR_REQUIRED
, "SINGLE_PAIR_REQUIRED"},
44 {NO_ADDITIONAL_SAS
, "NO_ADDITIONAL_SAS"},
45 {INTERNAL_ADDRESS_FAILURE
, "INTERNAL_ADDRESS_FAILURE"},
46 {FAILED_CP_REQUIRED
, "FAILED_CP_REQUIRED"},
47 {TS_UACCEPTABLE
, "TS_UACCEPTABLE"},
48 {INVALID_SELECTORS
, "INVALID_SELECTORS"},
49 {INITIAL_CONTACT
, "INITIAL_CONTACT"},
50 {SET_WINDOW_SIZE
, "SET_WINDOW_SIZE"},
54 typedef struct private_notify_payload_t private_notify_payload_t
;
57 * Private data of an notify_payload_t object.
60 struct private_notify_payload_t
{
62 * Public notify_payload_t interface.
64 notify_payload_t
public;
69 u_int8_t next_payload
;
77 * Length of this payload.
79 u_int16_t payload_length
;
92 * Notify message type.
94 u_int16_t notify_message_type
;
97 * Security parameter index (spi).
104 chunk_t notification_data
;
112 * @brief Computes the length of this payload.
114 * @param this calling private_ke_payload_t object
116 void (*compute_length
) (private_notify_payload_t
*this);
120 * Encoding rules to parse or generate a IKEv2-Notify Payload.
122 * The defined offsets are the positions in a object of type
123 * private_notify_payload_t.
126 encoding_rule_t notify_payload_encodings
[] = {
127 /* 1 Byte next payload type, stored in the field next_payload */
128 { U_INT_8
, offsetof(private_notify_payload_t
, next_payload
) },
129 /* the critical bit */
130 { FLAG
, offsetof(private_notify_payload_t
, critical
) },
131 /* 7 Bit reserved bits, nowhere stored */
139 /* Length of the whole payload*/
140 { PAYLOAD_LENGTH
, offsetof(private_notify_payload_t
, payload_length
) },
141 /* Protocol ID as 8 bit field*/
142 { U_INT_8
, offsetof(private_notify_payload_t
, protocol_id
) },
143 /* SPI Size as 8 bit field*/
144 { SPI_SIZE
, offsetof(private_notify_payload_t
, spi_size
) },
145 /* Notify message type as 16 bit field*/
146 { U_INT_16
, offsetof(private_notify_payload_t
, notify_message_type
) },
147 /* SPI as variable length field*/
148 { SPI
, offsetof(private_notify_payload_t
, spi
) },
149 /* Key Exchange Data is from variable size */
150 { NOTIFICATION_DATA
, offsetof(private_notify_payload_t
, notification_data
) }
155 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
156 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
157 ! Next Payload !C! RESERVED ! Payload Length !
158 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
159 ! Protocol ID ! SPI Size ! Notify Message Type !
160 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
162 ~ Security Parameter Index (SPI) ~
164 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
166 ~ Notification Data ~
168 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
172 * Implementation of payload_t.verify.
174 static status_t
verify(private_notify_payload_t
*this)
176 if (this->protocol_id
> 3)
178 /* reserved for future use */
182 /* TODO: Check all kinds of notify */
184 if (this->notify_message_type
== INVALID_KE_PAYLOAD
)
186 /* check notification data */
187 diffie_hellman_group_t dh_group
;
188 if (this->notification_data
.len
!= 2)
192 dh_group
= ntohs(*((u_int16_t
*)this->notification_data
.ptr
));
205 this->logger
->log(this->logger
, ERROR
, "Bad DH group (%d)", dh_group
);
213 * Implementation of payload_t.get_encoding_rules.
215 static void get_encoding_rules(private_notify_payload_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
217 *rules
= notify_payload_encodings
;
218 *rule_count
= sizeof(notify_payload_encodings
) / sizeof(encoding_rule_t
);
222 * Implementation of payload_t.get_type.
224 static payload_type_t
get_type(private_notify_payload_t
*this)
230 * Implementation of payload_t.get_next_type.
232 static payload_type_t
get_next_type(private_notify_payload_t
*this)
234 return (this->next_payload
);
238 * Implementation of payload_t.set_next_type.
240 static void set_next_type(private_notify_payload_t
*this,payload_type_t type
)
242 this->next_payload
= type
;
246 * Implementation of payload_t.get_length.
248 static size_t get_length(private_notify_payload_t
*this)
250 this->compute_length(this);
251 return this->payload_length
;
255 * Implementation of private_notify_payload_t.compute_length.
257 static void compute_length (private_notify_payload_t
*this)
259 size_t length
= NOTIFY_PAYLOAD_HEADER_LENGTH
;
260 if (this->notification_data
.ptr
!= NULL
)
262 length
+= this->notification_data
.len
;
264 if (this->spi
.ptr
!= NULL
)
266 length
+= this->spi
.len
;
269 this->payload_length
= length
;
274 * Implementation of notify_payload_t.get_protocol_id.
276 static u_int8_t
get_protocol_id(private_notify_payload_t
*this)
278 return this->protocol_id
;
282 * Implementation of notify_payload_t.set_protocol_id.
284 static void set_protocol_id(private_notify_payload_t
*this, u_int8_t protocol_id
)
286 this->protocol_id
= protocol_id
;
290 * Implementation of notify_payload_t.get_notify_message_type.
292 static u_int16_t
get_notify_message_type(private_notify_payload_t
*this)
294 return this->notify_message_type
;
298 * Implementation of notify_payload_t.set_notify_message_type.
300 static void set_notify_message_type(private_notify_payload_t
*this, u_int16_t notify_message_type
)
302 this->notify_message_type
= notify_message_type
;
306 * Implementation of notify_payload_t.get_spi.
308 static chunk_t
get_spi(private_notify_payload_t
*this)
314 * Implementation of notify_payload_t.set_spi.
316 static void set_spi(private_notify_payload_t
*this, chunk_t spi
)
318 /* destroy existing data first */
319 if (this->spi
.ptr
!= NULL
)
321 /* free existing value */
323 this->spi
.ptr
= NULL
;
328 this->spi
.ptr
= clalloc(spi
.ptr
,spi
.len
);
330 this->spi
.len
= spi
.len
;
331 this->spi_size
= spi
.len
;
332 this->compute_length(this);
337 * Implementation of notify_payload_t.get_notification_data.
339 static chunk_t
get_notification_data(private_notify_payload_t
*this)
341 return (this->notification_data
);
345 * Implementation of notify_payload_t.set_notification_data.
347 static status_t
set_notification_data(private_notify_payload_t
*this, chunk_t notification_data
)
349 /* destroy existing data first */
350 if (this->notification_data
.ptr
!= NULL
)
352 /* free existing value */
353 free(this->notification_data
.ptr
);
354 this->notification_data
.ptr
= NULL
;
355 this->notification_data
.len
= 0;
359 this->notification_data
.ptr
= clalloc(notification_data
.ptr
,notification_data
.len
);
360 this->notification_data
.len
= notification_data
.len
;
361 this->compute_length(this);
367 * Implementation of notify_payload_t.destroy and notify_payload_t.destroy.
369 static status_t
destroy(private_notify_payload_t
*this)
371 if (this->notification_data
.ptr
!= NULL
)
373 free(this->notification_data
.ptr
);
375 if (this->spi
.ptr
!= NULL
)
385 * Described in header
387 notify_payload_t
*notify_payload_create()
389 private_notify_payload_t
*this = malloc_thing(private_notify_payload_t
);
391 /* interface functions */
392 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
393 this->public.payload_interface
.get_encoding_rules
= (void (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
394 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
395 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
396 this->public.payload_interface
.set_next_type
= (void (*) (payload_t
*,payload_type_t
)) set_next_type
;
397 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
398 this->public.payload_interface
.destroy
= (void (*) (payload_t
*))destroy
;
400 /* public functions */
401 this->public.get_protocol_id
= (u_int8_t (*) (notify_payload_t
*)) get_protocol_id
;
402 this->public.set_protocol_id
= (void (*) (notify_payload_t
*,u_int8_t
)) set_protocol_id
;
403 this->public.get_notify_message_type
= (u_int16_t (*) (notify_payload_t
*)) get_notify_message_type
;
404 this->public.set_notify_message_type
= (void (*) (notify_payload_t
*,u_int16_t
)) set_notify_message_type
;
405 this->public.get_spi
= (chunk_t (*) (notify_payload_t
*)) get_spi
;
406 this->public.set_spi
= (void (*) (notify_payload_t
*,chunk_t
)) set_spi
;
407 this->public.get_notification_data
= (chunk_t (*) (notify_payload_t
*)) get_notification_data
;
408 this->public.set_notification_data
= (void (*) (notify_payload_t
*,chunk_t
)) set_notification_data
;
409 this->public.destroy
= (void (*) (notify_payload_t
*)) destroy
;
411 /* private functions */
412 this->compute_length
= compute_length
;
414 /* set default values of the fields */
415 this->critical
= FALSE
;
416 this->next_payload
= NO_PAYLOAD
;
417 this->payload_length
= NOTIFY_PAYLOAD_HEADER_LENGTH
;
418 this->protocol_id
= 0;
419 this->notify_message_type
= 0;
420 this->spi
.ptr
= NULL
;
423 this->notification_data
.ptr
= NULL
;
424 this->notification_data
.len
= 0;
425 this->logger
= logger_manager
->get_logger(logger_manager
, PAYLOAD
);
427 return (&(this->public));
431 * Described in header.
433 notify_payload_t
*notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id
, notify_message_type_t notify_message_type
)
435 notify_payload_t
*notify
= notify_payload_create();
437 notify
->set_notify_message_type(notify
,notify_message_type
);
438 notify
->set_protocol_id(notify
,protocol_id
);