Skip to content

Commit 28e144c

Browse files
lxinFlorian Westphal
authored andcommitted
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>
1 parent 0b24bd7 commit 28e144c

File tree

3 files changed

+55
-54
lines changed

3 files changed

+55
-54
lines changed

include/linux/netfilter_ipv6.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ static inline int nf_cookie_v6_check(const struct ipv6hdr *iph,
197197
__sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
198198
unsigned int dataoff, u_int8_t protocol);
199199

200+
int nf_ip6_check_hbh_len(struct sk_buff *skb, u32 *plen);
201+
200202
int ipv6_netfilter_init(void);
201203
void ipv6_netfilter_fini(void);
202204

net/bridge/br_netfilter_ipv6.c

Lines changed: 1 addition & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -40,59 +40,6 @@
4040
#include <linux/sysctl.h>
4141
#endif
4242

43-
/* We only check the length. A bridge shouldn't do any hop-by-hop stuff
44-
* anyway
45-
*/
46-
static int br_nf_check_hbh_len(struct sk_buff *skb, u32 *plen)
47-
{
48-
int len, off = sizeof(struct ipv6hdr);
49-
unsigned char *nh;
50-
51-
if (!pskb_may_pull(skb, off + 8))
52-
return -1;
53-
nh = (unsigned char *)(ipv6_hdr(skb) + 1);
54-
len = (nh[1] + 1) << 3;
55-
56-
if (!pskb_may_pull(skb, off + len))
57-
return -1;
58-
nh = skb_network_header(skb);
59-
60-
off += 2;
61-
len -= 2;
62-
while (len > 0) {
63-
int optlen;
64-
65-
if (nh[off] == IPV6_TLV_PAD1) {
66-
off++;
67-
len--;
68-
continue;
69-
}
70-
if (len < 2)
71-
return -1;
72-
optlen = nh[off + 1] + 2;
73-
if (optlen > len)
74-
return -1;
75-
76-
if (nh[off] == IPV6_TLV_JUMBO) {
77-
u32 pkt_len;
78-
79-
if (nh[off + 1] != 4 || (off & 3) != 2)
80-
return -1;
81-
pkt_len = ntohl(*(__be32 *)(nh + off + 2));
82-
if (pkt_len <= IPV6_MAXPLEN ||
83-
ipv6_hdr(skb)->payload_len)
84-
return -1;
85-
if (pkt_len > skb->len - sizeof(struct ipv6hdr))
86-
return -1;
87-
*plen = pkt_len;
88-
}
89-
off += optlen;
90-
len -= optlen;
91-
}
92-
93-
return len ? -1 : 0;
94-
}
95-
9643
int br_validate_ipv6(struct net *net, struct sk_buff *skb)
9744
{
9845
const struct ipv6hdr *hdr;
@@ -112,7 +59,7 @@ int br_validate_ipv6(struct net *net, struct sk_buff *skb)
11259
goto inhdr_error;
11360

11461
pkt_len = ntohs(hdr->payload_len);
115-
if (hdr->nexthdr == NEXTHDR_HOP && br_nf_check_hbh_len(skb, &pkt_len))
62+
if (hdr->nexthdr == NEXTHDR_HOP && nf_ip6_check_hbh_len(skb, &pkt_len))
11663
goto drop;
11764

11865
if (pkt_len + ip6h_len > skb->len) {

net/netfilter/utils.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,3 +215,55 @@ int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry)
215215
}
216216
return ret;
217217
}
218+
219+
/* Only get and check the lengths, not do any hop-by-hop stuff. */
220+
int nf_ip6_check_hbh_len(struct sk_buff *skb, u32 *plen)
221+
{
222+
int len, off = sizeof(struct ipv6hdr);
223+
unsigned char *nh;
224+
225+
if (!pskb_may_pull(skb, off + 8))
226+
return -ENOMEM;
227+
nh = (unsigned char *)(ipv6_hdr(skb) + 1);
228+
len = (nh[1] + 1) << 3;
229+
230+
if (!pskb_may_pull(skb, off + len))
231+
return -ENOMEM;
232+
nh = skb_network_header(skb);
233+
234+
off += 2;
235+
len -= 2;
236+
while (len > 0) {
237+
int optlen;
238+
239+
if (nh[off] == IPV6_TLV_PAD1) {
240+
off++;
241+
len--;
242+
continue;
243+
}
244+
if (len < 2)
245+
return -EBADMSG;
246+
optlen = nh[off + 1] + 2;
247+
if (optlen > len)
248+
return -EBADMSG;
249+
250+
if (nh[off] == IPV6_TLV_JUMBO) {
251+
u32 pkt_len;
252+
253+
if (nh[off + 1] != 4 || (off & 3) != 2)
254+
return -EBADMSG;
255+
pkt_len = ntohl(*(__be32 *)(nh + off + 2));
256+
if (pkt_len <= IPV6_MAXPLEN ||
257+
ipv6_hdr(skb)->payload_len)
258+
return -EBADMSG;
259+
if (pkt_len > skb->len - sizeof(struct ipv6hdr))
260+
return -EBADMSG;
261+
*plen = pkt_len;
262+
}
263+
off += optlen;
264+
len -= optlen;
265+
}
266+
267+
return len ? -EBADMSG : 0;
268+
}
269+
EXPORT_SYMBOL_GPL(nf_ip6_check_hbh_len);

0 commit comments

Comments
 (0)