traffic-selector: Use single buffer for both address families

The generic field of size 0 in the union that was used previously
triggered index-out-of-bounds errors with the UBSAN sanitizer that's
used on OSS-Fuzz.  Since the two family specific union members don't
really provide any advantage, we can just use a single buffer for both
families to avoid the errors.
This commit is contained in:
Tobias Brunner
2017-08-17 12:34:40 +02:00
parent 936db031c7
commit 9cf2920512
2 changed files with 102 additions and 159 deletions
+73 -150
View File
@@ -25,6 +25,10 @@
#include <utils/identification.h> #include <utils/identification.h>
#include <collections/linked_list.h> #include <collections/linked_list.h>
#define IPV4_LEN 4
#define IPV6_LEN 16
#define TS_IP_LEN(this) ({ ((this)->type == TS_IPV4_ADDR_RANGE) ? IPV4_LEN : IPV6_LEN; })
#define NON_SUBNET_ADDRESS_RANGE 255 #define NON_SUBNET_ADDRESS_RANGE 255
ENUM(ts_type_name, TS_IPV4_ADDR_RANGE, TS_IPV6_ADDR_RANGE, ENUM(ts_type_name, TS_IPV4_ADDR_RANGE, TS_IPV6_ADDR_RANGE,
@@ -68,26 +72,12 @@ struct private_traffic_selector_t {
/** /**
* begin of address range, network order * begin of address range, network order
*/ */
union { char from[IPV6_LEN];
/** dummy char for common address manipulation */
char from[0];
/** IPv4 address */
uint32_t from4[1];
/** IPv6 address */
uint32_t from6[4];
};
/** /**
* end of address range, network order * end of address range, network order
*/ */
union { char to[IPV6_LEN];
/** dummy char for common address manipulation */
char to[0];
/** IPv4 address */
uint32_t to4[1];
/** IPv6 address */
uint32_t to6[4];
};
/** /**
* begin of port range * begin of port range
@@ -111,7 +101,7 @@ static void calc_range(private_traffic_selector_t *this, uint8_t netbits)
this->netbits = netbits; this->netbits = netbits;
len = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16; len = TS_IP_LEN(this);
bytes = (netbits + 7)/8; bytes = (netbits + 7)/8;
bits = (bytes * 8) - netbits; bits = (bytes * 8) - netbits;
mask = bits ? (1 << bits) - 1 : 0; mask = bits ? (1 << bits) - 1 : 0;
@@ -130,7 +120,7 @@ static uint8_t calc_netbits(private_traffic_selector_t *this)
{ {
int byte, bit; int byte, bit;
uint8_t netbits; uint8_t netbits;
size_t size = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16; size_t size = TS_IP_LEN(this);
bool prefix = TRUE; bool prefix = TRUE;
/* a perfect match results in a single address with a /32 or /128 netmask */ /* a perfect match results in a single address with a /32 or /128 netmask */
@@ -221,8 +211,8 @@ int traffic_selector_printf_hook(printf_hook_data_t *data,
char to_str[INET6_ADDRSTRLEN] = ""; char to_str[INET6_ADDRSTRLEN] = "";
char *serv_proto = NULL, *sep = ""; char *serv_proto = NULL, *sep = "";
bool has_proto, has_ports; bool has_proto, has_ports;
size_t written = 0; size_t written = 0, len;
uint32_t from[4], to[4]; char from[IPV6_LEN], to[IPV6_LEN];
if (this == NULL) if (this == NULL)
{ {
@@ -241,11 +231,11 @@ int traffic_selector_printf_hook(printf_hook_data_t *data,
return written; return written;
} }
memset(from, 0, sizeof(from)); len = TS_IP_LEN(this);
memset(to, 0xFF, sizeof(to)); memset(from, 0, len);
memset(to, 0xFF, len);
if (this->dynamic && if (this->dynamic &&
memeq(this->from, from, this->type == TS_IPV4_ADDR_RANGE ? 4 : 16) && memeq(this->from, from, len) && memeq(this->to, to, len))
memeq(this->to, to, this->type == TS_IPV4_ADDR_RANGE ? 4 : 16))
{ {
written += print_in_hook(data, "dynamic"); written += print_in_hook(data, "dynamic");
} }
@@ -253,21 +243,21 @@ int traffic_selector_printf_hook(printf_hook_data_t *data,
{ {
if (this->type == TS_IPV4_ADDR_RANGE) if (this->type == TS_IPV4_ADDR_RANGE)
{ {
inet_ntop(AF_INET, &this->from4, from_str, sizeof(from_str)); inet_ntop(AF_INET, &this->from, from_str, sizeof(from_str));
} }
else else
{ {
inet_ntop(AF_INET6, &this->from6, from_str, sizeof(from_str)); inet_ntop(AF_INET6, &this->from, from_str, sizeof(from_str));
} }
if (this->netbits == NON_SUBNET_ADDRESS_RANGE) if (this->netbits == NON_SUBNET_ADDRESS_RANGE)
{ {
if (this->type == TS_IPV4_ADDR_RANGE) if (this->type == TS_IPV4_ADDR_RANGE)
{ {
inet_ntop(AF_INET, &this->to4, to_str, sizeof(to_str)); inet_ntop(AF_INET, &this->to, to_str, sizeof(to_str));
} }
else else
{ {
inet_ntop(AF_INET6, &this->to6, to_str, sizeof(to_str)); inet_ntop(AF_INET6, &this->to, to_str, sizeof(to_str));
} }
written += print_in_hook(data, "%s..%s", from_str, to_str); written += print_in_hook(data, "%s..%s", from_str, to_str);
} }
@@ -377,17 +367,6 @@ METHOD(traffic_selector_t, get_subset, traffic_selector_t*,
{ {
return NULL; return NULL;
} }
switch (this->type)
{
case TS_IPV4_ADDR_RANGE:
size = sizeof(this->from4);
break;
case TS_IPV6_ADDR_RANGE:
size = sizeof(this->from6);
break;
default:
return NULL;
}
if (this->protocol != other->protocol && if (this->protocol != other->protocol &&
this->protocol != 0 && other->protocol != 0) this->protocol != 0 && other->protocol != 0)
@@ -414,6 +393,7 @@ METHOD(traffic_selector_t, get_subset, traffic_selector_t*,
return NULL; return NULL;
} }
} }
size = TS_IP_LEN(this);
/* get higher from-address */ /* get higher from-address */
if (memcmp(this->from, other->from, size) > 0) if (memcmp(this->from, other->from, size) > 0)
{ {
@@ -456,29 +436,13 @@ METHOD(traffic_selector_t, equals, bool,
METHOD(traffic_selector_t, get_from_address, chunk_t, METHOD(traffic_selector_t, get_from_address, chunk_t,
private_traffic_selector_t *this) private_traffic_selector_t *this)
{ {
switch (this->type) return chunk_create(this->from, TS_IP_LEN(this));
{
case TS_IPV4_ADDR_RANGE:
return chunk_create(this->from, sizeof(this->from4));
case TS_IPV6_ADDR_RANGE:
return chunk_create(this->from, sizeof(this->from6));
default:
return chunk_empty;
}
} }
METHOD(traffic_selector_t, get_to_address, chunk_t, METHOD(traffic_selector_t, get_to_address, chunk_t,
private_traffic_selector_t *this) private_traffic_selector_t *this)
{ {
switch (this->type) return chunk_create(this->to, TS_IP_LEN(this));
{
case TS_IPV4_ADDR_RANGE:
return chunk_create(this->to, sizeof(this->to4));
case TS_IPV6_ADDR_RANGE:
return chunk_create(this->to, sizeof(this->to6));
default:
return chunk_empty;
}
} }
METHOD(traffic_selector_t, get_from_port, uint16_t, METHOD(traffic_selector_t, get_from_port, uint16_t,
@@ -526,7 +490,7 @@ METHOD(traffic_selector_t, is_host, bool,
} }
else else
{ {
size_t length = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16; size_t length = TS_IP_LEN(this);
if (this->dynamic) if (this->dynamic)
{ {
@@ -555,8 +519,8 @@ METHOD(traffic_selector_t, set_address, void,
if (host->is_anyaddr(host)) if (host->is_anyaddr(host))
{ {
memset(this->from6, 0x00, sizeof(this->from6)); memset(this->from, 0x00, sizeof(this->from));
memset(this->to6, 0xFF, sizeof(this->to6)); memset(this->to, 0xFF, sizeof(this->to));
this->netbits = 0; this->netbits = 0;
} }
else else
@@ -624,11 +588,11 @@ METHOD(traffic_selector_t, to_subnet, bool,
{ {
case TS_IPV4_ADDR_RANGE: case TS_IPV4_ADDR_RANGE:
family = AF_INET; family = AF_INET;
net_chunk.len = sizeof(this->from4); net_chunk.len = IPV4_LEN;
break; break;
case TS_IPV6_ADDR_RANGE: case TS_IPV6_ADDR_RANGE:
family = AF_INET6; family = AF_INET6;
net_chunk.len = sizeof(this->from6); net_chunk.len = IPV6_LEN;
break; break;
default: default:
/* unreachable */ /* unreachable */
@@ -659,26 +623,16 @@ METHOD(traffic_selector_t, clone_, traffic_selector_t*,
private_traffic_selector_t *this) private_traffic_selector_t *this)
{ {
private_traffic_selector_t *clone; private_traffic_selector_t *clone;
size_t len = TS_IP_LEN(this);
clone = traffic_selector_create(this->protocol, this->type, clone = traffic_selector_create(this->protocol, this->type,
this->from_port, this->to_port); this->from_port, this->to_port);
clone->netbits = this->netbits; clone->netbits = this->netbits;
clone->dynamic = this->dynamic; clone->dynamic = this->dynamic;
switch (clone->type) memcpy(clone->from, this->from, len);
{ memcpy(clone->to, this->to, len);
case TS_IPV4_ADDR_RANGE: return &clone->public;
memcpy(clone->from4, this->from4, sizeof(this->from4));
memcpy(clone->to4, this->to4, sizeof(this->to4));
return &clone->public;
case TS_IPV6_ADDR_RANGE:
memcpy(clone->from6, this->from6, sizeof(this->from6));
memcpy(clone->to6, this->to6, sizeof(this->to6));
return &clone->public;
default:
/* unreachable */
return &clone->public;
}
} }
METHOD(traffic_selector_t, hash, u_int, METHOD(traffic_selector_t, hash, u_int,
@@ -713,6 +667,7 @@ int traffic_selector_cmp(traffic_selector_t *a_pub, traffic_selector_t *b_pub,
void *opts) void *opts)
{ {
private_traffic_selector_t *a, *b; private_traffic_selector_t *a, *b;
size_t len;
int res; int res;
a = (private_traffic_selector_t*)a_pub; a = (private_traffic_selector_t*)a_pub;
@@ -724,36 +679,18 @@ int traffic_selector_cmp(traffic_selector_t *a_pub, traffic_selector_t *b_pub,
{ {
return res; return res;
} }
switch (a->type) len = TS_IP_LEN(a);
/* lower starting subnets first */
res = memcmp(a->from, b->from, len);
if (res)
{ {
case TS_IPV4_ADDR_RANGE: return res;
/* lower starting subnets first */ }
res = memcmp(a->from4, b->from4, sizeof(a->from4)); /* larger subnets first */
if (res) res = memcmp(b->to, a->to, len);
{ if (res)
return res; {
} return res;
/* larger subnets first */
res = memcmp(b->to4, a->to4, sizeof(a->to4));
if (res)
{
return res;
}
break;
case TS_IPV6_ADDR_RANGE:
res = memcmp(a->from6, b->from6, sizeof(a->from6));
if (res)
{
return res;
}
res = memcmp(b->to6, a->to6, sizeof(a->to6));
if (res)
{
return res;
}
break;
default:
return 1;
} }
/* lower protocols first */ /* lower protocols first */
res = compare_int(a->protocol, b->protocol); res = compare_int(a->protocol, b->protocol);
@@ -782,32 +719,19 @@ traffic_selector_t *traffic_selector_create_from_bytes(uint8_t protocol,
private_traffic_selector_t *this = traffic_selector_create(protocol, type, private_traffic_selector_t *this = traffic_selector_create(protocol, type,
from_port, to_port); from_port, to_port);
switch (type) if (!this)
{ {
case TS_IPV4_ADDR_RANGE: return NULL;
if (from.len != 4 || to.len != 4)
{
free(this);
return NULL;
}
memcpy(this->from4, from.ptr, from.len);
memcpy(this->to4, to.ptr, to.len);
break;
case TS_IPV6_ADDR_RANGE:
if (from.len != 16 || to.len != 16)
{
free(this);
return NULL;
}
memcpy(this->from6, from.ptr, from.len);
memcpy(this->to6, to.ptr, to.len);
break;
default:
free(this);
return NULL;
} }
if (from.len != to.len || from.len != TS_IP_LEN(this))
{
free(this);
return NULL;
}
memcpy(this->from, from.ptr, from.len);
memcpy(this->to, to.ptr, to.len);
calc_netbits(this); calc_netbits(this);
return (&this->public); return &this->public;
} }
/* /*
@@ -816,21 +740,15 @@ traffic_selector_t *traffic_selector_create_from_bytes(uint8_t protocol,
traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type, traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type,
chunk_t from, chunk_t to) chunk_t from, chunk_t to)
{ {
size_t len;
private_traffic_selector_t *this = traffic_selector_create(0, type, 0, 65535); private_traffic_selector_t *this = traffic_selector_create(0, type, 0, 65535);
size_t len;
switch (type) if (!this)
{ {
case TS_IPV4_ADDR_RANGE: return NULL;
len = 4;
break;
case TS_IPV6_ADDR_RANGE:
len = 16;
break;
default:
free(this);
return NULL;
} }
len = TS_IP_LEN(this);
memset(this->from, 0x00, len); memset(this->from, 0x00, len);
memset(this->to , 0xff, len); memset(this->to , 0xff, len);
@@ -846,7 +764,7 @@ traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type,
this->to[to.len-2] |= mask; this->to[to.len-2] |= mask;
} }
calc_netbits(this); calc_netbits(this);
return (&this->public); return &this->public;
} }
/* /*
@@ -857,29 +775,29 @@ traffic_selector_t *traffic_selector_create_from_subnet(host_t *net,
uint16_t from_port, uint16_t to_port) uint16_t from_port, uint16_t to_port)
{ {
private_traffic_selector_t *this; private_traffic_selector_t *this;
ts_type_t type;
chunk_t from; chunk_t from;
this = traffic_selector_create(protocol, 0, from_port, to_port);
switch (net->get_family(net)) switch (net->get_family(net))
{ {
case AF_INET: case AF_INET:
this->type = TS_IPV4_ADDR_RANGE; type = TS_IPV4_ADDR_RANGE;
break; break;
case AF_INET6: case AF_INET6:
this->type = TS_IPV6_ADDR_RANGE; type = TS_IPV6_ADDR_RANGE;
break; break;
default: default:
net->destroy(net); net->destroy(net);
free(this);
return NULL; return NULL;
} }
this = traffic_selector_create(protocol, type, from_port, to_port);
from = net->get_address(net); from = net->get_address(net);
memcpy(this->from, from.ptr, from.len); memcpy(this->from, from.ptr, from.len);
netbits = min(netbits, this->type == TS_IPV4_ADDR_RANGE ? 32 : 128); netbits = min(netbits, TS_IP_LEN(this) * 8);
calc_range(this, netbits); calc_range(this, netbits);
net->destroy(net); net->destroy(net);
return &this->public; return &this->public;
} }
@@ -914,7 +832,6 @@ traffic_selector_t *traffic_selector_create_from_string(
free(this); free(this);
return NULL; return NULL;
} }
calc_netbits(this); calc_netbits(this);
return &this->public; return &this->public;
} }
@@ -947,8 +864,8 @@ traffic_selector_t *traffic_selector_create_dynamic(uint8_t protocol,
private_traffic_selector_t *this = traffic_selector_create( private_traffic_selector_t *this = traffic_selector_create(
protocol, TS_IPV4_ADDR_RANGE, from_port, to_port); protocol, TS_IPV4_ADDR_RANGE, from_port, to_port);
memset(this->from6, 0, sizeof(this->from6)); memset(this->from, 0, sizeof(this->from));
memset(this->to6, 0xFF, sizeof(this->to6)); memset(this->to, 0xFF, sizeof(this->to));
this->netbits = 0; this->netbits = 0;
this->dynamic = TRUE; this->dynamic = TRUE;
@@ -963,6 +880,12 @@ static private_traffic_selector_t *traffic_selector_create(uint8_t protocol,
{ {
private_traffic_selector_t *this; private_traffic_selector_t *this;
/* sanity check */
if (type != TS_IPV4_ADDR_RANGE && type != TS_IPV6_ADDR_RANGE)
{
return NULL;
}
INIT(this, INIT(this,
.public = { .public = {
.get_subset = _get_subset, .get_subset = _get_subset,
@@ -25,6 +25,11 @@ static void verify(const char *str, const char *alt, traffic_selector_t *ts)
{ {
char buf[512]; char buf[512];
if (!str)
{
ck_assert_msg(!ts, "traffic selector not null: %R", ts);
return;
}
snprintf(buf, sizeof(buf), "%R", ts); snprintf(buf, sizeof(buf), "%R", ts);
DESTROY_IF(ts); DESTROY_IF(ts);
if (!streq(buf, str) && (!alt || !streq(buf, alt))) if (!streq(buf, str) && (!alt || !streq(buf, alt)))
@@ -48,12 +53,14 @@ START_TEST(test_create_from_string)
verify("fec1::1..fec1::ffff:ffff:ffff:ffff", NULL, verify("fec1::1..fec1::ffff:ffff:ffff:ffff", NULL,
traffic_selector_create_from_string(0, TS_IPV6_ADDR_RANGE, traffic_selector_create_from_string(0, TS_IPV6_ADDR_RANGE,
"fec1::1", 0, "fec1::ffff:ffff:ffff:ffff", 65535)); "fec1::1", 0, "fec1::ffff:ffff:ffff:ffff", 65535));
verify(NULL, NULL,
ck_assert(!traffic_selector_create_from_string(IPPROTO_TCP, 0, traffic_selector_create_from_string(IPPROTO_TCP, 0,
"10.1.0.0", 80, "10.1.255.255", 80)); "10.1.0.0", 80, "10.1.255.255", 80));
ck_assert(!traffic_selector_create_from_string(IPPROTO_TCP, TS_IPV4_ADDR_RANGE, verify(NULL, NULL,
traffic_selector_create_from_string(IPPROTO_TCP, TS_IPV4_ADDR_RANGE,
"a.b.c.d", 80, "10.1.255.255", 80)); "a.b.c.d", 80, "10.1.255.255", 80));
ck_assert(!traffic_selector_create_from_string(IPPROTO_TCP, TS_IPV4_ADDR_RANGE, verify(NULL, NULL,
traffic_selector_create_from_string(IPPROTO_TCP, TS_IPV4_ADDR_RANGE,
"10.1.0.0", 80, "a.b.c.d", 80)); "10.1.0.0", 80, "a.b.c.d", 80));
} }
END_TEST END_TEST
@@ -62,13 +69,17 @@ START_TEST(test_create_from_cidr)
{ {
verify("10.1.0.0/16", NULL, verify("10.1.0.0/16", NULL,
traffic_selector_create_from_cidr("10.1.0.0/16", 0, 0, 65535)); traffic_selector_create_from_cidr("10.1.0.0/16", 0, 0, 65535));
verify("10.1.0.1/32[udp]", "10.1.0.1/32[17]",
traffic_selector_create_from_cidr("10.1.0.1/32", IPPROTO_UDP,
0, 65535));
verify("10.1.0.1/32[udp/1234-1235]", "10.1.0.1/32[17/1234-1235]", verify("10.1.0.1/32[udp/1234-1235]", "10.1.0.1/32[17/1234-1235]",
traffic_selector_create_from_cidr("10.1.0.1/32", IPPROTO_UDP, traffic_selector_create_from_cidr("10.1.0.1/32", IPPROTO_UDP,
1234, 1235)); 1234, 1235));
verify("10.1.0.0/16[OPAQUE]", NULL, verify("10.1.0.0/16[OPAQUE]", NULL,
traffic_selector_create_from_cidr("10.1.0.0/16", 0, 65535, 0)); traffic_selector_create_from_cidr("10.1.0.0/16", 0, 65535, 0));
ck_assert(!traffic_selector_create_from_cidr("a.b.c.d/16", 0, 0, 65535)); verify(NULL, NULL,
traffic_selector_create_from_cidr("a.b.c.d/16", 0, 0, 65535));
} }
END_TEST END_TEST
@@ -78,14 +89,20 @@ START_TEST(test_create_from_bytes)
traffic_selector_create_from_bytes(0, TS_IPV4_ADDR_RANGE, traffic_selector_create_from_bytes(0, TS_IPV4_ADDR_RANGE,
chunk_from_chars(0x0a,0x01,0x00,0x00), 0, chunk_from_chars(0x0a,0x01,0x00,0x00), 0,
chunk_from_chars(0x0a,0x01,0xff,0xff), 65535)); chunk_from_chars(0x0a,0x01,0xff,0xff), 65535));
verify(NULL, NULL,
ck_assert(!traffic_selector_create_from_bytes(0, TS_IPV4_ADDR_RANGE, traffic_selector_create_from_bytes(0, TS_IPV4_ADDR_RANGE,
chunk_from_chars(0x0a,0x01,0x00,0x00), 0,
chunk_from_chars(0x0a,0x01,0xff,0xff,0xff), 65535));
verify(NULL, NULL,
traffic_selector_create_from_bytes(0, TS_IPV4_ADDR_RANGE,
chunk_empty, 0, chunk_empty, 0,
chunk_empty, 65535)); chunk_empty, 65535));
ck_assert(!traffic_selector_create_from_bytes(0, TS_IPV6_ADDR_RANGE, verify(NULL, NULL,
traffic_selector_create_from_bytes(0, TS_IPV6_ADDR_RANGE,
chunk_from_chars(0x0a,0x01,0x00,0x00), 0, chunk_from_chars(0x0a,0x01,0x00,0x00), 0,
chunk_from_chars(0x0a,0x01,0xff,0xff), 65535)); chunk_from_chars(0x0a,0x01,0xff,0xff), 65535));
ck_assert(!traffic_selector_create_from_bytes(0, 0, verify(NULL, NULL,
traffic_selector_create_from_bytes(0, 0,
chunk_from_chars(0x0a,0x01,0x00,0x00), 0, chunk_from_chars(0x0a,0x01,0x00,0x00), 0,
chunk_from_chars(0x0a,0x01,0xff,0xff), 65535)); chunk_from_chars(0x0a,0x01,0xff,0xff), 65535));
} }
@@ -117,6 +134,7 @@ struct {
{ "128.0.0.0/4", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x04,0x80), }, { "128.0.0.0/4", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x04,0x80), },
{ "172.16.0.0/12", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x04,0xac,0x10), }, { "172.16.0.0/12", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x04,0xac,0x10), },
{ "0.0.0.0/0", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x00), }, { "0.0.0.0/0", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x00), },
{ NULL, 0, chunk_from_chars(0x00), },
/* FIXME: not a correct encoding, so we might want to fail here */ /* FIXME: not a correct encoding, so we might want to fail here */
{ "0.0.0.0/0", TS_IPV4_ADDR_RANGE, {NULL, 0}, }, { "0.0.0.0/0", TS_IPV4_ADDR_RANGE, {NULL, 0}, },
{ "2001:0:2::/48", TS_IPV6_ADDR_RANGE, chunk_from_chars(0x00,0x20,0x01,0x00,0x00,0x00,0x02),}, { "2001:0:2::/48", TS_IPV6_ADDR_RANGE, chunk_from_chars(0x00,0x20,0x01,0x00,0x00,0x00,0x02),},
@@ -411,6 +429,7 @@ struct {
{ "0.0.0.0/0", "fec2::1", FALSE }, { "0.0.0.0/0", "fec2::1", FALSE },
{ "::/0", "1.2.3.4", FALSE }, { "::/0", "1.2.3.4", FALSE },
{ "10.0.0.0/16", "10.1.0.0", FALSE }, { "10.0.0.0/16", "10.1.0.0", FALSE },
{ "10.1.0.0/16", "10.0.255.255", FALSE },
{ "fec2::/64", "fec2:0:0:1::afaf", FALSE }, { "fec2::/64", "fec2:0:0:1::afaf", FALSE },
}; };
@@ -469,6 +488,7 @@ struct {
} is_host_tests[] = { } is_host_tests[] = {
{ "0.0.0.0/0", "192.168.1.2", FALSE, FALSE }, { "0.0.0.0/0", "192.168.1.2", FALSE, FALSE },
{ "::/0", "fec2::1", FALSE, FALSE }, { "::/0", "fec2::1", FALSE, FALSE },
{ "192.168.1.0/24", "192.168.1.0", FALSE, FALSE },
{ "192.168.1.2/32", "192.168.1.2", TRUE, TRUE }, { "192.168.1.2/32", "192.168.1.2", TRUE, TRUE },
{ "192.168.1.2/32", "192.168.1.1", FALSE, TRUE }, { "192.168.1.2/32", "192.168.1.1", FALSE, TRUE },
{ "192.168.1.2/32", "fec2::1", FALSE, TRUE }, { "192.168.1.2/32", "fec2::1", FALSE, TRUE },