netfilter: bridge: move pskb_trim_rcsum out of br_nf_check_hbh_len
br_nf_check_hbh_len() is a function to check the Hop-by-hop option header, and shouldn't do pskb_trim_rcsum() there. This patch is to pass pkt_len out to br_validate_ipv6() and do pskb_trim_rcsum() after calling br_validate_ipv6() instead. Signed-off-by: Xin Long <lucien.xin@gmail.com> Reviewed-by: Simon Horman <simon.horman@corigine.com> Acked-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
a7f1a2f43e
commit
0b24bd71a6
|
@ -43,11 +43,10 @@
|
||||||
/* We only check the length. A bridge shouldn't do any hop-by-hop stuff
|
/* We only check the length. A bridge shouldn't do any hop-by-hop stuff
|
||||||
* anyway
|
* anyway
|
||||||
*/
|
*/
|
||||||
static int br_nf_check_hbh_len(struct sk_buff *skb)
|
static int br_nf_check_hbh_len(struct sk_buff *skb, u32 *plen)
|
||||||
{
|
{
|
||||||
int len, off = sizeof(struct ipv6hdr);
|
int len, off = sizeof(struct ipv6hdr);
|
||||||
unsigned char *nh;
|
unsigned char *nh;
|
||||||
u32 pkt_len;
|
|
||||||
|
|
||||||
if (!pskb_may_pull(skb, off + 8))
|
if (!pskb_may_pull(skb, off + 8))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -75,6 +74,8 @@ static int br_nf_check_hbh_len(struct sk_buff *skb)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (nh[off] == IPV6_TLV_JUMBO) {
|
if (nh[off] == IPV6_TLV_JUMBO) {
|
||||||
|
u32 pkt_len;
|
||||||
|
|
||||||
if (nh[off + 1] != 4 || (off & 3) != 2)
|
if (nh[off + 1] != 4 || (off & 3) != 2)
|
||||||
return -1;
|
return -1;
|
||||||
pkt_len = ntohl(*(__be32 *)(nh + off + 2));
|
pkt_len = ntohl(*(__be32 *)(nh + off + 2));
|
||||||
|
@ -83,10 +84,7 @@ static int br_nf_check_hbh_len(struct sk_buff *skb)
|
||||||
return -1;
|
return -1;
|
||||||
if (pkt_len > skb->len - sizeof(struct ipv6hdr))
|
if (pkt_len > skb->len - sizeof(struct ipv6hdr))
|
||||||
return -1;
|
return -1;
|
||||||
if (pskb_trim_rcsum(skb,
|
*plen = pkt_len;
|
||||||
pkt_len + sizeof(struct ipv6hdr)))
|
|
||||||
return -1;
|
|
||||||
nh = skb_network_header(skb);
|
|
||||||
}
|
}
|
||||||
off += optlen;
|
off += optlen;
|
||||||
len -= optlen;
|
len -= optlen;
|
||||||
|
@ -114,23 +112,20 @@ 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 (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
|
|
||||||
if (pkt_len + ip6h_len > skb->len) {
|
|
||||||
__IP6_INC_STATS(net, idev,
|
|
||||||
IPSTATS_MIB_INTRUNCATEDPKTS);
|
|
||||||
goto drop;
|
|
||||||
}
|
|
||||||
if (pskb_trim_rcsum(skb, pkt_len + ip6h_len)) {
|
|
||||||
__IP6_INC_STATS(net, idev,
|
|
||||||
IPSTATS_MIB_INDISCARDS);
|
|
||||||
goto drop;
|
|
||||||
}
|
|
||||||
hdr = ipv6_hdr(skb);
|
|
||||||
}
|
|
||||||
if (hdr->nexthdr == NEXTHDR_HOP && br_nf_check_hbh_len(skb))
|
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
|
if (pkt_len + ip6h_len > skb->len) {
|
||||||
|
__IP6_INC_STATS(net, idev,
|
||||||
|
IPSTATS_MIB_INTRUNCATEDPKTS);
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
|
if (pskb_trim_rcsum(skb, pkt_len + ip6h_len)) {
|
||||||
|
__IP6_INC_STATS(net, idev,
|
||||||
|
IPSTATS_MIB_INDISCARDS);
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
|
|
||||||
memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
|
memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
|
||||||
/* No IP options in IPv6 header; however it should be
|
/* No IP options in IPv6 header; however it should be
|
||||||
* checked if some next headers need special treatment
|
* checked if some next headers need special treatment
|
||||||
|
|
Loading…
Reference in New Issue