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