osmith has uploaded this change for review. (
https://gerrit.osmocom.org/c/libgtpnl/+/34739?usp=email )
Change subject: IPv4-in-IPv6-GTP and IPv6-in-IPv4-GTP
......................................................................
IPv4-in-IPv6-GTP and IPv6-in-IPv4-GTP
allow to combine:
- GTPA_MS_ADDRESS and GTPA_PEER_ADDR6
- GTPA_MS_ADDR6 and GTPA_PEER_ADDRESS
to specify IPv4-in-IPv6-GTP and IPv6-in-IPv4-GTP in the tunnel
declaration from control plane.
Remove union in gtp_pdp and gtp_tunnel objects, since ms and sgsn fields
might now use different IP family. Update listing to support too to deal
with this new feature.
Update syntax of gtp-tunnel tool:
add <gtp device> <v0> <tid> <family> <ms-addr>
<family> <sgsn-addr>
add <gtp device> <v1> <i_tei> <o_tei> <family>
<ms-addr> <family> <sgsn-addr>
to allow specify the family for the peer (sgsn) address too.
Changes by Oliver:
- cosmetics
Change-Id: Ibc581a92a561dc0bd9924d9f15c7a27dc513c8d7
---
M src/gtp-genl.c
M src/internal.h
M tools/gtp-tunnel.c
3 files changed, 93 insertions(+), 34 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libgtpnl refs/changes/39/34739/1
diff --git a/src/gtp-genl.c b/src/gtp-genl.c
index 4e4e63d..2cf4102 100644
--- a/src/gtp-genl.c
+++ b/src/gtp-genl.c
@@ -53,11 +53,18 @@
case AF_INET:
if (t->ip.sgsn_addr.s_addr)
mnl_attr_put_u32(nlh, GTPA_PEER_ADDRESS, t->ip.sgsn_addr.s_addr);
+ else
+ mnl_attr_put(nlh, GTPA_PEER_ADDR6, sizeof(t->ip6.sgsn_addr),
&t->ip6.sgsn_addr);
+
if (t->ip.ms_addr.s_addr)
mnl_attr_put_u32(nlh, GTPA_MS_ADDRESS, t->ip.ms_addr.s_addr);
break;
case AF_INET6:
- mnl_attr_put(nlh, GTPA_PEER_ADDR6, sizeof(t->ip6.sgsn_addr),
&t->ip6.sgsn_addr);
+ if (t->ip.sgsn_addr.s_addr)
+ mnl_attr_put_u32(nlh, GTPA_PEER_ADDRESS, t->ip.sgsn_addr.s_addr);
+ else
+ mnl_attr_put(nlh, GTPA_PEER_ADDR6, sizeof(t->ip6.sgsn_addr),
&t->ip6.sgsn_addr);
+
mnl_attr_put(nlh, GTPA_MS_ADDR6, sizeof(t->ip6.ms_addr), &t->ip6.ms_addr);
break;
}
@@ -126,16 +133,14 @@
uint32_t o_tei;
} v1;
} u;
- union {
- struct {
- struct in_addr sgsn_addr;
- struct in_addr ms_addr;
- } ip;
- struct {
- struct in6_addr sgsn_addr;
- struct in6_addr ms_addr;
- } ip6;
- };
+ struct {
+ struct in_addr sgsn_addr;
+ struct in_addr ms_addr;
+ } ip;
+ struct {
+ struct in6_addr sgsn_addr;
+ struct in6_addr ms_addr;
+ } ip6;
};
static int genl_gtp_validate_cb(const struct nlattr *attr, void *data)
@@ -188,6 +193,7 @@
{
struct nlattr *tb[GTPA_MAX + 1] = {};
char buf[INET6_ADDRSTRLEN];
+ int peer_family = AF_UNSPEC;
struct gtp_pdp pdp = {};
struct genlmsghdr *genl;
@@ -204,16 +210,21 @@
if (tb[GTPA_O_TEI])
pdp.u.v1.o_tei = mnl_attr_get_u32(tb[GTPA_O_TEI]);
+ if (tb[GTPA_PEER_ADDRESS]) {
+ pdp.ip.sgsn_addr.s_addr = mnl_attr_get_u32(tb[GTPA_PEER_ADDRESS]);
+ peer_family = AF_INET;
+ } else if (tb[GTPA_PEER_ADDR6]) {
+ memcpy(&pdp.ip6.sgsn_addr, mnl_attr_get_payload(tb[GTPA_PEER_ADDR6]),
+ sizeof(struct in6_addr));
+ peer_family = AF_INET6;
+ }
+
switch (pdp.family) {
case AF_INET:
- if (tb[GTPA_PEER_ADDRESS])
- pdp.ip.sgsn_addr.s_addr = mnl_attr_get_u32(tb[GTPA_PEER_ADDRESS]);
if (tb[GTPA_MS_ADDRESS])
pdp.ip.ms_addr.s_addr = mnl_attr_get_u32(tb[GTPA_MS_ADDRESS]);
break;
case AF_INET6:
- if (tb[GTPA_PEER_ADDR6])
- memcpy(&pdp.ip6.sgsn_addr, mnl_attr_get_payload(tb[GTPA_PEER_ADDR6]),
sizeof(struct in6_addr));
if (tb[GTPA_MS_ADDR6])
memcpy(&pdp.ip6.ms_addr, mnl_attr_get_payload(tb[GTPA_MS_ADDR6]), sizeof(struct
in6_addr));
break;
@@ -228,18 +239,27 @@
else if (pdp.version == GTP_V1)
printf("tei %u/%u ", pdp.u.v1.i_tei, pdp.u.v1.o_tei);
- printf("family %s ", pdp.family == AF_INET6 ? "ip6" :
"ip");
+ printf("%s ", pdp.family == AF_INET6 ? "ip6" : "ip");
switch (pdp.family) {
case AF_INET:
inet_ntop(AF_INET, &pdp.ip.ms_addr, buf, sizeof(buf));
printf("ms_addr %s ", buf);
- inet_ntop(AF_INET, &pdp.ip.sgsn_addr, buf, sizeof(buf));
- printf("sgsn_addr %s\n", buf);
break;
case AF_INET6:
inet_ntop(AF_INET6, &pdp.ip6.ms_addr, buf, sizeof(buf));
printf("ms_addr6 %s ", buf);
+ break;
+ }
+
+ printf("%s ", peer_family == AF_INET6 ? "ip6" : "ip");
+
+ switch (peer_family) {
+ case AF_INET:
+ inet_ntop(AF_INET, &pdp.ip.sgsn_addr, buf, sizeof(buf));
+ printf("sgsn_addr %s\n", buf);
+ break;
+ case AF_INET6:
inet_ntop(AF_INET6, &pdp.ip6.sgsn_addr, buf, sizeof(buf));
printf("sgsn_addr6 %s\n", buf);
break;
diff --git a/src/internal.h b/src/internal.h
index 8e8b3c5..10be913 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -16,16 +16,14 @@
uint8_t family;
int ifns;
uint32_t ifidx;
- union {
- struct {
- struct in_addr ms_addr;
- struct in_addr sgsn_addr;
- } ip;
- struct {
- struct in6_addr ms_addr;
- struct in6_addr sgsn_addr;
- } ip6;
- };
+ struct {
+ struct in_addr ms_addr;
+ struct in_addr sgsn_addr;
+ } ip;
+ struct {
+ struct in6_addr ms_addr;
+ struct in6_addr sgsn_addr;
+ } ip6;
int gtp_version;
union {
struct {
diff --git a/tools/gtp-tunnel.c b/tools/gtp-tunnel.c
index 3f5de5f..3033d64 100644
--- a/tools/gtp-tunnel.c
+++ b/tools/gtp-tunnel.c
@@ -43,9 +43,9 @@
static void add_usage(const char *name)
{
- printf("%s add <gtp device> <v0> <tid> <family>
<ms-addr> <sgsn-addr>\n",
+ printf("%s add <gtp device> <v0> <tid> <family>
<ms-addr> <family> <sgsn-addr>\n",
name);
- printf("%s add <gtp device> <v1> <i_tei> <o_tei>
<family> <ms-addr> <sgsn-addr>\n",
+ printf("%s add <gtp device> <v1> <i_tei> <o_tei>
<family> <ms-addr> <family> <sgsn-addr>\n",
name);
}
@@ -60,12 +60,12 @@
struct in_addr addr;
struct in6_addr addr6;
} sgsn;
+ int optidx, family, peer_family;
struct gtp_tunnel *t;
uint32_t gtp_version;
uint32_t gtp_ifidx;
- int optidx, family;
- if (argc < 8 || argc > 9) {
+ if (argc < 9 || argc > 10) {
add_usage(argv[0]);
return EXIT_FAILURE;
}
@@ -129,12 +129,22 @@
break;
}
- if (inet_pton(family, argv[optidx++], &sgsn) <= 0) {
+ if (!strcmp(argv[optidx], "ip")) {
+ peer_family = AF_INET;
+ } else if (!strcmp(argv[optidx], "ip6")) {
+ peer_family = AF_INET6;
+ } else {
+ fprintf(stderr, "wrong family `%s', expecting `ip' or `ip6'\n",
argv[optidx]);
+ return EXIT_FAILURE;
+ }
+ optidx++;
+
+ if (inet_pton(peer_family, argv[optidx++], &sgsn) <= 0) {
fprintf(stderr, "bad address for sgsn\n");
exit(EXIT_FAILURE);
}
- switch (family) {
+ switch (peer_family) {
case AF_INET:
gtp_tunnel_set_sgsn_ip4(t, &sgsn.addr);
break;
--
To view, visit
https://gerrit.osmocom.org/c/libgtpnl/+/34739?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: libgtpnl
Gerrit-Branch: master
Gerrit-Change-Id: Ibc581a92a561dc0bd9924d9f15c7a27dc513c8d7
Gerrit-Change-Number: 34739
Gerrit-PatchSet: 1
Gerrit-Owner: osmith <osmith(a)sysmocom.de>
Gerrit-MessageType: newchange