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:
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,
|
||||
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);
|
||||
|
||||
|
@ -40,59 +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;
|
||||
|
||||
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)
|
||||
{
|
||||
const struct ipv6hdr *hdr;
|
||||
@ -112,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) {
|
||||
|
@ -215,3 +215,55 @@ 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;
|
||||
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user