4 * @brief Class message_t. Object of this type represents an IKEv2-Message.
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
29 #include "ike_sa_id.h"
30 #include "generator.h"
31 #include "utils/linked_list.h"
32 #include "utils/allocator.h"
33 #include "utils/logger_manager.h"
34 #include "payloads/encodings.h"
35 #include "payloads/payload.h"
40 * Supported payload entry used in message_rule_t
43 typedef struct supported_payload_entry_s supported_payload_entry_t
;
45 struct supported_payload_entry_s
{
49 payload_type_t payload_type
;
52 * Minimal occurence of this payload
57 * Max occurence of this payload
63 * Message Rule used to find out which payloads are supported by each message type
66 typedef struct message_rule_s message_rule_t
;
68 struct message_rule_s
{
72 exchange_type_t exchange_type
;
75 * Is message a request or response
79 * Number of supported payloads
81 size_t supported_payloads_count
;
83 * Pointer to first supported payload entry
85 supported_payload_entry_t
*supported_payloads
;
89 supported_payload_entry_t supported_ike_sa_init_i_payloads
[] =
91 {SECURITY_ASSOCIATION
,1,1},
96 supported_payload_entry_t supported_ike_sa_init_r_payloads
[] =
98 {SECURITY_ASSOCIATION
,1,1},
103 message_rule_t message_rules
[] = {
104 {IKE_SA_INIT
,TRUE
,sizeof(supported_ike_sa_init_i_payloads
),supported_ike_sa_init_i_payloads
},
105 {IKE_SA_INIT
,FALSE
,sizeof(supported_ike_sa_init_r_payloads
),supported_ike_sa_init_r_payloads
}
110 * Entry for a payload in the internal used linked list
113 typedef struct payload_entry_s payload_entry_t
;
115 struct payload_entry_s
{
119 payload_type_t payload_type
;
121 * Data struct holding the data of given payload
128 * Private data of an message_t object
130 typedef struct private_message_s private_message_t
;
132 struct private_message_s
{
135 * Public part of a message_t object
141 * Minor version of message
143 u_int8_t major_version
;
146 * Major version of message
148 u_int8_t minor_version
;
151 * First Payload in message
153 payload_type_t first_payload
;
156 * Assigned exchange type
158 exchange_type_t exchange_type
;
161 * TRUE if message is from original initiator, FALSE otherwise.
163 bool original_initiator
;
166 * TRUE if message is request.
167 * FALSE if message is reply.
172 * Message ID of this message
174 u_int32_t message_id
;
177 * ID of assigned IKE_SA
179 ike_sa_id_t
*ike_sa_id
;
182 * Assigned UDP packet.
184 * Stores incoming packet or last generated one.
189 * Linked List where payload data are stored in
191 linked_list_t
*payloads
;
194 * Assigned parser to parse Header and Body of this message
199 * logger for this message
207 * Implements message_t's set_ike_sa_id function.
208 * See #message_s.set_ike_sa_id.
210 static status_t
set_ike_sa_id (private_message_t
*this,ike_sa_id_t
*ike_sa_id
)
213 status
= ike_sa_id
->clone(ike_sa_id
,&(this->ike_sa_id
));
218 * Implements message_t's get_ike_sa_id function.
219 * See #message_s.get_ike_sa_id.
221 static status_t
get_ike_sa_id (private_message_t
*this,ike_sa_id_t
**ike_sa_id
)
224 if (this->ike_sa_id
== NULL
)
228 status
= this->ike_sa_id
->clone(this->ike_sa_id
,ike_sa_id
);
234 * Implements message_t's set_message_id function.
235 * See #message_s.set_message_id.
237 static status_t
set_message_id (private_message_t
*this,u_int32_t message_id
)
239 this->message_id
= message_id
;
245 * Implements message_t's set_message_id function.
246 * See #message_s.set_message_id.
248 static u_int32_t
get_message_id (private_message_t
*this)
250 return this->message_id
;
254 * Implements message_t's set_major_version function.
255 * See #message_s.set_major_version.
257 static status_t
set_major_version (private_message_t
*this,u_int8_t major_version
)
259 this->major_version
= major_version
;
265 * Implements message_t's get_major_version function.
266 * See #message_s.get_major_version.
268 static u_int8_t
get_major_version (private_message_t
*this)
270 return this->major_version
;
274 * Implements message_t's set_minor_version function.
275 * See #message_s.set_minor_version.
277 static status_t
set_minor_version (private_message_t
*this,u_int8_t minor_version
)
279 this->minor_version
= minor_version
;
285 * Implements message_t's get_minor_version function.
286 * See #message_s.get_minor_version.
288 static u_int8_t
get_minor_version (private_message_t
*this)
290 return this->minor_version
;
294 * Implements message_t's set_exchange_type function.
295 * See #message_s.set_exchange_type.
297 static status_t
set_exchange_type (private_message_t
*this,exchange_type_t exchange_type
)
299 this->exchange_type
= exchange_type
;
305 * Implements message_t's get_exchange_type function.
306 * See #message_s.get_exchange_type.
308 static exchange_type_t
get_exchange_type (private_message_t
*this)
310 return this->exchange_type
;
314 * Implements message_t's set_original_initiator function.
315 * See #message_s.set_original_initiator.
317 static status_t
set_original_initiator (private_message_t
*this,bool original_initiator
)
319 this->original_initiator
= original_initiator
;
324 * Implements message_t's get_original_initiator function.
325 * See #message_s.get_original_initiator.
327 static exchange_type_t
get_original_initiator (private_message_t
*this)
329 return this->original_initiator
;
333 * Implements message_t's set_request function.
334 * See #message_s.set_request.
336 static status_t
set_request (private_message_t
*this,bool request
)
338 this->is_request
= request
;
343 * Implements message_t's get_request function.
344 * See #message_s.get_request.
346 static exchange_type_t
get_request (private_message_t
*this)
348 return this->is_request
;
351 static status_t
add_payload(private_message_t
*this, payload_t
*payload
)
353 if (this->payloads
->insert_last(this->payloads
, payload
) != SUCCESS
)
360 static status_t
set_source(private_message_t
*this, host_t
*host
)
362 if (this->packet
->source
!= NULL
)
364 this->packet
->source
->destroy(this->packet
->source
);
366 this->packet
->source
= host
;
370 static status_t
set_destination(private_message_t
*this, host_t
*host
)
372 if (this->packet
->destination
!= NULL
)
374 this->packet
->destination
->destroy(this->packet
->destination
);
376 this->packet
->destination
= host
;
380 static status_t
get_source(private_message_t
*this, host_t
**host
)
382 *host
= this->packet
->source
;
386 static status_t
get_destination(private_message_t
*this, host_t
**host
)
388 *host
= this->packet
->destination
;
394 * Implements message_t's generate function.
395 * See #message_s.generate.
397 static status_t
generate(private_message_t
*this, packet_t
**packet
)
399 generator_t
*generator
;
400 ike_header_t
*ike_header
;
401 payload_t
*payload
, *next_payload
;
402 linked_list_iterator_t
*iterator
;
403 u_int64_t initiator_spi
, responder_spi
;
407 if (this->exchange_type
== EXCHANGE_TYPE_UNDEFINED
)
409 return INVALID_STATE
;
412 if (this->packet
->source
== NULL
||
413 this->packet
->destination
== NULL
)
415 return INVALID_STATE
;
418 ike_header
= ike_header_create();
419 if (ike_header
== NULL
)
424 this->ike_sa_id
->get_values(this->ike_sa_id
, &initiator_spi
, &responder_spi
, &is_initiator
);
426 ike_header
->set_exchange_type(ike_header
, this->exchange_type
);
427 ike_header
->set_initiator_flag(ike_header
, this->original_initiator
);
428 ike_header
->set_message_id(ike_header
, this->message_id
);
429 ike_header
->set_response_flag(ike_header
, !this->is_request
);
430 ike_header
->set_initiator_flag(ike_header
, is_initiator
);
431 ike_header
->set_initiator_spi(ike_header
, initiator_spi
);
432 ike_header
->set_initiator_spi(ike_header
, responder_spi
);
434 generator
= generator_create();
436 payload
= (payload_t
*)ike_header
;
438 if (this->payloads
->create_iterator(this->payloads
, &iterator
, TRUE
) != SUCCESS
)
440 generator
->destroy(generator
);
441 ike_header
->destroy(ike_header
);
444 while(iterator
->has_next(iterator
))
446 iterator
->current(iterator
, (void**)&next_payload
);
447 payload
->set_next_type(payload
, next_payload
->get_type(next_payload
));
448 status
= generator
->generate_payload(generator
, payload
);
449 if (status
!= SUCCESS
)
451 generator
->destroy(generator
);
452 ike_header
->destroy(ike_header
);
455 payload
= next_payload
;
457 iterator
->destroy(iterator
);
459 payload
->set_next_type(payload
, NO_PAYLOAD
);
460 status
= generator
->generate_payload(generator
, payload
);
461 if (status
!= SUCCESS
)
463 generator
->destroy(generator
);
464 ike_header
->destroy(ike_header
);
468 ike_header
->destroy(ike_header
);
472 if (this->packet
->data
.ptr
!= NULL
)
474 allocator_free(this->packet
->data
.ptr
);
477 status
= generator
->write_to_chunk(generator
, &(this->packet
->data
));
478 if (status
!= SUCCESS
)
480 generator
->destroy(generator
);
484 this->packet
->clone(this->packet
, packet
);
486 generator
->destroy(generator
);
491 * Implements message_t's parse_header function.
492 * See #message_s.parse_header.
494 static status_t
parse_header (private_message_t
*this)
496 ike_header_t
*ike_header
;
499 this->parser
->reset_context(this->parser
);
500 status
= this->parser
->parse_payload(this->parser
,HEADER
,(payload_t
**) &ike_header
);
501 if (status
!= SUCCESS
)
506 if (this->ike_sa_id
!= NULL
)
508 this->ike_sa_id
->destroy(this->ike_sa_id
);
510 this->original_initiator
= (!ike_header
->get_initiator_flag(ike_header
));
512 this->ike_sa_id
= ike_sa_id_create(ike_header
->get_initiator_spi(ike_header
),ike_header
->get_responder_spi(ike_header
),this->original_initiator
);
513 if (this->ike_sa_id
== NULL
)
515 ike_header
->destroy(ike_header
);
518 this->exchange_type
= ike_header
->get_exchange_type(ike_header
);
519 this->message_id
= ike_header
->get_message_id(ike_header
);
520 this->is_request
= (!ike_header
->get_response_flag(ike_header
));
521 if ((ike_header
->get_initiator_spi(ike_header
) == 0) && (ike_header
->get_responder_spi(ike_header
) != 0))
523 /* initiator spi not set */
524 ike_header
->destroy(ike_header
);
527 this->major_version
= ike_header
->get_maj_version(ike_header
);
528 this->minor_version
= ike_header
->get_min_version(ike_header
);
529 this->first_payload
= ike_header
->payload_interface
.get_next_type(&(ike_header
->payload_interface
));
531 ike_header
->destroy(ike_header
);
536 * Implements message_t's parse_body function.
537 * See #message_s.parse_body.
539 static status_t
parse_body (private_message_t
*this)
542 payload_type_t current_payload_type
= this->first_payload
;
545 while (current_payload_type
!= NO_PAYLOAD
)
547 payload_t
*current_payload
;
549 status
= this->parser
->parse_payload(this->parser
,current_payload_type
,(payload_t
**) ¤t_payload
);
551 current_payload_type
= current_payload
->get_next_type(current_payload
);
552 current_payload
->destroy(current_payload
);
563 * Implements message_t's destroy function.
564 * See #message_s.destroy.
566 static status_t
destroy (private_message_t
*this)
568 linked_list_iterator_t
*iterator
;
570 if (this->packet
!= NULL
)
572 this->packet
->destroy(this->packet
);
574 if (this->ike_sa_id
!= NULL
)
576 this->ike_sa_id
->destroy(this->ike_sa_id
);
579 this->payloads
->create_iterator(this->payloads
, &iterator
, TRUE
);
580 while (iterator
->has_next(iterator
))
583 iterator
->current(iterator
, (void**)&payload
);
584 this->logger
->log(this->logger
, CONTROL_MORE
, "Destroying payload of type %s",
585 mapping_find(payload_type_m
, payload
->get_type(payload
)));
586 payload
->destroy(payload
);
588 iterator
->destroy(iterator
);
589 this->payloads
->destroy(this->payloads
);
590 this->parser
->destroy(this->parser
);
592 allocator_free(this);
597 * Described in Header-File
599 message_t
*message_create_from_packet(packet_t
*packet
)
601 private_message_t
*this = allocator_alloc_thing(private_message_t
);
607 /* public functions */
608 this->public.set_major_version
= (status_t(*)(message_t
*, u_int8_t
))set_major_version
;
609 this->public.get_major_version
= (u_int8_t(*)(message_t
*))get_major_version
;
610 this->public.set_minor_version
= (status_t(*)(message_t
*, u_int8_t
))set_minor_version
;
611 this->public.get_minor_version
= (u_int8_t(*)(message_t
*))get_minor_version
;
612 this->public.set_message_id
= (status_t(*)(message_t
*, u_int32_t
))set_message_id
;
613 this->public.get_message_id
= (u_int32_t(*)(message_t
*))get_message_id
;
614 this->public.set_ike_sa_id
= (status_t(*)(message_t
*, ike_sa_id_t
*))set_ike_sa_id
;
615 this->public.get_ike_sa_id
= (status_t(*)(message_t
*, ike_sa_id_t
**))get_ike_sa_id
;
616 this->public.set_exchange_type
= (status_t(*)(message_t
*, exchange_type_t
))set_exchange_type
;
617 this->public.get_exchange_type
= (exchange_type_t(*)(message_t
*))get_exchange_type
;
618 this->public.set_original_initiator
= (status_t(*)(message_t
*, bool))set_original_initiator
;
619 this->public.get_original_initiator
= (bool(*)(message_t
*))get_original_initiator
;
620 this->public.set_request
= (status_t(*)(message_t
*, bool))set_request
;
621 this->public.get_request
= (bool(*)(message_t
*))get_request
;
622 this->public.add_payload
= (status_t(*)(message_t
*,payload_t
*))add_payload
;
623 this->public.generate
= (status_t (*) (message_t
*, packet_t
**)) generate
;
624 this->public.set_source
= (status_t (*) (message_t
*,host_t
*)) set_source
;
625 this->public.get_source
= (status_t (*) (message_t
*,host_t
**)) get_source
;
626 this->public.set_destination
= (status_t (*) (message_t
*,host_t
*)) set_destination
;
627 this->public.get_destination
= (status_t (*) (message_t
*,host_t
**)) get_destination
;
628 this->public.parse_header
= (status_t (*) (message_t
*)) parse_header
;
629 this->public.parse_body
= (status_t (*) (message_t
*)) parse_body
;
630 this->public.destroy
= (status_t(*)(message_t
*))destroy
;
633 this->exchange_type
= EXCHANGE_TYPE_UNDEFINED
;
634 this->original_initiator
= TRUE
;
635 this->is_request
= TRUE
;
636 this->ike_sa_id
= NULL
;
637 this->first_payload
= NO_PAYLOAD
;
638 this->message_id
= 0;
643 packet
= packet_create();
647 allocator_free(this);
650 this->packet
= packet
;
651 this->payloads
= linked_list_create();
652 if (this->payloads
== NULL
)
654 allocator_free(this);
658 /* parser is created from data of packet */
659 this->parser
= parser_create(this->packet
->data
);
660 if (this->parser
== NULL
)
662 this->payloads
->destroy(this->payloads
);
663 allocator_free(this);
667 this->logger
= global_logger_manager
->create_logger(global_logger_manager
, MESSAGE
, NULL
);
668 if (this->logger
== NULL
)
670 this->parser
->destroy(this->parser
);
671 this->payloads
->destroy(this->payloads
);
672 allocator_free(this);
676 return (&this->public);
680 * Described in Header-File
682 message_t
*message_create()
684 return message_create_from_packet(NULL
);