diff options
36 files changed, 268 insertions, 137 deletions
diff --git a/Documentation/networking/phonet.txt b/Documentation/networking/phonet.txt index 0e6e592f4f5..6a07e45d4a9 100644 --- a/Documentation/networking/phonet.txt +++ b/Documentation/networking/phonet.txt @@ -146,8 +146,8 @@ WARNING:  When polling a connected pipe socket for writability, there is an  intrinsic race condition whereby writability might be lost between the  polling and the writing system calls. In this case, the socket will -block until write because possible again, unless non-blocking mode -becomes enabled. +block until write becomes possible again, unless non-blocking mode +is enabled.  The pipe protocol provides two socket options at the SOL_PNPIPE level: diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 74726990d59..f05f584ab7b 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1640,6 +1640,11 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,  	return ret;  } +static int ath9k_no_fragmentation(struct ieee80211_hw *hw, u32 value) +{ +	return -EOPNOTSUPP; +} +  static struct ieee80211_ops ath9k_ops = {  	.tx 		    = ath9k_tx,  	.start 		    = ath9k_start, @@ -1664,7 +1669,8 @@ static struct ieee80211_ops ath9k_ops = {  	.get_tsf 	    = ath9k_get_tsf,  	.reset_tsf 	    = ath9k_reset_tsf,  	.tx_last_beacon     = NULL, -	.ampdu_action       = ath9k_ampdu_action +	.ampdu_action       = ath9k_ampdu_action, +	.set_frag_threshold = ath9k_no_fragmentation,  };  static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index f6003e7996a..5155b8a760a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -833,12 +833,12 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)  	switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {  	case CSR_HW_REV_TYPE_5100:  	case CSR_HW_REV_TYPE_5300: -		/* 5X00 wants in Celsius */ +	case CSR_HW_REV_TYPE_5350: +		/* 5X00 and 5350 wants in Celsius */  		priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;  		break;  	case CSR_HW_REV_TYPE_5150: -	case CSR_HW_REV_TYPE_5350: -		/* 5X50 wants in Kelvin */ +		/* 5150 wants in Kelvin */  		priv->hw_params.ct_kill_threshold =  				CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD);  		break; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 93944de923c..e2a58e47703 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2422,7 +2422,7 @@ static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta,  			void *priv_sta)  {  	struct iwl_lq_sta *lq_sta = priv_sta; -	struct iwl_priv *priv = priv_r; +	struct iwl_priv *priv __maybe_unused = priv_r;  	IWL_DEBUG_RATE("enter\n");  	kfree(lq_sta); diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index a912fb68c09..297696de2da 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -823,7 +823,9 @@ int lbs_update_channel(struct lbs_private *priv)  int lbs_set_channel(struct lbs_private *priv, u8 channel)  {  	struct cmd_ds_802_11_rf_channel cmd; +#ifdef DEBUG  	u8 old_channel = priv->curbssparams.channel; +#endif  	int ret = 0;  	lbs_deb_enter(LBS_DEB_CMD); diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index e585684e59a..6fcf2bda7cd 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -378,6 +378,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link)  	struct orinoco_private *priv = netdev_priv(dev);  	struct orinoco_pccard *card = priv->card;  	int err = 0; +	unsigned long flags;  	if (! test_bit(0, &card->hard_reset_in_progress)) {  		err = orinoco_reinit_firmware(dev); @@ -387,7 +388,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link)  			return -EIO;  		} -		spin_lock(&priv->lock); +		spin_lock_irqsave(&priv->lock, flags);  		netif_device_attach(dev);  		priv->hw_unavailable--; @@ -399,7 +400,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link)  				       dev->name, err);  		} -		spin_unlock(&priv->lock); +		spin_unlock_irqrestore(&priv->lock, flags);  	}  	return err; diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 1994aa199d3..117c7d3a52b 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -479,7 +479,6 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)  	printk(KERN_ERR "p54: eeprom parse failed!\n");  	return err;  } -EXPORT_SYMBOL_GPL(p54_parse_eeprom);  static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi)  { diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 1912f5e9a0a..75d749bccb0 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -39,6 +39,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {  	{USB_DEVICE(0x0846, 0x4200)},	/* Netgear WG121 */  	{USB_DEVICE(0x0846, 0x4210)},	/* Netgear WG121 the second ? */  	{USB_DEVICE(0x0846, 0x4220)},	/* Netgear WG111 */ +	{USB_DEVICE(0x09aa, 0x1000)},	/* Spinnaker Proto board */  	{USB_DEVICE(0x0cde, 0x0006)},	/* Medion 40900, Roper Europe */  	{USB_DEVICE(0x124a, 0x4023)},	/* Shuttle PN15, Airvast WM168g, IOGear GWU513 */  	{USB_DEVICE(0x1915, 0x2234)},	/* Linksys WUSB54G OEM */ @@ -63,8 +64,8 @@ static struct usb_device_id p54u_table[] __devinitdata = {  	{USB_DEVICE(0x0cde, 0x0006)},   /* Medion MD40900 */  	{USB_DEVICE(0x0cde, 0x0008)},	/* Sagem XG703A */  	{USB_DEVICE(0x0d8e, 0x3762)},	/* DLink DWL-G120 Cohiba */ -	{USB_DEVICE(0x09aa, 0x1000)},	/* Spinnaker Proto board */  	{USB_DEVICE(0x124a, 0x4025)},	/* IOGear GWU513 (GW3887IK chip) */ +	{USB_DEVICE(0x1260, 0xee22)},	/* SMC 2862W-G version 2 */  	{USB_DEVICE(0x13b1, 0x000a)},	/* Linksys WUSB54G ver 2 */  	{USB_DEVICE(0x13B1, 0x000C)},	/* Linksys WUSB54AG */  	{USB_DEVICE(0x1435, 0x0427)},	/* Inventel UR054G */ diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 1676ac48479..451d410ecda 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -374,7 +374,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)  	struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);  	struct txentry_desc txdesc;  	struct skb_frame_desc *skbdesc; -	unsigned int iv_len; +	unsigned int iv_len = 0;  	if (unlikely(rt2x00queue_full(queue)))  		return -EINVAL; @@ -395,6 +395,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)  	entry->skb = skb;  	rt2x00queue_create_tx_descriptor(entry, &txdesc); +	if (IEEE80211_SKB_CB(skb)->control.hw_key != NULL) +		iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len; +  	/*  	 * All information is retreived from the skb->cb array,  	 * now we should claim ownership of the driver part of that @@ -410,9 +413,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)  	 * the frame so we can provide it to the driver seperately.  	 */  	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && -	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags) && -		(IEEE80211_SKB_CB(skb)->control.hw_key != NULL)) { -		iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len; +	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {  		rt2x00crypto_tx_remove_iv(skb, iv_len);  	} diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index e9902613e2e..431e3c78bf2 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -33,10 +33,13 @@ MODULE_LICENSE("GPL");  static struct usb_device_id rtl8187_table[] __devinitdata = {  	/* Asus */  	{USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187}, +	/* Belkin */ +	{USB_DEVICE(0x050d, 0x705e), .driver_info = DEVICE_RTL8187B},  	/* Realtek */  	{USB_DEVICE(0x0bda, 0x8187), .driver_info = DEVICE_RTL8187},  	{USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B},  	{USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B}, +	{USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B},  	/* Netgear */  	{USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187},  	{USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index b0c71c3be46..852789ad34b 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c @@ -426,10 +426,11 @@ spectrum_cs_suspend(struct pcmcia_device *link)  {  	struct net_device *dev = link->priv;  	struct orinoco_private *priv = netdev_priv(dev); +	unsigned long flags;  	int err = 0;  	/* Mark the device as stopped, to block IO until later */ -	spin_lock(&priv->lock); +	spin_lock_irqsave(&priv->lock, flags);  	err = __orinoco_down(dev);  	if (err) @@ -439,7 +440,7 @@ spectrum_cs_suspend(struct pcmcia_device *link)  	netif_device_detach(dev);  	priv->hw_unavailable++; -	spin_unlock(&priv->lock); +	spin_unlock_irqrestore(&priv->lock, flags);  	return err;  } diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h index 03067443198..a93a8dd3311 100644 --- a/include/linux/icmpv6.h +++ b/include/linux/icmpv6.h @@ -40,16 +40,18 @@ struct icmp6hdr {                  struct icmpv6_nd_ra {  			__u8		hop_limit;  #if defined(__LITTLE_ENDIAN_BITFIELD) -			__u8		reserved:4, +			__u8		reserved:3,  					router_pref:2, +					home_agent:1,  					other:1,  					managed:1;  #elif defined(__BIG_ENDIAN_BITFIELD)  			__u8		managed:1,  					other:1, +					home_agent:1,  					router_pref:2, -					reserved:4; +					reserved:3;  #else  #error	"Please fix <asm/byteorder.h>"  #endif diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index 0d8424f7689..7d8e0455cca 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -78,6 +78,9 @@ extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group,  			  int echo);  extern int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags); +extern void nfnl_lock(void); +extern void nfnl_unlock(void); +  #define MODULE_ALIAS_NFNL_SUBSYS(subsys) \  	MODULE_ALIAS("nfnetlink-subsys-" __stringify(subsys)) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 5617a1613c9..d861197f83c 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -645,7 +645,8 @@ enum ieee80211_key_flags {   * 	- Temporal Encryption Key (128 bits)   * 	- Temporal Authenticator Tx MIC Key (64 bits)   * 	- Temporal Authenticator Rx MIC Key (64 bits) - * + * @icv_len: FIXME + * @iv_len: FIXME   */  struct ieee80211_key_conf {  	enum ieee80211_key_alg alg; diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h index f29eeb9777e..58684066388 100644 --- a/include/net/netfilter/nf_nat_core.h +++ b/include/net/netfilter/nf_nat_core.h @@ -25,4 +25,12 @@ static inline int nf_nat_initialized(struct nf_conn *ct,  	else  		return test_bit(IPS_DST_NAT_DONE_BIT, &ct->status);  } + +struct nlattr; + +extern int +(*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct, +				  enum nf_nat_manip_type manip, +				  struct nlattr *attr); +  #endif /* _NF_NAT_CORE_H */ diff --git a/net/802/fc.c b/net/802/fc.c index cb3475ea6fd..34cf1ee014b 100644 --- a/net/802/fc.c +++ b/net/802/fc.c @@ -82,13 +82,13 @@ static int fc_header(struct sk_buff *skb, struct net_device *dev,  static int fc_rebuild_header(struct sk_buff *skb)  { +#ifdef CONFIG_INET  	struct fch_hdr *fch=(struct fch_hdr *)skb->data;  	struct fcllc *fcllc=(struct fcllc *)(skb->data+sizeof(struct fch_hdr));  	if(fcllc->ethertype != htons(ETH_P_IP)) {  		printk("fc_rebuild_header: Don't know how to resolve type %04X addresses ?\n", ntohs(fcllc->ethertype));  		return 0;  	} -#ifdef CONFIG_INET  	return arp_find(fch->daddr, skb);  #else  	return 0; diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig index 366d3e9d51f..ba6f73eb06c 100644 --- a/net/bridge/netfilter/Kconfig +++ b/net/bridge/netfilter/Kconfig @@ -4,6 +4,7 @@  menuconfig BRIDGE_NF_EBTABLES  	tristate "Ethernet Bridge tables (ebtables) support" +	depends on BRIDGE && BRIDGE_NETFILTER  	select NETFILTER_XTABLES  	help  	  ebtables is a general, extensible frame/packet identification diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index b0dc818a91d..f1d07b5c1e1 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -96,7 +96,7 @@ static void net_free(struct net *net)  		return;  	}  #endif - +	kfree(net->gen);  	kmem_cache_free(net_cachep, net);  } diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 96f9fcef295..8008c861302 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -152,7 +152,7 @@ static struct dn_dev_parms dn_dev_list[] =  {  #define DN_DEV_LIST_SIZE ARRAY_SIZE(dn_dev_list) -#define DN_DEV_PARMS_OFFSET(x) ((int) ((char *) &((struct dn_dev_parms *)0)->x)) +#define DN_DEV_PARMS_OFFSET(x) offsetof(struct dn_dev_parms, x)  #ifdef CONFIG_SYSCTL diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index aa2c50a180f..fa2d6b6fc3e 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c @@ -41,12 +41,13 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,  					  int (*okfn)(struct sk_buff *))  {  #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) +#if !defined(CONFIG_NF_NAT) && !defined(CONFIG_NF_NAT_MODULE)  	/* Previously seen (loopback)?  Ignore.  Do this before  	   fragment check. */  	if (skb->nfct)  		return NF_ACCEPT;  #endif - +#endif  	/* Gather fragments. */  	if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {  		if (nf_ct_ipv4_gather_frags(skb, diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 2ac9eaf1a8c..a65cf692359 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -584,6 +584,98 @@ static struct nf_ct_ext_type nat_extend __read_mostly = {  	.flags		= NF_CT_EXT_F_PREALLOC,  }; +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) + +#include <linux/netfilter/nfnetlink.h> +#include <linux/netfilter/nfnetlink_conntrack.h> + +static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = { +	[CTA_PROTONAT_PORT_MIN]	= { .type = NLA_U16 }, +	[CTA_PROTONAT_PORT_MAX]	= { .type = NLA_U16 }, +}; + +static int nfnetlink_parse_nat_proto(struct nlattr *attr, +				     const struct nf_conn *ct, +				     struct nf_nat_range *range) +{ +	struct nlattr *tb[CTA_PROTONAT_MAX+1]; +	const struct nf_nat_protocol *npt; +	int err; + +	err = nla_parse_nested(tb, CTA_PROTONAT_MAX, attr, protonat_nla_policy); +	if (err < 0) +		return err; + +	npt = nf_nat_proto_find_get(nf_ct_protonum(ct)); +	if (npt->nlattr_to_range) +		err = npt->nlattr_to_range(tb, range); +	nf_nat_proto_put(npt); +	return err; +} + +static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = { +	[CTA_NAT_MINIP]		= { .type = NLA_U32 }, +	[CTA_NAT_MAXIP]		= { .type = NLA_U32 }, +}; + +static int +nfnetlink_parse_nat(struct nlattr *nat, +		    const struct nf_conn *ct, struct nf_nat_range *range) +{ +	struct nlattr *tb[CTA_NAT_MAX+1]; +	int err; + +	memset(range, 0, sizeof(*range)); + +	err = nla_parse_nested(tb, CTA_NAT_MAX, nat, nat_nla_policy); +	if (err < 0) +		return err; + +	if (tb[CTA_NAT_MINIP]) +		range->min_ip = nla_get_be32(tb[CTA_NAT_MINIP]); + +	if (!tb[CTA_NAT_MAXIP]) +		range->max_ip = range->min_ip; +	else +		range->max_ip = nla_get_be32(tb[CTA_NAT_MAXIP]); + +	if (range->min_ip) +		range->flags |= IP_NAT_RANGE_MAP_IPS; + +	if (!tb[CTA_NAT_PROTO]) +		return 0; + +	err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range); +	if (err < 0) +		return err; + +	return 0; +} + +static int +nfnetlink_parse_nat_setup(struct nf_conn *ct, +			  enum nf_nat_manip_type manip, +			  struct nlattr *attr) +{ +	struct nf_nat_range range; + +	if (nfnetlink_parse_nat(attr, ct, &range) < 0) +		return -EINVAL; +	if (nf_nat_initialized(ct, manip)) +		return -EEXIST; + +	return nf_nat_setup_info(ct, &range, manip); +} +#else +static int +nfnetlink_parse_nat_setup(struct nf_conn *ct, +			  enum nf_nat_manip_type manip, +			  struct nlattr *attr) +{ +	return -EOPNOTSUPP; +} +#endif +  static int __net_init nf_nat_net_init(struct net *net)  {  	net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size, @@ -654,6 +746,9 @@ static int __init nf_nat_init(void)  	BUG_ON(nf_nat_seq_adjust_hook != NULL);  	rcu_assign_pointer(nf_nat_seq_adjust_hook, nf_nat_seq_adjust); +	BUG_ON(nfnetlink_parse_nat_setup_hook != NULL); +	rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, +			   nfnetlink_parse_nat_setup);  	return 0;   cleanup_extend: @@ -667,10 +762,12 @@ static void __exit nf_nat_cleanup(void)  	nf_ct_l3proto_put(l3proto);  	nf_ct_extend_unregister(&nat_extend);  	rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL); +	rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, NULL);  	synchronize_net();  }  MODULE_LICENSE("GPL"); +MODULE_ALIAS("nf-nat-ipv4");  module_init(nf_nat_init);  module_exit(nf_nat_cleanup); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 7f39e9b3645..172438320ee 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1199,7 +1199,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)  		}  		neigh->flags |= NTF_ROUTER;  	} else if (rt) { -		rt->rt6i_flags |= (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); +		rt->rt6i_flags = (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);  	}  	if (rt) diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 6b29b03925f..fd5b3a4e332 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -12,6 +12,7 @@  int ip6_route_me_harder(struct sk_buff *skb)  { +	struct net *net = dev_net(skb->dst->dev);  	struct ipv6hdr *iph = ipv6_hdr(skb);  	struct dst_entry *dst;  	struct flowi fl = { @@ -23,7 +24,7 @@ int ip6_route_me_harder(struct sk_buff *skb)  		    .saddr = iph->saddr, } },  	}; -	dst = ip6_route_output(dev_net(skb->dst->dev), skb->sk, &fl); +	dst = ip6_route_output(net, skb->sk, &fl);  #ifdef CONFIG_XFRM  	if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && @@ -33,8 +34,7 @@ int ip6_route_me_harder(struct sk_buff *skb)  #endif  	if (dst->error) { -		IP6_INC_STATS(&init_net, ip6_dst_idev(dst), -			      IPSTATS_MIB_OUTNOROUTES); +		IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);  		LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n");  		dst_release(dst);  		return -EINVAL; diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 2a451562377..2ad504fc341 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -545,8 +545,12 @@ static int netdev_notify(struct notifier_block *nb,  	sdata = IEEE80211_DEV_TO_SUB_IF(dev); -	sprintf(buf, "netdev:%s", dev->name);  	dir = sdata->debugfsdir; + +	if (!dir) +		return 0; + +	sprintf(buf, "netdev:%s", dev->name);  	if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf))  		printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs "  		       "dir to %s\n", buf); diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index b9902e425f0..189d0bafa91 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -249,11 +249,22 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)  	DECLARE_MAC_BUF(mbuf);  	u8 *mac; +	sta->debugfs.add_has_run = true; +  	if (!stations_dir)  		return;  	mac = print_mac(mbuf, sta->sta.addr); +	/* +	 * This might fail due to a race condition: +	 * When mac80211 unlinks a station, the debugfs entries +	 * remain, but it is already possible to link a new +	 * station with the same address which triggers adding +	 * it to debugfs; therefore, if the old station isn't +	 * destroyed quickly enough the old station's debugfs +	 * dir might still be around. +	 */  	sta->debugfs.dir = debugfs_create_dir(mac, stations_dir);  	if (!sta->debugfs.dir)  		return; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8025b294588..156e42a003a 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -816,8 +816,8 @@ struct ieee802_11_elems {  	u8 *ext_supp_rates;  	u8 *wmm_info;  	u8 *wmm_param; -	u8 *ht_cap_elem; -	u8 *ht_info_elem; +	struct ieee80211_ht_cap *ht_cap_elem; +	struct ieee80211_ht_addt_info *ht_info_elem;  	u8 *mesh_config;  	u8 *mesh_id;  	u8 *peer_link; @@ -844,8 +844,6 @@ struct ieee802_11_elems {  	u8 ext_supp_rates_len;  	u8 wmm_info_len;  	u8 wmm_param_len; -	u8 ht_cap_elem_len; -	u8 ht_info_elem_len;  	u8 mesh_config_len;  	u8 mesh_id_len;  	u8 peer_link_len; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 49f86fa56bf..87665d7bb4f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1348,10 +1348,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,  	    (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {  		struct ieee80211_ht_bss_info bss_info;  		ieee80211_ht_cap_ie_to_ht_info( -				(struct ieee80211_ht_cap *)  				elems.ht_cap_elem, &sta->sta.ht_info);  		ieee80211_ht_addt_info_ie_to_ht_bss_info( -				(struct ieee80211_ht_addt_info *)  				elems.ht_info_elem, &bss_info);  		ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info);  	} @@ -1709,7 +1707,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,  		struct ieee80211_ht_bss_info bss_info;  		ieee80211_ht_addt_info_ie_to_ht_bss_info( -				(struct ieee80211_ht_addt_info *)  				elems.ht_info_elem, &bss_info);  		changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf,  					       &bss_info); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 8e6685e7ae8..416bb41099f 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -388,7 +388,8 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,  	bss = ieee80211_bss_info_update(sdata->local, rx_status,  					mgmt, skb->len, &elems,  					freq, beacon); -	ieee80211_rx_bss_put(sdata->local, bss); +	if (bss) +		ieee80211_rx_bss_put(sdata->local, bss);  	dev_kfree_skb(skb);  	return RX_QUEUED; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 9b72d15bc8d..7fef8ea1f5e 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -635,7 +635,12 @@ static void sta_info_debugfs_add_work(struct work_struct *work)  		spin_lock_irqsave(&local->sta_lock, flags);  		list_for_each_entry(tmp, &local->sta_list, list) { -			if (!tmp->debugfs.dir) { +			/* +			 * debugfs.add_has_run will be set by +			 * ieee80211_sta_debugfs_add regardless +			 * of what else it does. +			 */ +			if (!tmp->debugfs.add_has_run) {  				sta = tmp;  				__sta_info_pin(sta);  				break; diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index a6b51862a89..168a39a298b 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -300,6 +300,7 @@ struct sta_info {  		struct dentry *inactive_ms;  		struct dentry *last_seq_ctrl;  		struct dentry *agg_status; +		bool add_has_run;  	} debugfs;  #endif diff --git a/net/mac80211/util.c b/net/mac80211/util.c index f32561ec224..cee4884b9d0 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -529,12 +529,12 @@ void ieee802_11_parse_elems(u8 *start, size_t len,  			elems->ext_supp_rates_len = elen;  			break;  		case WLAN_EID_HT_CAPABILITY: -			elems->ht_cap_elem = pos; -			elems->ht_cap_elem_len = elen; +			if (elen >= sizeof(struct ieee80211_ht_cap)) +				elems->ht_cap_elem = (void *)pos;  			break;  		case WLAN_EID_HT_EXTRA_INFO: -			elems->ht_info_elem = pos; -			elems->ht_info_elem_len = elen; +			if (elen >= sizeof(struct ieee80211_ht_addt_info)) +				elems->ht_info_elem = (void *)pos;  			break;  		case WLAN_EID_MESH_ID:  			elems->mesh_id = pos; diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 7e0d53abde2..742f811ca41 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -775,7 +775,7 @@ static int ieee80211_ioctl_siwfrag(struct net_device *dev,  	 * configure it here */  	if (local->ops->set_frag_threshold) -		local->ops->set_frag_threshold( +		return local->ops->set_frag_threshold(  			local_to_hw(local),  			local->fragmentation_threshold); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 27de3c7b006..622d7c671cb 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -38,9 +38,16 @@  #include <net/netfilter/nf_conntrack_core.h>  #include <net/netfilter/nf_conntrack_extend.h>  #include <net/netfilter/nf_conntrack_acct.h> +#include <net/netfilter/nf_nat.h>  #define NF_CONNTRACK_VERSION	"0.5.0" +unsigned int +(*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct, +				  enum nf_nat_manip_type manip, +				  struct nlattr *attr) __read_mostly; +EXPORT_SYMBOL_GPL(nfnetlink_parse_nat_setup_hook); +  DEFINE_SPINLOCK(nf_conntrack_lock);  EXPORT_SYMBOL_GPL(nf_conntrack_lock); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index cadfd15b44f..08e82d64eb6 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -689,71 +689,6 @@ ctnetlink_parse_tuple(struct nlattr *cda[], struct nf_conntrack_tuple *tuple,  	return 0;  } -#ifdef CONFIG_NF_NAT_NEEDED -static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = { -	[CTA_PROTONAT_PORT_MIN]	= { .type = NLA_U16 }, -	[CTA_PROTONAT_PORT_MAX]	= { .type = NLA_U16 }, -}; - -static int nfnetlink_parse_nat_proto(struct nlattr *attr, -				     const struct nf_conn *ct, -				     struct nf_nat_range *range) -{ -	struct nlattr *tb[CTA_PROTONAT_MAX+1]; -	const struct nf_nat_protocol *npt; -	int err; - -	err = nla_parse_nested(tb, CTA_PROTONAT_MAX, attr, protonat_nla_policy); -	if (err < 0) -		return err; - -	npt = nf_nat_proto_find_get(nf_ct_protonum(ct)); -	if (npt->nlattr_to_range) -		err = npt->nlattr_to_range(tb, range); -	nf_nat_proto_put(npt); -	return err; -} - -static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = { -	[CTA_NAT_MINIP]		= { .type = NLA_U32 }, -	[CTA_NAT_MAXIP]		= { .type = NLA_U32 }, -}; - -static inline int -nfnetlink_parse_nat(struct nlattr *nat, -		    const struct nf_conn *ct, struct nf_nat_range *range) -{ -	struct nlattr *tb[CTA_NAT_MAX+1]; -	int err; - -	memset(range, 0, sizeof(*range)); - -	err = nla_parse_nested(tb, CTA_NAT_MAX, nat, nat_nla_policy); -	if (err < 0) -		return err; - -	if (tb[CTA_NAT_MINIP]) -		range->min_ip = nla_get_be32(tb[CTA_NAT_MINIP]); - -	if (!tb[CTA_NAT_MAXIP]) -		range->max_ip = range->min_ip; -	else -		range->max_ip = nla_get_be32(tb[CTA_NAT_MAXIP]); - -	if (range->min_ip) -		range->flags |= IP_NAT_RANGE_MAP_IPS; - -	if (!tb[CTA_NAT_PROTO]) -		return 0; - -	err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range); -	if (err < 0) -		return err; - -	return 0; -} -#endif -  static inline int  ctnetlink_parse_help(struct nlattr *attr, char **helper_name)  { @@ -879,6 +814,34 @@ out:  }  static int +ctnetlink_parse_nat_setup(struct nf_conn *ct, +			  enum nf_nat_manip_type manip, +			  struct nlattr *attr) +{ +	typeof(nfnetlink_parse_nat_setup_hook) parse_nat_setup; + +	parse_nat_setup = rcu_dereference(nfnetlink_parse_nat_setup_hook); +	if (!parse_nat_setup) { +#ifdef CONFIG_KMOD +		rcu_read_unlock(); +		nfnl_unlock(); +		if (request_module("nf-nat-ipv4") < 0) { +			nfnl_lock(); +			rcu_read_lock(); +			return -EOPNOTSUPP; +		} +		nfnl_lock(); +		rcu_read_lock(); +		if (nfnetlink_parse_nat_setup_hook) +			return -EAGAIN; +#endif +		return -EOPNOTSUPP; +	} + +	return parse_nat_setup(ct, manip, attr); +} + +static int  ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])  {  	unsigned long d; @@ -897,31 +860,6 @@ ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])  		/* ASSURED bit can only be set */  		return -EBUSY; -	if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { -#ifndef CONFIG_NF_NAT_NEEDED -		return -EOPNOTSUPP; -#else -		struct nf_nat_range range; - -		if (cda[CTA_NAT_DST]) { -			if (nfnetlink_parse_nat(cda[CTA_NAT_DST], ct, -						&range) < 0) -				return -EINVAL; -			if (nf_nat_initialized(ct, IP_NAT_MANIP_DST)) -				return -EEXIST; -			nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); -		} -		if (cda[CTA_NAT_SRC]) { -			if (nfnetlink_parse_nat(cda[CTA_NAT_SRC], ct, -						&range) < 0) -				return -EINVAL; -			if (nf_nat_initialized(ct, IP_NAT_MANIP_SRC)) -				return -EEXIST; -			nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); -		} -#endif -	} -  	/* Be careful here, modifying NAT bits can screw up things,  	 * so don't let users modify them directly if they don't pass  	 * nf_nat_range. */ @@ -929,6 +867,31 @@ ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])  	return 0;  } +static int +ctnetlink_change_nat(struct nf_conn *ct, struct nlattr *cda[]) +{ +#ifdef CONFIG_NF_NAT_NEEDED +	int ret; + +	if (cda[CTA_NAT_DST]) { +		ret = ctnetlink_parse_nat_setup(ct, +						IP_NAT_MANIP_DST, +						cda[CTA_NAT_DST]); +		if (ret < 0) +			return ret; +	} +	if (cda[CTA_NAT_SRC]) { +		ret = ctnetlink_parse_nat_setup(ct, +						IP_NAT_MANIP_SRC, +						cda[CTA_NAT_SRC]); +		if (ret < 0) +			return ret; +	} +	return 0; +#else +	return -EOPNOTSUPP; +#endif +}  static inline int  ctnetlink_change_helper(struct nf_conn *ct, struct nlattr *cda[]) @@ -1157,6 +1120,14 @@ ctnetlink_create_conntrack(struct nlattr *cda[],  		}  	} +	if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { +		err = ctnetlink_change_nat(ct, cda); +		if (err < 0) { +			rcu_read_unlock(); +			goto err; +		} +	} +  	if (cda[CTA_PROTOINFO]) {  		err = ctnetlink_change_protoinfo(ct, cda);  		if (err < 0) { diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index b75c9c4a995..4739f9f961d 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -44,15 +44,17 @@ static struct sock *nfnl = NULL;  static const struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT];  static DEFINE_MUTEX(nfnl_mutex); -static inline void nfnl_lock(void) +void nfnl_lock(void)  {  	mutex_lock(&nfnl_mutex);  } +EXPORT_SYMBOL_GPL(nfnl_lock); -static inline void nfnl_unlock(void) +void nfnl_unlock(void)  {  	mutex_unlock(&nfnl_mutex);  } +EXPORT_SYMBOL_GPL(nfnl_unlock);  int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)  { @@ -132,6 +134,7 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  		return 0;  	type = nlh->nlmsg_type; +replay:  	ss = nfnetlink_get_subsys(type);  	if (!ss) {  #ifdef CONFIG_KMOD @@ -165,7 +168,10 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  		} else  			return -EINVAL; -		return nc->call(nfnl, skb, nlh, cda); +		err = nc->call(nfnl, skb, nlh, cda); +		if (err == -EAGAIN) +			goto replay; +		return err;  	}  } diff --git a/net/wireless/core.c b/net/wireless/core.c index 24fdd4cd22c..5031db7b275 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -184,7 +184,8 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,  	if (result)  		goto out_unlock; -	if (!debugfs_rename(rdev->wiphy.debugfsdir->d_parent, +	if (rdev->wiphy.debugfsdir && +	    !debugfs_rename(rdev->wiphy.debugfsdir->d_parent,  			    rdev->wiphy.debugfsdir,  			    rdev->wiphy.debugfsdir->d_parent,  			    newname)) @@ -317,6 +318,8 @@ int wiphy_register(struct wiphy *wiphy)  	drv->wiphy.debugfsdir =  		debugfs_create_dir(wiphy_name(&drv->wiphy),  				   ieee80211_debugfs_dir); +	if (IS_ERR(drv->wiphy.debugfsdir)) +		drv->wiphy.debugfsdir = NULL;  	res = 0;  out_unlock:  |