2 * @file traffic_selector.c
4 * @brief Implementation of traffic_selector_t.
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
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>.
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
23 #include "traffic_selector.h"
25 #include <utils/linked_list.h>
26 #include <utils/identification.h>
27 #include <arpa/inet.h>
30 typedef struct private_traffic_selector_t private_traffic_selector_t
;
33 * Private data of an traffic_selector_t object
35 struct private_traffic_selector_t
{
40 traffic_selector_t
public;
48 * IP protocol (UDP, TCP, ICMP, ...)
53 * begin of address range, host order
56 u_int32_t from_addr_ipv4
;
60 * end of address range, host order
63 u_int32_t to_addr_ipv4
;
78 * internal generic constructor
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
);
83 * implements traffic_selector_t.get_subset
85 static traffic_selector_t
*get_subset(private_traffic_selector_t
*this, private_traffic_selector_t
*other
)
87 if ((this->type
== TS_IPV4_ADDR_RANGE
) &&
88 (other
->type
== TS_IPV4_ADDR_RANGE
) &&
89 (this->protocol
== other
->protocol
))
91 u_int32_t from_addr
, to_addr
;
92 u_int16_t from_port
, to_port
;
93 private_traffic_selector_t
*new_ts
;
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
)
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
)
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);
124 * Implements traffic_selector_t.get_from_address.
126 static chunk_t
get_from_address(private_traffic_selector_t
*this)
128 chunk_t from_addr
= CHUNK_INITIALIZER
;
132 case TS_IPV4_ADDR_RANGE
:
135 from_addr
.len
= sizeof(network
);
136 from_addr
.ptr
= malloc(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
);
142 case TS_IPV6_ADDR_RANGE
:
151 * Implements traffic_selector_t.get_to_address.
153 static chunk_t
get_to_address(private_traffic_selector_t
*this)
155 chunk_t to_addr
= CHUNK_INITIALIZER
;
159 case TS_IPV4_ADDR_RANGE
:
162 to_addr
.len
= sizeof(network
);
163 to_addr
.ptr
= malloc(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
);
169 case TS_IPV6_ADDR_RANGE
:
178 * Implements traffic_selector_t.get_from_port.
180 static u_int16_t
get_from_port(private_traffic_selector_t
*this)
182 return this->from_port
;
186 * Implements traffic_selector_t.get_to_port.
188 static u_int16_t
get_to_port(private_traffic_selector_t
*this)
190 return this->to_port
;
194 * Implements traffic_selector_t.get_type.
196 static ts_type_t
get_type(private_traffic_selector_t
*this)
202 * Implements traffic_selector_t.get_protocol.
204 static u_int8_t
get_protocol(private_traffic_selector_t
*this)
206 return this->protocol
;
210 * Implements traffic_selector_t.get_netmask.
212 static u_int8_t
get_netmask(private_traffic_selector_t
*this)
216 case TS_IPV4_ADDR_RANGE
:
218 u_int32_t from
, to
, bit
;
219 from
= htonl(this->from_addr_ipv4
);
220 to
= htonl(this->to_addr_ipv4
);
221 for (bit
= 0; bit
< 32; bit
++)
223 if ((1<<bit
& from
) != (1<<bit
& to
))
230 case TS_IPV6_ADDR_RANGE
:
239 * Implements traffic_selector_t.update_address_range.
241 static void update_address_range(private_traffic_selector_t
*this, host_t
*host
)
243 if (host
->get_family(host
) == AF_INET
&&
244 this->type
== TS_IPV4_ADDR_RANGE
)
246 if (this->from_addr_ipv4
== 0)
248 chunk_t from
= host
->get_address_as_chunk(host
);
249 this->from_addr_ipv4
= ntohl(*((u_int32_t
*)from
.ptr
));
250 this->to_addr_ipv4
= this->from_addr_ipv4
;
257 * Implements traffic_selector_t.clone.
259 static traffic_selector_t
*clone(private_traffic_selector_t
*this)
261 private_traffic_selector_t
*clone
= traffic_selector_create(this->protocol
, this->type
, this->from_port
, this->to_port
);
262 clone
->type
= this->type
;
265 case TS_IPV4_ADDR_RANGE
:
267 clone
->from_addr_ipv4
= this->from_addr_ipv4
;
268 clone
->to_addr_ipv4
= this->to_addr_ipv4
;
269 return &(clone
->public);
271 case TS_IPV6_ADDR_RANGE
:
281 * Implements traffic_selector_t.destroy.
283 static void destroy(private_traffic_selector_t
*this)
291 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
)
293 private_traffic_selector_t
*this = traffic_selector_create(protocol
, type
, from_port
, to_port
);
298 case TS_IPV4_ADDR_RANGE
:
300 if (from_addr
.len
!= 4 || to_addr
.len
!= 4)
305 /* chunk contains network order, convert! */
306 this->from_addr_ipv4
= ntohl(*((u_int32_t
*)from_addr
.ptr
));
307 this->to_addr_ipv4
= ntohl(*((u_int32_t
*)to_addr
.ptr
));
310 case TS_IPV6_ADDR_RANGE
:
317 return (&this->public);
323 traffic_selector_t
*traffic_selector_create_from_subnet(host_t
*net
, u_int8_t netbits
)
325 private_traffic_selector_t
*this = traffic_selector_create(0, 0, 0, 65535);
327 switch (net
->get_family(net
))
333 this->type
= TS_IPV4_ADDR_RANGE
;
334 from
= net
->get_address_as_chunk(net
);
335 this->from_addr_ipv4
= ntohl(*((u_int32_t
*)from
.ptr
));
336 if (this->from_addr_ipv4
== 0)
338 /* use /32 for 0.0.0.0 */
339 this->to_addr_ipv4
= 0xFFFFFF;
343 this->to_addr_ipv4
= this->from_addr_ipv4
| ((1 << (32 - netbits
)) - 1);
355 return (&this->public);
361 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
)
363 private_traffic_selector_t
*this = traffic_selector_create(protocol
, type
, from_port
, to_port
);
365 /* public functions */
366 this->public.get_subset
= (traffic_selector_t
*(*)(traffic_selector_t
*,traffic_selector_t
*))get_subset
;
367 this->public.destroy
= (void(*)(traffic_selector_t
*))destroy
;
372 case TS_IPV4_ADDR_RANGE
:
374 if (inet_aton(from_addr
, (struct in_addr
*)&(this->from_addr_ipv4
)) == 0)
379 if (inet_aton(to_addr
, (struct in_addr
*)&(this->to_addr_ipv4
)) == 0)
384 /* convert to host order, inet_aton has network order */
385 this->from_addr_ipv4
= ntohl(this->from_addr_ipv4
);
386 this->to_addr_ipv4
= ntohl(this->to_addr_ipv4
);
389 case TS_IPV6_ADDR_RANGE
:
396 return (&this->public);
402 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
)
404 private_traffic_selector_t
*this = malloc_thing(private_traffic_selector_t
);
406 /* public functions */
407 this->public.get_subset
= (traffic_selector_t
*(*)(traffic_selector_t
*,traffic_selector_t
*))get_subset
;
408 this->public.get_from_address
= (chunk_t(*)(traffic_selector_t
*))get_from_address
;
409 this->public.get_to_address
= (chunk_t(*)(traffic_selector_t
*))get_to_address
;
410 this->public.get_from_port
= (u_int16_t(*)(traffic_selector_t
*))get_from_port
;
411 this->public.get_to_port
= (u_int16_t(*)(traffic_selector_t
*))get_to_port
;
412 this->public.get_type
= (ts_type_t(*)(traffic_selector_t
*))get_type
;
413 this->public.get_protocol
= (u_int8_t(*)(traffic_selector_t
*))get_protocol
;
414 this->public.get_netmask
= (u_int8_t(*)(traffic_selector_t
*))get_netmask
;
415 this->public.update_address_range
= (void(*)(traffic_selector_t
*,host_t
*))update_address_range
;
416 this->public.clone
= (traffic_selector_t
*(*)(traffic_selector_t
*))clone
;
417 this->public.destroy
= (void(*)(traffic_selector_t
*))destroy
;
419 this->from_port
= from_port
;
420 this->to_port
= to_port
;
421 this->protocol
= protocol
;