ippool: Implement and use blacklist instead of blindly using IPPOOL_NOGATEWAY

Commit dda21ed7d4 modified previous calls
to ippool_new() removing the pass of flags to avoid allocating certain
problematic IPs from the pool to MS, such as the network, gateway and
broadcast IPs.

Today I did some unsucessful tests with osmo-ggsn with a pool "ip prefix
dynamic 176.16.222.0/24", and thus IP 176.16.222.0 was being assigned to
the MS. De-capsulated DNS packets were received in the tun interface,
but the Linux system in there was unable to correctly forward the
packets to the gateway interface connected to the Internet. However,
adding a second MS which got 176.16.222.1 had its packets forwarded
correctly.

However, previous implementation relies on flag IPPOOL_NOGATEWAY flag to
blindly blacklist first IP after the network ip (ie, .0 and .1 are
removed), which limits the IP reserved for the tun device to be .1. If a
different IP in the range is assigned, it may cause issues. As a result,
a blacklist is introduced in this commit to dynamically fetch the tun IP
address and exlucde it from the pool of available IPs.

Change-Id: I8e91f7280d60490c858a769dd578c1c8e54e9243
changes/56/4256/6
Pau Espin 2017-10-16 14:52:25 +02:00
parent a037e5908a
commit 859f9b0752
6 changed files with 365 additions and 32 deletions

View File

@ -146,10 +146,50 @@ int apn_stop(struct apn_ctx *apn, bool force)
return 0;
}
static int alloc_ippool_blacklist(struct apn_ctx *apn, const struct tun_t *tun, struct in46_prefix **blacklist, bool ipv6)
{
int flags, len, len2, i;
if (ipv6)
flags = IP_TYPE_IPv6_NONLINK;
else
flags = IP_TYPE_IPv4;
while (1) {
len = tun_ip_local_get(apn->tun.tun, NULL, 0, flags);
if (len < 1)
return len;
*blacklist = talloc_zero_size(apn, len * sizeof(struct in46_prefix));
len2 = tun_ip_local_get(apn->tun.tun, *blacklist, len, flags);
if (len2 < 1) {
talloc_free(*blacklist);
return len2;
}
if (len2 > len) /* iface was added between 2 calls, repeat operation */
talloc_free(*blacklist);
else
break;
}
for (i = 0; i < len2; i++)
LOGPAPN(LOGL_INFO, apn, "Blacklist tun IP %s\n",
in46p_ntoa(&(*blacklist)[i]));
return len2;
}
/* actually start the APN with its current config */
int apn_start(struct apn_ctx *apn)
{
int ippool_flags = IPPOOL_NONETWORK | IPPOOL_NOBROADCAST;
struct in46_prefix ipv6_tun_linklocal_ip;
struct in46_prefix *blacklist;
int blacklist_size;
if (apn->started)
return 0;
@ -231,24 +271,34 @@ int apn_start(struct apn_ctx *apn)
if (apn->v4.cfg.dynamic_prefix.addr.len) {
LOGPAPN(LOGL_INFO, apn, "Creating IPv4 pool %s\n",
in46p_ntoa(&apn->v4.cfg.dynamic_prefix));
if ((blacklist_size = alloc_ippool_blacklist(apn, apn->tun.tun, &blacklist, false)) < 0)
LOGPAPN(LOGL_ERROR, apn, "Failed obtaining IPv4 tun IPs\n");
if (ippool_new(&apn->v4.pool, &apn->v4.cfg.dynamic_prefix,
&apn->v4.cfg.static_prefix, 0)) {
&apn->v4.cfg.static_prefix, ippool_flags,
blacklist, blacklist_size)) {
LOGPAPN(LOGL_ERROR, apn, "Failed to create IPv4 pool\n");
talloc_free(blacklist);
apn_stop(apn, false);
return -1;
}
talloc_free(blacklist);
}
/* Create IPv6 pool */
if (apn->v6.cfg.dynamic_prefix.addr.len) {
LOGPAPN(LOGL_INFO, apn, "Creating IPv6 pool %s\n",
in46p_ntoa(&apn->v6.cfg.dynamic_prefix));
if ((blacklist_size = alloc_ippool_blacklist(apn, apn->tun.tun, &blacklist, true)) < 0)
LOGPAPN(LOGL_ERROR, apn, "Failed obtaining IPv6 tun IPs\n");
if (ippool_new(&apn->v6.pool, &apn->v6.cfg.dynamic_prefix,
&apn->v6.cfg.static_prefix, 0)) {
&apn->v6.cfg.static_prefix, ippool_flags,
blacklist, blacklist_size)) {
LOGPAPN(LOGL_ERROR, apn, "Failed to create IPv6 pool\n");
talloc_free(blacklist);
apn_stop(apn, false);
return -1;
}
talloc_free(blacklist);
}
LOGPAPN(LOGL_NOTICE, apn, "Successfully started\n");

