osmith has uploaded this change for review. (
https://gerrit.osmocom.org/c/libgtpnl/+/34735?usp=email )
Change subject: add IPv6 support
......................................................................
add IPv6 support
Changes made by Oliver:
- set t->family = AF_INET in gtp_tunnel_alloc for backwards
compatibility with older osmo-ggsn versions that don't explicitly set
it.
- cosmetics
Change-Id: If864c9170f74af52a95cbc4cdb1b866e0309306b
---
M include/linux/gtp.h
M src/gtp-genl.c
M src/gtp.c
M src/internal.h
4 files changed, 105 insertions(+), 25 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libgtpnl refs/changes/35/34735/1
diff --git a/include/linux/gtp.h b/include/linux/gtp.h
index c525cb3..c2ecec2 100644
--- a/include/linux/gtp.h
+++ b/include/linux/gtp.h
@@ -1,10 +1,14 @@
-#ifndef _UAPI_LINUX_GTP_H_
-#define _UAPI_LINUX_GTP_H__
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_GTP_H_
+#define __LINUX_GTP_H_
+
+#define GTP_GENL_MCGRP_NAME "gtp"
enum gtp_genl_cmds {
GTP_CMD_NEWPDP,
GTP_CMD_DELPDP,
GTP_CMD_GETPDP,
+ GTP_CMD_ECHOREQ,
GTP_CMD_MAX,
};
@@ -19,15 +23,19 @@
GTPA_LINK,
GTPA_VERSION,
GTPA_TID, /* for GTPv0 only */
- GTPA_PEER_ADDRESS,
+ GTPA_PEER_ADDRESS, /* Remote GSN peer, either SGSN or GGSN */
+#define GTPA_SGSN_ADDRESS GTPA_PEER_ADDRESS /* maintain legacy attr name */
GTPA_MS_ADDRESS,
GTPA_FLOW,
GTPA_NET_NS_FD,
GTPA_I_TEI, /* for GTPv1 only */
GTPA_O_TEI, /* for GTPv1 only */
GTPA_PAD,
+ GTPA_PEER_ADDR6, /* Remote GSN peer, either SGSN or GGSN */
+ GTPA_MS_ADDR6,
+ GTPA_FAMILY,
__GTPA_MAX,
};
#define GTPA_MAX (__GTPA_MAX + 1)
-#endif /* _UAPI_LINUX_GTP_H_ */
+#endif /* __LINUX_GTP_H_ */
diff --git a/src/gtp-genl.c b/src/gtp-genl.c
index 21297b7..0c90894 100644
--- a/src/gtp-genl.c
+++ b/src/gtp-genl.c
@@ -44,14 +44,23 @@
static void gtp_build_payload(struct nlmsghdr *nlh, struct gtp_tunnel *t)
{
+ mnl_attr_put_u8(nlh, GTPA_FAMILY, t->family);
mnl_attr_put_u32(nlh, GTPA_VERSION, t->gtp_version);
if (t->ifns >= 0)
mnl_attr_put_u32(nlh, GTPA_NET_NS_FD, t->ifns);
mnl_attr_put_u32(nlh, GTPA_LINK, t->ifidx);
- if (t->ip.sgsn_addr.s_addr)
- mnl_attr_put_u32(nlh, GTPA_PEER_ADDRESS, t->ip.sgsn_addr.s_addr);
- if (t->ip.ms_addr.s_addr)
- mnl_attr_put_u32(nlh, GTPA_MS_ADDRESS, t->ip.ms_addr.s_addr);
+ switch (t->family) {
+ case AF_INET:
+ if (t->ip.sgsn_addr.s_addr)
+ mnl_attr_put_u32(nlh, GTPA_PEER_ADDRESS, t->ip.sgsn_addr.s_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);
+ mnl_attr_put(nlh, GTPA_MS_ADDR6, sizeof(t->ip6.ms_addr), &t->ip6.ms_addr);
+ break;
+ }
if (t->gtp_version == GTP_V0) {
mnl_attr_put_u64(nlh, GTPA_TID, t->u.v0.tid);
mnl_attr_put_u16(nlh, GTPA_FLOW, t->u.v0.flowid);
@@ -106,6 +115,7 @@
EXPORT_SYMBOL(gtp_del_tunnel);
struct gtp_pdp {
+ int family;
uint32_t version;
union {
struct {
@@ -121,6 +131,10 @@
struct in_addr sgsn_addr;
struct in_addr ms_addr;
} ip;
+ struct {
+ struct in6_addr sgsn_addr;
+ struct in6_addr ms_addr;
+ } ip6;
};
};
@@ -133,6 +147,12 @@
return MNL_CB_OK;
switch(type) {
+ case GTPA_FAMILY:
+ if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) {
+ perror("mnl_attr_validate");
+ return MNL_CB_ERROR;
+ }
+ break;
case GTPA_TID:
if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) {
perror("mnl_attr_validate");
@@ -149,6 +169,14 @@
return MNL_CB_ERROR;
}
break;
+ case GTPA_PEER_ADDR6:
+ case GTPA_MS_ADDR6:
+ if (mnl_attr_validate2(attr, MNL_TYPE_BINARY,
+ sizeof(struct in6_addr)) < 0) {
+ perror("mnl_attr_validate");
+ return MNL_CB_ERROR;
+ }
+ break;
default:
break;
}
@@ -164,35 +192,58 @@
struct genlmsghdr *genl;
mnl_attr_parse(nlh, sizeof(*genl), genl_gtp_validate_cb, tb);
+ if (tb[GTPA_FAMILY])
+ pdp.family = mnl_attr_get_u32(tb[GTPA_FAMILY]);
+ else
+ pdp.family = AF_INET;
+
if (tb[GTPA_TID])
pdp.u.v0.tid = mnl_attr_get_u64(tb[GTPA_TID]);
if (tb[GTPA_I_TEI])
pdp.u.v1.i_tei = mnl_attr_get_u32(tb[GTPA_I_TEI]);
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]);
+
+ 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;
}
- if (tb[GTPA_MS_ADDRESS]) {
- pdp.ip.ms_addr.s_addr = mnl_attr_get_u32(tb[GTPA_MS_ADDRESS]);
- }
- if (tb[GTPA_VERSION]) {
+ if (tb[GTPA_VERSION])
pdp.version = mnl_attr_get_u32(tb[GTPA_VERSION]);
- }
printf("version %u ", pdp.version);
- if (pdp.version == GTP_V0) {
+
+ if (pdp.version == GTP_V0)
+ printf("tid %"PRIu64" ", pdp.u.v0.tid);
+ 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");
+
+ switch (pdp.family) {
+ case AF_INET:
inet_ntop(AF_INET, &pdp.ip.ms_addr, buf, sizeof(buf));
- printf("tid %"PRIu64" ms_addr %s ",
- pdp.u.v0.tid, buf);
- } else if (pdp.version == GTP_V1) {
- inet_ntop(AF_INET, &pdp.ip.ms_addr, buf, sizeof(buf));
- printf("tei %u/%u ms_addr %s ", pdp.u.v1.i_tei,
- pdp.u.v1.o_tei, 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);
+ inet_ntop(AF_INET6, &pdp.ip6.sgsn_addr, buf, sizeof(buf));
+ printf("sgsn_addr6 %s\n", buf);
+ break;
}
- inet_ntop(AF_INET, &pdp.ip.sgsn_addr, buf, sizeof(buf));
- printf("sgsn_addr %s\n", buf);
return MNL_CB_OK;
}
diff --git a/src/gtp.c b/src/gtp.c
index 12f4abe..05e3731 100644
--- a/src/gtp.c
+++ b/src/gtp.c
@@ -36,6 +36,7 @@
return NULL;
t->ifns = -1;
+ t->family = AF_INET;
return t;
}
EXPORT_SYMBOL(gtp_tunnel_alloc);
diff --git a/src/internal.h b/src/internal.h
index 559461f..8e8b3c5 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -13,6 +13,7 @@
#include <netinet/in.h>
struct gtp_tunnel {
+ uint8_t family;
int ifns;
uint32_t ifidx;
union {
@@ -20,6 +21,10 @@
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 {
--
To view, visit
https://gerrit.osmocom.org/c/libgtpnl/+/34735?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: If864c9170f74af52a95cbc4cdb1b866e0309306b
Gerrit-Change-Number: 34735
Gerrit-PatchSet: 1
Gerrit-Owner: osmith <osmith(a)sysmocom.de>
Gerrit-MessageType: newchange