Netdev Archive mirror
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, kuba@kernel.org, pabeni@redhat.com,
	edumazet@google.com, laforge@osmocom.org, pespin@sysmocom.de,
	osmith@sysmocom.de, horms@kernel.org
Subject: [PATCH net-next,v3 05/12] gtp: use IPv6 address /64 prefix for UE/MS
Date: Tue,  7 May 2024 01:52:44 +0200	[thread overview]
Message-ID: <20240506235251.3968262-6-pablo@netfilter.org> (raw)
In-Reply-To: <20240506235251.3968262-1-pablo@netfilter.org>

Harald Welte reports that according to 3GPP TS 29.060:

    PDN Connection: the association between a MS represented by one IPv4
address and/or one IPv6 prefix and a PDN represented by an APN.

this clearly states that IPv4 is a single address while IPv6 is a single prefix.

Then, 3GPP TS 29.061, Section 11.2.1.3:

    For APNs that are configured for IPv6 address allocation, the GGSN/P-GW
shall only use the Prefix part of the IPv6 address for forwarding of mobile
terminated IP packets. The size of the prefix shall be according to the maximum
prefix length for a global IPv6 address as specified in the IPv6 Addressing
Architecture, see RFC 4291 [82].

RFC 4291 section 2.5.4 states

    All Global Unicast addresses other than those that start with binary 000
have a 64-bit interface ID field (i.e., n + m = 64) ...

3GPP TS 29.61 Section 11.2.1.3.2a:

    In the procedure in the cases of using GTP-based S5/S8, P-GW acts as an
access router, and allocates to a UE a globally unique /64 IPv6 prefix if the
PLMN allocates the prefix.

Therefore, compare IPv6 address /64 prefix only since MS/UE is not a single
address like in the IPv4 case.

Reject IPv6 address with EADDRNOTAVAIL if it lower 64 bits of the IPv6 address
from the control plane are set.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 drivers/net/gtp.c | 52 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 42 insertions(+), 10 deletions(-)

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 84ff502a38bc..8e861778c4e9 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -136,7 +136,8 @@ static inline u32 ipv4_hashfn(__be32 ip)
 
 static u32 ipv6_hashfn(const struct in6_addr *ip6)
 {
-	return jhash(ip6, sizeof(*ip6), gtp_h_initval);
+	return jhash_2words((__force u32)ip6->s6_addr32[0],
+			    (__force u32)ip6->s6_addr32[1], gtp_h_initval);
 }
 
 /* Resolve a PDP context structure based on the 64bit TID. */
@@ -188,6 +189,24 @@ static struct pdp_ctx *ipv4_pdp_find(struct gtp_dev *gtp, __be32 ms_addr)
 	return NULL;
 }
 
