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