diff options
Diffstat (limited to 'src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c')
| -rw-r--r-- | src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c | 125 | 
1 files changed, 80 insertions, 45 deletions
| diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c index 8a7883c8a..a64c27f6f 100644 --- a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c +++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c @@ -1,5 +1,5 @@  /* - * Copyright (C) 2008-2009 Tobias Brunner + * Copyright (C) 2008-2010 Tobias Brunner   * Copyright (C) 2008 Andreas Steffen   * Hochschule fuer Technik Rapperswil   * @@ -67,8 +67,10 @@  /** non linux specific */  #ifndef IPPROTO_COMP +#ifdef IPPROTO_IPCOMP  #define IPPROTO_COMP IPPROTO_IPCOMP  #endif +#endif  #ifndef SADB_X_AALG_SHA2_256HMAC  #define SADB_X_AALG_SHA2_256HMAC SADB_X_AALG_SHA2_256 @@ -600,17 +602,43 @@ static int lookup_algorithm(kernel_algorithm_t *list, int ikev2)  }  /** - * add a host behind a sadb_address extension + * Copy a host_t as sockaddr_t to the given memory location. Ports are + * reset to zero as per RFC 2367. + * @return		the number of bytes copied   */ -static void host2ext(host_t *host, struct sadb_address *ext) +static size_t hostcpy(void *dest, host_t *host)  { -	sockaddr_t *host_addr = host->get_sockaddr(host); +	sockaddr_t *addr = host->get_sockaddr(host), *dest_addr = dest;  	socklen_t *len = host->get_sockaddr_len(host); +	memcpy(dest, addr, *len);  #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN -	host_addr->sa_len = *len; +	dest_addr->sa_len = *len;  #endif -	memcpy((char*)(ext + 1), host_addr, *len); -	ext->sadb_address_len = PFKEY_LEN(sizeof(*ext) + *len); +	switch (dest_addr->sa_family) +	{ +		case AF_INET: +		{ +			struct sockaddr_in *sin = dest; +			sin->sin_port = 0; +			break; +		} +		case AF_INET6: +		{ +			struct sockaddr_in6 *sin6 = dest; +			sin6->sin6_port = 0; +			break; +		} +	} +	return *len; +} + +/** + * add a host behind an sadb_address extension + */ +static void host2ext(host_t *host, struct sadb_address *ext) +{ +	size_t len = hostcpy(ext + 1, host); +	ext->sadb_address_len = PFKEY_LEN(sizeof(*ext) + len);  }  /** @@ -1019,7 +1047,7 @@ static void process_migrate(private_kernel_pfkey_ipsec_t *this, struct sadb_msg*  }  #endif /*SADB_X_MIGRATE*/ -#ifdef HAVE_NATT +#ifdef SADB_X_NAT_T_NEW_MAPPING  /**   * Process a SADB_X_NAT_T_NEW_MAPPING message from the kernel   */ @@ -1075,7 +1103,7 @@ static void process_mapping(private_kernel_pfkey_ipsec_t *this, struct sadb_msg*  		}  	}  } -#endif /*HAVE_NATT*/ +#endif /*SADB_X_NAT_T_NEW_MAPPING*/  /**   * Receives events from kernel @@ -1137,11 +1165,11 @@ static job_requeue_t receive_events(private_kernel_pfkey_ipsec_t *this)  			process_migrate(this, msg);  			break;  #endif /*SADB_X_MIGRATE*/ -#ifdef HAVE_NATT +#ifdef SADB_X_NAT_T_NEW_MAPPING  		case SADB_X_NAT_T_NEW_MAPPING:  			process_mapping(this, msg);  			break; -#endif /*HAVE_NATT*/ +#endif /*SADB_X_NAT_T_NEW_MAPPING*/  		default:  			break;  	} @@ -1217,10 +1245,11 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,  METHOD(kernel_ipsec_t, add_sa, status_t,  	private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, -	protocol_id_t protocol, u_int32_t reqid, lifetime_cfg_t *lifetime, -	u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key, -	ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool encap, -	bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts) +	protocol_id_t protocol, u_int32_t reqid, mark_t mark, +	lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, +	u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, +	u_int16_t ipcomp, u_int16_t cpi, bool encap, bool inbound, +	traffic_selector_t *src_ts, traffic_selector_t *dst_ts)  {  	unsigned char request[PFKEY_BUFFER_SIZE];  	struct sadb_msg *msg, *out; @@ -1364,7 +1393,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,  METHOD(kernel_ipsec_t, update_sa, status_t,  	private_kernel_pfkey_ipsec_t *this, u_int32_t spi, protocol_id_t protocol,  	u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst, -	bool encap, bool new_encap) +	bool encap, bool new_encap, mark_t mark)  {  	unsigned char request[PFKEY_BUFFER_SIZE];  	struct sadb_msg *msg, *out; @@ -1497,7 +1526,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,  METHOD(kernel_ipsec_t, query_sa, status_t,  	private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, -	u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes) +	u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes)  {  	unsigned char request[PFKEY_BUFFER_SIZE];  	struct sadb_msg *msg, *out; @@ -1553,7 +1582,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t,  METHOD(kernel_ipsec_t, del_sa, status_t,  	private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, -	u_int32_t spi, protocol_id_t protocol, u_int16_t cpi) +	u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark)  {  	unsigned char request[PFKEY_BUFFER_SIZE];  	struct sadb_msg *msg, *out; @@ -1604,8 +1633,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,  	private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,  	traffic_selector_t *src_ts, traffic_selector_t *dst_ts,  	policy_dir_t direction, u_int32_t spi, protocol_id_t protocol, -	u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, -	bool routed) +	u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp, +	u_int16_t cpi, bool routed)  {  	unsigned char request[PFKEY_BUFFER_SIZE];  	struct sadb_msg *msg, *out; @@ -1679,14 +1708,10 @@ METHOD(kernel_ipsec_t, add_policy, status_t,  	req->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;  	if (mode == MODE_TUNNEL)  	{ -		sockaddr_t *sa; -		socklen_t sl; -		sa = src->get_sockaddr(src); -		sl = *src->get_sockaddr_len(src); -		memcpy(req + 1, sa, sl); -		sa = dst->get_sockaddr(dst); -		memcpy((u_int8_t*)(req + 1) + sl, sa, sl); -		req->sadb_x_ipsecrequest_len += sl * 2; +		len = hostcpy(req + 1, src); +		req->sadb_x_ipsecrequest_len += len; +		len = hostcpy((char*)(req + 1) + len, dst); +		req->sadb_x_ipsecrequest_len += len;  	}  	pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len); @@ -1771,22 +1796,30 @@ METHOD(kernel_ipsec_t, add_policy, status_t,  			route->dst_net = chunk_clone(policy->src.net->get_address(policy->src.net));  			route->prefixlen = policy->src.mask; -			switch (charon->kernel_interface->add_route(charon->kernel_interface, -					route->dst_net, route->prefixlen, route->gateway, -					route->src_ip, route->if_name)) +			if (route->if_name) +			{ +				switch (charon->kernel_interface->add_route( +									charon->kernel_interface, route->dst_net, +									route->prefixlen, route->gateway, +									route->src_ip, route->if_name)) +				{ +					default: +						DBG1(DBG_KNL, "unable to install source route for %H", +							 route->src_ip); +						/* FALL */ +					case ALREADY_DONE: +						/* route exists, do not uninstall */ +						route_entry_destroy(route); +						break; +					case SUCCESS: +						/* cache the installed route */ +						policy->route = route; +						break; +				} +			} +			else  			{ -				default: -					DBG1(DBG_KNL, "unable to install source route for %H", -						 route->src_ip); -					/* FALL */ -				case ALREADY_DONE: -					/* route exists, do not uninstall */ -					route_entry_destroy(route); -					break; -				case SUCCESS: -					/* cache the installed route */ -					policy->route = route; -					break; +				route_entry_destroy(route);  			}  		}  		else @@ -1802,7 +1835,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,  METHOD(kernel_ipsec_t, query_policy, status_t,  	private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts, -	traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time) +	traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, +	u_int32_t *use_time)  {  	unsigned char request[PFKEY_BUFFER_SIZE];  	struct sadb_msg *msg, *out; @@ -1905,7 +1939,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,  METHOD(kernel_ipsec_t, del_policy, status_t,  	private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts, -	traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted) +	traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, +	bool unrouted)  {  	unsigned char request[PFKEY_BUFFER_SIZE];  	struct sadb_msg *msg, *out; | 