+/* 3GPP TS 29.060: PDN Connection: the association between a MS represented by
+ * [...] one IPv6 *prefix* and a PDN represented by an APN.
+ *
+ * Then, 3GPP TS 29.061, Section 11.2.1.3 says: The size of the prefix shall be
+ * according to the maximum prefix length for a global IPv6 address as
+ * specified in the IPv6 Addressing Architecture, see RFC 4291.
+ *
+ * Finally, RFC 4291 section 2.5.4 states: All Global Unicast addresses other
+ * than those that start with binary 000 have a 64-bit interface ID field
+ * (i.e., n + m = 64).
+ */
+static bool ipv6_pdp_addr_equal(const struct in6_addr *a,
+				const struct in6_addr *b)
+{
+	return a->s6_addr32[0] == b->s6_addr32[0] &&
+	       a->s6_addr32[1] == b->s6_addr32[1];
+}
+
 static struct pdp_ctx *ipv6_pdp_find(struct gtp_dev *gtp,
 				     const struct in6_addr *ms_addr)
 {
@@ -198,7 +217,7 @@ static struct pdp_ctx *ipv6_pdp_find(struct gtp_dev *gtp,
 
 	hlist_for_each_entry_rcu(pdp, head, hlist_addr) {
 		if (pdp->af == AF_INET6 &&
-		    memcmp(&pdp->ms.addr6, ms_addr, sizeof(struct in6_addr)) == 0)
+		    ipv6_pdp_addr_equal(&pdp->ms.addr6, ms_addr))
 			return pdp;
 	}
 
@@ -233,14 +252,12 @@ static bool gtp_check_ms_ipv6(struct sk_buff *skb, struct pdp_ctx *pctx,
 	ip6h = (struct ipv6hdr *)(skb->data + hdrlen);
 
 	if (role == GTP_ROLE_SGSN) {
-		ret = memcmp(&ip6h->daddr, &pctx->ms.addr6,
-			     sizeof(struct in6_addr));
+		ret = ipv6_pdp_addr_equal(&ip6h->daddr, &pctx->ms.addr6);
 	} else {
-		ret = memcmp(&ip6h->saddr, &pctx->ms.addr6,
-			     sizeof(struct in6_addr));
+		ret = ipv6_pdp_addr_equal(&ip6h->saddr, &pctx->ms.addr6);
 	}
 
-	return ret == 0;
+	return ret;
 }
 
 /* Check if the inner IP address in this packet is assigned to any
@@ -1652,11 +1669,17 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info)
 	gtp_pdp_fill(pctx, info);
 }
 
-static void ipv6_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info)
+static bool ipv6_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info)
 {
 	pctx->peer.addr6 = nla_get_in6_addr(info->attrs[GTPA_PEER_ADDR6]);
 	pctx->ms.addr6 = nla_get_in6_addr(info->attrs[GTPA_MS_ADDR6]);
+	if (pctx->ms.addr6.s6_addr32[2] ||
+	    pctx->ms.addr6.s6_addr32[3])
+		return false;
+
 	gtp_pdp_fill(pctx, info);
+
+	return true;
 }
 
 static struct pdp_ctx *gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk,
@@ -1742,7 +1765,8 @@ static struct pdp_ctx *gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk,
 			ipv4_pdp_fill(pctx, info);
 			break;
 		case AF_INET6:
-			ipv6_pdp_fill(pctx, info);
+			if (!ipv6_pdp_fill(pctx, info))
+				return ERR_PTR(-EADDRNOTAVAIL);
 			break;
 		}
 
@@ -1785,7 +1809,11 @@ static struct pdp_ctx *gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk,
 			return ERR_PTR(-EINVAL);
 		}
 
-		ipv6_pdp_fill(pctx, info);
+		if (!ipv6_pdp_fill(pctx, info)) {
+			sock_put(sk);
+			kfree(pctx);
+			return ERR_PTR(-EADDRNOTAVAIL);
+		}
 		break;
 	}
 	atomic_set(&pctx->tx_seq, 0);
@@ -1919,6 +1947,10 @@ static struct pdp_ctx *gtp_find_pdp_by_link(struct net *net,
 	} else if (nla[GTPA_MS_ADDR6]) {
 		struct in6_addr addr = nla_get_in6_addr(nla[GTPA_MS_ADDR6]);
 
+		if (addr.s6_addr32[2] ||
+		    addr.s6_addr32[3])
+			return ERR_PTR(-EADDRNOTAVAIL);
+
 		return ipv6_pdp_find(gtp, &addr);
 	} else if (nla[GTPA_VERSION]) {
 		u32 gtp_version = nla_get_u32(nla[GTPA_VERSION]);
-- 
2.30.2


  parent reply	other threads:[~2024-05-06 23:53 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-06 23:52 [PATCH net-next,v3 00/12] gtp updates for net-next (v3) Pablo Neira Ayuso
2024-05-06 23:52 ` [PATCH net-next,v3 01/12] gtp: remove useless initialization Pablo Neira Ayuso
2024-05-09 10:19   ` Simon Horman
2024-05-10 13:10   ` patchwork-bot+netdevbpf
2024-05-06 23:52 ` [PATCH net-next,v3 02/12] gtp: properly parse extension headers Pablo Neira Ayuso
2024-05-09 12:14   ` Simon Horman
2024-05-06 23:52 ` [PATCH net-next,v3 03/12] gtp: prepare for IPv6 support Pablo Neira Ayuso
2024-05-09 12:15   ` Simon Horman
2024-05-06 23:52 ` [PATCH net-next,v3 04/12] gtp: add " Pablo Neira Ayuso
2024-05-09 12:15   ` Simon Horman
2024-05-06 23:52 ` Pablo Neira Ayuso [this message]
2024-05-09 12:15   ` [PATCH net-next,v3 05/12] gtp: use IPv6 address /64 prefix for UE/MS Simon Horman
2024-05-06 23:52 ` [PATCH net-next,v3 06/12] gtp: pass up link local traffic to userspace socket Pablo Neira Ayuso
2024-05-09 12:16   ` Simon Horman
2024-05-06 23:52 ` [PATCH net-next,v3 07/12] gtp: move debugging to skbuff build helper function Pablo Neira Ayuso
2024-05-09 12:16   ` Simon Horman
2024-05-06 23:52 ` [PATCH net-next,v3 08/12] gtp: remove IPv4 and IPv6 header from context object Pablo Neira Ayuso
2024-05-09 12:17   ` Simon Horman
2024-05-06 23:52 ` [PATCH net-next,v3 09/12] gtp: add helper function to build GTP packets from an IPv4 packet Pablo Neira Ayuso
2024-05-09 12:17   ` Simon Horman
2024-05-06 23:52 ` [PATCH net-next,v3 10/12] gtp: add helper function to build GTP packets from an IPv6 packet Pablo Neira Ayuso
2024-05-09 12:17   ` Simon Horman
2024-05-06 23:52 ` [PATCH net-next,v3 11/12] gtp: support for IPv4-in-IPv6-GTP and IPv6-in-IPv4-GTP Pablo Neira Ayuso
2024-05-09 12:18   ` Simon Horman
2024-05-06 23:52 ` [PATCH net-next,v3 12/12] gtp: identify tunnel via GTP device + GTP version + TEID + family Pablo Neira Ayuso
2024-05-09 12:19   ` Simon Horman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240506235251.3968262-6-pablo@netfilter.org \
    --to=pablo@netfilter.org \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=laforge@osmocom.org \
    --cc=netdev@vger.kernel.org \
    --cc=osmith@sysmocom.de \
    --cc=pabeni@redhat.com \
    --cc=pespin@sysmocom.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).