added support for 0.0.0.0/0 traffic selectors
authorMartin Willi <martin@strongswan.org>
Thu, 1 Mar 2007 11:42:08 +0000 (11:42 -0000)
committerMartin Willi <martin@strongswan.org>
Thu, 1 Mar 2007 11:42:08 +0000 (11:42 -0000)
fixed routing to make correct 0.0.0.0/0 routes

src/charon/config/credentials/local_credential_store.c
src/charon/config/policies/policy.c
src/charon/config/traffic_selector.c
src/charon/config/traffic_selector.h
src/charon/threads/kernel_interface.c
src/charon/threads/stroke_interface.c
src/starter/starterstroke.c
src/stroke/stroke.c
src/stroke/stroke.h

index 37d696a..427fef2 100644 (file)
@@ -725,6 +725,8 @@ static status_t release_ca_info(private_local_credential_store_t *this, const ch
                }
        }
        iterator->destroy(iterator);
+       
+       return status;
 }
 
 /**
@@ -774,7 +776,7 @@ static x509_t* add_end_certificate(private_local_credential_store_t *this, x509_
  */
 static x509_t* add_ca_certificate(private_local_credential_store_t *this, x509_t *cert)
 {
-        add_certificate(this->ca_certs, cert);
+        return add_certificate(this->ca_certs, cert);
 }
 
 /**
index fa23955..3ff0e32 100644 (file)
@@ -235,7 +235,7 @@ static linked_list_t *get_traffic_selectors(private_policy_t *this,
                current = current->clone(current);
                if (host)
                {
-                       current->update_address_range(current, host);
+                       current->set_address(current, host);
                }
                
                result->insert_last(result, (void*)current);
@@ -285,7 +285,7 @@ static linked_list_t *select_traffic_selectors(private_policy_t *this,
                stored_ts = stored_ts->clone(stored_ts);
                if (host)
                {
-                       stored_ts->update_address_range(stored_ts, host);
+                       stored_ts->set_address(stored_ts, host);
                }
                
                supplied_iter->reset(supplied_iter);
index 519c90f..b66b77f 100644 (file)
@@ -60,6 +60,12 @@ struct private_traffic_selector_t {
         */
        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
         */
