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 \
|
||||
processing/jobs/callback_job.c processing/processor.c processing/scheduler.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_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 \
|
||||
|
||||
@@ -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 \
|
||||
processing/jobs/callback_job.c processing/processor.c processing/scheduler.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_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 \
|
||||
@@ -125,7 +125,7 @@ resolver/rr.h resolver/resolver_manager.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/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 \
|
||||
threading/thread.h threading/windows/thread.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) secunet Security Networks AG
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "test_suite.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)
|
||||
@@ -814,6 +815,199 @@ START_TEST(test_printf_hook_hash)
|
||||
}
|
||||
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 *s;
|
||||
@@ -890,5 +1084,12 @@ Suite *traffic_selector_suite_create()
|
||||
tcase_add_test(tc, test_printf_hook_hash);
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user