diff options
Diffstat (limited to 'net')
514 files changed, 2079 insertions, 833 deletions
diff --git a/net/802/garp.c b/net/802/garp.c index 1dcb0660c49..9ed7c0e7dc1 100644 --- a/net/802/garp.c +++ b/net/802/garp.c @@ -14,6 +14,7 @@  #include <linux/etherdevice.h>  #include <linux/rtnetlink.h>  #include <linux/llc.h> +#include <linux/slab.h>  #include <net/llc.h>  #include <net/llc_pdu.h>  #include <net/garp.h> diff --git a/net/802/p8022.c b/net/802/p8022.c index 2530f35241c..7f353c4f437 100644 --- a/net/802/p8022.c +++ b/net/802/p8022.c @@ -18,6 +18,7 @@  #include <linux/module.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/datalink.h>  #include <linux/mm.h>  #include <linux/in.h> diff --git a/net/802/p8023.c b/net/802/p8023.c index 6ab1835041a..1256a40da43 100644 --- a/net/802/p8023.c +++ b/net/802/p8023.c @@ -18,6 +18,7 @@  #include <linux/module.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/datalink.h>  #include <net/p8022.h> diff --git a/net/802/psnap.c b/net/802/psnap.c index 6fea0750662..21cde8fd579 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c @@ -14,6 +14,7 @@  #include <linux/module.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/datalink.h>  #include <net/llc.h>  #include <net/psnap.h> diff --git a/net/802/stp.c b/net/802/stp.c index 0b7a24452d1..53c8f77f0cc 100644 --- a/net/802/stp.c +++ b/net/802/stp.c @@ -11,6 +11,7 @@  #include <linux/skbuff.h>  #include <linux/etherdevice.h>  #include <linux/llc.h> +#include <linux/slab.h>  #include <net/llc.h>  #include <net/llc_pdu.h>  #include <net/stp.h> diff --git a/net/802/tr.c b/net/802/tr.c index 44acce47fcd..1c6e596074d 100644 --- a/net/802/tr.c +++ b/net/802/tr.c @@ -36,6 +36,7 @@  #include <linux/seq_file.h>  #include <linux/init.h>  #include <linux/sysctl.h> +#include <linux/slab.h>  #include <net/arp.h>  #include <net/net_namespace.h> diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 453512266ea..97da977c2a2 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -22,6 +22,7 @@  #include <linux/module.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <linux/init.h>  #include <linux/rculist.h>  #include <net/p8022.h> @@ -378,6 +379,8 @@ static void vlan_transfer_features(struct net_device *dev,  #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)  	vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid;  #endif +	vlandev->real_num_tx_queues = dev->real_num_tx_queues; +	BUG_ON(vlandev->real_num_tx_queues > vlandev->num_tx_queues);  	if (old_features != vlandev->features)  		netdev_features_change(vlandev); diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index c0316e0ca6e..c584a0af77d 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -11,7 +11,7 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,  	if (netpoll_rx(skb))  		return NET_RX_DROP; -	if (skb_bond_should_drop(skb)) +	if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))  		goto drop;  	skb->skb_iif = skb->dev->ifindex; @@ -83,7 +83,7 @@ vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp,  {  	struct sk_buff *p; -	if (skb_bond_should_drop(skb)) +	if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))  		goto drop;  	skb->skb_iif = skb->dev->ifindex; diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 9e83272fc5b..29b6348c8d4 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -21,6 +21,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/skbuff.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h> @@ -361,6 +362,14 @@ static netdev_tx_t vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb,  	return ret;  } +static u16 vlan_dev_select_queue(struct net_device *dev, struct sk_buff *skb) +{ +	struct net_device *rdev = vlan_dev_info(dev)->real_dev; +	const struct net_device_ops *ops = rdev->netdev_ops; + +	return ops->ndo_select_queue(rdev, skb); +} +  static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu)  {  	/* TODO: gotta make sure the underlying layer can handle it, @@ -688,7 +697,8 @@ static const struct header_ops vlan_header_ops = {  	.parse	 = eth_header_parse,  }; -static const struct net_device_ops vlan_netdev_ops, vlan_netdev_accel_ops; +static const struct net_device_ops vlan_netdev_ops, vlan_netdev_accel_ops, +		    vlan_netdev_ops_sq, vlan_netdev_accel_ops_sq;  static int vlan_dev_init(struct net_device *dev)  { @@ -722,11 +732,17 @@ static int vlan_dev_init(struct net_device *dev)  	if (real_dev->features & NETIF_F_HW_VLAN_TX) {  		dev->header_ops      = real_dev->header_ops;  		dev->hard_header_len = real_dev->hard_header_len; -		dev->netdev_ops         = &vlan_netdev_accel_ops; +		if (real_dev->netdev_ops->ndo_select_queue) +			dev->netdev_ops = &vlan_netdev_accel_ops_sq; +		else +			dev->netdev_ops = &vlan_netdev_accel_ops;  	} else {  		dev->header_ops      = &vlan_header_ops;  		dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN; -		dev->netdev_ops         = &vlan_netdev_ops; +		if (real_dev->netdev_ops->ndo_select_queue) +			dev->netdev_ops = &vlan_netdev_ops_sq; +		else +			dev->netdev_ops = &vlan_netdev_ops;  	}  	if (is_vlan_dev(real_dev)) @@ -865,6 +881,56 @@ static const struct net_device_ops vlan_netdev_accel_ops = {  #endif  }; +static const struct net_device_ops vlan_netdev_ops_sq = { +	.ndo_select_queue	= vlan_dev_select_queue, +	.ndo_change_mtu		= vlan_dev_change_mtu, +	.ndo_init		= vlan_dev_init, +	.ndo_uninit		= vlan_dev_uninit, +	.ndo_open		= vlan_dev_open, +	.ndo_stop		= vlan_dev_stop, +	.ndo_start_xmit =  vlan_dev_hard_start_xmit, +	.ndo_validate_addr	= eth_validate_addr, +	.ndo_set_mac_address	= vlan_dev_set_mac_address, +	.ndo_set_rx_mode	= vlan_dev_set_rx_mode, +	.ndo_set_multicast_list	= vlan_dev_set_rx_mode, +	.ndo_change_rx_flags	= vlan_dev_change_rx_flags, +	.ndo_do_ioctl		= vlan_dev_ioctl, +	.ndo_neigh_setup	= vlan_dev_neigh_setup, +	.ndo_get_stats		= vlan_dev_get_stats, +#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) +	.ndo_fcoe_ddp_setup	= vlan_dev_fcoe_ddp_setup, +	.ndo_fcoe_ddp_done	= vlan_dev_fcoe_ddp_done, +	.ndo_fcoe_enable	= vlan_dev_fcoe_enable, +	.ndo_fcoe_disable	= vlan_dev_fcoe_disable, +	.ndo_fcoe_get_wwn	= vlan_dev_fcoe_get_wwn, +#endif +}; + +static const struct net_device_ops vlan_netdev_accel_ops_sq = { +	.ndo_select_queue	= vlan_dev_select_queue, +	.ndo_change_mtu		= vlan_dev_change_mtu, +	.ndo_init		= vlan_dev_init, +	.ndo_uninit		= vlan_dev_uninit, +	.ndo_open		= vlan_dev_open, +	.ndo_stop		= vlan_dev_stop, +	.ndo_start_xmit =  vlan_dev_hwaccel_hard_start_xmit, +	.ndo_validate_addr	= eth_validate_addr, +	.ndo_set_mac_address	= vlan_dev_set_mac_address, +	.ndo_set_rx_mode	= vlan_dev_set_rx_mode, +	.ndo_set_multicast_list	= vlan_dev_set_rx_mode, +	.ndo_change_rx_flags	= vlan_dev_change_rx_flags, +	.ndo_do_ioctl		= vlan_dev_ioctl, +	.ndo_neigh_setup	= vlan_dev_neigh_setup, +	.ndo_get_stats		= vlan_dev_get_stats, +#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) +	.ndo_fcoe_ddp_setup	= vlan_dev_fcoe_ddp_setup, +	.ndo_fcoe_ddp_done	= vlan_dev_fcoe_ddp_done, +	.ndo_fcoe_enable	= vlan_dev_fcoe_enable, +	.ndo_fcoe_disable	= vlan_dev_fcoe_disable, +	.ndo_fcoe_get_wwn	= vlan_dev_fcoe_get_wwn, +#endif +}; +  void vlan_setup(struct net_device *dev)  {  	ether_setup(dev); diff --git a/net/9p/client.c b/net/9p/client.c index bde9f3d38c5..0aa79faa985 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -29,6 +29,7 @@  #include <linux/poll.h>  #include <linux/idr.h>  #include <linux/mutex.h> +#include <linux/slab.h>  #include <linux/sched.h>  #include <linux/uaccess.h>  #include <net/9p/9p.h> @@ -60,7 +61,7 @@ static const match_table_t tokens = {  inline int p9_is_proto_dotl(struct p9_client *clnt)  { -	return (clnt->proto_version == p9_proto_2010L); +	return (clnt->proto_version == p9_proto_2000L);  }  EXPORT_SYMBOL(p9_is_proto_dotl); @@ -71,18 +72,19 @@ inline int p9_is_proto_dotu(struct p9_client *clnt)  EXPORT_SYMBOL(p9_is_proto_dotu);  /* Interpret mount option for protocol version */ -static unsigned char get_protocol_version(const substring_t *name) +static int get_protocol_version(const substring_t *name)  { -	unsigned char version = -EINVAL; +	int version = -EINVAL; +  	if (!strncmp("9p2000", name->from, name->to-name->from)) {  		version = p9_proto_legacy;  		P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n");  	} else if (!strncmp("9p2000.u", name->from, name->to-name->from)) {  		version = p9_proto_2000u;  		P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n"); -	} else if (!strncmp("9p2010.L", name->from, name->to-name->from)) { -		version = p9_proto_2010L; -		P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2010.L\n"); +	} else if (!strncmp("9p2000.L", name->from, name->to-name->from)) { +		version = p9_proto_2000L; +		P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.L\n");  	} else {  		P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ",  							name->from); @@ -533,7 +535,12 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)  	P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); -	if (c->status != Connected) +	/* we allow for any status other than disconnected */ +	if (c->status == Disconnected) +		return ERR_PTR(-EIO); + +	/* if status is begin_disconnected we allow only clunk request */ +	if ((c->status == BeginDisconnect) && (type != P9_TCLUNK))  		return ERR_PTR(-EIO);  	if (signal_pending(current)) { @@ -672,9 +679,9 @@ int p9_client_version(struct p9_client *c)  						c->msize, c->proto_version);  	switch (c->proto_version) { -	case p9_proto_2010L: +	case p9_proto_2000L:  		req = p9_client_rpc(c, P9_TVERSION, "ds", -					c->msize, "9P2010.L"); +					c->msize, "9P2000.L");  		break;  	case p9_proto_2000u:  		req = p9_client_rpc(c, P9_TVERSION, "ds", @@ -700,8 +707,8 @@ int p9_client_version(struct p9_client *c)  	}  	P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version); -	if (!strncmp(version, "9P2010.L", 8)) -		c->proto_version = p9_proto_2010L; +	if (!strncmp(version, "9P2000.L", 8)) +		c->proto_version = p9_proto_2000L;  	else if (!strncmp(version, "9P2000.u", 8))  		c->proto_version = p9_proto_2000u;  	else if (!strncmp(version, "9P2000", 6)) @@ -799,8 +806,10 @@ void p9_client_destroy(struct p9_client *clnt)  	v9fs_put_trans(clnt->trans_mod); -	list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) +	list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) { +		printk(KERN_INFO "Found fid %d not clunked\n", fid->fid);  		p9_fid_destroy(fid); +	}  	if (clnt->fidpool)  		p9_idpool_destroy(clnt->fidpool); @@ -818,6 +827,13 @@ void p9_client_disconnect(struct p9_client *clnt)  }  EXPORT_SYMBOL(p9_client_disconnect); +void p9_client_begin_disconnect(struct p9_client *clnt) +{ +	P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); +	clnt->status = BeginDisconnect; +} +EXPORT_SYMBOL(p9_client_begin_disconnect); +  struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,  	char *uname, u32 n_uname, char *aname)  { diff --git a/net/9p/protocol.c b/net/9p/protocol.c index 94f5a8f65e9..e7541d5b011 100644 --- a/net/9p/protocol.c +++ b/net/9p/protocol.c @@ -28,6 +28,7 @@  #include <linux/module.h>  #include <linux/errno.h>  #include <linux/uaccess.h> +#include <linux/slab.h>  #include <linux/sched.h>  #include <linux/types.h>  #include <net/9p/9p.h> diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 31d0b05582a..98ce9bcb0e1 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -38,6 +38,7 @@  #include <linux/idr.h>  #include <linux/file.h>  #include <linux/parser.h> +#include <linux/slab.h>  #include <net/9p/9p.h>  #include <net/9p/client.h>  #include <net/9p/transport.h> diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 2c95a89c0f4..041101ab4aa 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -40,6 +40,7 @@  #include <linux/file.h>  #include <linux/parser.h>  #include <linux/semaphore.h> +#include <linux/slab.h>  #include <net/9p/9p.h>  #include <net/9p/client.h>  #include <net/9p/transport.h> diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 0aaed481937..7eb78ecc161 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -37,6 +37,7 @@  #include <linux/inet.h>  #include <linux/idr.h>  #include <linux/file.h> +#include <linux/slab.h>  #include <net/9p/9p.h>  #include <linux/parser.h>  #include <net/9p/client.h> @@ -78,6 +79,12 @@ struct virtio_chan {  	/* Scatterlist: can be too big for stack. */  	struct scatterlist sg[VIRTQUEUE_NUM]; +	int tag_len; +	/* +	 * tag name to identify a mount Non-null terminated +	 */ +	char *tag; +  	struct list_head chan_list;  }; @@ -214,6 +221,20 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)  	return 0;  } +static ssize_t p9_mount_tag_show(struct device *dev, +				struct device_attribute *attr, char *buf) +{ +	struct virtio_chan *chan; +	struct virtio_device *vdev; + +	vdev = dev_to_virtio(dev); +	chan = vdev->priv; + +	return snprintf(buf, chan->tag_len + 1, "%s", chan->tag); +} + +static DEVICE_ATTR(mount_tag, 0444, p9_mount_tag_show, NULL); +  /**   * p9_virtio_probe - probe for existence of 9P virtio channels   * @vdev: virtio device to probe @@ -224,6 +245,8 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)  static int p9_virtio_probe(struct virtio_device *vdev)  { +	__u16 tag_len; +	char *tag;  	int err;  	struct virtio_chan *chan; @@ -248,6 +271,28 @@ static int p9_virtio_probe(struct virtio_device *vdev)  	sg_init_table(chan->sg, VIRTQUEUE_NUM);  	chan->inuse = false; +	if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) { +		vdev->config->get(vdev, +				offsetof(struct virtio_9p_config, tag_len), +				&tag_len, sizeof(tag_len)); +	} else { +		err = -EINVAL; +		goto out_free_vq; +	} +	tag = kmalloc(tag_len, GFP_KERNEL); +	if (!tag) { +		err = -ENOMEM; +		goto out_free_vq; +	} +	vdev->config->get(vdev, offsetof(struct virtio_9p_config, tag), +			tag, tag_len); +	chan->tag = tag; +	chan->tag_len = tag_len; +	err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); +	if (err) { +		kfree(tag); +		goto out_free_vq; +	}  	mutex_lock(&virtio_9p_lock);  	list_add_tail(&chan->chan_list, &virtio_chan_list);  	mutex_unlock(&virtio_9p_lock); @@ -284,7 +329,7 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args)  	mutex_lock(&virtio_9p_lock);  	list_for_each_entry(chan, &virtio_chan_list, chan_list) { -		if (!strcmp(devname, dev_name(&chan->vdev->dev))) { +		if (!strncmp(devname, chan->tag, chan->tag_len)) {  			if (!chan->inuse) {  				chan->inuse = true;  				found = 1; @@ -323,6 +368,8 @@ static void p9_virtio_remove(struct virtio_device *vdev)  	mutex_lock(&virtio_9p_lock);  	list_del(&chan->chan_list);  	mutex_unlock(&virtio_9p_lock); +	sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); +	kfree(chan->tag);  	kfree(chan);  } @@ -332,13 +379,19 @@ static struct virtio_device_id id_table[] = {  	{ 0 },  }; +static unsigned int features[] = { +	VIRTIO_9P_MOUNT_TAG, +}; +  /* The standard "struct lguest_driver": */  static struct virtio_driver p9_virtio_drv = { -	.driver.name = 	KBUILD_MODNAME, -	.driver.owner = THIS_MODULE, -	.id_table =	id_table, -	.probe = 	p9_virtio_probe, -	.remove =	p9_virtio_remove, +	.feature_table  = features, +	.feature_table_size = ARRAY_SIZE(features), +	.driver.name    = KBUILD_MODNAME, +	.driver.owner	= THIS_MODULE, +	.id_table	= id_table, +	.probe		= p9_virtio_probe, +	.remove		= p9_virtio_remove,  };  static struct p9_trans_module p9_virtio_trans = { diff --git a/net/9p/util.c b/net/9p/util.c index dc4ec05ad93..e048701a72d 100644 --- a/net/9p/util.c +++ b/net/9p/util.c @@ -30,6 +30,7 @@  #include <linux/sched.h>  #include <linux/parser.h>  #include <linux/idr.h> +#include <linux/slab.h>  #include <net/9p/9p.h>  /** diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index f2b3b56aa77..50dce798132 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c @@ -30,6 +30,7 @@   */  #include <linux/if_arp.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/datalink.h>  #include <net/psnap.h> diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 9fc4da56fb1..7b02967fbbe 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -57,6 +57,7 @@  #include <linux/smp_lock.h>  #include <linux/termios.h>	/* For TIOCOUTQ/INQ */  #include <linux/compat.h> +#include <linux/slab.h>  #include <net/datalink.h>  #include <net/psnap.h>  #include <net/sock.h> diff --git a/net/atm/addr.c b/net/atm/addr.c index cf3ae8b4757..dcda35c66f1 100644 --- a/net/atm/addr.c +++ b/net/atm/addr.c @@ -4,6 +4,7 @@  #include <linux/atm.h>  #include <linux/atmdev.h> +#include <linux/slab.h>  #include <linux/uaccess.h>  #include "signaling.h" diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c index f693b78eb46..799c631f0fe 100644 --- a/net/atm/atm_sysfs.c +++ b/net/atm/atm_sysfs.c @@ -1,6 +1,7 @@  /* ATM driver model support. */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/init.h>  #include <linux/kobject.h>  #include <linux/atmdev.h> diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 4d64d87e757..d6c7ceaf13e 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -18,6 +18,7 @@  #include <linux/rtnetlink.h>  #include <linux/ip.h>  #include <linux/uaccess.h> +#include <linux/slab.h>  #include <net/arp.h>  #include <linux/atm.h>  #include <linux/atmdev.h> diff --git a/net/atm/clip.c b/net/atm/clip.c index ebfa022008f..313aba11316 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -30,6 +30,7 @@  #include <linux/seq_file.h>  #include <linux/rcupdate.h>  #include <linux/jhash.h> +#include <linux/slab.h>  #include <net/route.h> /* for struct rtable and routing */  #include <net/icmp.h> /* icmp_send */  #include <linux/param.h> /* for HZ */ diff --git a/net/atm/common.c b/net/atm/common.c index 74d095a081e..97ed94aa0cb 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -18,6 +18,7 @@  #include <linux/skbuff.h>  #include <linux/bitops.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <net/sock.h>		/* struct sock */  #include <linux/uaccess.h>  #include <linux/poll.h> diff --git a/net/atm/lec.c b/net/atm/lec.c index 5da5753157f..feeaf571847 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -6,6 +6,7 @@  #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ +#include <linux/slab.h>  #include <linux/kernel.h>  #include <linux/bitops.h>  #include <linux/capability.h> diff --git a/net/atm/mpc.c b/net/atm/mpc.c index a6521c8aa88..436f2e17765 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c @@ -2,6 +2,7 @@  #include <linux/kernel.h>  #include <linux/string.h> +#include <linux/slab.h>  #include <linux/timer.h>  #include <linux/init.h>  #include <linux/bitops.h> diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c index 4c141810eb6..e773d833691 100644 --- a/net/atm/mpoa_caches.c +++ b/net/atm/mpoa_caches.c @@ -1,5 +1,6 @@  #include <linux/types.h>  #include <linux/atmmpc.h> +#include <linux/slab.h>  #include <linux/time.h>  #include "mpoa_caches.h" diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c index b9bdb98427e..53e50029227 100644 --- a/net/atm/mpoa_proc.c +++ b/net/atm/mpoa_proc.c @@ -12,6 +12,7 @@  #include <linux/uaccess.h>  #include <linux/atmmpc.h>  #include <linux/atm.h> +#include <linux/gfp.h>  #include "mpc.h"  #include "mpoa_caches.h" diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c index 400839273c6..e49bb6d948a 100644 --- a/net/atm/pppoatm.c +++ b/net/atm/pppoatm.c @@ -38,6 +38,7 @@  #include <linux/module.h>  #include <linux/init.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <linux/atm.h>  #include <linux/atmdev.h>  #include <linux/capability.h> diff --git a/net/atm/proc.c b/net/atm/proc.c index 7a96b2376bd..696e218436e 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -22,6 +22,7 @@  #include <linux/netdevice.h>  #include <linux/atmclip.h>  #include <linux/init.h> /* for __init */ +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/atmclip.h>  #include <linux/uaccess.h> diff --git a/net/atm/raw.c b/net/atm/raw.c index d0c4bd047dc..b4f7b9ff3c7 100644 --- a/net/atm/raw.c +++ b/net/atm/raw.c @@ -10,6 +10,7 @@  #include <linux/kernel.h>  #include <linux/skbuff.h>  #include <linux/mm.h> +#include <linux/slab.h>  #include "common.h"  #include "protocols.h" diff --git a/net/atm/resources.c b/net/atm/resources.c index 90082904f20..d29e5826151 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -19,6 +19,7 @@  #include <linux/capability.h>  #include <linux/delay.h>  #include <linux/mutex.h> +#include <linux/slab.h>  #include <net/sock.h>	 /* for struct sock */ diff --git a/net/atm/signaling.c b/net/atm/signaling.c index ad1d28ae512..6ba6e466ee5 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c @@ -14,6 +14,7 @@  #include <linux/atmsvc.h>  #include <linux/atmdev.h>  #include <linux/bitops.h> +#include <linux/slab.h>  #include "resources.h"  #include "signaling.h" diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index a5beedf43e2..65c5801261f 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -25,6 +25,7 @@  #include <linux/string.h>  #include <linux/sockios.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c index a7a0e0c9698..c1cb982f6e8 100644 --- a/net/ax25/ax25_dev.c +++ b/net/ax25/ax25_dev.c @@ -9,6 +9,7 @@  #include <linux/errno.h>  #include <linux/types.h>  #include <linux/socket.h> +#include <linux/slab.h>  #include <linux/in.h>  #include <linux/kernel.h>  #include <linux/timer.h> diff --git a/net/ax25/ax25_ds_subr.c b/net/ax25/ax25_ds_subr.c index b5e59787be2..85816e612dc 100644 --- a/net/ax25/ax25_ds_subr.c +++ b/net/ax25/ax25_ds_subr.c @@ -17,6 +17,7 @@  #include <linux/sockios.h>  #include <linux/spinlock.h>  #include <linux/net.h> +#include <linux/gfp.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c index 71338f11210..5a0dda8df49 100644 --- a/net/ax25/ax25_iface.c +++ b/net/ax25/ax25_iface.c @@ -17,6 +17,7 @@  #include <linux/string.h>  #include <linux/sockios.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c index de56d3983de..9bb77654120 100644 --- a/net/ax25/ax25_in.c +++ b/net/ax25/ax25_in.c @@ -18,6 +18,7 @@  #include <linux/string.h>  #include <linux/sockios.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c index f047a57aa95..cf0c47a2653 100644 --- a/net/ax25/ax25_ip.c +++ b/net/ax25/ax25_ip.c @@ -16,6 +16,7 @@  #include <linux/string.h>  #include <linux/sockios.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c index 14912600ec5..37507d806f6 100644 --- a/net/ax25/ax25_out.c +++ b/net/ax25/ax25_out.c @@ -19,6 +19,7 @@  #include <linux/sockios.h>  #include <linux/spinlock.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index c833ba4c45a..7805945a5fd 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c @@ -23,6 +23,7 @@  #include <linux/string.h>  #include <linux/sockios.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c index 034aa10a519..c6715ee4ab8 100644 --- a/net/ax25/ax25_subr.c +++ b/net/ax25/ax25_subr.c @@ -18,6 +18,7 @@  #include <linux/string.h>  #include <linux/sockios.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c index 9f13f6eefcb..d349be9578f 100644 --- a/net/ax25/ax25_uid.c +++ b/net/ax25/ax25_uid.c @@ -18,6 +18,7 @@  #include <linux/sockios.h>  #include <linux/net.h>  #include <linux/spinlock.h> +#include <linux/slab.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c index 5159be6b262..ebe0ef3f1d8 100644 --- a/net/ax25/sysctl_net_ax25.c +++ b/net/ax25/sysctl_net_ax25.c @@ -7,6 +7,7 @@   * Copyright (C) 1996 Mike Shaver (shaver@zeroknowledge.com)   */  #include <linux/mm.h> +#include <linux/slab.h>  #include <linux/sysctl.h>  #include <linux/spinlock.h>  #include <net/ax25.h> diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 087cc51f592..404a8500fd0 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -31,7 +31,6 @@  #include <linux/errno.h>  #include <linux/kernel.h>  #include <linux/sched.h> -#include <linux/slab.h>  #include <linux/skbuff.h>  #include <linux/init.h>  #include <linux/poll.h> diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index ef09c7b3a85..8062dad6d10 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -35,6 +35,7 @@  #include <linux/freezer.h>  #include <linux/errno.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <linux/socket.h> diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index b6234b73c4c..5643a2391e7 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c @@ -26,6 +26,7 @@  */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/socket.h>  #include <linux/netdevice.h> diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 2ff6ac7b2ed..2862f53b66b 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c @@ -30,7 +30,6 @@  #include <linux/capability.h>  #include <linux/errno.h>  #include <linux/kernel.h> -#include <linux/slab.h>  #include <linux/poll.h>  #include <linux/fcntl.h>  #include <linux/skbuff.h> @@ -39,6 +38,7 @@  #include <linux/file.h>  #include <linux/init.h>  #include <linux/compat.h> +#include <linux/gfp.h>  #include <net/sock.h>  #include <asm/system.h> diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index 978cc3a718a..7ea1979a8e4 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c @@ -26,7 +26,6 @@  #include <linux/capability.h>  #include <linux/errno.h>  #include <linux/kernel.h> -#include <linux/slab.h>  #include <linux/poll.h>  #include <linux/fcntl.h>  #include <linux/skbuff.h> @@ -34,6 +33,7 @@  #include <linux/ioctl.h>  #include <linux/file.h>  #include <linux/compat.h> +#include <linux/gfp.h>  #include <net/sock.h>  #include <linux/isdn/capilli.h> diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 1a79a6c7e30..0e8e1a59856 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -1,14 +1,15 @@  /* Bluetooth HCI driver model support. */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/init.h>  #include <linux/debugfs.h> +#include <linux/seq_file.h>  #include <net/bluetooth/bluetooth.h>  #include <net/bluetooth/hci_core.h> -struct class *bt_class = NULL; -EXPORT_SYMBOL_GPL(bt_class); +static struct class *bt_class;  struct dentry *bt_debugfs = NULL;  EXPORT_SYMBOL_GPL(bt_debugfs); @@ -405,20 +406,11 @@ static struct device_type bt_host = {  	.release = bt_host_release,  }; -static int inquiry_cache_open(struct inode *inode, struct file *file) -{ -	file->private_data = inode->i_private; -	return 0; -} - -static ssize_t inquiry_cache_read(struct file *file, char __user *userbuf, -						size_t count, loff_t *ppos) +static int inquiry_cache_show(struct seq_file *f, void *p)  { -	struct hci_dev *hdev = file->private_data; +	struct hci_dev *hdev = f->private;  	struct inquiry_cache *cache = &hdev->inq_cache;  	struct inquiry_entry *e; -	char buf[4096]; -	int n = 0;  	hci_dev_lock_bh(hdev); @@ -426,23 +418,30 @@ static ssize_t inquiry_cache_read(struct file *file, char __user *userbuf,  		struct inquiry_data *data = &e->data;  		bdaddr_t bdaddr;  		baswap(&bdaddr, &data->bdaddr); -		n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", -				batostr(&bdaddr), -				data->pscan_rep_mode, data->pscan_period_mode, -				data->pscan_mode, data->dev_class[2], -				data->dev_class[1], data->dev_class[0], -				__le16_to_cpu(data->clock_offset), -				data->rssi, data->ssp_mode, e->timestamp); +		seq_printf(f, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", +			   batostr(&bdaddr), +			   data->pscan_rep_mode, data->pscan_period_mode, +			   data->pscan_mode, data->dev_class[2], +			   data->dev_class[1], data->dev_class[0], +			   __le16_to_cpu(data->clock_offset), +			   data->rssi, data->ssp_mode, e->timestamp);  	}  	hci_dev_unlock_bh(hdev); -	return simple_read_from_buffer(userbuf, count, ppos, buf, n); +	return 0; +} + +static int inquiry_cache_open(struct inode *inode, struct file *file) +{ +	return single_open(file, inquiry_cache_show, inode->i_private);  }  static const struct file_operations inquiry_cache_fops = { -	.open = inquiry_cache_open, -	.read = inquiry_cache_read, +	.open		= inquiry_cache_open, +	.read		= seq_read, +	.llseek		= seq_lseek, +	.release	= single_release,  };  int hci_register_sysfs(struct hci_dev *hdev) diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 9cfef68b9fe..250dfd46237 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c @@ -26,7 +26,6 @@  #include <linux/capability.h>  #include <linux/errno.h>  #include <linux/kernel.h> -#include <linux/slab.h>  #include <linux/poll.h>  #include <linux/fcntl.h>  #include <linux/skbuff.h> @@ -35,6 +34,7 @@  #include <linux/file.h>  #include <linux/init.h>  #include <linux/compat.h> +#include <linux/gfp.h>  #include <net/sock.h>  #include "hidp.h" diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 4db7ae2fe07..9753b690a8b 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -40,6 +40,8 @@  #include <linux/skbuff.h>  #include <linux/list.h>  #include <linux/device.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h>  #include <linux/uaccess.h>  #include <linux/crc16.h>  #include <net/sock.h> @@ -1000,7 +1002,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al  	BT_DBG("sk %p", sk); -	if (!addr || addr->sa_family != AF_BLUETOOTH) +	if (!addr || alen < sizeof(addr->sa_family) || +	    addr->sa_family != AF_BLUETOOTH)  		return -EINVAL;  	memset(&la, 0, sizeof(la)); @@ -1623,7 +1626,10 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms  	/* Connectionless channel */  	if (sk->sk_type == SOCK_DGRAM) {  		skb = l2cap_create_connless_pdu(sk, msg, len); -		err = l2cap_do_send(sk, skb); +		if (IS_ERR(skb)) +			err = PTR_ERR(skb); +		else +			err = l2cap_do_send(sk, skb);  		goto done;  	} @@ -2830,6 +2836,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr  			int len = cmd->len - sizeof(*rsp);  			char req[64]; +			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { +				l2cap_send_disconn_req(conn, sk); +				goto done; +			} +  			/* throw out any old stored conf requests */  			result = L2CAP_CONF_SUCCESS;  			len = l2cap_parse_conf_rsp(sk, rsp->data, @@ -3937,31 +3948,42 @@ drop:  	return 0;  } -static ssize_t l2cap_sysfs_show(struct class *dev, -				struct class_attribute *attr, -				char *buf) +static int l2cap_debugfs_show(struct seq_file *f, void *p)  {  	struct sock *sk;  	struct hlist_node *node; -	char *str = buf;  	read_lock_bh(&l2cap_sk_list.lock);  	sk_for_each(sk, node, &l2cap_sk_list.head) {  		struct l2cap_pinfo *pi = l2cap_pi(sk); -		str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n", -				batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), -				sk->sk_state, __le16_to_cpu(pi->psm), pi->scid, -				pi->dcid, pi->imtu, pi->omtu, pi->sec_level); +		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n", +					batostr(&bt_sk(sk)->src), +					batostr(&bt_sk(sk)->dst), +					sk->sk_state, __le16_to_cpu(pi->psm), +					pi->scid, pi->dcid, +					pi->imtu, pi->omtu, pi->sec_level);  	}  	read_unlock_bh(&l2cap_sk_list.lock); -	return str - buf; +	return 0;  } -static CLASS_ATTR(l2cap, S_IRUGO, l2cap_sysfs_show, NULL); +static int l2cap_debugfs_open(struct inode *inode, struct file *file) +{ +	return single_open(file, l2cap_debugfs_show, inode->i_private); +} + +static const struct file_operations l2cap_debugfs_fops = { +	.open		= l2cap_debugfs_open, +	.read		= seq_read, +	.llseek		= seq_lseek, +	.release	= single_release, +}; + +static struct dentry *l2cap_debugfs;  static const struct proto_ops l2cap_sock_ops = {  	.family		= PF_BLUETOOTH, @@ -4021,8 +4043,12 @@ static int __init l2cap_init(void)  		goto error;  	} -	if (class_create_file(bt_class, &class_attr_l2cap) < 0) -		BT_ERR("Failed to create L2CAP info file"); +	if (bt_debugfs) { +		l2cap_debugfs = debugfs_create_file("l2cap", 0444, +					bt_debugfs, NULL, &l2cap_debugfs_fops); +		if (!l2cap_debugfs) +			BT_ERR("Failed to create L2CAP debug file"); +	}  	BT_INFO("L2CAP ver %s", VERSION);  	BT_INFO("L2CAP socket layer initialized"); @@ -4036,7 +4062,7 @@ error:  static void __exit l2cap_exit(void)  { -	class_remove_file(bt_class, &class_attr_l2cap); +	debugfs_remove(l2cap_debugfs);  	if (bt_sock_unregister(BTPROTO_L2CAP) < 0)  		BT_ERR("L2CAP socket unregistration failed"); diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index db8a68e1a5b..7dca91bb8c5 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -33,9 +33,12 @@  #include <linux/init.h>  #include <linux/wait.h>  #include <linux/device.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h>  #include <linux/net.h>  #include <linux/mutex.h>  #include <linux/kthread.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <asm/uaccess.h> @@ -2098,13 +2101,10 @@ static struct hci_cb rfcomm_cb = {  	.security_cfm	= rfcomm_security_cfm  }; -static ssize_t rfcomm_dlc_sysfs_show(struct class *dev, -				     struct class_attribute *attr, -				     char *buf) +static int rfcomm_dlc_debugfs_show(struct seq_file *f, void *x)  {  	struct rfcomm_session *s;  	struct list_head *pp, *p; -	char *str = buf;  	rfcomm_lock(); @@ -2114,18 +2114,32 @@ static ssize_t rfcomm_dlc_sysfs_show(struct class *dev,  			struct sock *sk = s->sock->sk;  			struct rfcomm_dlc *d = list_entry(pp, struct rfcomm_dlc, list); -			str += sprintf(str, "%s %s %ld %d %d %d %d\n", -					batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), -					d->state, d->dlci, d->mtu, d->rx_credits, d->tx_credits); +			seq_printf(f, "%s %s %ld %d %d %d %d\n", +						batostr(&bt_sk(sk)->src), +						batostr(&bt_sk(sk)->dst), +						d->state, d->dlci, d->mtu, +						d->rx_credits, d->tx_credits);  		}  	}  	rfcomm_unlock(); -	return (str - buf); +	return 0;  } -static CLASS_ATTR(rfcomm_dlc, S_IRUGO, rfcomm_dlc_sysfs_show, NULL); +static int rfcomm_dlc_debugfs_open(struct inode *inode, struct file *file) +{ +	return single_open(file, rfcomm_dlc_debugfs_show, inode->i_private); +} + +static const struct file_operations rfcomm_dlc_debugfs_fops = { +	.open		= rfcomm_dlc_debugfs_open, +	.read		= seq_read, +	.llseek		= seq_lseek, +	.release	= single_release, +}; + +static struct dentry *rfcomm_dlc_debugfs;  /* ---- Initialization ---- */  static int __init rfcomm_init(void) @@ -2142,8 +2156,12 @@ static int __init rfcomm_init(void)  		goto unregister;  	} -	if (class_create_file(bt_class, &class_attr_rfcomm_dlc) < 0) -		BT_ERR("Failed to create RFCOMM info file"); +	if (bt_debugfs) { +		rfcomm_dlc_debugfs = debugfs_create_file("rfcomm_dlc", 0444, +				bt_debugfs, NULL, &rfcomm_dlc_debugfs_fops); +		if (!rfcomm_dlc_debugfs) +			BT_ERR("Failed to create RFCOMM debug file"); +	}  	err = rfcomm_init_ttys();  	if (err < 0) @@ -2171,7 +2189,7 @@ unregister:  static void __exit rfcomm_exit(void)  { -	class_remove_file(bt_class, &class_attr_rfcomm_dlc); +	debugfs_remove(rfcomm_dlc_debugfs);  	hci_unregister_cb(&rfcomm_cb); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index ca87d6ac6a2..8ed3c37684f 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -40,6 +40,8 @@  #include <linux/skbuff.h>  #include <linux/list.h>  #include <linux/device.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h>  #include <net/sock.h>  #include <asm/system.h> @@ -395,7 +397,8 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a  	BT_DBG("sk %p", sk); -	if (addr->sa_family != AF_BLUETOOTH || alen < sizeof(struct sockaddr_rc)) +	if (alen < sizeof(struct sockaddr_rc) || +	    addr->sa_family != AF_BLUETOOTH)  		return -EINVAL;  	lock_sock(sk); @@ -1061,28 +1064,38 @@ done:  	return result;  } -static ssize_t rfcomm_sock_sysfs_show(struct class *dev, -				      struct class_attribute *attr, -				      char *buf) +static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p)  {  	struct sock *sk;  	struct hlist_node *node; -	char *str = buf;  	read_lock_bh(&rfcomm_sk_list.lock);  	sk_for_each(sk, node, &rfcomm_sk_list.head) { -		str += sprintf(str, "%s %s %d %d\n", -				batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), +		seq_printf(f, "%s %s %d %d\n", +				batostr(&bt_sk(sk)->src), +				batostr(&bt_sk(sk)->dst),  				sk->sk_state, rfcomm_pi(sk)->channel);  	}  	read_unlock_bh(&rfcomm_sk_list.lock); -	return (str - buf); +	return 0;  } -static CLASS_ATTR(rfcomm, S_IRUGO, rfcomm_sock_sysfs_show, NULL); +static int rfcomm_sock_debugfs_open(struct inode *inode, struct file *file) +{ +	return single_open(file, rfcomm_sock_debugfs_show, inode->i_private); +} + +static const struct file_operations rfcomm_sock_debugfs_fops = { +	.open		= rfcomm_sock_debugfs_open, +	.read		= seq_read, +	.llseek		= seq_lseek, +	.release	= single_release, +}; + +static struct dentry *rfcomm_sock_debugfs;  static const struct proto_ops rfcomm_sock_ops = {  	.family		= PF_BLUETOOTH, @@ -1122,8 +1135,12 @@ int __init rfcomm_init_sockets(void)  	if (err < 0)  		goto error; -	if (class_create_file(bt_class, &class_attr_rfcomm) < 0) -		BT_ERR("Failed to create RFCOMM info file"); +	if (bt_debugfs) { +		rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444, +				bt_debugfs, NULL, &rfcomm_sock_debugfs_fops); +		if (!rfcomm_sock_debugfs) +			BT_ERR("Failed to create RFCOMM debug file"); +	}  	BT_INFO("RFCOMM socket layer initialized"); @@ -1137,7 +1154,7 @@ error:  void rfcomm_cleanup_sockets(void)  { -	class_remove_file(bt_class, &class_attr_rfcomm); +	debugfs_remove(rfcomm_sock_debugfs);  	if (bt_sock_unregister(BTPROTO_RFCOMM) < 0)  		BT_ERR("RFCOMM socket layer unregistration failed"); diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index f93b939539b..ca6b2ad1c3f 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -38,6 +38,8 @@  #include <linux/socket.h>  #include <linux/skbuff.h>  #include <linux/device.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h>  #include <linux/list.h>  #include <net/sock.h> @@ -497,7 +499,8 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen  	BT_DBG("sk %p", sk); -	if (addr->sa_family != AF_BLUETOOTH || alen < sizeof(struct sockaddr_sco)) +	if (alen < sizeof(struct sockaddr_sco) || +	    addr->sa_family != AF_BLUETOOTH)  		return -EINVAL;  	if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) @@ -953,28 +956,36 @@ drop:  	return 0;  } -static ssize_t sco_sysfs_show(struct class *dev, -				struct class_attribute *attr, -				char *buf) +static int sco_debugfs_show(struct seq_file *f, void *p)  {  	struct sock *sk;  	struct hlist_node *node; -	char *str = buf;  	read_lock_bh(&sco_sk_list.lock);  	sk_for_each(sk, node, &sco_sk_list.head) { -		str += sprintf(str, "%s %s %d\n", -				batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), -				sk->sk_state); +		seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src), +				batostr(&bt_sk(sk)->dst), sk->sk_state);  	}  	read_unlock_bh(&sco_sk_list.lock); -	return (str - buf); +	return 0;  } -static CLASS_ATTR(sco, S_IRUGO, sco_sysfs_show, NULL); +static int sco_debugfs_open(struct inode *inode, struct file *file) +{ +	return single_open(file, sco_debugfs_show, inode->i_private); +} + +static const struct file_operations sco_debugfs_fops = { +	.open		= sco_debugfs_open, +	.read		= seq_read, +	.llseek		= seq_lseek, +	.release	= single_release, +}; + +static struct dentry *sco_debugfs;  static const struct proto_ops sco_sock_ops = {  	.family		= PF_BLUETOOTH, @@ -1032,8 +1043,12 @@ static int __init sco_init(void)  		goto error;  	} -	if (class_create_file(bt_class, &class_attr_sco) < 0) -		BT_ERR("Failed to create SCO info file"); +	if (bt_debugfs) { +		sco_debugfs = debugfs_create_file("sco", 0444, +					bt_debugfs, NULL, &sco_debugfs_fops); +		if (!sco_debugfs) +			BT_ERR("Failed to create SCO debug file"); +	}  	BT_INFO("SCO (Voice Link) ver %s", VERSION);  	BT_INFO("SCO socket layer initialized"); @@ -1047,7 +1062,7 @@ error:  static void __exit sco_exit(void)  { -	class_remove_file(bt_class, &class_attr_sco); +	debugfs_remove(sco_debugfs);  	if (bt_sock_unregister(BTPROTO_SCO) < 0)  		BT_ERR("SCO socket unregistration failed"); diff --git a/net/bridge/Kconfig b/net/bridge/Kconfig index 19a6b9629c5..d115d5cea5b 100644 --- a/net/bridge/Kconfig +++ b/net/bridge/Kconfig @@ -35,6 +35,7 @@ config BRIDGE  config BRIDGE_IGMP_SNOOPING  	bool "IGMP snooping"  	depends on BRIDGE +	depends on INET  	default y  	---help---  	  If you say Y here, then the Ethernet bridge will be able selectively diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index eb7062d2e9e..90a9024e5c1 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -40,7 +40,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)  			goto out;  		mdst = br_mdb_get(br, skb); -		if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only) +		if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb))  			br_multicast_deliver(mdst, skb);  		else  			br_flood_deliver(br, skb); diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 3b8e038ab32..9101a4e5620 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -20,6 +20,7 @@  #include <linux/etherdevice.h>  #include <linux/jhash.h>  #include <linux/random.h> +#include <linux/slab.h>  #include <asm/atomic.h>  #include <asm/unaligned.h>  #include "br_private.h" diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index d61e6f74112..7a241c39698 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -12,6 +12,7 @@   */  #include <linux/err.h> +#include <linux/slab.h>  #include <linux/kernel.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h> @@ -19,6 +20,11 @@  #include <linux/netfilter_bridge.h>  #include "br_private.h" +static int deliver_clone(const struct net_bridge_port *prev, +			 struct sk_buff *skb, +			 void (*__packet_hook)(const struct net_bridge_port *p, +					       struct sk_buff *skb)); +  /* Don't forward packets to originating port or forwarding diasabled */  static inline int should_deliver(const struct net_bridge_port *p,  				 const struct sk_buff *skb) @@ -94,17 +100,22 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)  }  /* called with rcu_read_lock */ -void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) +void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0)  {  	if (should_deliver(to, skb)) { -		__br_forward(to, skb); +		if (skb0) +			deliver_clone(to, skb, __br_forward); +		else +			__br_forward(to, skb);  		return;  	} -	kfree_skb(skb); +	if (!skb0) +		kfree_skb(skb);  } -static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb, +static int deliver_clone(const struct net_bridge_port *prev, +			 struct sk_buff *skb,  			 void (*__packet_hook)(const struct net_bridge_port *p,  					       struct sk_buff *skb))  { diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index b6a3872f568..0b6b1f2ff7a 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -19,6 +19,7 @@  #include <linux/init.h>  #include <linux/rtnetlink.h>  #include <linux/if_ether.h> +#include <linux/slab.h>  #include <net/sock.h>  #include "br_private.h" diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 53b39851d87..a82dde2d2ea 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -11,6 +11,7 @@   *	2 of the License, or (at your option) any later version.   */ +#include <linux/slab.h>  #include <linux/kernel.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h> @@ -70,7 +71,7 @@ int br_handle_frame_finish(struct sk_buff *skb)  	if (is_multicast_ether_addr(dest)) {  		mdst = br_mdb_get(br, skb); -		if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only) { +		if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) {  			if ((mdst && !hlist_unhashed(&mdst->mglist)) ||  			    br_multicast_is_router(br))  				skb2 = skb; @@ -90,7 +91,7 @@ int br_handle_frame_finish(struct sk_buff *skb)  	if (skb) {  		if (dst) -			br_forward(dst->dst, skb); +			br_forward(dst->dst, skb, skb2);  		else  			br_flood_forward(br, skb, skb2);  	} diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index 2af6e4a9026..995afc4b04d 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c @@ -15,6 +15,7 @@  #include <linux/kernel.h>  #include <linux/if_bridge.h>  #include <linux/netdevice.h> +#include <linux/slab.h>  #include <linux/times.h>  #include <net/net_namespace.h>  #include <asm/uaccess.h> diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 2559fb53983..eaa0e1bae49 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -38,7 +38,7 @@ static struct net_bridge_mdb_entry *__br_mdb_ip_get(  	struct net_bridge_mdb_entry *mp;  	struct hlist_node *p; -	hlist_for_each_entry(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { +	hlist_for_each_entry_rcu(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) {  		if (dst == mp->addr)  			return mp;  	} @@ -49,22 +49,23 @@ static struct net_bridge_mdb_entry *__br_mdb_ip_get(  static struct net_bridge_mdb_entry *br_mdb_ip_get(  	struct net_bridge_mdb_htable *mdb, __be32 dst)  { +	if (!mdb) +		return NULL; +  	return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst));  }  struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,  					struct sk_buff *skb)  { -	struct net_bridge_mdb_htable *mdb = br->mdb; - -	if (!mdb || br->multicast_disabled) +	if (br->multicast_disabled)  		return NULL;  	switch (skb->protocol) {  	case htons(ETH_P_IP):  		if (BR_INPUT_SKB_CB(skb)->igmp)  			break; -		return br_mdb_ip_get(mdb, ip_hdr(skb)->daddr); +		return br_mdb_ip_get(br->mdb, ip_hdr(skb)->daddr);  	}  	return NULL; @@ -627,8 +628,8 @@ static void br_multicast_port_query_expired(unsigned long data)  	struct net_bridge *br = port->br;  	spin_lock(&br->multicast_lock); -	if (port && (port->state == BR_STATE_DISABLED || -		     port->state == BR_STATE_BLOCKING)) +	if (port->state == BR_STATE_DISABLED || +	    port->state == BR_STATE_BLOCKING)  		goto out;  	if (port->multicast_startup_queries_sent < @@ -722,11 +723,11 @@ static int br_multicast_igmp3_report(struct net_bridge *br,  		if (!pskb_may_pull(skb, len))  			return -EINVAL; -		grec = (void *)(skb->data + len); +		grec = (void *)(skb->data + len - sizeof(*grec));  		group = grec->grec_mca;  		type = grec->grec_type; -		len += grec->grec_nsrcs * 4; +		len += ntohs(grec->grec_nsrcs) * 4;  		if (!pskb_may_pull(skb, len))  			return -EINVAL; @@ -823,6 +824,7 @@ static int br_multicast_query(struct net_bridge *br,  	unsigned long max_delay;  	unsigned long now = jiffies;  	__be32 group; +	int err = 0;  	spin_lock(&br->multicast_lock);  	if (!netif_running(br->dev) || @@ -841,15 +843,17 @@ static int br_multicast_query(struct net_bridge *br,  			group = 0;  		}  	} else { -		if (!pskb_may_pull(skb, sizeof(struct igmpv3_query))) -			return -EINVAL; +		if (!pskb_may_pull(skb, sizeof(struct igmpv3_query))) { +			err = -EINVAL; +			goto out; +		}  		ih3 = igmpv3_query_hdr(skb);  		if (ih3->nsrcs) -			return 0; +			goto out; -		max_delay = ih3->code ? 1 : -			    IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE); +		max_delay = ih3->code ? +			    IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1;  	}  	if (!group) @@ -876,7 +880,7 @@ static int br_multicast_query(struct net_bridge *br,  out:  	spin_unlock(&br->multicast_lock); -	return 0; +	return err;  }  static void br_multicast_leave_group(struct net_bridge *br, @@ -953,9 +957,6 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,  	unsigned offset;  	int err; -	BR_INPUT_SKB_CB(skb)->igmp = 0; -	BR_INPUT_SKB_CB(skb)->mrouters_only = 0; -  	/* We treat OOM as packet loss for now. */  	if (!pskb_may_pull(skb, sizeof(*iph)))  		return -EINVAL; @@ -987,7 +988,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,  		err = pskb_trim_rcsum(skb2, len);  		if (err) -			return err; +			goto err_out;  	}  	len -= ip_hdrlen(skb2); @@ -1009,7 +1010,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,  	case CHECKSUM_NONE:  		skb2->csum = 0;  		if (skb_checksum_complete(skb2)) -			return -EINVAL; +			goto out;  	}  	err = 0; @@ -1036,6 +1037,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,  out:  	__skb_push(skb2, offset); +err_out:  	if (skb2 != skb)  		kfree_skb(skb2);  	return err; @@ -1044,6 +1046,9 @@ out:  int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port,  		     struct sk_buff *skb)  { +	BR_INPUT_SKB_CB(skb)->igmp = 0; +	BR_INPUT_SKB_CB(skb)->mrouters_only = 0; +  	if (br->multicast_disabled)  		return 0; @@ -1135,7 +1140,7 @@ void br_multicast_stop(struct net_bridge *br)  	if (mdb->old) {  		spin_unlock_bh(&br->multicast_lock); -		synchronize_rcu_bh(); +		rcu_barrier_bh();  		spin_lock_bh(&br->multicast_lock);  		WARN_ON(mdb->old);  	} diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 268e2e72588..4c4977d12fd 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -23,6 +23,7 @@  #include <linux/module.h>  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/ip.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h> diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index fcffb3fb117..aa56ac2c882 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -11,6 +11,7 @@   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <net/rtnetlink.h>  #include <net/net_namespace.h>  #include <net/sock.h> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index fef0384e3c0..846d7d1e207 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -206,12 +206,20 @@ struct net_bridge  struct br_input_skb_cb {  	struct net_device *brdev; +#ifdef CONFIG_BRIDGE_IGMP_SNOOPING  	int igmp;  	int mrouters_only; +#endif  };  #define BR_INPUT_SKB_CB(__skb)	((struct br_input_skb_cb *)(__skb)->cb) +#ifdef CONFIG_BRIDGE_IGMP_SNOOPING +# define BR_INPUT_SKB_CB_MROUTERS_ONLY(__skb)	(BR_INPUT_SKB_CB(__skb)->mrouters_only) +#else +# define BR_INPUT_SKB_CB_MROUTERS_ONLY(__skb)	(0) +#endif +  extern struct notifier_block br_device_notifier;  extern const u8 br_group_address[ETH_ALEN]; @@ -252,7 +260,7 @@ extern void br_deliver(const struct net_bridge_port *to,  		struct sk_buff *skb);  extern int br_dev_queue_push_xmit(struct sk_buff *skb);  extern void br_forward(const struct net_bridge_port *to, -		struct sk_buff *skb); +		struct sk_buff *skb, struct sk_buff *skb0);  extern int br_forward_finish(struct sk_buff *skb);  extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb);  extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index 81ae40b3f65..d66cce11f3b 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c @@ -15,6 +15,7 @@  #include <linux/netfilter_bridge.h>  #include <linux/etherdevice.h>  #include <linux/llc.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/llc.h>  #include <net/llc_pdu.h> diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index c6ac657074a..f9560f3dbdc 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -29,6 +29,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/spinlock.h>  #include <linux/socket.h>  #include <linux/skbuff.h> diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index dfb58056a89..f0865fd1e3e 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -23,6 +23,7 @@  #include <linux/netfilter_bridge/ebtables.h>  #include <linux/spinlock.h>  #include <linux/mutex.h> +#include <linux/slab.h>  #include <asm/uaccess.h>  #include <linux/smp.h>  #include <linux/cpumask.h> diff --git a/net/can/bcm.c b/net/can/bcm.c index e32af52238a..907dc871fac 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -56,6 +56,7 @@  #include <linux/can.h>  #include <linux/can/core.h>  #include <linux/can/bcm.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/net_namespace.h> @@ -1478,6 +1479,9 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,  	struct sock *sk = sock->sk;  	struct bcm_sock *bo = bcm_sk(sk); +	if (len < sizeof(*addr)) +		return -EINVAL; +  	if (bo->bound)  		return -EISCONN; diff --git a/net/can/raw.c b/net/can/raw.c index abca920440b..da99cf153b3 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -45,6 +45,7 @@  #include <linux/init.h>  #include <linux/uio.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <linux/netdevice.h>  #include <linux/socket.h>  #include <linux/if_arp.h> @@ -444,7 +445,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,  				return -EFAULT;  			}  		} else if (count == 1) { -			if (copy_from_user(&sfilter, optval, optlen)) +			if (copy_from_user(&sfilter, optval, sizeof(sfilter)))  				return -EFAULT;  		} diff --git a/net/compat.c b/net/compat.c index a1fb1b079a8..ec24d9edb02 100644 --- a/net/compat.c +++ b/net/compat.c @@ -12,6 +12,7 @@   */  #include <linux/kernel.h> +#include <linux/gfp.h>  #include <linux/fs.h>  #include <linux/types.h>  #include <linux/file.h> diff --git a/net/core/datagram.c b/net/core/datagram.c index 95c2e0840d0..2dccd4ee591 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -48,6 +48,7 @@  #include <linux/poll.h>  #include <linux/highmem.h>  #include <linux/spinlock.h> +#include <linux/slab.h>  #include <net/protocol.h>  #include <linux/skbuff.h> diff --git a/net/core/dev.c b/net/core/dev.c index bcc490cc945..264137fce3a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -80,6 +80,7 @@  #include <linux/types.h>  #include <linux/kernel.h>  #include <linux/hash.h> +#include <linux/slab.h>  #include <linux/sched.h>  #include <linux/mutex.h>  #include <linux/string.h> @@ -1450,7 +1451,7 @@ static inline void net_timestamp(struct sk_buff *skb)   *   * return values:   *	NET_RX_SUCCESS	(no congestion) - *	NET_RX_DROP     (packet was dropped) + *	NET_RX_DROP     (packet was dropped, but freed)   *   * dev_forward_skb can be used for injecting an skb from the   * start_xmit function of one device into the receive queue @@ -1464,12 +1465,11 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)  {  	skb_orphan(skb); -	if (!(dev->flags & IFF_UP)) -		return NET_RX_DROP; - -	if (skb->len > (dev->mtu + dev->hard_header_len)) +	if (!(dev->flags & IFF_UP) || +	    (skb->len > (dev->mtu + dev->hard_header_len))) { +		kfree_skb(skb);  		return NET_RX_DROP; - +	}  	skb_set_dev(skb, dev);  	skb->tstamp.tv64 = 0;  	skb->pkt_type = PACKET_HOST; @@ -1988,8 +1988,12 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,  			if (dev->real_num_tx_queues > 1)  				queue_index = skb_tx_hash(dev, skb); -			if (sk && sk->sk_dst_cache) -				sk_tx_queue_set(sk, queue_index); +			if (sk) { +				struct dst_entry *dst = rcu_dereference_bh(sk->sk_dst_cache); + +				if (dst && skb_dst(skb) == dst) +					sk_tx_queue_set(sk, queue_index); +			}  		}  	} @@ -2483,6 +2487,7 @@ int netif_receive_skb(struct sk_buff *skb)  {  	struct packet_type *ptype, *pt_prev;  	struct net_device *orig_dev; +	struct net_device *master;  	struct net_device *null_or_orig;  	struct net_device *null_or_bond;  	int ret = NET_RX_DROP; @@ -2503,11 +2508,12 @@ int netif_receive_skb(struct sk_buff *skb)  	null_or_orig = NULL;  	orig_dev = skb->dev; -	if (orig_dev->master) { -		if (skb_bond_should_drop(skb)) +	master = ACCESS_ONCE(orig_dev->master); +	if (master) { +		if (skb_bond_should_drop(skb, master))  			null_or_orig = orig_dev; /* deliver only exact match */  		else -			skb->dev = orig_dev->master; +			skb->dev = master;  	}  	__get_cpu_var(netdev_rx_stat).total++; diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index fd91569e239..3dc295beb48 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c @@ -97,8 +97,9 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)  	netif_addr_lock_bh(dev);  	if (alen != dev->addr_len) -		return -EINVAL; -	err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl); +		err = -EINVAL; +	else +		err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl);  	if (!err)  		__dev_set_rx_mode(dev);  	netif_addr_unlock_bh(dev); diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index f8c87497535..cf208d8042b 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -21,6 +21,7 @@  #include <linux/percpu.h>  #include <linux/timer.h>  #include <linux/bitops.h> +#include <linux/slab.h>  #include <net/genetlink.h>  #include <net/netevent.h> diff --git a/net/core/dst.c b/net/core/dst.c index cb1b3488b73..f307bc18f6a 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -12,6 +12,7 @@  #include <linux/workqueue.h>  #include <linux/mm.h>  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h>  #include <linux/string.h> diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 0f2f82185ec..9d55c57f318 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -17,6 +17,8 @@  #include <linux/errno.h>  #include <linux/ethtool.h>  #include <linux/netdevice.h> +#include <linux/bitops.h> +#include <linux/slab.h>  #include <asm/uaccess.h>  /* @@ -199,10 +201,7 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr)  	return dev->ethtool_ops->set_settings(dev, &cmd);  } -/* - * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() - */ -static noinline int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) +static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr)  {  	struct ethtool_drvinfo info;  	const struct ethtool_ops *ops = dev->ethtool_ops; @@ -214,6 +213,10 @@ static noinline int ethtool_get_drvinfo(struct net_device *dev, void __user *use  	info.cmd = ETHTOOL_GDRVINFO;  	ops->get_drvinfo(dev, &info); +	/* +	 * this method of obtaining string set info is deprecated; +	 * Use ETHTOOL_GSSET_INFO instead. +	 */  	if (ops->get_sset_count) {  		int rc; @@ -237,10 +240,67 @@ static noinline int ethtool_get_drvinfo(struct net_device *dev, void __user *use  	return 0;  } -/* - * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() - */ -static noinline int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) +static noinline_for_stack int ethtool_get_sset_info(struct net_device *dev, +                                          void __user *useraddr) +{ +	struct ethtool_sset_info info; +	const struct ethtool_ops *ops = dev->ethtool_ops; +	u64 sset_mask; +	int i, idx = 0, n_bits = 0, ret, rc; +	u32 *info_buf = NULL; + +	if (!ops->get_sset_count) +		return -EOPNOTSUPP; + +	if (copy_from_user(&info, useraddr, sizeof(info))) +		return -EFAULT; + +	/* store copy of mask, because we zero struct later on */ +	sset_mask = info.sset_mask; +	if (!sset_mask) +		return 0; + +	/* calculate size of return buffer */ +	n_bits = hweight64(sset_mask); + +	memset(&info, 0, sizeof(info)); +	info.cmd = ETHTOOL_GSSET_INFO; + +	info_buf = kzalloc(n_bits * sizeof(u32), GFP_USER); +	if (!info_buf) +		return -ENOMEM; + +	/* +	 * fill return buffer based on input bitmask and successful +	 * get_sset_count return +	 */ +	for (i = 0; i < 64; i++) { +		if (!(sset_mask & (1ULL << i))) +			continue; + +		rc = ops->get_sset_count(dev, i); +		if (rc >= 0) { +			info.sset_mask |= (1ULL << i); +			info_buf[idx++] = rc; +		} +	} + +	ret = -EFAULT; +	if (copy_to_user(useraddr, &info, sizeof(info))) +		goto out; + +	useraddr += offsetof(struct ethtool_sset_info, data); +	if (copy_to_user(useraddr, info_buf, idx * sizeof(u32))) +		goto out; + +	ret = 0; + +out: +	kfree(info_buf); +	return ret; +} + +static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr)  {  	struct ethtool_rxnfc cmd; @@ -253,10 +313,7 @@ static noinline int ethtool_set_rxnfc(struct net_device *dev, void __user *usera  	return dev->ethtool_ops->set_rxnfc(dev, &cmd);  } -/* - * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() - */ -static noinline int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr) +static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr)  {  	struct ethtool_rxnfc info;  	const struct ethtool_ops *ops = dev->ethtool_ops; @@ -328,10 +385,7 @@ static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list,  	list->count++;  } -/* - * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() - */ -static noinline int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr) +static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr)  {  	struct ethtool_rx_ntuple cmd;  	const struct ethtool_ops *ops = dev->ethtool_ops; @@ -799,10 +853,7 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr)  	return ret;  } -/* - * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() - */ -static noinline int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr) +static noinline_for_stack int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr)  {  	struct ethtool_coalesce coalesce = { .cmd = ETHTOOL_GCOALESCE }; @@ -816,10 +867,7 @@ static noinline int ethtool_get_coalesce(struct net_device *dev, void __user *us  	return 0;  } -/* - * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() - */ -static noinline int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr) +static noinline_for_stack int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr)  {  	struct ethtool_coalesce coalesce; @@ -1229,10 +1277,7 @@ static int ethtool_set_value(struct net_device *dev, char __user *useraddr,  	return actor(dev, edata.data);  } -/* - * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() - */ -static noinline int ethtool_flash_device(struct net_device *dev, char __user *useraddr) +static noinline_for_stack int ethtool_flash_device(struct net_device *dev, char __user *useraddr)  {  	struct ethtool_flash efl; @@ -1471,6 +1516,9 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)  	case ETHTOOL_GRXNTUPLE:  		rc = ethtool_get_rx_ntuple(dev, useraddr);  		break; +	case ETHTOOL_GSSET_INFO: +		rc = ethtool_get_sset_info(dev, useraddr); +		break;  	default:  		rc = -EOPNOTSUPP;  	} diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 9a24377146b..d2c3e7dc2e5 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -10,6 +10,7 @@  #include <linux/types.h>  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/list.h>  #include <net/net_namespace.h>  #include <net/sock.h> diff --git a/net/core/filter.c b/net/core/filter.c index d38ef7fd50f..ff943bed21a 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -25,6 +25,7 @@  #include <linux/inet.h>  #include <linux/netdevice.h>  #include <linux/if_packet.h> +#include <linux/gfp.h>  #include <net/ip.h>  #include <net/protocol.h>  #include <net/netlink.h> diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 493775f4f2f..cf8e70392fe 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -32,6 +32,7 @@  #include <linux/rtnetlink.h>  #include <linux/init.h>  #include <linux/rbtree.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/gen_stats.h> diff --git a/net/core/iovec.c b/net/core/iovec.c index 16ad45d4882..1e7f4e91a93 100644 --- a/net/core/iovec.c +++ b/net/core/iovec.c @@ -20,7 +20,6 @@  #include <linux/module.h>  #include <linux/kernel.h>  #include <linux/mm.h> -#include <linux/slab.h>  #include <linux/net.h>  #include <linux/in6.h>  #include <asm/uaccess.h> diff --git a/net/core/link_watch.c b/net/core/link_watch.c index 5910b555a54..bdbce2f5875 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -19,7 +19,6 @@  #include <linux/rtnetlink.h>  #include <linux/jiffies.h>  #include <linux/spinlock.h> -#include <linux/slab.h>  #include <linux/workqueue.h>  #include <linux/bitops.h>  #include <asm/types.h> diff --git a/net/core/neighbour.c b/net/core/neighbour.c index d102f6d9abd..bff37908bd5 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -15,6 +15,7 @@   *	Harald Welte		Add neighbour cache statistics like rtstat   */ +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/kernel.h>  #include <linux/module.h> @@ -771,6 +772,8 @@ static __inline__ int neigh_max_probes(struct neighbour *n)  }  static void neigh_invalidate(struct neighbour *neigh) +	__releases(neigh->lock) +	__acquires(neigh->lock)  {  	struct sk_buff *skb; diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 099c753c421..59cfc7d8fc4 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -13,6 +13,7 @@  #include <linux/kernel.h>  #include <linux/netdevice.h>  #include <linux/if_arp.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <linux/rtnetlink.h>  #include <linux/wireless.h> diff --git a/net/core/net-traces.c b/net/core/net-traces.c index f1e982c508b..afa6380ed88 100644 --- a/net/core/net-traces.c +++ b/net/core/net-traces.c @@ -19,6 +19,7 @@  #include <linux/workqueue.h>  #include <linux/netlink.h>  #include <linux/net_dropmon.h> +#include <linux/slab.h>  #include <asm/unaligned.h>  #include <asm/bitops.h> diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 7aa69725376..a58f59b9759 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -22,6 +22,7 @@  #include <linux/delay.h>  #include <linux/rcupdate.h>  #include <linux/workqueue.h> +#include <linux/slab.h>  #include <net/tcp.h>  #include <net/udp.h>  #include <asm/unaligned.h> @@ -614,7 +615,7 @@ void netpoll_print_options(struct netpoll *np)  			 np->name, np->local_port);  	printk(KERN_INFO "%s: local IP %pI4\n",  			 np->name, &np->local_ip); -	printk(KERN_INFO "%s: interface %s\n", +	printk(KERN_INFO "%s: interface '%s'\n",  			 np->name, np->dev_name);  	printk(KERN_INFO "%s: remote port %d\n",  			 np->name, np->remote_port); @@ -661,6 +662,9 @@ int netpoll_parse_options(struct netpoll *np, char *opt)  		if ((delim = strchr(cur, '@')) == NULL)  			goto parse_failed;  		*delim = 0; +		if (*cur == ' ' || *cur == '\t') +			printk(KERN_INFO "%s: warning: whitespace" +					"is not allowed\n", np->name);  		np->remote_port = simple_strtol(cur, NULL, 10);  		cur = delim;  	} @@ -708,7 +712,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt)  	return 0;   parse_failed: -	printk(KERN_INFO "%s: couldn't parse config at %s!\n", +	printk(KERN_INFO "%s: couldn't parse config at '%s'!\n",  	       np->name, cur);  	return -1;  } @@ -735,7 +739,7 @@ int netpoll_setup(struct netpoll *np)  		npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL);  		if (!npinfo) {  			err = -ENOMEM; -			goto release; +			goto put;  		}  		npinfo->rx_flags = 0; @@ -845,7 +849,7 @@ int netpoll_setup(struct netpoll *np)  		kfree(npinfo);  	} - +put:  	dev_put(ndev);  	return err;  } diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 4568120d853..31e85d327aa 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -602,12 +602,19 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a,  	a->tx_compressed = b->tx_compressed;  }; +/* All VF info */  static inline int rtnl_vfinfo_size(const struct net_device *dev)  { -	if (dev->dev.parent && dev_is_pci(dev->dev.parent)) -		return dev_num_vf(dev->dev.parent) * -			sizeof(struct ifla_vf_info); -	else +	if (dev->dev.parent && dev_is_pci(dev->dev.parent)) { + +		int num_vfs = dev_num_vf(dev->dev.parent); +		size_t size = nlmsg_total_size(sizeof(struct nlattr)); +		size += nlmsg_total_size(num_vfs * sizeof(struct nlattr)); +		size += num_vfs * (sizeof(struct ifla_vf_mac) + +				  sizeof(struct ifla_vf_vlan) + +				  sizeof(struct ifla_vf_tx_rate)); +		return size; +	} else  		return 0;  } @@ -629,7 +636,7 @@ static inline size_t if_nlmsg_size(const struct net_device *dev)  	       + nla_total_size(1) /* IFLA_OPERSTATE */  	       + nla_total_size(1) /* IFLA_LINKMODE */  	       + nla_total_size(4) /* IFLA_NUM_VF */ -	       + nla_total_size(rtnl_vfinfo_size(dev)) /* IFLA_VFINFO */ +	       + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */  	       + rtnl_link_get_size(dev); /* IFLA_LINKINFO */  } @@ -700,14 +707,37 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,  	if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) {  		int i; -		struct ifla_vf_info ivi; -		NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)); -		for (i = 0; i < dev_num_vf(dev->dev.parent); i++) { +		struct nlattr *vfinfo, *vf; +		int num_vfs = dev_num_vf(dev->dev.parent); + +		NLA_PUT_U32(skb, IFLA_NUM_VF, num_vfs); +		vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST); +		if (!vfinfo) +			goto nla_put_failure; +		for (i = 0; i < num_vfs; i++) { +			struct ifla_vf_info ivi; +			struct ifla_vf_mac vf_mac; +			struct ifla_vf_vlan vf_vlan; +			struct ifla_vf_tx_rate vf_tx_rate;  			if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi))  				break; -			NLA_PUT(skb, IFLA_VFINFO, sizeof(ivi), &ivi); +			vf_mac.vf = vf_vlan.vf = vf_tx_rate.vf = ivi.vf; +			memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); +			vf_vlan.vlan = ivi.vlan; +			vf_vlan.qos = ivi.qos; +			vf_tx_rate.rate = ivi.tx_rate; +			vf = nla_nest_start(skb, IFLA_VF_INFO); +			if (!vf) { +				nla_nest_cancel(skb, vfinfo); +				goto nla_put_failure; +			} +			NLA_PUT(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac); +			NLA_PUT(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan); +			NLA_PUT(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate), &vf_tx_rate); +			nla_nest_end(skb, vf);  		} +		nla_nest_end(skb, vfinfo);  	}  	if (dev->rtnl_link_ops) {  		if (rtnl_link_fill(skb, dev) < 0) @@ -769,12 +799,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {  	[IFLA_LINKINFO]		= { .type = NLA_NESTED },  	[IFLA_NET_NS_PID]	= { .type = NLA_U32 },  	[IFLA_IFALIAS]	        = { .type = NLA_STRING, .len = IFALIASZ-1 }, -	[IFLA_VF_MAC]		= { .type = NLA_BINARY, -				    .len = sizeof(struct ifla_vf_mac) }, -	[IFLA_VF_VLAN]		= { .type = NLA_BINARY, -				    .len = sizeof(struct ifla_vf_vlan) }, -	[IFLA_VF_TX_RATE]	= { .type = NLA_BINARY, -				    .len = sizeof(struct ifla_vf_tx_rate) }, +	[IFLA_VFINFO_LIST]	= {. type = NLA_NESTED },  };  EXPORT_SYMBOL(ifla_policy); @@ -783,6 +808,19 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {  	[IFLA_INFO_DATA]	= { .type = NLA_NESTED },  }; +static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = { +	[IFLA_VF_INFO]		= { .type = NLA_NESTED }, +}; + +static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { +	[IFLA_VF_MAC]		= { .type = NLA_BINARY, +				    .len = sizeof(struct ifla_vf_mac) }, +	[IFLA_VF_VLAN]		= { .type = NLA_BINARY, +				    .len = sizeof(struct ifla_vf_vlan) }, +	[IFLA_VF_TX_RATE]	= { .type = NLA_BINARY, +				    .len = sizeof(struct ifla_vf_tx_rate) }, +}; +  struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])  {  	struct net *net; @@ -812,6 +850,52 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])  	return 0;  } +static int do_setvfinfo(struct net_device *dev, struct nlattr *attr) +{ +	int rem, err = -EINVAL; +	struct nlattr *vf; +	const struct net_device_ops *ops = dev->netdev_ops; + +	nla_for_each_nested(vf, attr, rem) { +		switch (nla_type(vf)) { +		case IFLA_VF_MAC: { +			struct ifla_vf_mac *ivm; +			ivm = nla_data(vf); +			err = -EOPNOTSUPP; +			if (ops->ndo_set_vf_mac) +				err = ops->ndo_set_vf_mac(dev, ivm->vf, +							  ivm->mac); +			break; +		} +		case IFLA_VF_VLAN: { +			struct ifla_vf_vlan *ivv; +			ivv = nla_data(vf); +			err = -EOPNOTSUPP; +			if (ops->ndo_set_vf_vlan) +				err = ops->ndo_set_vf_vlan(dev, ivv->vf, +							   ivv->vlan, +							   ivv->qos); +			break; +		} +		case IFLA_VF_TX_RATE: { +			struct ifla_vf_tx_rate *ivt; +			ivt = nla_data(vf); +			err = -EOPNOTSUPP; +			if (ops->ndo_set_vf_tx_rate) +				err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, +							      ivt->rate); +			break; +		} +		default: +			err = -EINVAL; +			break; +		} +		if (err) +			break; +	} +	return err; +} +  static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,  		      struct nlattr **tb, char *ifname, int modified)  { @@ -942,40 +1026,17 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,  		write_unlock_bh(&dev_base_lock);  	} -	if (tb[IFLA_VF_MAC]) { -		struct ifla_vf_mac *ivm; -		ivm = nla_data(tb[IFLA_VF_MAC]); -		err = -EOPNOTSUPP; -		if (ops->ndo_set_vf_mac) -			err = ops->ndo_set_vf_mac(dev, ivm->vf, ivm->mac); -		if (err < 0) -			goto errout; -		modified = 1; -	} - -	if (tb[IFLA_VF_VLAN]) { -		struct ifla_vf_vlan *ivv; -		ivv = nla_data(tb[IFLA_VF_VLAN]); -		err = -EOPNOTSUPP; -		if (ops->ndo_set_vf_vlan) -			err = ops->ndo_set_vf_vlan(dev, ivv->vf, -						   ivv->vlan, -						   ivv->qos); -		if (err < 0) -			goto errout; -		modified = 1; -	} -	err = 0; - -	if (tb[IFLA_VF_TX_RATE]) { -		struct ifla_vf_tx_rate *ivt; -		ivt = nla_data(tb[IFLA_VF_TX_RATE]); -		err = -EOPNOTSUPP; -		if (ops->ndo_set_vf_tx_rate) -			err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, ivt->rate); -		if (err < 0) -			goto errout; -		modified = 1; +	if (tb[IFLA_VFINFO_LIST]) { +		struct nlattr *attr; +		int rem; +		nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) { +			if (nla_type(attr) != IFLA_VF_INFO) +				goto errout; +			err = do_setvfinfo(dev, attr); +			if (err < 0) +				goto errout; +			modified = 1; +		}  	}  	err = 0; @@ -1270,10 +1331,11 @@ replay:  			err = ops->newlink(net, dev, tb, data);  		else  			err = register_netdevice(dev); -		if (err < 0 && !IS_ERR(dev)) { + +		if (err < 0 && !IS_ERR(dev))  			free_netdev(dev); +		if (err < 0)  			goto out; -		}  		err = rtnl_configure_link(dev, ifm);  		if (err < 0) diff --git a/net/core/scm.c b/net/core/scm.c index 9b264634acf..b88f6f9d0b9 100644 --- a/net/core/scm.c +++ b/net/core/scm.c @@ -26,6 +26,7 @@  #include <linux/security.h>  #include <linux/pid.h>  #include <linux/nsproxy.h> +#include <linux/slab.h>  #include <asm/system.h>  #include <asm/uaccess.h> diff --git a/net/core/sock.c b/net/core/sock.c index fcd397a762f..c5812bbc2cc 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -340,8 +340,12 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested)  		rc = sk_backlog_rcv(sk, skb);  		mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_); -	} else -		sk_add_backlog(sk, skb); +	} else if (sk_add_backlog(sk, skb)) { +		bh_unlock_sock(sk); +		atomic_inc(&sk->sk_drops); +		goto discard_and_relse; +	} +  	bh_unlock_sock(sk);  out:  	sock_put(sk); @@ -1139,6 +1143,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)  		sock_lock_init(newsk);  		bh_lock_sock(newsk);  		newsk->sk_backlog.head	= newsk->sk_backlog.tail = NULL; +		newsk->sk_backlog.len = 0;  		atomic_set(&newsk->sk_rmem_alloc, 0);  		/* @@ -1542,6 +1547,12 @@ static void __release_sock(struct sock *sk)  		bh_lock_sock(sk);  	} while ((skb = sk->sk_backlog.head) != NULL); + +	/* +	 * Doing the zeroing here guarantee we can not loop forever +	 * while a wild producer attempts to flood us. +	 */ +	sk->sk_backlog.len = 0;  }  /** @@ -1874,6 +1885,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)  	sk->sk_allocation	=	GFP_KERNEL;  	sk->sk_rcvbuf		=	sysctl_rmem_default;  	sk->sk_sndbuf		=	sysctl_wmem_default; +	sk->sk_backlog.limit	=	sk->sk_rcvbuf << 1;  	sk->sk_state		=	TCP_CLOSE;  	sk_set_socket(sk, sock); @@ -2276,7 +2288,8 @@ out_free_request_sock_slab:  		prot->rsk_prot->slab = NULL;  	}  out_free_request_sock_slab_name: -	kfree(prot->rsk_prot->slab_name); +	if (prot->rsk_prot) +		kfree(prot->rsk_prot->slab_name);  out_free_sock_slab:  	kmem_cache_destroy(prot->slab);  	prot->slab = NULL; diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 06124872af5..b7b6b8208f7 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -12,6 +12,7 @@  #include <linux/netdevice.h>  #include <linux/ratelimit.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <net/ip.h>  #include <net/sock.h> diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 813e399220a..19ac2b98548 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -19,6 +19,7 @@  #include <linux/netdevice.h>  #include <linux/netlink.h> +#include <linux/slab.h>  #include <net/netlink.h>  #include <net/rtnetlink.h>  #include <linux/dcbnl.h> diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c index 49d27c556be..36479ca61e0 100644 --- a/net/dccp/ccid.c +++ b/net/dccp/ccid.c @@ -11,6 +11,8 @@   *	published by the Free Software Foundation.   */ +#include <linux/slab.h> +  #include "ccid.h"  #include "ccids/lib/tfrc.h" diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index a47a8c918ee..9b3ae9922be 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -23,6 +23,7 @@  /*   * This implementation should follow RFC 4341   */ +#include <linux/slab.h>  #include "../feat.h"  #include "../ccid.h"  #include "../dccp.h" diff --git a/net/dccp/feat.c b/net/dccp/feat.c index 972b8dc918d..df7dd26cf07 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c @@ -22,6 +22,7 @@   *  2 of the License, or (at your option) any later version.   */  #include <linux/module.h> +#include <linux/slab.h>  #include "ccid.h"  #include "feat.h" diff --git a/net/dccp/input.c b/net/dccp/input.c index 7648f316310..9ec71742602 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -12,6 +12,7 @@  #include <linux/dccp.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/sock.h> diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index b195c4feaa0..52ffa1cde15 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -12,6 +12,7 @@  #include <linux/dccp.h>  #include <linux/icmp.h> +#include <linux/slab.h>  #include <linux/module.h>  #include <linux/skbuff.h>  #include <linux/random.h> @@ -998,11 +999,11 @@ static struct inet_protosw dccp_v4_protosw = {  static int __net_init dccp_v4_init_net(struct net *net)  { -	int err; +	if (dccp_hashinfo.bhash == NULL) +		return -ESOCKTNOSUPPORT; -	err = inet_ctl_sock_create(&net->dccp.v4_ctl_sk, PF_INET, -				   SOCK_DCCP, IPPROTO_DCCP, net); -	return err; +	return inet_ctl_sock_create(&net->dccp.v4_ctl_sk, PF_INET, +				    SOCK_DCCP, IPPROTO_DCCP, net);  }  static void __net_exit dccp_v4_exit_net(struct net *net) diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 1aec6349e85..3b11e41a292 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -14,6 +14,7 @@  #include <linux/module.h>  #include <linux/random.h> +#include <linux/slab.h>  #include <linux/xfrm.h>  #include <net/addrconf.h> @@ -1191,11 +1192,11 @@ static struct inet_protosw dccp_v6_protosw = {  static int __net_init dccp_v6_init_net(struct net *net)  { -	int err; +	if (dccp_hashinfo.bhash == NULL) +		return -ESOCKTNOSUPPORT; -	err = inet_ctl_sock_create(&net->dccp.v6_ctl_sk, PF_INET6, -				   SOCK_DCCP, IPPROTO_DCCP, net); -	return err; +	return inet_ctl_sock_create(&net->dccp.v6_ctl_sk, PF_INET6, +				    SOCK_DCCP, IPPROTO_DCCP, net);  }  static void __net_exit dccp_v6_exit_net(struct net *net) diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index af226a06314..128b089d3ae 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -11,6 +11,7 @@   */  #include <linux/dccp.h> +#include <linux/gfp.h>  #include <linux/kernel.h>  #include <linux/skbuff.h>  #include <linux/timer.h> @@ -254,7 +255,7 @@ int dccp_child_process(struct sock *parent, struct sock *child,  		 * in main socket hash table and lock on listening  		 * socket does not protect us more.  		 */ -		sk_add_backlog(child, skb); +		__sk_add_backlog(child, skb);  	}  	bh_unlock_sock(child); diff --git a/net/dccp/output.c b/net/dccp/output.c index d6bb753bf6a..fc3f436440b 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -13,6 +13,7 @@  #include <linux/dccp.h>  #include <linux/kernel.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/inet_sock.h>  #include <net/sock.h> diff --git a/net/dccp/probe.c b/net/dccp/probe.c index f5b3464f124..078e48d442f 100644 --- a/net/dccp/probe.c +++ b/net/dccp/probe.c @@ -30,6 +30,7 @@  #include <linux/module.h>  #include <linux/kfifo.h>  #include <linux/vmalloc.h> +#include <linux/gfp.h>  #include <net/net_namespace.h>  #include "dccp.h" diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 0ef7061920c..a0e38d8018f 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -20,6 +20,7 @@  #include <linux/if_arp.h>  #include <linux/init.h>  #include <linux/random.h> +#include <linux/slab.h>  #include <net/checksum.h>  #include <net/inet_sock.h> @@ -1036,7 +1037,7 @@ static int __init dccp_init(void)  		     FIELD_SIZEOF(struct sk_buff, cb));  	rc = percpu_counter_init(&dccp_orphan_count, 0);  	if (rc) -		goto out; +		goto out_fail;  	rc = -ENOBUFS;  	inet_hashinfo_init(&dccp_hashinfo);  	dccp_hashinfo.bind_bucket_cachep = @@ -1125,8 +1126,9 @@ static int __init dccp_init(void)  		goto out_sysctl_exit;  	dccp_timestamping_init(); -out: -	return rc; + +	return 0; +  out_sysctl_exit:  	dccp_sysctl_exit();  out_ackvec_exit: @@ -1135,18 +1137,19 @@ out_free_dccp_mib:  	dccp_mib_exit();  out_free_dccp_bhash:  	free_pages((unsigned long)dccp_hashinfo.bhash, bhash_order); -	dccp_hashinfo.bhash = NULL;  out_free_dccp_locks:  	inet_ehash_locks_free(&dccp_hashinfo);  out_free_dccp_ehash:  	free_pages((unsigned long)dccp_hashinfo.ehash, ehash_order); -	dccp_hashinfo.ehash = NULL;  out_free_bind_bucket_cachep:  	kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep); -	dccp_hashinfo.bind_bucket_cachep = NULL;  out_free_percpu:  	percpu_counter_destroy(&dccp_orphan_count); -	goto out; +out_fail: +	dccp_hashinfo.bhash = NULL; +	dccp_hashinfo.ehash = NULL; +	dccp_hashinfo.bind_bucket_cachep = NULL; +	return rc;  }  static void __exit dccp_fini(void) diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 238af093495..cead68eb254 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -40,6 +40,7 @@  #include <linux/skbuff.h>  #include <linux/sysctl.h>  #include <linux/notifier.h> +#include <linux/slab.h>  #include <asm/uaccess.h>  #include <asm/system.h>  #include <net/net_namespace.h> diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c index e9d48700e83..4ab96c15166 100644 --- a/net/decnet/dn_fib.c +++ b/net/decnet/dn_fib.c @@ -20,6 +20,7 @@  #include <linux/string.h>  #include <linux/net.h>  #include <linux/socket.h> +#include <linux/slab.h>  #include <linux/sockios.h>  #include <linux/init.h>  #include <linux/skbuff.h> diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index 794b5bf95af..deb723dba44 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c @@ -28,6 +28,7 @@  #include <linux/module.h>  #include <linux/socket.h>  #include <linux/if_arp.h> +#include <linux/slab.h>  #include <linux/if_ether.h>  #include <linux/init.h>  #include <linux/proc_fs.h> diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index 932408dca86..25a37299bc6 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c @@ -57,6 +57,7 @@  #include <linux/netdevice.h>  #include <linux/inet.h>  #include <linux/route.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/tcp_states.h>  #include <asm/system.h> diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c index a65e929ce76..baeb1eaf011 100644 --- a/net/decnet/dn_nsp_out.c +++ b/net/decnet/dn_nsp_out.c @@ -50,6 +50,7 @@  #include <linux/netdevice.h>  #include <linux/inet.h>  #include <linux/route.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <asm/system.h>  #include <linux/fcntl.h> diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index a7bf03ca0a3..70ebe74027d 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -66,6 +66,7 @@  #include <linux/inet.h>  #include <linux/route.h>  #include <linux/in_route.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <linux/mm.h>  #include <linux/proc_fs.h> diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c index b9a33bb5e9c..f2abd375569 100644 --- a/net/decnet/dn_table.c +++ b/net/decnet/dn_table.c @@ -15,6 +15,7 @@  #include <linux/string.h>  #include <linux/net.h>  #include <linux/socket.h> +#include <linux/slab.h>  #include <linux/sockios.h>  #include <linux/init.h>  #include <linux/skbuff.h> diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c index 6d2bd320204..64a7f39e069 100644 --- a/net/decnet/netfilter/dn_rtmsg.c +++ b/net/decnet/netfilter/dn_rtmsg.c @@ -14,6 +14,7 @@   */  #include <linux/module.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <linux/init.h>  #include <linux/netdevice.h>  #include <linux/netfilter.h> diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 71489f69a42..6112a12578b 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -11,6 +11,7 @@  #include <linux/list.h>  #include <linux/netdevice.h>  #include <linux/platform_device.h> +#include <linux/slab.h>  #include <net/dsa.h>  #include "dsa_priv.h" diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c index cdf2d28a029..98dfe80b453 100644 --- a/net/dsa/tag_dsa.c +++ b/net/dsa/tag_dsa.c @@ -11,6 +11,7 @@  #include <linux/etherdevice.h>  #include <linux/list.h>  #include <linux/netdevice.h> +#include <linux/slab.h>  #include "dsa_priv.h"  #define DSA_HLEN	4 diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c index 8f53948cff4..6f383322ad2 100644 --- a/net/dsa/tag_edsa.c +++ b/net/dsa/tag_edsa.c @@ -11,6 +11,7 @@  #include <linux/etherdevice.h>  #include <linux/list.h>  #include <linux/netdevice.h> +#include <linux/slab.h>  #include "dsa_priv.h"  #define DSA_HLEN	4 diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c index a85c829853c..d6d7d0add3c 100644 --- a/net/dsa/tag_trailer.c +++ b/net/dsa/tag_trailer.c @@ -11,6 +11,7 @@  #include <linux/etherdevice.h>  #include <linux/list.h>  #include <linux/netdevice.h> +#include <linux/slab.h>  #include "dsa_priv.h"  netdev_tx_t trailer_xmit(struct sk_buff *skb, struct net_device *dev) diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 29b4931aae5..2a5a8053e00 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -30,6 +30,7 @@  #include <linux/wireless.h>  #include <linux/skbuff.h>  #include <linux/udp.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/inet_common.h>  #include <linux/stat.h> diff --git a/net/ethernet/pe2.c b/net/ethernet/pe2.c index d60e15d9365..eb00796758c 100644 --- a/net/ethernet/pe2.c +++ b/net/ethernet/pe2.c @@ -3,6 +3,7 @@  #include <linux/module.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/datalink.h> diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c index bad1c49fd96..93c91b633a5 100644 --- a/net/ieee802154/af_ieee802154.c +++ b/net/ieee802154/af_ieee802154.c @@ -28,6 +28,7 @@  #include <linux/if.h>  #include <linux/termios.h>	/* For TIOCOUTQ/INQ */  #include <linux/list.h> +#include <linux/slab.h>  #include <net/datalink.h>  #include <net/psnap.h>  #include <net/sock.h> @@ -126,6 +127,9 @@ static int ieee802154_sock_connect(struct socket *sock, struct sockaddr *uaddr,  {  	struct sock *sk = sock->sk; +	if (addr_len < sizeof(uaddr->sa_family)) +		return -EINVAL; +  	if (uaddr->sa_family == AF_UNSPEC)  		return sk->sk_prot->disconnect(sk, flags); @@ -147,6 +151,9 @@ static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg,  	dev_load(sock_net(sk), ifr.ifr_name);  	dev = dev_get_by_name(sock_net(sk), ifr.ifr_name); +	if (!dev) +		return -ENODEV; +  	if (dev->type == ARPHRD_IEEE802154 && dev->netdev_ops->ndo_do_ioctl)  		ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, cmd); diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c index 9aac5aee157..1a3334c2609 100644 --- a/net/ieee802154/dgram.c +++ b/net/ieee802154/dgram.c @@ -25,6 +25,7 @@  #include <linux/module.h>  #include <linux/if_arp.h>  #include <linux/list.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/af_ieee802154.h>  #include <net/ieee802154.h> diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index 33137b99e47..c8097ae2482 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c @@ -23,6 +23,7 @@   */  #include <linux/kernel.h> +#include <linux/gfp.h>  #include <net/genetlink.h>  #include <linux/nl802154.h> diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c index 135c1678fb1..71ee1108d4f 100644 --- a/net/ieee802154/nl-mac.c +++ b/net/ieee802154/nl-mac.c @@ -22,6 +22,7 @@   * Maxim Osipov <maxim.osipov@siemens.com>   */ +#include <linux/gfp.h>  #include <linux/kernel.h>  #include <linux/if_arp.h>  #include <linux/netdevice.h> diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index 199a2d9d12f..ed0eab39f53 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c @@ -23,6 +23,7 @@   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <net/netlink.h>  #include <net/genetlink.h>  #include <net/wpan-phy.h> diff --git a/net/ieee802154/raw.c b/net/ieee802154/raw.c index 9c9b85c0003..10970ca8574 100644 --- a/net/ieee802154/raw.c +++ b/net/ieee802154/raw.c @@ -25,6 +25,7 @@  #include <linux/module.h>  #include <linux/if_arp.h>  #include <linux/list.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/af_ieee802154.h> diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c index 268691256a6..3d803a1b9fb 100644 --- a/net/ieee802154/wpan-class.c +++ b/net/ieee802154/wpan-class.c @@ -16,6 +16,7 @@   *   */ +#include <linux/slab.h>  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/device.h> diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 33b7dffa773..f7135742238 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -86,6 +86,7 @@  #include <linux/poll.h>  #include <linux/netfilter_ipv4.h>  #include <linux/random.h> +#include <linux/slab.h>  #include <asm/uaccess.h>  #include <asm/system.h> @@ -530,6 +531,8 @@ int inet_dgram_connect(struct socket *sock, struct sockaddr * uaddr,  {  	struct sock *sk = sock->sk; +	if (addr_len < sizeof(uaddr->sa_family)) +		return -EINVAL;  	if (uaddr->sa_family == AF_UNSPEC)  		return sk->sk_prot->disconnect(sk, flags); @@ -573,6 +576,9 @@ int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,  	int err;  	long timeo; +	if (addr_len < sizeof(uaddr->sa_family)) +		return -EINVAL; +  	lock_sock(sk);  	if (uaddr->sa_family == AF_UNSPEC) { diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 987b47dc69a..880a5ec6dce 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -1,6 +1,7 @@  #include <crypto/hash.h>  #include <linux/err.h>  #include <linux/module.h> +#include <linux/slab.h>  #include <net/ip.h>  #include <net/xfrm.h>  #include <net/ah.h> diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index c4dd1354280..80769f1f9fa 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -98,6 +98,7 @@  #include <linux/net.h>  #include <linux/rcupdate.h>  #include <linux/jhash.h> +#include <linux/slab.h>  #ifdef CONFIG_SYSCTL  #include <linux/sysctl.h>  #endif @@ -660,13 +661,13 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,  #endif  #endif -#ifdef CONFIG_FDDI +#if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE)  	case ARPHRD_FDDI:  		arp->ar_hrd = htons(ARPHRD_ETHER);  		arp->ar_pro = htons(ETH_P_IP);  		break;  #endif -#ifdef CONFIG_TR +#if defined(CONFIG_TR) || defined(CONFIG_TR_MODULE)  	case ARPHRD_IEEE802_TR:  		arp->ar_hrd = htons(ARPHRD_IEEE802);  		arp->ar_pro = htons(ETH_P_IP); @@ -1050,7 +1051,7 @@ static int arp_req_set(struct net *net, struct arpreq *r,  			return -EINVAL;  	}  	switch (dev->type) { -#ifdef CONFIG_FDDI +#if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE)  	case ARPHRD_FDDI:  		/*  		 * According to RFC 1390, FDDI devices should accept ARP diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 1e029dc7545..c97cd9ff697 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -44,6 +44,7 @@  #include <linux/string.h>  #include <linux/jhash.h>  #include <linux/audit.h> +#include <linux/slab.h>  #include <net/ip.h>  #include <net/icmp.h>  #include <net/tcp.h> diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 51ca946e339..90e3d6379a4 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -50,6 +50,7 @@  #include <linux/notifier.h>  #include <linux/inetdevice.h>  #include <linux/igmp.h> +#include <linux/slab.h>  #ifdef CONFIG_SYSCTL  #include <linux/sysctl.h>  #endif @@ -1194,7 +1195,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)  		hlist_for_each_entry_rcu(dev, node, head, index_hlist) {  			if (idx < s_idx)  				goto cont; -			if (idx > s_idx) +			if (h > s_h || idx > s_idx)  				s_ip_idx = 0;  			in_dev = __in_dev_get_rcu(dev);  			if (!in_dev) diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 9b3e28ed524..4f0ed458c88 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -34,6 +34,7 @@  #include <linux/skbuff.h>  #include <linux/init.h>  #include <linux/list.h> +#include <linux/slab.h>  #include <net/ip.h>  #include <net/protocol.h> diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c index 14972017b9c..4ed7e0dea1b 100644 --- a/net/ipv4/fib_hash.c +++ b/net/ipv4/fib_hash.c @@ -32,6 +32,7 @@  #include <linux/skbuff.h>  #include <linux/netlink.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/ip.h> diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 1af0ea0fb6a..20f09c5b31e 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -32,6 +32,7 @@  #include <linux/proc_fs.h>  #include <linux/skbuff.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <net/arp.h>  #include <net/ip.h> diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index af5d8979286..c98f115fb0f 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -71,6 +71,7 @@  #include <linux/netlink.h>  #include <linux/init.h>  #include <linux/list.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/ip.h>  #include <net/protocol.h> @@ -208,7 +209,9 @@ static inline struct node *tnode_get_child_rcu(struct tnode *tn, unsigned int i)  {  	struct node *ret = tnode_get_child(tn, i); -	return rcu_dereference(ret); +	return rcu_dereference_check(ret, +				     rcu_read_lock_held() || +				     lockdep_rtnl_is_held());  }  static inline int tnode_child_length(const struct tnode *tn) @@ -961,7 +964,9 @@ fib_find_node(struct trie *t, u32 key)  	struct node *n;  	pos = 0; -	n = rcu_dereference(t->trie); +	n = rcu_dereference_check(t->trie, +				  rcu_read_lock_held() || +				  lockdep_rtnl_is_held());  	while (n != NULL &&  NODE_TYPE(n) == T_TNODE) {  		tn = (struct tnode *) n; diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 4b4c2bcd15d..ac4dec13273 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -74,6 +74,7 @@  #include <linux/netdevice.h>  #include <linux/string.h>  #include <linux/netfilter_ipv4.h> +#include <linux/slab.h>  #include <net/snmp.h>  #include <net/ip.h>  #include <net/route.h> diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 63bf298ca10..15d3eeda92f 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -71,6 +71,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <asm/uaccess.h>  #include <asm/system.h>  #include <linux/types.h> diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 1aaa8110d84..e5fa2ddce32 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -14,6 +14,7 @@  #include <linux/types.h>  #include <linux/fcntl.h>  #include <linux/random.h> +#include <linux/slab.h>  #include <linux/cache.h>  #include <linux/init.h>  #include <linux/time.h> diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index eaf3e2c8646..a2ca6aed763 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c @@ -19,6 +19,7 @@  #include <linux/random.h>  #include <linux/skbuff.h>  #include <linux/rtnetlink.h> +#include <linux/slab.h>  #include <net/inet_frag.h> diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index cc94cc2d8b2..c5af909cf70 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -10,6 +10,7 @@  #include <linux/kernel.h>  #include <linux/kmemcheck.h> +#include <linux/slab.h>  #include <net/inet_hashtables.h>  #include <net/inet_timewait_sock.h>  #include <net/ip.h> diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index a2991bc8e32..af10942b326 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -25,6 +25,7 @@  #include <linux/ip.h>  #include <linux/icmp.h>  #include <linux/netdevice.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/ip.h>  #include <net/tcp.h> diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index b59430bc041..75347ea70ea 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -32,6 +32,7 @@  #include <linux/netdevice.h>  #include <linux/jhash.h>  #include <linux/random.h> +#include <linux/slab.h>  #include <net/route.h>  #include <net/dst.h>  #include <net/sock.h> diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index c0c5274d027..fe381d12ecd 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -14,6 +14,7 @@  #include <linux/module.h>  #include <linux/types.h>  #include <linux/kernel.h> +#include <linux/slab.h>  #include <asm/uaccess.h>  #include <linux/skbuff.h>  #include <linux/netdevice.h> @@ -810,11 +811,13 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev  			tunnel->err_count = 0;  	} -	max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen; +	max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + rt->u.dst.header_len;  	if (skb_headroom(skb) < max_headroom || skb_shared(skb)||  	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {  		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); +		if (max_headroom > dev->needed_headroom) +			dev->needed_headroom = max_headroom;  		if (!new_skb) {  			ip_rt_put(rt);  			txq->tx_dropped++; @@ -1144,12 +1147,9 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev,  	if (saddr)  		memcpy(&iph->saddr, saddr, 4); - -	if (daddr) { +	if (daddr)  		memcpy(&iph->daddr, daddr, 4); -		return t->hlen; -	} -	if (iph->daddr && !ipv4_is_multicast(iph->daddr)) +	if (iph->daddr)  		return t->hlen;  	return -t->hlen; diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index c29de9879fd..f8ab7a380d4 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -119,6 +119,7 @@  #include <linux/kernel.h>  #include <linux/string.h>  #include <linux/errno.h> +#include <linux/slab.h>  #include <linux/net.h>  #include <linux/socket.h> diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 94bf105ef3c..4c09a31fd14 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -11,6 +11,7 @@  #include <linux/capability.h>  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/types.h>  #include <asm/uaccess.h>  #include <linux/skbuff.h> diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 3451799e3db..d1bcc9f21d4 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -51,6 +51,7 @@  #include <linux/string.h>  #include <linux/errno.h>  #include <linux/highmem.h> +#include <linux/slab.h>  #include <linux/socket.h>  #include <linux/sockios.h> @@ -119,7 +120,7 @@ static int ip_dev_loopback_xmit(struct sk_buff *newskb)  	newskb->pkt_type = PACKET_LOOPBACK;  	newskb->ip_summed = CHECKSUM_UNNECESSARY;  	WARN_ON(!skb_dst(newskb)); -	netif_rx(newskb); +	netif_rx_ni(newskb);  	return 0;  } diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 644dc43a55d..1e64dabbd23 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -23,6 +23,7 @@  #include <linux/icmp.h>  #include <linux/inetdevice.h>  #include <linux/netdevice.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/ip.h>  #include <net/icmp.h> diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 10a6a604bf3..067ce9e043d 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -53,6 +53,7 @@  #include <linux/root_dev.h>  #include <linux/delay.h>  #include <linux/nfs_fs.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/arp.h>  #include <net/ip.h> @@ -187,6 +188,16 @@ struct ic_device {  static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */  static struct net_device *ic_dev __initdata = NULL;	/* Selected device */ +static bool __init ic_device_match(struct net_device *dev) +{ +	if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) : +	    (!(dev->flags & IFF_LOOPBACK) && +	     (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) && +	     strncmp(dev->name, "dummy", 5))) +		return true; +	return false; +} +  static int __init ic_open_devs(void)  {  	struct ic_device *d, **last; @@ -207,10 +218,7 @@ static int __init ic_open_devs(void)  	for_each_netdev(&init_net, dev) {  		if (dev->flags & IFF_LOOPBACK)  			continue; -		if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) : -		    (!(dev->flags & IFF_LOOPBACK) && -		     (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) && -		     strncmp(dev->name, "dummy", 5))) { +		if (ic_device_match(dev)) {  			int able = 0;  			if (dev->mtu >= 364)  				able |= IC_BOOTP; @@ -228,7 +236,7 @@ static int __init ic_open_devs(void)  			}  			if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) {  				rtnl_unlock(); -				return -1; +				return -ENOMEM;  			}  			d->dev = dev;  			*last = d; @@ -253,7 +261,7 @@ static int __init ic_open_devs(void)  			printk(KERN_ERR "IP-Config: Device `%s' not found.\n", user_dev_name);  		else  			printk(KERN_ERR "IP-Config: No network devices available.\n"); -		return -1; +		return -ENODEV;  	}  	return 0;  } @@ -1303,6 +1311,32 @@ __be32 __init root_nfs_parse_addr(char *name)  	return addr;  } +#define DEVICE_WAIT_MAX		12 /* 12 seconds */ + +static int __init wait_for_devices(void) +{ +	int i; + +	msleep(CONF_PRE_OPEN); +	for (i = 0; i < DEVICE_WAIT_MAX; i++) { +		struct net_device *dev; +		int found = 0; + +		rtnl_lock(); +		for_each_netdev(&init_net, dev) { +			if (ic_device_match(dev)) { +				found = 1; +				break; +			} +		} +		rtnl_unlock(); +		if (found) +			return 0; +		ssleep(1); +	} +	return -ENODEV; +} +  /*   *	IP Autoconfig dispatcher.   */ @@ -1313,6 +1347,7 @@ static int __init ip_auto_config(void)  #ifdef IPCONFIG_DYNAMIC  	int retries = CONF_OPEN_RETRIES;  #endif +	int err;  #ifdef CONFIG_PROC_FS  	proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops); @@ -1325,12 +1360,15 @@ static int __init ip_auto_config(void)  #ifdef IPCONFIG_DYNAMIC   try_try_again:  #endif -	/* Give hardware a chance to settle */ -	msleep(CONF_PRE_OPEN); +	/* Wait for devices to appear */ +	err = wait_for_devices(); +	if (err) +		return err;  	/* Setup all network devices */ -	if (ic_open_devs() < 0) -		return -1; +	err = ic_open_devs(); +	if (err) +		return err;  	/* Give drivers a chance to settle */  	ssleep(CONF_POST_OPEN); diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 2f302d3ac9a..0b27b14dcc9 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -95,6 +95,7 @@  #include <linux/module.h>  #include <linux/types.h>  #include <linux/kernel.h> +#include <linux/slab.h>  #include <asm/uaccess.h>  #include <linux/skbuff.h>  #include <linux/netdevice.h> diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 8582e12e4a6..ec19a890c9a 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -47,6 +47,7 @@  #include <linux/mroute.h>  #include <linux/init.h>  #include <linux/if_ether.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/ip.h>  #include <net/protocol.h> @@ -753,7 +754,8 @@ ipmr_cache_unresolved(struct net *net, vifi_t vifi, struct sk_buff *skb)  		c->next = mfc_unres_queue;  		mfc_unres_queue = c; -		mod_timer(&ipmr_expire_timer, c->mfc_un.unres.expires); +		if (atomic_read(&net->ipv4.cache_resolve_queue_len) == 1) +			mod_timer(&ipmr_expire_timer, c->mfc_un.unres.expires);  	}  	/* @@ -802,6 +804,9 @@ static int ipmr_mfc_add(struct net *net, struct mfcctl *mfc, int mrtsock)  	int line;  	struct mfc_cache *uc, *c, **cp; +	if (mfc->mfcc_parent >= MAXVIFS) +		return -ENFILE; +  	line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr);  	for (cp = &net->ipv4.mfc_cache_array[line]; @@ -1613,17 +1618,20 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm)  	int ct;  	struct rtnexthop *nhp;  	struct net *net = mfc_net(c); -	struct net_device *dev = net->ipv4.vif_table[c->mfc_parent].dev;  	u8 *b = skb_tail_pointer(skb);  	struct rtattr *mp_head; -	if (dev) -		RTA_PUT(skb, RTA_IIF, 4, &dev->ifindex); +	/* If cache is unresolved, don't try to parse IIF and OIF */ +	if (c->mfc_parent > MAXVIFS) +		return -ENOENT; + +	if (VIF_EXISTS(net, c->mfc_parent)) +		RTA_PUT(skb, RTA_IIF, 4, &net->ipv4.vif_table[c->mfc_parent].dev->ifindex);  	mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0));  	for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { -		if (c->mfc_un.res.ttls[ct] < 255) { +		if (VIF_EXISTS(net, ct) && c->mfc_un.res.ttls[ct] < 255) {  			if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))  				goto rtattr_failure;  			nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index c14623fc4d5..82fb43c5c59 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -4,6 +4,7 @@  #include <linux/netfilter_ipv4.h>  #include <linux/ip.h>  #include <linux/skbuff.h> +#include <linux/gfp.h>  #include <net/route.h>  #include <net/xfrm.h>  #include <net/ip.h> diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index bfe26f32b93..79ca5e70d49 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c @@ -8,6 +8,7 @@  #include <linux/module.h>  #include <linux/netfilter/x_tables.h>  #include <linux/netfilter_arp/arp_tables.h> +#include <linux/slab.h>  MODULE_LICENSE("GPL");  MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 2855f1f38cb..e2787048aa0 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -26,6 +26,7 @@  #include <linux/security.h>  #include <linux/net.h>  #include <linux/mutex.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/sock.h>  #include <net/route.h> diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 0886f96c736..ab828400ed7 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -14,6 +14,7 @@  #include <linux/jhash.h>  #include <linux/bitops.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <linux/ip.h>  #include <linux/tcp.h>  #include <linux/udp.h> diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 5113b8f1a37..a0e8bcf0415 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -12,6 +12,7 @@  #include <linux/module.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <linux/ip.h>  #include <linux/udp.h>  #include <linux/icmp.h> diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 09a5d3f7cc4..0dbe697f164 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -33,6 +33,7 @@  #include <linux/module.h>  #include <linux/spinlock.h>  #include <linux/socket.h> +#include <linux/slab.h>  #include <linux/skbuff.h>  #include <linux/kernel.h>  #include <linux/timer.h> diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index c8dc9800d62..55392466daa 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -13,6 +13,7 @@  #include <linux/module.h>  #include <linux/moduleparam.h>  #include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/slab.h>  #include <net/ip.h>  MODULE_LICENSE("GPL"); diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index b9b83464cbf..294a2a32f29 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -12,6 +12,7 @@  #include <linux/netfilter_ipv4/ip_tables.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/route.h>  #include <linux/ip.h> diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 06fb9d11953..07fb710cd72 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -5,6 +5,7 @@   */  #include <linux/module.h>  #include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/slab.h>  #include <net/ip.h>  #define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c index cce2f64e6f2..be45bdc4c60 100644 --- a/net/ipv4/netfilter/iptable_security.c +++ b/net/ipv4/netfilter/iptable_security.c @@ -17,6 +17,7 @@   */  #include <linux/module.h>  #include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/slab.h>  #include <net/ip.h>  MODULE_LICENSE("GPL"); diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 4595281c286..4f8bddb760c 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -12,6 +12,7 @@  #include <linux/types.h>  #include <linux/timer.h>  #include <linux/skbuff.h> +#include <linux/gfp.h>  #include <net/checksum.h>  #include <net/icmp.h>  #include <net/ip.h> diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 4b6af4bb1f5..4a0c6b548ee 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c @@ -8,6 +8,7 @@   * published by the Free Software Foundation.   */  #include <linux/module.h> +#include <linux/gfp.h>  #include <linux/kmod.h>  #include <linux/types.h>  #include <linux/timer.h> diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index ab74cc0535e..26de2c1f7fa 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c @@ -15,6 +15,7 @@  #include <linux/kmod.h>  #include <linux/skbuff.h>  #include <linux/proc_fs.h> +#include <linux/slab.h>  #include <net/checksum.h>  #include <net/route.h>  #include <linux/bitops.h> diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index 0b9c7ce3d6c..4d85b6e55f2 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -43,6 +43,7 @@  #include <linux/moduleparam.h>  #include <linux/types.h>  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/in.h>  #include <linux/ip.h>  #include <linux/udp.h> diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 5678e9562c1..c39c9cf6bee 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c @@ -7,6 +7,7 @@   */  #include <linux/types.h>  #include <linux/icmp.h> +#include <linux/gfp.h>  #include <linux/ip.h>  #include <linux/netfilter.h>  #include <linux/netfilter_ipv4.h> diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 242ed230737..4f1f337f433 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -249,6 +249,8 @@ static const struct snmp_mib snmp4_net_list[] = {  	SNMP_MIB_ITEM("TCPSackShifted", LINUX_MIB_SACKSHIFTED),  	SNMP_MIB_ITEM("TCPSackMerged", LINUX_MIB_SACKMERGED),  	SNMP_MIB_ITEM("TCPSackShiftFallback", LINUX_MIB_SACKSHIFTFALLBACK), +	SNMP_MIB_ITEM("TCPBacklogDrop", LINUX_MIB_TCPBACKLOGDROP), +	SNMP_MIB_ITEM("TCPMinTTLDrop", LINUX_MIB_TCPMINTTLDROP),  	SNMP_MIB_SENTINEL  }; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index ce154b47f1d..cc6f097fbd5 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -60,7 +60,6 @@  #include <net/net_namespace.h>  #include <net/dst.h>  #include <net/sock.h> -#include <linux/gfp.h>  #include <linux/ip.h>  #include <linux/net.h>  #include <net/ip.h> diff --git a/net/ipv4/route.c b/net/ipv4/route.c index b2ba5581d2a..cb562fdd9b9 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -90,6 +90,7 @@  #include <linux/jhash.h>  #include <linux/rcupdate.h>  #include <linux/times.h> +#include <linux/slab.h>  #include <net/dst.h>  #include <net/net_namespace.h>  #include <net/protocol.h> @@ -146,7 +147,6 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);  static void		 ipv4_link_failure(struct sk_buff *skb);  static void		 ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu);  static int rt_garbage_collect(struct dst_ops *ops); -static void rt_emergency_hash_rebuild(struct net *net);  static struct dst_ops ipv4_dst_ops = { @@ -780,11 +780,30 @@ static void rt_do_flush(int process_context)  #define FRACT_BITS 3  #define ONE (1UL << FRACT_BITS) +/* + * Given a hash chain and an item in this hash chain, + * find if a previous entry has the same hash_inputs + * (but differs on tos, mark or oif) + * Returns 0 if an alias is found. + * Returns ONE if rth has no alias before itself. + */ +static int has_noalias(const struct rtable *head, const struct rtable *rth) +{ +	const struct rtable *aux = head; + +	while (aux != rth) { +		if (compare_hash_inputs(&aux->fl, &rth->fl)) +			return 0; +		aux = aux->u.dst.rt_next; +	} +	return ONE; +} +  static void rt_check_expire(void)  {  	static unsigned int rover;  	unsigned int i = rover, goal; -	struct rtable *rth, *aux, **rthp; +	struct rtable *rth, **rthp;  	unsigned long samples = 0;  	unsigned long sum = 0, sum2 = 0;  	unsigned long delta; @@ -835,15 +854,7 @@ nofree:  					 * attributes don't unfairly skew  					 * the length computation  					 */ -					for (aux = rt_hash_table[i].chain;;) { -						if (aux == rth) { -							length += ONE; -							break; -						} -						if (compare_hash_inputs(&aux->fl, &rth->fl)) -							break; -						aux = aux->u.dst.rt_next; -					} +					length += has_noalias(rt_hash_table[i].chain, rth);  					continue;  				}  			} else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout)) @@ -922,10 +933,8 @@ static void rt_secret_rebuild_oneshot(struct net *net)  {  	del_timer_sync(&net->ipv4.rt_secret_timer);  	rt_cache_invalidate(net); -	if (ip_rt_secret_interval) { -		net->ipv4.rt_secret_timer.expires += ip_rt_secret_interval; -		add_timer(&net->ipv4.rt_secret_timer); -	} +	if (ip_rt_secret_interval) +		mod_timer(&net->ipv4.rt_secret_timer, jiffies + ip_rt_secret_interval);  }  static void rt_emergency_hash_rebuild(struct net *net) @@ -1073,8 +1082,23 @@ work_done:  out:	return 0;  } +/* + * Returns number of entries in a hash chain that have different hash_inputs + */ +static int slow_chain_length(const struct rtable *head) +{ +	int length = 0; +	const struct rtable *rth = head; + +	while (rth) { +		length += has_noalias(head, rth); +		rth = rth->u.dst.rt_next; +	} +	return length >> FRACT_BITS; +} +  static int rt_intern_hash(unsigned hash, struct rtable *rt, -			  struct rtable **rp, struct sk_buff *skb) +			  struct rtable **rp, struct sk_buff *skb, int ifindex)  {  	struct rtable	*rth, **rthp;  	unsigned long	now; @@ -1185,14 +1209,20 @@ restart:  			rt_free(cand);  		}  	} else { -		if (chain_length > rt_chain_length_max) { +		if (chain_length > rt_chain_length_max && +		    slow_chain_length(rt_hash_table[hash].chain) > rt_chain_length_max) {  			struct net *net = dev_net(rt->u.dst.dev);  			int num = ++net->ipv4.current_rt_cache_rebuild_count; -			if (!rt_caching(dev_net(rt->u.dst.dev))) { +			if (!rt_caching(net)) {  				printk(KERN_WARNING "%s: %d rebuilds is over limit, route caching disabled\n",  					rt->u.dst.dev->name, num);  			} -			rt_emergency_hash_rebuild(dev_net(rt->u.dst.dev)); +			rt_emergency_hash_rebuild(net); +			spin_unlock_bh(rt_hash_lock_addr(hash)); + +			hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src, +					ifindex, rt_genid(net)); +			goto restart;  		}  	} @@ -1417,7 +1447,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,  					dev_hold(rt->u.dst.dev);  				if (rt->idev)  					in_dev_hold(rt->idev); -				rt->u.dst.obsolete	= 0; +				rt->u.dst.obsolete	= -1;  				rt->u.dst.lastuse	= jiffies;  				rt->u.dst.path		= &rt->u.dst;  				rt->u.dst.neighbour	= NULL; @@ -1453,7 +1483,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,  							&netevent);  				rt_del(hash, rth); -				if (!rt_intern_hash(hash, rt, &rt, NULL)) +				if (!rt_intern_hash(hash, rt, &rt, NULL, rt->fl.oif))  					ip_rt_put(rt);  				goto do_next;  			} @@ -1482,11 +1512,12 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)  	struct dst_entry *ret = dst;  	if (rt) { -		if (dst->obsolete) { +		if (dst->obsolete > 0) {  			ip_rt_put(rt);  			ret = NULL;  		} else if ((rt->rt_flags & RTCF_REDIRECTED) || -			   rt->u.dst.expires) { +			   (rt->u.dst.expires && +			    time_after_eq(jiffies, rt->u.dst.expires))) {  			unsigned hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src,  						rt->fl.oif,  						rt_genid(dev_net(dst->dev))); @@ -1702,7 +1733,9 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)  static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)  { -	return NULL; +	if (rt_is_expired((struct rtable *)dst)) +		return NULL; +	return dst;  }  static void ipv4_dst_destroy(struct dst_entry *dst) @@ -1864,7 +1897,8 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,  	if (!rth)  		goto e_nobufs; -	rth->u.dst.output= ip_rt_bug; +	rth->u.dst.output = ip_rt_bug; +	rth->u.dst.obsolete = -1;  	atomic_set(&rth->u.dst.__refcnt, 1);  	rth->u.dst.flags= DST_HOST; @@ -1903,7 +1937,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,  	in_dev_put(in_dev);  	hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev))); -	return rt_intern_hash(hash, rth, NULL, skb); +	return rt_intern_hash(hash, rth, NULL, skb, dev->ifindex);  e_nobufs:  	in_dev_put(in_dev); @@ -2030,6 +2064,7 @@ static int __mkroute_input(struct sk_buff *skb,  	rth->fl.oif 	= 0;  	rth->rt_spec_dst= spec_dst; +	rth->u.dst.obsolete = -1;  	rth->u.dst.input = ip_forward;  	rth->u.dst.output = ip_output;  	rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev)); @@ -2069,7 +2104,7 @@ static int ip_mkroute_input(struct sk_buff *skb,  	/* put it into the cache */  	hash = rt_hash(daddr, saddr, fl->iif,  		       rt_genid(dev_net(rth->u.dst.dev))); -	return rt_intern_hash(hash, rth, NULL, skb); +	return rt_intern_hash(hash, rth, NULL, skb, fl->iif);  }  /* @@ -2194,6 +2229,7 @@ local_input:  		goto e_nobufs;  	rth->u.dst.output= ip_rt_bug; +	rth->u.dst.obsolete = -1;  	rth->rt_genid = rt_genid(net);  	atomic_set(&rth->u.dst.__refcnt, 1); @@ -2225,7 +2261,7 @@ local_input:  	}  	rth->rt_type	= res.type;  	hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net)); -	err = rt_intern_hash(hash, rth, NULL, skb); +	err = rt_intern_hash(hash, rth, NULL, skb, fl.iif);  	goto done;  no_route: @@ -2420,6 +2456,7 @@ static int __mkroute_output(struct rtable **result,  	rth->rt_spec_dst= fl->fl4_src;  	rth->u.dst.output=ip_output; +	rth->u.dst.obsolete = -1;  	rth->rt_genid = rt_genid(dev_net(dev_out));  	RT_CACHE_STAT_INC(out_slow_tot); @@ -2471,7 +2508,7 @@ static int ip_mkroute_output(struct rtable **rp,  	if (err == 0) {  		hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif,  			       rt_genid(dev_net(dev_out))); -		err = rt_intern_hash(hash, rth, rp, NULL); +		err = rt_intern_hash(hash, rth, rp, NULL, oldflp->oif);  	}  	return err; @@ -3077,22 +3114,20 @@ static void rt_secret_reschedule(int old)  	rtnl_lock();  	for_each_net(net) {  		int deleted = del_timer_sync(&net->ipv4.rt_secret_timer); +		long time;  		if (!new)  			continue;  		if (deleted) { -			long time = net->ipv4.rt_secret_timer.expires - jiffies; +			time = net->ipv4.rt_secret_timer.expires - jiffies;  			if (time <= 0 || (time += diff) <= 0)  				time = 0; - -			net->ipv4.rt_secret_timer.expires = time;  		} else -			net->ipv4.rt_secret_timer.expires = new; +			time = new; -		net->ipv4.rt_secret_timer.expires += jiffies; -		add_timer(&net->ipv4.rt_secret_timer); +		mod_timer(&net->ipv4.rt_secret_timer, jiffies + time);  	}  	rtnl_unlock();  } diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index c1bc074f61b..1cd5c15174b 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -12,6 +12,7 @@  #include <linux/inetdevice.h>  #include <linux/seqlock.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <net/snmp.h>  #include <net/icmp.h>  #include <net/ip.h> diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 5901010fad5..296150b2a62 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -265,6 +265,7 @@  #include <linux/err.h>  #include <linux/crypto.h>  #include <linux/time.h> +#include <linux/slab.h>  #include <net/icmp.h>  #include <net/tcp.h> @@ -429,7 +430,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)  		if (tp->urg_seq == tp->copied_seq &&  		    !sock_flag(sk, SOCK_URGINLINE) &&  		    tp->urg_data) -			target--; +			target++;  		/* Potential race condition. If read of tp below will  		 * escape above sk->sk_state, we can be illegally awaken @@ -1254,6 +1255,39 @@ static void tcp_prequeue_process(struct sock *sk)  	tp->ucopy.memory = 0;  } +#ifdef CONFIG_NET_DMA +static void tcp_service_net_dma(struct sock *sk, bool wait) +{ +	dma_cookie_t done, used; +	dma_cookie_t last_issued; +	struct tcp_sock *tp = tcp_sk(sk); + +	if (!tp->ucopy.dma_chan) +		return; + +	last_issued = tp->ucopy.dma_cookie; +	dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); + +	do { +		if (dma_async_memcpy_complete(tp->ucopy.dma_chan, +					      last_issued, &done, +					      &used) == DMA_SUCCESS) { +			/* Safe to free early-copied skbs now */ +			__skb_queue_purge(&sk->sk_async_wait_queue); +			break; +		} else { +			struct sk_buff *skb; +			while ((skb = skb_peek(&sk->sk_async_wait_queue)) && +			       (dma_async_is_complete(skb->dma_cookie, done, +						      used) == DMA_SUCCESS)) { +				__skb_dequeue(&sk->sk_async_wait_queue); +				kfree_skb(skb); +			} +		} +	} while (wait); +} +#endif +  static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)  {  	struct sk_buff *skb; @@ -1335,6 +1369,7 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,  		sk_eat_skb(sk, skb, 0);  		if (!desc->count)  			break; +		tp->copied_seq = seq;  	}  	tp->copied_seq = seq; @@ -1546,6 +1581,10 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,  			/* __ Set realtime policy in scheduler __ */  		} +#ifdef CONFIG_NET_DMA +		if (tp->ucopy.dma_chan) +			dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); +#endif  		if (copied >= target) {  			/* Do not sleep, just process backlog. */  			release_sock(sk); @@ -1554,6 +1593,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,  			sk_wait_data(sk, &timeo);  #ifdef CONFIG_NET_DMA +		tcp_service_net_dma(sk, false);  /* Don't block */  		tp->ucopy.wakeup = 0;  #endif @@ -1633,6 +1673,9 @@ do_prequeue:  						copied = -EFAULT;  					break;  				} + +				dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); +  				if ((offset + used) == skb->len)  					copied_early = 1; @@ -1702,27 +1745,9 @@ skip_copy:  	}  #ifdef CONFIG_NET_DMA -	if (tp->ucopy.dma_chan) { -		dma_cookie_t done, used; - -		dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); - -		while (dma_async_memcpy_complete(tp->ucopy.dma_chan, -						 tp->ucopy.dma_cookie, &done, -						 &used) == DMA_IN_PROGRESS) { -			/* do partial cleanup of sk_async_wait_queue */ -			while ((skb = skb_peek(&sk->sk_async_wait_queue)) && -			       (dma_async_is_complete(skb->dma_cookie, done, -						      used) == DMA_SUCCESS)) { -				__skb_dequeue(&sk->sk_async_wait_queue); -				kfree_skb(skb); -			} -		} +	tcp_service_net_dma(sk, true);  /* Wait for queue to drain */ +	tp->ucopy.dma_chan = NULL; -		/* Safe to free early-copied skbs now */ -		__skb_queue_purge(&sk->sk_async_wait_queue); -		tp->ucopy.dma_chan = NULL; -	}  	if (tp->ucopy.pinned_list) {  		dma_unpin_iovec_pages(tp->ucopy.pinned_list);  		tp->ucopy.pinned_list = NULL; @@ -2814,7 +2839,6 @@ static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool * __percpu *pool)  			if (p->md5_desc.tfm)  				crypto_free_hash(p->md5_desc.tfm);  			kfree(p); -			p = NULL;  		}  	}  	free_percpu(pool); @@ -2912,25 +2936,40 @@ retry:  EXPORT_SYMBOL(tcp_alloc_md5sig_pool); -struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu) + +/** + *	tcp_get_md5sig_pool - get md5sig_pool for this user + * + *	We use percpu structure, so if we succeed, we exit with preemption + *	and BH disabled, to make sure another thread or softirq handling + *	wont try to get same context. + */ +struct tcp_md5sig_pool *tcp_get_md5sig_pool(void)  {  	struct tcp_md5sig_pool * __percpu *p; -	spin_lock_bh(&tcp_md5sig_pool_lock); + +	local_bh_disable(); + +	spin_lock(&tcp_md5sig_pool_lock);  	p = tcp_md5sig_pool;  	if (p)  		tcp_md5sig_users++; -	spin_unlock_bh(&tcp_md5sig_pool_lock); -	return (p ? *per_cpu_ptr(p, cpu) : NULL); -} +	spin_unlock(&tcp_md5sig_pool_lock); -EXPORT_SYMBOL(__tcp_get_md5sig_pool); +	if (p) +		return *per_cpu_ptr(p, smp_processor_id()); -void __tcp_put_md5sig_pool(void) +	local_bh_enable(); +	return NULL; +} +EXPORT_SYMBOL(tcp_get_md5sig_pool); + +void tcp_put_md5sig_pool(void)  { +	local_bh_enable();  	tcp_free_md5sig_pool();  } - -EXPORT_SYMBOL(__tcp_put_md5sig_pool); +EXPORT_SYMBOL(tcp_put_md5sig_pool);  int tcp_md5_hash_header(struct tcp_md5sig_pool *hp,  			struct tcphdr *th) diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 6428b342b16..0ec9bd0ae94 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -10,6 +10,7 @@  #include <linux/mm.h>  #include <linux/types.h>  #include <linux/list.h> +#include <linux/gfp.h>  #include <net/tcp.h>  int sysctl_tcp_max_ssthresh = 0; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 788851ca8c5..f240f57b219 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -62,6 +62,7 @@   */  #include <linux/mm.h> +#include <linux/slab.h>  #include <linux/module.h>  #include <linux/sysctl.h>  #include <linux/kernel.h> @@ -2511,6 +2512,9 @@ static void tcp_mark_head_lost(struct sock *sk, int packets)  	int err;  	unsigned int mss; +	if (packets == 0) +		return; +  	WARN_ON(packets > tp->packets_out);  	if (tp->lost_skb_hint) {  		skb = tp->lost_skb_hint; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index c3588b4fd97..3c23e70885f 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -60,6 +60,7 @@  #include <linux/jhash.h>  #include <linux/init.h>  #include <linux/times.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/icmp.h> @@ -370,6 +371,11 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)  	if (sk->sk_state == TCP_CLOSE)  		goto out; +	if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) { +		NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP); +		goto out; +	} +  	icsk = inet_csk(sk);  	tp = tcp_sk(sk);  	seq = ntohl(th->seq); @@ -1651,13 +1657,15 @@ int tcp_v4_rcv(struct sk_buff *skb)  	if (!sk)  		goto no_tcp_socket; -	if (iph->ttl < inet_sk(sk)->min_ttl) -		goto discard_and_relse; -  process:  	if (sk->sk_state == TCP_TIME_WAIT)  		goto do_time_wait; +	if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) { +		NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP); +		goto discard_and_relse; +	} +  	if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))  		goto discard_and_relse;  	nf_reset(skb); @@ -1682,8 +1690,11 @@ process:  			if (!tcp_prequeue(sk, skb))  				ret = tcp_v4_do_rcv(sk, skb);  		} -	} else -		sk_add_backlog(sk, skb); +	} else if (unlikely(sk_add_backlog(sk, skb))) { +		bh_unlock_sock(sk); +		NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP); +		goto discard_and_relse; +	}  	bh_unlock_sock(sk);  	sock_put(sk); diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index f206ee5dda8..5fabff9ac6d 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -20,6 +20,7 @@  #include <linux/mm.h>  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/sysctl.h>  #include <linux/workqueue.h>  #include <net/tcp.h> @@ -728,7 +729,7 @@ int tcp_child_process(struct sock *parent, struct sock *child,  		 * in main socket hash table and lock on listening  		 * socket does not protect us more.  		 */ -		sk_add_backlog(child, skb); +		__sk_add_backlog(child, skb);  	}  	bh_unlock_sock(child); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 4a1605d3f90..0dda86e72ad 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -37,6 +37,7 @@  #include <net/tcp.h>  #include <linux/compiler.h> +#include <linux/gfp.h>  #include <linux/module.h>  /* People can turn this off for buggy TCP's found in printers etc. */ @@ -2395,13 +2396,17 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,  	struct tcp_extend_values *xvp = tcp_xv(rvp);  	struct inet_request_sock *ireq = inet_rsk(req);  	struct tcp_sock *tp = tcp_sk(sk); +	const struct tcp_cookie_values *cvp = tp->cookie_values;  	struct tcphdr *th;  	struct sk_buff *skb;  	struct tcp_md5sig_key *md5;  	int tcp_header_size;  	int mss; +	int s_data_desired = 0; -	skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC); +	if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired) +		s_data_desired = cvp->s_data_desired; +	skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15 + s_data_desired, 1, GFP_ATOMIC);  	if (skb == NULL)  		return NULL; @@ -2457,16 +2462,12 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,  			     TCPCB_FLAG_SYN | TCPCB_FLAG_ACK);  	if (OPTION_COOKIE_EXTENSION & opts.options) { -		const struct tcp_cookie_values *cvp = tp->cookie_values; - -		if (cvp != NULL && -		    cvp->s_data_constant && -		    cvp->s_data_desired > 0) { -			u8 *buf = skb_put(skb, cvp->s_data_desired); +		if (s_data_desired) { +			u8 *buf = skb_put(skb, s_data_desired);  			/* copy data directly from the listening socket. */ -			memcpy(buf, cvp->s_data_payload, cvp->s_data_desired); -			TCP_SKB_CB(skb)->end_seq += cvp->s_data_desired; +			memcpy(buf, cvp->s_data_payload, s_data_desired); +			TCP_SKB_CB(skb)->end_seq += s_data_desired;  		}  		if (opts.hash_size > 0) { diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c index 9bc805df95d..f8efada580e 100644 --- a/net/ipv4/tcp_probe.c +++ b/net/ipv4/tcp_probe.c @@ -22,6 +22,7 @@  #include <linux/kprobes.h>  #include <linux/socket.h>  #include <linux/tcp.h> +#include <linux/slab.h>  #include <linux/proc_fs.h>  #include <linux/module.h>  #include <linux/ktime.h> diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index a17629b8912..8a0ab2977f1 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -19,6 +19,7 @@   */  #include <linux/module.h> +#include <linux/gfp.h>  #include <net/tcp.h>  int sysctl_tcp_syn_retries __read_mostly = TCP_SYN_RETRIES; @@ -134,7 +135,7 @@ static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk)  }  /* This function calculates a "timeout" which is equivalent to the timeout of a - * TCP connection after "boundary" unsucessful, exponentially backed-off + * TCP connection after "boundary" unsuccessful, exponentially backed-off   * retransmissions with an initial RTO of TCP_RTO_MIN.   */  static bool retransmits_timed_out(struct sock *sk, diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c index 3959e0ca456..3b3813cc80b 100644 --- a/net/ipv4/tunnel4.c +++ b/net/ipv4/tunnel4.c @@ -8,6 +8,7 @@  #include <linux/mutex.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/icmp.h>  #include <net/ip.h>  #include <net/protocol.h> diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 608a5446d05..c36522a0f11 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -95,6 +95,7 @@  #include <linux/mm.h>  #include <linux/inet.h>  #include <linux/netdevice.h> +#include <linux/slab.h>  #include <net/tcp_states.h>  #include <linux/skbuff.h>  #include <linux/proc_fs.h> @@ -471,8 +472,8 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,  			if (hslot->count < hslot2->count)  				goto begin; -			result = udp4_lib_lookup2(net, INADDR_ANY, sport, -						  daddr, hnum, dif, +			result = udp4_lib_lookup2(net, saddr, sport, +						  INADDR_ANY, hnum, dif,  						  hslot2, slot2);  		}  		rcu_read_unlock(); @@ -1371,8 +1372,10 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)  	bh_lock_sock(sk);  	if (!sock_owned_by_user(sk))  		rc = __udp_queue_rcv_skb(sk, skb); -	else -		sk_add_backlog(sk, skb); +	else if (sk_add_backlog(sk, skb)) { +		bh_unlock_sock(sk); +		goto drop; +	}  	bh_unlock_sock(sk);  	return rc; @@ -1524,6 +1527,9 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,  	uh   = udp_hdr(skb);  	ulen = ntohs(uh->len); +	saddr = ip_hdr(skb)->saddr; +	daddr = ip_hdr(skb)->daddr; +  	if (ulen > skb->len)  		goto short_packet; @@ -1537,9 +1543,6 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,  	if (udp4_csum_init(skb, uh, proto))  		goto csum_error; -	saddr = ip_hdr(skb)->saddr; -	daddr = ip_hdr(skb)->daddr; -  	if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))  		return __udp4_lib_mcast_deliver(net, skb, uh,  				saddr, daddr, udptable); diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index f9f922a0ba8..c791bb63203 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c @@ -9,6 +9,7 @@   *   */ +#include <linux/slab.h>  #include <linux/module.h>  #include <linux/string.h>  #include <linux/netfilter.h> diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c index 3444f3b34ec..6f368413eb0 100644 --- a/net/ipv4/xfrm4_mode_tunnel.c +++ b/net/ipv4/xfrm4_mode_tunnel.c @@ -4,6 +4,7 @@   * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>   */ +#include <linux/gfp.h>  #include <linux/init.h>  #include <linux/kernel.h>  #include <linux/module.h> diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 67107d63c1c..e4a1483fba7 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -91,11 +91,12 @@ static int xfrm4_init_path(struct xfrm_dst *path, struct dst_entry *dst,  	return 0;  } -static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev) +static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, +			  struct flowi *fl)  {  	struct rtable *rt = (struct rtable *)xdst->route; -	xdst->u.rt.fl = rt->fl; +	xdst->u.rt.fl = *fl;  	xdst->u.dst.dev = dev;  	dev_hold(dev); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 88fd8c5877e..413054f02aa 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -53,6 +53,7 @@  #include <linux/route.h>  #include <linux/inetdevice.h>  #include <linux/init.h> +#include <linux/slab.h>  #ifdef CONFIG_SYSCTL  #include <linux/sysctl.h>  #endif @@ -1380,6 +1381,8 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed)  		if (dad_failed)  			ifp->flags |= IFA_F_DADFAILED;  		spin_unlock_bh(&ifp->lock); +		if (dad_failed) +			ipv6_ifa_notify(0, ifp);  		in6_ifa_put(ifp);  #ifdef CONFIG_IPV6_PRIVACY  	} else if (ifp->flags&IFA_F_TEMPORARY) { @@ -2615,7 +2618,7 @@ static void addrconf_bonding_change(struct net_device *dev, unsigned long event)  static int addrconf_ifdown(struct net_device *dev, int how)  {  	struct inet6_dev *idev; -	struct inet6_ifaddr *ifa, **bifa; +	struct inet6_ifaddr *ifa, *keep_list, **bifa;  	struct net *net = dev_net(dev);  	int i; @@ -2649,11 +2652,11 @@ static int addrconf_ifdown(struct net_device *dev, int how)  		write_lock_bh(&addrconf_hash_lock);  		while ((ifa = *bifa) != NULL) {  			if (ifa->idev == idev && -			    (how || !(ifa->flags&IFA_F_PERMANENT))) { +			    (how || !(ifa->flags&IFA_F_PERMANENT) || +			     ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) {  				*bifa = ifa->lst_next;  				ifa->lst_next = NULL; -				addrconf_del_timer(ifa); -				in6_ifa_put(ifa); +				__in6_ifa_put(ifa);  				continue;  			}  			bifa = &ifa->lst_next; @@ -2689,31 +2692,51 @@ static int addrconf_ifdown(struct net_device *dev, int how)  		write_lock_bh(&idev->lock);  	}  #endif -	bifa = &idev->addr_list; -	while ((ifa = *bifa) != NULL) { -		if (how == 0 && (ifa->flags&IFA_F_PERMANENT)) { -			/* Retain permanent address on admin down */ +	keep_list = NULL; +	bifa = &keep_list; +	while ((ifa = idev->addr_list) != NULL) { +		idev->addr_list = ifa->if_next; +		ifa->if_next = NULL; + +		addrconf_del_timer(ifa); + +		/* If just doing link down, and address is permanent +		   and not link-local, then retain it. */ +		if (how == 0 && +		    (ifa->flags&IFA_F_PERMANENT) && +		    !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { + +			/* Move to holding list */ +			*bifa = ifa;  			bifa = &ifa->if_next; -			/* Restart DAD if needed when link comes back up */ -			if ( !((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || -			       idev->cnf.accept_dad <= 0 || -			       (ifa->flags & IFA_F_NODAD))) -				ifa->flags |= IFA_F_TENTATIVE; -		} else { -			*bifa = ifa->if_next; -			ifa->if_next = NULL; +			/* If not doing DAD on this address, just keep it. */ +			if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || +			    idev->cnf.accept_dad <= 0 || +			    (ifa->flags & IFA_F_NODAD)) +				continue; +			/* If it was tentative already, no need to notify */ +			if (ifa->flags & IFA_F_TENTATIVE) +				continue; + +			/* Flag it for later restoration when link comes up */ +			ifa->flags |= IFA_F_TENTATIVE; +			in6_ifa_hold(ifa); +		} else {  			ifa->dead = 1; -			write_unlock_bh(&idev->lock); +		} +		write_unlock_bh(&idev->lock); -			__ipv6_ifa_notify(RTM_DELADDR, ifa); -			atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); -			in6_ifa_put(ifa); +		__ipv6_ifa_notify(RTM_DELADDR, ifa); +		atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); +		in6_ifa_put(ifa); -			write_lock_bh(&idev->lock); -		} +		write_lock_bh(&idev->lock);  	} + +	idev->addr_list = keep_list; +  	write_unlock_bh(&idev->lock);  	/* Step 5: Discard multicast list */ @@ -2739,28 +2762,29 @@ static int addrconf_ifdown(struct net_device *dev, int how)  static void addrconf_rs_timer(unsigned long data)  {  	struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; +	struct inet6_dev *idev = ifp->idev; -	if (ifp->idev->cnf.forwarding) +	read_lock(&idev->lock); +	if (idev->dead || !(idev->if_flags & IF_READY))  		goto out; -	if (ifp->idev->if_flags & IF_RA_RCVD) { -		/* -		 *	Announcement received after solicitation -		 *	was sent -		 */ +	if (idev->cnf.forwarding) +		goto out; + +	/* Announcement received after solicitation was sent */ +	if (idev->if_flags & IF_RA_RCVD)  		goto out; -	}  	spin_lock(&ifp->lock); -	if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) { +	if (ifp->probes++ < idev->cnf.rtr_solicits) {  		/* The wait after the last probe can be shorter */  		addrconf_mod_timer(ifp, AC_RS, -				   (ifp->probes == ifp->idev->cnf.rtr_solicits) ? -				   ifp->idev->cnf.rtr_solicit_delay : -				   ifp->idev->cnf.rtr_solicit_interval); +				   (ifp->probes == idev->cnf.rtr_solicits) ? +				   idev->cnf.rtr_solicit_delay : +				   idev->cnf.rtr_solicit_interval);  		spin_unlock(&ifp->lock); -		ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); +		ndisc_send_rs(idev->dev, &ifp->addr, &in6addr_linklocal_allrouters);  	} else {  		spin_unlock(&ifp->lock);  		/* @@ -2768,10 +2792,11 @@ static void addrconf_rs_timer(unsigned long data)  		 * assumption any longer.  		 */  		printk(KERN_DEBUG "%s: no IPv6 routers present\n", -		       ifp->idev->dev->name); +		       idev->dev->name);  	}  out: +	read_unlock(&idev->lock);  	in6_ifa_put(ifp);  } @@ -2850,9 +2875,9 @@ static void addrconf_dad_timer(unsigned long data)  	struct inet6_dev *idev = ifp->idev;  	struct in6_addr mcaddr; -	read_lock_bh(&idev->lock); -	if (idev->dead) { -		read_unlock_bh(&idev->lock); +	read_lock(&idev->lock); +	if (idev->dead || !(idev->if_flags & IF_READY)) { +		read_unlock(&idev->lock);  		goto out;  	} @@ -2864,7 +2889,7 @@ static void addrconf_dad_timer(unsigned long data)  		ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);  		spin_unlock(&ifp->lock); -		read_unlock_bh(&idev->lock); +		read_unlock(&idev->lock);  		addrconf_dad_completed(ifp); @@ -2874,7 +2899,7 @@ static void addrconf_dad_timer(unsigned long data)  	ifp->probes--;  	addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time);  	spin_unlock(&ifp->lock); -	read_unlock_bh(&idev->lock); +	read_unlock(&idev->lock);  	/* send a neighbour solicitation for our addr */  	addrconf_addr_solict_mult(&ifp->addr, &mcaddr); @@ -3586,7 +3611,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,  		hlist_for_each_entry_rcu(dev, node, head, index_hlist) {  			if (idx < s_idx)  				goto cont; -			if (idx > s_idx) +			if (h > s_h || idx > s_idx)  				s_ip_idx = 0;  			ip_idx = 0;  			if ((idev = __in6_dev_get(dev)) == NULL) diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index 6ff73c4c126..ae404c9a746 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c @@ -13,6 +13,7 @@  #include <linux/list.h>  #include <linux/rcupdate.h>  #include <linux/in6.h> +#include <linux/slab.h>  #include <net/addrconf.h>  #include <linux/if_addrlabel.h>  #include <linux/netlink.h> diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 37d14e735c2..3f9e86b15e0 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -36,6 +36,7 @@  #include <linux/proc_fs.h>  #include <linux/stat.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <linux/inet.h>  #include <linux/netdevice.h> @@ -199,7 +200,7 @@ lookup_protocol:  	inet_sk(sk)->pinet6 = np = inet6_sk_generic(sk);  	np->hop_limit	= -1; -	np->mcast_hops	= -1; +	np->mcast_hops	= IPV6_DEFAULT_MCASTHOPS;  	np->mc_loop	= 1;  	np->pmtudisc	= IPV6_PMTUDISC_WANT;  	np->ipv6only	= net->ipv6.sysctl.bindv6only; diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 5ac89025f9d..ee82d4ef26c 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -26,6 +26,7 @@  #include <crypto/hash.h>  #include <linux/module.h> +#include <linux/slab.h>  #include <net/ip.h>  #include <net/ah.h>  #include <linux/crypto.h> diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index c4f6ca32fa7..b5b07054508 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c @@ -29,6 +29,7 @@  #include <linux/init.h>  #include <linux/proc_fs.h>  #include <linux/seq_file.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/sock.h> diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index e6f9cdf780f..61573885e45 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -21,6 +21,7 @@  #include <linux/in6.h>  #include <linux/ipv6.h>  #include <linux/route.h> +#include <linux/slab.h>  #include <net/ipv6.h>  #include <net/ndisc.h> @@ -221,6 +222,8 @@ void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err,  	if (!skb)  		return; +	skb->protocol = htons(ETH_P_IPV6); +  	serr = SKB_EXT_ERR(skb);  	serr->ee.ee_errno = err;  	serr->ee.ee_origin = SO_EE_ORIGIN_ICMP6; @@ -254,6 +257,8 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info)  	if (!skb)  		return; +	skb->protocol = htons(ETH_P_IPV6); +  	skb_put(skb, sizeof(struct ipv6hdr));  	skb_reset_network_header(skb);  	iph = ipv6_hdr(skb); @@ -318,7 +323,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)  		sin->sin6_flowinfo = 0;  		sin->sin6_port = serr->port;  		sin->sin6_scope_id = 0; -		if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { +		if (skb->protocol == htons(ETH_P_IPV6)) {  			ipv6_addr_copy(&sin->sin6_addr,  				  (struct in6_addr *)(nh + serr->addr_offset));  			if (np->sndflow) @@ -340,7 +345,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)  		sin->sin6_family = AF_INET6;  		sin->sin6_flowinfo = 0;  		sin->sin6_scope_id = 0; -		if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { +		if (skb->protocol == htons(ETH_P_IPV6)) {  			ipv6_addr_copy(&sin->sin6_addr, &ipv6_hdr(skb)->saddr);  			if (np->rxopt.all)  				datagram_recv_ctl(sk, msg, skb); diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 074f2c084f9..8a659f92d17 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -29,6 +29,7 @@  #include <linux/netdevice.h>  #include <linux/in6.h>  #include <linux/icmpv6.h> +#include <linux/slab.h>  #include <net/dst.h>  #include <net/sock.h> diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 551882b9dfd..5e463c43fcc 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -84,18 +84,11 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,  		if ((rule->flags & FIB_RULE_FIND_SADDR) &&  		    r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) {  			struct in6_addr saddr; -			unsigned int srcprefs = 0; - -			if (flags & RT6_LOOKUP_F_SRCPREF_TMP) -				srcprefs |= IPV6_PREFER_SRC_TMP; -			if (flags & RT6_LOOKUP_F_SRCPREF_PUBLIC) -				srcprefs |= IPV6_PREFER_SRC_PUBLIC; -			if (flags & RT6_LOOKUP_F_SRCPREF_COA) -				srcprefs |= IPV6_PREFER_SRC_COA;  			if (ipv6_dev_get_saddr(net,  					       ip6_dst_idev(&rt->u.dst)->dev, -					       &flp->fl6_dst, srcprefs, +					       &flp->fl6_dst, +					       rt6_flags2srcprefs(flags),  					       &saddr))  				goto again;  			if (!ipv6_prefix_equal(&saddr, &r->src.addr, diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index eb9abe24bdf..3330a4bd615 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -40,6 +40,7 @@  #include <linux/skbuff.h>  #include <linux/init.h>  #include <linux/netfilter.h> +#include <linux/slab.h>  #ifdef CONFIG_SYSCTL  #include <linux/sysctl.h> diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 3516e6fe2e5..628db24bcf2 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -17,6 +17,7 @@  #include <linux/in6.h>  #include <linux/ipv6.h>  #include <linux/jhash.h> +#include <linux/slab.h>  #include <net/addrconf.h>  #include <net/inet_connection_sock.h> diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 2f9847924fa..6b82e02158c 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -26,6 +26,7 @@  #include <linux/in6.h>  #include <linux/init.h>  #include <linux/list.h> +#include <linux/slab.h>  #ifdef 	CONFIG_PROC_FS  #include <linux/proc_fs.h> diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index e41eba8aacf..14e23216eb2 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -20,6 +20,7 @@  #include <linux/route.h>  #include <linux/proc_fs.h>  #include <linux/seq_file.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/sock.h> diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index e28f9203dec..6aa7ee1295c 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -28,6 +28,7 @@  #include <linux/in6.h>  #include <linux/icmpv6.h>  #include <linux/mroute6.h> +#include <linux/slab.h>  #include <linux/netfilter.h>  #include <linux/netfilter_ipv6.h> diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index dabf108ad81..75d5ef83009 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -37,6 +37,7 @@  #include <linux/tcp.h>  #include <linux/route.h>  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/netfilter.h>  #include <linux/netfilter_ipv6.h> @@ -107,7 +108,7 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb)  	newskb->ip_summed = CHECKSUM_UNNECESSARY;  	WARN_ON(!skb_dst(newskb)); -	netif_rx(newskb); +	netif_rx_ni(newskb);  	return 0;  } @@ -628,7 +629,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))  	/* We must not fragment if the socket is set to force MTU discovery  	 * or if the skb it not generated by a local socket.  	 */ -	if (!skb->local_df) { +	if (!skb->local_df && skb->len > mtu) {  		skb->dev = skb_dst(skb)->dev;  		icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);  		IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 138980eec21..2599870747e 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -37,6 +37,7 @@  #include <linux/route.h>  #include <linux/rtnetlink.h>  #include <linux/netfilter_ipv6.h> +#include <linux/slab.h>  #include <asm/uaccess.h>  #include <asm/atomic.h> diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 52e0f74fdfe..3e333268db8 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -33,6 +33,7 @@  #include <linux/proc_fs.h>  #include <linux/seq_file.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <net/protocol.h>  #include <linux/skbuff.h>  #include <net/sock.h> @@ -1113,6 +1114,9 @@ static int ip6mr_mfc_add(struct net *net, struct mf6cctl *mfc, int mrtsock)  	unsigned char ttls[MAXMIFS];  	int i; +	if (mfc->mf6cc_parent >= MAXMIFS) +		return -ENFILE; +  	memset(ttls, 255, MAXMIFS);  	for (i = 0; i < MAXMIFS; i++) {  		if (IF_ISSET(i, &mfc->mf6cc_ifset)) @@ -1692,17 +1696,20 @@ ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm)  	int ct;  	struct rtnexthop *nhp;  	struct net *net = mfc6_net(c); -	struct net_device *dev = net->ipv6.vif6_table[c->mf6c_parent].dev;  	u8 *b = skb_tail_pointer(skb);  	struct rtattr *mp_head; -	if (dev) -		RTA_PUT(skb, RTA_IIF, 4, &dev->ifindex); +	/* If cache is unresolved, don't try to parse IIF and OIF */ +	if (c->mf6c_parent > MAXMIFS) +		return -ENOENT; + +	if (MIF_EXISTS(net, c->mf6c_parent)) +		RTA_PUT(skb, RTA_IIF, 4, &net->ipv6.vif6_table[c->mf6c_parent].dev->ifindex);  	mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0));  	for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { -		if (c->mfc_un.res.ttls[ct] < 255) { +		if (MIF_EXISTS(net, ct) && c->mfc_un.res.ttls[ct] < 255) {  			if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))  				goto rtattr_failure;  			nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 430454ee5ea..33f60fca7aa 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -36,6 +36,7 @@  #include <linux/init.h>  #include <linux/sysctl.h>  #include <linux/netfilter.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/snmp.h> diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index bcd97191596..c483ab9fd67 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -43,6 +43,7 @@  #include <linux/init.h>  #include <linux/proc_fs.h>  #include <linux/seq_file.h> +#include <linux/slab.h>  #include <linux/netfilter.h>  #include <linux/netfilter_ipv6.h> diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 8bcc4b7db3b..da0a4d2adc6 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -59,6 +59,7 @@  #include <linux/route.h>  #include <linux/init.h>  #include <linux/rcupdate.h> +#include <linux/slab.h>  #ifdef CONFIG_SYSCTL  #include <linux/sysctl.h>  #endif diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 7854052be60..6a68a74d14a 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -25,6 +25,7 @@  #include <linux/proc_fs.h>  #include <linux/seq_file.h>  #include <linux/mutex.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/sock.h>  #include <net/ipv6.h> diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index dd8afbaf00a..39b50c3768e 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c @@ -15,6 +15,7 @@   * 2 of the License, or (at your option) any later version.   */ +#include <linux/gfp.h>  #include <linux/module.h>  #include <linux/skbuff.h>  #include <linux/icmpv6.h> diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 36b72cafc22..d6fc9aff316 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -12,6 +12,7 @@  #include <linux/module.h>  #include <linux/moduleparam.h>  #include <linux/netfilter_ipv6/ip6_tables.h> +#include <linux/slab.h>  MODULE_LICENSE("GPL");  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 7844e557c0e..6a102b57f35 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -10,6 +10,7 @@   */  #include <linux/module.h>  #include <linux/netfilter_ipv6/ip6_tables.h> +#include <linux/slab.h>  MODULE_LICENSE("GPL");  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index aef31a29de9..5b9926a011b 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -5,6 +5,7 @@   */  #include <linux/module.h>  #include <linux/netfilter_ipv6/ip6_tables.h> +#include <linux/slab.h>  #define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) @@ -13,7 +14,7 @@ static const struct xt_table packet_raw = {  	.valid_hooks = RAW_VALID_HOOKS,  	.me = THIS_MODULE,  	.af = NFPROTO_IPV6, -	.priority = NF_IP6_PRI_FIRST, +	.priority = NF_IP6_PRI_RAW,  };  /* The work comes in here from netfilter.c. */ diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c index 0824d865aa9..91aa2b4d83c 100644 --- a/net/ipv6/netfilter/ip6table_security.c +++ b/net/ipv6/netfilter/ip6table_security.c @@ -17,6 +17,7 @@   */  #include <linux/module.h>  #include <linux/netfilter_ipv6/ip6_tables.h> +#include <linux/slab.h>  MODULE_LICENSE("GPL");  MODULE_AUTHOR("James Morris <jmorris <at> redhat.com>"); diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index f1171b74465..dd5b9bd61c6 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -27,6 +27,7 @@  #include <linux/ipv6.h>  #include <linux/icmpv6.h>  #include <linux/random.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/snmp.h> diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ed31c37c6e3..8763b1a0814 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -21,6 +21,7 @@  #include <linux/errno.h>  #include <linux/types.h>  #include <linux/socket.h> +#include <linux/slab.h>  #include <linux/sockios.h>  #include <linux/net.h>  #include <linux/in6.h> diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index a555156e977..6d4292ff585 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -41,6 +41,7 @@  #include <linux/random.h>  #include <linux/jhash.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/snmp.h> diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b08879e97f2..05ebd783304 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -40,6 +40,7 @@  #include <linux/proc_fs.h>  #include <linux/seq_file.h>  #include <linux/nsproxy.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/snmp.h>  #include <net/ipv6.h> @@ -814,20 +815,13 @@ struct dst_entry * ip6_route_output(struct net *net, struct sock *sk,  {  	int flags = 0; -	if (rt6_need_strict(&fl->fl6_dst)) +	if (fl->oif || rt6_need_strict(&fl->fl6_dst))  		flags |= RT6_LOOKUP_F_IFACE;  	if (!ipv6_addr_any(&fl->fl6_src))  		flags |= RT6_LOOKUP_F_HAS_SADDR; -	else if (sk) { -		unsigned int prefs = inet6_sk(sk)->srcprefs; -		if (prefs & IPV6_PREFER_SRC_TMP) -			flags |= RT6_LOOKUP_F_SRCPREF_TMP; -		if (prefs & IPV6_PREFER_SRC_PUBLIC) -			flags |= RT6_LOOKUP_F_SRCPREF_PUBLIC; -		if (prefs & IPV6_PREFER_SRC_COA) -			flags |= RT6_LOOKUP_F_SRCPREF_COA; -	} +	else if (sk) +		flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs);  	return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output);  } @@ -886,7 +880,7 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)  	rt = (struct rt6_info *) dst; -	if (rt && rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) +	if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie))  		return dst;  	return NULL; @@ -897,12 +891,17 @@ static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)  	struct rt6_info *rt = (struct rt6_info *) dst;  	if (rt) { -		if (rt->rt6i_flags & RTF_CACHE) -			ip6_del_rt(rt); -		else +		if (rt->rt6i_flags & RTF_CACHE) { +			if (rt6_check_expired(rt)) { +				ip6_del_rt(rt); +				dst = NULL; +			} +		} else {  			dst_release(dst); +			dst = NULL; +		}  	} -	return NULL; +	return dst;  }  static void ip6_link_failure(struct sk_buff *skb) diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index b1eea811be4..5abae10cd88 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -28,6 +28,7 @@  #include <linux/netdevice.h>  #include <linux/if_arp.h>  #include <linux/icmp.h> +#include <linux/slab.h>  #include <asm/uaccess.h>  #include <linux/init.h>  #include <linux/netfilter_ipv4.h> diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index f841d93bf98..fa1d8f4e005 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c @@ -9,6 +9,7 @@  #include <linux/sysctl.h>  #include <linux/in6.h>  #include <linux/ipv6.h> +#include <linux/slab.h>  #include <net/ndisc.h>  #include <net/ipv6.h>  #include <net/addrconf.h> diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 6963a6b6763..075f540ec19 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -38,6 +38,7 @@  #include <linux/jhash.h>  #include <linux/ipsec.h>  #include <linux/times.h> +#include <linux/slab.h>  #include <linux/ipv6.h>  #include <linux/icmpv6.h> @@ -1014,7 +1015,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,  	skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len);  	t1 = (struct tcphdr *) skb_push(buff, tot_len); -	skb_reset_transport_header(skb); +	skb_reset_transport_header(buff);  	/* Swap the send and the receive. */  	memset(t1, 0, sizeof(*t1)); @@ -1740,8 +1741,11 @@ process:  			if (!tcp_prequeue(sk, skb))  				ret = tcp_v6_do_rcv(sk, skb);  		} -	} else -		sk_add_backlog(sk, skb); +	} else if (unlikely(sk_add_backlog(sk, skb))) { +		bh_unlock_sock(sk); +		NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP); +		goto discard_and_relse; +	}  	bh_unlock_sock(sk);  	sock_put(sk); diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c index e17bc1dfc1a..fc3c86a4745 100644 --- a/net/ipv6/tunnel6.c +++ b/net/ipv6/tunnel6.c @@ -25,6 +25,7 @@  #include <linux/mutex.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/ipv6.h>  #include <net/protocol.h>  #include <net/xfrm.h> diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 52b8347ae3b..90824852f59 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -34,6 +34,7 @@  #include <linux/init.h>  #include <linux/module.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <asm/uaccess.h>  #include <net/ndisc.h> @@ -258,8 +259,8 @@ static struct sock *__udp6_lib_lookup(struct net *net,  			if (hslot->count < hslot2->count)  				goto begin; -			result = udp6_lib_lookup2(net, &in6addr_any, sport, -						  daddr, hnum, dif, +			result = udp6_lib_lookup2(net, saddr, sport, +						  &in6addr_any, hnum, dif,  						  hslot2, slot2);  		}  		rcu_read_unlock(); @@ -583,16 +584,20 @@ static void flush_stack(struct sock **stack, unsigned int count,  			bh_lock_sock(sk);  			if (!sock_owned_by_user(sk))  				udpv6_queue_rcv_skb(sk, skb1); -			else -				sk_add_backlog(sk, skb1); +			else if (sk_add_backlog(sk, skb1)) { +				kfree_skb(skb1); +				bh_unlock_sock(sk); +				goto drop; +			}  			bh_unlock_sock(sk); -		} else { -			atomic_inc(&sk->sk_drops); -			UDP6_INC_STATS_BH(sock_net(sk), -					UDP_MIB_RCVBUFERRORS, IS_UDPLITE(sk)); -			UDP6_INC_STATS_BH(sock_net(sk), -					UDP_MIB_INERRORS, IS_UDPLITE(sk)); +			continue;  		} +drop: +		atomic_inc(&sk->sk_drops); +		UDP6_INC_STATS_BH(sock_net(sk), +				UDP_MIB_RCVBUFERRORS, IS_UDPLITE(sk)); +		UDP6_INC_STATS_BH(sock_net(sk), +				UDP_MIB_INERRORS, IS_UDPLITE(sk));  	}  }  /* @@ -754,8 +759,12 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,  	bh_lock_sock(sk);  	if (!sock_owned_by_user(sk))  		udpv6_queue_rcv_skb(sk, skb); -	else -		sk_add_backlog(sk, skb); +	else if (sk_add_backlog(sk, skb)) { +		atomic_inc(&sk->sk_drops); +		bh_unlock_sock(sk); +		sock_put(sk); +		goto discard; +	}  	bh_unlock_sock(sk);  	sock_put(sk);  	return 0; diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index 3927832227b..b809812c8d3 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c @@ -5,6 +5,7 @@   * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>   */ +#include <linux/gfp.h>  #include <linux/init.h>  #include <linux/kernel.h>  #include <linux/module.h> diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index dbdc696f5fc..00bf7c962b7 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -116,14 +116,15 @@ static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst,  	return 0;  } -static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev) +static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, +			  struct flowi *fl)  {  	struct rt6_info *rt = (struct rt6_info*)xdst->route;  	xdst->u.dst.dev = dev;  	dev_hold(dev); -	xdst->u.rt6.rt6i_idev = in6_dev_get(rt->u.dst.dev); +	xdst->u.rt6.rt6i_idev = in6_dev_get(dev);  	if (!xdst->u.rt6.rt6i_idev)  		return -ENODEV; diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index fa85a7d22dc..2ce3a8278f2 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -23,6 +23,7 @@   */  #include <linux/module.h>  #include <linux/xfrm.h> +#include <linux/slab.h>  #include <linux/rculist.h>  #include <net/ip.h>  #include <net/xfrm.h> diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index f9759b54a6d..da3d21c41d9 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -40,6 +40,7 @@  #include <linux/net.h>  #include <linux/netdevice.h>  #include <linux/uio.h> +#include <linux/slab.h>  #include <linux/skbuff.h>  #include <linux/smp_lock.h>  #include <linux/socket.h> diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c index e16c1142352..30f4519b092 100644 --- a/net/ipx/ipx_route.c +++ b/net/ipx/ipx_route.c @@ -9,6 +9,7 @@  #include <linux/list.h>  #include <linux/route.h> +#include <linux/slab.h>  #include <linux/spinlock.h>  #include <net/ipx.h> diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 10093aab617..2a4efcea342 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -48,6 +48,7 @@  #include <linux/smp_lock.h>  #include <linux/socket.h>  #include <linux/sockios.h> +#include <linux/slab.h>  #include <linux/init.h>  #include <linux/net.h>  #include <linux/irda.h> diff --git a/net/irda/discovery.c b/net/irda/discovery.c index a6f99b5a149..c1c8ae93912 100644 --- a/net/irda/discovery.c +++ b/net/irda/discovery.c @@ -34,6 +34,7 @@  #include <linux/socket.h>  #include <linux/fs.h>  #include <linux/seq_file.h> +#include <linux/slab.h>  #include <net/irda/irda.h>  #include <net/irda/irlmp.h> diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c index 018c92941ab..e97082017f4 100644 --- a/net/irda/ircomm/ircomm_core.c +++ b/net/irda/ircomm/ircomm_core.c @@ -33,6 +33,7 @@  #include <linux/proc_fs.h>  #include <linux/seq_file.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <net/irda/irda.h>  #include <net/irda/irmod.h> diff --git a/net/irda/ircomm/ircomm_lmp.c b/net/irda/ircomm/ircomm_lmp.c index 7ba96618660..08fb54dc8c4 100644 --- a/net/irda/ircomm/ircomm_lmp.c +++ b/net/irda/ircomm/ircomm_lmp.c @@ -31,6 +31,7 @@   ********************************************************************/  #include <linux/init.h> +#include <linux/gfp.h>  #include <net/irda/irda.h>  #include <net/irda/irlmp.h> diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c index d57aefd9fe7..e2e893b474e 100644 --- a/net/irda/ircomm/ircomm_param.c +++ b/net/irda/ircomm/ircomm_param.c @@ -28,6 +28,7 @@   *   ********************************************************************/ +#include <linux/gfp.h>  #include <linux/workqueue.h>  #include <linux/interrupt.h> diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 8b85d774e47..faa82ca2dfd 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -33,6 +33,7 @@  #include <linux/init.h>  #include <linux/module.h>  #include <linux/fs.h> +#include <linux/slab.h>  #include <linux/sched.h>  #include <linux/seq_file.h>  #include <linux/termios.h> diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c index bf92e147344..25cc2e69515 100644 --- a/net/irda/irda_device.c +++ b/net/irda/irda_device.c @@ -41,6 +41,7 @@  #include <linux/tty.h>  #include <linux/kmod.h>  #include <linux/spinlock.h> +#include <linux/slab.h>  #include <asm/ioctls.h>  #include <asm/uaccess.h> diff --git a/net/irda/iriap.c b/net/irda/iriap.c index 294e34d3517..79a1e5a23e1 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c @@ -31,6 +31,7 @@  #include <linux/string.h>  #include <linux/init.h>  #include <linux/seq_file.h> +#include <linux/slab.h>  #include <asm/byteorder.h>  #include <asm/unaligned.h> diff --git a/net/irda/iriap_event.c b/net/irda/iriap_event.c index a301cbd9378..703774e29e3 100644 --- a/net/irda/iriap_event.c +++ b/net/irda/iriap_event.c @@ -24,6 +24,8 @@   *   ********************************************************************/ +#include <linux/slab.h> +  #include <net/irda/irda.h>  #include <net/irda/irlmp.h>  #include <net/irda/iriap.h> diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c index 99ebb96f138..f07ed9fd579 100644 --- a/net/irda/irias_object.c +++ b/net/irda/irias_object.c @@ -22,6 +22,7 @@   *   ********************************************************************/ +#include <linux/slab.h>  #include <linux/string.h>  #include <linux/socket.h>  #include <linux/module.h> diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c index 42f7d960d05..7ed3af95793 100644 --- a/net/irda/irlan/irlan_client.c +++ b/net/irda/irlan/irlan_client.c @@ -28,6 +28,7 @@  #include <linux/kernel.h>  #include <linux/string.h> +#include <linux/slab.h>  #include <linux/errno.h>  #include <linux/init.h>  #include <linux/netdevice.h> diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index e486dc89ea5..a788f9e9427 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c @@ -27,6 +27,7 @@  #include <linux/kernel.h>  #include <linux/string.h> +#include <linux/gfp.h>  #include <linux/init.h>  #include <linux/errno.h>  #include <linux/proc_fs.h> diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c index 3f81f81b2df..5cf5e6c872b 100644 --- a/net/irda/irlan/irlan_provider.c +++ b/net/irda/irlan/irlan_provider.c @@ -34,6 +34,7 @@  #include <linux/init.h>  #include <linux/random.h>  #include <linux/bitops.h> +#include <linux/slab.h>  #include <asm/system.h>  #include <asm/byteorder.h> diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c index 94a9884d714..d434c888074 100644 --- a/net/irda/irlap_event.c +++ b/net/irda/irlap_event.c @@ -29,6 +29,7 @@  #include <linux/kernel.h>  #include <linux/delay.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/irda/irda.h>  #include <net/irda/irlap_event.h> diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index 7af2e74deda..688222cbf55 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c @@ -29,6 +29,7 @@  #include <linux/if_ether.h>  #include <linux/netdevice.h>  #include <linux/irda.h> +#include <linux/slab.h>  #include <net/pkt_sched.h>  #include <net/sock.h> diff --git a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c index b26dee784ab..df18ab4b6c5 100644 --- a/net/irda/irnet/irnet_irda.c +++ b/net/irda/irnet/irnet_irda.c @@ -11,6 +11,7 @@  #include "irnet_irda.h"		/* Private header */  #include <linux/sched.h>  #include <linux/seq_file.h> +#include <linux/slab.h>  #include <asm/unaligned.h>  /* diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c index 6b3602de359..6a1a202710c 100644 --- a/net/irda/irnet/irnet_ppp.c +++ b/net/irda/irnet/irnet_ppp.c @@ -14,6 +14,7 @@   */  #include <linux/sched.h> +#include <linux/slab.h>  #include <linux/smp_lock.h>  #include "irnet_ppp.h"		/* Private header */  /* Please put other headers in irnet.h - Thanks */ diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c index 69b5b75f543..6c7c4b92e4f 100644 --- a/net/irda/irnetlink.c +++ b/net/irda/irnetlink.c @@ -15,6 +15,7 @@  #include <linux/socket.h>  #include <linux/irda.h> +#include <linux/gfp.h>  #include <net/net_namespace.h>  #include <net/sock.h>  #include <net/irda/irda.h> diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c index ba01938becb..849aaf0dabb 100644 --- a/net/irda/irqueue.c +++ b/net/irda/irqueue.c @@ -192,6 +192,7 @@   * Jean II   */  #include <linux/module.h> +#include <linux/slab.h>  #include <net/irda/irda.h>  #include <net/irda/irqueue.h> diff --git a/net/irda/irttp.c b/net/irda/irttp.c index 9cb79f95bf6..47db1d8a0d9 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c @@ -28,6 +28,7 @@  #include <linux/init.h>  #include <linux/fs.h>  #include <linux/seq_file.h> +#include <linux/slab.h>  #include <asm/byteorder.h>  #include <asm/unaligned.h> diff --git a/net/key/af_key.c b/net/key/af_key.c index 36870788264..ba9a3fcc2fe 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -26,6 +26,7 @@  #include <linux/in6.h>  #include <linux/proc_fs.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/netns/generic.h>  #include <net/xfrm.h> @@ -2129,10 +2130,9 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c  	int err;  	out_skb = pfkey_xfrm_policy2msg_prep(xp); -	if (IS_ERR(out_skb)) { -		err = PTR_ERR(out_skb); -		goto out; -	} +	if (IS_ERR(out_skb)) +		return PTR_ERR(out_skb); +  	err = pfkey_xfrm_policy2msg(out_skb, xp, dir);  	if (err < 0)  		return err; @@ -2148,7 +2148,6 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c  	out_hdr->sadb_msg_seq = c->seq;  	out_hdr->sadb_msg_pid = c->pid;  	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xp_net(xp)); -out:  	return 0;  } diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c index bda96d18fd9..d5d8d555c41 100644 --- a/net/lapb/lapb_iface.c +++ b/net/lapb/lapb_iface.c @@ -29,6 +29,7 @@  #include <linux/inet.h>  #include <linux/if_arp.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <asm/uaccess.h>  #include <asm/system.h> diff --git a/net/lapb/lapb_in.c b/net/lapb/lapb_in.c index 6762e7c751e..21904a00244 100644 --- a/net/lapb/lapb_in.c +++ b/net/lapb/lapb_in.c @@ -27,6 +27,7 @@  #include <linux/inet.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <asm/uaccess.h>  #include <asm/system.h> diff --git a/net/lapb/lapb_out.c b/net/lapb/lapb_out.c index 339cc5f2684..c75a79540f9 100644 --- a/net/lapb/lapb_out.c +++ b/net/lapb/lapb_out.c @@ -25,6 +25,7 @@  #include <linux/net.h>  #include <linux/inet.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <asm/uaccess.h>  #include <asm/system.h> diff --git a/net/lapb/lapb_subr.c b/net/lapb/lapb_subr.c index b827f47ac13..43a2a7fb327 100644 --- a/net/lapb/lapb_subr.c +++ b/net/lapb/lapb_subr.c @@ -24,6 +24,7 @@  #include <linux/net.h>  #include <linux/inet.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <asm/uaccess.h>  #include <asm/system.h> diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index e35d907fba2..2db6a9f7591 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -25,6 +25,7 @@  #include <linux/module.h>  #include <linux/rtnetlink.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <net/llc.h>  #include <net/llc_sap.h>  #include <net/llc_pdu.h> diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index 019c780512e..ea225bd2672 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -18,6 +18,7 @@   * See the GNU General Public License for more details.   */  #include <linux/netdevice.h> +#include <linux/slab.h>  #include <net/llc_conn.h>  #include <net/llc_sap.h>  #include <net/sock.h> @@ -1437,7 +1438,7 @@ static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb)  			llc_conn_state_process(sk, skb);  		else {  			llc_set_backlog_type(skb, LLC_EVENT); -			sk_add_backlog(sk, skb); +			__sk_add_backlog(sk, skb);  		}  	}  } diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index a8dde9b010d..ba137a6a224 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -13,6 +13,7 @@   */  #include <linux/init.h> +#include <linux/slab.h>  #include <net/llc_sap.h>  #include <net/llc_conn.h>  #include <net/sock.h> @@ -827,7 +828,8 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)  	else {  		dprintk("%s: adding to backlog...\n", __func__);  		llc_set_backlog_type(skb, LLC_PACKET); -		sk_add_backlog(sk, skb); +		if (sk_add_backlog(sk, skb)) +			goto drop_unlock;  	}  out:  	bh_unlock_sock(sk); diff --git a/net/llc/llc_if.c b/net/llc/llc_if.c index a89917130a7..25c31c0a3fd 100644 --- a/net/llc/llc_if.c +++ b/net/llc/llc_if.c @@ -11,6 +11,7 @@   *   * See the GNU General Public License for more details.   */ +#include <linux/gfp.h>  #include <linux/module.h>  #include <linux/kernel.h>  #include <linux/netdevice.h> diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index 57ad974e4d9..f9968743913 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c @@ -12,6 +12,7 @@   * See the GNU General Public License for more details.   */  #include <linux/netdevice.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/llc.h>  #include <net/llc_pdu.h> diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index ad6e6e1cf22..94e7fca75b8 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c @@ -23,6 +23,7 @@  #include <net/sock.h>  #include <net/tcp_states.h>  #include <linux/llc.h> +#include <linux/slab.h>  static int llc_mac_header_len(unsigned short devtype)  { @@ -30,7 +31,7 @@ static int llc_mac_header_len(unsigned short devtype)  	case ARPHRD_ETHER:  	case ARPHRD_LOOPBACK:  		return sizeof(struct ethhdr); -#ifdef CONFIG_TR +#if defined(CONFIG_TR) || defined(CONFIG_TR_MODULE)  	case ARPHRD_IEEE802_TR:  		return sizeof(struct trh_hdr);  #endif diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index 83da1333949..e4dae0244d7 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c @@ -13,6 +13,7 @@   */  #include <linux/init.h>  #include <linux/module.h> +#include <linux/slab.h>  #include <net/llc.h>  #include <net/llc_sap.h>  #include <net/llc_conn.h> diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index a978e666ed6..f9516a27e23 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -14,6 +14,7 @@   */  #include <linux/ieee80211.h> +#include <linux/slab.h>  #include <net/mac80211.h>  #include "ieee80211_i.h"  #include "driver-ops.h" diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 5538e1b4a69..87782a4bb54 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -14,6 +14,7 @@   */  #include <linux/ieee80211.h> +#include <linux/slab.h>  #include <net/mac80211.h>  #include "ieee80211_i.h"  #include "driver-ops.h" @@ -183,7 +184,6 @@ static void sta_addba_resp_timer_expired(unsigned long data)  		       HT_AGG_STATE_REQ_STOP_BA_MSK)) !=  						HT_ADDBA_REQUESTED_MSK) {  		spin_unlock_bh(&sta->lock); -		*state = HT_AGG_STATE_IDLE;  #ifdef CONFIG_MAC80211_HT_DEBUG  		printk(KERN_DEBUG "timer expired on tid %d but we are not "  				"(or no longer) expecting addBA response there", diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index b7116ef84a3..edc872e22c9 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -9,6 +9,7 @@  #include <linux/ieee80211.h>  #include <linux/nl80211.h>  #include <linux/rtnetlink.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <linux/rcupdate.h>  #include <net/cfg80211.h> diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index d12e743cb4e..97c9e46e859 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c @@ -9,6 +9,7 @@   */  #include <linux/kobject.h> +#include <linux/slab.h>  #include "ieee80211_i.h"  #include "key.h"  #include "debugfs.h" diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 9affe2cd185..83d4289d954 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -13,6 +13,7 @@  #include <linux/interrupt.h>  #include <linux/netdevice.h>  #include <linux/rtnetlink.h> +#include <linux/slab.h>  #include <linux/notifier.h>  #include <net/mac80211.h>  #include <net/cfg80211.h> @@ -48,20 +49,24 @@ static ssize_t ieee80211_if_write(  	ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int))  {  	u8 *buf; -	ssize_t ret = -ENODEV; +	ssize_t ret; -	buf = kzalloc(count, GFP_KERNEL); +	buf = kmalloc(count, GFP_KERNEL);  	if (!buf)  		return -ENOMEM; +	ret = -EFAULT;  	if (copy_from_user(buf, userbuf, count)) -		return -EFAULT; +		goto freebuf; +	ret = -ENODEV;  	rtnl_lock();  	if (sdata->dev->reg_state == NETREG_REGISTERED)  		ret = (*write)(sdata, buf, count);  	rtnl_unlock(); +freebuf: +	kfree(buf);  	return ret;  } diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index f3e94248674..e2976da4e0d 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -13,6 +13,7 @@   */  #include <linux/delay.h> +#include <linux/slab.h>  #include <linux/if_ether.h>  #include <linux/skbuff.h>  #include <linux/if_arp.h> diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 0793d7a8d74..e08fa8eda1b 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -10,6 +10,7 @@   * it under the terms of the GNU General Public License version 2 as   * published by the Free Software Foundation.   */ +#include <linux/slab.h>  #include <linux/kernel.h>  #include <linux/if_arp.h>  #include <linux/netdevice.h> diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 8160d9c5372..e8f6e3b252d 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -14,6 +14,7 @@  #include <linux/list.h>  #include <linux/rcupdate.h>  #include <linux/rtnetlink.h> +#include <linux/slab.h>  #include <net/mac80211.h>  #include "ieee80211_i.h"  #include "driver-ops.h" diff --git a/net/mac80211/led.c b/net/mac80211/led.c index 162a643f16b..063aad94424 100644 --- a/net/mac80211/led.c +++ b/net/mac80211/led.c @@ -8,6 +8,7 @@  /* just for IFNAMSIZ */  #include <linux/if.h> +#include <linux/slab.h>  #include "led.h"  void ieee80211_led_rx(struct ieee80211_local *local) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 06c33b68d8e..b887e484ae0 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -225,11 +225,11 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,  			switch (sdata->vif.type) {  			case NL80211_IFTYPE_AP:  				sdata->vif.bss_conf.enable_beacon = -					!!rcu_dereference(sdata->u.ap.beacon); +					!!sdata->u.ap.beacon;  				break;  			case NL80211_IFTYPE_ADHOC:  				sdata->vif.bss_conf.enable_beacon = -					!!rcu_dereference(sdata->u.ibss.presp); +					!!sdata->u.ibss.presp;  				break;  			case NL80211_IFTYPE_MESH_POINT:  				sdata->vif.bss_conf.enable_beacon = true; diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 61080c5fad5..859ee5f3d94 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -8,6 +8,7 @@   * published by the Free Software Foundation.   */ +#include <linux/slab.h>  #include <asm/unaligned.h>  #include "ieee80211_i.h"  #include "mesh.h" @@ -749,9 +750,6 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)  	switch (fc & IEEE80211_FCTL_STYPE) {  	case IEEE80211_STYPE_ACTION: -		if (skb->len < IEEE80211_MIN_ACTION_SIZE) -			return RX_DROP_MONITOR; -		/* fall through */  	case IEEE80211_STYPE_PROBE_RESP:  	case IEEE80211_STYPE_BEACON:  		skb_queue_tail(&ifmsh->skb_queue, skb); diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index ce84237ebad..fefc45c4b4e 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -7,6 +7,7 @@   * published by the Free Software Foundation.   */ +#include <linux/slab.h>  #include "mesh.h"  #ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG @@ -391,7 +392,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,  				if (SN_GT(mpath->sn, orig_sn) ||  				    (mpath->sn == orig_sn &&  				     action == MPATH_PREQ && -				     new_metric > mpath->metric)) { +				     new_metric >= mpath->metric)) {  					process = false;  					fresh_info = false;  				} @@ -611,7 +612,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,  	mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr,  		cpu_to_le32(orig_sn), 0, target_addr, -		cpu_to_le32(target_sn), mpath->next_hop->sta.addr, hopcount, +		cpu_to_le32(target_sn), next_hop, hopcount,  		ttl, cpu_to_le32(lifetime), cpu_to_le32(metric),  		0, sdata);  	rcu_read_unlock(); diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 2312efe04c6..181ffd6efd8 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -10,6 +10,7 @@  #include <linux/etherdevice.h>  #include <linux/list.h>  #include <linux/random.h> +#include <linux/slab.h>  #include <linux/spinlock.h>  #include <linux/string.h>  #include <net/mac80211.h> diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index bc4e20e57ff..7b7080e2b49 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -6,6 +6,7 @@   * it under the terms of the GNU General Public License version 2 as   * published by the Free Software Foundation.   */ +#include <linux/gfp.h>  #include <linux/kernel.h>  #include <linux/random.h>  #include "ieee80211_i.h" @@ -744,7 +745,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  		break;  	default:  		/* should not get here, PLINK_BLOCKED is dealt with at the -		 * beggining of the function +		 * beginning of the function  		 */  		spin_unlock_bh(&sta->lock);  		break; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 41812a15eea..875c8dec940 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -19,6 +19,7 @@  #include <linux/rtnetlink.h>  #include <linux/pm_qos_params.h>  #include <linux/crc32.h> +#include <linux/slab.h>  #include <net/mac80211.h>  #include <asm/unaligned.h> @@ -167,6 +168,8 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,  	ht_changed = conf_is_ht(&local->hw.conf) != enable_ht ||  		     channel_type != local->hw.conf.channel_type; +	if (local->tmp_channel) +		local->tmp_channel_type = channel_type;  	local->oper_channel_type = channel_type;  	if (ht_changed) { @@ -177,7 +180,8 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,  		sta = sta_info_get(sdata, bssid);  		if (sta)  			rate_control_rate_update(local, sband, sta, -						 IEEE80211_RC_HT_CHANGED); +						 IEEE80211_RC_HT_CHANGED, +						 local->oper_channel_type);  		rcu_read_unlock();          } @@ -435,10 +439,12 @@ static void ieee80211_enable_ps(struct ieee80211_local *local,  		if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)  			ieee80211_send_nullfunc(local, sdata, 1); -		if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { -			conf->flags |= IEEE80211_CONF_PS; -			ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); -		} +		if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && +		    (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) +			return; + +		conf->flags |= IEEE80211_CONF_PS; +		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);  	}  } @@ -557,7 +563,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)  	    (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)))  		ieee80211_send_nullfunc(local, sdata, 1); -	if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) || +	if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) && +	      (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) ||  	    (ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {  		ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;  		local->hw.conf.flags |= IEEE80211_CONF_PS; @@ -1893,8 +1900,20 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,  	mutex_lock(&ifmgd->mtx);  	if (ifmgd->associated) { -		mutex_unlock(&ifmgd->mtx); -		return -EALREADY; +		if (!req->prev_bssid || +		    memcmp(req->prev_bssid, ifmgd->associated->bssid, +			   ETH_ALEN)) { +			/* +			 * We are already associated and the request was not a +			 * reassociation request from the current BSS, so +			 * reject it. +			 */ +			mutex_unlock(&ifmgd->mtx); +			return -EALREADY; +		} + +		/* Trying to reassociate - clear previous association state */ +		ieee80211_set_disassoc(sdata);  	}  	mutex_unlock(&ifmgd->mtx); @@ -2011,7 +2030,8 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,  				continue;  			if (wk->type != IEEE80211_WORK_DIRECT_PROBE && -			    wk->type != IEEE80211_WORK_AUTH) +			    wk->type != IEEE80211_WORK_AUTH && +			    wk->type != IEEE80211_WORK_ASSOC)  				continue;  			if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN)) diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 0b299d236fa..6d0bd198af1 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -10,6 +10,7 @@  #include <linux/kernel.h>  #include <linux/rtnetlink.h> +#include <linux/slab.h>  #include "rate.h"  #include "ieee80211_i.h"  #include "debugfs.h" diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index b6108bca96d..065a96190e3 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -66,7 +66,8 @@ static inline void rate_control_rate_init(struct sta_info *sta)  static inline void rate_control_rate_update(struct ieee80211_local *local,  				    struct ieee80211_supported_band *sband, -				    struct sta_info *sta, u32 changed) +				    struct sta_info *sta, u32 changed, +				    enum nl80211_channel_type oper_chan_type)  {  	struct rate_control_ref *ref = local->rate_ctrl;  	struct ieee80211_sta *ista = &sta->sta; @@ -74,7 +75,7 @@ static inline void rate_control_rate_update(struct ieee80211_local *local,  	if (ref && ref->ops->rate_update)  		ref->ops->rate_update(ref->priv, sband, ista, -				      priv_sta, changed); +				      priv_sta, changed, oper_chan_type);  }  static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 6e5d68b4e42..818abfae900 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -50,6 +50,7 @@  #include <linux/debugfs.h>  #include <linux/random.h>  #include <linux/ieee80211.h> +#include <linux/slab.h>  #include <net/mac80211.h>  #include "rate.h"  #include "rc80211_minstrel.h" diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index a715d9454f6..0e1f12b1b6d 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c @@ -49,6 +49,7 @@  #include <linux/skbuff.h>  #include <linux/debugfs.h>  #include <linux/ieee80211.h> +#include <linux/slab.h>  #include <net/mac80211.h>  #include "rc80211_minstrel.h" diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 2652a374974..aeda65466f3 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -13,6 +13,7 @@  #include <linux/types.h>  #include <linux/skbuff.h>  #include <linux/debugfs.h> +#include <linux/slab.h>  #include <net/mac80211.h>  #include "rate.h"  #include "mesh.h" diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c index 45667054a5f..47438b4a9af 100644 --- a/net/mac80211/rc80211_pid_debugfs.c +++ b/net/mac80211/rc80211_pid_debugfs.c @@ -12,6 +12,7 @@  #include <linux/netdevice.h>  #include <linux/types.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/mac80211.h>  #include "rate.h" diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b5c48de81d8..04ea07f0e78 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -10,6 +10,7 @@   */  #include <linux/jiffies.h> +#include <linux/slab.h>  #include <linux/kernel.h>  #include <linux/skbuff.h>  #include <linux/netdevice.h> @@ -1973,6 +1974,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)  			goto handled;  		}  		break; +	case MESH_PLINK_CATEGORY: +	case MESH_PATH_SEL_CATEGORY: +		if (ieee80211_vif_is_mesh(&sdata->vif)) +			return ieee80211_mesh_rx_mgmt(sdata, rx->skb); +		break;  	}  	/* diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index b822dce9786..85507bd9e34 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -14,6 +14,7 @@  #include <linux/if_arp.h>  #include <linux/rtnetlink.h> +#include <linux/slab.h>  #include <net/mac80211.h>  #include "ieee80211_i.h" diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 211c475f73c..fb12cec4d33 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -93,12 +93,18 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,  	struct ieee80211_local *local = sdata->local;  	struct sta_info *sta; -	sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); +	sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], +				    rcu_read_lock_held() || +				    lockdep_is_held(&local->sta_lock) || +				    lockdep_is_held(&local->sta_mtx));  	while (sta) {  		if (sta->sdata == sdata &&  		    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)  			break; -		sta = rcu_dereference(sta->hnext); +		sta = rcu_dereference_check(sta->hnext, +					    rcu_read_lock_held() || +					    lockdep_is_held(&local->sta_lock) || +					    lockdep_is_held(&local->sta_mtx));  	}  	return sta;  } @@ -113,13 +119,19 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,  	struct ieee80211_local *local = sdata->local;  	struct sta_info *sta; -	sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); +	sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], +				    rcu_read_lock_held() || +				    lockdep_is_held(&local->sta_lock) || +				    lockdep_is_held(&local->sta_mtx));  	while (sta) {  		if ((sta->sdata == sdata ||  		     sta->sdata->bss == sdata->bss) &&  		    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)  			break; -		sta = rcu_dereference(sta->hnext); +		sta = rcu_dereference_check(sta->hnext, +					    rcu_read_lock_held() || +					    lockdep_is_held(&local->sta_lock) || +					    lockdep_is_held(&local->sta_mtx));  	}  	return sta;  } @@ -434,6 +446,7 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)  	/* check if STA exists already */  	if (sta_info_get_bss(sdata, sta->sta.addr)) {  		spin_unlock_irqrestore(&local->sta_lock, flags); +		mutex_unlock(&local->sta_mtx);  		rcu_read_lock();  		err = -EEXIST;  		goto out_free; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index cbe53ed4fb0..cfc473e1b05 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1991,6 +1991,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,  void ieee80211_tx_pending(unsigned long data)  {  	struct ieee80211_local *local = (struct ieee80211_local *)data; +	struct ieee80211_sub_if_data *sdata;  	unsigned long flags;  	int i;  	bool txok; @@ -2029,6 +2030,11 @@ void ieee80211_tx_pending(unsigned long data)  			if (!txok)  				break;  		} + +		if (skb_queue_empty(&local->pending[i])) +			list_for_each_entry_rcu(sdata, &local->interfaces, list) +				netif_tx_wake_queue( +					netdev_get_tx_queue(sdata->dev, i));  	}  	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index c453226f06b..53af5704743 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -279,13 +279,13 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,  		/* someone still has this queue stopped */  		return; -	if (!skb_queue_empty(&local->pending[queue])) +	if (skb_queue_empty(&local->pending[queue])) { +		rcu_read_lock(); +		list_for_each_entry_rcu(sdata, &local->interfaces, list) +			netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue)); +		rcu_read_unlock(); +	} else  		tasklet_schedule(&local->tx_pending_tasklet); - -	rcu_read_lock(); -	list_for_each_entry_rcu(sdata, &local->interfaces, list) -		netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue)); -	rcu_read_unlock();  }  void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, @@ -1097,9 +1097,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)  		 */  		res = drv_start(local);  		if (res) { -			WARN(local->suspended, "Harware became unavailable " -			     "upon resume. This is could be a software issue" -			     "prior to suspend or a hardware issue\n"); +			WARN(local->suspended, "Hardware became unavailable " +			     "upon resume. This could be a software issue " +			     "prior to suspend or a hardware issue.\n");  			return res;  		} diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 5d745f2d723..5f3a4113bda 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -17,6 +17,7 @@  #include <linux/err.h>  #include <linux/mm.h>  #include <linux/scatterlist.h> +#include <linux/slab.h>  #include <asm/unaligned.h>  #include <net/mac80211.h> diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 1e1ea3007b0..15e1ba931b8 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -19,6 +19,7 @@  #include <linux/if_arp.h>  #include <linux/etherdevice.h>  #include <linux/crc32.h> +#include <linux/slab.h>  #include <net/mac80211.h>  #include <asm/unaligned.h> diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index f4971cd45c6..0adbcc941ac 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -9,10 +9,10 @@  #include <linux/netdevice.h>  #include <linux/types.h> -#include <linux/slab.h>  #include <linux/skbuff.h>  #include <linux/compiler.h>  #include <linux/ieee80211.h> +#include <linux/gfp.h>  #include <asm/unaligned.h>  #include <net/mac80211.h> diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 60ec4e4bada..78b505d33bf 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -19,6 +19,7 @@  #include <linux/inetdevice.h>  #include <linux/proc_fs.h>  #include <linux/mutex.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/sock.h> diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c index 3c7e42735b6..1cb0e834f8f 100644 --- a/net/netfilter/ipvs/ip_vs_app.c +++ b/net/netfilter/ipvs/ip_vs_app.c @@ -27,6 +27,7 @@  #include <linux/in.h>  #include <linux/ip.h>  #include <linux/netfilter.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/protocol.h>  #include <net/tcp.h> diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 60bb41a8d8d..d8f7e8ef67b 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -32,6 +32,7 @@  #include <linux/module.h>  #include <linux/vmalloc.h>  #include <linux/proc_fs.h>		/* for proc_net_* */ +#include <linux/slab.h>  #include <linux/seq_file.h>  #include <linux/jhash.h>  #include <linux/random.h> diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 44590887a92..1cd6e3fd058 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -33,6 +33,7 @@  #include <linux/tcp.h>  #include <linux/sctp.h>  #include <linux/icmp.h> +#include <linux/slab.h>  #include <net/ip.h>  #include <net/tcp.h> diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 7ee9c3426f4..36dc1d88c2f 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -31,6 +31,7 @@  #include <linux/workqueue.h>  #include <linux/swap.h>  #include <linux/seq_file.h> +#include <linux/slab.h>  #include <linux/netfilter.h>  #include <linux/netfilter_ipv4.h> diff --git a/net/netfilter/ipvs/ip_vs_dh.c b/net/netfilter/ipvs/ip_vs_dh.c index fe3e18834b9..95fd0d14200 100644 --- a/net/netfilter/ipvs/ip_vs_dh.c +++ b/net/netfilter/ipvs/ip_vs_dh.c @@ -39,6 +39,7 @@  #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt  #include <linux/ip.h> +#include <linux/slab.h>  #include <linux/module.h>  #include <linux/kernel.h>  #include <linux/skbuff.h> diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c index 702b53ca937..ff28801962e 100644 --- a/net/netfilter/ipvs/ip_vs_est.c +++ b/net/netfilter/ipvs/ip_vs_est.c @@ -17,7 +17,6 @@  #include <linux/kernel.h>  #include <linux/jiffies.h> -#include <linux/slab.h>  #include <linux/types.h>  #include <linux/interrupt.h>  #include <linux/sysctl.h> diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c index 73f38ea98f2..2c7f185dfae 100644 --- a/net/netfilter/ipvs/ip_vs_ftp.c +++ b/net/netfilter/ipvs/ip_vs_ftp.c @@ -32,6 +32,7 @@  #include <linux/in.h>  #include <linux/ip.h>  #include <linux/netfilter.h> +#include <linux/gfp.h>  #include <net/protocol.h>  #include <net/tcp.h>  #include <asm/unaligned.h> diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c index 1b9370db230..94a45213faa 100644 --- a/net/netfilter/ipvs/ip_vs_lblc.c +++ b/net/netfilter/ipvs/ip_vs_lblc.c @@ -43,6 +43,7 @@  #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt  #include <linux/ip.h> +#include <linux/slab.h>  #include <linux/module.h>  #include <linux/kernel.h>  #include <linux/skbuff.h> diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index caa58fa1438..535dc2b419d 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c @@ -46,6 +46,7 @@  #include <linux/skbuff.h>  #include <linux/jiffies.h>  #include <linux/list.h> +#include <linux/slab.h>  /* for sysctl */  #include <linux/fs.h> diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c index 0e584553819..7fc49f4cf5a 100644 --- a/net/netfilter/ipvs/ip_vs_proto.c +++ b/net/netfilter/ipvs/ip_vs_proto.c @@ -19,6 +19,7 @@  #include <linux/module.h>  #include <linux/kernel.h>  #include <linux/skbuff.h> +#include <linux/gfp.h>  #include <linux/in.h>  #include <linux/ip.h>  #include <net/protocol.h> diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c index 8e6cfd36e6f..e6cc174fbc0 100644 --- a/net/netfilter/ipvs/ip_vs_sh.c +++ b/net/netfilter/ipvs/ip_vs_sh.c @@ -36,6 +36,7 @@  #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt  #include <linux/ip.h> +#include <linux/slab.h>  #include <linux/module.h>  #include <linux/kernel.h>  #include <linux/skbuff.h> diff --git a/net/netfilter/ipvs/ip_vs_wrr.c b/net/netfilter/ipvs/ip_vs_wrr.c index 3c115fc1978..30db633f88f 100644 --- a/net/netfilter/ipvs/ip_vs_wrr.c +++ b/net/netfilter/ipvs/ip_vs_wrr.c @@ -23,6 +23,7 @@  #include <linux/module.h>  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/net.h>  #include <linux/gcd.h> diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 223b5018c7d..e450cd6f4eb 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -17,6 +17,7 @@  #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/tcp.h>                  /* for tcphdr */  #include <net/ip.h>  #include <net/tcp.h>                    /* for csum_tcpudp_magic */ diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c index 018f90db511..ab81b380eae 100644 --- a/net/netfilter/nf_conntrack_acct.c +++ b/net/netfilter/nf_conntrack_acct.c @@ -9,6 +9,7 @@   */  #include <linux/netfilter.h> +#include <linux/slab.h>  #include <linux/kernel.h>  #include <linux/moduleparam.h> diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c index 07d9d8857e5..372e80f07a8 100644 --- a/net/netfilter/nf_conntrack_amanda.c +++ b/net/netfilter/nf_conntrack_amanda.c @@ -16,6 +16,7 @@  #include <linux/in.h>  #include <linux/udp.h>  #include <linux/netfilter.h> +#include <linux/gfp.h>  #include <net/netfilter/nf_conntrack.h>  #include <net/netfilter/nf_conntrack_expect.h> diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index d5a9bcd7d61..f516961a83b 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -18,6 +18,7 @@  #include <linux/percpu.h>  #include <linux/kernel.h>  #include <linux/netdevice.h> +#include <linux/slab.h>  #include <net/netfilter/nf_conntrack.h>  #include <net/netfilter/nf_conntrack_core.h> diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index f0732aa18e4..2ae3169e763 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -13,6 +13,7 @@  #include <linux/moduleparam.h>  #include <linux/netfilter.h>  #include <linux/ip.h> +#include <linux/slab.h>  #include <linux/ipv6.h>  #include <linux/ctype.h>  #include <linux/inet.h> diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index a1c8dd917e1..a487c803804 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -17,6 +17,7 @@  #include <linux/inet.h>  #include <linux/in.h>  #include <linux/ip.h> +#include <linux/slab.h>  #include <linux/udp.h>  #include <linux/tcp.h>  #include <linux/skbuff.h> diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 4509fa6726f..59e1a4cd4e8 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -15,7 +15,6 @@  #include <linux/skbuff.h>  #include <linux/vmalloc.h>  #include <linux/stddef.h> -#include <linux/slab.h>  #include <linux/random.h>  #include <linux/err.h>  #include <linux/kernel.h> diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index 8bd98c84f77..7673930ca34 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c @@ -15,6 +15,7 @@  #include <linux/ip.h>  #include <linux/tcp.h>  #include <linux/netfilter.h> +#include <linux/slab.h>  #include <net/netfilter/nf_conntrack.h>  #include <net/netfilter/nf_conntrack_expect.h> diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 2b2af631d2b..afc52f2ee4a 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -27,6 +27,7 @@  #include <linux/netlink.h>  #include <linux/spinlock.h>  #include <linux/interrupt.h> +#include <linux/slab.h>  #include <linux/netfilter.h>  #include <net/netlink.h> @@ -582,7 +583,9 @@ nla_put_failure:  nlmsg_failure:  	kfree_skb(skb);  errout: -	nfnetlink_set_err(net, 0, group, -ENOBUFS); +	if (nfnetlink_set_err(net, 0, group, -ENOBUFS) > 0) +		return -ENOBUFS; +  	return 0;  }  #endif /* CONFIG_NF_CONNTRACK_EVENTS */ diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 1a4568bf7ea..a44fa75b517 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c @@ -12,6 +12,7 @@  #include <linux/types.h>  #include <linux/netfilter.h>  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/mutex.h>  #include <linux/skbuff.h>  #include <linux/vmalloc.h> diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index 9a281554937..5292560d6d4 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c @@ -15,6 +15,7 @@  #include <linux/spinlock.h>  #include <linux/skbuff.h>  #include <linux/dccp.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/netns/generic.h> diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index d899b1a6994..cf616e55ca4 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -31,6 +31,7 @@  #include <linux/in.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/dst.h>  #include <net/net_namespace.h>  #include <net/netns/generic.h> diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c index dcfecbb81c4..d9e27734b2a 100644 --- a/net/netfilter/nf_conntrack_sane.c +++ b/net/netfilter/nf_conntrack_sane.c @@ -20,6 +20,7 @@  #include <linux/module.h>  #include <linux/moduleparam.h>  #include <linux/netfilter.h> +#include <linux/slab.h>  #include <linux/in.h>  #include <linux/tcp.h>  #include <net/netfilter/nf_conntrack.h> diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 8dd75d90efc..c6cd1b84edd 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -284,7 +284,7 @@ EXPORT_SYMBOL_GPL(ct_sip_parse_request);   * tabs, spaces and continuation lines, which are treated as a single whitespace   * character.   * - * Some headers may appear multiple times. A comma seperated list of values is + * Some headers may appear multiple times. A comma separated list of values is   * equivalent to multiple headers.   */  static const struct sip_header ct_sip_hdrs[] = { @@ -421,7 +421,7 @@ int ct_sip_get_header(const struct nf_conn *ct, const char *dptr,  }  EXPORT_SYMBOL_GPL(ct_sip_get_header); -/* Get next header field in a list of comma seperated values */ +/* Get next header field in a list of comma separated values */  static int ct_sip_next_header(const struct nf_conn *ct, const char *dptr,  			      unsigned int dataoff, unsigned int datalen,  			      enum sip_header_types type, diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 24a42efe62e..faa8eb3722b 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -8,6 +8,7 @@  #include <linux/types.h>  #include <linux/netfilter.h> +#include <linux/slab.h>  #include <linux/module.h>  #include <linux/skbuff.h>  #include <linux/proc_fs.h> diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index ba095fd014e..c49ef219899 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -1,4 +1,5 @@  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/init.h>  #include <linux/module.h>  #include <linux/proc_fs.h> diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 8eb0cc23ada..6afa3d52ea5 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -113,9 +113,9 @@ int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid,  }  EXPORT_SYMBOL_GPL(nfnetlink_send); -void nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error) +int nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error)  { -	netlink_set_err(net->nfnl, pid, group, error); +	return netlink_set_err(net->nfnl, pid, group, error);  }  EXPORT_SYMBOL_GPL(nfnetlink_set_err); diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index d9b8fb8ab34..203643fb2c5 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -28,6 +28,7 @@  #include <linux/list.h>  #include <linux/jhash.h>  #include <linux/random.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/netfilter/nf_log.h>  #include <net/netfilter/nfnetlink_log.h> diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 7ba4abc405c..e70a6ef1f4f 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -18,6 +18,7 @@  #include <linux/skbuff.h>  #include <linux/init.h>  #include <linux/spinlock.h> +#include <linux/slab.h>  #include <linux/notifier.h>  #include <linux/netdevice.h>  #include <linux/netfilter.h> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 0a12cedfe9e..665f5beef6a 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -22,6 +22,7 @@  #include <linux/vmalloc.h>  #include <linux/mutex.h>  #include <linux/mm.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <linux/netfilter/x_tables.h> diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 61c50fa8470..ee18b231b95 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c @@ -7,6 +7,7 @@   */  #include <linux/module.h> +#include <linux/gfp.h>  #include <linux/skbuff.h>  #include <linux/selinux.h>  #include <linux/netfilter_ipv4/ip_tables.h> diff --git a/net/netfilter/xt_LED.c b/net/netfilter/xt_LED.c index 8ff7843bb92..3271c8e5215 100644 --- a/net/netfilter/xt_LED.c +++ b/net/netfilter/xt_LED.c @@ -22,6 +22,7 @@  #include <linux/module.h>  #include <linux/skbuff.h>  #include <linux/netfilter/x_tables.h> +#include <linux/slab.h>  #include <linux/leds.h>  #include <linux/mutex.h> diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c index 87ae97e5516..d16d55df4f6 100644 --- a/net/netfilter/xt_RATEEST.c +++ b/net/netfilter/xt_RATEEST.c @@ -11,6 +11,7 @@  #include <linux/jhash.h>  #include <linux/rtnetlink.h>  #include <linux/random.h> +#include <linux/slab.h>  #include <net/gen_stats.h>  #include <net/netlink.h> diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 0e357ac9a2a..c5f4b9919e9 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -11,6 +11,7 @@  #include <linux/module.h>  #include <linux/skbuff.h>  #include <linux/ip.h> +#include <linux/gfp.h>  #include <linux/ipv6.h>  #include <linux/tcp.h>  #include <net/dst.h> diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c index 26997ce90e4..388ca459609 100644 --- a/net/netfilter/xt_connlimit.c +++ b/net/netfilter/xt_connlimit.c @@ -17,6 +17,7 @@  #include <linux/ip.h>  #include <linux/ipv6.h>  #include <linux/jhash.h> +#include <linux/slab.h>  #include <linux/list.h>  #include <linux/module.h>  #include <linux/random.h> diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c index 0989f29ade2..395af5943ff 100644 --- a/net/netfilter/xt_dccp.c +++ b/net/netfilter/xt_dccp.c @@ -10,6 +10,7 @@  #include <linux/module.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <linux/spinlock.h>  #include <net/ip.h>  #include <linux/dccp.h> diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index d952806b646..215a64835de 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -1,6 +1,6 @@  /*   *	xt_hashlimit - Netfilter module to limit the number of packets per time - *	seperately for each hashbucket (sourceip/sourceport/dstip/dstport) + *	separately for each hashbucket (sourceip/sourceport/dstip/dstport)   *   *	(C) 2003-2004 by Harald Welte <laforge@netfilter.org>   *	Copyright © CC Computer Consultants GmbH, 2007 - 2008 @@ -493,6 +493,7 @@ static void hashlimit_ipv6_mask(__be32 *i, unsigned int p)  	case 64 ... 95:  		i[2] = maskl(i[2], p - 64);  		i[3] = 0; +		break;  	case 96 ... 127:  		i[3] = maskl(i[3], p - 96);  		break; @@ -879,7 +880,8 @@ static void dl_seq_stop(struct seq_file *s, void *v)  	struct xt_hashlimit_htable *htable = s->private;  	unsigned int *bucket = (unsigned int *)v; -	kfree(bucket); +	if (!IS_ERR(bucket)) +		kfree(bucket);  	spin_unlock_bh(&htable->lock);  } diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c index a0ca5339af4..e5d7e1ffb1a 100644 --- a/net/netfilter/xt_limit.c +++ b/net/netfilter/xt_limit.c @@ -6,6 +6,7 @@   * published by the Free Software Foundation.   */ +#include <linux/slab.h>  #include <linux/module.h>  #include <linux/skbuff.h>  #include <linux/spinlock.h> diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c index 390b7d09fe5..2d5562498c4 100644 --- a/net/netfilter/xt_quota.c +++ b/net/netfilter/xt_quota.c @@ -4,6 +4,7 @@   * Sam Johnston <samj@samj.net>   */  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <linux/spinlock.h>  #include <linux/netfilter/x_tables.h> diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 7073dbb8100..834b736857c 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -27,6 +27,7 @@  #include <linux/bitops.h>  #include <linux/skbuff.h>  #include <linux/inet.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/netns/generic.h> @@ -267,7 +268,7 @@ recent_mt(const struct sk_buff *skb, const struct xt_match_param *par)  		for (i = 0; i < e->nstamps; i++) {  			if (info->seconds && time_after(time, e->stamps[i]))  				continue; -			if (info->hit_count && ++hits >= info->hit_count) { +			if (!info->hit_count || ++hits >= info->hit_count) {  				ret = !ret;  				break;  			} diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c index d8c0f8f1a78..937ce0633e9 100644 --- a/net/netfilter/xt_statistic.c +++ b/net/netfilter/xt_statistic.c @@ -12,6 +12,7 @@  #include <linux/spinlock.h>  #include <linux/skbuff.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <linux/netfilter/xt_statistic.h>  #include <linux/netfilter/x_tables.h> diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c index b4d77411131..96801ffd8af 100644 --- a/net/netfilter/xt_string.c +++ b/net/netfilter/xt_string.c @@ -7,6 +7,7 @@   * published by the Free Software Foundation.   */ +#include <linux/gfp.h>  #include <linux/init.h>  #include <linux/module.h>  #include <linux/kernel.h> diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index e639298bc9c..5f14c8462e3 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -33,6 +33,7 @@  #include <linux/string.h>  #include <linux/skbuff.h>  #include <linux/audit.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/netlink.h>  #include <net/genetlink.h> diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 0bfeaab88ef..d37b7f80fa3 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -35,6 +35,7 @@  #include <linux/spinlock.h>  #include <linux/string.h>  #include <linux/audit.h> +#include <linux/slab.h>  #include <net/netlabel.h>  #include <net/cipso_ipv4.h>  #include <asm/bug.h> @@ -50,9 +51,12 @@ struct netlbl_domhsh_tbl {  };  /* Domain hash table */ -/* XXX - updates should be so rare that having one spinlock for the entire - * hash table should be okay */ +/* updates should be so rare that having one spinlock for the entire hash table + * should be okay */  static DEFINE_SPINLOCK(netlbl_domhsh_lock); +#define netlbl_domhsh_rcu_deref(p) \ +	rcu_dereference_check(p, rcu_read_lock_held() || \ +				 lockdep_is_held(&netlbl_domhsh_lock))  static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL;  static struct netlbl_dom_map *netlbl_domhsh_def = NULL; @@ -106,7 +110,8 @@ static void netlbl_domhsh_free_entry(struct rcu_head *entry)   * Description:   * This is the hashing function for the domain hash table, it returns the   * correct bucket number for the domain.  The caller is responsibile for - * calling the rcu_read_[un]lock() functions. + * ensuring that the hash table is protected with either a RCU read lock or the + * hash table lock.   *   */  static u32 netlbl_domhsh_hash(const char *key) @@ -120,7 +125,7 @@ static u32 netlbl_domhsh_hash(const char *key)  	for (iter = 0, val = 0, len = strlen(key); iter < len; iter++)  		val = (val << 4 | (val >> (8 * sizeof(u32) - 4))) ^ key[iter]; -	return val & (rcu_dereference(netlbl_domhsh)->size - 1); +	return val & (netlbl_domhsh_rcu_deref(netlbl_domhsh)->size - 1);  }  /** @@ -130,7 +135,8 @@ static u32 netlbl_domhsh_hash(const char *key)   * Description:   * Searches the domain hash table and returns a pointer to the hash table   * entry if found, otherwise NULL is returned.  The caller is responsibile for - * the rcu hash table locks (i.e. the caller much call rcu_read_[un]lock()). + * ensuring that the hash table is protected with either a RCU read lock or the + * hash table lock.   *   */  static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) @@ -141,7 +147,7 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain)  	if (domain != NULL) {  		bkt = netlbl_domhsh_hash(domain); -		bkt_list = &rcu_dereference(netlbl_domhsh)->tbl[bkt]; +		bkt_list = &netlbl_domhsh_rcu_deref(netlbl_domhsh)->tbl[bkt];  		list_for_each_entry_rcu(iter, bkt_list, list)  			if (iter->valid && strcmp(iter->domain, domain) == 0)  				return iter; @@ -159,8 +165,8 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain)   * Searches the domain hash table and returns a pointer to the hash table   * entry if an exact match is found, if an exact match is not present in the   * hash table then the default entry is returned if valid otherwise NULL is - * returned.  The caller is responsibile for the rcu hash table locks - * (i.e. the caller much call rcu_read_[un]lock()). + * returned.  The caller is responsibile ensuring that the hash table is + * protected with either a RCU read lock or the hash table lock.   *   */  static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) @@ -169,7 +175,7 @@ static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain)  	entry = netlbl_domhsh_search(domain);  	if (entry == NULL) { -		entry = rcu_dereference(netlbl_domhsh_def); +		entry = netlbl_domhsh_rcu_deref(netlbl_domhsh_def);  		if (entry != NULL && !entry->valid)  			entry = NULL;  	} @@ -306,8 +312,11 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,  	struct netlbl_af6list *tmp6;  #endif /* IPv6 */ +	/* XXX - we can remove this RCU read lock as the spinlock protects the +	 *       entire function, but before we do we need to fixup the +	 *       netlbl_af[4,6]list RCU functions to do "the right thing" with +	 *       respect to rcu_dereference() when only a spinlock is held. */  	rcu_read_lock(); -  	spin_lock(&netlbl_domhsh_lock);  	if (entry->domain != NULL)  		entry_old = netlbl_domhsh_search(entry->domain); diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 6ce00205f34..1b83e0009d8 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -30,6 +30,7 @@  #include <linux/init.h>  #include <linux/types.h> +#include <linux/slab.h>  #include <linux/audit.h>  #include <linux/in.h>  #include <linux/in6.h> diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 8203623e65a..998e85e895d 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -34,6 +34,7 @@  #include <linux/skbuff.h>  #include <linux/in.h>  #include <linux/in6.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/netlink.h>  #include <net/genetlink.h> diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 852d9d7976b..a3d64aabe2f 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -43,6 +43,7 @@  #include <linux/notifier.h>  #include <linux/netdevice.h>  #include <linux/security.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/netlink.h>  #include <net/genetlink.h> @@ -114,6 +115,9 @@ struct netlbl_unlhsh_walk_arg {  /* updates should be so rare that having one spinlock for the entire   * hash table should be okay */  static DEFINE_SPINLOCK(netlbl_unlhsh_lock); +#define netlbl_unlhsh_rcu_deref(p) \ +	rcu_dereference_check(p, rcu_read_lock_held() || \ +				 lockdep_is_held(&netlbl_unlhsh_lock))  static struct netlbl_unlhsh_tbl *netlbl_unlhsh = NULL;  static struct netlbl_unlhsh_iface *netlbl_unlhsh_def = NULL; @@ -235,15 +239,13 @@ static void netlbl_unlhsh_free_iface(struct rcu_head *entry)   * Description:   * This is the hashing function for the unlabeled hash table, it returns the   * bucket number for the given device/interface.  The caller is responsible for - * calling the rcu_read_[un]lock() functions. + * ensuring that the hash table is protected with either a RCU read lock or + * the hash table lock.   *   */  static u32 netlbl_unlhsh_hash(int ifindex)  { -	/* this is taken _almost_ directly from -	 * security/selinux/netif.c:sel_netif_hasfn() as they do pretty much -	 * the same thing */ -	return ifindex & (rcu_dereference(netlbl_unlhsh)->size - 1); +	return ifindex & (netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->size - 1);  }  /** @@ -253,7 +255,8 @@ static u32 netlbl_unlhsh_hash(int ifindex)   * Description:   * Searches the unlabeled connection hash table and returns a pointer to the   * interface entry which matches @ifindex, otherwise NULL is returned.  The - * caller is responsible for calling the rcu_read_[un]lock() functions. + * caller is responsible for ensuring that the hash table is protected with + * either a RCU read lock or the hash table lock.   *   */  static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex) @@ -263,7 +266,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)  	struct netlbl_unlhsh_iface *iter;  	bkt = netlbl_unlhsh_hash(ifindex); -	bkt_list = &rcu_dereference(netlbl_unlhsh)->tbl[bkt]; +	bkt_list = &netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->tbl[bkt];  	list_for_each_entry_rcu(iter, bkt_list, list)  		if (iter->valid && iter->ifindex == ifindex)  			return iter; @@ -272,33 +275,6 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)  }  /** - * netlbl_unlhsh_search_iface_def - Search for a matching interface entry - * @ifindex: the network interface - * - * Description: - * Searches the unlabeled connection hash table and returns a pointer to the - * interface entry which matches @ifindex.  If an exact match can not be found - * and there is a valid default entry, the default entry is returned, otherwise - * NULL is returned.  The caller is responsible for calling the - * rcu_read_[un]lock() functions. - * - */ -static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface_def(int ifindex) -{ -	struct netlbl_unlhsh_iface *entry; - -	entry = netlbl_unlhsh_search_iface(ifindex); -	if (entry != NULL) -		return entry; - -	entry = rcu_dereference(netlbl_unlhsh_def); -	if (entry != NULL && entry->valid) -		return entry; - -	return NULL; -} - -/**   * netlbl_unlhsh_add_addr4 - Add a new IPv4 address entry to the hash table   * @iface: the associated interface entry   * @addr: IPv4 address in network byte order @@ -308,8 +284,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface_def(int ifindex)   * Description:   * Add a new address entry into the unlabeled connection hash table using the   * interface entry specified by @iface.  On success zero is returned, otherwise - * a negative value is returned.  The caller is responsible for calling the - * rcu_read_[un]lock() functions. + * a negative value is returned.   *   */  static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, @@ -349,8 +324,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,   * Description:   * Add a new address entry into the unlabeled connection hash table using the   * interface entry specified by @iface.  On success zero is returned, otherwise - * a negative value is returned.  The caller is responsible for calling the - * rcu_read_[un]lock() functions. + * a negative value is returned.   *   */  static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface, @@ -391,8 +365,7 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,   * Description:   * Add a new, empty, interface entry into the unlabeled connection hash table.   * On success a pointer to the new interface entry is returned, on failure NULL - * is returned.  The caller is responsible for calling the rcu_read_[un]lock() - * functions. + * is returned.   *   */  static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex) @@ -415,10 +388,10 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex)  		if (netlbl_unlhsh_search_iface(ifindex) != NULL)  			goto add_iface_failure;  		list_add_tail_rcu(&iface->list, -				  &rcu_dereference(netlbl_unlhsh)->tbl[bkt]); +			     &netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->tbl[bkt]);  	} else {  		INIT_LIST_HEAD(&iface->list); -		if (rcu_dereference(netlbl_unlhsh_def) != NULL) +		if (netlbl_unlhsh_rcu_deref(netlbl_unlhsh_def) != NULL)  			goto add_iface_failure;  		rcu_assign_pointer(netlbl_unlhsh_def, iface);  	} @@ -548,8 +521,7 @@ unlhsh_add_return:   *   * Description:   * Remove an IP address entry from the unlabeled connection hash table. - * Returns zero on success, negative values on failure.  The caller is - * responsible for calling the rcu_read_[un]lock() functions. + * Returns zero on success, negative values on failure.   *   */  static int netlbl_unlhsh_remove_addr4(struct net *net, @@ -611,8 +583,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,   *   * Description:   * Remove an IP address entry from the unlabeled connection hash table. - * Returns zero on success, negative values on failure.  The caller is - * responsible for calling the rcu_read_[un]lock() functions. + * Returns zero on success, negative values on failure.   *   */  static int netlbl_unlhsh_remove_addr6(struct net *net, @@ -1547,8 +1518,10 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb,  	struct netlbl_unlhsh_iface *iface;  	rcu_read_lock(); -	iface = netlbl_unlhsh_search_iface_def(skb->skb_iif); +	iface = netlbl_unlhsh_search_iface(skb->skb_iif);  	if (iface == NULL) +		iface = rcu_dereference(netlbl_unlhsh_def); +	if (iface == NULL || !iface->valid)  		goto unlabel_getattr_nolabel;  	switch (family) {  	case PF_INET: { diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c index 68706b4e3bf..a3fd75ac3fa 100644 --- a/net/netlabel/netlabel_user.c +++ b/net/netlabel/netlabel_user.c @@ -35,6 +35,7 @@  #include <linux/audit.h>  #include <linux/tty.h>  #include <linux/security.h> +#include <linux/gfp.h>  #include <net/sock.h>  #include <net/netlink.h>  #include <net/genetlink.h> diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 320d0423a24..795424396af 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -683,6 +683,9 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,  	struct netlink_sock *nlk = nlk_sk(sk);  	struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; +	if (alen < sizeof(addr->sa_family)) +		return -EINVAL; +  	if (addr->sa_family == AF_UNSPEC) {  		sk->sk_state	= NETLINK_UNCONNECTED;  		nlk->dst_pid	= 0; @@ -1093,6 +1096,7 @@ static inline int do_one_set_err(struct sock *sk,  				 struct netlink_set_err_data *p)  {  	struct netlink_sock *nlk = nlk_sk(sk); +	int ret = 0;  	if (sk == p->exclude_sk)  		goto out; @@ -1104,10 +1108,15 @@ static inline int do_one_set_err(struct sock *sk,  	    !test_bit(p->group - 1, nlk->groups))  		goto out; +	if (p->code == ENOBUFS && nlk->flags & NETLINK_RECV_NO_ENOBUFS) { +		ret = 1; +		goto out; +	} +  	sk->sk_err = p->code;  	sk->sk_error_report(sk);  out: -	return 0; +	return ret;  }  /** @@ -1116,12 +1125,16 @@ out:   * @pid: the PID of a process that we want to skip (if any)   * @groups: the broadcast group that will notice the error   * @code: error code, must be negative (as usual in kernelspace) + * + * This function returns the number of broadcast listeners that have set the + * NETLINK_RECV_NO_ENOBUFS socket option.   */ -void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) +int netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)  {  	struct netlink_set_err_data info;  	struct hlist_node *node;  	struct sock *sk; +	int ret = 0;  	info.exclude_sk = ssk;  	info.pid = pid; @@ -1132,9 +1145,10 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)  	read_lock(&nl_table_lock);  	sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) -		do_one_set_err(sk, &info); +		ret += do_one_set_err(sk, &info);  	read_unlock(&nl_table_lock); +	return ret;  }  EXPORT_SYMBOL(netlink_set_err); diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index a4b6e148c5d..06438fa2b1e 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -8,6 +8,7 @@  #include <linux/module.h>  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/errno.h>  #include <linux/types.h>  #include <linux/socket.h> diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index a249127020a..fa07f044b59 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -15,6 +15,7 @@  #include <linux/types.h>  #include <linux/socket.h>  #include <linux/in.h> +#include <linux/slab.h>  #include <linux/kernel.h>  #include <linux/sched.h>  #include <linux/timer.h> diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c index 7aa11b01b2e..64e6dde9749 100644 --- a/net/netrom/nr_dev.c +++ b/net/netrom/nr_dev.c @@ -19,6 +19,7 @@  #include <linux/fcntl.h>  #include <linux/in.h>  #include <linux/if_ether.h>	/* For the statistics structure. */ +#include <linux/slab.h>  #include <asm/system.h>  #include <asm/uaccess.h> diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c index 68176483617..6d4ef6d65b3 100644 --- a/net/netrom/nr_in.c +++ b/net/netrom/nr_in.c @@ -16,6 +16,7 @@  #include <linux/string.h>  #include <linux/sockios.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/netrom/nr_loopback.c b/net/netrom/nr_loopback.c index f324d5df418..94d4e922af5 100644 --- a/net/netrom/nr_loopback.c +++ b/net/netrom/nr_loopback.c @@ -7,6 +7,7 @@   * Copyright Tomi Manninen OH2BNS (oh2bns@sral.fi)   */  #include <linux/types.h> +#include <linux/slab.h>  #include <linux/socket.h>  #include <linux/timer.h>  #include <net/ax25.h> diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c index e3e6c44e189..607fddb4fdb 100644 --- a/net/netrom/nr_out.c +++ b/net/netrom/nr_out.c @@ -16,6 +16,7 @@  #include <linux/string.h>  #include <linux/sockios.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c index 5cc648012f5..44059d0c8dd 100644 --- a/net/netrom/nr_route.c +++ b/net/netrom/nr_route.c @@ -17,6 +17,7 @@  #include <linux/string.h>  #include <linux/sockios.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c index 04e7d0d2fd8..6a947ae50db 100644 --- a/net/netrom/nr_subr.c +++ b/net/netrom/nr_subr.c @@ -15,6 +15,7 @@  #include <linux/string.h>  #include <linux/sockios.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 031a5e6fb4a..243946d4809 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -60,6 +60,7 @@  #include <linux/wireless.h>  #include <linux/kernel.h>  #include <linux/kmod.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/ip.h>  #include <net/protocol.h> @@ -1688,6 +1689,8 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i,  {  	switch (i->type) {  	case PACKET_MR_MULTICAST: +		if (i->alen != dev->addr_len) +			return -EINVAL;  		if (what > 0)  			return dev_mc_add(dev, i->addr, i->alen, 0);  		else @@ -1700,6 +1703,8 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i,  		return dev_set_allmulti(dev, what);  		break;  	case PACKET_MR_UNICAST: +		if (i->alen != dev->addr_len) +			return -EINVAL;  		if (what > 0)  			return dev_unicast_add(dev, i->addr);  		else @@ -1734,7 +1739,7 @@ static int packet_mc_add(struct sock *sk, struct packet_mreq_max *mreq)  		goto done;  	err = -EINVAL; -	if (mreq->mr_alen != dev->addr_len) +	if (mreq->mr_alen > dev->addr_len)  		goto done;  	err = -ENOBUFS; @@ -2164,8 +2169,6 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd,  	case SIOCGIFDSTADDR:  	case SIOCSIFDSTADDR:  	case SIOCSIFFLAGS: -		if (!net_eq(sock_net(sk), &init_net)) -			return -ENOIOCTLCMD;  		return inet_dgram_ops.ioctl(sock, cmd, arg);  #endif diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 526d0273991..73aee7f2fcd 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -25,6 +25,7 @@  #include <linux/kernel.h>  #include <linux/module.h> +#include <linux/slab.h>  #include <asm/unaligned.h>  #include <net/sock.h> diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c index 387197b579b..1bd38db4fe1 100644 --- a/net/phonet/datagram.c +++ b/net/phonet/datagram.c @@ -24,6 +24,7 @@   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/socket.h>  #include <asm/ioctls.h>  #include <net/sock.h> diff --git a/net/phonet/pep.c b/net/phonet/pep.c index 360cf377693..e2a95762abd 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -23,6 +23,7 @@   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/socket.h>  #include <net/sock.h>  #include <net/tcp_states.h> diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index c597cc53a6f..9b4ced6e096 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -25,6 +25,7 @@  #include <linux/kernel.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <linux/netdevice.h>  #include <linux/phonet.h>  #include <linux/proc_fs.h> @@ -107,8 +108,7 @@ static void phonet_device_destroy(struct net_device *dev)  	if (pnd) {  		u8 addr; -		for (addr = find_first_bit(pnd->addrs, 64); addr < 64; -			addr = find_next_bit(pnd->addrs, 64, 1+addr)) +		for_each_set_bit(addr, pnd->addrs, 64)  			phonet_address_notify(RTM_DELADDR, dev, addr);  		kfree(pnd);  	} diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c index 2e6c7eb8e76..58b3b1f991e 100644 --- a/net/phonet/pn_netlink.c +++ b/net/phonet/pn_netlink.c @@ -26,6 +26,7 @@  #include <linux/kernel.h>  #include <linux/netlink.h>  #include <linux/phonet.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/phonet/pn_dev.h> @@ -141,8 +142,7 @@ static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)  			continue;  		addr_idx = 0; -		for (addr = find_first_bit(pnd->addrs, 64); addr < 64; -			addr = find_next_bit(pnd->addrs, 64, 1+addr)) { +		for_each_set_bit(addr, pnd->addrs, 64) {  			if (addr_idx++ < addr_start_idx)  				continue; diff --git a/net/phonet/socket.c b/net/phonet/socket.c index 69c8b826a0c..c785bfd0744 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c @@ -23,6 +23,7 @@   * 02110-1301 USA   */ +#include <linux/gfp.h>  #include <linux/kernel.h>  #include <linux/net.h>  #include <linux/poll.h> diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c index 853c52be781..f81862baf4d 100644 --- a/net/rds/af_rds.c +++ b/net/rds/af_rds.c @@ -33,6 +33,7 @@  #include <linux/module.h>  #include <linux/errno.h>  #include <linux/kernel.h> +#include <linux/gfp.h>  #include <linux/in.h>  #include <linux/poll.h>  #include <net/sock.h> diff --git a/net/rds/cong.c b/net/rds/cong.c index 6d06cac2649..f1da27ceb06 100644 --- a/net/rds/cong.c +++ b/net/rds/cong.c @@ -30,6 +30,7 @@   * SOFTWARE.   *   */ +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/rbtree.h> diff --git a/net/rds/connection.c b/net/rds/connection.c index 278f607ab60..7619b671ca2 100644 --- a/net/rds/connection.c +++ b/net/rds/connection.c @@ -32,6 +32,7 @@   */  #include <linux/kernel.h>  #include <linux/list.h> +#include <linux/slab.h>  #include <net/inet_hashtables.h>  #include "rds.h" diff --git a/net/rds/ib.c b/net/rds/ib.c index 3b899236104..8f2d6dd7700 100644 --- a/net/rds/ib.c +++ b/net/rds/ib.c @@ -37,6 +37,7 @@  #include <linux/inetdevice.h>  #include <linux/if_arp.h>  #include <linux/delay.h> +#include <linux/slab.h>  #include "rds.h"  #include "ib.h" diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index 647cb8ffc39..88d0856cb79 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c @@ -32,6 +32,7 @@   */  #include <linux/kernel.h>  #include <linux/in.h> +#include <linux/slab.h>  #include <linux/vmalloc.h>  #include "rds.h" diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c index 4b0da865a72..059989fdb7d 100644 --- a/net/rds/ib_rdma.c +++ b/net/rds/ib_rdma.c @@ -31,6 +31,7 @@   *   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include "rds.h"  #include "rdma.h" diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c index 04dc0d3f3c9..c7dd11b835f 100644 --- a/net/rds/ib_recv.c +++ b/net/rds/ib_recv.c @@ -31,6 +31,7 @@   *   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/pci.h>  #include <linux/dma-mapping.h>  #include <rdma/rdma_cm.h> diff --git a/net/rds/info.c b/net/rds/info.c index 814a91a6f4a..c45c4173a44 100644 --- a/net/rds/info.c +++ b/net/rds/info.c @@ -32,6 +32,7 @@   */  #include <linux/percpu.h>  #include <linux/seq_file.h> +#include <linux/slab.h>  #include <linux/proc_fs.h>  #include "rds.h" diff --git a/net/rds/iw.c b/net/rds/iw.c index b28fa8525b2..c8f3d3525cb 100644 --- a/net/rds/iw.c +++ b/net/rds/iw.c @@ -37,6 +37,7 @@  #include <linux/inetdevice.h>  #include <linux/if_arp.h>  #include <linux/delay.h> +#include <linux/slab.h>  #include "rds.h"  #include "iw.h" diff --git a/net/rds/iw_cm.c b/net/rds/iw_cm.c index 394cf6b4d0a..3e9460f935d 100644 --- a/net/rds/iw_cm.c +++ b/net/rds/iw_cm.c @@ -32,6 +32,7 @@   */  #include <linux/kernel.h>  #include <linux/in.h> +#include <linux/slab.h>  #include <linux/vmalloc.h>  #include "rds.h" diff --git a/net/rds/iw_rdma.c b/net/rds/iw_rdma.c index 9eda11cca95..13dc1862d86 100644 --- a/net/rds/iw_rdma.c +++ b/net/rds/iw_rdma.c @@ -31,6 +31,7 @@   *   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include "rds.h"  #include "rdma.h" diff --git a/net/rds/iw_recv.c b/net/rds/iw_recv.c index 54af7d6b92d..da43ee840ca 100644 --- a/net/rds/iw_recv.c +++ b/net/rds/iw_recv.c @@ -31,6 +31,7 @@   *   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/pci.h>  #include <linux/dma-mapping.h>  #include <rdma/rdma_cm.h> diff --git a/net/rds/loop.c b/net/rds/loop.c index 4a61997f554..0d7a159158b 100644 --- a/net/rds/loop.c +++ b/net/rds/loop.c @@ -31,6 +31,7 @@   *   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/in.h>  #include "rds.h" diff --git a/net/rds/message.c b/net/rds/message.c index 73e600ffd87..9a1d67e001b 100644 --- a/net/rds/message.c +++ b/net/rds/message.c @@ -31,6 +31,7 @@   *   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include "rds.h"  #include "rdma.h" diff --git a/net/rds/page.c b/net/rds/page.c index 36790122dfd..595a952d4b1 100644 --- a/net/rds/page.c +++ b/net/rds/page.c @@ -31,6 +31,7 @@   *   */  #include <linux/highmem.h> +#include <linux/gfp.h>  #include "rds.h" diff --git a/net/rds/rdma.c b/net/rds/rdma.c index 4c64daa1f5d..5ce9437cad6 100644 --- a/net/rds/rdma.c +++ b/net/rds/rdma.c @@ -31,6 +31,7 @@   *   */  #include <linux/pagemap.h> +#include <linux/slab.h>  #include <linux/rbtree.h>  #include <linux/dma-mapping.h> /* for DMA_*_DEVICE */ diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c index 9ece910ea39..7b155081b4d 100644 --- a/net/rds/rdma_transport.c +++ b/net/rds/rdma_transport.c @@ -134,7 +134,7 @@ static int __init rds_rdma_listen_init(void)  		ret = PTR_ERR(cm_id);  		printk(KERN_ERR "RDS/RDMA: failed to setup listener, "  		       "rdma_create_id() returned %d\n", ret); -		goto out; +		return ret;  	}  	sin.sin_family = AF_INET, diff --git a/net/rds/recv.c b/net/rds/recv.c index b426d67f760..e2a2b9344f7 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c @@ -31,6 +31,7 @@   *   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <linux/in.h> diff --git a/net/rds/send.c b/net/rds/send.c index b2fccfc2076..f04b929ded9 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -31,6 +31,7 @@   *   */  #include <linux/kernel.h> +#include <linux/gfp.h>  #include <net/sock.h>  #include <linux/in.h>  #include <linux/list.h> diff --git a/net/rds/tcp.c b/net/rds/tcp.c index b5198aee45d..babf4577ff7 100644 --- a/net/rds/tcp.c +++ b/net/rds/tcp.c @@ -31,6 +31,7 @@   *   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/in.h>  #include <net/tcp.h> diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c index 53cb1b54165..975183fe695 100644 --- a/net/rds/tcp_listen.c +++ b/net/rds/tcp_listen.c @@ -31,6 +31,7 @@   *   */  #include <linux/kernel.h> +#include <linux/gfp.h>  #include <linux/in.h>  #include <net/tcp.h> diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c index c00dafffbb5..e08ec912d8b 100644 --- a/net/rds/tcp_recv.c +++ b/net/rds/tcp_recv.c @@ -31,6 +31,7 @@   *   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <net/tcp.h>  #include "rds.h" diff --git a/net/rfkill/core.c b/net/rfkill/core.c index c218e07e5ca..a9fa86f6598 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -33,6 +33,7 @@  #include <linux/wait.h>  #include <linux/poll.h>  #include <linux/fs.h> +#include <linux/slab.h>  #include "rfkill.h" diff --git a/net/rfkill/input.c b/net/rfkill/input.c index a7295ad5f9c..3713d7ecab9 100644 --- a/net/rfkill/input.c +++ b/net/rfkill/input.c @@ -212,6 +212,9 @@ static void rfkill_event(struct input_handle *handle, unsigned int type,  		case KEY_WIMAX:  			rfkill_schedule_toggle(RFKILL_TYPE_WIMAX);  			break; +		case KEY_RFKILL: +			rfkill_schedule_toggle(RFKILL_TYPE_ALL); +			break;  		}  	} else if (type == EV_SW && code == SW_RFKILL_ALL)  		rfkill_schedule_evsw_rfkillall(data); @@ -295,6 +298,11 @@ static const struct input_device_id rfkill_ids[] = {  		.keybit = { [BIT_WORD(KEY_WIMAX)] = BIT_MASK(KEY_WIMAX) },  	},  	{ +		.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, +		.evbit = { BIT_MASK(EV_KEY) }, +		.keybit = { [BIT_WORD(KEY_RFKILL)] = BIT_MASK(KEY_RFKILL) }, +	}, +	{  		.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_SWBIT,  		.evbit = { BIT(EV_SW) },  		.swbit = { [BIT_WORD(SW_RFKILL_ALL)] = BIT_MASK(SW_RFKILL_ALL) }, diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index e90b9b6c16a..4fb711a035f 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -18,6 +18,7 @@  #include <linux/types.h>  #include <linux/socket.h>  #include <linux/in.h> +#include <linux/slab.h>  #include <linux/kernel.h>  #include <linux/sched.h>  #include <linux/spinlock.h> diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index 424b893d145..178ff4f73c8 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c @@ -19,6 +19,7 @@  #include <linux/fcntl.h>  #include <linux/in.h>  #include <linux/if_ether.h> +#include <linux/slab.h>  #include <asm/system.h>  #include <asm/io.h> diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c index 5ef5f6988a2..a750a28e022 100644 --- a/net/rose/rose_link.c +++ b/net/rose/rose_link.c @@ -16,6 +16,7 @@  #include <linux/string.h>  #include <linux/sockios.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.c index 968e8bac1b5..ae4a9d99aec 100644 --- a/net/rose/rose_loopback.c +++ b/net/rose/rose_loopback.c @@ -7,6 +7,7 @@   * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)   */  #include <linux/types.h> +#include <linux/slab.h>  #include <linux/socket.h>  #include <linux/timer.h>  #include <net/ax25.h> diff --git a/net/rose/rose_out.c b/net/rose/rose_out.c index 69820f93414..4ebf33afbe4 100644 --- a/net/rose/rose_out.c +++ b/net/rose/rose_out.c @@ -15,6 +15,7 @@  #include <linux/string.h>  #include <linux/sockios.h>  #include <linux/net.h> +#include <linux/gfp.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 70a0b3b4b4d..cbc244a128b 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -16,6 +16,7 @@  #include <linux/string.h>  #include <linux/sockios.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index b05108f382d..1734abba26a 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c @@ -15,6 +15,7 @@  #include <linux/string.h>  #include <linux/sockios.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <net/ax25.h>  #include <linux/inet.h>  #include <linux/netdevice.h> diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 287b1415cee..c060095b27c 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -11,6 +11,7 @@  #include <linux/module.h>  #include <linux/net.h> +#include <linux/slab.h>  #include <linux/skbuff.h>  #include <linux/poll.h>  #include <linux/proc_fs.h> diff --git a/net/rxrpc/ar-accept.c b/net/rxrpc/ar-accept.c index 77228f28fa3..6d79310fcaa 100644 --- a/net/rxrpc/ar-accept.c +++ b/net/rxrpc/ar-accept.c @@ -17,6 +17,7 @@  #include <linux/in.h>  #include <linux/in6.h>  #include <linux/icmp.h> +#include <linux/gfp.h>  #include <net/sock.h>  #include <net/af_rxrpc.h>  #include <net/ip.h> @@ -88,6 +89,11 @@ static int rxrpc_accept_incoming_call(struct rxrpc_local *local,  	/* get a notification message to send to the server app */  	notification = alloc_skb(0, GFP_NOFS); +	if (!notification) { +		_debug("no memory"); +		ret = -ENOMEM; +		goto error_nofree; +	}  	rxrpc_new_skb(notification);  	notification->mark = RXRPC_SKB_MARK_NEW_CALL; @@ -189,6 +195,7 @@ invalid_service:  	ret = -ECONNREFUSED;  error:  	rxrpc_free_skb(notification); +error_nofree:  	_leave(" = %d", ret);  	return ret;  } diff --git a/net/rxrpc/ar-ack.c b/net/rxrpc/ar-ack.c index b4a22097703..2714da167fb 100644 --- a/net/rxrpc/ar-ack.c +++ b/net/rxrpc/ar-ack.c @@ -13,6 +13,7 @@  #include <linux/circ_buf.h>  #include <linux/net.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <linux/udp.h>  #include <net/sock.h>  #include <net/af_rxrpc.h> diff --git a/net/rxrpc/ar-call.c b/net/rxrpc/ar-call.c index bc0019f704f..909d092de9f 100644 --- a/net/rxrpc/ar-call.c +++ b/net/rxrpc/ar-call.c @@ -9,6 +9,7 @@   * 2 of the License, or (at your option) any later version.   */ +#include <linux/slab.h>  #include <linux/module.h>  #include <linux/circ_buf.h>  #include <net/sock.h> diff --git a/net/rxrpc/ar-connection.c b/net/rxrpc/ar-connection.c index 9f1ce841a0b..4106ca95ec8 100644 --- a/net/rxrpc/ar-connection.c +++ b/net/rxrpc/ar-connection.c @@ -10,6 +10,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/net.h>  #include <linux/skbuff.h>  #include <linux/crypto.h> diff --git a/net/rxrpc/ar-input.c b/net/rxrpc/ar-input.c index f98c8027e5c..89315009bab 100644 --- a/net/rxrpc/ar-input.c +++ b/net/rxrpc/ar-input.c @@ -17,6 +17,7 @@  #include <linux/in.h>  #include <linux/in6.h>  #include <linux/icmp.h> +#include <linux/gfp.h>  #include <net/sock.h>  #include <net/af_rxrpc.h>  #include <net/ip.h> diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 74697b20049..5ee16f0353f 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c @@ -18,6 +18,7 @@  #include <linux/key-type.h>  #include <linux/crypto.h>  #include <linux/ctype.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/af_rxrpc.h>  #include <keys/rxrpc-type.h> diff --git a/net/rxrpc/ar-local.c b/net/rxrpc/ar-local.c index 807535ff29b..87f7135d238 100644 --- a/net/rxrpc/ar-local.c +++ b/net/rxrpc/ar-local.c @@ -12,6 +12,7 @@  #include <linux/module.h>  #include <linux/net.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/af_rxrpc.h>  #include "ar-internal.h" diff --git a/net/rxrpc/ar-output.c b/net/rxrpc/ar-output.c index cc9102c5b58..5f22e263eda 100644 --- a/net/rxrpc/ar-output.c +++ b/net/rxrpc/ar-output.c @@ -10,6 +10,7 @@   */  #include <linux/net.h> +#include <linux/gfp.h>  #include <linux/skbuff.h>  #include <linux/circ_buf.h>  #include <net/sock.h> diff --git a/net/rxrpc/ar-peer.c b/net/rxrpc/ar-peer.c index edc026c1eb7..f0f85b0123f 100644 --- a/net/rxrpc/ar-peer.c +++ b/net/rxrpc/ar-peer.c @@ -16,6 +16,7 @@  #include <linux/in.h>  #include <linux/in6.h>  #include <linux/icmp.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/af_rxrpc.h>  #include <net/ip.h> diff --git a/net/rxrpc/ar-transport.c b/net/rxrpc/ar-transport.c index 0936e1acc30..5e0226fe587 100644 --- a/net/rxrpc/ar-transport.c +++ b/net/rxrpc/ar-transport.c @@ -12,6 +12,7 @@  #include <linux/module.h>  #include <linux/net.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/af_rxrpc.h>  #include "ar-internal.h" diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index 713ac593e2e..7635107726c 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c @@ -16,6 +16,7 @@  #include <linux/crypto.h>  #include <linux/scatterlist.h>  #include <linux/ctype.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/af_rxrpc.h>  #include <keys/rxrpc-type.h> diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 21f9c7678aa..2f691fb180d 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -328,13 +328,16 @@ config NET_CLS_FLOW  	  module will be called cls_flow.  config NET_CLS_CGROUP -	bool "Control Group Classifier" +	tristate "Control Group Classifier"  	select NET_CLS  	depends on CGROUPS  	---help---  	  Say Y here if you want to classify packets based on the control  	  cgroup of their process. +	  To compile this code as a module, choose M here: the +	  module will be called cls_cgroup. +  config NET_EMATCH  	bool "Extended Matches"  	select NET_CLS diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 64f5e328cee..d8e0171d9a4 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -15,6 +15,7 @@  #include <linux/kernel.h>  #include <linux/string.h>  #include <linux/errno.h> +#include <linux/slab.h>  #include <linux/skbuff.h>  #include <linux/init.h>  #include <linux/kmod.h> diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 082c520b0de..da27a170b6b 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -19,6 +19,7 @@  #include <linux/rtnetlink.h>  #include <linux/module.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <net/netlink.h>  #include <net/pkt_sched.h>  #include <linux/tc_act/tc_ipt.h> diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index d329170243c..c046682054e 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c @@ -20,6 +20,7 @@  #include <linux/rtnetlink.h>  #include <linux/module.h>  #include <linux/init.h> +#include <linux/gfp.h>  #include <net/net_namespace.h>  #include <net/netlink.h>  #include <net/pkt_sched.h> diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 6b0359a500e..b7dcfedc802 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -17,6 +17,7 @@  #include <linux/rtnetlink.h>  #include <linux/module.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <net/netlink.h>  #include <net/pkt_sched.h>  #include <linux/tc_act/tc_pedit.h> diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 723964c3ee4..654f73dff7c 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c @@ -18,6 +18,7 @@  #include <linux/skbuff.h>  #include <linux/rtnetlink.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <net/act_api.h>  #include <net/netlink.h> diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index 8daa1ebc741..622ca809c15 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c @@ -11,6 +11,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/init.h>  #include <linux/kernel.h>  #include <linux/skbuff.h> diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 3725d8fa29d..f082b27ff46 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -24,6 +24,7 @@  #include <linux/kmod.h>  #include <linux/netlink.h>  #include <linux/err.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/sock.h>  #include <net/netlink.h> diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index 4e2bda85411..efd4f95fd05 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c @@ -10,6 +10,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/kernel.h>  #include <linux/string.h> diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c index e4877ca6727..221180384fd 100644 --- a/net/sched/cls_cgroup.c +++ b/net/sched/cls_cgroup.c @@ -10,6 +10,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/string.h>  #include <linux/errno.h> @@ -24,6 +25,25 @@ struct cgroup_cls_state  	u32 classid;  }; +static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss, +					       struct cgroup *cgrp); +static void cgrp_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp); +static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp); + +struct cgroup_subsys net_cls_subsys = { +	.name		= "net_cls", +	.create		= cgrp_create, +	.destroy	= cgrp_destroy, +	.populate	= cgrp_populate, +#ifdef CONFIG_NET_CLS_CGROUP +	.subsys_id	= net_cls_subsys_id, +#else +#define net_cls_subsys_id net_cls_subsys.subsys_id +#endif +	.module		= THIS_MODULE, +}; + +  static inline struct cgroup_cls_state *cgrp_cls_state(struct cgroup *cgrp)  {  	return container_of(cgroup_subsys_state(cgrp, net_cls_subsys_id), @@ -79,14 +99,6 @@ static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp)  	return cgroup_add_files(cgrp, ss, ss_files, ARRAY_SIZE(ss_files));  } -struct cgroup_subsys net_cls_subsys = { -	.name		= "net_cls", -	.create		= cgrp_create, -	.destroy	= cgrp_destroy, -	.populate	= cgrp_populate, -	.subsys_id	= net_cls_subsys_id, -}; -  struct cls_cgroup_head  {  	u32			handle; @@ -277,12 +289,19 @@ static struct tcf_proto_ops cls_cgroup_ops __read_mostly = {  static int __init init_cgroup_cls(void)  { -	return register_tcf_proto_ops(&cls_cgroup_ops); +	int ret = register_tcf_proto_ops(&cls_cgroup_ops); +	if (ret) +		return ret; +	ret = cgroup_load_subsys(&net_cls_subsys); +	if (ret) +		unregister_tcf_proto_ops(&cls_cgroup_ops); +	return ret;  }  static void __exit exit_cgroup_cls(void)  {  	unregister_tcf_proto_ops(&cls_cgroup_ops); +	cgroup_unload_subsys(&net_cls_subsys);  }  module_init(init_cgroup_cls); diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index e054c62857e..6ed61b10e00 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c @@ -20,6 +20,7 @@  #include <linux/ip.h>  #include <linux/ipv6.h>  #include <linux/if_vlan.h> +#include <linux/slab.h>  #include <net/pkt_cls.h>  #include <net/ip.h> diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index 6d6e87585fb..93b0a7b6f9b 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c @@ -19,6 +19,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/kernel.h>  #include <linux/string.h> diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index dd872d5383e..694dcd85dec 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c @@ -10,6 +10,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/kernel.h>  #include <linux/string.h> diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index e806f2314b5..20ef330bb91 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -9,6 +9,7 @@  #include <linux/kernel.h>  #include <linux/skbuff.h>  #include <linux/errno.h> +#include <linux/slab.h>  #include <net/act_api.h>  #include <net/netlink.h>  #include <net/pkt_cls.h> diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 07372f60bee..17c5dfc6732 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -31,6 +31,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/kernel.h>  #include <linux/string.h> diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index 24dce8b648a..3bcac8aa333 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c @@ -58,6 +58,7 @@   * 	      only available if that subsystem is enabled in the kernel.   */ +#include <linux/slab.h>  #include <linux/module.h>  #include <linux/types.h>  #include <linux/kernel.h> diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c index 370a1b2ea31..1a4176aee6e 100644 --- a/net/sched/em_nbyte.c +++ b/net/sched/em_nbyte.c @@ -9,6 +9,7 @@   * Authors:	Thomas Graf <tgraf@suug.ch>   */ +#include <linux/gfp.h>  #include <linux/module.h>  #include <linux/types.h>  #include <linux/kernel.h> diff --git a/net/sched/em_text.c b/net/sched/em_text.c index 853c5ead87f..76325325741 100644 --- a/net/sched/em_text.c +++ b/net/sched/em_text.c @@ -9,6 +9,7 @@   * Authors:	Thomas Graf <tgraf@suug.ch>   */ +#include <linux/slab.h>  #include <linux/module.h>  #include <linux/types.h>  #include <linux/kernel.h> diff --git a/net/sched/ematch.c b/net/sched/ematch.c index aab59409728..e782bdeedc5 100644 --- a/net/sched/ematch.c +++ b/net/sched/ematch.c @@ -82,6 +82,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/kernel.h>  #include <linux/errno.h> diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 6cd491013b5..145268ca57c 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -28,6 +28,7 @@  #include <linux/list.h>  #include <linux/hrtimer.h>  #include <linux/lockdep.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/sock.h> diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index ab82f145f68..fcbb86a486a 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -3,6 +3,7 @@  /* Written 1998-2000 by Werner Almesberger, EPFL ICA */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/init.h>  #include <linux/string.h>  #include <linux/errno.h> diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 3846d65bc03..28c01ef5abc 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -11,6 +11,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/kernel.h>  #include <linux/string.h> diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index a65604f8f2b..b74046a9539 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c @@ -9,6 +9,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/init.h>  #include <linux/errno.h>  #include <linux/netdevice.h> diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index d303daa45d4..63d41f86679 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -5,6 +5,7 @@  #include <linux/module.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/string.h>  #include <linux/errno.h> diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c index 4b0a6cc44c7..5948bafa8ce 100644 --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c @@ -10,6 +10,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/kernel.h>  #include <linux/errno.h> diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 5173c1e1b19..ff4dd53eeff 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -24,6 +24,7 @@  #include <linux/init.h>  #include <linux/rcupdate.h>  #include <linux/list.h> +#include <linux/slab.h>  #include <net/pkt_sched.h>  /* Main transmission queue. */ diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 40408d595c0..51dcc2aa5c9 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -18,6 +18,7 @@   *  For all the glorious comments look at include/net/red.h   */ +#include <linux/slab.h>  #include <linux/module.h>  #include <linux/types.h>  #include <linux/kernel.h> diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 508cf5f3a6d..0b52b8de562 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -36,6 +36,7 @@  #include <linux/compiler.h>  #include <linux/rbtree.h>  #include <linux/workqueue.h> +#include <linux/slab.h>  #include <net/netlink.h>  #include <net/pkt_sched.h> diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c index d1dea3d5dc9..b2aba3f5e6f 100644 --- a/net/sched/sch_mq.c +++ b/net/sched/sch_mq.c @@ -9,6 +9,7 @@   */  #include <linux/types.h> +#include <linux/slab.h>  #include <linux/kernel.h>  #include <linux/string.h>  #include <linux/errno.h> diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c index 7db2c88ce58..c50876cd870 100644 --- a/net/sched/sch_multiq.c +++ b/net/sched/sch_multiq.c @@ -18,6 +18,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/kernel.h>  #include <linux/string.h> diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index d8b10e05462..4714ff162bb 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -14,6 +14,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/kernel.h>  #include <linux/errno.h> diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index 93285cecb24..81672e0c1b2 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -12,6 +12,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/kernel.h>  #include <linux/string.h> diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index cb21380c060..c5a9ac56600 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -20,6 +20,7 @@  #include <linux/ipv6.h>  #include <linux/skbuff.h>  #include <linux/jhash.h> +#include <linux/slab.h>  #include <net/ip.h>  #include <net/netlink.h>  #include <net/pkt_sched.h> diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index db69637069c..3415b6ce1c0 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -11,6 +11,7 @@  #include <linux/module.h>  #include <linux/types.h>  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/string.h>  #include <linux/errno.h>  #include <linux/if_arp.h> diff --git a/net/sctp/associola.c b/net/sctp/associola.c index df5abbff63e..99c93ee98ad 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1194,8 +1194,10 @@ void sctp_assoc_update(struct sctp_association *asoc,  	/* Remove any peer addresses not present in the new association. */  	list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {  		trans = list_entry(pos, struct sctp_transport, transports); -		if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr)) -			sctp_assoc_del_peer(asoc, &trans->ipaddr); +		if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr)) { +			sctp_assoc_rm_peer(asoc, trans); +			continue; +		}  		if (asoc->state >= SCTP_STATE_ESTABLISHED)  			sctp_transport_reset(trans); diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 56935bbc149..86366390038 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -34,6 +34,7 @@   * be incorporated into the next SCTP release.   */ +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/crypto.h>  #include <linux/scatterlist.h> diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index bef13373168..faf71d179e4 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -43,6 +43,7 @@   */  #include <linux/types.h> +#include <linux/slab.h>  #include <linux/in.h>  #include <net/sock.h>  #include <net/ipv6.h> diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 8e4320040f0..3eab6db59a3 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c @@ -42,6 +42,7 @@  #include <linux/net.h>  #include <linux/inet.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/sctp/sctp.h>  #include <net/sctp/sm.h> diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 905fda582b9..7ec09ba03a1 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -144,6 +144,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,  	/* Use SCTP specific send buffer space queues.  */  	ep->sndbuf_policy = sctp_sndbuf_policy; +	sk->sk_data_ready = sctp_data_ready;  	sk->sk_write_space = sctp_write_space;  	sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); diff --git a/net/sctp/input.c b/net/sctp/input.c index c0c973e67ad..ea2192444ce 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -53,6 +53,7 @@  #include <linux/socket.h>  #include <linux/ip.h>  #include <linux/time.h> /* For struct timeval */ +#include <linux/slab.h>  #include <net/ip.h>  #include <net/icmp.h>  #include <net/snmp.h> @@ -75,7 +76,7 @@ static struct sctp_association *__sctp_lookup_association(  					const union sctp_addr *peer,  					struct sctp_transport **pt); -static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb); +static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb);  /* Calculate the SCTP checksum of an SCTP packet.  */ @@ -265,8 +266,13 @@ int sctp_rcv(struct sk_buff *skb)  	}  	if (sock_owned_by_user(sk)) { +		if (sctp_add_backlog(sk, skb)) { +			sctp_bh_unlock_sock(sk); +			sctp_chunk_free(chunk); +			skb = NULL; /* sctp_chunk_free already freed the skb */ +			goto discard_release; +		}  		SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG); -		sctp_add_backlog(sk, skb);  	} else {  		SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_SOFTIRQ);  		sctp_inq_push(&chunk->rcvr->inqueue, chunk); @@ -336,8 +342,10 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)  		sctp_bh_lock_sock(sk);  		if (sock_owned_by_user(sk)) { -			sk_add_backlog(sk, skb); -			backloged = 1; +			if (sk_add_backlog(sk, skb)) +				sctp_chunk_free(chunk); +			else +				backloged = 1;  		} else  			sctp_inq_push(inqueue, chunk); @@ -362,22 +370,27 @@ done:  	return 0;  } -static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb) +static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)  {  	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;  	struct sctp_ep_common *rcvr = chunk->rcvr; +	int ret; -	/* Hold the assoc/ep while hanging on the backlog queue. -	 * This way, we know structures we need will not disappear from us -	 */ -	if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type) -		sctp_association_hold(sctp_assoc(rcvr)); -	else if (SCTP_EP_TYPE_SOCKET == rcvr->type) -		sctp_endpoint_hold(sctp_ep(rcvr)); -	else -		BUG(); +	ret = sk_add_backlog(sk, skb); +	if (!ret) { +		/* Hold the assoc/ep while hanging on the backlog queue. +		 * This way, we know structures we need will not disappear +		 * from us +		 */ +		if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type) +			sctp_association_hold(sctp_assoc(rcvr)); +		else if (SCTP_EP_TYPE_SOCKET == rcvr->type) +			sctp_endpoint_hold(sctp_ep(rcvr)); +		else +			BUG(); +	} +	return ret; -	sk_add_backlog(sk, skb);  }  /* Handle icmp frag needed error. */ @@ -427,11 +440,25 @@ void sctp_icmp_proto_unreachable(struct sock *sk,  {  	SCTP_DEBUG_PRINTK("%s\n",  __func__); -	sctp_do_sm(SCTP_EVENT_T_OTHER, -		   SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), -		   asoc->state, asoc->ep, asoc, t, -		   GFP_ATOMIC); +	if (sock_owned_by_user(sk)) { +		if (timer_pending(&t->proto_unreach_timer)) +			return; +		else { +			if (!mod_timer(&t->proto_unreach_timer, +						jiffies + (HZ/20))) +				sctp_association_hold(asoc); +		} +			 +	} else { +		if (timer_pending(&t->proto_unreach_timer) && +		    del_timer(&t->proto_unreach_timer)) +			sctp_association_put(asoc); +		sctp_do_sm(SCTP_EVENT_T_OTHER, +			   SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), +			   asoc->state, asoc->ep, asoc, t, +			   GFP_ATOMIC); +	}  }  /* Common lookup code for icmp/icmpv6 error handler. */ diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c index bbf5dd2a97c..ccb6dc48d15 100644 --- a/net/sctp/inqueue.c +++ b/net/sctp/inqueue.c @@ -46,6 +46,7 @@  #include <net/sctp/sctp.h>  #include <net/sctp/sm.h>  #include <linux/interrupt.h> +#include <linux/slab.h>  /* Initialize an SCTP inqueue.  */  void sctp_inq_init(struct sctp_inq *queue) diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 1d7ac70ba39..9fb5d37c37a 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -58,6 +58,7 @@  #include <linux/netdevice.h>  #include <linux/init.h>  #include <linux/ipsec.h> +#include <linux/slab.h>  #include <linux/ipv6.h>  #include <linux/icmpv6.h> diff --git a/net/sctp/output.c b/net/sctp/output.c index 7c558936343..fad261d41ec 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -48,6 +48,7 @@  #include <linux/ip.h>  #include <linux/ipv6.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <net/inet_ecn.h>  #include <net/ip.h>  #include <net/icmp.h> diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 229690f02a1..abfc0b8dee7 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -50,6 +50,7 @@  #include <linux/list.h>   /* For struct list_head */  #include <linux/socket.h>  #include <linux/ip.h> +#include <linux/slab.h>  #include <net/sock.h>	  /* For skb_set_owner_w */  #include <net/sctp/sctp.h> diff --git a/net/sctp/primitive.c b/net/sctp/primitive.c index 8cb4f060bce..534c7eae9d1 100644 --- a/net/sctp/primitive.c +++ b/net/sctp/primitive.c @@ -50,6 +50,7 @@  #include <linux/socket.h>  #include <linux/ip.h>  #include <linux/time.h> /* For struct timeval */ +#include <linux/gfp.h>  #include <net/sock.h>  #include <net/sctp/sctp.h>  #include <net/sctp/sm.h> diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index e771690f6d5..a56f98e82f9 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -54,6 +54,7 @@  #include <linux/bootmem.h>  #include <linux/highmem.h>  #include <linux/swap.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/protocol.h>  #include <net/ip.h> diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 9e732916b67..30c1767186b 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -58,6 +58,7 @@  #include <linux/inet.h>  #include <linux/scatterlist.h>  #include <linux/crypto.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <linux/skbuff.h> @@ -107,7 +108,7 @@ static const struct sctp_paramhdr prsctp_param = {  	cpu_to_be16(sizeof(struct sctp_paramhdr)),  }; -/* A helper to initialize to initialize an op error inside a +/* A helper to initialize an op error inside a   * provided chunk, as most cause codes will be embedded inside an   * abort chunk.   */ @@ -124,6 +125,29 @@ void  sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,  	chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);  } +/* A helper to initialize an op error inside a + * provided chunk, as most cause codes will be embedded inside an + * abort chunk.  Differs from sctp_init_cause in that it won't oops + * if there isn't enough space in the op error chunk + */ +int sctp_init_cause_fixed(struct sctp_chunk *chunk, __be16 cause_code, +		      size_t paylen) +{ +	sctp_errhdr_t err; +	__u16 len; + +	/* Cause code constants are now defined in network order.  */ +	err.cause = cause_code; +	len = sizeof(sctp_errhdr_t) + paylen; +	err.length  = htons(len); + +	if (skb_tailroom(chunk->skb) >  len) +		return -ENOSPC; +	chunk->subh.err_hdr = sctp_addto_chunk_fixed(chunk, +						     sizeof(sctp_errhdr_t), +						     &err); +	return 0; +}  /* 3.3.2 Initiation (INIT) (1)   *   * This chunk is used to initiate a SCTP association between two @@ -207,7 +231,8 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,  	sp = sctp_sk(asoc->base.sk);  	num_types = sp->pf->supported_addrs(sp, types); -	chunksize = sizeof(init) + addrs_len + SCTP_SAT_LEN(num_types); +	chunksize = sizeof(init) + addrs_len; +	chunksize += WORD_ROUND(SCTP_SAT_LEN(num_types));  	chunksize += sizeof(ecap_param);  	if (sctp_prsctp_enable) @@ -237,14 +262,14 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,  		/* Add HMACS parameter length if any were defined */  		auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs;  		if (auth_hmacs->length) -			chunksize += ntohs(auth_hmacs->length); +			chunksize += WORD_ROUND(ntohs(auth_hmacs->length));  		else  			auth_hmacs = NULL;  		/* Add CHUNKS parameter length */  		auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks;  		if (auth_chunks->length) -			chunksize += ntohs(auth_chunks->length); +			chunksize += WORD_ROUND(ntohs(auth_chunks->length));  		else  			auth_chunks = NULL; @@ -254,7 +279,8 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,  	/* If we have any extensions to report, account for that */  	if (num_ext) -		chunksize += sizeof(sctp_supported_ext_param_t) + num_ext; +		chunksize += WORD_ROUND(sizeof(sctp_supported_ext_param_t) + +					num_ext);  	/* RFC 2960 3.3.2 Initiation (INIT) (1)  	 * @@ -396,13 +422,13 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,  		auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs;  		if (auth_hmacs->length) -			chunksize += ntohs(auth_hmacs->length); +			chunksize += WORD_ROUND(ntohs(auth_hmacs->length));  		else  			auth_hmacs = NULL;  		auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks;  		if (auth_chunks->length) -			chunksize += ntohs(auth_chunks->length); +			chunksize += WORD_ROUND(ntohs(auth_chunks->length));  		else  			auth_chunks = NULL; @@ -411,7 +437,8 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,  	}  	if (num_ext) -		chunksize += sizeof(sctp_supported_ext_param_t) + num_ext; +		chunksize += WORD_ROUND(sizeof(sctp_supported_ext_param_t) + +					num_ext);  	/* Now allocate and fill out the chunk.  */  	retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize); @@ -1128,6 +1155,24 @@ nodata:  	return retval;  } +/* Create an Operation Error chunk of a fixed size, + * specifically, max(asoc->pathmtu, SCTP_DEFAULT_MAXSEGMENT) + * This is a helper function to allocate an error chunk for + * for those invalid parameter codes in which we may not want + * to report all the errors, if the incomming chunk is large + */ +static inline struct sctp_chunk *sctp_make_op_error_fixed( +	const struct sctp_association *asoc, +	const struct sctp_chunk *chunk) +{ +	size_t size = asoc ? asoc->pathmtu : 0; + +	if (!size) +		size = SCTP_DEFAULT_MAXSEGMENT; + +	return sctp_make_op_error_space(asoc, chunk, size); +} +  /* Create an Operation Error chunk.  */  struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,  				 const struct sctp_chunk *chunk, @@ -1370,6 +1415,18 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data)  	return target;  } +/* Append bytes to the end of a chunk. Returns NULL if there isn't sufficient + * space in the chunk + */ +void *sctp_addto_chunk_fixed(struct sctp_chunk *chunk, +			     int len, const void *data) +{ +	if (skb_tailroom(chunk->skb) > len) +		return sctp_addto_chunk(chunk, len, data); +	else +		return NULL; +} +  /* Append bytes from user space to the end of a chunk.  Will panic if   * chunk is not big enough.   * Returns a kernel err value. @@ -1973,13 +2030,12 @@ static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc,  		 * returning multiple unknown parameters.  		 */  		if (NULL == *errp) -			*errp = sctp_make_op_error_space(asoc, chunk, -					ntohs(chunk->chunk_hdr->length)); +			*errp = sctp_make_op_error_fixed(asoc, chunk);  		if (*errp) { -			sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, +			sctp_init_cause_fixed(*errp, SCTP_ERROR_UNKNOWN_PARAM,  					WORD_ROUND(ntohs(param.p->length))); -			sctp_addto_chunk(*errp, +			sctp_addto_chunk_fixed(*errp,  					WORD_ROUND(ntohs(param.p->length)),  					param.v);  		} else { @@ -3314,21 +3370,6 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,  	sctp_chunk_free(asconf);  	asoc->addip_last_asconf = NULL; -	/* Send the next asconf chunk from the addip chunk queue. */ -	if (!list_empty(&asoc->addip_chunk_list)) { -		struct list_head *entry = asoc->addip_chunk_list.next; -		asconf = list_entry(entry, struct sctp_chunk, list); - -		list_del_init(entry); - -		/* Hold the chunk until an ASCONF_ACK is received. */ -		sctp_chunk_hold(asconf); -		if (sctp_primitive_ASCONF(asoc, asconf)) -			sctp_chunk_free(asconf); -		else -			asoc->addip_last_asconf = asconf; -	} -  	return retval;  } diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 4e4ca65cd32..eb1f42f45fd 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -51,6 +51,7 @@  #include <linux/types.h>  #include <linux/socket.h>  #include <linux/ip.h> +#include <linux/gfp.h>  #include <net/sock.h>  #include <net/sctp/sctp.h>  #include <net/sctp/sm.h> @@ -396,6 +397,41 @@ out_unlock:  	sctp_transport_put(transport);  } +/* Handle the timeout of the ICMP protocol unreachable timer.  Trigger + * the correct state machine transition that will close the association. + */ +void sctp_generate_proto_unreach_event(unsigned long data) +{ +	struct sctp_transport *transport = (struct sctp_transport *) data; +	struct sctp_association *asoc = transport->asoc; +	 +	sctp_bh_lock_sock(asoc->base.sk); +	if (sock_owned_by_user(asoc->base.sk)) { +		SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__); + +		/* Try again later.  */ +		if (!mod_timer(&transport->proto_unreach_timer, +				jiffies + (HZ/20))) +			sctp_association_hold(asoc); +		goto out_unlock; +	} + +	/* Is this structure just waiting around for us to actually +	 * get destroyed? +	 */ +	if (asoc->base.dead) +		goto out_unlock; + +	sctp_do_sm(SCTP_EVENT_T_OTHER, +		   SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), +		   asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC); + +out_unlock: +	sctp_bh_unlock_sock(asoc->base.sk); +	sctp_association_put(asoc); +} + +  /* Inject a SACK Timeout event into the state machine.  */  static void sctp_generate_sack_event(unsigned long data)  { @@ -475,7 +511,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,  	 * used to provide an upper bound to this doubling operation.  	 *  	 * Special Case:  the first HB doesn't trigger exponential backoff. -	 * The first unacknowleged HB triggers it.  We do this with a flag +	 * The first unacknowledged HB triggers it.  We do this with a flag  	 * that indicates that we have an outstanding HB.  	 */  	if (!is_hb || transport->hb_sent) { @@ -961,6 +997,29 @@ static int sctp_cmd_send_msg(struct sctp_association *asoc,  } +/* Sent the next ASCONF packet currently stored in the association. + * This happens after the ASCONF_ACK was succeffully processed. + */ +static void sctp_cmd_send_asconf(struct sctp_association *asoc) +{ +	/* Send the next asconf chunk from the addip chunk +	 * queue. +	 */ +	if (!list_empty(&asoc->addip_chunk_list)) { +		struct list_head *entry = asoc->addip_chunk_list.next; +		struct sctp_chunk *asconf = list_entry(entry, +						struct sctp_chunk, list); +		list_del_init(entry); + +		/* Hold the chunk until an ASCONF_ACK is received. */ +		sctp_chunk_hold(asconf); +		if (sctp_primitive_ASCONF(asoc, asconf)) +			sctp_chunk_free(asconf); +		else +			asoc->addip_last_asconf = asconf; +	} +} +  /* These three macros allow us to pull the debugging code out of the   * main flow of sctp_do_sm() to keep attention focused on the real @@ -1616,6 +1675,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,  			}  			error = sctp_cmd_send_msg(asoc, cmd->obj.msg);  			break; +		case SCTP_CMD_SEND_NEXT_ASCONF: +			sctp_cmd_send_asconf(asoc); +			break;  		default:  			printk(KERN_WARNING "Impossible command: %u, %p\n",  			       cmd->verb, cmd->obj.ptr); diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 47bc20d3a85..24b2cd55563 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -56,6 +56,7 @@  #include <linux/ipv6.h>  #include <linux/net.h>  #include <linux/inet.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/inet_ecn.h>  #include <linux/skbuff.h> @@ -3675,8 +3676,14 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,  				SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));  		if (!sctp_process_asconf_ack((struct sctp_association *)asoc, -					     asconf_ack)) +					     asconf_ack)) { +			/* Successfully processed ASCONF_ACK.  We can +			 * release the next asconf if we have one. +			 */ +			sctp_add_cmd_sf(commands, SCTP_CMD_SEND_NEXT_ASCONF, +					SCTP_NULL());  			return SCTP_DISPOSITION_CONSUME; +		}  		abort = sctp_make_abort(asoc, asconf_ack,  					sizeof(sctp_errhdr_t)); diff --git a/net/sctp/socket.c b/net/sctp/socket.c index f6d1e59c415..44a1ab03a3f 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -67,6 +67,7 @@  #include <linux/poll.h>  #include <linux/init.h>  #include <linux/crypto.h> +#include <linux/slab.h>  #include <net/ip.h>  #include <net/icmp.h> @@ -3718,9 +3719,12 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)  	sp->hmac = NULL;  	SCTP_DBG_OBJCNT_INC(sock); -	percpu_counter_inc(&sctp_sockets_allocated); + +	/* Set socket backlog limit. */ +	sk->sk_backlog.limit = sysctl_sctp_rmem[1];  	local_bh_disable(); +	percpu_counter_inc(&sctp_sockets_allocated);  	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);  	local_bh_enable(); @@ -3737,8 +3741,8 @@ SCTP_STATIC void sctp_destroy_sock(struct sock *sk)  	/* Release our hold on the endpoint. */  	ep = sctp_sk(sk)->ep;  	sctp_endpoint_free(ep); -	percpu_counter_dec(&sctp_sockets_allocated);  	local_bh_disable(); +	percpu_counter_dec(&sctp_sockets_allocated);  	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);  	local_bh_enable();  } @@ -6185,6 +6189,16 @@ do_nonblock:  	goto out;  } +void sctp_data_ready(struct sock *sk, int len) +{ +	read_lock_bh(&sk->sk_callback_lock); +	if (sk_has_sleeper(sk)) +		wake_up_interruptible_sync_poll(sk->sk_sleep, POLLIN | +						POLLRDNORM | POLLRDBAND); +	sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); +	read_unlock_bh(&sk->sk_callback_lock); +} +  /* If socket sndbuf has changed, wake up all per association waiters.  */  void sctp_write_space(struct sock *sk)  { diff --git a/net/sctp/ssnmap.c b/net/sctp/ssnmap.c index 737d330e5ff..442ad4ed631 100644 --- a/net/sctp/ssnmap.c +++ b/net/sctp/ssnmap.c @@ -37,6 +37,7 @@   */  #include <linux/types.h> +#include <linux/slab.h>  #include <net/sctp/sctp.h>  #include <net/sctp/sm.h> diff --git a/net/sctp/transport.c b/net/sctp/transport.c index b827d21dbe5..165d54e07fc 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -48,6 +48,7 @@   * be incorporated into the next SCTP release.   */ +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/random.h>  #include <net/sctp/sctp.h> @@ -107,6 +108,8 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,  			(unsigned long)peer);  	setup_timer(&peer->hb_timer, sctp_generate_heartbeat_event,  			(unsigned long)peer); +	setup_timer(&peer->proto_unreach_timer, +		    sctp_generate_proto_unreach_event, (unsigned long)peer);  	/* Initialize the 64-bit random nonce sent with heartbeat. */  	get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce)); @@ -170,6 +173,10 @@ void sctp_transport_free(struct sctp_transport *transport)  	    del_timer(&transport->T3_rtx_timer))  		sctp_transport_put(transport); +	/* Delete the ICMP proto unreachable timer if it's active. */ +	if (timer_pending(&transport->proto_unreach_timer) && +	    del_timer(&transport->proto_unreach_timer)) +		sctp_association_put(transport->asoc);  	sctp_transport_put(transport);  } diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c index 9bd64565021..747d5412c46 100644 --- a/net/sctp/tsnmap.c +++ b/net/sctp/tsnmap.c @@ -42,6 +42,7 @@   * be incorporated into the next SCTP release.   */ +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/bitmap.h>  #include <net/sctp/sctp.h> diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 8b3560fd876..aa72e89c3ee 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -43,6 +43,7 @@   * be incorporated into the next SCTP release.   */ +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/skbuff.h>  #include <net/sctp/structs.h> diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 7b23803343c..3a448536f0b 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -41,6 +41,7 @@   * be incorporated into the next SCTP release.   */ +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/skbuff.h>  #include <net/sock.h> diff --git a/net/socket.c b/net/socket.c index 769c386bd42..5e8d0af3c0e 100644 --- a/net/socket.c +++ b/net/socket.c @@ -87,6 +87,7 @@  #include <linux/wireless.h>  #include <linux/nsproxy.h>  #include <linux/magic.h> +#include <linux/slab.h>  #include <asm/uaccess.h>  #include <asm/unistd.h> @@ -2135,6 +2136,10 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,  			break;  		++datagrams; +		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */ +		if (flags & MSG_WAITFORONE) +			flags |= MSG_DONTWAIT; +  		if (timeout) {  			ktime_get_ts(timeout);  			*timeout = timespec_sub(end_time, *timeout); diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c index f845d9d72f7..1419d0cdbba 100644 --- a/net/sunrpc/addr.c +++ b/net/sunrpc/addr.c @@ -18,6 +18,7 @@  #include <net/ipv6.h>  #include <linux/sunrpc/clnt.h> +#include <linux/slab.h>  #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index f394fc190a4..95afe79dd9d 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c @@ -237,7 +237,7 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan)  	list_for_each_entry_safe(cred, next, &cred_unused, cr_lru) {  		/* Enforce a 60 second garbage collection moratorium */ -		if (time_in_range_open(cred->cr_expire, expired, jiffies) && +		if (time_in_range(cred->cr_expire, expired, jiffies) &&  		    test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0)  			continue; diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index bf88bf8e936..8f623b0f03d 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c @@ -5,6 +5,7 @@   */  #include <linux/err.h> +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/module.h>  #include <linux/sched.h> diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 0cfccc2a029..c389ccf6437 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -1280,9 +1280,8 @@ alloc_enc_pages(struct rpc_rqst *rqstp)  	rqstp->rq_release_snd_buf = priv_release_snd_buf;  	return 0;  out_free: -	for (i--; i >= 0; i--) { -		__free_page(rqstp->rq_enc_pages[i]); -	} +	rqstp->rq_enc_pages_num = i; +	priv_release_snd_buf(rqstp);  out:  	return -EAGAIN;  } diff --git a/net/sunrpc/auth_gss/gss_generic_token.c b/net/sunrpc/auth_gss/gss_generic_token.c index c0ba39c4f5f..310b78e9945 100644 --- a/net/sunrpc/auth_gss/gss_generic_token.c +++ b/net/sunrpc/auth_gss/gss_generic_token.c @@ -33,7 +33,6 @@  #include <linux/types.h>  #include <linux/module.h> -#include <linux/slab.h>  #include <linux/string.h>  #include <linux/sunrpc/sched.h>  #include <linux/sunrpc/gss_asn1.h> diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index c93fca20455..e9b63617668 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -37,7 +37,6 @@  #include <linux/err.h>  #include <linux/types.h>  #include <linux/mm.h> -#include <linux/slab.h>  #include <linux/scatterlist.h>  #include <linux/crypto.h>  #include <linux/highmem.h> diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index b8f42ef7178..88fe6e75ed7 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c @@ -59,7 +59,6 @@   */  #include <linux/types.h> -#include <linux/slab.h>  #include <linux/jiffies.h>  #include <linux/sunrpc/gss_krb5.h>  #include <linux/random.h> diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c index 17562b4c35f..6331cd6866e 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c +++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c @@ -32,7 +32,6 @@   */  #include <linux/types.h> -#include <linux/slab.h>  #include <linux/sunrpc/gss_krb5.h>  #include <linux/crypto.h> diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c index 066ec73c84d..ce6c247edad 100644 --- a/net/sunrpc/auth_gss/gss_krb5_unseal.c +++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c @@ -58,7 +58,6 @@   */  #include <linux/types.h> -#include <linux/slab.h>  #include <linux/jiffies.h>  #include <linux/sunrpc/gss_krb5.h>  #include <linux/crypto.h> diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index ae8e69b59c4..a6e905637e0 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -1,5 +1,4 @@  #include <linux/types.h> -#include <linux/slab.h>  #include <linux/jiffies.h>  #include <linux/sunrpc/gss_krb5.h>  #include <linux/random.h> diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c index c832712f8d5..5a3a65a0e2b 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_seal.c +++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c @@ -34,7 +34,6 @@   */  #include <linux/types.h> -#include <linux/slab.h>  #include <linux/jiffies.h>  #include <linux/sunrpc/gss_spkm3.h>  #include <linux/random.h> diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index e34bc531fcb..b81e790ef9f 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -37,6 +37,7 @@   *   */ +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/module.h>  #include <linux/pagemap.h> diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 46b2647c5bd..aac2f8b4ee2 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c @@ -6,6 +6,7 @@   * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>   */ +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/sched.h>  #include <linux/module.h> diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 553621fb2c4..cf06af3b63c 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c @@ -22,6 +22,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  ******************************************************************************/  #include <linux/tcp.h> +#include <linux/slab.h>  #include <linux/sunrpc/xprt.h>  #ifdef RPC_DEBUG diff --git a/net/sunrpc/bc_svc.c b/net/sunrpc/bc_svc.c index 13f214f5312..f0c05d3311c 100644 --- a/net/sunrpc/bc_svc.c +++ b/net/sunrpc/bc_svc.c @@ -37,21 +37,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  #define RPCDBG_FACILITY	RPCDBG_SVCDSP -void bc_release_request(struct rpc_task *task) -{ -	struct rpc_rqst *req = task->tk_rqstp; - -	dprintk("RPC:       bc_release_request: task= %p\n", task); - -	/* -	 * Release this request only if it's a backchannel -	 * preallocated request -	 */ -	if (!bc_prealloc(req)) -		return; -	xprt_free_bc_request(req); -} -  /* Empty callback ops */  static const struct rpc_call_ops nfs41_callback_ops = {  }; diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 154034b675b..19c9983d536 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -659,6 +659,7 @@ struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req,  	task = rpc_new_task(&task_setup_data);  	if (!task) {  		xprt_free_bc_request(req); +		task = ERR_PTR(-ENOMEM);  		goto out;  	}  	task->tk_rqstp = req; diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 8d63f8fd29b..20e30c6f835 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -587,6 +587,8 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent,  	struct dentry *dentry;  	dentry = __rpc_lookup_create(parent, name); +	if (IS_ERR(dentry)) +		return dentry;  	if (dentry->d_inode == NULL)  		return dentry;  	dput(dentry); diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 3e3772d8eb9..121105355f6 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -21,6 +21,7 @@  #include <linux/kernel.h>  #include <linux/errno.h>  #include <linux/mutex.h> +#include <linux/slab.h>  #include <net/ipv6.h>  #include <linux/sunrpc/clnt.h> diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c index a661a3acb37..10b4319ebbc 100644 --- a/net/sunrpc/socklib.c +++ b/net/sunrpc/socklib.c @@ -8,6 +8,7 @@  #include <linux/compiler.h>  #include <linux/netdevice.h> +#include <linux/gfp.h>  #include <linux/skbuff.h>  #include <linux/types.h>  #include <linux/pagemap.h> diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index 1b4e6791ecf..5785d2037f4 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c @@ -13,6 +13,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/init.h>  #include <linux/kernel.h> diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 8420a4205b7..d9017d64597 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -19,6 +19,7 @@  #include <linux/interrupt.h>  #include <linux/module.h>  #include <linux/kthread.h> +#include <linux/slab.h>  #include <linux/sunrpc/types.h>  #include <linux/sunrpc/xdr.h> diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 8f0f1fb3dc5..061b2e0f911 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -9,6 +9,7 @@  #include <linux/errno.h>  #include <linux/freezer.h>  #include <linux/kthread.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <linux/sunrpc/stats.h>  #include <linux/sunrpc/svc_xprt.h> diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index afdcb0459a8..20731161098 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -10,6 +10,7 @@  #include <linux/seq_file.h>  #include <linux/hash.h>  #include <linux/string.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/ipv6.h>  #include <linux/kernel.h> diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 8bd690c48b6..2763fde8849 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -7,6 +7,7 @@   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/types.h>  #include <linux/string.h>  #include <linux/kernel.h> diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 469de292c23..42f09ade004 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -46,6 +46,7 @@  #include <linux/sunrpc/clnt.h>  #include <linux/sunrpc/metrics.h> +#include <linux/sunrpc/bc_xprt.h>  #include "sunrpc.h" @@ -1032,21 +1033,16 @@ void xprt_release(struct rpc_task *task)  	if (req->rq_release_snd_buf)  		req->rq_release_snd_buf(req); -	/* -	 * Early exit if this is a backchannel preallocated request. -	 * There is no need to have it added to the RPC slot list. -	 */ -	if (is_bc_request) -		return; - -	memset(req, 0, sizeof(*req));	/* mark unused */ -  	dprintk("RPC: %5u release request %p\n", task->tk_pid, req); +	if (likely(!is_bc_request)) { +		memset(req, 0, sizeof(*req));	/* mark unused */ -	spin_lock(&xprt->reserve_lock); -	list_add(&req->rq_list, &xprt->free); -	rpc_wake_up_next(&xprt->backlog); -	spin_unlock(&xprt->reserve_lock); +		spin_lock(&xprt->reserve_lock); +		list_add(&req->rq_list, &xprt->free); +		rpc_wake_up_next(&xprt->backlog); +		spin_unlock(&xprt->reserve_lock); +	} else +		xprt_free_bc_request(req);  }  /** diff --git a/net/sunrpc/xprtrdma/svc_rdma.c b/net/sunrpc/xprtrdma/svc_rdma.c index 5b8a8ff93a2..d718b8fa952 100644 --- a/net/sunrpc/xprtrdma/svc_rdma.c +++ b/net/sunrpc/xprtrdma/svc_rdma.c @@ -40,6 +40,7 @@   */  #include <linux/module.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <linux/fs.h>  #include <linux/sysctl.h>  #include <linux/sunrpc/clnt.h> diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 3fa5751af0e..edea15a54e5 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -43,6 +43,7 @@  #include <linux/sunrpc/debug.h>  #include <linux/sunrpc/rpc_rdma.h>  #include <linux/sched.h> +#include <linux/slab.h>  #include <linux/spinlock.h>  #include <rdma/ib_verbs.h>  #include <rdma/rdma_cm.h> @@ -678,7 +679,10 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,  	int ret;  	dprintk("svcrdma: Creating RDMA socket\n"); - +	if (sa->sa_family != AF_INET) { +		dprintk("svcrdma: Address family %d is not supported.\n", sa->sa_family); +		return ERR_PTR(-EAFNOSUPPORT); +	}  	cma_xprt = rdma_create_xprt(serv, 1);  	if (!cma_xprt)  		return ERR_PTR(-ENOMEM); diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 7018eef1dcd..187257b1d88 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -49,6 +49,7 @@  #include <linux/module.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <linux/seq_file.h>  #include "xprt_rdma.h" @@ -160,16 +161,15 @@ xprt_rdma_format_addresses(struct rpc_xprt *xprt)  	(void)rpc_ntop(sap, buf, sizeof(buf));  	xprt->address_strings[RPC_DISPLAY_ADDR] = kstrdup(buf, GFP_KERNEL); -	(void)snprintf(buf, sizeof(buf), "%u", rpc_get_port(sap)); +	snprintf(buf, sizeof(buf), "%u", rpc_get_port(sap));  	xprt->address_strings[RPC_DISPLAY_PORT] = kstrdup(buf, GFP_KERNEL);  	xprt->address_strings[RPC_DISPLAY_PROTO] = "rdma"; -	(void)snprintf(buf, sizeof(buf), "%02x%02x%02x%02x", -				NIPQUAD(sin->sin_addr.s_addr)); +	snprintf(buf, sizeof(buf), "%08x", ntohl(sin->sin_addr.s_addr));  	xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = kstrdup(buf, GFP_KERNEL); -	(void)snprintf(buf, sizeof(buf), "%4hx", rpc_get_port(sap)); +	snprintf(buf, sizeof(buf), "%4hx", rpc_get_port(sap));  	xprt->address_strings[RPC_DISPLAY_HEX_PORT] = kstrdup(buf, GFP_KERNEL);  	/* netid */ diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 2209aa87d89..27015c6d8eb 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c @@ -48,6 +48,7 @@   */  #include <linux/pci.h>	/* for Tavor hack below */ +#include <linux/slab.h>  #include "xprt_rdma.h" diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 712412982ce..9847c30b500 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -297,12 +297,11 @@ static void xs_format_common_peer_addresses(struct rpc_xprt *xprt)  	switch (sap->sa_family) {  	case AF_INET:  		sin = xs_addr_in(xprt); -		(void)snprintf(buf, sizeof(buf), "%02x%02x%02x%02x", -					NIPQUAD(sin->sin_addr.s_addr)); +		snprintf(buf, sizeof(buf), "%08x", ntohl(sin->sin_addr.s_addr));  		break;  	case AF_INET6:  		sin6 = xs_addr_in6(xprt); -		(void)snprintf(buf, sizeof(buf), "%pi6", &sin6->sin6_addr); +		snprintf(buf, sizeof(buf), "%pi6", &sin6->sin6_addr);  		break;  	default:  		BUG(); @@ -315,10 +314,10 @@ static void xs_format_common_peer_ports(struct rpc_xprt *xprt)  	struct sockaddr *sap = xs_addr(xprt);  	char buf[128]; -	(void)snprintf(buf, sizeof(buf), "%u", rpc_get_port(sap)); +	snprintf(buf, sizeof(buf), "%u", rpc_get_port(sap));  	xprt->address_strings[RPC_DISPLAY_PORT] = kstrdup(buf, GFP_KERNEL); -	(void)snprintf(buf, sizeof(buf), "%4hx", rpc_get_port(sap)); +	snprintf(buf, sizeof(buf), "%4hx", rpc_get_port(sap));  	xprt->address_strings[RPC_DISPLAY_HEX_PORT] = kstrdup(buf, GFP_KERNEL);  } @@ -549,8 +548,6 @@ static int xs_udp_send_request(struct rpc_task *task)  		/* Still some bytes left; set up for a retry later. */  		status = -EAGAIN;  	} -	if (!transport->sock) -		goto out;  	switch (status) {  	case -ENOTSOCK: @@ -570,7 +567,7 @@ static int xs_udp_send_request(struct rpc_task *task)  		 * prompts ECONNREFUSED. */  		clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);  	} -out: +  	return status;  } @@ -652,8 +649,6 @@ static int xs_tcp_send_request(struct rpc_task *task)  		status = -EAGAIN;  		break;  	} -	if (!transport->sock) -		goto out;  	switch (status) {  	case -ENOTSOCK: @@ -673,7 +668,7 @@ static int xs_tcp_send_request(struct rpc_task *task)  	case -ENOTCONN:  		clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);  	} -out: +  	return status;  } @@ -2256,9 +2251,6 @@ static struct rpc_xprt_ops xs_tcp_ops = {  	.buf_free		= rpc_free,  	.send_request		= xs_tcp_send_request,  	.set_retrans_timeout	= xprt_set_retrans_timeout_def, -#if defined(CONFIG_NFS_V4_1) -	.release_request	= bc_release_request, -#endif /* CONFIG_NFS_V4_1 */  	.close			= xs_tcp_close,  	.destroy		= xs_destroy,  	.print_stats		= xs_tcp_print_stats, diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 327011fcc40..78091375ca1 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -45,10 +45,10 @@  #define MAX_ADDR_STR 32 -static struct media *media_list = NULL; +static struct media media_list[MAX_MEDIA];  static u32 media_count = 0; -struct bearer *tipc_bearers = NULL; +struct bearer tipc_bearers[MAX_BEARERS];  /**   * media_name_valid - validate media name @@ -108,9 +108,11 @@ int  tipc_register_media(u32 media_type,  	int res = -EINVAL;  	write_lock_bh(&tipc_net_lock); -	if (!media_list) -		goto exit; +	if (tipc_mode != TIPC_NET_MODE) { +		warn("Media <%s> rejected, not in networked mode yet\n", name); +		goto exit; +	}  	if (!media_name_valid(name)) {  		warn("Media <%s> rejected, illegal name\n", name);  		goto exit; @@ -660,33 +662,10 @@ int tipc_disable_bearer(const char *name) -int tipc_bearer_init(void) -{ -	int res; - -	write_lock_bh(&tipc_net_lock); -	tipc_bearers = kcalloc(MAX_BEARERS, sizeof(struct bearer), GFP_ATOMIC); -	media_list = kcalloc(MAX_MEDIA, sizeof(struct media), GFP_ATOMIC); -	if (tipc_bearers && media_list) { -		res = 0; -	} else { -		kfree(tipc_bearers); -		kfree(media_list); -		tipc_bearers = NULL; -		media_list = NULL; -		res = -ENOMEM; -	} -	write_unlock_bh(&tipc_net_lock); -	return res; -} -  void tipc_bearer_stop(void)  {  	u32 i; -	if (!tipc_bearers) -		return; -  	for (i = 0; i < MAX_BEARERS; i++) {  		if (tipc_bearers[i].active)  			tipc_bearers[i].publ.blocked = 1; @@ -695,10 +674,6 @@ void tipc_bearer_stop(void)  		if (tipc_bearers[i].active)  			bearer_disable(tipc_bearers[i].publ.name);  	} -	kfree(tipc_bearers); -	kfree(media_list); -	tipc_bearers = NULL; -	media_list = NULL;  	media_count = 0;  } diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index ca573489271..000228e93f9 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -114,7 +114,7 @@ struct bearer_name {  struct link; -extern struct bearer *tipc_bearers; +extern struct bearer tipc_bearers[];  void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a);  struct sk_buff *tipc_media_get_names(void); diff --git a/net/tipc/core.h b/net/tipc/core.h index a881f92a853..c58a1d16563 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -56,6 +56,7 @@  #include <linux/netdevice.h>  #include <linux/in.h>  #include <linux/list.h> +#include <linux/slab.h>  #include <linux/vmalloc.h>  /* diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index 524ba5696d4..6230d16020c 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c @@ -38,6 +38,7 @@  #include <net/tipc/tipc_bearer.h>  #include <net/tipc/tipc_msg.h>  #include <linux/netdevice.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #define MAX_ETH_BEARERS		2 diff --git a/net/tipc/link.c b/net/tipc/link.c index 6f50f6423f6..1a7e4665af8 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1882,6 +1882,15 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)  			     (msg_destnode(msg) != tipc_own_addr)))  			goto cont; +		/* Discard non-routeable messages destined for another node */ + +		if (unlikely(!msg_isdata(msg) && +			     (msg_destnode(msg) != tipc_own_addr))) { +			if ((msg_user(msg) != CONN_MANAGER) && +			    (msg_user(msg) != MSG_FRAGMENTER)) +				goto cont; +		} +  		/* Locate unicast link endpoint that should handle message */  		n_ptr = tipc_node_find(msg_prevnode(msg)); diff --git a/net/tipc/net.c b/net/tipc/net.c index 7906608bf51..f25b1cdb64e 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -116,7 +116,8 @@  */  DEFINE_RWLOCK(tipc_net_lock); -struct network tipc_net = { NULL }; +struct _zone *tipc_zones[256] = { NULL, }; +struct network tipc_net = { tipc_zones };  struct tipc_node *tipc_net_select_remote_node(u32 addr, u32 ref)  { @@ -158,28 +159,12 @@ void tipc_net_send_external_routes(u32 dest)  	}  } -static int net_init(void) -{ -	memset(&tipc_net, 0, sizeof(tipc_net)); -	tipc_net.zones = kcalloc(tipc_max_zones + 1, sizeof(struct _zone *), GFP_ATOMIC); -	if (!tipc_net.zones) { -		return -ENOMEM; -	} -	return 0; -} -  static void net_stop(void)  {  	u32 z_num; -	if (!tipc_net.zones) -		return; - -	for (z_num = 1; z_num <= tipc_max_zones; z_num++) { +	for (z_num = 1; z_num <= tipc_max_zones; z_num++)  		tipc_zone_delete(tipc_net.zones[z_num]); -	} -	kfree(tipc_net.zones); -	tipc_net.zones = NULL;  }  static void net_route_named_msg(struct sk_buff *buf) @@ -282,9 +267,7 @@ int tipc_net_start(u32 addr)  	tipc_named_reinit();  	tipc_port_reinit(); -	if ((res = tipc_bearer_init()) || -	    (res = net_init()) || -	    (res = tipc_cltr_init()) || +	if ((res = tipc_cltr_init()) ||  	    (res = tipc_bclink_init())) {  		return res;  	} diff --git a/net/tipc/ref.c b/net/tipc/ref.c index 414fc34b8be..8dea66500cf 100644 --- a/net/tipc/ref.c +++ b/net/tipc/ref.c @@ -153,11 +153,11 @@ void tipc_ref_table_stop(void)  u32 tipc_ref_acquire(void *object, spinlock_t **lock)  { -	struct reference *entry;  	u32 index;  	u32 index_mask;  	u32 next_plus_upper;  	u32 ref; +	struct reference *entry = NULL;  	if (!object) {  		err("Attempt to acquire reference to non-existent object\n"); @@ -175,30 +175,36 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock)  		index = tipc_ref_table.first_free;  		entry = &(tipc_ref_table.entries[index]);  		index_mask = tipc_ref_table.index_mask; -		/* take lock in case a previous user of entry still holds it */ -		spin_lock_bh(&entry->lock);  		next_plus_upper = entry->ref;  		tipc_ref_table.first_free = next_plus_upper & index_mask;  		ref = (next_plus_upper & ~index_mask) + index; -		entry->ref = ref; -		entry->object = object; -		*lock = &entry->lock;  	}  	else if (tipc_ref_table.init_point < tipc_ref_table.capacity) {  		index = tipc_ref_table.init_point++;  		entry = &(tipc_ref_table.entries[index]);  		spin_lock_init(&entry->lock); -		spin_lock_bh(&entry->lock);  		ref = tipc_ref_table.start_mask + index; -		entry->ref = ref; -		entry->object = object; -		*lock = &entry->lock;  	}  	else {  		ref = 0;  	}  	write_unlock_bh(&ref_table_lock); +	/* +	 * Grab the lock so no one else can modify this entry +	 * While we assign its ref value & object pointer +	 */ +	if (entry) { +		spin_lock_bh(&entry->lock); +		entry->ref = ref; +		entry->object = object; +		*lock = &entry->lock; +		/* +		 * keep it locked, the caller is responsible +		 * for unlocking this when they're done with it +		 */ +	} +  	return ref;  } diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 1ea64f09cc4..cfb20b80b3a 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -40,9 +40,9 @@  #include <linux/socket.h>  #include <linux/errno.h>  #include <linux/mm.h> -#include <linux/slab.h>  #include <linux/poll.h>  #include <linux/fcntl.h> +#include <linux/gfp.h>  #include <asm/string.h>  #include <asm/atomic.h>  #include <net/sock.h> @@ -1322,8 +1322,10 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)  	if (!sock_owned_by_user(sk)) {  		res = filter_rcv(sk, buf);  	} else { -		sk_add_backlog(sk, buf); -		res = TIPC_OK; +		if (sk_add_backlog(sk, buf)) +			res = TIPC_ERR_OVERLOAD; +		else +			res = TIPC_OK;  	}  	bh_unlock_sock(sk); diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index ac91f0dfa14..ff123e56114 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -76,19 +76,6 @@ struct top_srv {  static struct top_srv topsrv = { 0 };  /** - * htohl - convert value to endianness used by destination - * @in: value to convert - * @swap: non-zero if endianness must be reversed - * - * Returns converted value - */ - -static u32 htohl(u32 in, int swap) -{ -	return swap ? swab32(in) : in; -} - -/**   * subscr_send_event - send a message containing a tipc_event to the subscriber   *   * Note: Must not hold subscriber's server port lock, since tipc_send() will @@ -107,11 +94,11 @@ static void subscr_send_event(struct subscription *sub,  	msg_sect.iov_base = (void *)&sub->evt;  	msg_sect.iov_len = sizeof(struct tipc_event); -	sub->evt.event = htohl(event, sub->swap); -	sub->evt.found_lower = htohl(found_lower, sub->swap); -	sub->evt.found_upper = htohl(found_upper, sub->swap); -	sub->evt.port.ref = htohl(port_ref, sub->swap); -	sub->evt.port.node = htohl(node, sub->swap); +	sub->evt.event = htonl(event); +	sub->evt.found_lower = htonl(found_lower); +	sub->evt.found_upper = htonl(found_upper); +	sub->evt.port.ref = htonl(port_ref); +	sub->evt.port.node = htonl(node);  	tipc_send(sub->server_ref, 1, &msg_sect);  } @@ -287,16 +274,23 @@ static void subscr_cancel(struct tipc_subscr *s,  {  	struct subscription *sub;  	struct subscription *sub_temp; +	__u32 type, lower, upper;  	int found = 0;  	/* Find first matching subscription, exit if not found */ +	type = ntohl(s->seq.type); +	lower = ntohl(s->seq.lower); +	upper = ntohl(s->seq.upper); +  	list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,  				 subscription_list) { -		if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) { -			found = 1; -			break; -		} +			if ((type == sub->seq.type) && +			    (lower == sub->seq.lower) && +			    (upper == sub->seq.upper)) { +				found = 1; +				break; +			}  	}  	if (!found)  		return; @@ -325,16 +319,10 @@ static struct subscription *subscr_subscribe(struct tipc_subscr *s,  					     struct subscriber *subscriber)  {  	struct subscription *sub; -	int swap; - -	/* Determine subscriber's endianness */ - -	swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE));  	/* Detect & process a subscription cancellation request */ -	if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { -		s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); +	if (ntohl(s->filter) & TIPC_SUB_CANCEL) {  		subscr_cancel(s, subscriber);  		return NULL;  	} @@ -359,11 +347,11 @@ static struct subscription *subscr_subscribe(struct tipc_subscr *s,  	/* Initialize subscription object */ -	sub->seq.type = htohl(s->seq.type, swap); -	sub->seq.lower = htohl(s->seq.lower, swap); -	sub->seq.upper = htohl(s->seq.upper, swap); -	sub->timeout = htohl(s->timeout, swap); -	sub->filter = htohl(s->filter, swap); +	sub->seq.type = ntohl(s->seq.type); +	sub->seq.lower = ntohl(s->seq.lower); +	sub->seq.upper = ntohl(s->seq.upper); +	sub->timeout = ntohl(s->timeout); +	sub->filter = ntohl(s->filter);  	if ((!(sub->filter & TIPC_SUB_PORTS) ==  	     !(sub->filter & TIPC_SUB_SERVICE)) ||  	    (sub->seq.lower > sub->seq.upper)) { @@ -376,7 +364,6 @@ static struct subscription *subscr_subscribe(struct tipc_subscr *s,  	INIT_LIST_HEAD(&sub->nameseq_list);  	list_add(&sub->subscription_list, &subscriber->subscription_list);  	sub->server_ref = subscriber->port_ref; -	sub->swap = swap;  	memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr));  	atomic_inc(&topsrv.subscription_count);  	if (sub->timeout != TIPC_WAIT_FOREVER) { diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 45d89bf4d20..c20f496d95b 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h @@ -53,7 +53,6 @@ typedef void (*tipc_subscr_event) (struct subscription *sub,   * @nameseq_list: adjacent subscriptions in name sequence's subscription list   * @subscription_list: adjacent subscriptions in subscriber's subscription list   * @server_ref: object reference of server port associated with subscription - * @swap: indicates if subscriber uses opposite endianness in its messages   * @evt: template for events generated by subscription   */ @@ -66,7 +65,6 @@ struct subscription {  	struct list_head nameseq_list;  	struct list_head subscription_list;  	u32 server_ref; -	int swap;  	struct tipc_event evt;  }; diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 19c17e4a0c8..14c22c3768d 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -74,7 +74,6 @@  #include <linux/un.h>  #include <linux/net.h>  #include <linux/fs.h> -#include <linux/slab.h>  #include <linux/skbuff.h>  #include <linux/netdevice.h>  #include <linux/file.h> diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c index d095c7be10d..397cffebb3b 100644 --- a/net/unix/sysctl_net_unix.c +++ b/net/unix/sysctl_net_unix.c @@ -10,6 +10,7 @@   */  #include <linux/mm.h> +#include <linux/slab.h>  #include <linux/sysctl.h>  #include <net/af_unix.h> diff --git a/net/wimax/op-msg.c b/net/wimax/op-msg.c index 7718657e93d..d5b7c3779c4 100644 --- a/net/wimax/op-msg.c +++ b/net/wimax/op-msg.c @@ -72,6 +72,7 @@   *   wimax_msg_send()   */  #include <linux/device.h> +#include <linux/slab.h>  #include <net/genetlink.h>  #include <linux/netdevice.h>  #include <linux/wimax.h> diff --git a/net/wimax/stack.c b/net/wimax/stack.c index 813e1eaea29..1ed65dbdab0 100644 --- a/net/wimax/stack.c +++ b/net/wimax/stack.c @@ -51,6 +51,7 @@   *   wimax_rfkill_rm()   */  #include <linux/device.h> +#include <linux/gfp.h>  #include <net/genetlink.h>  #include <linux/netdevice.h>  #include <linux/wimax.h> diff --git a/net/wireless/core.c b/net/wireless/core.c index 7fdb9409ad2..6ac70c10152 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -8,6 +8,7 @@  #include <linux/module.h>  #include <linux/err.h>  #include <linux/list.h> +#include <linux/slab.h>  #include <linux/nl80211.h>  #include <linux/debugfs.h>  #include <linux/notifier.h> diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c index 2e489561503..a4991a3efec 100644 --- a/net/wireless/debugfs.c +++ b/net/wireless/debugfs.c @@ -9,6 +9,7 @@   * published by the Free Software Foundation.   */ +#include <linux/slab.h>  #include "core.h"  #include "debugfs.h" diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 6ef5a491fb4..6a5acf75017 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -6,6 +6,7 @@  #include <linux/etherdevice.h>  #include <linux/if_arp.h> +#include <linux/slab.h>  #include <net/cfg80211.h>  #include "wext-compat.h"  #include "nl80211.h" diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 62bc8855e12..22139fa4611 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -8,6 +8,7 @@  #include <linux/module.h>  #include <linux/netdevice.h>  #include <linux/nl80211.h> +#include <linux/slab.h>  #include <linux/wireless.h>  #include <net/cfg80211.h>  #include <net/iw_handler.h> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e447db04cf7..030cf153bea 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -7,6 +7,7 @@  #include <linux/if.h>  #include <linux/module.h>  #include <linux/err.h> +#include <linux/slab.h>  #include <linux/list.h>  #include <linux/if_ether.h>  #include <linux/ieee80211.h> diff --git a/net/wireless/reg.c b/net/wireless/reg.c index ed89c59bb43..422da20d1e5 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -33,6 +33,7 @@   *   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/list.h>  #include <linux/random.h>  #include <linux/nl80211.h> @@ -324,7 +325,7 @@ struct reg_regdb_search_request {  };  static LIST_HEAD(reg_regdb_search_list); -static DEFINE_SPINLOCK(reg_regdb_search_lock); +static DEFINE_MUTEX(reg_regdb_search_mutex);  static void reg_regdb_search(struct work_struct *work)  { @@ -332,7 +333,7 @@ static void reg_regdb_search(struct work_struct *work)  	const struct ieee80211_regdomain *curdom, *regdom;  	int i, r; -	spin_lock(®_regdb_search_lock); +	mutex_lock(®_regdb_search_mutex);  	while (!list_empty(®_regdb_search_list)) {  		request = list_first_entry(®_regdb_search_list,  					   struct reg_regdb_search_request, @@ -346,18 +347,16 @@ static void reg_regdb_search(struct work_struct *work)  				r = reg_copy_regd(®dom, curdom);  				if (r)  					break; -				spin_unlock(®_regdb_search_lock);  				mutex_lock(&cfg80211_mutex);  				set_regdom(regdom);  				mutex_unlock(&cfg80211_mutex); -				spin_lock(®_regdb_search_lock);  				break;  			}  		}  		kfree(request);  	} -	spin_unlock(®_regdb_search_lock); +	mutex_unlock(®_regdb_search_mutex);  }  static DECLARE_WORK(reg_regdb_work, reg_regdb_search); @@ -375,9 +374,9 @@ static void reg_regdb_query(const char *alpha2)  	memcpy(request->alpha2, alpha2, 2); -	spin_lock(®_regdb_search_lock); +	mutex_lock(®_regdb_search_mutex);  	list_add_tail(&request->list, ®_regdb_search_list); -	spin_unlock(®_regdb_search_lock); +	mutex_unlock(®_regdb_search_mutex);  	schedule_work(®_regdb_work);  } diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 978cac3414b..a026c6d56bd 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -4,6 +4,7 @@   * Copyright 2008 Johannes Berg <johannes@sipsolutions.net>   */  #include <linux/kernel.h> +#include <linux/slab.h>  #include <linux/module.h>  #include <linux/netdevice.h>  #include <linux/wireless.h> diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 17fde0da1b0..f4dfd5f5f2e 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -7,6 +7,7 @@  #include <linux/etherdevice.h>  #include <linux/if_arp.h> +#include <linux/slab.h>  #include <linux/workqueue.h>  #include <linux/wireless.h>  #include <net/iw_handler.h> diff --git a/net/wireless/util.c b/net/wireless/util.c index be2ab8c59e3..d3574a4eb3b 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -5,6 +5,7 @@   */  #include <linux/bitops.h>  #include <linux/etherdevice.h> +#include <linux/slab.h>  #include <net/cfg80211.h>  #include <net/ip.h>  #include "core.h" diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 9ab51838849..a60a2773b49 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -12,6 +12,7 @@  #include <linux/nl80211.h>  #include <linux/if_arp.h>  #include <linux/etherdevice.h> +#include <linux/slab.h>  #include <net/iw_handler.h>  #include <net/cfg80211.h>  #include "wext-compat.h" diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 5e1656bdf23..4f5a47091fd 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -10,6 +10,7 @@  #include <linux/kernel.h>  #include <linux/netdevice.h>  #include <linux/rtnetlink.h> +#include <linux/slab.h>  #include <linux/wireless.h>  #include <linux/uaccess.h>  #include <net/cfg80211.h> diff --git a/net/wireless/wext-priv.c b/net/wireless/wext-priv.c index a3c2277de9e..3feb28e41c5 100644 --- a/net/wireless/wext-priv.c +++ b/net/wireless/wext-priv.c @@ -7,6 +7,7 @@   *   * (As all part of the Linux kernel, this file is GPL)   */ +#include <linux/slab.h>  #include <linux/wireless.h>  #include <linux/netdevice.h>  #include <net/iw_handler.h> diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 5615a880253..d5c6140f4cb 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c @@ -7,6 +7,7 @@  #include <linux/etherdevice.h>  #include <linux/if_arp.h> +#include <linux/slab.h>  #include <net/cfg80211.h>  #include "wext-compat.h"  #include "nl80211.h" diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 9796f3ed1ed..36e84e13c6a 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -47,6 +47,7 @@  #include <linux/netdevice.h>  #include <linux/if_arp.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/tcp_states.h>  #include <asm/uaccess.h> @@ -82,6 +83,41 @@ struct compat_x25_subscrip_struct {  };  #endif + +int x25_parse_address_block(struct sk_buff *skb, +		struct x25_address *called_addr, +		struct x25_address *calling_addr) +{ +	unsigned char len; +	int needed; +	int rc; + +	if (skb->len < 1) { +		/* packet has no address block */ +		rc = 0; +		goto empty; +	} + +	len = *skb->data; +	needed = 1 + (len >> 4) + (len & 0x0f); + +	if (skb->len < needed) { +		/* packet is too short to hold the addresses it claims +		   to hold */ +		rc = -1; +		goto empty; +	} + +	return x25_addr_ntoa(skb->data, called_addr, calling_addr); + +empty: +	*called_addr->x25_addr = 0; +	*calling_addr->x25_addr = 0; + +	return rc; +} + +  int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr,  		  struct x25_address *calling_addr)  { @@ -366,6 +402,7 @@ static void __x25_destroy_socket(struct sock *sk)  			/*  			 * Queue the unaccepted socket for death  			 */ +			skb->sk->sk_state = TCP_LISTEN;  			sock_set_flag(skb->sk, SOCK_DEAD);  			x25_start_heartbeat(skb->sk);  			x25_sk(skb->sk)->state = X25_STATE_0; @@ -553,7 +590,8 @@ static int x25_create(struct net *net, struct socket *sock, int protocol,  	x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE;  	x25->facilities.pacsize_in  = X25_DEFAULT_PACKET_SIZE;  	x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; -	x25->facilities.throughput  = X25_DEFAULT_THROUGHPUT; +	x25->facilities.throughput  = 0;	/* by default don't negotiate +						   throughput */  	x25->facilities.reverse     = X25_DEFAULT_REVERSE;  	x25->dte_facilities.calling_len = 0;  	x25->dte_facilities.called_len = 0; @@ -921,16 +959,26 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,  	/*  	 *	Extract the X.25 addresses and convert them to ASCII strings,  	 *	and remove them. +	 * +	 *	Address block is mandatory in call request packets  	 */ -	addr_len = x25_addr_ntoa(skb->data, &source_addr, &dest_addr); +	addr_len = x25_parse_address_block(skb, &source_addr, &dest_addr); +	if (addr_len <= 0) +		goto out_clear_request;  	skb_pull(skb, addr_len);  	/*  	 *	Get the length of the facilities, skip past them for the moment  	 *	get the call user data because this is needed to determine  	 *	the correct listener +	 * +	 *	Facilities length is mandatory in call request packets  	 */ +	if (skb->len < 1) +		goto out_clear_request;  	len = skb->data[0] + 1; +	if (skb->len < len) +		goto out_clear_request;  	skb_pull(skb,len);  	/* @@ -1414,9 +1462,20 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)  			if (facilities.winsize_in < 1 ||  			    facilities.winsize_in > 127)  				break; -			if (facilities.throughput < 0x03 || -			    facilities.throughput > 0xDD) -				break; +			if (facilities.throughput) { +				int out = facilities.throughput & 0xf0; +				int in  = facilities.throughput & 0x0f; +				if (!out) +					facilities.throughput |= +						X25_DEFAULT_THROUGHPUT << 4; +				else if (out < 0x30 || out > 0xD0) +					break; +				if (!in) +					facilities.throughput |= +						X25_DEFAULT_THROUGHPUT; +				else if (in < 0x03 || in > 0x0D) +					break; +			}  			if (facilities.reverse &&  				(facilities.reverse & 0x81) != 0x81)  				break; diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c index 3e1efe53464..b9ef682230a 100644 --- a/net/x25/x25_dev.c +++ b/net/x25/x25_dev.c @@ -20,6 +20,7 @@  #include <linux/kernel.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <linux/if_arp.h>  #include <net/x25.h> @@ -53,7 +54,7 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb)  		if (!sock_owned_by_user(sk)) {  			queued = x25_process_rx_frame(sk, skb);  		} else { -			sk_add_backlog(sk, skb); +			queued = !sk_add_backlog(sk, skb);  		}  		bh_unlock_sock(sk);  		sock_put(sk); diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index a21f6646eb3..771bab00754 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c @@ -35,7 +35,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,  		struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask)  {  	unsigned char *p = skb->data; -	unsigned int len = *p++; +	unsigned int len;  	*vc_fac_mask = 0; @@ -50,6 +50,14 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,  	memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae));  	memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); +	if (skb->len < 1) +		return 0; + +	len = *p++; + +	if (len >= skb->len) +		return -1; +  	while (len > 0) {  		switch (*p & X25_FAC_CLASS_MASK) {  		case X25_FAC_CLASS_A: @@ -247,6 +255,8 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,  	memcpy(new, ours, sizeof(*new));  	len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask); +	if (len < 0) +		return len;  	/*  	 *	They want reverse charging, we won't accept it. @@ -259,9 +269,18 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,  	new->reverse = theirs.reverse;  	if (theirs.throughput) { -		if (theirs.throughput < ours->throughput) { -			SOCK_DEBUG(sk, "X.25: throughput negotiated down\n"); -			new->throughput = theirs.throughput; +		int theirs_in =  theirs.throughput & 0x0f; +		int theirs_out = theirs.throughput & 0xf0; +		int ours_in  = ours->throughput & 0x0f; +		int ours_out = ours->throughput & 0xf0; +		if (!ours_in || theirs_in < ours_in) { +			SOCK_DEBUG(sk, "X.25: inbound throughput negotiated\n"); +			new->throughput = (new->throughput & 0xf0) | theirs_in; +		} +		if (!ours_out || theirs_out < ours_out) { +			SOCK_DEBUG(sk, +				"X.25: outbound throughput negotiated\n"); +			new->throughput = (new->throughput & 0x0f) | theirs_out;  		}  	} diff --git a/net/x25/x25_forward.c b/net/x25/x25_forward.c index 056a55f3a87..25a81079396 100644 --- a/net/x25/x25_forward.c +++ b/net/x25/x25_forward.c @@ -10,6 +10,7 @@   */  #include <linux/if_arp.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <net/x25.h>  LIST_HEAD(x25_forward_list); diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index 96d92278354..372ac226e64 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c @@ -23,6 +23,7 @@   *					  i-frames.   */ +#include <linux/slab.h>  #include <linux/errno.h>  #include <linux/kernel.h>  #include <linux/string.h> @@ -89,6 +90,7 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)  static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype)  {  	struct x25_address source_addr, dest_addr; +	int len;  	switch (frametype) {  		case X25_CALL_ACCEPTED: { @@ -106,11 +108,17 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp  			 *	Parse the data in the frame.  			 */  			skb_pull(skb, X25_STD_MIN_LEN); -			skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); -			skb_pull(skb, -				 x25_parse_facilities(skb, &x25->facilities, + +			len = x25_parse_address_block(skb, &source_addr, +						&dest_addr); +			if (len > 0) +				skb_pull(skb, len); + +			len = x25_parse_facilities(skb, &x25->facilities,  						&x25->dte_facilities, -						&x25->vc_facil_mask)); +						&x25->vc_facil_mask); +			if (len > 0) +				skb_pull(skb, len);  			/*  			 *	Copy any Call User Data.  			 */ diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c index e4e1b6e4953..73e7b954ad2 100644 --- a/net/x25/x25_link.c +++ b/net/x25/x25_link.c @@ -24,6 +24,7 @@  #include <linux/kernel.h>  #include <linux/jiffies.h>  #include <linux/timer.h> +#include <linux/slab.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h>  #include <asm/uaccess.h> diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c index 2b96b52114d..52351a26b6f 100644 --- a/net/x25/x25_out.c +++ b/net/x25/x25_out.c @@ -22,6 +22,7 @@   *					needed cleaned seq-number fields.   */ +#include <linux/slab.h>  #include <linux/socket.h>  #include <linux/kernel.h>  #include <linux/string.h> diff --git a/net/x25/x25_route.c b/net/x25/x25_route.c index b95fae9ab39..97d77c532d8 100644 --- a/net/x25/x25_route.c +++ b/net/x25/x25_route.c @@ -19,6 +19,7 @@  #include <linux/if_arp.h>  #include <linux/init.h> +#include <linux/slab.h>  #include <net/x25.h>  LIST_HEAD(x25_route_list); diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c index 352b32d216f..dc20cf12f39 100644 --- a/net/x25/x25_subr.c +++ b/net/x25/x25_subr.c @@ -23,6 +23,7 @@   *						restriction on response.   */ +#include <linux/slab.h>  #include <linux/kernel.h>  #include <linux/string.h>  #include <linux/skbuff.h> diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c index 0fc5ff66d1f..fc91ad7ee26 100644 --- a/net/xfrm/xfrm_ipcomp.c +++ b/net/xfrm/xfrm_ipcomp.c @@ -17,11 +17,11 @@  #include <linux/crypto.h>  #include <linux/err.h> -#include <linux/gfp.h>  #include <linux/list.h>  #include <linux/module.h>  #include <linux/mutex.h>  #include <linux/percpu.h> +#include <linux/slab.h>  #include <linux/smp.h>  #include <linux/vmalloc.h>  #include <net/ip.h> diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index b9fe13138c0..6a329158bdf 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -14,6 +14,7 @@  #include <linux/netdevice.h>  #include <linux/netfilter.h>  #include <linux/skbuff.h> +#include <linux/slab.h>  #include <linux/spinlock.h>  #include <net/dst.h>  #include <net/xfrm.h> diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 34a5ef8316e..843e066649c 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1372,7 +1372,8 @@ static inline int xfrm_init_path(struct xfrm_dst *path, struct dst_entry *dst,  	return err;  } -static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev) +static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, +				struct flowi *fl)  {  	struct xfrm_policy_afinfo *afinfo =  		xfrm_policy_get_afinfo(xdst->u.dst.ops->family); @@ -1381,7 +1382,7 @@ static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev)  	if (!afinfo)  		return -EINVAL; -	err = afinfo->fill_dst(xdst, dev); +	err = afinfo->fill_dst(xdst, dev, fl);  	xfrm_policy_put_afinfo(afinfo); @@ -1486,7 +1487,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,  	for (dst_prev = dst0; dst_prev != dst; dst_prev = dst_prev->child) {  		struct xfrm_dst *xdst = (struct xfrm_dst *)dst_prev; -		err = xfrm_fill_dst(xdst, dev); +		err = xfrm_fill_dst(xdst, dev, fl);  		if (err)  			goto free_dst; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 17d5b96f2fc..add77ecb8ac 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -22,6 +22,7 @@  #include <linux/audit.h>  #include <asm/uaccess.h>  #include <linux/ktime.h> +#include <linux/slab.h>  #include <linux/interrupt.h>  #include <linux/kernel.h> diff --git a/net/xfrm/xfrm_sysctl.c b/net/xfrm/xfrm_sysctl.c index 2c4d6cdcba4..05640bc9594 100644 --- a/net/xfrm/xfrm_sysctl.c +++ b/net/xfrm/xfrm_sysctl.c @@ -1,4 +1,5 @@  #include <linux/sysctl.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/xfrm.h>  |