moved traffic_selectors from charon to libstrongswan
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 20 Dec 2009 13:57:38 +0000 (14:57 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 20 Dec 2009 13:57:38 +0000 (14:57 +0100)
14 files changed:
src/charon/Makefile.am
src/charon/config/child_cfg.h
src/charon/config/peer_cfg.h
src/charon/config/proposal.h
src/charon/config/traffic_selector.c [deleted file]
src/charon/config/traffic_selector.h [deleted file]
src/charon/daemon.c
src/charon/encoding/payloads/traffic_selector_substructure.h
src/charon/encoding/payloads/ts_payload.h
src/charon/processing/jobs/acquire_job.h
src/charon/processing/jobs/migrate_job.h
src/libstrongswan/Makefile.am
src/libstrongswan/selectors/traffic_selector.c [new file with mode: 0644]
src/libstrongswan/selectors/traffic_selector.h [new file with mode: 0644]

index 9302b63..1d6fa6d 100644 (file)
@@ -11,7 +11,6 @@ config/ike_cfg.c config/ike_cfg.h \
 config/peer_cfg.c config/peer_cfg.h \
 config/proposal.c config/proposal.h \
 config/auth_cfg.c config/auth_cfg.h \
-config/traffic_selector.c config/traffic_selector.h \
 control/controller.c control/controller.h \
 daemon.c daemon.h \
 encoding/generator.c encoding/generator.h \
index becee81..b189ab4 100644 (file)
@@ -29,8 +29,8 @@ typedef struct lifetime_cfg_t lifetime_cfg_t;
 typedef struct child_cfg_t child_cfg_t;
 
 #include <library.h>
+#include <selectors/traffic_selector.h>
 #include <config/proposal.h>
-#include <config/traffic_selector.h>
 #include <kernel/kernel_ipsec.h>
 
 /**
index 94a04bd..6855276 100644 (file)
@@ -30,7 +30,7 @@ typedef struct peer_cfg_t peer_cfg_t;
 #include <library.h>
 #include <utils/identification.h>
 #include <utils/enumerator.h>
-#include <config/traffic_selector.h>
+#include <selectors/traffic_selector.h>
 #include <config/proposal.h>
 #include <config/ike_cfg.h>
 #include <config/child_cfg.h>
index c342fb9..d3973fb 100644 (file)
@@ -33,7 +33,7 @@ typedef struct proposal_t proposal_t;
 #include <crypto/crypters/crypter.h>
 #include <crypto/signers/signer.h>
 #include <crypto/diffie_hellman.h>
-#include <config/traffic_selector.h>
+#include <selectors/traffic_selector.h>
 
 /**
  * Protocol ID of a proposal.
diff --git a/src/charon/config/traffic_selector.c b/src/charon/config/traffic_selector.c
deleted file mode 100644 (file)
index 40977db..0000000
+++ /dev/null
@@ -1,857 +0,0 @@
-/*
- * Copyright (C) 2007-2009 Tobias Brunner
- * Copyright (C) 2005-2007 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include <arpa/inet.h>
-#include <string.h>
-#include <netdb.h>
-#include <stdio.h>
-
-#include "traffic_selector.h"
-
-#include <daemon.h>
-#include <utils/linked_list.h>
-#include <utils/identification.h>
-
-ENUM(ts_type_name, TS_IPV4_ADDR_RANGE, TS_IPV6_ADDR_RANGE,
-       "TS_IPV4_ADDR_RANGE",
-       "TS_IPV6_ADDR_RANGE",
-);
-
-typedef struct private_traffic_selector_t private_traffic_selector_t;
-
-/**
- * Private data of an traffic_selector_t object
- */
-struct private_traffic_selector_t {
-
-       /**
-        * Public part
-        */
-       traffic_selector_t public;
-
-       /**
-        * Type of address
-        */
-       ts_type_t type;
-
-       /**
-        * IP protocol (UDP, TCP, ICMP, ...)
-        */
-       u_int8_t protocol;
-
-       /**
-        * narrow this traffic selector to hosts external ip
-        * if set, from and to have no meaning until set_address() is called
-        */
-       bool dynamic;
-
-       /**
-        * begin of address range, network order
-        */
-       union {
-               /** dummy char for common address manipulation */
-               char from[0];
-               /** IPv4 address */
-               u_int32_t from4[1];
-               /** IPv6 address */
-               u_int32_t from6[4];
-       };
-
-       /**
-        * end of address range, network order
-        */
-       union {
-               /** dummy char for common address manipulation */
-               char to[0];
-               /** IPv4 address */
-               u_int32_t to4[1];
-               /** IPv6 address */
-               u_int32_t to6[4];
-       };
-
-       /**
-        * begin of port range
-        */
-       u_int16_t from_port;
-
-       /**
-        * end of port range
-        */
-       u_int16_t to_port;
-};
-
-/**
- * calculate to "to"-address for the "from" address and a subnet size
- */
-static void calc_range(private_traffic_selector_t *this, u_int8_t netbits)
-{
-       int byte;
-       size_t size = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
-
-       /* go through the from address, starting at the tail. While we
-        * have not processed the bits belonging to the host, set them to 1 on
-        * the to address. If we reach the bits for the net, copy them from "from". */
-       for (byte = size - 1; byte >=0; byte--)
-       {
-               u_char mask = 0x00;
-               int shift;
-
-               shift = (byte+1) * 8 - netbits;
-               if (shift > 0)
-               {
-                       mask = 1 << shift;
-                       if (mask != 0xFF)
-                       {
-                               mask--;
-                       }
-               }
-               this->from[byte] &= ~mask;
-               this->to[byte] = this->from[byte] | mask;
-       }
-}
-
-/**
- * calculate to subnet size from "to"- and "from"-address
- */
-static u_int8_t calc_netbits(private_traffic_selector_t *this)
-{
-       int byte, bit;
-       size_t size = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
-
-       /* go trough all bits of the addresses, beginning in the front.
-        * as long as they are equal, the subnet gets larger
-        */
-       for (byte = 0; byte < size; byte++)
-       {
-               for (bit = 7; bit >= 0; bit--)
-               {
-                       if ((1<<bit & this->from[byte]) != (1<<bit & this->to[byte]))
-                       {
-                               return ((7 - bit) + (byte * 8));
-                       }
-               }
-       }
-       /* single host, netmask is 32/128 */
-       return (size * 8);
-}
-
-/**
- * internal generic constructor
- */
-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);
-
-/**
- * Described in header.
- */
-int traffic_selector_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
-                                                                const void *const *args)
-{
-       private_traffic_selector_t *this = *((private_traffic_selector_t**)(args[0]));
-       linked_list_t *list = *((linked_list_t**)(args[0]));
-       iterator_t *iterator;
-       char addr_str[INET6_ADDRSTRLEN] = "";
-       char *serv_proto = NULL;
-       u_int8_t mask;
-       bool has_proto;
-       bool has_ports;
-       size_t written = 0;
-       u_int32_t from[4], to[4];
-
-       if (this == NULL)
-       {
-               return print_in_hook(dst, len, "(null)");
-       }
-
-       if (spec->hash)
-       {
-               iterator = list->create_iterator(list, TRUE);
-               while (iterator->iterate(iterator, (void**)&this))
-               {
-                       /* call recursivly */
-                       written += print_in_hook(dst, len, "%R ", this);
-               }
-               iterator->destroy(iterator);
-               return written;
-       }
-
-       memset(from, 0, sizeof(from));
-       memset(to, 0xFF, sizeof(to));
-       if (this->dynamic &&
-               memeq(this->from, from, this->type == TS_IPV4_ADDR_RANGE ? 4 : 16) &&
-               memeq(this->to, to, this->type == TS_IPV4_ADDR_RANGE ? 4 : 16))
-       {
-               written += print_in_hook(dst, len, "dynamic");
-       }
-       else
-       {
-               if (this->type == TS_IPV4_ADDR_RANGE)
-               {
-                       inet_ntop(AF_INET, &this->from4, addr_str, sizeof(addr_str));
-               }
-               else
-               {
-                       inet_ntop(AF_INET6, &this->from6, addr_str, sizeof(addr_str));
-               }
-               mask = calc_netbits(this);
-               written += print_in_hook(dst, len, "%s/%d", addr_str, mask);
-       }
-
-       /* check if we have protocol and/or port selectors */
-       has_proto = this->protocol != 0;
-       has_ports = !(this->from_port == 0 && this->to_port == 0xFFFF);
-
-       if (!has_proto && !has_ports)
-       {
-               return written;
-       }
-
-       written += print_in_hook(dst, len, "[");
-
-       /* build protocol string */
-       if (has_proto)
-       {
-               struct protoent *proto = getprotobynumber(this->protocol);
-
-               if (proto)
-               {
-                       written += print_in_hook(dst, len, "%s", proto->p_name);
-                       serv_proto = proto->p_name;
-               }
-               else
-               {
-                       written += print_in_hook(dst, len, "%d", this->protocol);
-               }
-       }
-
-       if (has_proto && has_ports)
-       {
-               written += print_in_hook(dst, len, "/");
-       }
-
-       /* build port string */
-       if (has_ports)
-       {
-               if (this->from_port == this->to_port)
-               {
-                       struct servent *serv = getservbyport(htons(this->from_port), serv_proto);
-
-                       if (serv)
-                       {
-                               written += print_in_hook(dst, len, "%s", serv->s_name);
-                       }
-                       else
-                       {
-                               written += print_in_hook(dst, len, "%d", this->from_port);
-                       }
-               }
-               else
-               {
-                       written += print_in_hook(dst, len, "%d-%d", this->from_port, this->to_port);
-               }
-       }
-
-       written += print_in_hook(dst, len, "]");
-
-       return written;
-}
-
-/**
- * implements traffic_selector_t.get_subset
- */
-static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_traffic_selector_t *other)
-{
-       if (this->type == other->type && (this->protocol == other->protocol ||
-                                                               this->protocol == 0 || other->protocol == 0))
-       {
-               u_int16_t from_port, to_port;
-               u_char *from, *to;
-               u_int8_t protocol;
-               size_t size;
-               private_traffic_selector_t *new_ts;
-
-               /* calculate the maximum port range allowed for both */
-               from_port = max(this->from_port, other->from_port);
-               to_port = min(this->to_port, other->to_port);
-               if (from_port > to_port)
-               {
-                       return NULL;
-               }
-               /* select protocol, which is not zero */
-               protocol = max(this->protocol, other->protocol);
-
-               switch (this->type)
-               {
-                       case TS_IPV4_ADDR_RANGE:
-                               size = sizeof(this->from4);
-                               break;
-                       case TS_IPV6_ADDR_RANGE:
-                               size = sizeof(this->from6);
-                               break;
-                       default:
-                               return NULL;
-               }
-
-               /* get higher from-address */
-               if (memcmp(this->from, other->from, size) > 0)
-               {
-                       from = this->from;
-               }
-               else
-               {
-                       from = other->from;
-               }
-               /* get lower to-address */
-               if (memcmp(this->to, other->to, size) > 0)
-               {
-                       to = other->to;
-               }
-               else
-               {
-                       to = this->to;
-               }
-               /* if "from" > "to", we don't have a match */
-               if (memcmp(from, to, size) > 0)
-               {
-                       return NULL;
-               }
-
-               /* we have a match in protocol, port, and address: return it... */
-               new_ts = traffic_selector_create(protocol, this->type, from_port, to_port);
-               new_ts->type = this->type;
-               new_ts->dynamic = this->dynamic || other->dynamic;
-               memcpy(new_ts->from, from, size);
-               memcpy(new_ts->to, to, size);
-
-               return &new_ts->public;
-       }
-       return NULL;
-}
-
-/**
- * implements traffic_selector_t.equals
- */
-static bool equals(private_traffic_selector_t *this, private_traffic_selector_t *other)
-{
-       if (this->type != other->type)
-       {
-               return FALSE;
-       }
-       if (!(this->from_port == other->from_port &&
-                 this->to_port == other->to_port &&
-                 this->protocol == other->protocol))
-       {
-               return FALSE;
-       }
-       switch (this->type)
-       {
-               case TS_IPV4_ADDR_RANGE:
-                       if (memeq(this->from4, other->from4, sizeof(this->from4)))
-                       {
-                               return TRUE;
-                       }
-                       break;
-               case TS_IPV6_ADDR_RANGE:
-                       if (memeq(this->from6, other->from6, sizeof(this->from6)))
-                       {
-                               return TRUE;
-                       }
-                       break;
-               default:
-                       break;
-       }
-       return FALSE;
-}
-
-/**
- * Implements traffic_selector_t.get_from_address.
- */
-static chunk_t get_from_address(private_traffic_selector_t *this)
-{
-       switch (this->type)
-       {
-               case TS_IPV4_ADDR_RANGE:
-                       return chunk_create(this->from, sizeof(this->from4));
-               case TS_IPV6_ADDR_RANGE:
-                       return chunk_create(this->from, sizeof(this->from6));
-               default:
-                       return chunk_empty;
-       }
-}
-
-/**
- * Implements traffic_selector_t.get_to_address.
- */
-static chunk_t get_to_address(private_traffic_selector_t *this)
-{
-       switch (this->type)
-       {
-               case TS_IPV4_ADDR_RANGE:
-                       return chunk_create(this->to, sizeof(this->to4));
-               case TS_IPV6_ADDR_RANGE:
-                       return chunk_create(this->to, sizeof(this->to6));
-               default:
-                       return chunk_empty;
-       }
-}
-
-/**
- * Implements traffic_selector_t.get_from_port.
- */
-static u_int16_t get_from_port(private_traffic_selector_t *this)
-{
-       return this->from_port;
-}
-
-/**
- * Implements traffic_selector_t.get_to_port.
- */
-static u_int16_t get_to_port(private_traffic_selector_t *this)
-{
-       return this->to_port;
-}
-
-/**
- * Implements traffic_selector_t.get_type.
- */
-static ts_type_t get_type(private_traffic_selector_t *this)
-{
-       return this->type;
-}
-
-/**
- * Implements traffic_selector_t.get_protocol.
- */
-static u_int8_t get_protocol(private_traffic_selector_t *this)
-{
-       return this->protocol;
-}
-
-/**
- * Implements traffic_selector_t.is_host.
- */
-static bool is_host(private_traffic_selector_t *this, host_t *host)
-{
-       if (host)
-       {
-               chunk_t addr;
-               int family = host->get_family(host);
-
-               if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
-                       (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
-               {
-                       addr = host->get_address(host);
-                       if (memeq(addr.ptr, this->from, addr.len) &&
-                               memeq(addr.ptr, this->to, addr.len))
-                       {
-                               return TRUE;
-                       }
-               }
-       }
-       else
-       {
-               size_t length = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
-
-               if (this->dynamic)
-               {
-                       return TRUE;
-               }
-
-               if (memeq(this->from, this->to, length))
-               {
-                       return TRUE;
-               }
-       }
-       return FALSE;
-}
-
-/**
- * Implementation of traffic_selector_t.is_dynamic
- */
-static bool is_dynamic(private_traffic_selector_t *this)
-{
-       return this->dynamic;
-}
-
-/**
- * Implements traffic_selector_t.set_address.
- */
-static void set_address(private_traffic_selector_t *this, host_t *host)
-{
-       if (this->dynamic)
-       {
-               this->type = host->get_family(host) == AF_INET ?
-                               TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
-
-               if (host->is_anyaddr(host))
-               {
-                       memset(this->from6, 0x00, sizeof(this->from6));
-                       memset(this->to6, 0xFF, sizeof(this->to6));
-               }
-               else
-               {
-                       chunk_t from = host->get_address(host);
-                       memcpy(this->from, from.ptr, from.len);
-                       memcpy(this->to, from.ptr, from.len);
-               }
-       }
-}
-
-/**
- * Implements traffic_selector_t.is_contained_in.
- */
-static bool is_contained_in(private_traffic_selector_t *this,
-                                                       private_traffic_selector_t *other)
-{
-       private_traffic_selector_t *subset;
-       bool contained_in = FALSE;
-
-       subset = (private_traffic_selector_t*)get_subset(this, other);
-
-       if (subset)
-       {
-               if (equals(subset, this))
-               {
-                       contained_in = TRUE;
-               }
-               free(subset);
-       }
-       return contained_in;
-}
-
-/**
- * Implements traffic_selector_t.includes.
- */
-static bool includes(private_traffic_selector_t *this, host_t *host)
-{
-       chunk_t addr;
-       int family = host->get_family(host);
-
-       if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
-               (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
-       {
-               addr = host->get_address(host);
-
-               return memcmp(this->from, addr.ptr, addr.len) <= 0 &&
-                               memcmp(this->to, addr.ptr, addr.len) >= 0;
-       }
-
-       return FALSE;
-}
-
-/**
- * Implements traffic_selector_t.to_subnet.
- */
-static void to_subnet(private_traffic_selector_t *this, host_t **net, u_int8_t *mask)
-{
-       /* there is no way to do this cleanly, as the address range may
-        * be anything else but a subnet. We use from_addr as subnet
-        * and try to calculate a usable subnet mask.
-        */
-       int family, byte;
-       u_int16_t port = 0;
-       chunk_t net_chunk;
-
-       *mask = calc_netbits(this);
-
-       switch (this->type)
-       {
-               case TS_IPV4_ADDR_RANGE:
-               {
-                       family = AF_INET;
-                       net_chunk.len = sizeof(this->from4);
-                       break;
-               }
-               case TS_IPV6_ADDR_RANGE:
-               {
-                       family = AF_INET6;
-                       net_chunk.len = sizeof(this->from6);
-                       break;
-               }
-               default:
-               {
-                       /* unreachable */
-                       return;
-               }
-       }
-
-       net_chunk.ptr = malloc(net_chunk.len);
-       memcpy(net_chunk.ptr, this->from, net_chunk.len);
-
-       for (byte = net_chunk.len - 1; byte >= (*mask / 8); --byte)
-       {
-               int shift = (byte + 1) * 8 - *mask;
-               net_chunk.ptr[byte] = net_chunk.ptr[byte] & (0xFF << shift);
-       }
-
-       if (this->to_port == this->from_port)
-       {
-               port = this->to_port;
-       }
-
-       *net = host_create_from_chunk(family, net_chunk, port);
-       chunk_free(&net_chunk);
-}
-
-/**
- * Implements traffic_selector_t.clone.
- */
-static traffic_selector_t *clone_(private_traffic_selector_t *this)
-{
-       private_traffic_selector_t *clone;
-
-       clone = traffic_selector_create(this->protocol, this->type,
-                                                                       this->from_port, this->to_port);
-
-       clone->dynamic = this->dynamic;
-       switch (clone->type)
-       {
-               case TS_IPV4_ADDR_RANGE:
-               {
-                       memcpy(clone->from4, this->from4, sizeof(this->from4));
-                       memcpy(clone->to4, this->to4, sizeof(this->to4));
-                       return &clone->public;
-               }
-               case TS_IPV6_ADDR_RANGE:
-               {
-                       memcpy(clone->from6, this->from6, sizeof(this->from6));
-                       memcpy(clone->to6, this->to6, sizeof(this->to6));
-                       return &clone->public;
-               }
-               default:
-               {
-                       /* unreachable */
-                       return &clone->public;
-               }
-       }
-}
-
-/**
- * Implements traffic_selector_t.destroy.
- */
-static void destroy(private_traffic_selector_t *this)
-{
-       free(this);
-}
-
-/*
- * see header
- */
-traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol,
-                                                                                               ts_type_t type,
-                                                                                               chunk_t from, u_int16_t from_port,
-                                                                                               chunk_t to, u_int16_t to_port)
-{
-       private_traffic_selector_t *this = traffic_selector_create(protocol, type,
-                                                                                                                       from_port, to_port);
-
-       switch (type)
-       {
-               case TS_IPV4_ADDR_RANGE:
-               {
-                       if (from.len != 4 || to.len != 4)
-                       {
-                               free(this);
-                               return NULL;
-                       }
-                       memcpy(this->from4, from.ptr, from.len);
-                       memcpy(this->to4, to.ptr, to.len);
-                       break;
-               }
-               case TS_IPV6_ADDR_RANGE:
-               {
-                       if (from.len != 16 || to.len != 16)
-                       {
-                               free(this);
-                               return NULL;
-                       }
-                       memcpy(this->from6, from.ptr, from.len);
-                       memcpy(this->to6, to.ptr, to.len);
-                       break;
-               }
-               default:
-               {
-                       free(this);
-                       return NULL;
-               }
-       }
-       return (&this->public);
-}
-
-/*
- * see header
- */
-traffic_selector_t *traffic_selector_create_from_subnet(host_t *net,
-                                                       u_int8_t netbits, u_int8_t protocol, u_int16_t port)
-{
-       private_traffic_selector_t *this = traffic_selector_create(protocol, 0, 0, 65535);
-
-       switch (net->get_family(net))
-       {
-               case AF_INET:
-               {
-                       chunk_t from;
-
-                       this->type = TS_IPV4_ADDR_RANGE;
-                       from = net->get_address(net);
-                       memcpy(this->from4, from.ptr, from.len);
-                       if (this->from4[0] == 0)
-                       {
-                               /* use /0 for 0.0.0.0 */
-                               this->to4[0] = ~0;
-                       }
-                       else
-                       {
-                               calc_range(this, netbits);
-                       }
-                       break;
-               }
-               case AF_INET6:
-               {
-                       chunk_t from;
-
-                       this->type = TS_IPV6_ADDR_RANGE;
-                       from = net->get_address(net);
-                       memcpy(this->from6, from.ptr, from.len);
-                       if (this->from6[0] == 0 && this->from6[1] == 0 &&
-                               this->from6[2] == 0 && this->from6[3] == 0)
-                       {
-                               /* use /0 for ::0 */
-                               this->to6[0] = ~0;
-                               this->to6[1] = ~0;
-                               this->to6[2] = ~0;
-                               this->to6[3] = ~0;
-                       }
-                       else
-                       {
-                               calc_range(this, netbits);
-                       }
-                       break;
-               }
-               default:
-               {
-                       net->destroy(net);
-                       free(this);
-                       return NULL;
-               }
-       }
-       if (port)
-       {
-               this->from_port = port;
-               this->to_port = port;
-       }
-       net->destroy(net);
-       return (&this->public);
-}
-
-/*
- * see header
- */
-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)
-{
-       private_traffic_selector_t *this = traffic_selector_create(protocol, type,
-                                                                                                                       from_port, to_port);
-
-       this->type = type;
-       switch (type)
-       {
-               case TS_IPV4_ADDR_RANGE:
-               {
-                       if (inet_pton(AF_INET, from_addr, (struct in_addr*)this->from4) < 0)
-                       {
-                               free(this);
-                               return NULL;
-                       }
-                       if (inet_pton(AF_INET, to_addr, (struct in_addr*)this->to4) < 0)
-                       {
-                               free(this);
-                               return NULL;
-                       }
-                       break;
-               }
-               case TS_IPV6_ADDR_RANGE:
-               {
-                       if (inet_pton(AF_INET6, from_addr, (struct in6_addr*)this->from6) < 0)
-                       {
-                               free(this);
-                               return NULL;
-                       }
-                       if (inet_pton(AF_INET6, to_addr, (struct in6_addr*)this->to6) < 0)
-                       {
-                               free(this);
-                               return NULL;
-                       }
-                       break;
-               }
-       }
-       return (&this->public);
-}
-
-/*
- * see header
- */
-traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol,
-                                                                       u_int16_t from_port, u_int16_t to_port)
-{
-       private_traffic_selector_t *this = traffic_selector_create(
-                                                       protocol, TS_IPV4_ADDR_RANGE, from_port, to_port);
-
-       memset(this->from6, 0, sizeof(this->from6));
-       memset(this->to6, 0xFF, sizeof(this->to6));
-
-       this->dynamic = TRUE;
-
-       return &this->public;
-}
-
-/*
- * see declaration
- */
-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)
-{
-       private_traffic_selector_t *this = malloc_thing(private_traffic_selector_t);
-
-       /* public functions */
-       this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset;
-       this->public.equals = (bool(*)(traffic_selector_t*,traffic_selector_t*))equals;
-       this->public.get_from_address = (chunk_t(*)(traffic_selector_t*))get_from_address;
-       this->public.get_to_address = (chunk_t(*)(traffic_selector_t*))get_to_address;
-       this->public.get_from_port = (u_int16_t(*)(traffic_selector_t*))get_from_port;
-       this->public.get_to_port = (u_int16_t(*)(traffic_selector_t*))get_to_port;
-       this->public.get_type = (ts_type_t(*)(traffic_selector_t*))get_type;
-       this->public.get_protocol = (u_int8_t(*)(traffic_selector_t*))get_protocol;
-       this->public.is_host = (bool(*)(traffic_selector_t*,host_t*))is_host;
-       this->public.is_dynamic = (bool(*)(traffic_selector_t*))is_dynamic;
-       this->public.is_contained_in = (bool(*)(traffic_selector_t*,traffic_selector_t*))is_contained_in;
-       this->public.includes = (bool(*)(traffic_selector_t*,host_t*))includes;
-       this->public.set_address = (void(*)(traffic_selector_t*,host_t*))set_address;
-       this->public.to_subnet = (void(*)(traffic_selector_t*,host_t**,u_int8_t*))to_subnet;
-       this->public.clone = (traffic_selector_t*(*)(traffic_selector_t*))clone_;
-       this->public.destroy = (void(*)(traffic_selector_t*))destroy;
-
-       this->from_port = from_port;
-       this->to_port = to_port;
-       this->protocol = protocol;
-       this->type = type;
-       this->dynamic = FALSE;
-
-       return this;
-}
-
diff --git a/src/charon/config/traffic_selector.h b/src/charon/config/traffic_selector.h
deleted file mode 100644 (file)
index 900212d..0000000
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (C) 2007 Tobias Brunner
- * Copyright (C) 2005-2006 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup traffic_selector traffic_selector
- * @{ @ingroup config
- */
-
-#ifndef TRAFFIC_SELECTOR_H_
-#define TRAFFIC_SELECTOR_H_
-
-typedef enum ts_type_t ts_type_t;
-typedef struct traffic_selector_t traffic_selector_t;
-
-#include <library.h>
-#include <utils/host.h>
-
-/**
- * Traffic selector types.
- */
-enum ts_type_t {
-
-       /**
-        * A range of IPv4 addresses, represented by two four (4) octet
-        * values.  The first value is the beginning IPv4 address
-        * (inclusive) and the second value is the ending IPv4 address
-        * (inclusive). All addresses falling between the two specified
-        * addresses are considered to be within the list.
-        */
-       TS_IPV4_ADDR_RANGE = 7,
-
-       /**
-        * A range of IPv6 addresses, represented by two sixteen (16)
-        * octet values.  The first value is the beginning IPv6 address
-        * (inclusive) and the second value is the ending IPv6 address
-        * (inclusive). All addresses falling between the two specified
-        *  addresses are considered to be within the list.
-        */
-       TS_IPV6_ADDR_RANGE = 8
-};
-
-/**
- * enum names for ts_type_t
- */
-extern enum_name_t *ts_type_name;
-
-/**
- * Object representing a traffic selector entry.
- *
- * A traffic selector defines an range of addresses
- * and a range of ports. IPv6 is not fully supported yet.
- */
-struct traffic_selector_t {
-
-       /**
-        * Compare two traffic selectors, and create a new one
-        * which is the largest subset of both (subnet & port).
-        *
-        * Resulting traffic_selector is newly created and must be destroyed.
-        *
-        * @param other         traffic selector to compare
-        * @return
-        *                                      - created subset of them
-        *                                      - or NULL if no match between this and other
-        */
-       traffic_selector_t *(*get_subset)  (traffic_selector_t *this,
-                                                                               traffic_selector_t *other);
-
-       /**
-        * Clone a traffic selector.
-        *
-        * @return                      clone of it
-        */
-       traffic_selector_t *(*clone) (traffic_selector_t *this);
-
-       /**
-        * Get starting address of this ts as a chunk.
-        *
-        * Chunk is in network order and points to internal data.
-        *
-        * @return                      chunk containing the address
-        */
-       chunk_t (*get_from_address) (traffic_selector_t *this);
-
-       /**
-        * Get ending address of this ts as a chunk.
-        *
-        * Chunk is in network order and points to internal data.
-        *
-        * @return                      chunk containing the address
-        */
-       chunk_t (*get_to_address) (traffic_selector_t *this);
-
-       /**
-        * Get starting port of this ts.
-        *
-        * Port is in host order, since the parser converts it.
-        * Size depends on protocol.
-        *
-        * @return                      port
-        */
-       u_int16_t (*get_from_port) (traffic_selector_t *this);
-
-       /**
-        * Get ending port of this ts.
-        *
-        * Port is in host order, since the parser converts it.
-        * Size depends on protocol.
-        *
-        * @return                      port
-        */
-       u_int16_t (*get_to_port) (traffic_selector_t *this);
-
-       /**
-        * Get the type of the traffic selector.
-        *
-        * @return                      ts_type_t specifying the type
-        */
-       ts_type_t (*get_type) (traffic_selector_t *this);
-
-       /**
-        * Get the protocol id of this ts.
-        *
-        * @return                      protocol id
-        */
-       u_int8_t (*get_protocol) (traffic_selector_t *this);
-
-       /**
-        * Check if the traffic selector is for a single host.
-        *
-        * Traffic selector may describe the end of *-to-host tunnel. In this
-        * case, the address range is a single address equal to the hosts
-        * peer address.
-        * If host is NULL, the traffic selector is checked if it is a single host,
-        * but not a specific one.
-        *
-        * @param host          host_t specifying the address range
-        */
-       bool (*is_host) (traffic_selector_t *this, host_t* host);
-
-       /**
-        * Check if a traffic selector has been created by create_dynamic().
-        *
-        * @return                      TRUE if TS is dynamic
-        */
-       bool (*is_dynamic)(traffic_selector_t *this);
-
-       /**
-        * Update the address of a traffic selector.
-        *
-        * Update the address range of a traffic selector, if it is
-        * constructed with the traffic_selector_create_dynamic().
-        *
-        * @param host          host_t specifying the address
-        */
-       void (*set_address) (traffic_selector_t *this, host_t* host);
-
-       /**
-        * Compare two traffic selectors for equality.
-        *
-        * @param other         ts to compare with this
-        * @return                      TRUE if equal, FALSE otherwise
-        */
-       bool (*equals) (traffic_selector_t *this, traffic_selector_t *other);
-
-       /**
-        * Check if a traffic selector is contained completly in another.
-        *
-        * contains() allows to check if multiple traffic selectors are redundant.
-        *
-        * @param other         ts that contains this
-        * @return                      TRUE if other contains this completly, FALSE otherwise
-        */
-       bool (*is_contained_in) (traffic_selector_t *this, traffic_selector_t *other);
-
-       /**
-        * Check if a specific host is included in the address range of
-        * this traffic selector.
-        *
-        * @param host          the host to check
-        */
-       bool (*includes) (traffic_selector_t *this, host_t *host);
-
-       /**
-        * Convert a traffic selector address range to a subnet
-        * and its net mask.
-        * If from and to ports of this traffic selector are equal,
-        * the port of the returned host_t is set to that port.
-        *
-        * @param net           converted subnet (has to be freed)
-        * @param mask          converted net mask
-        */
-       void (*to_subnet) (traffic_selector_t *this, host_t **net, u_int8_t *mask);
-
-       /**
-        * Destroys the ts object
-        */
-       void (*destroy) (traffic_selector_t *this);
-};
-
-/**
- * Create a new traffic selector using human readable params.
- *
- * @param protocol             protocol for this ts, such as TCP or UDP
- * @param type                 type of following addresses, such as TS_IPV4_ADDR_RANGE
- * @param from_addr            start of address range as string
- * @param from_port            port number in host order
- * @param to_addr              end of address range as string
- * @param to_port              port number in host order
- * @return
- *                                             - traffic_selector_t object
- *                                             - NULL if invalid address strings/protocol
- */
-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);
-
-/**
- * Create a new traffic selector using data read from the net.
- *
- * There exists a mix of network and host order in the params.
- * But the parser gives us this data in this format, so we
- * don't have to convert twice.
- *
- * @param protocol             protocol for this ts, such as TCP or UDP
- * @param type                 type of following addresses, such as TS_IPV4_ADDR_RANGE
- * @param from_address start of address range, network order
- * @param from_port            port number, host order
- * @param to_address   end of address range, network order
- * @param to_port              port number, host order
- * @return                             traffic_selector_t object
- */
-traffic_selector_t *traffic_selector_create_from_bytes(
-                                                               u_int8_t protocol, ts_type_t type,
-                                                               chunk_t from_address, u_int16_t from_port,
-                                                               chunk_t to_address, u_int16_t to_port);
-
-/**
- * Create a new traffic selector defining a whole subnet.
- *
- * In most cases, definition of a traffic selector for full subnets
- * is sufficient. This constructor creates a traffic selector for
- * all protocols, all ports and the address range specified by the
- * subnet.
- * Additionally, a protocol and a port may be specified. Port ranges
- * are not supported via this constructor.
- *
- * @param net                  subnet to use
- * @param netbits              size of the subnet, as used in e.g. 192.168.0.0/24 notation
- * @param protocol             protocol for this ts, such as TCP or UDP
- * @param port                 port number, host order
- * @return
- *                                             - traffic_selector_t object
- *                                             - NULL if address family of net not supported
- */
-traffic_selector_t *traffic_selector_create_from_subnet(
-                                                                       host_t *net, u_int8_t netbits,
-                                                                       u_int8_t protocol, u_int16_t port);
-
-/**
- * Create a traffic selector for host-to-host cases.
- *
- * For host2host or virtual IP setups, the traffic selectors gets
- * created at runtime using the external/virtual IP. Using this constructor,
- * a call to set_address() sets this traffic selector to the supplied host.
- *
- *
- * @param protocol             upper layer protocl to allow
- * @param from_port            start of allowed port range
- * @param to_port              end of range
- * @return
- *                                             - traffic_selector_t object
- *                                             - NULL if type not supported
- */
-traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol,
-                                                                       u_int16_t from_port, u_int16_t to_port);
-
-/**
- * printf hook function for traffic_selector_t.
- *
- * Arguments are:
- *     traffic_selector_t *ts
- * With the #-specifier, arguments are:
- *     linked_list_t *list containing traffic_selector_t*
- */
-int traffic_selector_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
-                                                                const void *const *args);
-
-#endif /** TRAFFIC_SELECTOR_H_ @}*/
index 06495df..d895cf4 100644 (file)
@@ -41,7 +41,7 @@
 
 #include <library.h>
 #include <utils/backtrace.h>
