diff options
-rw-r--r-- | src/charon/config/credentials/local_credential_store.c | 4 | ||||
-rw-r--r-- | src/charon/config/policies/policy.c | 4 | ||||
-rw-r--r-- | src/charon/config/traffic_selector.c | 69 | ||||
-rw-r--r-- | src/charon/config/traffic_selector.h | 40 | ||||
-rw-r--r-- | src/charon/threads/kernel_interface.c | 47 | ||||
-rwxr-xr-x | src/charon/threads/stroke_interface.c | 34 | ||||
-rw-r--r-- | src/starter/starterstroke.c | 1 | ||||
-rw-r--r-- | src/stroke/stroke.c | 2 | ||||
-rw-r--r-- | src/stroke/stroke.h | 1 |
9 files changed, 162 insertions, 40 deletions
diff --git a/src/charon/config/credentials/local_credential_store.c b/src/charon/config/credentials/local_credential_store.c index 37d696a2b..427fef290 100644 --- a/src/charon/config/credentials/local_credential_store.c +++ b/src/charon/config/credentials/local_credential_store.c @@ -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); } /** diff --git a/src/charon/config/policies/policy.c b/src/charon/config/policies/policy.c index fa23955fb..3ff0e32ea 100644 --- a/src/charon/config/policies/policy.c +++ b/src/charon/config/policies/policy.c @@ -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); diff --git a/src/charon/config/traffic_selector.c b/src/charon/config/traffic_selector.c index 519c90f77..b66b77f4a 100644 --- a/src/charon/config/traffic_selector.c +++ b/src/charon/config/traffic_selector.c @@ -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: */ - diff --git a/src/charon/config/traffic_selector.h b/src/charon/config/traffic_selector.h index 7728ba307..33152b008 100644 --- a/src/charon/config/traffic_selector.h +++ b/src/charon/config/traffic_selector.h @@ -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: */ - diff --git a/src/charon/threads/kernel_interface.c b/src/charon/threads/kernel_interface.c index e595108ee..0fa8e6d2d 100644 --- a/src/charon/threads/kernel_interface.c +++ b/src/charon/threads/kernel_interface.c @@ -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) { diff --git a/src/charon/threads/stroke_interface.c b/src/charon/threads/stroke_interface.c index c491be975..c93712bc1 100755 --- a/src/charon/threads/stroke_interface.c +++ b/src/charon/threads/stroke_interface.c @@ -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) diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c index 79ad33f61..fb8e74b8c 100644 --- a/src/starter/starterstroke.c +++ b/src/starter/starterstroke.c @@ -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; diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c index 1fed6e281..5d3fd6e77 100644 --- a/src/stroke/stroke.c +++ b/src/stroke/stroke.c @@ -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; diff --git a/src/stroke/stroke.h b/src/stroke/stroke.h index 57ddf29be..2eefb36c4 100644 --- a/src/stroke/stroke.h +++ b/src/stroke/stroke.h @@ -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; }; |