diff options
| author | Yves-Alexis Perez <corsac@debian.org> | 2013-08-25 15:37:26 +0200 | 
|---|---|---|
| committer | Yves-Alexis Perez <corsac@debian.org> | 2013-08-25 15:37:26 +0200 | 
| commit | 6b99c8d9cff7b3e8ae8f3204b99e7ea40f791349 (patch) | |
| tree | 009fc492961e13860d2a4bc2de8caf2bbe2975e7 /src/libcharon/plugins/unity/unity_handler.c | |
| parent | c83921a2b566aa9d55d8ccc7258f04fca6292ee6 (diff) | |
| download | vyos-strongswan-6b99c8d9cff7b3e8ae8f3204b99e7ea40f791349.tar.gz vyos-strongswan-6b99c8d9cff7b3e8ae8f3204b99e7ea40f791349.zip  | |
Imported Upstream version 5.1.0
Diffstat (limited to 'src/libcharon/plugins/unity/unity_handler.c')
| -rw-r--r-- | src/libcharon/plugins/unity/unity_handler.c | 147 | 
1 files changed, 97 insertions, 50 deletions
diff --git a/src/libcharon/plugins/unity/unity_handler.c b/src/libcharon/plugins/unity/unity_handler.c index 3dec7a3b6..bcef0dc25 100644 --- a/src/libcharon/plugins/unity/unity_handler.c +++ b/src/libcharon/plugins/unity/unity_handler.c @@ -1,4 +1,7 @@  /* + * Copyright (C) 2013 Tobias Brunner + * Hochschule fuer Technik Rapperswil + *   * Copyright (C) 2012 Martin Willi   * Copyright (C) 2012 revosec AG   * @@ -70,12 +73,8 @@ static traffic_selector_t *create_ts(chunk_t subnet)  	chunk_t net, mask;  	int i; -	if (subnet.len != 8) -	{ -		return NULL; -	}  	net = chunk_create(subnet.ptr, 4); -	mask = chunk_clonea(chunk_skip(subnet, 4)); +	mask = chunk_clonea(chunk_create(subnet.ptr + 4, 4));  	for (i = 0; i < net.len; i++)  	{  		mask.ptr[i] = (mask.ptr[i] ^ 0xFF) | net.ptr[i]; @@ -85,11 +84,37 @@ static traffic_selector_t *create_ts(chunk_t subnet)  }  /** - * Store a subnet to include in tunnels under this IKE_SA + * Parse a unity attribute and extract all subnets as traffic selectors + */ +static linked_list_t *parse_subnets(chunk_t data) +{ +	linked_list_t *list = NULL; +	traffic_selector_t *ts; + +	while (data.len >= 8) +	{	/* the padding is optional */ +		ts = create_ts(data); +		if (ts) +		{ +			if (!list) +			{ +				list = linked_list_create(); +			} +			list->insert_last(list, ts); +		} +		/* skip address, mask and 6 bytes of padding */ +		data = chunk_skip(data, 14); +	} +	return list; +} + +/** + * Store a list of subnets to include in tunnels under this IKE_SA   */ -static bool add_include(private_unity_handler_t *this, chunk_t subnet) +static bool add_include(private_unity_handler_t *this, chunk_t data)  {  	traffic_selector_t *ts; +	linked_list_t *list;  	ike_sa_t *ike_sa;  	entry_t *entry; @@ -98,29 +123,34 @@ static bool add_include(private_unity_handler_t *this, chunk_t subnet)  	{  		return FALSE;  	} -	ts = create_ts(subnet); -	if (!ts) +	list = parse_subnets(data); +	if (!list)  	{  		return FALSE;  	} -	INIT(entry, -		.sa = ike_sa->get_unique_id(ike_sa), -		.ts = ts, -	); - -	this->mutex->lock(this->mutex); -	this->include->insert_last(this->include, entry); -	this->mutex->unlock(this->mutex); +	while (list->remove_first(list, (void**)&ts) == SUCCESS) +	{ +		INIT(entry, +			.sa = ike_sa->get_unique_id(ike_sa), +			.ts = ts, +		); + +		this->mutex->lock(this->mutex); +		this->include->insert_last(this->include, entry); +		this->mutex->unlock(this->mutex); +	} +	list->destroy(list);  	return TRUE;  }  /** - * Remove a subnet from the inclusion list for this IKE_SA + * Remove a list of subnets from the inclusion list for this IKE_SA   */ -static bool remove_include(private_unity_handler_t *this, chunk_t subnet) +static bool remove_include(private_unity_handler_t *this, chunk_t data)  {  	enumerator_t *enumerator;  	traffic_selector_t *ts; +	linked_list_t *list;  	ike_sa_t *ike_sa;  	entry_t *entry; @@ -129,27 +159,31 @@ static bool remove_include(private_unity_handler_t *this, chunk_t subnet)  	{  		return FALSE;  	} -	ts = create_ts(subnet); -	if (!ts) +	list = parse_subnets(data); +	if (!list)  	{  		return FALSE;  	}  	this->mutex->lock(this->mutex); -	enumerator = this->include->create_enumerator(this->include); -	while (enumerator->enumerate(enumerator, &entry)) +	while (list->remove_first(list, (void**)&ts) == SUCCESS)  	{ -		if (entry->sa == ike_sa->get_unique_id(ike_sa) && -			ts->equals(ts, entry->ts)) +		enumerator = this->include->create_enumerator(this->include); +		while (enumerator->enumerate(enumerator, &entry))  		{ -			this->include->remove_at(this->include, enumerator); -			entry_destroy(entry); -			break; +			if (entry->sa == ike_sa->get_unique_id(ike_sa) && +				ts->equals(ts, entry->ts)) +			{ +				this->include->remove_at(this->include, enumerator); +				entry_destroy(entry); +				break; +			}  		} +		enumerator->destroy(enumerator); +		ts->destroy(ts);  	} -	enumerator->destroy(enumerator);  	this->mutex->unlock(this->mutex); -	ts->destroy(ts); +	list->destroy(list);  	return TRUE;  } @@ -212,9 +246,10 @@ static job_requeue_t add_exclude_async(entry_t *entry)  /**   * Add a bypass policy for a given subnet   */ -static bool add_exclude(private_unity_handler_t *this, chunk_t subnet) +static bool add_exclude(private_unity_handler_t *this, chunk_t data)  {  	traffic_selector_t *ts; +	linked_list_t *list;  	ike_sa_t *ike_sa;  	entry_t *entry; @@ -223,48 +258,60 @@ static bool add_exclude(private_unity_handler_t *this, chunk_t subnet)  	{  		return FALSE;  	} -	ts = create_ts(subnet); -	if (!ts) +	list = parse_subnets(data); +	if (!list)  	{  		return FALSE;  	} -	INIT(entry, -		.sa = ike_sa->get_unique_id(ike_sa), -		.ts = ts, -	); -	/* we can't install the shunt policy yet, as we don't know the virtual IP. -	 * Defer installation using an async callback. */ -	lib->processor->queue_job(lib->processor, (job_t*) -						callback_job_create((void*)add_exclude_async, entry, -											(void*)entry_destroy, NULL)); +	while (list->remove_first(list, (void**)&ts) == SUCCESS) +	{ +		INIT(entry, +			.sa = ike_sa->get_unique_id(ike_sa), +			.ts = ts, +		); + +		/* we can't install the shunt policy yet, as we don't know the virtual IP. +		 * Defer installation using an async callback. */ +		lib->processor->queue_job(lib->processor, (job_t*) +							callback_job_create((void*)add_exclude_async, entry, +												(void*)entry_destroy, NULL)); +	} +	list->destroy(list);  	return TRUE;  }  /**   * Remove a bypass policy for a given subnet   */ -static bool remove_exclude(private_unity_handler_t *this, chunk_t subnet) +static bool remove_exclude(private_unity_handler_t *this, chunk_t data)  {  	traffic_selector_t *ts; +	linked_list_t *list;  	ike_sa_t *ike_sa;  	char name[128]; +	bool success = TRUE;  	ike_sa = charon->bus->get_sa(charon->bus);  	if (!ike_sa)  	{  		return FALSE;  	} -	ts = create_ts(subnet); -	if (!ts) +	list = parse_subnets(data); +	if (!list)  	{  		return FALSE;  	} -	create_shunt_name(ike_sa, ts, name, sizeof(name)); -	DBG1(DBG_IKE, "uninstalling %N bypass policy for %R", -		 configuration_attribute_type_names, UNITY_LOCAL_LAN, ts); -	ts->destroy(ts); -	return charon->shunts->uninstall(charon->shunts, name); +	while (list->remove_first(list, (void**)&ts) == SUCCESS) +	{ +		create_shunt_name(ike_sa, ts, name, sizeof(name)); +		DBG1(DBG_IKE, "uninstalling %N bypass policy for %R", +			 configuration_attribute_type_names, UNITY_LOCAL_LAN, ts); +		ts->destroy(ts); +		success = charon->shunts->uninstall(charon->shunts, name) && success; +	} +	list->destroy(list); +	return success;  }  METHOD(attribute_handler_t, handle, bool,  | 
