traffic-selector-list: Add helper class to manage a collection of TS
Provides functions to optionally resolve dynamic TS and to narrow them based on a list of supplied TS.
This commit is contained in:
@@ -42,7 +42,7 @@ networking/streams/stream_tcp.c networking/streams/stream_service_tcp.c \
|
|||||||
pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c \
|
pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c \
|
||||||
processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \
|
processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \
|
||||||
processing/watcher.c resolver/resolver_manager.c resolver/rr_set.c \
|
processing/watcher.c resolver/resolver_manager.c resolver/rr_set.c \
|
||||||
selectors/sec_label.c selectors/traffic_selector.c \
|
selectors/sec_label.c selectors/traffic_selector.c selectors/traffic_selector_list.c \
|
||||||
settings/settings.c settings/settings_types.c \
|
settings/settings.c settings/settings_types.c \
|
||||||
settings/settings_parser.c settings/settings_lexer.c utils/cpu_feature.c \
|
settings/settings_parser.c settings/settings_lexer.c utils/cpu_feature.c \
|
||||||
utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \
|
utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ networking/streams/stream_tcp.c networking/streams/stream_service_tcp.c \
|
|||||||
pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c \
|
pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c \
|
||||||
processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \
|
processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \
|
||||||
processing/watcher.c resolver/resolver_manager.c resolver/rr_set.c \
|
processing/watcher.c resolver/resolver_manager.c resolver/rr_set.c \
|
||||||
selectors/sec_label.c selectors/traffic_selector.c \
|
selectors/sec_label.c selectors/traffic_selector.c selectors/traffic_selector_list.c \
|
||||||
settings/settings.c settings/settings_types.c \
|
settings/settings.c settings/settings_types.c \
|
||||||
settings/settings_parser.y settings/settings_lexer.l utils/cpu_feature.c \
|
settings/settings_parser.y settings/settings_lexer.l utils/cpu_feature.c \
|
||||||
utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \
|
utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \
|
||||||
@@ -125,7 +125,7 @@ resolver/rr.h resolver/resolver_manager.h \
|
|||||||
plugins/plugin_loader.h plugins/plugin.h plugins/plugin_feature.h \
|
plugins/plugin_loader.h plugins/plugin.h plugins/plugin_feature.h \
|
||||||
processing/jobs/job.h processing/jobs/callback_job.h processing/processor.h \
|
processing/jobs/job.h processing/jobs/callback_job.h processing/processor.h \
|
||||||
processing/scheduler.h processing/watcher.h \
|
processing/scheduler.h processing/watcher.h \
|
||||||
selectors/sec_label.h selectors/traffic_selector.h \
|
selectors/sec_label.h selectors/traffic_selector.h selectors/traffic_selector_list.h \
|
||||||
settings/settings.h settings/settings_parser.h threading/thread_value.h \
|
settings/settings.h settings/settings_parser.h threading/thread_value.h \
|
||||||
threading/thread.h threading/windows/thread.h \
|
threading/thread.h threading/windows/thread.h \
|
||||||
threading/mutex.h threading/condvar.h threading/spinlock.h threading/semaphore.h \
|
threading/mutex.h threading/condvar.h threading/spinlock.h threading/semaphore.h \
|
||||||
|
|||||||
@@ -0,0 +1,292 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008-2025 Tobias Brunner
|
||||||
|
* Copyright (C) 2005-2007 Martin Willi
|
||||||
|
*
|
||||||
|
* Copyright (C) secunet Security Networks AG
|
||||||
|
*
|
||||||
|
* 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 "traffic_selector_list.h"
|
||||||
|
|
||||||
|
#include <utils/debug.h>
|
||||||
|
|
||||||
|
typedef struct private_traffic_selector_list_t private_traffic_selector_list_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private data.
|
||||||
|
*/
|
||||||
|
struct private_traffic_selector_list_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public interface.
|
||||||
|
*/
|
||||||
|
traffic_selector_list_t public;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of managed traffic selectors.
|
||||||
|
*/
|
||||||
|
linked_list_t *ts;
|
||||||
|
};
|
||||||
|
|
||||||
|
METHOD(traffic_selector_list_t, add, void,
|
||||||
|
private_traffic_selector_list_t *this, traffic_selector_t *ts)
|
||||||
|
{
|
||||||
|
this->ts->insert_last(this->ts, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(traffic_selector_list_t, create_enumerator, enumerator_t*,
|
||||||
|
private_traffic_selector_list_t *this)
|
||||||
|
{
|
||||||
|
return this->ts->create_enumerator(this->ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a copy of the traffic selectors in the given list, while resolving
|
||||||
|
* "dynamic" traffic selectors using the given hosts, if any. When not narrowing
|
||||||
|
* as initiator, we also replace TS in transport mode.
|
||||||
|
*/
|
||||||
|
static linked_list_t *resolve_dynamic_ts(private_traffic_selector_list_t *this,
|
||||||
|
linked_list_t *hosts, bool narrowing,
|
||||||
|
bool force_dynamic)
|
||||||
|
{
|
||||||
|
enumerator_t *e1, *e2;
|
||||||
|
traffic_selector_t *ts1, *ts2;
|
||||||
|
linked_list_t *result;
|
||||||
|
host_t *host;
|
||||||
|
|
||||||
|
if (!hosts || !hosts->get_count(hosts))
|
||||||
|
{
|
||||||
|
return this->ts->clone_offset(this->ts,
|
||||||
|
offsetof(traffic_selector_t, clone));
|
||||||
|
}
|
||||||
|
|
||||||
|
result = linked_list_create();
|
||||||
|
e1 = this->ts->create_enumerator(this->ts);
|
||||||
|
while (e1->enumerate(e1, &ts1))
|
||||||
|
{
|
||||||
|
/* set hosts if TS is dynamic or if forced as initiator in
|
||||||
|
* transport mode */
|
||||||
|
bool dynamic = ts1->is_dynamic(ts1);
|
||||||
|
if (!dynamic && !force_dynamic)
|
||||||
|
{
|
||||||
|
result->insert_last(result, ts1->clone(ts1));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
e2 = hosts->create_enumerator(hosts);
|
||||||
|
while (e2->enumerate(e2, &host))
|
||||||
|
{
|
||||||
|
if (!dynamic && !host->is_anyaddr(host) &&
|
||||||
|
!ts1->includes(ts1, host))
|
||||||
|
{ /* for transport mode, we skip TS that don't match
|
||||||
|
* specific IPs */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ts2 = ts1->clone(ts1);
|
||||||
|
if (dynamic || !host->is_anyaddr(host))
|
||||||
|
{ /* don't make regular TS larger than they were */
|
||||||
|
ts2->set_address(ts2, host);
|
||||||
|
}
|
||||||
|
result->insert_last(result, ts2);
|
||||||
|
}
|
||||||
|
e2->destroy(e2);
|
||||||
|
}
|
||||||
|
e1->destroy(e1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove duplicate traffic selectors in the given list.
|
||||||
|
*/
|
||||||
|
static void remove_duplicate_ts(linked_list_t *list)
|
||||||
|
{
|
||||||
|
enumerator_t *e1, *e2;
|
||||||
|
traffic_selector_t *ts1, *ts2;
|
||||||
|
|
||||||
|
e1 = list->create_enumerator(list);
|
||||||
|
e2 = list->create_enumerator(list);
|
||||||
|
while (e1->enumerate(e1, &ts1))
|
||||||
|
{
|
||||||
|
while (e2->enumerate(e2, &ts2))
|
||||||
|
{
|
||||||
|
if (ts1 != ts2)
|
||||||
|
{
|
||||||
|
if (ts2->is_contained_in(ts2, ts1))
|
||||||
|
{
|
||||||
|
list->remove_at(list, e2);
|
||||||
|
ts2->destroy(ts2);
|
||||||
|
list->reset_enumerator(list, e1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ts1->is_contained_in(ts1, ts2))
|
||||||
|
{
|
||||||
|
list->remove_at(list, e1);
|
||||||
|
ts1->destroy(ts1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list->reset_enumerator(list, e2);
|
||||||
|
}
|
||||||
|
e1->destroy(e1);
|
||||||
|
e2->destroy(e2);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(traffic_selector_list_t, get, linked_list_t*,
|
||||||
|
private_traffic_selector_list_t *this, linked_list_t *hosts,
|
||||||
|
bool force_dynamic)
|
||||||
|
{
|
||||||
|
linked_list_t *result;
|
||||||
|
|
||||||
|
result = resolve_dynamic_ts(this, hosts, FALSE, force_dynamic);
|
||||||
|
remove_duplicate_ts(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(traffic_selector_list_t, select_, linked_list_t*,
|
||||||
|
private_traffic_selector_list_t *this, linked_list_t *supplied,
|
||||||
|
linked_list_t *hosts, bool force_dynamic, bool *narrowed)
|
||||||
|
{
|
||||||
|
enumerator_t *e1, *e2;
|
||||||
|
traffic_selector_t *ts1, *ts2, *selected;
|
||||||
|
linked_list_t *resolved, *result;
|
||||||
|
|
||||||
|
result = linked_list_create();
|
||||||
|
resolved = resolve_dynamic_ts(this, hosts, supplied != NULL, force_dynamic);
|
||||||
|
|
||||||
|
if (!supplied)
|
||||||
|
{
|
||||||
|
while (resolved->remove_first(resolved, (void**)&ts1) == SUCCESS)
|
||||||
|
{
|
||||||
|
DBG2(DBG_CFG, " %R", ts1);
|
||||||
|
result->insert_last(result, ts1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
e1 = resolved->create_enumerator(resolved);
|
||||||
|
e2 = supplied->create_enumerator(supplied);
|
||||||
|
/* enumerate all configured/resolved selectors */
|
||||||
|
while (e1->enumerate(e1, &ts1))
|
||||||
|
{
|
||||||
|
/* enumerate all supplied traffic selectors */
|
||||||
|
while (e2->enumerate(e2, &ts2))
|
||||||
|
{
|
||||||
|
selected = ts1->get_subset(ts1, ts2);
|
||||||
|
if (selected)
|
||||||
|
{
|
||||||
|
DBG2(DBG_CFG, " config: %R, received: %R => match: %R",
|
||||||
|
ts1, ts2, selected);
|
||||||
|
result->insert_last(result, selected);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG2(DBG_CFG, " config: %R, received: %R => no match",
|
||||||
|
ts1, ts2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
supplied->reset_enumerator(supplied, e2);
|
||||||
|
}
|
||||||
|
e1->destroy(e1);
|
||||||
|
e2->destroy(e2);
|
||||||
|
|
||||||
|
if (narrowed)
|
||||||
|
{
|
||||||
|
*narrowed = FALSE;
|
||||||
|
|
||||||
|
e1 = resolved->create_enumerator(resolved);
|
||||||
|
e2 = result->create_enumerator(result);
|
||||||
|
while (e1->enumerate(e1, &ts1))
|
||||||
|
{
|
||||||
|
if (!e2->enumerate(e2, &ts2) || !ts1->equals(ts1, ts2))
|
||||||
|
{
|
||||||
|
*narrowed = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e1->destroy(e1);
|
||||||
|
e2->destroy(e2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolved->destroy_offset(resolved, offsetof(traffic_selector_t, destroy));
|
||||||
|
remove_duplicate_ts(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(traffic_selector_list_t, equals, bool,
|
||||||
|
private_traffic_selector_list_t *this, traffic_selector_list_t *other_pub)
|
||||||
|
{
|
||||||
|
private_traffic_selector_list_t *other = (private_traffic_selector_list_t*)other_pub;
|
||||||
|
return this->ts->equals_offset(this->ts, other->ts,
|
||||||
|
offsetof(traffic_selector_t, equals));
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(traffic_selector_list_t, destroy, void,
|
||||||
|
private_traffic_selector_list_t *this)
|
||||||
|
{
|
||||||
|
this->ts->destroy_offset(this->ts, offsetof(traffic_selector_t, destroy));
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(traffic_selector_list_t, clone_, traffic_selector_list_t*,
|
||||||
|
private_traffic_selector_list_t *this)
|
||||||
|
{
|
||||||
|
return traffic_selector_list_create_from_list(
|
||||||
|
this->ts->clone_offset(this->ts, offsetof(traffic_selector_t, clone)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Described in header
|
||||||
|
*/
|
||||||
|
traffic_selector_list_t *traffic_selector_list_create_from_list(linked_list_t *list)
|
||||||
|
{
|
||||||
|
private_traffic_selector_list_t *this;
|
||||||
|
|
||||||
|
INIT(this,
|
||||||
|
.public = {
|
||||||
|
.add = _add,
|
||||||
|
.create_enumerator = _create_enumerator,
|
||||||
|
.get = _get,
|
||||||
|
.select = _select_,
|
||||||
|
.equals = _equals,
|
||||||
|
.clone = _clone_,
|
||||||
|
.destroy = _destroy,
|
||||||
|
},
|
||||||
|
.ts = list,
|
||||||
|
);
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Described in header
|
||||||
|
*/
|
||||||
|
traffic_selector_list_t *traffic_selector_list_create()
|
||||||
|
{
|
||||||
|
return traffic_selector_list_create_from_list(linked_list_create());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Described in header
|
||||||
|
*/
|
||||||
|
traffic_selector_list_t *traffic_selector_list_create_from_enumerator(
|
||||||
|
enumerator_t *enumerator)
|
||||||
|
{
|
||||||
|
traffic_selector_list_t *this = traffic_selector_list_create();
|
||||||
|
traffic_selector_t *ts;
|
||||||
|
|
||||||
|
while (enumerator->enumerate(enumerator, &ts))
|
||||||
|
{
|
||||||
|
add((private_traffic_selector_list_t*)this, ts->clone(ts));
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2025 Tobias Brunner
|
||||||
|
*
|
||||||
|
* Copyright (C) secunet Security Networks AG
|
||||||
|
*
|
||||||
|
* 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_list traffic_selector_list
|
||||||
|
* @{ @ingroup selectors
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TRAFFIC_SELECTOR_LIST_H_
|
||||||
|
#define TRAFFIC_SELECTOR_LIST_H_
|
||||||
|
|
||||||
|
typedef struct traffic_selector_list_t traffic_selector_list_t;
|
||||||
|
|
||||||
|
#include "traffic_selector.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection of traffic selectors that can be narrowed to a new set of
|
||||||
|
* traffic selectors.
|
||||||
|
*/
|
||||||
|
struct traffic_selector_list_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a traffic selector to the collection.
|
||||||
|
*
|
||||||
|
* @param ts traffic_selector to add (adopted)
|
||||||
|
*/
|
||||||
|
void (*add)(traffic_selector_list_t *this, traffic_selector_t *ts);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumerate all traffic selectors in the collection.
|
||||||
|
*
|
||||||
|
* Similar to calling get() without \p hosts, but does not clone the traffic
|
||||||
|
* selectors and duplicates are not removed.
|
||||||
|
*
|
||||||
|
* @return enumerator over traffic_selector_t*
|
||||||
|
*/
|
||||||
|
enumerator_t *(*create_enumerator)(traffic_selector_list_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of traffic selectors contained in the collection.
|
||||||
|
*
|
||||||
|
* Some traffic selectors may be "dynamic", meaning they are narrowed down
|
||||||
|
* to a specific address (host-to-host or virtual-IP setups). Use the
|
||||||
|
* \p hosts parameter to narrow such traffic selectors to an address. If
|
||||||
|
* \p force_dynamic is also passed, even non-dynamic traffic selectors that
|
||||||
|
* match are replaced using the IPs in \p hosts (useful as initiator with
|
||||||
|
* transport mode).
|
||||||
|
*
|
||||||
|
* If \p hosts is not passed, the list of traffic selectors is returned as
|
||||||
|
* configured, except that exact duplicates are removed. However, note that
|
||||||
|
* "dynamic" traffic selectors are not considered duplicates.
|
||||||
|
*
|
||||||
|
* Returned list and its traffic selectors must be destroyed after use.
|
||||||
|
*
|
||||||
|
* Note that this method does not log anything. If logging is required, use
|
||||||
|
* select() without passing supplied traffic selectors.
|
||||||
|
*
|
||||||
|
* @param hosts addresses to use for narrowing "dynamic" TS, host_t
|
||||||
|
* @param force_dynamic TRUE to replace non-"dynamic" TS with \p hosts as
|
||||||
|
* initiator in transport mode
|
||||||
|
* @return list containing the traffic selectors
|
||||||
|
*/
|
||||||
|
linked_list_t *(*get)(traffic_selector_list_t *this, linked_list_t *hosts,
|
||||||
|
bool force_dynamic);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select a list of traffic selectors contained in the collection.
|
||||||
|
*
|
||||||
|
* If a list with traffic selectors is supplied, these are used to narrow
|
||||||
|
* down the traffic selectors to the greatest common subset.
|
||||||
|
*
|
||||||
|
* Some traffic selectors may be "dynamic", meaning they are narrowed down
|
||||||
|
* to a specific address (host-to-host or virtual-IP setups). Use the
|
||||||
|
* \p hosts parameter to narrow such traffic selectors to an address. If
|
||||||
|
* \p force_dynamic is also passed, even non-dynamic traffic selectors that
|
||||||
|
* match are replaced using the IPs in \p hosts (useful as initiator with
|
||||||
|
* transport mode).
|
||||||
|
*
|
||||||
|
* Details about the selection of each individual traffic selector are
|
||||||
|
* logged.
|
||||||
|
*
|
||||||
|
* Returned list and its traffic selectors must be destroyed after use.
|
||||||
|
*
|
||||||
|
* @param supplied list with TS to select from, or NULL
|
||||||
|
* @param hosts addresses to use for narrowing "dynamic" TS', host_t
|
||||||
|
* @param force_dynamic TRUE to replace non-"dynamic" TS with \p hosts as
|
||||||
|
* initiator in transport mode
|
||||||
|
* @param narrowed[out] optional flag that indicates if any TS were narrowed
|
||||||
|
* @return list containing the traffic selectors
|
||||||
|
*/
|
||||||
|
linked_list_t *(*select)(traffic_selector_list_t *this,
|
||||||
|
linked_list_t *supplied, linked_list_t *hosts,
|
||||||
|
bool force_dynamic, bool *narrowed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two collections of traffic selectors.
|
||||||
|
*
|
||||||
|
* @param other collection to compare with this
|
||||||
|
* @return TRUE if equal, FALSE otherwise
|
||||||
|
*/
|
||||||
|
bool (*equals)(traffic_selector_list_t *this, traffic_selector_list_t *other);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone this collection of traffic selectors.
|
||||||
|
*
|
||||||
|
* @return cloned collection
|
||||||
|
*/
|
||||||
|
traffic_selector_list_t *(*clone)(traffic_selector_list_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys this collection.
|
||||||
|
*/
|
||||||
|
void (*destroy)(traffic_selector_list_t *this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an empty traffic selector collection.
|
||||||
|
*
|
||||||
|
* @return created object
|
||||||
|
*/
|
||||||
|
traffic_selector_list_t *traffic_selector_list_create();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a collection with traffic selectors from the given list (adopted).
|
||||||
|
*
|
||||||
|
* @param list list of traffic_selector_t (adopted)
|
||||||
|
* @return created object
|
||||||
|
*/
|
||||||
|
traffic_selector_list_t *traffic_selector_list_create_from_list(
|
||||||
|
linked_list_t *list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a collection with traffic selectors from the given enumerator (objects
|
||||||
|
* are cloned, the enumerator is destroyed).
|
||||||
|
*
|
||||||
|
* @param enumerator enumerator over traffic_selector_t (cloned/destroyed)
|
||||||
|
* @return created object
|
||||||
|
*/
|
||||||
|
traffic_selector_list_t *traffic_selector_list_create_from_enumerator(
|
||||||
|
enumerator_t *enumerator);
|
||||||
|
|
||||||
|
#endif /** TRAFFIC_SELECTOR_LIST_H_ @}*/
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 Tobias Brunner
|
* Copyright (C) 2015-2025 Tobias Brunner
|
||||||
* Copyright (C) 2015 Martin Willi
|
* Copyright (C) 2015 Martin Willi
|
||||||
*
|
*
|
||||||
* Copyright (C) secunet Security Networks AG
|
* Copyright (C) secunet Security Networks AG
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "test_suite.h"
|
#include "test_suite.h"
|
||||||
|
|
||||||
#include <selectors/traffic_selector.h>
|
#include <selectors/traffic_selector.h>
|
||||||
|
#include <selectors/traffic_selector_list.h>
|
||||||
|
|
||||||
|
|
||||||
static void verify(const char *str, const char *alt, traffic_selector_t *ts)
|
static void verify(const char *str, const char *alt, traffic_selector_t *ts)
|
||||||
@@ -814,6 +815,199 @@ START_TEST(test_printf_hook_hash)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a linked list of either traffic selectors or hosts from a
|
||||||
|
* comma-separated list.
|
||||||
|
*/
|
||||||
|
static linked_list_t *create_list(char *str, bool hosts)
|
||||||
|
{
|
||||||
|
linked_list_t *list = linked_list_create();
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
char *item;
|
||||||
|
void *obj;
|
||||||
|
|
||||||
|
enumerator = enumerator_create_token(str, " ", "");
|
||||||
|
while (enumerator->enumerate(enumerator, &item))
|
||||||
|
{
|
||||||
|
if (hosts)
|
||||||
|
{
|
||||||
|
obj = host_create_from_string(item, 0);
|
||||||
|
}
|
||||||
|
else if (streq(item, "dynamic"))
|
||||||
|
{
|
||||||
|
obj = traffic_selector_create_dynamic(0, 0, 65535);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obj = traffic_selector_create_from_cidr(item, 0, 0, 65535);
|
||||||
|
}
|
||||||
|
list->insert_last(list, obj);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char *ts;
|
||||||
|
char *hosts;
|
||||||
|
char *get;
|
||||||
|
char *get_force;
|
||||||
|
} list_get_tests[] = {
|
||||||
|
{ "dynamic", NULL, "dynamic", "dynamic" },
|
||||||
|
{ "dynamic", "10.0.1.1", "10.0.1.1/32", "10.0.1.1/32" },
|
||||||
|
{ "dynamic", "10.0.1.1 192.168.0.1",
|
||||||
|
"10.0.1.1/32 192.168.0.1/32", "10.0.1.1/32 192.168.0.1/32" },
|
||||||
|
{ "0.0.0.0/0", "10.0.1.1", "0.0.0.0/0", "10.0.1.1/32" },
|
||||||
|
{ "0.0.0.0/0", "10.0.1.1 192.168.0.1",
|
||||||
|
"0.0.0.0/0", "10.0.1.1/32 192.168.0.1/32" },
|
||||||
|
{ "10.0.1.0/24", "10.0.1.1", "10.0.1.0/24", "10.0.1.1/32" },
|
||||||
|
{ "10.0.2.0/24", "10.0.1.1", "10.0.2.0/24", "" },
|
||||||
|
{ "10.0.2.0/24", "10.0.1.1 10.0.2.1", "10.0.2.0/24", "10.0.2.1/32" },
|
||||||
|
/* two dynamic TS are not treated as duplicates */
|
||||||
|
{ "dynamic dynamic", NULL, "dynamic dynamic", "dynamic dynamic" },
|
||||||
|
{ "dynamic dynamic", "10.0.1.1", "10.0.1.1/32", "10.0.1.1/32" },
|
||||||
|
{ "dynamic dynamic", "10.0.1.1 192.168.0.1",
|
||||||
|
"10.0.1.1/32 192.168.0.1/32", "10.0.1.1/32 192.168.0.1/32" },
|
||||||
|
{ "0.0.0.0/0 0.0.0.0/0", "10.0.1.1", "0.0.0.0/0", "10.0.1.1/32" },
|
||||||
|
{ "0.0.0.0/0 0.0.0.0/0", "10.0.1.1 192.168.0.1",
|
||||||
|
"0.0.0.0/0", "10.0.1.1/32 192.168.0.1/32" },
|
||||||
|
{ "10.0.1.0/24 10.0.1.0/24", NULL, "10.0.1.0/24", "10.0.1.0/24" },
|
||||||
|
{ "10.0.1.1/32 10.0.1.0/24", NULL, "10.0.1.0/24", "10.0.1.0/24" },
|
||||||
|
{ "10.0.1.0/24 10.0.1.1/32", NULL, "10.0.1.0/24", "10.0.1.0/24" },
|
||||||
|
{ "10.0.1.0/24 10.0.2.0/24", NULL,
|
||||||
|
"10.0.1.0/24 10.0.2.0/24", "10.0.1.0/24 10.0.2.0/24" },
|
||||||
|
{ "10.0.1.0/24 10.0.2.0/24", "10.0.1.1",
|
||||||
|
"10.0.1.0/24 10.0.2.0/24", "10.0.1.1/32" },
|
||||||
|
{ "10.0.1.0/24 10.0.2.0/24", "10.0.1.1 10.0.2.1",
|
||||||
|
"10.0.1.0/24 10.0.2.0/24", "10.0.1.1/32 10.0.2.1/32" },
|
||||||
|
};
|
||||||
|
|
||||||
|
START_TEST(test_list_get)
|
||||||
|
{
|
||||||
|
traffic_selector_list_t *ts;
|
||||||
|
linked_list_t *list, *hosts, *result;
|
||||||
|
|
||||||
|
list = create_list(list_get_tests[_i].ts, FALSE);
|
||||||
|
ts = traffic_selector_list_create_from_enumerator(list->create_enumerator(list));
|
||||||
|
hosts = list_get_tests[_i].hosts ? create_list(list_get_tests[_i].hosts, TRUE) : NULL;
|
||||||
|
|
||||||
|
result = ts->get(ts, hosts, FALSE);
|
||||||
|
verify_list(list_get_tests[_i].get, NULL, result);
|
||||||
|
|
||||||
|
result = ts->get(ts, hosts, TRUE);
|
||||||
|
verify_list(list_get_tests[_i].get_force, NULL, result);
|
||||||
|
|
||||||
|
DESTROY_OFFSET_IF(hosts, offsetof(host_t, destroy));
|
||||||
|
list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
|
||||||
|
ts->destroy(ts);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char *ts;
|
||||||
|
char *hosts;
|
||||||
|
char *supplied;
|
||||||
|
char *select;
|
||||||
|
char *select_force;
|
||||||
|
bool narrowed;
|
||||||
|
} list_select_tests[] = {
|
||||||
|
{ "dynamic", NULL, NULL, "dynamic", "dynamic", FALSE },
|
||||||
|
{ "dynamic", NULL, "10.0.1.0/24", "", "", TRUE },
|
||||||
|
{ "dynamic", "10.0.1.1", "0.0.0.0/0", "10.0.1.1/32", "10.0.1.1/32", FALSE },
|
||||||
|
{ "dynamic", "10.0.1.1", "10.0.1.1/32", "10.0.1.1/32", "10.0.1.1/32", FALSE },
|
||||||
|
{ "dynamic", "10.0.1.1 192.168.0.1", "10.0.1.0/24",
|
||||||
|
"10.0.1.1/32", "10.0.1.1/32", TRUE },
|
||||||
|
{ "dynamic", "10.0.1.1 192.168.0.1", "10.0.1.0/24 192.168.0.0/24",
|
||||||
|
"10.0.1.1/32 192.168.0.1/32", "10.0.1.1/32 192.168.0.1/32", FALSE },
|
||||||
|
{ "0.0.0.0/0", NULL, "0.0.0.0/0", "0.0.0.0/0", "0.0.0.0/0", FALSE },
|
||||||
|
{ "0.0.0.0/0", "10.0.1.1", "0.0.0.0/0", "0.0.0.0/0", "10.0.1.1/32", FALSE },
|
||||||
|
{ "0.0.0.0/0", NULL, "10.0.1.0/24", "10.0.1.0/24", "10.0.1.0/24", TRUE },
|
||||||
|
{ "0.0.0.0/0", NULL, "10.0.1.0/24 10.0.2.0/24",
|
||||||
|
"10.0.1.0/24 10.0.2.0/24", "10.0.1.0/24 10.0.2.0/24", TRUE },
|
||||||
|
{ "0.0.0.0/0", NULL, "10.0.2.0/24 10.0.1.0/24",
|
||||||
|
"10.0.2.0/24 10.0.1.0/24", "10.0.2.0/24 10.0.1.0/24", TRUE },
|
||||||
|
{ "10.0.1.0/24", NULL, "0.0.0.0/0", "10.0.1.0/24", "10.0.1.0/24", FALSE },
|
||||||
|
{ "10.0.1.0/24", "10.0.1.1", "0.0.0.0/0", "10.0.1.0/24", "10.0.1.1/32", FALSE },
|
||||||
|
{ "10.0.1.0/24 10.0.2.0/24", NULL, "0.0.0.0/0",
|
||||||
|
"10.0.1.0/24 10.0.2.0/24", "10.0.1.0/24 10.0.2.0/24", FALSE },
|
||||||
|
{ "10.0.2.0/24 10.0.1.0/24", NULL, "0.0.0.0/0",
|
||||||
|
"10.0.2.0/24 10.0.1.0/24", "10.0.2.0/24 10.0.1.0/24", FALSE },
|
||||||
|
{ "10.0.1.0/24 10.0.2.0/24", NULL, "10.0.2.0/24 10.0.1.0/24",
|
||||||
|
"10.0.1.0/24 10.0.2.0/24", "10.0.1.0/24 10.0.2.0/24", FALSE },
|
||||||
|
{ "10.0.1.0/24 10.0.2.0/24", NULL, "10.0.1.1/32 10.0.1.0/24",
|
||||||
|
"10.0.1.0/24", "10.0.1.0/24", TRUE },
|
||||||
|
{ "10.0.1.0/24 10.0.2.0/24", NULL, "10.0.2.1/32 10.0.1.0/24",
|
||||||
|
"10.0.1.0/24 10.0.2.1/32", "10.0.1.0/24 10.0.2.1/32", TRUE },
|
||||||
|
};
|
||||||
|
|
||||||
|
START_TEST(test_list_select)
|
||||||
|
{
|
||||||
|
traffic_selector_list_t *ts;
|
||||||
|
linked_list_t *list, *hosts, *supplied, *result;
|
||||||
|
bool narrowed = FALSE;
|
||||||
|
|
||||||
|
list = create_list(list_select_tests[_i].ts, FALSE);
|
||||||
|
ts = traffic_selector_list_create_from_enumerator(list->create_enumerator(list));
|
||||||
|
hosts = list_select_tests[_i].hosts ? create_list(list_select_tests[_i].hosts, TRUE) : NULL;
|
||||||
|
supplied = list_select_tests[_i].supplied ? create_list(list_select_tests[_i].supplied, FALSE) : NULL;
|
||||||
|
|
||||||
|
result = ts->select(ts, supplied, hosts, FALSE, &narrowed);
|
||||||
|
verify_list(list_select_tests[_i].select, NULL, result);
|
||||||
|
ck_assert(narrowed == list_select_tests[_i].narrowed);
|
||||||
|
|
||||||
|
result = ts->select(ts, supplied, hosts, TRUE, &narrowed);
|
||||||
|
verify_list(list_select_tests[_i].select_force, NULL, result);
|
||||||
|
ck_assert(narrowed == list_select_tests[_i].narrowed);
|
||||||
|
|
||||||
|
DESTROY_OFFSET_IF(hosts, offsetof(host_t, destroy));
|
||||||
|
DESTROY_OFFSET_IF(supplied, offsetof(traffic_selector_t, destroy));
|
||||||
|
list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
|
||||||
|
ts->destroy(ts);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_list_equals)
|
||||||
|
{
|
||||||
|
traffic_selector_list_t *ts1, *ts2;
|
||||||
|
|
||||||
|
ts1 = traffic_selector_list_create();
|
||||||
|
ts2 = traffic_selector_list_create();
|
||||||
|
ck_assert(ts1->equals(ts1, ts2));
|
||||||
|
|
||||||
|
ts1->add(ts1, traffic_selector_create_from_cidr("10.0.1.0/24", 0, 0, 65535));
|
||||||
|
ck_assert(!ts1->equals(ts1, ts2));
|
||||||
|
|
||||||
|
ts2->add(ts2, traffic_selector_create_from_cidr("10.0.1.0/24", 0, 0, 65535));
|
||||||
|
ck_assert(ts1->equals(ts1, ts2));
|
||||||
|
|
||||||
|
ts1->destroy(ts1);
|
||||||
|
ts2->destroy(ts2);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_list_clone)
|
||||||
|
{
|
||||||
|
traffic_selector_list_t *ts1, *ts2;
|
||||||
|
|
||||||
|
ts1 = traffic_selector_list_create();
|
||||||
|
ts2 = ts1->clone(ts1);
|
||||||
|
ck_assert(ts1->equals(ts1, ts2));
|
||||||
|
ts2->destroy(ts2);
|
||||||
|
|
||||||
|
ts1->add(ts1, traffic_selector_create_from_cidr("10.0.1.0/24", 0, 0, 65535));
|
||||||
|
ts2 = ts1->clone(ts1);
|
||||||
|
ck_assert(ts1->equals(ts1, ts2));
|
||||||
|
ts2->destroy(ts2);
|
||||||
|
|
||||||
|
ts1->add(ts1, traffic_selector_create_from_cidr("10.0.1.0/24", 0, 0, 65535));
|
||||||
|
ts2 = ts1->clone(ts1);
|
||||||
|
ck_assert(ts1->equals(ts1, ts2));
|
||||||
|
|
||||||
|
ts1->destroy(ts1);
|
||||||
|
ts2->destroy(ts2);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
Suite *traffic_selector_suite_create()
|
Suite *traffic_selector_suite_create()
|
||||||
{
|
{
|
||||||
Suite *s;
|
Suite *s;
|
||||||
@@ -890,5 +1084,12 @@ Suite *traffic_selector_suite_create()
|
|||||||
tcase_add_test(tc, test_printf_hook_hash);
|
tcase_add_test(tc, test_printf_hook_hash);
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
tc = tcase_create("list");
|
||||||
|
tcase_add_loop_test(tc, test_list_get, 0, 0/*countof(list_get_tests)*/);
|
||||||
|
tcase_add_loop_test(tc, test_list_select, 0, countof(list_select_tests));
|
||||||
|
tcase_add_test(tc, test_list_equals);
|
||||||
|
tcase_add_test(tc, test_list_clone);
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user