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
This commit is contained in:
parent
86d1bc36b7
commit
b9c3b49410
|
@ -53,11 +53,18 @@ static void gtp_build_payload(struct nlmsghdr *nlh, struct gtp_tunnel *t)
|
|||
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 @@ struct gtp_pdp {
|
|||
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 @@ static int genl_gtp_attr_cb(const struct nlmsghdr *nlh, void *data)
|
|||
{
|
||||
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 @@ static int genl_gtp_attr_cb(const struct nlmsghdr *nlh, void *data)
|
|||
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 @@ static int genl_gtp_attr_cb(const struct nlmsghdr *nlh, void *data)
|
|||
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;
|
||||
|
|
|
@ -16,16 +16,14 @@ struct gtp_tunnel {
|
|||
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 {
|
||||
|
|
|
@ -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 @@ add_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl)
|
|||
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 @@ add_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl)
|
|||
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;
|
||||
|
|
Loading…
Reference in New Issue