4 * @brief Implementation of sa_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 "sa_payload.h"
27 #include <encoding/payloads/encodings.h>
28 #include <utils/linked_list.h>
31 typedef struct private_sa_payload_t private_sa_payload_t
;
34 * Private data of an sa_payload_t object.
37 struct private_sa_payload_t
{
39 * Public sa_payload_t interface.
46 u_int8_t next_payload
;
54 * Length of this payload.
56 u_int16_t payload_length
;
59 * Proposals in this payload are stored in a linked_list_t.
61 linked_list_t
* proposals
;
64 * @brief Computes the length of this payload.
66 * @param this calling private_sa_payload_t object
68 void (*compute_length
) (private_sa_payload_t
*this);
72 * Encoding rules to parse or generate a IKEv2-SA Payload
74 * The defined offsets are the positions in a object of type
75 * private_sa_payload_t.
78 encoding_rule_t sa_payload_encodings
[] = {
79 /* 1 Byte next payload type, stored in the field next_payload */
80 { U_INT_8
, offsetof(private_sa_payload_t
, next_payload
) },
81 /* the critical bit */
82 { FLAG
, offsetof(private_sa_payload_t
, critical
) },
83 /* 7 Bit reserved bits, nowhere stored */
91 /* Length of the whole SA payload*/
92 { PAYLOAD_LENGTH
, offsetof(private_sa_payload_t
, payload_length
) },
93 /* Proposals are stored in a proposal substructure,
94 offset points to a linked_list_t pointer */
95 { PROPOSALS
, offsetof(private_sa_payload_t
, proposals
) }
100 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
101 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102 ! Next Payload !C! RESERVED ! Payload Length !
103 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
111 * Implementation of payload_t.verify.
113 static status_t
verify(private_sa_payload_t
*this)
115 int proposal_number
= 1;
116 status_t status
= SUCCESS
;
117 iterator_t
*iterator
;
120 /* check proposal numbering */
121 iterator
= this->proposals
->create_iterator(this->proposals
,TRUE
);
123 while(iterator
->has_next(iterator
))
125 proposal_substructure_t
*current_proposal
;
126 iterator
->current(iterator
,(void **)¤t_proposal
);
127 if (current_proposal
->get_proposal_number(current_proposal
) > proposal_number
)
131 /* first number must be 1 */
136 if (current_proposal
->get_proposal_number(current_proposal
) != (proposal_number
+ 1))
138 /* must be only one more then previous proposal */
143 else if (current_proposal
->get_proposal_number(current_proposal
) < proposal_number
)
145 /* must not be smaller then proceeding one */
150 status
= current_proposal
->payload_interface
.verify(&(current_proposal
->payload_interface
));
151 if (status
!= SUCCESS
)
158 iterator
->destroy(iterator
);
164 * Implementation of payload_t.destroy and sa_payload_t.destroy.
166 static status_t
destroy(private_sa_payload_t
*this)
168 /* all proposals are getting destroyed */
169 while (this->proposals
->get_count(this->proposals
) > 0)
171 proposal_substructure_t
*current_proposal
;
172 this->proposals
->remove_last(this->proposals
,(void **)¤t_proposal
);
173 current_proposal
->destroy(current_proposal
);
175 this->proposals
->destroy(this->proposals
);
183 * Implementation of payload_t.get_encoding_rules.
185 static void get_encoding_rules(private_sa_payload_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
187 *rules
= sa_payload_encodings
;
188 *rule_count
= sizeof(sa_payload_encodings
) / sizeof(encoding_rule_t
);
192 * Implementation of payload_t.get_type.
194 static payload_type_t
get_type(private_sa_payload_t
*this)
196 return SECURITY_ASSOCIATION
;
200 * Implementation of payload_t.get_next_type.
202 static payload_type_t
get_next_type(private_sa_payload_t
*this)
204 return (this->next_payload
);
208 * Implementation of payload_t.set_next_type.
210 static void set_next_type(private_sa_payload_t
*this,payload_type_t type
)
212 this->next_payload
= type
;
216 * Implementation of payload_t.get_length.
218 static size_t get_length(private_sa_payload_t
*this)
220 this->compute_length(this);
221 return this->payload_length
;
225 * Implementation of sa_payload_t.create_proposal_substructure_iterator.
227 static iterator_t
*create_proposal_substructure_iterator (private_sa_payload_t
*this,bool forward
)
229 return this->proposals
->create_iterator(this->proposals
,forward
);
233 * Implementation of sa_payload_t.add_proposal_substructure.
235 static void add_proposal_substructure (private_sa_payload_t
*this,proposal_substructure_t
*proposal
)
238 if (this->proposals
->get_count(this->proposals
) > 0)
240 proposal_substructure_t
*last_proposal
;
241 status
= this->proposals
->get_last(this->proposals
,(void **) &last_proposal
);
242 /* last transform is now not anymore last one */
243 last_proposal
->set_is_last_proposal(last_proposal
,FALSE
);
245 proposal
->set_is_last_proposal(proposal
,TRUE
);
247 this->proposals
->insert_last(this->proposals
,(void *) proposal
);
248 this->compute_length(this);
252 * Implementation of sa_payload_t.add_proposal.
254 static void add_proposal(private_sa_payload_t
*this, proposal_t
*proposal
)
256 proposal_substructure_t
*substructure
;
257 protocol_id_t proto
[2];
260 /* build the substructures for every protocol */
261 proposal
->get_protocols(proposal
, proto
);
262 for (i
= 0; i
<2; i
++)
264 if (proto
[i
] != PROTO_NONE
)
266 substructure
= proposal_substructure_create_from_proposal(proposal
, proto
[i
]);
267 add_proposal_substructure(this, substructure
);
273 * Implementation of sa_payload_t.get_proposals.
275 static linked_list_t
*get_proposals(private_sa_payload_t
*this)
277 int proposal_struct_number
= 0;
278 iterator_t
*iterator
;
279 proposal_t
*proposal
;
280 linked_list_t
*proposal_list
;
282 /* this list will hold our proposals */
283 proposal_list
= linked_list_create();
285 /* iterate over structures, one OR MORE structures will result in a proposal */
286 iterator
= this->proposals
->create_iterator(this->proposals
,TRUE
);
287 while (iterator
->has_next(iterator
))
289 proposal_substructure_t
*proposal_struct
;
290 iterator
->current(iterator
,(void **)&(proposal_struct
));
292 if (proposal_struct
->get_proposal_number(proposal_struct
) > proposal_struct_number
)
294 /* here starts a new proposal, create a new one and add it to the list */
295 proposal_struct_number
= proposal_struct
->get_proposal_number(proposal_struct
);
296 proposal
= proposal_create(proposal_struct_number
);
297 proposal_list
->insert_last(proposal_list
, proposal
);
299 /* proposal_substructure_t does the dirty work and builds up the proposal */
300 proposal_struct
->add_to_proposal(proposal_struct
, proposal
);
302 iterator
->destroy(iterator
);
303 return proposal_list
;
307 * Implementation of private_sa_payload_t.compute_length.
309 static void compute_length (private_sa_payload_t
*this)
311 iterator_t
*iterator
;
312 size_t length
= SA_PAYLOAD_HEADER_LENGTH
;
313 iterator
= this->proposals
->create_iterator(this->proposals
,TRUE
);
314 while (iterator
->has_next(iterator
))
316 payload_t
*current_proposal
;
317 iterator
->current(iterator
,(void **) ¤t_proposal
);
318 length
+= current_proposal
->get_length(current_proposal
);
320 iterator
->destroy(iterator
);
322 this->payload_length
= length
;
326 * Described in header.
328 sa_payload_t
*sa_payload_create()
330 private_sa_payload_t
*this = malloc_thing(private_sa_payload_t
);
332 /* public interface */
333 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
334 this->public.payload_interface
.get_encoding_rules
= (void (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
335 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
336 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
337 this->public.payload_interface
.set_next_type
= (void (*) (payload_t
*,payload_type_t
)) set_next_type
;
338 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
339 this->public.payload_interface
.destroy
= (void (*) (payload_t
*))destroy
;
341 /* public functions */
342 this->public.create_proposal_substructure_iterator
= (iterator_t
* (*) (sa_payload_t
*,bool)) create_proposal_substructure_iterator
;
343 this->public.add_proposal_substructure
= (void (*) (sa_payload_t
*,proposal_substructure_t
*)) add_proposal_substructure
;
344 this->public.get_proposals
= (linked_list_t
* (*) (sa_payload_t
*)) get_proposals
;
345 this->public.destroy
= (void (*) (sa_payload_t
*)) destroy
;
347 /* private functions */
348 this->compute_length
= compute_length
;
350 /* set default values of the fields */
351 this->critical
= FALSE
;
352 this->next_payload
= NO_PAYLOAD
;
353 this->payload_length
= SA_PAYLOAD_HEADER_LENGTH
;
355 this->proposals
= linked_list_create();
356 return (&(this->public));
360 * Described in header.
362 sa_payload_t
*sa_payload_create_from_proposal_list(linked_list_t
*proposals
)
364 iterator_t
*iterator
;
365 proposal_t
*proposal
;
366 sa_payload_t
*sa_payload
= sa_payload_create();
368 /* add every payload from the list */
369 iterator
= proposals
->create_iterator(proposals
, TRUE
);
370 while (iterator
->has_next(iterator
))
372 iterator
->current(iterator
, (void**)&proposal
);
373 add_proposal((private_sa_payload_t
*)sa_payload
, proposal
);
375 iterator
->destroy(iterator
);
381 * Described in header.
383 sa_payload_t
*sa_payload_create_from_proposal(proposal_t
*proposal
)
385 sa_payload_t
*sa_payload
= sa_payload_create();
387 add_proposal((private_sa_payload_t
*)sa_payload
, proposal
);