@@ -448,6 +454,11 @@ static u_int8_t get_protocol(private_traffic_selector_t *this)
  */
 static bool is_host(private_traffic_selector_t *this, host_t *host)
 {
+       if (this->dynamic)
+       {
+               return TRUE;
+       }
+
        if (host)
        {
                chunk_t addr;
@@ -477,13 +488,11 @@ static bool is_host(private_traffic_selector_t *this, host_t *host)
 }
 
 /**
- * Implements traffic_selector_t.update_address_range.
+ * Implements traffic_selector_t.set_address.
  */
-static void update_address_range(private_traffic_selector_t *this, host_t *host)
+static void set_address(private_traffic_selector_t *this, host_t *host)
 {
-       if ((this->type == TS_IPV4_ADDR_RANGE && this->from4[0] == 0) ||
-                       (this->type == TS_IPV6_ADDR_RANGE && this->from6[0] == 0 &&
-                       this->from6[1] == 0 && this->from6[2] == 0 && this->from6[3] == 0))
+       if (this->dynamic)
        {
                this->type = host->get_family(host) == AF_INET ?
                                TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
@@ -523,6 +532,8 @@ static traffic_selector_t *clone_(private_traffic_selector_t *this)
        
        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:
@@ -556,9 +567,13 @@ static void destroy(private_traffic_selector_t *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)
+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);
+       private_traffic_selector_t *this = traffic_selector_create(protocol, type,
+                                                                                                                       from_port, to_port);
        
        switch (type)
        {
@@ -596,7 +611,8 @@ traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_typ
 /*
  * 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)
+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);
 
@@ -659,13 +675,13 @@ traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, u_int8_t ne
 /*
  * 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)
+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);
-
-       /* public functions */
-       this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset;
-       this->public.destroy = (void(*)(traffic_selector_t*))destroy;
+       private_traffic_selector_t *this = traffic_selector_create(protocol, type,
+                                                                                                                       from_port, to_port);
 
        this->type = type;
        switch (type)
@@ -703,9 +719,28 @@ traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_ty
 }
 
 /*
+ * see header
+ */
+traffic_selector_t *traffic_selector_create_dynamic(
+                                                                       u_int8_t protocol, ts_type_t type,
+                                                                       u_int16_t from_port, u_int16_t to_port)
+{
+       private_traffic_selector_t *this = traffic_selector_create(protocol, type,
+                                                                                                                       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)
+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);
 
@@ -720,7 +755,7 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts
        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.includes = (bool(*)(traffic_selector_t*,host_t*))includes;
-       this->public.update_address_range = (void(*)(traffic_selector_t*,host_t*))update_address_range;
+       this->public.set_address = (void(*)(traffic_selector_t*,host_t*))set_address;
        this->public.clone = (traffic_selector_t*(*)(traffic_selector_t*))clone_;
        this->public.destroy = (void(*)(traffic_selector_t*))destroy;
        
@@ -728,9 +763,9 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts
        this->to_port = to_port;
        this->protocol = protocol;
        this->type = type;
+       this->dynamic = FALSE;
        
        return this;
 }
 
 /* vim: set ts=4 sw=4 noet: */
-
index 7728ba3..33152b0 100644 (file)
@@ -176,15 +176,13 @@ struct traffic_selector_t {
        /**
         * @brief Update the address of a traffic selector.
         *
-        * Update the address range of a traffic selector, 
-        * if the current address is 0.0.0.0. The new address range
-        * starts from the supplied address and also ends there 
-        * (which means it is a one-host-address-range ;-).
+        * Update the address range of a traffic selector, if it is
+        * constructed with the traffic_selector_create_dynamic().
         *
         * @param this          called object
-        * @param host          host_t specifying the address range
+        * @param host          host_t specifying the address
         */
-       void (*update_address_range) (traffic_selector_t *this, host_t* host);
+       void (*set_address) (traffic_selector_t *this, host_t* host);
        
        /**
         * @brief Compare two traffic selectors for equality.
@@ -196,7 +194,8 @@ struct traffic_selector_t {
        bool (*equals) (traffic_selector_t *this, traffic_selector_t *other);
 
        /**
-        * @brief Check if a specific host is included in the address range of this traffic selector.
+        * @brief Check if a specific host is included in the address range of 
+        * this traffic selector.
         *
         * @param this          called object
         * @param host          the host to check
@@ -244,9 +243,7 @@ traffic_selector_t *traffic_selector_create_from_string(
  * @param from_port            port number, host order
  * @param to_address   end of address range as string, network
  * @param to_port              port number, host order
- * @return
- *                                             - traffic_selector_t object
- *                                             - NULL if invalid address input/protocol
+ * @return                             traffic_selector_t object
  *
  * @ingroup config
  */
@@ -277,7 +274,28 @@ traffic_selector_t *traffic_selector_create_from_subnet(
                                                                        host_t *net, u_int8_t netbits, 
                                                                        u_int8_t protocol, u_int16_t port);
 
+/**
+ * @brief 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 type                 family type
+ * @param from_port            start of allowed port range
+ * @param to_port              end of range
+ * @return
+ *                                             - traffic_selector_t object
+ *                                             - NULL if type not supported
+ *
+ * @ingroup config
+ */
+traffic_selector_t *traffic_selector_create_dynamic(
+                                                                       u_int8_t protocol, ts_type_t type,
+                                                                       u_int16_t from_port, u_int16_t to_port);
+
 #endif /* TRAFFIC_SELECTOR_H_ */
 
 /* vim: set ts=4 sw=4 noet: */
-
index e595108..0fa8e6d 100644 (file)
@@ -1085,7 +1085,29 @@ static struct xfrm_selector ts2selector(traffic_selector_t *src,
  */
 static status_t find_addr_by_ts(traffic_selector_t *ts, host_t **ip)
 {
-       host_t *try = NULL;
+       host_t *try = NULL, *local;
+       int family;
+       
+       /* if we have a family which includes localhost, we do not
+        * search for an IP, we use the default */
+       family = ts->get_type(ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6;
+       
+       if (family == AF_INET)
+       {
+               local = host_create_from_string("127.0.0.1", 0);
+       }
+       else
+       {
+               local = host_create_from_string("::1", 0);
+       }
+       
+       if (ts->includes(ts, local))
+       {
+               *ip = host_create_any(family);
+               local->destroy(local);
+               return SUCCESS;
+       }
+       local->destroy(local);
 
 #ifdef HAVE_GETIFADDRS
        struct ifaddrs *list;
@@ -1660,6 +1682,26 @@ static status_t manage_srcroute(private_kernel_interface_t *this,
        unsigned char request[BUFFER_SIZE];
        chunk_t src;
        
+       /* if route is 0.0.0.0/0, we can't install it, as it would
+        * overwrite the default route. Instead, we add two routes:
+        * 0.0.0.0/1 and 128.0.0.0/1 */
+       if (route->prefixlen == 0)
+       {
+               rt_refcount_t half;
+               status_t status;
+               
+               half.dst_net = chunk_alloca(route->dst_net.len);
+               memset(half.dst_net.ptr, 0, half.dst_net.len);
+               half.src_ip = route->src_ip;
+               half.if_index = route->if_index;
+               half.prefixlen = 1;
+               
+               status = manage_srcroute(this, nlmsg_type, flags, &half);
+               half.dst_net.ptr[0] |= 0x80;
+               status = manage_srcroute(this, nlmsg_type, flags, &half);
+               return status;
+       }
+       
        memset(&request, 0, sizeof(request));
 
        hdr = (struct nlmsghdr*)request;
@@ -1675,14 +1717,13 @@ static status_t manage_srcroute(private_kernel_interface_t *this,
        msg->rtm_type = RTN_UNICAST;
        msg->rtm_scope = RT_SCOPE_UNIVERSE;
 
-       src = route->src_ip->get_address(route->src_ip);
-
        if (add_rtattr(hdr, sizeof(request), RTA_DST,
                                   route->dst_net.ptr, route->dst_net.len) != SUCCESS)
        {
                return FAILED;
        }
 
+       src = route->src_ip->get_address(route->src_ip);
        if (add_rtattr(hdr, sizeof(request), RTA_PREFSRC,
                                   src.ptr, src.len) != SUCCESS)
        {
index c491be9..c93712b 100755 (executable)
@@ -314,15 +314,37 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
                my_vip = host_create_from_string(msg->add_conn.me.sourceip, 0);
        }
        other_vip = host_create_from_string(msg->add_conn.other.sourceip, 0);
-               
-       my_ts = traffic_selector_create_from_subnet(my_subnet,
+       
+       if (msg->add_conn.me.tohost)
+       {
+               my_ts = traffic_selector_create_dynamic(msg->add_conn.me.protocol,
+                                       my_host->get_family(my_host) == AF_INET ?
+                                               TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE,
+                                       msg->add_conn.me.port ? msg->add_conn.me.port : 0,
+                                       msg->add_conn.me.port ? msg->add_conn.me.port : 65535);
+       }
+       else
+       {
+               my_ts = traffic_selector_create_from_subnet(my_subnet,
                                msg->add_conn.me.subnet ?  msg->add_conn.me.subnet_mask : 0,
                                msg->add_conn.me.protocol, msg->add_conn.me.port);
+       }
        my_subnet->destroy(my_subnet);
-
-       other_ts = traffic_selector_create_from_subnet(other_subnet, 
-                       msg->add_conn.other.subnet ?  msg->add_conn.other.subnet_mask : 0,
-                       msg->add_conn.other.protocol, msg->add_conn.other.port);
+       
+       if (msg->add_conn.other.tohost)
+       {
+               other_ts = traffic_selector_create_dynamic(msg->add_conn.other.protocol,
+                                       other_host->get_family(other_host) == AF_INET ?
+                                               TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE,
+                                       msg->add_conn.other.port ? msg->add_conn.other.port : 0,
+                                       msg->add_conn.other.port ? msg->add_conn.other.port : 65535);
+       }
+       else
+       {
+               other_ts = traffic_selector_create_from_subnet(other_subnet, 
+                               msg->add_conn.other.subnet ?  msg->add_conn.other.subnet_mask : 0,
+                               msg->add_conn.other.protocol, msg->add_conn.other.port);
+       }
        other_subnet->destroy(other_subnet);
 
        if (msg->add_conn.me.ca)
index 79ad33f..fb8e74b 100644 (file)
@@ -164,6 +164,7 @@ static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, sta
        msg_end->subnet_mask = conn_end->subnet.maskbits;
        msg_end->sendcert = conn_end->sendcert;
        msg_end->hostaccess = conn_end->hostaccess;
+       msg_end->tohost = !conn_end->has_client;
        msg_end->protocol = conn_end->protocol;
        msg_end->port = conn_end->port;
        msg_end->virtual_ip = conn_end->modecfg;
index 1fed6e2..5d3fd6e 100644 (file)
@@ -133,6 +133,7 @@ static int add_connection(char *name,
        msg.add_conn.me.ca = NULL;
        msg.add_conn.me.sendcert = 1;
        msg.add_conn.me.hostaccess = 0;
+       msg.add_conn.me.tohost = 0;
        msg.add_conn.me.protocol = 0;
        msg.add_conn.me.port = 0;
        
@@ -146,6 +147,7 @@ static int add_connection(char *name,
        msg.add_conn.other.ca = NULL;
        msg.add_conn.other.sendcert = 1;
        msg.add_conn.other.hostaccess = 0;
+       msg.add_conn.other.tohost = 0;
        msg.add_conn.other.protocol = 0;
        msg.add_conn.other.port = 0;
        
index 57ddf29..2eefb36 100644 (file)
@@ -106,6 +106,7 @@ struct stroke_end_t {
        int subnet_mask;
        int sendcert;
        int hostaccess;
+       int tohost;
        u_int8_t protocol;
        u_int16_t port;
 };