osmith has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-ggsn/+/36031?usp=email )


Change subject: kernel-gtp: support IPv6 on outer layer
......................................................................

kernel-gtp: support IPv6 on outer layer

Related: OS#1953, OS#6096
Change-Id: I257fff1dcd9d030a7f9ea936b2693a3f13208230
---
M ggsn/ggsn.c
M gtp/gsn.c
M gtp/gsn.h
M gtp/gtp.c
M lib/in46_addr.c
M lib/in46_addr.h
M sgsnemu/sgsnemu.c
M tests/gtp/Makefile.am
8 files changed, 78 insertions(+), 41 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-ggsn refs/changes/31/36031/1

diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index 918d565..cec043d 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -822,7 +822,7 @@
        LOGPGGSN(LOGL_INFO, ggsn, "Starting GGSN\n");

        /* Start libgtp listener */
-       if (gtp_new(&ggsn->gsn, ggsn->cfg.state_dir, &ggsn->cfg.listen_addr.v4, 
GTP_MODE_GGSN)) {
+       if (gtp_new(&ggsn->gsn, ggsn->cfg.state_dir, &ggsn->cfg.listen_addr, 
GTP_MODE_GGSN)) {
                LOGPGGSN(LOGL_ERROR, ggsn, "Failed to create GTP: %s\n", 
strerror(errno));
                return -1;
        }
@@ -830,11 +830,9 @@

        /* patch in different addresses to use (in case we're behind NAT, the 
listen
         * address is different from what we advertise externally) */
-       if (ggsn->cfg.gtpc_addr.v4.s_addr)
-               ggsn->gsn->gsnc = ggsn->cfg.gtpc_addr.v4;
+       ggsn->gsn->gsnc = ggsn->cfg.gtpc_addr;

-       if (ggsn->cfg.gtpu_addr.v4.s_addr)
-               ggsn->gsn->gsnu = ggsn->cfg.gtpu_addr.v4;
+       ggsn->gsn->gsnu = ggsn->cfg.gtpu_addr;

        /* Register File Descriptors */
        osmo_fd_setup(&ggsn->gtp_fd0, ggsn->gsn->fd0, OSMO_FD_READ, 
ggsn_gtp_fd_cb, ggsn, 0);
diff --git a/gtp/gsn.c b/gtp/gsn.c
index eb15eaf..1109d66 100644
--- a/gtp/gsn.c
+++ b/gtp/gsn.c
@@ -64,11 +64,6 @@

 /* Error reporting functions */

-#define LOGP_WITH_ADDR(ss, level, addr, fmt, args...)                    \
-               LOGP(ss, level, "addr(%s:%d) " fmt,                      \
-                    inet_ntoa((addr).sin_addr), htons((addr).sin_port), \
-                    ##args);
-
 static const struct rate_ctr_desc gsn_ctr_description[] = {
        [GSN_CTR_ERR_SOCKET] = { "err:socket", "Socket error" },
        [GSN_CTR_ERR_READFROM] = { "err:readfrom", "readfrom() errors" },
@@ -423,10 +418,10 @@
        talloc_free(filename);
 }

-static int create_and_bind_socket(const char *name, struct gsn_t *gsn, int 
*fd, int domain,
-                                 const struct in_addr *listen, int port)
+static int create_and_bind_socket(const char *name, struct gsn_t *gsn, int 
*fd, const struct in46_addr *listen,
+                                 int port)
 {
-       struct sockaddr_in addr;
+       int domain = in46a_to_af(listen);
        int type = SOCK_DGRAM;
        int protocol = 0;

@@ -440,29 +435,51 @@
                return -errno;
        }

-       memset(&addr, 0, sizeof(addr));
-       addr.sin_family = domain;
-       addr.sin_addr = *listen;
-       addr.sin_port = htons(port);
+       switch (domain) {
+       case AF_INET:
+       {
+               struct sockaddr_in addr = {0};
+               addr.sin_family = AF_INET;
+               addr.sin_addr = listen->v4;
+               addr.sin_port = htons(port);
 #if defined(__FreeBSD__) || defined(__APPLE__)
-       addr.sin_len = sizeof(addr);
+                       addr.sin_len = sizeof(struct addr);
 #endif
-
-       if (bind(*fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-               rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_SOCKET);
-               LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
-                              "%s bind(fd=%d) failed: Error = %s\n",
-                              name, *fd, strerror(errno));
-               return -errno;
+                       if (bind(*fd, &addr, sizeof(addr)) < 0)
+                               goto bind_err;
+                       break;
+               }
+       case AF_INET6:
+       {
+               struct sockaddr_in6 addr = {0};
+               addr.sin6_family = AF_INET6;
+               addr.sin6_addr = listen->v6;
+               addr.sin6_port = htons(port);
+#if defined(__FreeBSD__) || defined(__APPLE__)
+               addr.sin6_len = sizeof(struct addr);
+#endif
+               if (bind(*fd, &addr, sizeof(addr)) < 0)
+                       goto bind_err;
+               break;
+       }
+       default:
+               OSMO_ASSERT(false);
+               break;
        }

        return 0;
+
+bind_err:
+       rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_SOCKET);
+       LOGP(DLGTP, LOGL_ERROR,
+            "%s bind(fd=%d, addr=(%s:%d)) failed: Error = %s\n",
+            name, *fd, in46a_ntoa(listen), port, strerror(errno));
+       return -errno;
 }

