4 * @brief Declaration of the class sa_payload_t.
6 * An object of this type represents an IKEv2 SA-Payload and contains proposal
12 * Copyright (C) 2005 Jan Hutter, Martin Willi
13 * Hochschule fuer Technik Rapperswil
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the
17 * Free Software Foundation; either version 2 of the License, or (at your
18 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
29 #include "sa_payload.h"
31 #include <encoding/payloads/encodings.h>
32 #include <utils/allocator.h>
33 #include <utils/linked_list.h>
37 * Private data of an sa_payload_t' Object
40 typedef struct private_sa_payload_s private_sa_payload_t
;
42 struct private_sa_payload_s
{
44 * public sa_payload_t interface
51 u_int8_t next_payload
;
59 * Length of this payload
61 u_int16_t payload_length
;
64 * Proposals in this payload are stored in a linked_list_t
66 linked_list_t
* proposals
;
69 * @brief Computes the length of this payload.
71 * @param this calling private_sa_payload_t object
75 status_t (*compute_length
) (private_sa_payload_t
*this);
79 * Encoding rules to parse or generate a IKEv2-SA Payload
81 * The defined offsets are the positions in a object of type
82 * private_sa_payload_t.
85 encoding_rule_t sa_payload_encodings
[] = {
86 /* 1 Byte next payload type, stored in the field next_payload */
87 { U_INT_8
, offsetof(private_sa_payload_t
, next_payload
) },
88 /* the critical bit */
89 { FLAG
, offsetof(private_sa_payload_t
, critical
) },
90 /* 7 Bit reserved bits, nowhere stored */
98 /* Length of the whole SA payload*/
99 { PAYLOAD_LENGTH
, offsetof(private_sa_payload_t
, payload_length
) },
100 /* Proposals are stored in a proposal substructure,
101 offset points to a linked_list_t pointer */
102 { PROPOSALS
, offsetof(private_sa_payload_t
, proposals
) }
107 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
108 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109 ! Next Payload !C! RESERVED ! Payload Length !
110 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
114 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
118 * Implements payload_t's verify function.
119 * See #payload_s.verify for description.
121 static status_t
verify(private_sa_payload_t
*this)
123 int proposal_number
= 1;
125 linked_list_iterator_t
*iterator
;
130 /* critical bit set! */
134 /* check proposal numbering */
135 status
= this->proposals
->create_iterator(this->proposals
,&iterator
,TRUE
);
136 if (status
!= SUCCESS
)
141 while(iterator
->has_next(iterator
))
143 proposal_substructure_t
*current_proposal
;
144 status
= iterator
->current(iterator
,(void **)¤t_proposal
);
148 if (current_proposal
->get_proposal_number(current_proposal
) > proposal_number
)
152 /* first number must be 1 */
157 if (current_proposal
->get_proposal_number(current_proposal
) != (proposal_number
+ 1))
159 /* must be only one more then previous proposal */
164 else if (current_proposal
->get_proposal_number(current_proposal
) < proposal_number
)
166 iterator
->destroy(iterator
);
167 /* must not be smaller then proceeding one */
174 iterator
->destroy(iterator
);
180 * Implements payload_t's and sa_payload_t's destroy function.
181 * See #payload_s.destroy or sa_payload_s.destroy for description.
183 static status_t
destroy(private_sa_payload_t
*this)
185 /* all proposals are getting destroyed */
186 while (this->proposals
->get_count(this->proposals
) > 0)
188 proposal_substructure_t
*current_proposal
;
189 if (this->proposals
->remove_last(this->proposals
,(void **)¤t_proposal
) != SUCCESS
)
193 current_proposal
->destroy(current_proposal
);
195 this->proposals
->destroy(this->proposals
);
197 allocator_free(this);
203 * Implements payload_t's get_encoding_rules function.
204 * See #payload_s.get_encoding_rules for description.
206 static status_t
get_encoding_rules(private_sa_payload_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
208 *rules
= sa_payload_encodings
;
209 *rule_count
= sizeof(sa_payload_encodings
) / sizeof(encoding_rule_t
);
215 * Implements payload_t's get_type function.
216 * See #payload_s.get_type for description.
218 static payload_type_t
get_type(private_sa_payload_t
*this)
220 return SECURITY_ASSOCIATION
;
224 * Implements payload_t's get_next_type function.
225 * See #payload_s.get_next_type for description.
227 static payload_type_t
get_next_type(private_sa_payload_t
*this)
229 return (this->next_payload
);
233 * Implements payload_t's set_next_type function.
234 * See #payload_s.set_next_type for description.
236 static status_t
set_next_type(private_sa_payload_t
*this,payload_type_t type
)
238 this->next_payload
= type
;
243 * Implements payload_t's get_length function.
244 * See #payload_s.get_length for description.
246 static size_t get_length(private_sa_payload_t
*this)
248 this->compute_length(this);
249 return this->payload_length
;
253 * Implements sa_payload_t's create_proposal_substructure_iterator function.
254 * See #sa_payload_s.create_proposal_substructure_iterator for description.
256 static status_t
create_proposal_substructure_iterator (private_sa_payload_t
*this,linked_list_iterator_t
**iterator
,bool forward
)
258 return (this->proposals
->create_iterator(this->proposals
,iterator
,forward
));
262 * Implements sa_payload_t's add_proposal_substructure function.
263 * See #sa_payload_s.add_proposal_substructure for description.
265 static status_t
add_proposal_substructure (private_sa_payload_t
*this,proposal_substructure_t
*proposal
)
268 status
= this->proposals
->insert_last(this->proposals
,(void *) proposal
);
269 this->compute_length(this);
274 * Implements private_sa_payload_t's compute_length function.
275 * See #private_sa_payload_s.compute_length for description.
277 static status_t
compute_length (private_sa_payload_t
*this)
279 linked_list_iterator_t
*iterator
;
281 size_t length
= SA_PAYLOAD_HEADER_LENGTH
;
282 status
= this->proposals
->create_iterator(this->proposals
,&iterator
,TRUE
);
283 if (status
!= SUCCESS
)
287 while (iterator
->has_next(iterator
))
289 payload_t
*current_proposal
;
290 iterator
->current(iterator
,(void **) ¤t_proposal
);
291 length
+= current_proposal
->get_length(current_proposal
);
293 iterator
->destroy(iterator
);
295 this->payload_length
= length
;
301 * Described in header
303 sa_payload_t
*sa_payload_create()
305 private_sa_payload_t
*this = allocator_alloc_thing(private_sa_payload_t
);
311 /* public interface */
312 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
313 this->public.payload_interface
.get_encoding_rules
= (status_t (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
314 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
315 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
316 this->public.payload_interface
.set_next_type
= (status_t (*) (payload_t
*,payload_type_t
)) set_next_type
;
317 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
318 this->public.payload_interface
.destroy
= (status_t (*) (payload_t
*))destroy
;
320 /* public functions */
321 this->public.create_proposal_substructure_iterator
= (status_t (*) (sa_payload_t
*,linked_list_iterator_t
**,bool)) create_proposal_substructure_iterator
;
322 this->public.add_proposal_substructure
= (status_t (*) (sa_payload_t
*,proposal_substructure_t
*)) add_proposal_substructure
;
323 this->public.destroy
= (status_t (*) (sa_payload_t
*)) destroy
;
325 /* private functions */
326 this->compute_length
= compute_length
;
328 /* set default values of the fields */
329 this->critical
= SA_PAYLOAD_CRITICAL_FLAG
;
330 this->next_payload
= NO_PAYLOAD
;
331 this->payload_length
= SA_PAYLOAD_HEADER_LENGTH
;
333 this->proposals
= linked_list_create();
335 if (this->proposals
== NULL
)
337 allocator_free(this);
340 return (&(this->public));