- creation of ts payloads using ts
[strongswan.git] / Source / charon / encoding / payloads / traffic_selector_substructure.c
1 /**
2 * @file traffic_selector_substructure.c
3 *
4 * @brief Interface of traffic_selector_substructure_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
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>.
16 *
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
20 * for more details.
21 */
22
23 #include "traffic_selector_substructure.h"
24
25 #include <encoding/payloads/encodings.h>
26 #include <utils/allocator.h>
27 #include <utils/linked_list.h>
28
29 /**
30 * String mappings for ts_type_t.
31 */
32 mapping_t ts_type_m[] = {
33 {TS_IPV4_ADDR_RANGE, "TS_IPV4_ADDR_RANGE"},
34 {TS_IPV6_ADDR_RANGE, "TS_IPV6_ADDR_RANGE"},
35 {MAPPING_END, NULL}
36 };
37
38
39 typedef struct private_traffic_selector_substructure_t private_traffic_selector_substructure_t;
40
41 /**
42 * Private data of an traffic_selector_substructure_t object.
43 *
44 */
45 struct private_traffic_selector_substructure_t {
46 /**
47 * Public traffic_selector_substructure_t interface.
48 */
49 traffic_selector_substructure_t public;
50
51 /**
52 * Type of traffic selector.
53 */
54 u_int8_t ts_type;
55
56 /**
57 * IP Protocol ID.
58 */
59 u_int8_t ip_protocol_id;
60
61 /**
62 * Length of this payload.
63 */
64 u_int16_t payload_length;
65
66 /**
67 * Start port number.
68 */
69 u_int16_t start_port;
70
71 /**
72 * End port number.
73 */
74 u_int16_t end_port;
75
76 /**
77 * Starting address.
78 */
79 chunk_t starting_address;
80
81 /**
82 * Ending address.
83 */
84 chunk_t ending_address;
85
86 /**
87 * update length
88 */
89 void (*compute_length) (private_traffic_selector_substructure_t *this);
90 };
91
92 /**
93 * Encoding rules to parse or generate a TS payload
94 *
95 * The defined offsets are the positions in a object of type
96 * private_traffic_selector_substructure_t.
97 *
98 */
99 encoding_rule_t traffic_selector_substructure_encodings[] = {
100 /* 1 Byte next ts type*/
101 { TS_TYPE, offsetof(private_traffic_selector_substructure_t, ts_type) },
102 /* 1 Byte IP protocol id*/
103 { U_INT_8, offsetof(private_traffic_selector_substructure_t, ip_protocol_id) },
104 /* Length of the whole payload*/
105 { PAYLOAD_LENGTH, offsetof(private_traffic_selector_substructure_t, payload_length) },
106 /* 2 Byte start port*/
107 { U_INT_16, offsetof(private_traffic_selector_substructure_t, start_port) },
108 /* 2 Byte end port*/
109 { U_INT_16, offsetof(private_traffic_selector_substructure_t, end_port) },
110 /* starting address is either 4 or 16 byte */
111 { ADDRESS, offsetof(private_traffic_selector_substructure_t, starting_address) },
112 /* ending address is either 4 or 16 byte */
113 { ADDRESS, offsetof(private_traffic_selector_substructure_t, ending_address) }
114
115 };
116
117 /*
118 1 2 3
119 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
120 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
121 ! TS Type !IP Protocol ID*| Selector Length |
122 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
123 | Start Port* | End Port* |
124 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
125 ! !
126 ~ Starting Address* ~
127 ! !
128 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129 ! !
130 ~ Ending Address* ~
131 ! !
132 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133 */
134
135 /**
136 * Implementation of payload_t.verify.
137 */
138 static status_t verify(private_traffic_selector_substructure_t *this)
139 {
140
141 if (this->start_port > this->end_port)
142 {
143 return FAILED;
144 }
145 switch (this->ts_type)
146 {
147 case TS_IPV4_ADDR_RANGE:
148 {
149 if ((this->starting_address.len != 4) ||
150 (this->ending_address.len != 4))
151 {
152 /* ipv4 address must be 4 bytes long */
153 return FAILED;
154 }
155 break;
156 }
157 case TS_IPV6_ADDR_RANGE:
158 default:
159 {
160 /* not supported ts type */
161 return FAILED;
162 }
163 }
164
165
166 return SUCCESS;
167 }
168
169 /**
170 * Implementation of traffic_selector_substructure_t.get_encoding_rules.
171 */
172 static void get_encoding_rules(private_traffic_selector_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
173 {
174 *rules = traffic_selector_substructure_encodings;
175 *rule_count = sizeof(traffic_selector_substructure_encodings) / sizeof(encoding_rule_t);
176 }
177
178 /**
179 * Implementation of payload_t.get_type.
180 */
181 static payload_type_t get_payload_type(private_traffic_selector_substructure_t *this)
182 {
183 return TRAFFIC_SELECTOR_SUBSTRUCTURE;
184 }
185
186 /**
187 * Implementation of payload_t.get_next_type.
188 */
189 static payload_type_t get_next_type(private_traffic_selector_substructure_t *this)
190 {
191 return 0;
192 }
193
194 /**
195 * Implementation of payload_t.set_next_type.
196 */
197 static void set_next_type(private_traffic_selector_substructure_t *this,payload_type_t type)
198 {
199 }
200
201 /**
202 * Implementation of payload_t.get_length.
203 */
204 static size_t get_length(private_traffic_selector_substructure_t *this)
205 {
206 return this->payload_length;
207 }
208
209 /**
210 * Implementation of traffic_selector_substructure_t.get_ts_type.
211 */
212 static ts_type_t get_ts_type (private_traffic_selector_substructure_t *this)
213 {
214 return this->ts_type;
215 }
216
217 /**
218 * Implementation of traffic_selector_substructure_t.set_ts_type.
219 */
220 static void set_ts_type (private_traffic_selector_substructure_t *this,ts_type_t ts_type)
221 {
222 this->ts_type = ts_type;
223 }
224
225 /**
226 * Implementation of traffic_selector_substructure_t.get_protocol_id.
227 */
228 static u_int8_t get_protocol_id (private_traffic_selector_substructure_t *this)
229 {
230 return this->ip_protocol_id;
231 }
232
233 /**
234 * Implementation of traffic_selector_substructure_t.set_protocol_id.
235 */
236 static void set_protocol_id (private_traffic_selector_substructure_t *this,u_int8_t protocol_id)
237 {
238 this->ip_protocol_id = protocol_id;
239 }
240
241 /**
242 * Implementation of traffic_selector_substructure_t.get_start_host.
243 */
244 static host_t * get_start_host (private_traffic_selector_substructure_t *this)
245 {
246 return (host_create_from_chunk(AF_INET,this->starting_address, this->start_port));
247 }
248
249 /**
250 * Implementation of traffic_selector_substructure_t.set_start_host.
251 */
252 static void set_start_host (private_traffic_selector_substructure_t *this,host_t *start_host)
253 {
254 this->start_port = start_host->get_port(start_host);
255 if (this->starting_address.ptr != NULL)
256 {
257 allocator_free_chunk(&(this->starting_address));
258 }
259 this->starting_address = start_host->get_address_as_chunk(start_host);
260 this->compute_length(this);
261 }
262
263 /**
264 * Implementation of traffic_selector_substructure_t.get_end_host.
265 */
266 static host_t *get_end_host (private_traffic_selector_substructure_t *this)
267 {
268 return (host_create_from_chunk(AF_INET,this->ending_address, this->end_port));
269 }
270
271 /**
272 * Implementation of traffic_selector_substructure_t.set_end_host.
273 */
274 static void set_end_host (private_traffic_selector_substructure_t *this,host_t *end_host)
275 {
276 this->end_port = end_host->get_port(end_host);
277 if (this->ending_address.ptr != NULL)
278 {
279 allocator_free_chunk(&(this->ending_address));
280 }
281 this->ending_address = end_host->get_address_as_chunk(end_host);
282 this->compute_length(this);
283 }
284
285 /**
286 * Implementation of traffic_selector_substructure_t.get_traffic_selector.
287 */
288 static traffic_selector_t *get_traffic_selector(private_traffic_selector_substructure_t *this)
289 {
290 traffic_selector_t *ts;
291 ts = traffic_selector_create_from_bytes(this->ip_protocol_id, this->ts_type,
292 this->starting_address, this->start_port,
293 this->ending_address, this->end_port);
294 return ts;
295 }
296
297 /**
298 * Implementation of private_ts_payload_t.compute_length
299 */
300 void compute_length(private_traffic_selector_substructure_t *this)
301 {
302 this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH + this->ending_address.len + this->starting_address.len;
303 }
304
305 /**
306 * Implementation of payload_t.destroy and traffic_selector_substructure_t.destroy.
307 */
308 static void destroy(private_traffic_selector_substructure_t *this)
309 {
310 allocator_free(this->starting_address.ptr);
311 allocator_free(this->ending_address.ptr);
312 allocator_free(this);
313 }
314
315 /*
316 * Described in header
317 */
318 traffic_selector_substructure_t *traffic_selector_substructure_create()
319 {
320 private_traffic_selector_substructure_t *this = allocator_alloc_thing(private_traffic_selector_substructure_t);
321
322 /* interface functions */
323 this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
324 this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
325 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
326 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
327 this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
328 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_payload_type;
329 this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
330
331 /* public functions */
332 this->public.destroy = (void (*) (traffic_selector_substructure_t *)) destroy;
333 this->public.get_ts_type = (ts_type_t (*) (traffic_selector_substructure_t *)) get_ts_type;
334 this->public.set_ts_type = (void (*) (traffic_selector_substructure_t *,ts_type_t)) set_ts_type;
335 this->public.get_protocol_id = (u_int8_t (*) (traffic_selector_substructure_t *)) get_protocol_id;
336 this->public.set_protocol_id = (void (*) (traffic_selector_substructure_t *,u_int8_t)) set_protocol_id;
337 this->public.get_start_host = (host_t * (*) (traffic_selector_substructure_t *))get_start_host;
338 this->public.set_start_host = (void (*) (traffic_selector_substructure_t *, host_t *))set_start_host;
339 this->public.get_end_host = (host_t * (*) (traffic_selector_substructure_t *))get_end_host;
340 this->public.set_end_host = (void (*) (traffic_selector_substructure_t *, host_t *))set_end_host;
341 this->public.get_traffic_selector = (traffic_selector_t* (*)(traffic_selector_substructure_t*))get_traffic_selector;
342
343 /* private functions */
344 this->compute_length = compute_length;
345
346 /* private variables */
347 this->payload_length = TRAFFIC_SELECTOR_HEADER_LENGTH;
348 this->start_port = 0;
349 this->end_port = 0;
350 this->starting_address = CHUNK_INITIALIZER;
351 this->ending_address = CHUNK_INITIALIZER;
352 this->ip_protocol_id = 0;
353 /* must be set to be valid */
354 this->ts_type = TS_IPV4_ADDR_RANGE;
355
356 return (&(this->public));
357 }
358
359 /*
360 * Described in header
361 */
362 traffic_selector_substructure_t *traffic_selector_substructure_create_from_traffic_selector(traffic_selector_t *traffic_selector)
363 {
364 private_traffic_selector_substructure_t *this = (private_traffic_selector_substructure_t*)traffic_selector_substructure_create();
365 this->ts_type = traffic_selector->get_type(traffic_selector);
366 this->ip_protocol_id = traffic_selector->get_protocol(traffic_selector);
367 this->start_port = traffic_selector->get_from_port(traffic_selector);
368 this->end_port = traffic_selector->get_to_port(traffic_selector);
369 this->starting_address = traffic_selector->get_from_address(traffic_selector);
370 this->ending_address = traffic_selector->get_to_address(traffic_selector);
371
372 this->compute_length(this);
373
374 return &(this->public);
375 }