removed deprecated iterator methods (has_next & current)
[strongswan.git] / src / charon / encoding / payloads / ts_payload.c
1 /**
2 * @file ts_payload.c
3 *
4 * @brief Implementation of ts_payload_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include <stddef.h>
25
26 #include "ts_payload.h"
27
28 #include <encoding/payloads/encodings.h>
29 #include <utils/linked_list.h>
30
31 typedef struct private_ts_payload_t private_ts_payload_t;
32
33 /**
34 * Private data of an ts_payload_t object.
35 *
36 */
37 struct private_ts_payload_t {
38 /**
39 * Public ts_payload_t interface.
40 */
41 ts_payload_t public;
42
43 /**
44 * TRUE if this TS payload is of type TSi, FALSE for TSr.
45 */
46 bool is_initiator;
47
48 /**
49 * Next payload type.
50 */
51 u_int8_t next_payload;
52
53 /**
54 * Critical flag.
55 */
56 bool critical;
57
58 /**
59 * Length of this payload.
60 */
61 u_int16_t payload_length;
62
63 /**
64 * Number of traffic selectors
65 */
66 u_int8_t number_of_traffic_selectors;
67
68 /**
69 * Contains the traffic selectors of type traffic_selector_substructure_t.
70 */
71 linked_list_t *traffic_selectors;
72 };
73
74 /**
75 * Encoding rules to parse or generate a TS payload
76 *
77 * The defined offsets are the positions in a object of type
78 * private_ts_payload_t.
79 *
80 */
81 encoding_rule_t ts_payload_encodings[] = {
82 /* 1 Byte next payload type, stored in the field next_payload */
83 { U_INT_8, offsetof(private_ts_payload_t, next_payload) },
84 /* the critical bit */
85 { FLAG, offsetof(private_ts_payload_t, critical) },
86 /* 7 Bit reserved bits, nowhere stored */
87 { RESERVED_BIT, 0 },
88 { RESERVED_BIT, 0 },
89 { RESERVED_BIT, 0 },
90 { RESERVED_BIT, 0 },
91 { RESERVED_BIT, 0 },
92 { RESERVED_BIT, 0 },
93 { RESERVED_BIT, 0 },
94 /* Length of the whole payload*/
95 { PAYLOAD_LENGTH, offsetof(private_ts_payload_t, payload_length)},
96 /* 1 Byte TS type*/
97 { U_INT_8, offsetof(private_ts_payload_t, number_of_traffic_selectors) },
98 /* 3 reserved bytes */
99 { RESERVED_BYTE, 0 },
100 { RESERVED_BYTE, 0 },
101 { RESERVED_BYTE, 0 },
102 /* some ts data bytes, length is defined in PAYLOAD_LENGTH */
103 { TRAFFIC_SELECTORS, offsetof(private_ts_payload_t, traffic_selectors) }
104 };
105
106 /*
107 1 2 3
108 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
109 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110 ! Next Payload !C! RESERVED ! Payload Length !
111 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
112 ! Number of TSs ! RESERVED !
113 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
114 ! !
115 ~ <Traffic Selectors> ~
116 ! !
117 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
118 */
119
120 /**
121 * Implementation of payload_t.verify.
122 */
123 static status_t verify(private_ts_payload_t *this)
124 {
125 iterator_t *iterator;
126 payload_t *current_traffic_selector;
127 status_t status = SUCCESS;
128
129 if (this->number_of_traffic_selectors != (this->traffic_selectors->get_count(this->traffic_selectors)))
130 {
131 /* must be the same */
132 return FAILED;
133 }
134
135 iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE);
136 while(iterator->iterate(iterator, (void**)&current_traffic_selector))
137 {
138 status = current_traffic_selector->verify(current_traffic_selector);
139 if (status != SUCCESS)
140 {
141 break;
142 }
143 }
144 iterator->destroy(iterator);
145
146 return status;
147 }
148
149 /**
150 * Implementation of ts_payload_t.get_encoding_rules.
151 */
152 static void get_encoding_rules(private_ts_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
153 {
154 *rules = ts_payload_encodings;
155 *rule_count = sizeof(ts_payload_encodings) / sizeof(encoding_rule_t);
156 }
157
158 /**
159 * Implementation of payload_t.get_type.
160 */
161 static payload_type_t get_payload_type(private_ts_payload_t *this)
162 {
163 if (this->is_initiator)
164 {
165 return TRAFFIC_SELECTOR_INITIATOR;
166 }
167 else
168 {
169 return TRAFFIC_SELECTOR_RESPONDER;
170 }
171 }
172
173 /**
174 * Implementation of payload_t.get_next_type.
175 */
176 static payload_type_t get_next_type(private_ts_payload_t *this)
177 {
178 return (this->next_payload);
179 }
180
181 /**
182 * Implementation of payload_t.set_next_type.
183 */
184 static void set_next_type(private_ts_payload_t *this,payload_type_t type)
185 {
186 this->next_payload = type;
187 }
188
189 /**
190 * recompute the length of the payload.
191 */
192 static void compute_length (private_ts_payload_t *this)
193 {
194 iterator_t *iterator;
195 size_t ts_count = 0;
196 size_t length = TS_PAYLOAD_HEADER_LENGTH;
197 payload_t *current_traffic_selector;
198
199 iterator = this->traffic_selectors->create_iterator(this->traffic_selectors,TRUE);
200 while (iterator->iterate(iterator, (void**)&current_traffic_selector))
201 {
202 length += current_traffic_selector->get_length(current_traffic_selector);
203 ts_count++;
204 }
205 iterator->destroy(iterator);
206
207 this->number_of_traffic_selectors= ts_count;
208 this->payload_length = length;
209 }
210
211 /**
212 * Implementation of payload_t.get_length.
213 */
214 static size_t get_length(private_ts_payload_t *this)
215 {
216 compute_length(this);
217 return this->payload_length;
218 }
219
220 /**
221 * Implementation of ts_payload_t.get_initiator.
222 */
223 static bool get_initiator (private_ts_payload_t *this)
224 {
225 return (this->is_initiator);
226 }
227
228 /**
229 * Implementation of ts_payload_t.set_initiator.
230 */
231 static void set_initiator (private_ts_payload_t *this,bool is_initiator)
232 {
233 this->is_initiator = is_initiator;
234 }
235
236 /**
237 * Implementation of ts_payload_t.add_traffic_selector_substructure.
238 */
239 static void add_traffic_selector_substructure (private_ts_payload_t *this,traffic_selector_substructure_t *traffic_selector)
240 {
241 this->traffic_selectors->insert_last(this->traffic_selectors,traffic_selector);
242 this->number_of_traffic_selectors = this->traffic_selectors->get_count(this->traffic_selectors);
243 }
244
245 /**
246 * Implementation of ts_payload_t.create_traffic_selector_substructure_iterator.
247 */
248 static iterator_t * create_traffic_selector_substructure_iterator (private_ts_payload_t *this, bool forward)
249 {
250 return this->traffic_selectors->create_iterator(this->traffic_selectors,forward);
251 }
252
253 /**
254 * Implementation of ts_payload_t.get_traffic_selectors.
255 */
256 static linked_list_t *get_traffic_selectors(private_ts_payload_t *this)
257 {
258 traffic_selector_t *ts;
259 iterator_t *iterator;
260 traffic_selector_substructure_t *ts_substructure;
261 linked_list_t *ts_list = linked_list_create();
262
263 iterator = this->traffic_selectors->create_iterator(this->traffic_selectors, TRUE);
264 while (iterator->iterate(iterator, (void**)&ts_substructure))
265 {
266 ts = ts_substructure->get_traffic_selector(ts_substructure);
267 ts_list->insert_last(ts_list, (void*)ts);
268 }
269 iterator->destroy(iterator);
270
271 return ts_list;
272 }
273
274 /**
275 * Implementation of payload_t.destroy and ts_payload_t.destroy.
276 */
277 static void destroy(private_ts_payload_t *this)
278 {
279 this->traffic_selectors->destroy_offset(this->traffic_selectors,
280 offsetof(payload_t, destroy));
281 free(this);
282 }
283
284 /*
285 * Described in header
286 */
287 ts_payload_t *ts_payload_create(bool is_initiator)
288 {
289 private_ts_payload_t *this = malloc_thing(private_ts_payload_t);
290
291 /* interface functions */
292 this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
293 this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
294 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
295 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
296 this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
297 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
298 this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
299
300 /* public functions */
301 this->public.destroy = (void (*) (ts_payload_t *)) destroy;
302 this->public.get_initiator = (bool (*) (ts_payload_t *)) get_initiator;
303 this->public.set_initiator = (void (*) (ts_payload_t *,bool)) set_initiator;
304 this->public.add_traffic_selector_substructure = (void (*) (ts_payload_t *,traffic_selector_substructure_t *)) add_traffic_selector_substructure;
305 this->public.create_traffic_selector_substructure_iterator = (iterator_t* (*) (ts_payload_t *,bool)) create_traffic_selector_substructure_iterator;
306 this->public.get_traffic_selectors = (linked_list_t *(*) (ts_payload_t *)) get_traffic_selectors;
307
308 /* private variables */
309 this->critical = FALSE;
310 this->next_payload = NO_PAYLOAD;
311 this->payload_length =TS_PAYLOAD_HEADER_LENGTH;
312 this->is_initiator = is_initiator;
313 this->number_of_traffic_selectors = 0;
314 this->traffic_selectors = linked_list_create();
315
316 return &(this->public);
317 }
318
319 /*
320 * Described in header
321 */
322 ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator, linked_list_t *traffic_selectors)
323 {
324 iterator_t *iterator;
325 traffic_selector_t *ts;
326 traffic_selector_substructure_t *ts_substructure;
327 private_ts_payload_t *this;
328
329 this = (private_ts_payload_t*)ts_payload_create(is_initiator);
330
331 iterator = traffic_selectors->create_iterator(traffic_selectors, TRUE);
332 while (iterator->iterate(iterator, (void**)&ts))
333 {
334 ts_substructure = traffic_selector_substructure_create_from_traffic_selector(ts);
335 this->public.add_traffic_selector_substructure(&(this->public), ts_substructure);
336 }
337 iterator->destroy(iterator);
338
339 return &(this->public);
340 }
341