- creation of ts payloads using ts
[strongswan.git] / Source / charon / config / traffic_selector.c
1 /**
2 * @file traffic_selector.c
3 *
4 * @brief Implementation of traffic_selector_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.h"
24
25 #include <utils/linked_list.h>
26 #include <utils/allocator.h>
27 #include <utils/identification.h>
28 #include <arpa/inet.h>
29
30 typedef struct private_traffic_selector_t private_traffic_selector_t;
31
32 /**
33 * Private data of an traffic_selector_t object
34 */
35 struct private_traffic_selector_t {
36
37 /**
38 * Public part
39 */
40 traffic_selector_t public;
41
42 /**
43 * Type of address
44 */
45 ts_type_t type;
46
47 /**
48 * IP protocol (UDP, TCP, ICMP, ...)
49 */
50 u_int8_t protocol;
51
52 /**
53 * begin of address range
54 */
55 union {
56 struct {
57 u_int32_t from_addr_ipv4;
58 };
59 struct {
60 };
61 };
62
63 /**
64 * end of address range
65 */
66 union {
67 struct {
68 u_int32_t to_addr_ipv4;
69 };
70 struct {
71 };
72 };
73
74 /**
75 * begin of port range
76 */
77 u_int16_t from_port;
78
79 /**
80 * end of port range
81 */
82 u_int16_t to_port;
83 };
84
85 /**
86 * internal generic constructor
87 */
88 static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts_type_t type, u_int16_t from_port, u_int16_t to_port);
89
90 /**
91 * implements traffic_selector_t.get_subset
92 */
93 static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_traffic_selector_t *other)
94 {
95 if ((this->type == TS_IPV4_ADDR_RANGE) &&
96 (other->type == TS_IPV4_ADDR_RANGE) &&
97 (this->protocol == other->protocol))
98 {
99 u_int32_t from_addr, to_addr;
100 u_int16_t from_port, to_port;
101 private_traffic_selector_t *new_ts;
102
103 /* calculate the maximum address range allowed for both */
104 from_addr = max(this->from_addr_ipv4, other->from_addr_ipv4);
105 to_addr = min(this->to_addr_ipv4, other->to_addr_ipv4);
106 if (from_addr > to_addr)
107 {
108 /* no match */
109 return NULL;
110 }
111
112 /* calculate the maximum port range allowed for both */
113 from_port = max(this->from_port, other->from_port);
114 to_port = min(this->to_port, other->to_port);
115 if (from_port > to_port)
116 {
117 /* no match */
118 return NULL;
119 }
120
121 /* got a match, return it */
122 new_ts = traffic_selector_create(this->protocol, this->type, from_port, to_port);
123 new_ts->from_addr_ipv4 = from_addr;
124 new_ts->to_addr_ipv4 = to_addr;
125 new_ts->type = TS_IPV4_ADDR_RANGE;
126 return &(new_ts->public);
127 }
128 return NULL;
129 }
130
131 /**
132 * Implements traffic_selector_t.get_from_address.
133 */
134 static chunk_t get_from_address(private_traffic_selector_t *this)
135 {
136 chunk_t from_addr = CHUNK_INITIALIZER;
137
138 switch (this->type)
139 {
140 case TS_IPV4_ADDR_RANGE:
141 {
142 u_int32_t network;
143 from_addr.len = sizeof(network);
144 from_addr.ptr = allocator_alloc(from_addr.len);
145 /* chunk must contain network order, convert! */
146 network = htonl(this->from_addr_ipv4);
147 memcpy(from_addr.ptr, &network, from_addr.len);
148 break;
149 }
150 case TS_IPV6_ADDR_RANGE:
151 {
152 break;
153 }
154 }
155 return from_addr;
156 }
157
158 /**
159 * Implements traffic_selector_t.get_to_address.
160 */
161 static chunk_t get_to_address(private_traffic_selector_t *this)
162 {
163 chunk_t to_addr = CHUNK_INITIALIZER;
164
165 switch (this->type)
166 {
167 case TS_IPV4_ADDR_RANGE:
168 {
169 u_int32_t network;
170 to_addr.len = sizeof(network);
171 to_addr.ptr = allocator_alloc(to_addr.len);
172 /* chunk must contain network order, convert! */
173 network = htonl(this->to_addr_ipv4);
174 memcpy(to_addr.ptr, &network, to_addr.len);
175 break;
176 }
177 case TS_IPV6_ADDR_RANGE:
178 {
179 break;
180 }
181 }
182 return to_addr;
183 }
184
185 /**
186 * Implements traffic_selector_t.get_from_port.
187 */
188 static u_int16_t get_from_port(private_traffic_selector_t *this)
189 {
190 return this->from_port;
191 }
192
193 /**
194 * Implements traffic_selector_t.get_to_port.
195 */
196 static u_int16_t get_to_port(private_traffic_selector_t *this)
197 {
198 return this->to_port;
199 }
200
201 /**
202 * Implements traffic_selector_t.get_type.
203 */
204 static ts_type_t get_type(private_traffic_selector_t *this)
205 {
206 return this->type;
207 }
208
209 /**
210 * Implements traffic_selector_t.get_protocol.
211 */
212 static u_int8_t get_protocol(private_traffic_selector_t *this)
213 {
214 return this->protocol;
215 }
216
217 /**
218 * Implements traffic_selector_t.clone.
219 */
220 static traffic_selector_t *clone(private_traffic_selector_t *this)
221 {
222 private_traffic_selector_t *clone = traffic_selector_create(this->protocol, this->type, this->from_port, this->to_port);
223 clone->type = this->type;
224 switch (clone->type)
225 {
226 case TS_IPV4_ADDR_RANGE:
227 {
228 clone->from_addr_ipv4 = this->from_addr_ipv4;
229 clone->to_addr_ipv4 = this->to_addr_ipv4;
230 return &(clone->public);
231 }
232 case TS_IPV6_ADDR_RANGE:
233 default:
234 {
235 allocator_free(this);
236 return NULL;
237 }
238 }
239 }
240
241 /**
242 * Implements traffic_selector_t.destroy.
243 */
244 static void destroy(private_traffic_selector_t *this)
245 {
246 allocator_free(this);
247 }
248
249 /*
250 * see header
251 */
252 traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_type_t type, chunk_t from_addr, int16_t from_port, chunk_t to_addr, u_int16_t to_port)
253 {
254 private_traffic_selector_t *this = traffic_selector_create(protocol, type, from_port, to_port);
255
256 this->type = type;
257 switch (type)
258 {
259 case TS_IPV4_ADDR_RANGE:
260 {
261 if (from_addr.len != 4 || to_addr.len != 4)
262 {
263 allocator_free(this);
264 return NULL;
265 }
266 /* chunk contains network order, convert! */
267 this->from_addr_ipv4 = ntohl(*((u_int32_t*)from_addr.ptr));
268 this->to_addr_ipv4 = ntohl(*((u_int32_t*)to_addr.ptr));
269 break;
270 }
271 case TS_IPV6_ADDR_RANGE:
272 default:
273 {
274 allocator_free(this);
275 return NULL;
276 }
277 }
278 return (&this->public);
279 }
280
281
282 /*
283 * Described in header-file
284 */
285 traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_type_t type, char *from_addr, u_int16_t from_port, char *to_addr, u_int16_t to_port)
286 {
287 private_traffic_selector_t *this = traffic_selector_create(protocol, type, from_port, to_port);
288
289 /* public functions */
290 this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset;
291 this->public.destroy = (void(*)(traffic_selector_t*))destroy;
292
293 this->type = type;
294 switch (type)
295 {
296 case TS_IPV4_ADDR_RANGE:
297 {
298 if (inet_aton(from_addr, (struct in_addr*)&(this->from_addr_ipv4)) == 0)
299 {
300 allocator_free(this);
301 return NULL;
302 }
303 if (inet_aton(to_addr, (struct in_addr*)&(this->to_addr_ipv4)) == 0)
304 {
305 allocator_free(this);
306 return NULL;
307 }
308 /* convert to host order, inet_aton has network order */
309 this->from_addr_ipv4 = ntohl(this->from_addr_ipv4);
310 this->to_addr_ipv4 = ntohl(this->to_addr_ipv4);
311 break;
312 }
313 case TS_IPV6_ADDR_RANGE:
314 {
315 allocator_free(this);
316 return NULL;
317 }
318 }
319
320 return (&this->public);
321 }
322
323 /*
324 * see declaration
325 */
326 static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts_type_t type, u_int16_t from_port, u_int16_t to_port)
327 {
328 private_traffic_selector_t *this = allocator_alloc_thing(private_traffic_selector_t);
329
330 /* public functions */
331 this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset;
332 this->public.get_from_address = (chunk_t(*)(traffic_selector_t*))get_from_address;
333 this->public.get_to_address = (chunk_t(*)(traffic_selector_t*))get_to_address;
334 this->public.get_from_port = (u_int16_t(*)(traffic_selector_t*))get_from_port;
335 this->public.get_to_port = (u_int16_t(*)(traffic_selector_t*))get_to_port;
336 this->public.get_type = (ts_type_t(*)(traffic_selector_t*))get_type;
337 this->public.get_protocol = (u_int8_t(*)(traffic_selector_t*))get_protocol;
338 this->public.clone = (traffic_selector_t*(*)(traffic_selector_t*))clone;
339 this->public.destroy = (void(*)(traffic_selector_t*))destroy;
340
341 this->from_port = from_port;
342 this->to_port = to_port;
343 this->protocol = protocol;
344 this->type = type;
345
346 return this;
347 }
348