aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2017-10-11 18:56:08 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2017-10-12 14:27:09 +0200
commit3a8fb39d6d91d5e7e7ac5ef649ba74977fcede3e (patch)
tree78a7cbfff2c60139398062f57c2ffcb97f6a268f
parent958256f5cfd19610ecec8b1130f726b7a6bb17fc (diff)
apnt_start(): Pass ippool flags to avoid certain IPs
Commit dda21ed7d4a897c9284c69175d0da598598eae40 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. Change-Id: I72ae59ad5929ca0dc9ee69937c50e57a5f49ca76
-rw-r--r--ggsn/ggsn.c12
-rw-r--r--lib/ippool.c34
-rw-r--r--lib/ippool.h5
3 files changed, 34 insertions, 17 deletions
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index 6c5c1a8..4f90599 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -149,6 +149,10 @@ int apn_stop(struct apn_ctx *apn, bool force)
/* actually start the APN with its current config */
int apn_start(struct apn_ctx *apn)
{
+ int ipv4_blacklist_size = 0;
+ int ipv6_blacklist_size = 0;
+ int ippool_flags = IPPOOL_NONETWORK | IPPOOL_NOBROADCAST;
+
if (apn->started)
return 0;
@@ -179,6 +183,7 @@ int apn_start(struct apn_ctx *apn)
apn_stop(apn, false);
return -1;
}
+ ipv4_blacklist_size++;
}
if (apn->v6.cfg.ifconfig_prefix.addr.len) {
@@ -192,6 +197,7 @@ int apn_start(struct apn_ctx *apn)
apn_stop(apn, false);
return -1;
}
+ ipv6_blacklist_size++;
}
if (apn->tun.cfg.ipup_script) {
@@ -230,7 +236,8 @@ int apn_start(struct apn_ctx *apn)
LOGPAPN(LOGL_INFO, apn, "Creating IPv4 pool %s\n",
in46p_ntoa(&apn->v4.cfg.dynamic_prefix));
if (ippool_new(&apn->v4.pool, &apn->v4.cfg.dynamic_prefix,
- &apn->v4.cfg.static_prefix, 0)) {
+ &apn->v4.cfg.static_prefix, ippool_flags,
+ &apn->v4.cfg.ifconfig_prefix, ipv4_blacklist_size)) {
LOGPAPN(LOGL_ERROR, apn, "Failed to create IPv4 pool\n");
apn_stop(apn, false);
return -1;
@@ -242,7 +249,8 @@ int apn_start(struct apn_ctx *apn)
LOGPAPN(LOGL_INFO, apn, "Creating IPv6 pool %s\n",
in46p_ntoa(&apn->v6.cfg.dynamic_prefix));
if (ippool_new(&apn->v6.pool, &apn->v6.cfg.dynamic_prefix,
- &apn->v6.cfg.static_prefix, 0)) {
+ &apn->v6.cfg.static_prefix, ippool_flags,
+ &apn->v6.cfg.ifconfig_prefix, ipv6_blacklist_size)) {
LOGPAPN(LOGL_ERROR, apn, "Failed to create IPv6 pool\n");
apn_stop(apn, false);
return -1;
diff --git a/lib/ippool.c b/lib/ippool.c
index a236fe7..2a41e58 100644
--- a/lib/ippool.c
+++ b/lib/ippool.c
@@ -184,9 +184,18 @@ 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)
+{
+ for (int 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 +219,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)) -1;
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 (int i = 0; i < blacklist_size; i++) {
+ if (in46a_within_mask(&blacklist[i].addr, &addr, addrprefixlen))
+ dynsize--;
+ }
}
if (!stat || stat->addr.len == 0) {
@@ -278,13 +285,16 @@ 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);
+ continue;
+ }
(*this)->member[i].addr = addr;
in46a_inc(&addr);
diff --git a/lib/ippool.h b/lib/ippool.h
index fbac66d..704b887 100644
--- a/lib/ippool.h
+++ b/lib/ippool.h
@@ -31,7 +31,6 @@
#define IPPOOL_NONETWORK 0x01
#define IPPOOL_NOBROADCAST 0x02
-#define IPPOOL_NOGATEWAY 0x04
#define IPPOOL_STATSIZE 0x10000
@@ -71,8 +70,8 @@ struct ippoolm_t {
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);
+extern int ippool_new(struct ippool_t **this, const struct in46_prefix *dyn, 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);