aboutsummaryrefslogtreecommitdiffstats
path: root/ggsn/ggsn.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2017-08-02 19:49:47 +0200
committerHarald Welte <laforge@gnumonks.org>2017-08-09 22:08:57 +0200
commitd12eab9c4e375e1669637dd34674c8b8208cf867 (patch)
tree2a105db1821f3b1db6a12b1ab8f3c1ef9d301648 /ggsn/ggsn.c
parentd9d8862a58702ba71b5194faa01ecf1eb234519c (diff)
ippool: Add IPv6 support to IP pool implementation
Extend the IP pool implementation to be able to manage both pools of 32bit addresses (IPv4) as well as pools of 128bit addresses (IPv6) Change-Id: Ib98cc4bf634d6be9a7bf8c03a24e629455fcafc8
Diffstat (limited to 'ggsn/ggsn.c')
-rw-r--r--ggsn/ggsn.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index 168e907..0d0e569 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -56,6 +56,7 @@
#include "../lib/tun.h"
#include "../lib/ippool.h"
#include "../lib/syserr.h"
+#include "../lib/in46_addr.h"
#include "../gtp/pdp.h"
#include "../gtp/gtp.h"
#include "cmdline.h"
@@ -65,7 +66,8 @@ int end = 0;
int maxfd = 0; /* For select() */
struct in_addr listen_;
-struct in_addr netaddr, destaddr, net, mask; /* Network interface */
+struct in_addr netaddr, destaddr, net; /* Network interface */
+size_t prefixlen;
struct in_addr dns1, dns2; /* PCO DNS address */
char *ipup, *ipdown; /* Filename of scripts */
int debug; /* Print debug output */
@@ -135,9 +137,12 @@ int daemon(int nochdir, int noclose)
static bool send_trap(const struct gsn_t *gsn, const struct pdp_t *pdp, const struct ippoolm_t *member, const char *var)
{
+ char addrbuf[256];
char val[NAMESIZE];
- snprintf(val, sizeof(val), "%" PRIu64 ",%s", pdp->imsi, inet_ntoa(member->addr));
+ const char *addrstr = in46a_ntop(&member->addr, addrbuf, sizeof(addrbuf));
+
+ snprintf(val, sizeof(val), "%" PRIu64 ",%s", pdp->imsi, addrstr);
if (ctrl_cmd_send_trap(gsn->ctrl, var, val) < 0) {
LOGP(DGGSN, LOGL_ERROR, "Failed to create and send TRAP for IMSI %" PRIu64 " [%s].\n", pdp->imsi, var);
@@ -168,7 +173,7 @@ int delete_context(struct pdp_t *pdp)
int create_context_ind(struct pdp_t *pdp)
{
- struct in_addr addr;
+ struct in46_addr addr;
struct ippoolm_t *member;
DEBUGP(DGGSN, "Received create PDP context request\n");
@@ -183,8 +188,8 @@ int create_context_ind(struct pdp_t *pdp)
memcpy(pdp->qos_neg.v, pdp->qos_req.v, pdp->qos_req.l); /* TODO */
pdp->qos_neg.l = pdp->qos_req.l;
- if (pdp_euaton(&pdp->eua, &addr)) {
- addr.s_addr = 0; /* Request dynamic */
+ if (pdp_euaton(&pdp->eua, &addr.v4)) {
+ addr.v4.s_addr = 0; /* Request dynamic */
}
if (ippool_newip(ippool, &member, &addr, 0)) {
@@ -192,7 +197,7 @@ int create_context_ind(struct pdp_t *pdp)
return 0; /* Allready in use, or no more available */
}
- pdp_ntoeua(&member->addr, &pdp->eua);
+ pdp_ntoeua(&member->addr.v4, &pdp->eua);
pdp->peer = member;
pdp->ipif = tun; /* TODO */
member->peer = pdp;
@@ -215,10 +220,18 @@ int create_context_ind(struct pdp_t *pdp)
int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
{
struct ippoolm_t *ipm;
- struct in_addr dst;
+ struct in46_addr dst;
struct tun_packet_t *iph = (struct tun_packet_t *)pack;
- dst.s_addr = iph->dst;
+ if (iph->ver == 4) {
+ if (len < sizeof(*iph) || len < 4*iph->ihl)
+ return -1;
+ dst.len = 4;
+ dst.v4.s_addr = iph->dst;
+ } else {
+ LOGP(DGGSN, LOGL_NOTICE, "non-IPv4 packet received from tun\n");
+ return -1;
+ }
DEBUGP(DGGSN, "Received packet from tun!\n");
@@ -383,12 +396,14 @@ int main(int argc, char **argv)
/* net */
/* Store net as in_addr net and mask */
if (args_info.net_arg) {
- if (ippool_aton(&net, &mask, args_info.net_arg, 0)) {
+ struct in46_addr in46;
+ if (ippool_aton(&in46, &prefixlen, args_info.net_arg, 0)) {
SYS_ERR(DGGSN, LOGL_ERROR, 0,
"Invalid network address: %s!",
args_info.net_arg);
exit(1);
}
+ net.s_addr = in46.v4.s_addr;
netaddr.s_addr = htonl(ntohl(net.s_addr) + 1);
destaddr.s_addr = htonl(ntohl(net.s_addr) + 1);
} else {
@@ -547,7 +562,7 @@ int main(int argc, char **argv)
maxfd = gsn->fd1u;
/* use GTP kernel module for data packet encapsulation */
- if (gtp_kernel_init(gsn, &net, &mask, &args_info) < 0)
+ if (gtp_kernel_init(gsn, &net, prefixlen, &args_info) < 0)
goto err;
gtp_set_cb_data_ind(gsn, encaps_tun);
@@ -572,7 +587,7 @@ int main(int argc, char **argv)
}
DEBUGP(DGGSN, "Setting tun IP address\n");
- if (tun_setaddr(tun, &netaddr, &destaddr, &mask)) {
+ if (tun_setaddr(tun, &netaddr, &destaddr, &prefixlen)) {
SYS_ERR(DGGSN, LOGL_ERROR, 0, "Failed to set tun IP address");
exit(1);
}