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