diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/core/dev.c | 1 | ||||
| -rw-r--r-- | net/core/skbuff.c | 7 | ||||
| -rw-r--r-- | net/ipv6/addrconf.c | 14 | ||||
| -rw-r--r-- | net/mac80211/cfg.c | 2 | ||||
| -rw-r--r-- | net/sched/act_mirred.c | 43 | 
5 files changed, 56 insertions, 11 deletions
| diff --git a/net/core/dev.c b/net/core/dev.c index 0ea10f849be8..1f466e82ac33 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1488,6 +1488,7 @@ static inline void net_timestamp_check(struct sk_buff *skb)  int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)  {  	skb_orphan(skb); +	nf_reset(skb);  	if (!(dev->flags & IFF_UP) ||  	    (skb->len > (dev->mtu + dev->hard_header_len))) { diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 34432b4e96bb..ce88293a34e2 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -843,7 +843,9 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,  	skb->network_header   += off;  	if (skb_mac_header_was_set(skb))  		skb->mac_header += off; -	skb->csum_start       += nhead; +	/* Only adjust this if it actually is csum_start rather than csum */ +	if (skb->ip_summed == CHECKSUM_PARTIAL) +		skb->csum_start += nhead;  	skb->cloned   = 0;  	skb->hdr_len  = 0;  	skb->nohdr    = 0; @@ -930,7 +932,8 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb,  	copy_skb_header(n, skb);  	off                  = newheadroom - oldheadroom; -	n->csum_start       += off; +	if (n->ip_summed == CHECKSUM_PARTIAL) +		n->csum_start += off;  #ifdef NET_SKBUFF_DATA_USES_OFFSET  	n->transport_header += off;  	n->network_header   += off; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e1a698df5706..784f34d11fdd 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1760,7 +1760,10 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev)  	idev = ipv6_find_idev(dev);  	if (!idev) -		return NULL; +		return ERR_PTR(-ENOBUFS); + +	if (idev->cnf.disable_ipv6) +		return ERR_PTR(-EACCES);  	/* Add default multicast route */  	addrconf_add_mroute(dev); @@ -2129,8 +2132,9 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx,  	if (!dev)  		return -ENODEV; -	if ((idev = addrconf_add_dev(dev)) == NULL) -		return -ENOBUFS; +	idev = addrconf_add_dev(dev); +	if (IS_ERR(idev)) +		return PTR_ERR(idev);  	scope = ipv6_addr_scope(pfx); @@ -2377,7 +2381,7 @@ static void addrconf_dev_config(struct net_device *dev)  	}  	idev = addrconf_add_dev(dev); -	if (idev == NULL) +	if (IS_ERR(idev))  		return;  	memset(&addr, 0, sizeof(struct in6_addr)); @@ -2468,7 +2472,7 @@ static void addrconf_ip6_tnl_config(struct net_device *dev)  	ASSERT_RTNL();  	idev = addrconf_add_dev(dev); -	if (!idev) { +	if (IS_ERR(idev)) {  		printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n");  		return;  	} diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c7000a6ca379..67ee34f57df7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -632,7 +632,7 @@ static void ieee80211_send_layer2_update(struct sta_info *sta)  	skb->dev = sta->sdata->dev;  	skb->protocol = eth_type_trans(skb, sta->sdata->dev);  	memset(skb->cb, 0, sizeof(skb->cb)); -	netif_rx(skb); +	netif_rx_ni(skb);  }  static void sta_apply_parameters(struct ieee80211_local *local, diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index c0b6863e3b87..1980b71c283f 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c @@ -33,6 +33,7 @@  static struct tcf_common *tcf_mirred_ht[MIRRED_TAB_MASK + 1];  static u32 mirred_idx_gen;  static DEFINE_RWLOCK(mirred_lock); +static LIST_HEAD(mirred_list);  static struct tcf_hashinfo mirred_hash_info = {  	.htab	=	tcf_mirred_ht, @@ -47,7 +48,9 @@ static inline int tcf_mirred_release(struct tcf_mirred *m, int bind)  			m->tcf_bindcnt--;  		m->tcf_refcnt--;  		if(!m->tcf_bindcnt && m->tcf_refcnt <= 0) { -			dev_put(m->tcfm_dev); +			list_del(&m->tcfm_list); +			if (m->tcfm_dev) +				dev_put(m->tcfm_dev);  			tcf_hash_destroy(&m->common, &mirred_hash_info);  			return 1;  		} @@ -134,8 +137,10 @@ static int tcf_mirred_init(struct nlattr *nla, struct nlattr *est,  		m->tcfm_ok_push = ok_push;  	}  	spin_unlock_bh(&m->tcf_lock); -	if (ret == ACT_P_CREATED) +	if (ret == ACT_P_CREATED) { +		list_add(&m->tcfm_list, &mirred_list);  		tcf_hash_insert(pc, &mirred_hash_info); +	}  	return ret;  } @@ -162,9 +167,14 @@ static int tcf_mirred(struct sk_buff *skb, struct tc_action *a,  	m->tcf_tm.lastuse = jiffies;  	dev = m->tcfm_dev; +	if (!dev) { +		printk_once(KERN_NOTICE "tc mirred: target device is gone\n"); +		goto out; +	} +  	if (!(dev->flags & IFF_UP)) {  		if (net_ratelimit()) -			pr_notice("tc mirred to Houston: device %s is gone!\n", +			pr_notice("tc mirred to Houston: device %s is down\n",  				  dev->name);  		goto out;  	} @@ -232,6 +242,28 @@ nla_put_failure:  	return -1;  } +static int mirred_device_event(struct notifier_block *unused, +			       unsigned long event, void *ptr) +{ +	struct net_device *dev = ptr; +	struct tcf_mirred *m; + +	if (event == NETDEV_UNREGISTER) +		list_for_each_entry(m, &mirred_list, tcfm_list) { +			if (m->tcfm_dev == dev) { +				dev_put(dev); +				m->tcfm_dev = NULL; +			} +		} + +	return NOTIFY_DONE; +} + +static struct notifier_block mirred_device_notifier = { +	.notifier_call = mirred_device_event, +}; + +  static struct tc_action_ops act_mirred_ops = {  	.kind		=	"mirred",  	.hinfo		=	&mirred_hash_info, @@ -252,12 +284,17 @@ MODULE_LICENSE("GPL");  static int __init mirred_init_module(void)  { +	int err = register_netdevice_notifier(&mirred_device_notifier); +	if (err) +		return err; +  	pr_info("Mirror/redirect action on\n");  	return tcf_register_action(&act_mirred_ops);  }  static void __exit mirred_cleanup_module(void)  { +	unregister_netdevice_notifier(&mirred_device_notifier);  	tcf_unregister_action(&act_mirred_ops);  } | 
