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 <utils/logger_manager.h>
28 #include <arpa/inet.h>
31 typedef struct private_traffic_selector_t private_traffic_selector_t
;
34 * Private data of an traffic_selector_t object
36 struct private_traffic_selector_t
{
41 traffic_selector_t
public;
49 * IP protocol (UDP, TCP, ICMP, ...)
54 * begin of address range, host order
57 u_int32_t from_addr_ipv4
;
61 * end of address range, host order
64 u_int32_t to_addr_ipv4
;
84 * internal generic constructor
86 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 * implements traffic_selector_t.get_subset
91 static traffic_selector_t
*get_subset(private_traffic_selector_t
*this, private_traffic_selector_t
*other
)
93 if ((this->type
== TS_IPV4_ADDR_RANGE
) &&
94 (other
->type
== TS_IPV4_ADDR_RANGE
) &&
95 (this->protocol
== other
->protocol
))
97 u_int32_t from_addr
, to_addr
;
98 u_int16_t from_port
, to_port
;
99 private_traffic_selector_t
*new_ts
;
101 /* TODO: make output more human readable */
102 this->logger
->log(this->logger
, CONTROL
|LEVEL2
,
103 "matching traffic selector ranges %x:%d-%x:%d <=> %x:%d-%x:%d",
104 this->from_addr_ipv4
, this->from_port
, this->to_addr_ipv4
, this->to_port
,
105 other
->from_addr_ipv4
, other
->from_port
, other
->to_addr_ipv4
, other
->to_port
);
106 /* calculate the maximum address range allowed for both */
107 from_addr
= max(this->from_addr_ipv4
, other
->from_addr_ipv4
);
108 to_addr
= min(this->to_addr_ipv4
, other
->to_addr_ipv4
);
109 if (from_addr
> to_addr
)
111 this->logger
->log(this->logger
, CONTROL
|LEVEL2
,
112 "no match in address range");
116 /* calculate the maximum port range allowed for both */
117 from_port
= max(this->from_port
, other
->from_port
);
118 to_port
= min(this->to_port
, other
->to_port
);
119 if (from_port
> to_port
)
121 this->logger
->log(this->logger
, CONTROL
|LEVEL2
,
122 "no match in port range");
126 /* got a match, return it */
127 new_ts
= traffic_selector_create(this->protocol
, this->type
, from_port
, to_port
);
128 new_ts
->from_addr_ipv4
= from_addr
;
129 new_ts
->to_addr_ipv4
= to_addr
;
130 new_ts
->type
= TS_IPV4_ADDR_RANGE
;
132 this->logger
->log(this->logger
, CONTROL
|LEVEL2
,
133 "got a match: %x:%d-%x:%d",
134 new_ts
->from_addr_ipv4
, new_ts
->from_port
, new_ts
->to_addr_ipv4
, new_ts
->to_port
);
135 return &(new_ts
->public);
141 * Implements traffic_selector_t.get_from_address.
143 static chunk_t
get_from_address(private_traffic_selector_t
*this)
145 chunk_t from_addr
= CHUNK_INITIALIZER
;
149 case TS_IPV4_ADDR_RANGE
:
152 from_addr
.len
= sizeof(network
);
153 from_addr
.ptr
= malloc(from_addr
.len
);
154 /* chunk must contain network order, convert! */
155 network
= htonl(this->from_addr_ipv4
);
156 memcpy(from_addr
.ptr
, &network
, from_addr
.len
);
159 case TS_IPV6_ADDR_RANGE
:
168 * Implements traffic_selector_t.get_to_address.
170 static chunk_t
get_to_address(private_traffic_selector_t
*this)
172 chunk_t to_addr
= CHUNK_INITIALIZER
;
176 case TS_IPV4_ADDR_RANGE
:
179 to_addr
.len
= sizeof(network
);
180 to_addr
.ptr
= malloc(to_addr
.len
);
181 /* chunk must contain network order, convert! */
182 network
= htonl(this->to_addr_ipv4
);
183 memcpy(to_addr
.ptr
, &network
, to_addr
.len
);
186 case TS_IPV6_ADDR_RANGE
:
195 * Implements traffic_selector_t.get_from_port.
197 static u_int16_t
get_from_port(private_traffic_selector_t
*this)
199 return this->from_port
;
203 * Implements traffic_selector_t.get_to_port.
205 static u_int16_t
get_to_port(private_traffic_selector_t
*this)
207 return this->to_port
;
211 * Implements traffic_selector_t.get_type.
213 static ts_type_t
get_type(private_traffic_selector_t
*this)
219 * Implements traffic_selector_t.get_protocol.
221 static u_int8_t
get_protocol(private_traffic_selector_t
*this)
223 return this->protocol
;
227 * Implements traffic_selector_t.get_netmask.
229 static u_int8_t
get_netmask(private_traffic_selector_t
*this)
233 case TS_IPV4_ADDR_RANGE
:
235 u_int32_t from
, to
, bit
;
236 from
= htonl(this->from_addr_ipv4
);
237 to
= htonl(this->to_addr_ipv4
);
238 for (bit
= 0; bit
< 32; bit
++)
240 if ((1<<bit
& from
) != (1<<bit
& to
))
247 case TS_IPV6_ADDR_RANGE
:
256 * Implements traffic_selector_t.update_address_range.
258 static void update_address_range(private_traffic_selector_t
*this, host_t
*host
)
260 if (host
->get_family(host
) == AF_INET
&&
261 this->type
== TS_IPV4_ADDR_RANGE
)
263 if (this->from_addr_ipv4
== 0)
265 chunk_t from
= host
->get_address_as_chunk(host
);
266 this->from_addr_ipv4
= ntohl(*((u_int32_t
*)from
.ptr
));
267 this->to_addr_ipv4
= this->from_addr_ipv4
;
274 * Implements traffic_selector_t.clone.
276 static traffic_selector_t
*clone_(private_traffic_selector_t
*this)
278 private_traffic_selector_t
*clone
= traffic_selector_create(this->protocol
, this->type
, this->from_port
, this->to_port
);
279 clone
->type
= this->type
;
282 case TS_IPV4_ADDR_RANGE
:
284 clone
->from_addr_ipv4
= this->from_addr_ipv4
;
285 clone
->to_addr_ipv4
= this->to_addr_ipv4
;
286 return &(clone
->public);
288 case TS_IPV6_ADDR_RANGE
:
298 * Implements traffic_selector_t.destroy.
300 static void destroy(private_traffic_selector_t
*this)
308 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
)
310 private_traffic_selector_t
*this = traffic_selector_create(protocol
, type
, from_port
, to_port
);
315 case TS_IPV4_ADDR_RANGE
:
317 if (from_addr
.len
!= 4 || to_addr
.len
!= 4)
322 /* chunk contains network order, convert! */
323 this->from_addr_ipv4
= ntohl(*((u_int32_t
*)from_addr
.ptr
));
324 this->to_addr_ipv4
= ntohl(*((u_int32_t
*)to_addr
.ptr
));
327 case TS_IPV6_ADDR_RANGE
:
334 return (&this->public);
340 traffic_selector_t
*traffic_selector_create_from_subnet(host_t
*net
, u_int8_t netbits
)
342 private_traffic_selector_t
*this = traffic_selector_create(0, 0, 0, 65535);
344 switch (net
->get_family(net
))
350 this->type
= TS_IPV4_ADDR_RANGE
;
351 from
= net
->get_address_as_chunk(net
);
352 this->from_addr_ipv4
= ntohl(*((u_int32_t
*)from
.ptr
));
353 if (this->from_addr_ipv4
== 0)
355 /* use /0 for 0.0.0.0 */
356 this->to_addr_ipv4
= ~0;
360 this->to_addr_ipv4
= this->from_addr_ipv4
| ((1 << (32 - netbits
)) - 1);
372 return (&this->public);
378 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
)
380 private_traffic_selector_t
*this = traffic_selector_create(protocol
, type
, from_port
, to_port
);
382 /* public functions */
383 this->public.get_subset
= (traffic_selector_t
*(*)(traffic_selector_t
*,traffic_selector_t
*))get_subset
;
384 this->public.destroy
= (void(*)(traffic_selector_t
*))destroy
;
389 case TS_IPV4_ADDR_RANGE
:
391 if (inet_aton(from_addr
, (struct in_addr
*)&(this->from_addr_ipv4
)) == 0)
396 if (inet_aton(to_addr
, (struct in_addr
*)&(this->to_addr_ipv4
)) == 0)
401 /* convert to host order, inet_aton has network order */
402 this->from_addr_ipv4
= ntohl(this->from_addr_ipv4
);
403 this->to_addr_ipv4
= ntohl(this->to_addr_ipv4
);
406 case TS_IPV6_ADDR_RANGE
:
413 return (&this->public);
419 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
)
421 private_traffic_selector_t
*this = malloc_thing(private_traffic_selector_t
);
423 /* public functions */
424 this->public.get_subset
= (traffic_selector_t
*(*)(traffic_selector_t
*,traffic_selector_t
*))get_subset
;
425 this->public.get_from_address
= (chunk_t(*)(traffic_selector_t
*))get_from_address
;
426 this->public.get_to_address
= (chunk_t(*)(traffic_selector_t
*))get_to_address
;
427 this->public.get_from_port
= (u_int16_t(*)(traffic_selector_t
*))get_from_port
;
428 this->public.get_to_port
= (u_int16_t(*)(traffic_selector_t
*))get_to_port
;
429 this->public.get_type
= (ts_type_t(*)(traffic_selector_t
*))get_type
;
430 this->public.get_protocol
= (u_int8_t(*)(traffic_selector_t
*))get_protocol
;
431 this->public.get_netmask
= (u_int8_t(*)(traffic_selector_t
*))get_netmask
;
432 this->public.update_address_range
= (void(*)(traffic_selector_t
*,host_t
*))update_address_range
;
433 this->public.clone
= (traffic_selector_t
*(*)(traffic_selector_t
*))clone_
;
434 this->public.destroy
= (void(*)(traffic_selector_t
*))destroy
;
436 this->from_port
= from_port
;
437 this->to_port
= to_port
;
438 this->protocol
= protocol
;
440 this->logger
= logger_manager
->get_logger(logger_manager
, CONFIG
);