[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <84b12a8d761ac804794f6a0e08011eff4c2c0a3a.1677888566.git.lucien.xin@gmail.com>
Date: Fri, 3 Mar 2023 19:12:40 -0500
From: Xin Long <lucien.xin@...il.com>
To: netfilter-devel@...r.kernel.org,
network dev <netdev@...r.kernel.org>
Cc: Pablo Neira Ayuso <pablo@...filter.org>,
Jozsef Kadlecsik <kadlec@...filter.org>,
Florian Westphal <fw@...len.de>, davem@...emloft.net,
kuba@...nel.org, Eric Dumazet <edumazet@...gle.com>,
Paolo Abeni <pabeni@...hat.com>,
Roopa Prabhu <roopa@...dia.com>,
Nikolay Aleksandrov <razor@...ckwall.org>,
Pravin B Shelar <pshelar@....org>,
Aaron Conole <aconole@...hat.com>
Subject: [PATCH nf-next 4/6] netfilter: move br_nf_check_hbh_len to utils
Rename br_nf_check_hbh_len() to nf_ip6_check_hbh_len() and move it
to netfilter utils, so that it can be used by other modules, like
ovs and tc.
Signed-off-by: Xin Long <lucien.xin@...il.com>
---
include/linux/netfilter_ipv6.h | 2 ++
net/bridge/br_netfilter_ipv6.c | 57 +---------------------------------
net/netfilter/utils.c | 54 ++++++++++++++++++++++++++++++++
3 files changed, 57 insertions(+), 56 deletions(-)
diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
index 48314ade1506..7834c0be2831 100644
--- a/include/linux/netfilter_ipv6.h
+++ b/include/linux/netfilter_ipv6.h
@@ -197,6 +197,8 @@ static inline int nf_cookie_v6_check(const struct ipv6hdr *iph,
__sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, u_int8_t protocol);
+int nf_ip6_check_hbh_len(struct sk_buff *skb, u32 *plen);
+
int ipv6_netfilter_init(void);
void ipv6_netfilter_fini(void);
diff --git a/net/bridge/br_netfilter_ipv6.c b/net/bridge/br_netfilter_ipv6.c
index 07289e4f3213..550039dfc31a 100644
--- a/net/bridge/br_netfilter_ipv6.c
+++ b/net/bridge/br_netfilter_ipv6.c
@@ -40,61 +40,6 @@
#include <linux/sysctl.h>
#endif
-/* We only check the length. A bridge shouldn't do any hop-by-hop stuff
- * anyway
- */
-static int br_nf_check_hbh_len(struct sk_buff *skb, u32 *plen)
-{
- int len, off = sizeof(struct ipv6hdr);
- unsigned char *nh;
- u32 pkt_len = 0;
-
- if (!pskb_may_pull(skb, off + 8))
- return -1;
- nh = (u8 *)(ipv6_hdr(skb) + 1);
- len = (nh[1] + 1) << 3;
-
- if (!pskb_may_pull(skb, off + len))
- return -1;
- nh = skb_network_header(skb);
-
- off += 2;
- len -= 2;
- while (len > 0) {
- int optlen;
-
- if (nh[off] == IPV6_TLV_PAD1) {
- off++;
- len--;
- continue;
- }
- if (len < 2)
- return -1;
- optlen = nh[off + 1] + 2;
- if (optlen > len)
- return -1;
-
- if (nh[off] == IPV6_TLV_JUMBO) {
- if (nh[off + 1] != 4 || (off & 3) != 2)
- return -1;
- pkt_len = ntohl(*(__be32 *)(nh + off + 2));
- if (pkt_len <= IPV6_MAXPLEN ||
- ipv6_hdr(skb)->payload_len)
- return -1;
- if (pkt_len > skb->len - sizeof(struct ipv6hdr))
- return -1;
- }
- off += optlen;
- len -= optlen;
- }
- if (len)
- return -1;
-
- if (pkt_len)
- *plen = pkt_len;
- return 0;
-}
-
int br_validate_ipv6(struct net *net, struct sk_buff *skb)
{
const struct ipv6hdr *hdr;
@@ -114,7 +59,7 @@ int br_validate_ipv6(struct net *net, struct sk_buff *skb)
goto inhdr_error;
pkt_len = ntohs(hdr->payload_len);
- if (hdr->nexthdr == NEXTHDR_HOP && br_nf_check_hbh_len(skb, &pkt_len))
+ if (hdr->nexthdr == NEXTHDR_HOP && nf_ip6_check_hbh_len(skb, &pkt_len))
goto drop;
if (pkt_len + ip6h_len > skb->len) {
diff --git a/net/netfilter/utils.c b/net/netfilter/utils.c
index 2182d361e273..04f4bd661774 100644
--- a/net/netfilter/utils.c
+++ b/net/netfilter/utils.c
@@ -215,3 +215,57 @@ int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry)
}
return ret;
}
+
+/* Only get and check the lengths, not do any hop-by-hop stuff. */
+int nf_ip6_check_hbh_len(struct sk_buff *skb, u32 *plen)
+{
+ int len, off = sizeof(struct ipv6hdr);
+ unsigned char *nh;
+ u32 pkt_len = 0;
+
+ if (!pskb_may_pull(skb, off + 8))
+ return -ENOMEM;
+ nh = (u8 *)(ipv6_hdr(skb) + 1);
+ len = (nh[1] + 1) << 3;
+
+ if (!pskb_may_pull(skb, off + len))
+ return -ENOMEM;
+ nh = skb_network_header(skb);
+
+ off += 2;
+ len -= 2;
+ while (len > 0) {
+ int optlen;
+
+ if (nh[off] == IPV6_TLV_PAD1) {
+ off++;
+ len--;
+ continue;
+ }
+ if (len < 2)
+ return -EBADMSG;
+ optlen = nh[off + 1] + 2;
+ if (optlen > len)
+ return -EBADMSG;
+
+ if (nh[off] == IPV6_TLV_JUMBO) {
+ if (nh[off + 1] != 4 || (off & 3) != 2)
+ return -EBADMSG;
+ pkt_len = ntohl(*(__be32 *)(nh + off + 2));
+ if (pkt_len <= IPV6_MAXPLEN ||
+ ipv6_hdr(skb)->payload_len)
+ return -EBADMSG;
+ if (pkt_len > skb->len - sizeof(struct ipv6hdr))
+ return -EBADMSG;
+ }
+ off += optlen;
+ len -= optlen;
+ }
+ if (len)
+ return -EBADMSG;
+
+ if (pkt_len)
+ *plen = pkt_len;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nf_ip6_check_hbh_len);
--
2.39.1
Powered by blists - more mailing lists