-#include <config/traffic_selector.h>
+#include <selectors/traffic_selector.h>
 #include <config/proposal.h>
 
 #ifndef LOG_AUTHPRIV /* not defined on OpenSolaris */
index da4c9a4..0109fd7 100644 (file)
@@ -25,9 +25,9 @@
 typedef struct traffic_selector_substructure_t traffic_selector_substructure_t;
 
 #include <library.h>
-#include <encoding/payloads/payload.h>
 #include <utils/host.h>
-#include <config/traffic_selector.h>
+#include <selectors/traffic_selector.h>
+#include <encoding/payloads/payload.h>
 
 /**
  * Length of a TRAFFIC SELECTOR SUBSTRUCTURE without start and end address.
index 1d198a6..d322ff1 100644 (file)
@@ -27,7 +27,7 @@ typedef struct ts_payload_t ts_payload_t;
 
 #include <library.h>
 #include <utils/linked_list.h>
-#include <config/traffic_selector.h>
+#include <selectors/traffic_selector.h>
 #include <encoding/payloads/payload.h>
 #include <encoding/payloads/traffic_selector_substructure.h>
 
index 766e4db..eff79a9 100644 (file)
@@ -24,7 +24,7 @@
 typedef struct acquire_job_t acquire_job_t;
 
 #include <library.h>
-#include <config/traffic_selector.h>
+#include <selectors/traffic_selector.h>
 #include <processing/jobs/job.h>
 
 /**
index 927668f..de313d5 100644 (file)
@@ -25,7 +25,7 @@ typedef struct migrate_job_t migrate_job_t;
 
 #include <library.h>
 #include <utils/host.h>
-#include <config/traffic_selector.h>
+#include <selectors/traffic_selector.h>
 #include <kernel/kernel_ipsec.h>
 #include <processing/jobs/job.h>
 
index d8d027e..b811468 100644 (file)
@@ -42,6 +42,7 @@ credentials/certificates/pgp_certificate.h \
 credentials/ietf_attributes/ietf_attributes.c credentials/ietf_attributes/ietf_attributes.h \
 database/database.h database/database_factory.h database/database_factory.c \
 fetcher/fetcher.h fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
+selectors/traffic_selector.c selectors/traffic_selectors.h \
 utils.h utils.c \
 utils/host.c utils/host.h \
 utils/identification.c utils/identification.h \
diff --git a/src/libstrongswan/selectors/traffic_selector.c b/src/libstrongswan/selectors/traffic_selector.c
new file mode 100644 (file)
index 0000000..08bf987
--- /dev/null
@@ -0,0 +1,856 @@
+/*
+ * Copyright (C) 2007-2009 Tobias Brunner
+ * Copyright (C) 2005-2007 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <arpa/inet.h>
+#include <string.h>
+#include <netdb.h>
+#include <stdio.h>
+
+#include "traffic_selector.h"
+
+#include <utils/linked_list.h>
+#include <utils/identification.h>
+
+ENUM(ts_type_name, TS_IPV4_ADDR_RANGE, TS_IPV6_ADDR_RANGE,
+       "TS_IPV4_ADDR_RANGE",
+       "TS_IPV6_ADDR_RANGE",
+);
+
+typedef struct private_traffic_selector_t private_traffic_selector_t;
+
+/**
+ * Private data of an traffic_selector_t object
+ */
+struct private_traffic_selector_t {
+
+       /**
+        * Public part
+        */
+       traffic_selector_t public;
+
+       /**
+        * Type of address
+        */
+       ts_type_t type;
+
+       /**
+        * IP protocol (UDP, TCP, ICMP, ...)
+        */
+       u_int8_t protocol;
+
+       /**
+        * narrow this traffic selector to hosts external ip
+        * if set, from and to have no meaning until set_address() is called
+        */
+       bool dynamic;
+
+       /**
+        * begin of address range, network order
+        */
+       union {
+               /** dummy char for common address manipulation */
+               char from[0];
+               /** IPv4 address */
+               u_int32_t from4[1];
+               /** IPv6 address */
+               u_int32_t from6[4];
+       };
+
+       /**
+        * end of address range, network order
+        */
+       union {
+               /** dummy char for common address manipulation */
+               char to[0];
+               /** IPv4 address */
+               u_int32_t to4[1];
+               /** IPv6 address */
+               u_int32_t to6[4];
+       };
+
+       /**
+        * begin of port range
+        */
+       u_int16_t from_port;
+
+       /**
+        * end of port range
+        */
+       u_int16_t to_port;
+};
+
+/**
+ * calculate to "to"-address for the "from" address and a subnet size
+ */
+static void calc_range(private_traffic_selector_t *this, u_int8_t netbits)
+{
+       int byte;
+       size_t size = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
+
+       /* go through the from address, starting at the tail. While we
+        * have not processed the bits belonging to the host, set them to 1 on
+        * the to address. If we reach the bits for the net, copy them from "from". */
+       for (byte = size - 1; byte >=0; byte--)
+       {
+               u_char mask = 0x00;
+               int shift;
+
+               shift = (byte+1) * 8 - netbits;
+               if (shift > 0)
+               {
+                       mask = 1 << shift;
+                       if (mask != 0xFF)
+                       {
+                               mask--;
+                       }
+               }
+               this->from[byte] &= ~mask;
+               this->to[byte] = this->from[byte] | mask;
+       }
+}
+
+/**
+ * calculate to subnet size from "to"- and "from"-address
+ */
+static u_int8_t calc_netbits(private_traffic_selector_t *this)
+{
+       int byte, bit;
+       size_t size = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
+
+       /* go trough all bits of the addresses, beginning in the front.
+        * as long as they are equal, the subnet gets larger
+        */
+       for (byte = 0; byte < size; byte++)
+       {
+               for (bit = 7; bit >= 0; bit--)
+               {
+                       if ((1<<bit & this->from[byte]) != (1<<bit & this->to[byte]))
+                       {
+                               return ((7 - bit) + (byte * 8));
+                       }
+               }
+       }
+       /* single host, netmask is 32/128 */
+       return (size * 8);
+}
+
+/**
+ * internal generic constructor
+ */
+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);
+
+/**
+ * Described in header.
+ */
+int traffic_selector_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+                                                                const void *const *args)
+{
+       private_traffic_selector_t *this = *((private_traffic_selector_t**)(args[0]));
+       linked_list_t *list = *((linked_list_t**)(args[0]));
+       iterator_t *iterator;
+       char addr_str[INET6_ADDRSTRLEN] = "";
+       char *serv_proto = NULL;
+       u_int8_t mask;
+       bool has_proto;
+       bool has_ports;
+       size_t written = 0;
+       u_int32_t from[4], to[4];
+
+       if (this == NULL)
+       {
+               return print_in_hook(dst, len, "(null)");
+       }
+
+       if (spec->hash)
+       {
+               iterator = list->create_iterator(list, TRUE);
+               while (iterator->iterate(iterator, (void**)&this))
+               {
+                       /* call recursivly */
+                       written += print_in_hook(dst, len, "%R ", this);
+               }
+               iterator->destroy(iterator);
+               return written;
+       }
+
+       memset(from, 0, sizeof(from));
+       memset(to, 0xFF, sizeof(to));
+       if (this->dynamic &&
+               memeq(this->from, from, this->type == TS_IPV4_ADDR_RANGE ? 4 : 16) &&
+               memeq(this->to, to, this->type == TS_IPV4_ADDR_RANGE ? 4 : 16))
+       {
+               written += print_in_hook(dst, len, "dynamic");
+       }
+       else
+       {
+               if (this->type == TS_IPV4_ADDR_RANGE)
+               {
+                       inet_ntop(AF_INET, &this->from4, addr_str, sizeof(addr_str));
+               }
+               else
+               {
+                       inet_ntop(AF_INET6, &this->from6, addr_str, sizeof(addr_str));
+               }
+               mask = calc_netbits(this);
+               written += print_in_hook(dst, len, "%s/%d", addr_str, mask);
+       }
+
+       /* check if we have protocol and/or port selectors */
+       has_proto = this->protocol != 0;
+       has_ports = !(this->from_port == 0 && this->to_port == 0xFFFF);
+
+       if (!has_proto && !has_ports)
+       {
+               return written;
+       }
+
+       written += print_in_hook(dst, len, "[");
+
+       /* build protocol string */
+       if (has_proto)
+       {
+               struct protoent *proto = getprotobynumber(this->protocol);
+
+               if (proto)
+               {
+                       written += print_in_hook(dst, len, "%s", proto->p_name);
+                       serv_proto = proto->p_name;
+               }
+               else
+               {
+                       written += print_in_hook(dst, len, "%d", this->protocol);
+               }
+       }
+
+       if (has_proto && has_ports)
+       {
+               written += print_in_hook(dst, len, "/");
+       }
+
+       /* build port string */
+       if (has_ports)
+       {
+               if (this->from_port == this->to_port)
+               {
+                       struct servent *serv = getservbyport(htons(this->from_port), serv_proto);
+
+                       if (serv)
+                       {
+                               written += print_in_hook(dst, len, "%s", serv->s_name);
+                       }
+                       else
+                       {
+                               written += print_in_hook(dst, len, "%d", this->from_port);
+                       }
+               }
+               else
+               {
+                       written += print_in_hook(dst, len, "%d-%d", this->from_port, this->to_port);
+               }
+       }
+
+       written += print_in_hook(dst, len, "]");
+
+       return written;
+}
+
+/**
+ * implements traffic_selector_t.get_subset
+ */
+static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_traffic_selector_t *other)
+{
+       if (this->type == other->type && (this->protocol == other->protocol ||
+                                                               this->protocol == 0 || other->protocol == 0))
+       {
+               u_int16_t from_port, to_port;
+               u_char *from, *to;
+               u_int8_t protocol;
+               size_t size;
+               private_traffic_selector_t *new_ts;
+
+               /* calculate the maximum port range allowed for both */
+               from_port = max(this->from_port, other->from_port);
+               to_port = min(this->to_port, other->to_port);
+               if (from_port > to_port)
+               {
+                       return NULL;
+               }
+               /* select protocol, which is not zero */
+               protocol = max(this->protocol, other->protocol);
+
+               switch (this->type)
+               {
+                       case TS_IPV4_ADDR_RANGE:
+                               size = sizeof(this->from4);
+                               break;
+                       case TS_IPV6_ADDR_RANGE:
+                               size = sizeof(this->from6);
+                               break;
+                       default:
+                               return NULL;
+               }
+
+               /* get higher from-address */
+               if (memcmp(this->from, other->from, size) > 0)
+               {
+                       from = this->from;
+               }
+               else
+               {
+                       from = other->from;
+               }
+               /* get lower to-address */
+               if (memcmp(this->to, other->to, size) > 0)
+               {
+                       to = other->to;
+               }
+               else
+               {
+                       to = this->to;
+               }
+               /* if "from" > "to", we don't have a match */
+               if (memcmp(from, to, size) > 0)
+               {
+                       return NULL;
+               }
+
+               /* we have a match in protocol, port, and address: return it... */
+               new_ts = traffic_selector_create(protocol, this->type, from_port, to_port);
+               new_ts->type = this->type;
+               new_ts->dynamic = this->dynamic || other->dynamic;
+               memcpy(new_ts->from, from, size);
+               memcpy(new_ts->to, to, size);
+
+               return &new_ts->public;
+       }
+       return NULL;
+}
+
+/**
+ * implements traffic_selector_t.equals
+ */
+static bool equals(private_traffic_selector_t *this, private_traffic_selector_t *other)
+{
+       if (this->type != other->type)
+       {
+               return FALSE;
+       }
+       if (!(this->from_port == other->from_port &&
+                 this->to_port == other->to_port &&
+                 this->protocol == other->protocol))
+       {
+               return FALSE;
+       }
+       switch (this->type)
+       {
+               case TS_IPV4_ADDR_RANGE:
+                       if (memeq(this->from4, other->from4, sizeof(this->from4)))
+                       {
+                               return TRUE;
+                       }
+                       break;
+               case TS_IPV6_ADDR_RANGE:
+                       if (memeq(this->from6, other->from6, sizeof(this->from6)))
+                       {
+                               return TRUE;
+                       }
+                       break;
+               default:
+                       break;
+       }
+       return FALSE;
+}
+
+/**
+ * Implements traffic_selector_t.get_from_address.
+ */
+static chunk_t get_from_address(private_traffic_selector_t *this)
+{
+       switch (this->type)
+       {
+               case TS_IPV4_ADDR_RANGE:
+                       return chunk_create(this->from, sizeof(this->from4));
+               case TS_IPV6_ADDR_RANGE:
+                       return chunk_create(this->from, sizeof(this->from6));
+               default:
+                       return chunk_empty;
+       }
+}
+
+/**
+ * Implements traffic_selector_t.get_to_address.
+ */
+static chunk_t get_to_address(private_traffic_selector_t *this)
+{
+       switch (this->type)
+       {
+               case TS_IPV4_ADDR_RANGE:
+                       return chunk_create(this->to, sizeof(this->to4));
+               case TS_IPV6_ADDR_RANGE:
+                       return chunk_create(this->to, sizeof(this->to6));
+               default:
+                       return chunk_empty;
+       }
+}
+
+/**
+ * Implements traffic_selector_t.get_from_port.
+ */
+static u_int16_t get_from_port(private_traffic_selector_t *this)
+{
+       return this->from_port;
+}
+
+/**
+ * Implements traffic_selector_t.get_to_port.
+ */
+static u_int16_t get_to_port(private_traffic_selector_t *this)
+{
+       return this->to_port;
+}
+
+/**
+ * Implements traffic_selector_t.get_type.
+ */
+static ts_type_t get_type(private_traffic_selector_t *this)
+{
+       return this->type;
+}
+
+/**
+ * Implements traffic_selector_t.get_protocol.
+ */
+static u_int8_t get_protocol(private_traffic_selector_t *this)
+{
+       return this->protocol;
+}
+
+/**
+ * Implements traffic_selector_t.is_host.
+ */
+static bool is_host(private_traffic_selector_t *this, host_t *host)
+{
+       if (host)
+       {
+               chunk_t addr;
+               int family = host->get_family(host);
+
+               if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
+                       (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
+               {
+                       addr = host->get_address(host);
+                       if (memeq(addr.ptr, this->from, addr.len) &&
+                               memeq(addr.ptr, this->to, addr.len))
+                       {
+                               return TRUE;
+                       }
+               }
+       }
+       else
+       {
+               size_t length = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
+
+               if (this->dynamic)
+               {
+                       return TRUE;
+               }
+
+               if (memeq(this->from, this->to, length))
+               {
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
+/**
+ * Implementation of traffic_selector_t.is_dynamic
+ */
+static bool is_dynamic(private_traffic_selector_t *this)
+{
+       return this->dynamic;
+}
+
+/**
+ * Implements traffic_selector_t.set_address.
+ */
+static void set_address(private_traffic_selector_t *this, host_t *host)
+{
+       if (this->dynamic)
+       {
+               this->type = host->get_family(host) == AF_INET ?
+                               TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
+
+               if (host->is_anyaddr(host))
+               {
+                       memset(this->from6, 0x00, sizeof(this->from6));
+                       memset(this->to6, 0xFF, sizeof(this->to6));
+               }
+               else
+               {
+                       chunk_t from = host->get_address(host);
+                       memcpy(this->from, from.ptr, from.len);
+                       memcpy(this->to, from.ptr, from.len);
+               }
+       }
+}
+
+/**
+ * Implements traffic_selector_t.is_contained_in.
+ */
+static bool is_contained_in(private_traffic_selector_t *this,
+                                                       private_traffic_selector_t *other)
+{
+       private_traffic_selector_t *subset;
+       bool contained_in = FALSE;
+
+       subset = (private_traffic_selector_t*)get_subset(this, other);
+
+       if (subset)
+       {
+               if (equals(subset, this))
+               {
+                       contained_in = TRUE;
+               }
+               free(subset);
+       }
+       return contained_in;
+}
+
+/**
+ * Implements traffic_selector_t.includes.
+ */
+static bool includes(private_traffic_selector_t *this, host_t *host)
+{
+       chunk_t addr;
+       int family = host->get_family(host);
+
+       if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
+               (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
+       {
+               addr = host->get_address(host);
+
+               return memcmp(this->from, addr.ptr, addr.len) <= 0 &&
+                               memcmp(this->to, addr.ptr, addr.len) >= 0;
+       }
+
+       return FALSE;
+}
+
+/**
+ * Implements traffic_selector_t.to_subnet.
+ */
+static void to_subnet(private_traffic_selector_t *this, host_t **net, u_int8_t *mask)
+{
+       /* there is no way to do this cleanly, as the address range may
+        * be anything else but a subnet. We use from_addr as subnet
+        * and try to calculate a usable subnet mask.
+        */
+       int family, byte;
+       u_int16_t port = 0;
+       chunk_t net_chunk;
+
+       *mask = calc_netbits(this);
+
+       switch (this->type)
+       {
+               case TS_IPV4_ADDR_RANGE:
+               {
+                       family = AF_INET;
+                       net_chunk.len = sizeof(this->from4);
+                       break;
+               }
+               case TS_IPV6_ADDR_RANGE:
+               {
+                       family = AF_INET6;
+                       net_chunk.len = sizeof(this->from6);
+                       break;
+               }
+               default:
+               {
+                       /* unreachable */
+                       return;
+               }
+       }
+
+       net_chunk.ptr = malloc(net_chunk.len);
+       memcpy(net_chunk.ptr, this->from, net_chunk.len);
+
+       for (byte = net_chunk.len - 1; byte >= (*mask / 8); --byte)
+       {
+               int shift = (byte + 1) * 8 - *mask;
+               net_chunk.ptr[byte] = net_chunk.ptr[byte] & (0xFF << shift);
+       }
+
+       if (this->to_port == this->from_port)
+       {
+               port = this->to_port;
+       }
+
+       *net = host_create_from_chunk(family, net_chunk, port);
+       chunk_free(&net_chunk);
+}
+
+/**
+ * Implements traffic_selector_t.clone.
+ */
+static traffic_selector_t *clone_(private_traffic_selector_t *this)
+{
+       private_traffic_selector_t *clone;
+
+       clone = traffic_selector_create(this->protocol, this->type,
+                                                                       this->from_port, this->to_port);
+
+       clone->dynamic = this->dynamic;
+       switch (clone->type)
+       {
+               case TS_IPV4_ADDR_RANGE:
+               {
+                       memcpy(clone->from4, this->from4, sizeof(this->from4));
+                       memcpy(clone->to4, this->to4, sizeof(this->to4));
+                       return &clone->public;
+               }
+               case TS_IPV6_ADDR_RANGE:
+               {
+                       memcpy(clone->from6, this->from6, sizeof(this->from6));
+                       memcpy(clone->to6, this->to6, sizeof(this->to6));
+                       return &clone->public;
+               }
+               default:
+               {
+                       /* unreachable */
+                       return &clone->public;
+               }
+       }
+}
+
+/**
+ * Implements traffic_selector_t.destroy.
+ */
+static void destroy(private_traffic_selector_t *this)
+{
+       free(this);
+}
+
+/*
+ * see header
+ */
+traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol,
+                                                                                               ts_type_t type,
+                                                                                               chunk_t from, u_int16_t from_port,
+                                                                                               chunk_t to, u_int16_t to_port)
+{
+       private_traffic_selector_t *this = traffic_selector_create(protocol, type,
+                                                                                                                       from_port, to_port);
+
+       switch (type)
+       {
+               case TS_IPV4_ADDR_RANGE:
+               {
+                       if (from.len != 4 || to.len != 4)
+                       {
+                               free(this);
+                               return NULL;
+                       }
+                       memcpy(this->from4, from.ptr, from.len);
+                       memcpy(this->to4, to.ptr, to.len);
+                       break;
+               }
+               case TS_IPV6_ADDR_RANGE:
+               {
+                       if (from.len != 16 || to.len != 16)
+                       {
+                               free(this);
+                               return NULL;
+                       }
+                       memcpy(this->from6, from.ptr, from.len);
+                       memcpy(this->to6, to.ptr, to.len);
+                       break;
+               }
+               default:
+               {
+                       free(this);
+                       return NULL;
+               }
+       }
+       return (&this->public);
+}
+
+/*
+ * see header
+ */
+traffic_selector_t *traffic_selector_create_from_subnet(host_t *net,
+                                                       u_int8_t netbits, u_int8_t protocol, u_int16_t port)
+{
+       private_traffic_selector_t *this = traffic_selector_create(protocol, 0, 0, 65535);
+
+       switch (net->get_family(net))
+       {
+               case AF_INET:
+               {
+                       chunk_t from;
+
+                       this->type = TS_IPV4_ADDR_RANGE;
+                       from = net->get_address(net);
+                       memcpy(this->from4, from.ptr, from.len);
+                       if (this->from4[0] == 0)
+                       {
+                               /* use /0 for 0.0.0.0 */
+                               this->to4[0] = ~0;
+                       }
+                       else
+                       {
+                               calc_range(this, netbits);
+                       }
+                       break;
+               }
+               case AF_INET6:
+               {
+                       chunk_t from;
+
+                       this->type = TS_IPV6_ADDR_RANGE;
+                       from = net->get_address(net);
+                       memcpy(this->from6, from.ptr, from.len);
+                       if (this->from6[0] == 0 && this->from6[1] == 0 &&
+                               this->from6[2] == 0 && this->from6[3] == 0)
+                       {
+                               /* use /0 for ::0 */
+                               this->to6[0] = ~0;
+                               this->to6[1] = ~0;
+                               this->to6[2] = ~0;
+                               this->to6[3] = ~0;
+                       }
+                       else
+                       {
+                               calc_range(this, netbits);
+                       }
+                       break;
+               }
+               default:
+               {
+                       net->destroy(net);
+                       free(this);
+                       return NULL;
+               }
+       }
+       if (port)
+       {
+               this->from_port = port;
+               this->to_port = port;
+       }
+       net->destroy(net);
+       return (&this->public);
+}
+
+/*
+ * see header
+ */
+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)
+{
+       private_traffic_selector_t *this = traffic_selector_create(protocol, type,
+                                                                                                                       from_port, to_port);
+
+       this->type = type;
+       switch (type)
+       {
+               case TS_IPV4_ADDR_RANGE:
+               {
+                       if (inet_pton(AF_INET, from_addr, (struct in_addr*)this->from4) < 0)
+                       {
+                               free(this);
+                               return NULL;
+                       }
+                       if (inet_pton(AF_INET, to_addr, (struct in_addr*)this->to4) < 0)
+                       {
+                               free(this);
+                               return NULL;
+                       }
+                       break;
+               }
+               case TS_IPV6_ADDR_RANGE:
+               {
+                       if (inet_pton(AF_INET6, from_addr, (struct in6_addr*)this->from6) < 0)
+                       {
+                               free(this);
+                               return NULL;
+                       }
+                       if (inet_pton(AF_INET6, to_addr, (struct in6_addr*)this->to6) < 0)
+                       {
+                               free(this);
+                               return NULL;
+                       }
+                       break;
+               }
+       }
+       return (&this->public);
+}
+
+/*
+ * see header
+ */
+traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol,
+                                                                       u_int16_t from_port, u_int16_t to_port)
+{
+       private_traffic_selector_t *this = traffic_selector_create(
+                                                       protocol, TS_IPV4_ADDR_RANGE, from_port, to_port);
+
+       memset(this->from6, 0, sizeof(this->from6));
+       memset(this->to6, 0xFF, sizeof(this->to6));
+
+       this->dynamic = TRUE;
+
+       return &this->public;
+}
+
+/*
+ * see declaration
+ */
+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)
+{
+       private_traffic_selector_t *this = malloc_thing(private_traffic_selector_t);
+
+       /* public functions */
+       this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset;
+       this->public.equals = (bool(*)(traffic_selector_t*,traffic_selector_t*))equals;
+       this->public.get_from_address = (chunk_t(*)(traffic_selector_t*))get_from_address;
+       this->public.get_to_address = (chunk_t(*)(traffic_selector_t*))get_to_address;
+       this->public.get_from_port = (u_int16_t(*)(traffic_selector_t*))get_from_port;
+       this->public.get_to_port = (u_int16_t(*)(traffic_selector_t*))get_to_port;
+       this->public.get_type = (ts_type_t(*)(traffic_selector_t*))get_type;
+       this->public.get_protocol = (u_int8_t(*)(traffic_selector_t*))get_protocol;
+       this->public.is_host = (bool(*)(traffic_selector_t*,host_t*))is_host;
+       this->public.is_dynamic = (bool(*)(traffic_selector_t*))is_dynamic;
+       this->public.is_contained_in = (bool(*)(traffic_selector_t*,traffic_selector_t*))is_contained_in;
+       this->public.includes = (bool(*)(traffic_selector_t*,host_t*))includes;
+       this->public.set_address = (void(*)(traffic_selector_t*,host_t*))set_address;
+       this->public.to_subnet = (void(*)(traffic_selector_t*,host_t**,u_int8_t*))to_subnet;
+       this->public.clone = (traffic_selector_t*(*)(traffic_selector_t*))clone_;
+       this->public.destroy = (void(*)(traffic_selector_t*))destroy;
+
+       this->from_port = from_port;
+       this->to_port = to_port;
+       this->protocol = protocol;
+       this->type = type;
+       this->dynamic = FALSE;
+
+       return this;
+}
+
diff --git a/src/libstrongswan/selectors/traffic_selector.h b/src/libstrongswan/selectors/traffic_selector.h
new file mode 100644 (file)
index 0000000..900212d
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup traffic_selector traffic_selector
+ * @{ @ingroup config
+ */
+
+#ifndef TRAFFIC_SELECTOR_H_
+#define TRAFFIC_SELECTOR_H_
+
+typedef enum ts_type_t ts_type_t;
+typedef struct traffic_selector_t traffic_selector_t;
+
+#include <library.h>
+#include <utils/host.h>
+
+/**
+ * Traffic selector types.
+ */
+enum ts_type_t {
+
+       /**
+        * A range of IPv4 addresses, represented by two four (4) octet
+        * values.  The first value is the beginning IPv4 address
+        * (inclusive) and the second value is the ending IPv4 address
+        * (inclusive). All addresses falling between the two specified
+        * addresses are considered to be within the list.
+        */
+       TS_IPV4_ADDR_RANGE = 7,
+
+       /**
+        * A range of IPv6 addresses, represented by two sixteen (16)
+        * octet values.  The first value is the beginning IPv6 address
+        * (inclusive) and the second value is the ending IPv6 address
+        * (inclusive). All addresses falling between the two specified
+        *  addresses are considered to be within the list.
+        */
+       TS_IPV6_ADDR_RANGE = 8
+};
+
+/**
+ * enum names for ts_type_t
+ */
+extern enum_name_t *ts_type_name;
+
+/**
+ * Object representing a traffic selector entry.
+ *
+ * A traffic selector defines an range of addresses
+ * and a range of ports. IPv6 is not fully supported yet.
+ */
+struct traffic_selector_t {
+
+       /**
+        * Compare two traffic selectors, and create a new one
+        * which is the largest subset of both (subnet & port).
+        *
+        * Resulting traffic_selector is newly created and must be destroyed.
+        *
+        * @param other         traffic selector to compare
+        * @return
+        *                                      - created subset of them
+        *                                      - or NULL if no match between this and other
+        */
+       traffic_selector_t *(*get_subset)  (traffic_selector_t *this,
+                                                                               traffic_selector_t *other);
+
+       /**
+        * Clone a traffic selector.
+        *
+        * @return                      clone of it
+        */
+       traffic_selector_t *(*clone) (traffic_selector_t *this);
+
+       /**
+        * Get starting address of this ts as a chunk.
+        *
+        * Chunk is in network order and points to internal data.
+        *
+        * @return                      chunk containing the address
+        */
+       chunk_t (*get_from_address) (traffic_selector_t *this);
+
+       /**
+        * Get ending address of this ts as a chunk.
+        *
+        * Chunk is in network order and points to internal data.
+        *
+        * @return                      chunk containing the address
+        */
+       chunk_t (*get_to_address) (traffic_selector_t *this);
+
+       /**
+        * Get starting port of this ts.
+        *
+        * Port is in host order, since the parser converts it.
+        * Size depends on protocol.
+        *
+        * @return                      port
+        */
+       u_int16_t (*get_from_port) (traffic_selector_t *this);
+
+       /**
+        * Get ending port of this ts.
+        *
+        * Port is in host order, since the parser converts it.
+        * Size depends on protocol.
+        *
+        * @return                      port
+        */
+       u_int16_t (*get_to_port) (traffic_selector_t *this);
+
+       /**
+        * Get the type of the traffic selector.
+        *
+        * @return                      ts_type_t specifying the type
+        */
+       ts_type_t (*get_type) (traffic_selector_t *this);
+
+       /**
+        * Get the protocol id of this ts.
+        *
+        * @return                      protocol id
+        */
+       u_int8_t (*get_protocol) (traffic_selector_t *this);
+
+       /**
+        * Check if the traffic selector is for a single host.
+        *
+        * Traffic selector may describe the end of *-to-host tunnel. In this
+        * case, the address range is a single address equal to the hosts
+        * peer address.
+        * If host is NULL, the traffic selector is checked if it is a single host,
+        * but not a specific one.
+        *
+        * @param host          host_t specifying the address range
+        */
+       bool (*is_host) (traffic_selector_t *this, host_t* host);
+
+       /**
+        * Check if a traffic selector has been created by create_dynamic().
+        *
+        * @return                      TRUE if TS is dynamic
+        */
+       bool (*is_dynamic)(traffic_selector_t *this);
+
+       /**
+        * Update the address of a traffic selector.
+        *
+        * Update the address range of a traffic selector, if it is
+        * constructed with the traffic_selector_create_dynamic().
+        *
+        * @param host          host_t specifying the address
+        */
+       void (*set_address) (traffic_selector_t *this, host_t* host);
+
+       /**
+        * Compare two traffic selectors for equality.
+        *
+        * @param other         ts to compare with this
+        * @return                      TRUE if equal, FALSE otherwise
+        */
+       bool (*equals) (traffic_selector_t *this, traffic_selector_t *other);
+
+       /**
+        * Check if a traffic selector is contained completly in another.
+        *
+        * contains() allows to check if multiple traffic selectors are redundant.
+        *
+        * @param other         ts that contains this
+        * @return                      TRUE if other contains this completly, FALSE otherwise
+        */
+       bool (*is_contained_in) (traffic_selector_t *this, traffic_selector_t *other);
+
+       /**
+        * Check if a specific host is included in the address range of
+        * this traffic selector.
+        *
+        * @param host          the host to check
+        */
+       bool (*includes) (traffic_selector_t *this, host_t *host);
+
+       /**
+        * Convert a traffic selector address range to a subnet
+        * and its net mask.
+        * If from and to ports of this traffic selector are equal,
+        * the port of the returned host_t is set to that port.
+        *
+        * @param net           converted subnet (has to be freed)
+        * @param mask          converted net mask
+        */
+       void (*to_subnet) (traffic_selector_t *this, host_t **net, u_int8_t *mask);
+
+       /**
+        * Destroys the ts object
+        */
+       void (*destroy) (traffic_selector_t *this);
+};
+
+/**
+ * Create a new traffic selector using human readable params.
+ *
+ * @param protocol             protocol for this ts, such as TCP or UDP
+ * @param type                 type of following addresses, such as TS_IPV4_ADDR_RANGE
+ * @param from_addr            start of address range as string
+ * @param from_port            port number in host order
+ * @param to_addr              end of address range as string
+ * @param to_port              port number in host order
+ * @return
+ *                                             - traffic_selector_t object
+ *                                             - NULL if invalid address strings/protocol
+ */
+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);
+
+/**
+ * Create a new traffic selector using data read from the net.
+ *
+ * There exists a mix of network and host order in the params.
+ * But the parser gives us this data in this format, so we
+ * don't have to convert twice.
+ *
+ * @param protocol             protocol for this ts, such as TCP or UDP
+ * @param type                 type of following addresses, such as TS_IPV4_ADDR_RANGE
+ * @param from_address start of address range, network order
+ * @param from_port            port number, host order
+ * @param to_address   end of address range, network order
+ * @param to_port              port number, host order
+ * @return                             traffic_selector_t object
+ */
+traffic_selector_t *traffic_selector_create_from_bytes(
+                                                               u_int8_t protocol, ts_type_t type,
+                                                               chunk_t from_address, u_int16_t from_port,
+                                                               chunk_t to_address, u_int16_t to_port);
+
+/**
+ * Create a new traffic selector defining a whole subnet.
+ *
+ * In most cases, definition of a traffic selector for full subnets
+ * is sufficient. This constructor creates a traffic selector for
+ * all protocols, all ports and the address range specified by the
+ * subnet.
+ * Additionally, a protocol and a port may be specified. Port ranges
+ * are not supported via this constructor.
+ *
+ * @param net                  subnet to use
+ * @param netbits              size of the subnet, as used in e.g. 192.168.0.0/24 notation
+ * @param protocol             protocol for this ts, such as TCP or UDP
+ * @param port                 port number, host order
+ * @return
+ *                                             - traffic_selector_t object
+ *                                             - NULL if address family of net not supported
+ */
+traffic_selector_t *traffic_selector_create_from_subnet(
+                                                                       host_t *net, u_int8_t netbits,
+                                                                       u_int8_t protocol, u_int16_t port);
+
+/**
+ * Create a traffic selector for host-to-host cases.
+ *
+ * For host2host or virtual IP setups, the traffic selectors gets
+ * created at runtime using the external/virtual IP. Using this constructor,
+ * a call to set_address() sets this traffic selector to the supplied host.
+ *
+ *
+ * @param protocol             upper layer protocl to allow
+ * @param from_port            start of allowed port range
+ * @param to_port              end of range
+ * @return
+ *                                             - traffic_selector_t object
+ *                                             - NULL if type not supported
+ */
+traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol,
+                                                                       u_int16_t from_port, u_int16_t to_port);
+
+/**
+ * printf hook function for traffic_selector_t.
+ *
+ * Arguments are:
+ *     traffic_selector_t *ts
+ * With the #-specifier, arguments are:
+ *     linked_list_t *list containing traffic_selector_t*
+ */
+int traffic_selector_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
+                                                                const void *const *args);
+
+#endif /** TRAFFIC_SELECTOR_H_ @}*/