-int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
-           int mode)
+int gtp_new(struct gsn_t **gsn, char *statedir, struct in46_addr *listen, int 
mode)
 {
-       LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", 
inet_ntoa(*listen));
+       LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", 
in46a_ntoa(listen));

        *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */

@@ -511,15 +528,15 @@
        (*gsn)->fd1u = -1;

        /* Create GTP version 0 socket */
-       if (create_and_bind_socket("GTPv0", *gsn, &(*gsn)->fd0, AF_INET, 
listen, GTP0_PORT) < 0)
+       if (create_and_bind_socket("GTPv0", *gsn, &(*gsn)->fd0, listen, 
GTP0_PORT) < 0)
                goto error;

        /* Create GTP version 1 control plane socket */
-       if (create_and_bind_socket("GTPv1 control plane", *gsn, &(*gsn)->fd1c, 
AF_INET, listen, GTP1C_PORT) < 0)
+       if (create_and_bind_socket("GTPv1 control plane", *gsn, &(*gsn)->fd1c, 
listen, GTP1C_PORT) < 0)
                goto error;

        /* Create GTP version 1 user plane socket */
-       if (create_and_bind_socket("GTPv1 user plane", *gsn, &(*gsn)->fd1u, 
AF_INET, listen, GTP1U_PORT) < 0)
+       if (create_and_bind_socket("GTPv1 user plane", *gsn, &(*gsn)->fd1u, 
listen, GTP1U_PORT) < 0)
                goto error;

        /* Start internal queue timer */
diff --git a/gtp/gsn.h b/gtp/gsn.h
index 8e47ce3..df2f745 100644
--- a/gtp/gsn.h
+++ b/gtp/gsn.h
@@ -18,6 +18,7 @@
 #include <osmocom/core/tdef.h>
 #include <osmocom/core/rate_ctr.h>

+#include "../lib/in46_addr.h"
 #include "pdp.h"

 #define GTP_MODE_GGSN 1
@@ -77,8 +78,8 @@
        int fd1c;               /* GTP1 control plane file descriptor */
        int fd1u;               /* GTP0 user plane file descriptor */
        int mode;               /* Mode of operation: GGSN or SGSN */
-       struct in_addr gsnc;    /* IP address of this gsn for signalling */
-       struct in_addr gsnu;    /* IP address of this gsn for user traffic */
+       struct in46_addr gsnc;  /* IP address of this gsn for signalling */
+       struct in46_addr gsnu;  /* IP address of this gsn for user traffic */

        /* Parameters related to signalling messages */
        uint16_t seq_next;      /* Next sequence number to use */
@@ -117,8 +118,7 @@

 /* External API functions */

-extern int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
-                  int mode);
+extern int gtp_new(struct gsn_t **gsn, char *statedir, struct in46_addr 
*listen, int mode);

 extern int gtp_free(struct gsn_t *gsn);

diff --git a/gtp/gtp.c b/gtp/gtp.c
index 43e56b5..86c456f 100644
--- a/gtp/gtp.c
+++ b/gtp/gtp.c
@@ -1297,8 +1297,8 @@
        }

        /* Initialize our own IP addresses */
