Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 214579
b: refs/heads/master
c: 462fb2a
h: refs/heads/master
i:
  214577: 198e0a1
  214575: 5b8f942
v: v3
  • Loading branch information
Bandan Das authored and David S. Miller committed Sep 19, 2010
1 parent 7f59726 commit 339dc1a
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 31 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: aef3ea33e85035f7c827c1db9155f97f4b7ee725
refs/heads/master: 462fb2af9788a82a534f8184abfde31574e1cfa0
107 changes: 78 additions & 29 deletions trunk/net/bridge/br_netfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,72 @@ static inline void nf_bridge_update_protocol(struct sk_buff *skb)
skb->protocol = htons(ETH_P_PPP_SES);
}

/* When handing a packet over to the IP layer
* check whether we have a skb that is in the
* expected format
*/

int br_parse_ip_options(struct sk_buff *skb)
{
struct ip_options *opt;
struct iphdr *iph;
struct net_device *dev = skb->dev;
u32 len;

iph = ip_hdr(skb);
opt = &(IPCB(skb)->opt);

/* Basic sanity checks */
if (iph->ihl < 5 || iph->version != 4)
goto inhdr_error;

if (!pskb_may_pull(skb, iph->ihl*4))
goto inhdr_error;

iph = ip_hdr(skb);
if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
goto inhdr_error;

len = ntohs(iph->tot_len);
if (skb->len < len) {
IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INTRUNCATEDPKTS);
goto drop;
} else if (len < (iph->ihl*4))
goto inhdr_error;

if (pskb_trim_rcsum(skb, len)) {
IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
goto drop;
}

/* Zero out the CB buffer if no options present */
if (iph->ihl == 5) {
memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
return 0;
}

opt->optlen = iph->ihl*4 - sizeof(struct iphdr);
if (ip_options_compile(dev_net(dev), opt, skb))
goto inhdr_error;

/* Check correct handling of SRR option */
if (unlikely(opt->srr)) {
struct in_device *in_dev = __in_dev_get_rcu(dev);
if (in_dev && !IN_DEV_SOURCE_ROUTE(in_dev))
goto drop;

if (ip_options_rcv_srr(skb))
goto drop;
}

return 0;

inhdr_error:
IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS);
drop:
return -1;
}

/* Fill in the header for fragmented IP packets handled by
* the IPv4 connection tracking code.
*/
Expand Down Expand Up @@ -549,7 +615,6 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb,
{
struct net_bridge_port *p;
struct net_bridge *br;
struct iphdr *iph;
__u32 len = nf_bridge_encap_header_len(skb);

if (unlikely(!pskb_may_pull(skb, len)))
Expand Down Expand Up @@ -578,28 +643,9 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb,

nf_bridge_pull_encap_header_rcsum(skb);

if (!pskb_may_pull(skb, sizeof(struct iphdr)))
goto inhdr_error;

iph = ip_hdr(skb);
if (iph->ihl < 5 || iph->version != 4)
goto inhdr_error;

if (!pskb_may_pull(skb, 4 * iph->ihl))
goto inhdr_error;

iph = ip_hdr(skb);
if (ip_fast_csum((__u8 *) iph, iph->ihl) != 0)
goto inhdr_error;

len = ntohs(iph->tot_len);
if (skb->len < len || len < 4 * iph->ihl)
goto inhdr_error;

pskb_trim_rcsum(skb, len);

/* BUG: Should really parse the IP options here. */
memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
if (br_parse_ip_options(skb))
/* Drop invalid packet */
goto out;

nf_bridge_put(skb->nf_bridge);
if (!nf_bridge_alloc(skb))
Expand All @@ -614,8 +660,6 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb,

return NF_STOLEN;

inhdr_error:
// IP_INC_STATS_BH(IpInHdrErrors);
out:
return NF_DROP;
}
Expand Down Expand Up @@ -759,14 +803,19 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff *skb,
#if defined(CONFIG_NF_CONNTRACK_IPV4) || defined(CONFIG_NF_CONNTRACK_IPV4_MODULE)
static int br_nf_dev_queue_xmit(struct sk_buff *skb)
{
int ret;

if (skb->nfct != NULL && skb->protocol == htons(ETH_P_IP) &&
skb->len + nf_bridge_mtu_reduction(skb) > skb->dev->mtu &&
!skb_is_gso(skb)) {
/* BUG: Should really parse the IP options here. */
memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
return ip_fragment(skb, br_dev_queue_push_xmit);
if (br_parse_ip_options(skb))
/* Drop invalid packet */
return NF_DROP;
ret = ip_fragment(skb, br_dev_queue_push_xmit);
} else
return br_dev_queue_push_xmit(skb);
ret = br_dev_queue_push_xmit(skb);

return ret;
}
#else
static int br_nf_dev_queue_xmit(struct sk_buff *skb)
Expand Down
3 changes: 2 additions & 1 deletion trunk/net/ipv4/ip_options.c
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ int ip_options_compile(struct net *net,
}
return -EINVAL;
}

EXPORT_SYMBOL(ip_options_compile);

/*
* Undo all the changes done by ip_options_compile().
Expand Down Expand Up @@ -646,3 +646,4 @@ int ip_options_rcv_srr(struct sk_buff *skb)
}
return 0;
}
EXPORT_SYMBOL(ip_options_rcv_srr);

0 comments on commit 339dc1a

Please sign in to comment.