mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 04:33:26 +02:00
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@gmail.com> Reviewed-by: Simon Horman <simon.horman@corigine.com> Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org> Reviewed-by: Aaron Conole <aconole@redhat.com> Signed-off-by: Florian Westphal <fw@strlen.de>
This commit is contained in:
committed by
Florian Westphal
parent
0b24bd71a6
commit
28e144cf5f
@@ -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,
|
__sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
|
||||||
unsigned int dataoff, u_int8_t protocol);
|
unsigned int dataoff, u_int8_t protocol);
|
||||||
|
|
||||||
|
int nf_ip6_check_hbh_len(struct sk_buff *skb, u32 *plen);
|
||||||
|
|
||||||
int ipv6_netfilter_init(void);
|
int ipv6_netfilter_init(void);
|
||||||
void ipv6_netfilter_fini(void);
|
void ipv6_netfilter_fini(void);
|
||||||
|
|
||||||
|
@@ -40,59 +40,6 @@
|
|||||||
#include <linux/sysctl.h>
|
#include <linux/sysctl.h>
|
||||||
#endif
|
#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;
|
|
||||||
|
|
||||||
if (!pskb_may_pull(skb, off + 8))
|
|
||||||
return -1;
|
|
||||||
nh = (unsigned char *)(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) {
|
|
||||||
u32 pkt_len;
|
|
||||||
|
|
||||||
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;
|
|
||||||
*plen = pkt_len;
|
|
||||||
}
|
|
||||||
off += optlen;
|
|
||||||
len -= optlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
return len ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int br_validate_ipv6(struct net *net, struct sk_buff *skb)
|
int br_validate_ipv6(struct net *net, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
const struct ipv6hdr *hdr;
|
const struct ipv6hdr *hdr;
|
||||||
@@ -112,7 +59,7 @@ int br_validate_ipv6(struct net *net, struct sk_buff *skb)
|
|||||||
goto inhdr_error;
|
goto inhdr_error;
|
||||||
|
|
||||||
pkt_len = ntohs(hdr->payload_len);
|
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;
|
goto drop;
|
||||||
|
|
||||||
if (pkt_len + ip6h_len > skb->len) {
|
if (pkt_len + ip6h_len > skb->len) {
|
||||||
|
@@ -215,3 +215,55 @@ int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry)
|
|||||||
}
|
}
|
||||||
return ret;
|
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;
|
||||||
|
|
||||||
|
if (!pskb_may_pull(skb, off + 8))
|
||||||
|
return -ENOMEM;
|
||||||
|
nh = (unsigned char *)(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) {
|
||||||
|
u32 pkt_len;
|
||||||
|
|
||||||
|
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;
|
||||||
|
*plen = pkt_len;
|
||||||
|
}
|
||||||
|
off += optlen;
|
||||||
|
len -= optlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len ? -EBADMSG : 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(nf_ip6_check_hbh_len);
|
||||||
|
Reference in New Issue
Block a user