-       in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
-       in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
+       in46a_to_gsna(&pdp->gsnlc, &gsn->gsnc);
+       in46a_to_gsna(&pdp->gsnlu, &gsn->gsnu);

        if (!gtp_pdp_getimsi(gsn, &pdp_old, pdp->imsi, pdp->nsapi)) {
                /* Found old pdp with same tid. Now the voodoo begins! */
diff --git a/lib/in46_addr.c b/lib/in46_addr.c
index 648fe7e..d7c194f 100644
--- a/lib/in46_addr.c
+++ b/lib/in46_addr.c
@@ -376,6 +376,14 @@
        return 1;
 }

+void in46a_to_gsna(struct ul16_t *gsna, const struct in46_addr *src)
+{
+       memset(gsna, 0, sizeof(struct ul16_t));
+       gsna->l = src->len;
+       OSMO_ASSERT(gsna->l <= sizeof(gsna->v));
+       memcpy(gsna->v, &src->v6, gsna->l);
+}
+
 void in46a_from_gsna(const struct ul16_t *in, struct in46_addr *dst)
 {
        dst->len = in->l;
diff --git a/lib/in46_addr.h b/lib/in46_addr.h
index 5589f94..59f58fc 100644
--- a/lib/in46_addr.h
+++ b/lib/in46_addr.h
@@ -40,4 +40,5 @@
        return addr->len == sizeof(struct in_addr);
 }

+void in46a_to_gsna(struct ul16_t *gsna, const struct in46_addr *src);
 void in46a_from_gsna(const struct ul16_t *in, struct in46_addr *dst);
diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c
index 7893f4f..f5ed671 100644
--- a/sgsnemu/sgsnemu.c
+++ b/sgsnemu/sgsnemu.c
@@ -59,6 +59,7 @@
 #include "../lib/syserr.h"
 #include "../lib/netns.h"
 #include "../lib/icmpv6.h"
+#include "../lib/in46_addr.h"
 #include "../gtp/pdp.h"
 #include "../gtp/gtp.h"
 #include "cmdline.h"
@@ -117,7 +118,7 @@
        int pingsize;
        int pingcount;
        int pingquiet;
-       struct in_addr listen;
+       struct in46_addr listen;
        struct in_addr remote;
        struct in_addr dns;
        int contexts;           /* Number of contexts to create */
@@ -459,10 +460,10 @@
                                args_info.listen_arg);
                        return -1;
                } else {
-                       memcpy(&options.listen.s_addr, host->h_addr,
-                              host->h_length);
+                       options.listen.len = host->h_length;
+                       memcpy(&options.listen.v6, host->h_addr, 
host->h_length);
                        printf("Local IP address is:   %s (%s)\n",
-                              args_info.listen_arg, inet_ntoa(options.listen));
+                              args_info.listen_arg, 
in46a_ntoa(&options.listen));
                }
        } else {
                SYS_ERR(DSGSN, LOGL_ERROR, 0,
diff --git a/tests/gtp/Makefile.am b/tests/gtp/Makefile.am
index ef69260..4d4d2e3 100644
--- a/tests/gtp/Makefile.am
+++ b/tests/gtp/Makefile.am
@@ -22,11 +22,13 @@
 gtpie_test_LDADD = \
        $(top_builddir)/lib/debug.o \
        $(top_builddir)/gtp/libgtp.la \
+       $(top_builddir)/lib/libmisc.a \
        $(LIBOSMOCORE_LIBS) \
        $(NULL)

 queue_test_LDADD = \
        $(top_builddir)/lib/debug.o \
        $(top_builddir)/gtp/libgtp.la \
+       $(top_builddir)/lib/libmisc.a \
        $(LIBOSMOCORE_LIBS) \
        $(NULL)

--
To view, visit https://gerrit.osmocom.org/c/osmo-ggsn/+/36031?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-ggsn
Gerrit-Branch: master
Gerrit-Change-Id: I257fff1dcd9d030a7f9ea936b2693a3f13208230
Gerrit-Change-Number: 36031
Gerrit-PatchSet: 1
Gerrit-Owner: osmith <[email protected]>
Gerrit-MessageType: newchange

Reply via email to