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
26 #include "sa_payload.h"
28 #include <encoding/payloads/encodings.h>
29 #include <utils/allocator.h>
30 #include <utils/linked_list.h>
33 typedef struct private_sa_payload_t private_sa_payload_t
;
36 * Private data of an sa_payload_t object.
39 struct private_sa_payload_t
{
41 * Public sa_payload_t interface.
48 u_int8_t next_payload
;
56 * Length of this payload.
58 u_int16_t payload_length
;
61 * Proposals in this payload are stored in a linked_list_t.
63 linked_list_t
* proposals
;
66 * @brief Computes the length of this payload.
68 * @param this calling private_sa_payload_t object
70 void (*compute_length
) (private_sa_payload_t
*this);
74 * Encoding rules to parse or generate a IKEv2-SA Payload
76 * The defined offsets are the positions in a object of type
77 * private_sa_payload_t.
80 encoding_rule_t sa_payload_encodings
[] = {
81 /* 1 Byte next payload type, stored in the field next_payload */
82 { U_INT_8
, offsetof(private_sa_payload_t
, next_payload
) },
83 /* the critical bit */
84 { FLAG
, offsetof(private_sa_payload_t
, critical
) },
85 /* 7 Bit reserved bits, nowhere stored */
93 /* Length of the whole SA payload*/
94 { PAYLOAD_LENGTH
, offsetof(private_sa_payload_t
, payload_length
) },
95 /* Proposals are stored in a proposal substructure,
96 offset points to a linked_list_t pointer */
97 { PROPOSALS
, offsetof(private_sa_payload_t
, proposals
) }
102 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
103 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104 ! Next Payload !C! RESERVED ! Payload Length !
105 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
113 * Implementation of payload_t.verify.
115 static status_t
verify(private_sa_payload_t
*this)
117 int proposal_number
= 1;
119 iterator_t
*iterator
;
124 /* critical bit set! */
128 /* check proposal numbering */
129 iterator
= this->proposals
->create_iterator(this->proposals
,TRUE
);
131 while(iterator
->has_next(iterator
))
133 proposal_substructure_t
*current_proposal
;
134 status
= iterator
->current(iterator
,(void **)¤t_proposal
);
138 if (current_proposal
->get_proposal_number(current_proposal
) > proposal_number
)
142 /* first number must be 1 */
147 if (current_proposal
->get_proposal_number(current_proposal
) != (proposal_number
+ 1))
149 /* must be only one more then previous proposal */
154 else if (current_proposal
->get_proposal_number(current_proposal
) < proposal_number
)
156 iterator
->destroy(iterator
);
157 /* must not be smaller then proceeding one */
164 iterator
->destroy(iterator
);
170 * Implementation of payload_t.destroy and sa_payload_t.destroy.
172 static status_t
destroy(private_sa_payload_t
*this)
174 /* all proposals are getting destroyed */
175 while (this->proposals
->get_count(this->proposals
) > 0)
177 proposal_substructure_t
*current_proposal
;
178 this->proposals
->remove_last(this->proposals
,(void **)¤t_proposal
);
179 current_proposal
->destroy(current_proposal
);
181 this->proposals
->destroy(this->proposals
);
183 allocator_free(this);
189 * Implementation of payload_t.get_encoding_rules.
191 static void get_encoding_rules(private_sa_payload_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
193 *rules
= sa_payload_encodings
;
194 *rule_count
= sizeof(sa_payload_encodings
) / sizeof(encoding_rule_t
);
198 * Implementation of payload_t.get_type.
200 static payload_type_t
get_type(private_sa_payload_t
*this)
202 return SECURITY_ASSOCIATION
;
206 * Implementation of payload_t.get_next_type.
208 static payload_type_t
get_next_type(private_sa_payload_t
*this)
210 return (this->next_payload
);
214 * Implementation of payload_t.set_next_type.
216 static void set_next_type(private_sa_payload_t
*this,payload_type_t type
)
218 this->next_payload
= type
;
222 * Implementation of payload_t.get_length.
224 static size_t get_length(private_sa_payload_t
*this)
226 this->compute_length(this);
227 return this->payload_length
;
231 * Implementation of sa_payload_t.create_proposal_substructure_iterator.
233 static iterator_t
*create_proposal_substructure_iterator (private_sa_payload_t
*this,bool forward
)
235 return this->proposals
->create_iterator(this->proposals
,forward
);
239 * Implementation of sa_payload_t.add_proposal_substructure.
241 static void add_proposal_substructure (private_sa_payload_t
*this,proposal_substructure_t
*proposal
)
243 this->proposals
->insert_last(this->proposals
,(void *) proposal
);
244 this->compute_length(this);
248 * Implementation of private_sa_payload_t.compute_length.
250 static void compute_length (private_sa_payload_t
*this)
252 iterator_t
*iterator
;
253 size_t length
= SA_PAYLOAD_HEADER_LENGTH
;
254 iterator
= this->proposals
->create_iterator(this->proposals
,TRUE
);
255 while (iterator
->has_next(iterator
))
257 payload_t
*current_proposal
;
258 iterator
->current(iterator
,(void **) ¤t_proposal
);
259 length
+= current_proposal
->get_length(current_proposal
);
261 iterator
->destroy(iterator
);
263 this->payload_length
= length
;
267 * Described in header.
269 sa_payload_t
*sa_payload_create()
271 private_sa_payload_t
*this = allocator_alloc_thing(private_sa_payload_t
);
273 /* public interface */
274 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
275 this->public.payload_interface
.get_encoding_rules
= (void (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
276 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
277 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
278 this->public.payload_interface
.set_next_type
= (void (*) (payload_t
*,payload_type_t
)) set_next_type
;
279 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
280 this->public.payload_interface
.destroy
= (void (*) (payload_t
*))destroy
;
282 /* public functions */
283 this->public.create_proposal_substructure_iterator
= (iterator_t
* (*) (sa_payload_t
*,bool)) create_proposal_substructure_iterator
;
284 this->public.add_proposal_substructure
= (void (*) (sa_payload_t
*,proposal_substructure_t
*)) add_proposal_substructure
;
285 this->public.destroy
= (void (*) (sa_payload_t
*)) destroy
;
287 /* private functions */
288 this->compute_length
= compute_length
;
290 /* set default values of the fields */
291 this->critical
= SA_PAYLOAD_CRITICAL_FLAG
;
292 this->next_payload
= NO_PAYLOAD
;
293 this->payload_length
= SA_PAYLOAD_HEADER_LENGTH
;
295 this->proposals
= linked_list_create();
296 return (&(this->public));