View File

@ -184,9 +184,19 @@ void in46a_inc(struct in46_addr *addr)
}
}
static bool addr_in_prefix_list(struct in46_addr *addr, struct in46_prefix *list, size_t list_size)
{
int i;
for (i = 0; i < list_size; i++) {
if (in46a_prefix_equal(addr, &list[i].addr))
return true;
}
return false;
}
/* Create new address pool */
int ippool_new(struct ippool_t **this, const struct in46_prefix *dyn, const struct in46_prefix *stat,
int flags)
int flags, struct in46_prefix *blacklist, size_t blacklist_size)
{
/* Parse only first instance of pool for now */
@ -210,18 +220,16 @@ int ippool_new(struct ippool_t **this, const struct in46_prefix *dyn, const stru
if (addr.len == sizeof(struct in6_addr))
addr.len = 64/8;
/* Set IPPOOL_NONETWORK if IPPOOL_NOGATEWAY is set */
if (flags & IPPOOL_NOGATEWAY) {
flags |= IPPOOL_NONETWORK;
}
dynsize = (1 << (addr.len*8 - addrprefixlen));
if (flags & IPPOOL_NONETWORK) /* Exclude network address from pool */
dynsize--;
if (flags & IPPOOL_NOGATEWAY) /* Exclude gateway address from pool */
dynsize--;
if (flags & IPPOOL_NOBROADCAST) /* Exclude broadcast address from pool */
dynsize--;
/* Exclude included blacklist addresses from pool */
for (i = 0; i < blacklist_size; i++) {
if (in46a_within_mask(&blacklist[i].addr, &addr, addrprefixlen))
dynsize--;
}
}
if (!stat || stat->addr.len == 0) {
@ -278,13 +286,17 @@ int ippool_new(struct ippool_t **this, const struct in46_prefix *dyn, const stru
(*this)->firstdyn = NULL;
(*this)->lastdyn = NULL;
if (flags & IPPOOL_NOGATEWAY) {
in46a_inc(&addr);
in46a_inc(&addr);
} else if (flags & IPPOOL_NONETWORK) {
if (flags & IPPOOL_NONETWORK) {
in46a_inc(&addr);
}
for (i = 0; i < dynsize; i++) {
if (addr_in_prefix_list(&addr, blacklist, blacklist_size)) {
SYS_ERR(DIP, LOGL_DEBUG, 0,
"addr blacklisted from pool: %s", in46a_ntoa(&addr));
in46a_inc(&addr);
i--;
continue;
}
(*this)->member[i].addr = addr;
in46a_inc(&addr);

View File

@ -31,7 +31,6 @@
#define IPPOOL_NONETWORK 0x01
#define IPPOOL_NOBROADCAST 0x02
#define IPPOOL_NOGATEWAY 0x04
#define IPPOOL_STATSIZE 0x10000
@ -72,7 +71,8 @@ extern unsigned long int ippool_hash(struct in46_addr *addr);
/* Create new address pool */
extern int ippool_new(struct ippool_t **this, const struct in46_prefix *dyn,
const struct in46_prefix *stat, int flags);
const struct in46_prefix *stat, int flags,
struct in46_prefix *blacklist, size_t blacklist_size);
/* Delete existing address pool */
extern int ippool_free(struct ippool_t *this);

View File

@ -13,36 +13,47 @@
#include "../../lib/syserr.h"
static struct ippool_t *create_pool(const char *prefix_str, unsigned int flags)
static struct ippool_t *create_pool(const char *prefix_str, unsigned int flags, char **blacklist, size_t blacklist_size)
{
struct in46_prefix *blacklist_pfx;
struct ippool_t *pool;
struct in46_prefix pfx;
size_t t;
int rc;
int i;
blacklist_pfx = calloc(blacklist_size, sizeof(struct in46_prefix));
for (i = 0; i < blacklist_size; i++) {
rc = ippool_aton(&blacklist_pfx[i].addr, &t, blacklist[i], 0);
OSMO_ASSERT(rc == 0);
pfx.prefixlen = t;
}
/* dynamic-only v4 */
rc = ippool_aton(&pfx.addr, &t, prefix_str, flags);
rc = ippool_aton(&pfx.addr, &t, prefix_str, 0);
OSMO_ASSERT(rc == 0);
pfx.prefixlen = t;
rc = ippool_new(&pool, &pfx, NULL, flags);
rc = ippool_new(&pool, &pfx, NULL, flags, blacklist_pfx, blacklist_size);
OSMO_ASSERT(rc == 0);
//ippool_printaddr(pool);
free(blacklist_pfx);
return pool;
}
static void test_pool_size(const char *pfx, unsigned int flags, unsigned int expected_size)
static void test_pool_size(const char *pfx, unsigned int flags, char **blacklist, size_t blacklist_size, unsigned int expected_size)
{
struct ippool_t *pool;
struct ippoolm_t *member;
struct in46_addr addr;
int i, rc, n;
printf("testing pool for prefix %s, flags=0x%x, expected_size=%u\n", pfx, flags, expected_size);
pool = create_pool(pfx, flags);
printf("testing pool for prefix %s, flags=0x%x, blacklist_size=%lu, expected_size=%u\n", pfx, flags, blacklist_size, expected_size);
pool = create_pool(pfx, flags, blacklist, blacklist_size);
OSMO_ASSERT(pool->listsize == expected_size);
memset(&addr, 0, sizeof(addr));
@ -91,19 +102,23 @@ static void test_pool_size(const char *pfx, unsigned int flags, unsigned int exp
static void test_pool_sizes(void)
{
/* 256 addresses [0..255] */
test_pool_size("192.168.23.0/24", 0, 256);
test_pool_size("192.168.23.0/24", 0, NULL, 0, 256);
/* 255 addresses [1..255] */
test_pool_size("192.168.23.0/24", IPPOOL_NONETWORK, 255);
test_pool_size("192.168.23.0/24", IPPOOL_NONETWORK, NULL, 0, 255);
/* 254 addresses [1..254] */
test_pool_size("192.168.23.0/24", IPPOOL_NONETWORK | IPPOOL_NOBROADCAST, 254);
test_pool_size("192.168.23.0/24", IPPOOL_NONETWORK | IPPOOL_NOBROADCAST, NULL, 0, 254);
/* 65534 addresses [0.1..255.254] */
test_pool_size("192.168.0.0/16", IPPOOL_NONETWORK | IPPOOL_NOBROADCAST, 65534);
test_pool_size("192.168.0.0/16", IPPOOL_NONETWORK | IPPOOL_NOBROADCAST, NULL, 0, 65534);
/* 256 prefixes of /64 each */
test_pool_size("2001:DB8::/56", 0, 256);
test_pool_size("2001:DB8::/56", 0, NULL, 0, 256);
/* 253 addresses [1..254] & exclude 192.168.23.1/24 */
char *blacklist[] = {"176.16.222.10/24", "192.168.23.1/24", "192.168.38.2/24"};
test_pool_size("192.168.23.0/24", IPPOOL_NONETWORK | IPPOOL_NOBROADCAST, blacklist, 3, 253);
}
int main(int argc, char **argv)

View File

@ -8,3 +8,5 @@ No more IP addresses available
No more IP addresses available
No more IP addresses available
No more IP addresses available
No more IP addresses available
No more IP addresses available

View File

@ -1,4 +1,4 @@
testing pool for prefix 192.168.23.0/24, flags=0x0, expected_size=256
testing pool for prefix 192.168.23.0/24, flags=0x0, blacklist_size=0, expected_size=256
allocated address 192.168.23.0
allocated address 192.168.23.1
allocated address 192.168.23.2
@ -255,7 +255,7 @@ allocated address 192.168.23.252
allocated address 192.168.23.253
allocated address 192.168.23.254
allocated address 192.168.23.255
testing pool for prefix 192.168.23.0/24, flags=0x1, expected_size=255
testing pool for prefix 192.168.23.0/24, flags=0x1, blacklist_size=0, expected_size=255
allocated address 192.168.23.1
allocated address 192.168.23.2
allocated address 192.168.23.3
@ -511,7 +511,7 @@ allocated address 192.168.23.252
allocated address 192.168.23.253
allocated address 192.168.23.254
allocated address 192.168.23.255
testing pool for prefix 192.168.23.0/24, flags=0x3, expected_size=254
testing pool for prefix 192.168.23.0/24, flags=0x3, blacklist_size=0, expected_size=254
allocated address 192.168.23.1
allocated address 192.168.23.2
allocated address 192.168.23.3
@ -766,7 +766,7 @@ allocated address 192.168.23.251
allocated address 192.168.23.252
allocated address 192.168.23.253
allocated address 192.168.23.254
testing pool for prefix 192.168.0.0/16, flags=0x3, expected_size=65534
testing pool for prefix 192.168.0.0/16, flags=0x3, blacklist_size=0, expected_size=65534
allocated address 192.168.0.1
allocated address 192.168.0.2
allocated address 192.168.0.3
@ -66301,7 +66301,7 @@ allocated address 192.168.255.251
allocated address 192.168.255.252
allocated address 192.168.255.253
allocated address 192.168.255.254
testing pool for prefix 2001:DB8::/56, flags=0x0, expected_size=256
testing pool for prefix 2001:DB8::/56, flags=0x0, blacklist_size=0, expected_size=256
allocated address 2001:db8::
allocated address 2001:db8:0:1::
allocated address 2001:db8:0:2::
@ -66558,3 +66558,257 @@ allocated address 2001:db8:0:fc::
allocated address 2001:db8:0:fd::
allocated address 2001:db8:0:fe::
allocated address 2001:db8:0:ff::
testing pool for prefix 192.168.23.0/24, flags=0x3, blacklist_size=3, expected_size=253
allocated address 192.168.23.2
allocated address 192.168.23.3
allocated address 192.168.23.4
allocated address 192.168.23.5
allocated address 192.168.23.6
allocated address 192.168.23.7
allocated address 192.168.23.8
allocated address 192.168.23.9
allocated address 192.168.23.10
allocated address 192.168.23.11
allocated address 192.168.23.12
allocated address 192.168.23.13
allocated address 192.168.23.14
allocated address 192.168.23.15
allocated address 192.168.23.16
allocated address 192.168.23.17
allocated address 192.168.23.18
allocated address 192.168.23.19
allocated address 192.168.23.20
allocated address 192.168.23.21
allocated address 192.168.23.22
allocated address 192.168.23.23
allocated address 192.168.23.24
allocated address 192.168.23.25
allocated address 192.168.23.26
allocated address 192.168.23.27
allocated address 192.168.23.28
allocated address 192.168.23.29
allocated address 192.168.23.30
allocated address 192.168.23.31
allocated address 192.168.23.32
allocated address 192.168.23.33
allocated address 192.168.23.34
allocated address 192.168.23.35
allocated address 192.168.23.36
allocated address 192.168.23.37
allocated address 192.168.23.38
allocated address 192.168.23.39
allocated address 192.168.23.40
allocated address 192.168.23.41
allocated address 192.168.23.42
allocated address 192.168.23.43
allocated address 192.168.23.44
allocated address 192.168.23.45
allocated address 192.168.23.46
allocated address 192.168.23.47
allocated address 192.168.23.48
allocated address 192.168.23.49
allocated address 192.168.23.50
allocated address 192.168.23.51
allocated address 192.168.23.52
allocated address 192.168.23.53
allocated address 192.168.23.54
allocated address 192.168.23.55
allocated address 192.168.23.56
allocated address 192.168.23.57
allocated address 192.168.23.58
allocated address 192.168.23.59
allocated address 192.168.23.60
allocated address 192.168.23.61
allocated address 192.168.23.62
allocated address 192.168.23.63
allocated address 192.168.23.64
allocated address 192.168.23.65
allocated address 192.168.23.66
allocated address 192.168.23.67
allocated address 192.168.23.68
allocated address 192.168.23.69
allocated address 192.168.23.70
allocated address 192.168.23.71
allocated address 192.168.23.72
allocated address 192.168.23.73
allocated address 192.168.23.74
allocated address 192.168.23.75
allocated address 192.168.23.76
allocated address 192.168.23.77
allocated address 192.168.23.78
allocated address 192.168.23.79
allocated address 192.168.23.80
allocated address 192.168.23.81
allocated address 192.168.23.82
allocated address 192.168.23.83
allocated address 192.168.23.84
allocated address 192.168.23.85
allocated address 192.168.23.86
allocated address 192.168.23.87
allocated address 192.168.23.88
allocated address 192.168.23.89
allocated address 192.168.23.90
allocated address 192.168.23.91
allocated address 192.168.23.92
allocated address 192.168.23.93
allocated address 192.168.23.94
allocated address 192.168.23.95
allocated address 192.168.23.96
allocated address 192.168.23.97
allocated address 192.168.23.98
allocated address 192.168.23.99
allocated address 192.168.23.100
allocated address 192.168.23.101
allocated address 192.168.23.102
allocated address 192.168.23.103
allocated address 192.168.23.104
allocated address 192.168.23.105
allocated address 192.168.23.106
allocated address 192.168.23.107
allocated address 192.168.23.108
allocated address 192.168.23.109
allocated address 192.168.23.110
allocated address 192.168.23.111
allocated address 192.168.23.112
allocated address 192.168.23.113
allocated address 192.168.23.114
allocated address 192.168.23.115
allocated address 192.168.23.116
allocated address 192.168.23.117
allocated address 192.168.23.118
allocated address 192.168.23.119
allocated address 192.168.23.120
allocated address 192.168.23.121
allocated address 192.168.23.122
allocated address 192.168.23.123
allocated address 192.168.23.124
allocated address 192.168.23.125
allocated address 192.168.23.126
allocated address 192.168.23.127
allocated address 192.168.23.128
allocated address 192.168.23.129
allocated address 192.168.23.130
allocated address 192.168.23.131
allocated address 192.168.23.132
allocated address 192.168.23.133
allocated address 192.168.23.134
allocated address 192.168.23.135
allocated address 192.168.23.136
allocated address 192.168.23.137
allocated address 192.168.23.138
allocated address 192.168.23.139
allocated address 192.168.23.140
allocated address 192.168.23.141
allocated address 192.168.23.142
allocated address 192.168.23.143
allocated address 192.168.23.144
allocated address 192.168.23.145
allocated address 192.168.23.146
allocated address 192.168.23.147
allocated address 192.168.23.148
allocated address 192.168.23.149
allocated address 192.168.23.150
allocated address 192.168.23.151
allocated address 192.168.23.152
allocated address 192.168.23.153
allocated address 192.168.23.154
allocated address 192.168.23.155
allocated address 192.168.23.156
allocated address 192.168.23.157
allocated address 192.168.23.158
allocated address 192.168.23.159
allocated address 192.168.23.160
allocated address 192.168.23.161
allocated address 192.168.23.162
allocated address 192.168.23.163
allocated address 192.168.23.164
allocated address 192.168.23.165
allocated address 192.168.23.166
allocated address 192.168.23.167
allocated address 192.168.23.168
allocated address 192.168.23.169
allocated address 192.168.23.170
allocated address 192.168.23.171
allocated address 192.168.23.172
allocated address 192.168.23.173
allocated address 192.168.23.174
allocated address 192.168.23.175
allocated address 192.168.23.176
allocated address 192.168.23.177
allocated address 192.168.23.178
allocated address 192.168.23.179
allocated address 192.168.23.180
allocated address 192.168.23.181
allocated address 192.168.23.182
allocated address 192.168.23.183
allocated address 192.168.23.184
allocated address 192.168.23.185
allocated address 192.168.23.186
allocated address 192.168.23.187
allocated address 192.168.23.188
allocated address 192.168.23.189
allocated address 192.168.23.190
allocated address 192.168.23.191
allocated address 192.168.23.192
allocated address 192.168.23.193
allocated address 192.168.23.194
allocated address 192.168.23.195
allocated address 192.168.23.196
allocated address 192.168.23.197
allocated address 192.168.23.198
allocated address 192.168.23.199
allocated address 192.168.23.200
allocated address 192.168.23.201
allocated address 192.168.23.202
allocated address 192.168.23.203
allocated address 192.168.23.204
allocated address 192.168.23.205
allocated address 192.168.23.206
allocated address 192.168.23.207
allocated address 192.168.23.208
allocated address 192.168.23.209
allocated address 192.168.23.210
allocated address 192.168.23.211
allocated address 192.168.23.212
allocated address 192.168.23.213
allocated address 192.168.23.214
allocated address 192.168.23.215
allocated address 192.168.23.216
allocated address 192.168.23.217
allocated address 192.168.23.218
allocated address 192.168.23.219
allocated address 192.168.23.220
allocated address 192.168.23.221
allocated address 192.168.23.222
allocated address 192.168.23.223
allocated address 192.168.23.224
allocated address 192.168.23.225
allocated address 192.168.23.226
allocated address 192.168.23.227
allocated address 192.168.23.228
allocated address 192.168.23.229
allocated address 192.168.23.230
allocated address 192.168.23.231
allocated address 192.168.23.232
allocated address 192.168.23.233
allocated address 192.168.23.234
allocated address 192.168.23.235
allocated address 192.168.23.236
allocated address 192.168.23.237
allocated address 192.168.23.238
allocated address 192.168.23.239
allocated address 192.168.23.240
allocated address 192.168.23.241
allocated address 192.168.23.242
allocated address 192.168.23.243
allocated address 192.168.23.244
allocated address 192.168.23.245
allocated address 192.168.23.246
allocated address 192.168.23.247
allocated address 192.168.23.248
allocated address 192.168.23.249
allocated address 192.168.23.250
allocated address 192.168.23.251
allocated address 192.168.23.252
allocated address 192.168.23.253
allocated address 192.168.23.254