diff --git a/arch/x86_64/kernel/functionlist b/arch/x86_64/kernel/functionlist
index 2bcebdc3eedbc193546c7b28b26af627368dc306..01fa23580c85f4dd707f166dca06f49226924078 100644
--- a/arch/x86_64/kernel/functionlist
+++ b/arch/x86_64/kernel/functionlist
@@ -384,7 +384,6 @@
 *(.text.__end_that_request_first)
 *(.text.wake_up_bit)
 *(.text.unuse_mm)
-*(.text.skb_release_data)
 *(.text.shrink_icache_memory)
 *(.text.sched_balance_self)
 *(.text.__pmd_alloc)
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index fde9334059af595428f3f871599a538e3c3a29b0..a486eb1f1640207c29351a99cddd38ae4684fdca 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -1018,7 +1018,7 @@ he_init_irq(struct he_dev *he_dev)
 	return 0;
 }
 
-static int __init
+static int __devinit
 he_start(struct atm_dev *dev)
 {
 	struct he_dev *he_dev;
diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c
index 0aabfc2a59d9e42a574673772a34765dc64f5ab6..325325afabec839302521e16c09ec78532bdfeba 100644
--- a/drivers/atm/idt77105.c
+++ b/drivers/atm/idt77105.c
@@ -358,7 +358,7 @@ static const struct atmphy_ops idt77105_ops = {
 };
 
 
-int idt77105_init(struct atm_dev *dev)
+int __devinit idt77105_init(struct atm_dev *dev)
 {
 	dev->phy = &idt77105_ops;
 	return 0;
diff --git a/drivers/atm/idt77105.h b/drivers/atm/idt77105.h
index 8ba8218aaefe0c60a29ed2ba7111e27e1e6a66b1..3fd2bc8997618b787825a7e55deb5ff9240fdd45 100644
--- a/drivers/atm/idt77105.h
+++ b/drivers/atm/idt77105.h
@@ -76,7 +76,7 @@
 #define IDT77105_CTRSEL_RHEC	0x01	/* W, Rx HEC Error Counter */
 
 #ifdef __KERNEL__
-int idt77105_init(struct atm_dev *dev) __init;
+int idt77105_init(struct atm_dev *dev);
 #endif
 
 /*
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index 2e2e50e1167a3b59f31a809bfbea43992b19b478..333a7bc609d24b0337bdb2d928ebd8f3d2d57b56 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -2284,7 +2284,7 @@ static int reset_sar(struct atm_dev *dev)
 }  
 	  
 	  
-static int __init ia_init(struct atm_dev *dev)
+static int __devinit ia_init(struct atm_dev *dev)
 {  
 	IADEV *iadev;  
 	unsigned long real_base;
@@ -2480,7 +2480,7 @@ static void ia_free_rx(IADEV *iadev)
 			  iadev->rx_dle_dma);  
 }
 
-static int __init ia_start(struct atm_dev *dev)
+static int __devinit ia_start(struct atm_dev *dev)
 {  
 	IADEV *iadev;  
 	int error;  
diff --git a/drivers/atm/suni.c b/drivers/atm/suni.c
index b1d063cc4fbe0f6903359bf3328566e0e50aee93..f04f39c00833cc86dc572f6b00e32e8f0204c903 100644
--- a/drivers/atm/suni.c
+++ b/drivers/atm/suni.c
@@ -289,7 +289,7 @@ static const struct atmphy_ops suni_ops = {
 };
 
 
-int suni_init(struct atm_dev *dev)
+int __devinit suni_init(struct atm_dev *dev)
 {
 	unsigned char mri;
 
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 7635736cc791f6151c8f5f236050a51f430ebe9a..d55b0f7939a645a27ddc60082c466cfa5d7b6efd 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -57,8 +57,8 @@
 
 #define DRV_MODULE_NAME		"bnx2"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"1.4.42"
-#define DRV_MODULE_RELDATE	"June 12, 2006"
+#define DRV_MODULE_VERSION	"1.4.43"
+#define DRV_MODULE_RELDATE	"June 28, 2006"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -1676,7 +1676,7 @@ bnx2_tx_int(struct bnx2 *bp)
 
 		tx_free_bd += last + 1;
 
-		dev_kfree_skb_irq(skb);
+		dev_kfree_skb(skb);
 
 		hw_cons = bp->hw_tx_cons =
 			sblk->status_tx_quick_consumer_index0;
@@ -1824,7 +1824,7 @@ reuse_rx:
 		if ((len > (bp->dev->mtu + ETH_HLEN)) &&
 			(ntohs(skb->protocol) != 0x8100)) {
 
-			dev_kfree_skb_irq(skb);
+			dev_kfree_skb(skb);
 			goto next_rx;
 
 		}
@@ -3643,7 +3643,7 @@ bnx2_free_tx_skbs(struct bnx2 *bp)
 				skb_shinfo(skb)->frags[j].size,
 				PCI_DMA_TODEVICE);
 		}
-		dev_kfree_skb_any(skb);
+		dev_kfree_skb(skb);
 		i += j + 1;
 	}
 
@@ -3669,7 +3669,7 @@ bnx2_free_rx_skbs(struct bnx2 *bp)
 
 		rx_buf->skb = NULL;
 
-		dev_kfree_skb_any(skb);
+		dev_kfree_skb(skb);
 	}
 }
 
@@ -3999,7 +3999,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
 	udelay(5);
 
 	pci_unmap_single(bp->pdev, map, pkt_size, PCI_DMA_TODEVICE);
-	dev_kfree_skb_irq(skb);
+	dev_kfree_skb(skb);
 
 	if (bp->status_blk->status_tx_quick_consumer_index0 != bp->tx_prod) {
 		goto loopback_test_done;
@@ -4541,7 +4541,7 @@ bnx2_close(struct net_device *dev)
 	bnx2_netif_stop(bp);
 	del_timer_sync(&bp->timer);
 	if (bp->flags & NO_WOL_FLAG)
-		reset_code = BNX2_DRV_MSG_CODE_UNLOAD;
+		reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN;
 	else if (bp->wol)
 		reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
 	else
@@ -5128,6 +5128,16 @@ bnx2_set_rx_csum(struct net_device *dev, u32 data)
 	return 0;
 }
 
+static int
+bnx2_set_tso(struct net_device *dev, u32 data)
+{
+	if (data)
+		dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
+	else
+		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO_ECN);
+	return 0;
+}
+
 #define BNX2_NUM_STATS 46
 
 static struct {
@@ -5445,7 +5455,7 @@ static struct ethtool_ops bnx2_ethtool_ops = {
 	.set_sg			= ethtool_op_set_sg,
 #ifdef BCM_TSO
 	.get_tso		= ethtool_op_get_tso,
-	.set_tso		= ethtool_op_set_tso,
+	.set_tso		= bnx2_set_tso,
 #endif
 	.self_test_count	= bnx2_self_test_count,
 	.self_test		= bnx2_self_test,
@@ -5926,7 +5936,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 #endif
 #ifdef BCM_TSO
-	dev->features |= NETIF_F_TSO;
+	dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
 #endif
 
 	netif_carrier_off(bp->dev);
@@ -5968,7 +5978,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
 	netif_device_detach(dev);
 	del_timer_sync(&bp->timer);
 	if (bp->flags & NO_WOL_FLAG)
-		reset_code = BNX2_DRV_MSG_CODE_UNLOAD;
+		reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN;
 	else if (bp->wol)
 		reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
 	else
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 5845e334941b4f8e71ca80ad5c674bf7a7ffd5e9..658c5ee95c73ecdea4bd4c34c74e68e2b82b54bb 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -4174,6 +4174,7 @@ struct fw_info {
 #define BNX2_DRV_MSG_CODE_PULSE			 0x06000000
 #define BNX2_DRV_MSG_CODE_DIAG			 0x07000000
 #define BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL	 0x09000000
+#define BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN		 0x0b000000
 
 #define BNX2_DRV_MSG_DATA			 0x00ff0000
 #define BNX2_DRV_MSG_DATA_WAIT0			 0x00010000
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index d2ce4896abff24605d8b4ab37cf221f6e78f8107..e9e6d99a9add263619e2278f756b59ab29709aa4 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -350,7 +350,7 @@ config TOSHIBA_FIR
 
 config AU1000_FIR
 	tristate "Alchemy Au1000 SIR/FIR"
-	depends on MIPS_AU1000 && IRDA
+	depends on SOC_AU1000 && IRDA
 
 config SMC_IRCC_FIR
 	tristate "SMSC IrCC (EXPERIMENTAL)"
diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c
index 754297fc8f224f086fd52fe8597969576bb34001..47f6f64d604c980b2c5a553a5500a01fca4b1b78 100644
--- a/drivers/net/irda/mcs7780.c
+++ b/drivers/net/irda/mcs7780.c
@@ -101,7 +101,7 @@ static int transceiver_type = MCS_TSC_VISHAY;
 module_param(transceiver_type, int, 0444);
 MODULE_PARM_DESC(transceiver_type, "IR transceiver type, see mcs7780.h.");
 
-struct usb_driver mcs_driver = {
+static struct usb_driver mcs_driver = {
 	.name = "mcs7780",
 	.probe = mcs_probe,
 	.disconnect = mcs_disconnect,
diff --git a/include/asm-alpha/socket.h b/include/asm-alpha/socket.h
index b5193229132a12e5f73bfe510830aef1ab95235b..d22ab97ea72efc27e45ef4573498baef7c3a1059 100644
--- a/include/asm-alpha/socket.h
+++ b/include/asm-alpha/socket.h
@@ -51,6 +51,7 @@
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
 #define SO_PEERSEC		30
+#define SO_PASSSEC		34
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		19
diff --git a/include/asm-arm/socket.h b/include/asm-arm/socket.h
index 3c51da6438c95b6734e38243ebdbb21af5a6972a..19f7df702b069ebb8398dc3f2dc9d16d9564ec95 100644
--- a/include/asm-arm/socket.h
+++ b/include/asm-arm/socket.h
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN		30
 
 #define SO_PEERSEC		31
+#define SO_PASSSEC		34
 
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-arm26/socket.h b/include/asm-arm26/socket.h
index 3c51da6438c95b6734e38243ebdbb21af5a6972a..19f7df702b069ebb8398dc3f2dc9d16d9564ec95 100644
--- a/include/asm-arm26/socket.h
+++ b/include/asm-arm26/socket.h
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN		30
 
 #define SO_PEERSEC		31
+#define SO_PASSSEC		34
 
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-cris/socket.h b/include/asm-cris/socket.h
index 8b1da3e58c5580468f60961c498592b71c7f56c7..01cfdf1d6d339ab2f0b4a25649989e6cacfa9ea8 100644
--- a/include/asm-cris/socket.h
+++ b/include/asm-cris/socket.h
@@ -50,6 +50,7 @@
 #define SO_ACCEPTCONN          30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC		34
 
 #endif /* _ASM_SOCKET_H */
 
diff --git a/include/asm-frv/socket.h b/include/asm-frv/socket.h
index 7177f8b9817cc3586bf6c4bd4b21662ed32d2d72..31db18fc871fa07af87aad3a932eac3a46003362 100644
--- a/include/asm-frv/socket.h
+++ b/include/asm-frv/socket.h
@@ -48,6 +48,7 @@
 #define SO_ACCEPTCONN		30
 
 #define SO_PEERSEC		31
+#define SO_PASSSEC		34
 
 #endif /* _ASM_SOCKET_H */
 
diff --git a/include/asm-h8300/socket.h b/include/asm-h8300/socket.h
index d98cf85bafc1d667d9d2ebdac62752a7da267214..ebc830fee0d0888ce1f3e938d06d1d1832205ac4 100644
--- a/include/asm-h8300/socket.h
+++ b/include/asm-h8300/socket.h
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN		30
 
 #define SO_PEERSEC		31
+#define SO_PASSSEC		34
 
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-i386/socket.h b/include/asm-i386/socket.h
index 802ae76195b72a4a09e3f9c052e96968389be694..5755d57c4e952c121a0a215c94778cbf1c1386e6 100644
--- a/include/asm-i386/socket.h
+++ b/include/asm-i386/socket.h
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN		30
 
 #define SO_PEERSEC		31
+#define SO_PASSSEC		34
 
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-ia64/socket.h b/include/asm-ia64/socket.h
index a255006fb7b51f0db085e82f547f25938ee7c84c..d638ef3d50c3a5767a7d6a50496d47775c2145dc 100644
--- a/include/asm-ia64/socket.h
+++ b/include/asm-ia64/socket.h
@@ -57,5 +57,6 @@
 #define SO_ACCEPTCONN		30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC		34
 
 #endif /* _ASM_IA64_SOCKET_H */
diff --git a/include/asm-m32r/socket.h b/include/asm-m32r/socket.h
index 8b6680f223c0b4a5f18781f36129cc1d541b68f8..acdf748fcdc8a38220ffea31e946947ca671bee1 100644
--- a/include/asm-m32r/socket.h
+++ b/include/asm-m32r/socket.h
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN		30
 
 #define SO_PEERSEC		31
+#define SO_PASSSEC		34
 
 #endif /* _ASM_M32R_SOCKET_H */
diff --git a/include/asm-m68k/socket.h b/include/asm-m68k/socket.h
index f578ca4b776a3bfcb45b1e60781ebeb74eac785c..a5966ec005ae67d1bdb338aa209f1cf76f85bf78 100644
--- a/include/asm-m68k/socket.h
+++ b/include/asm-m68k/socket.h
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN		30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC		34
 
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-mips/socket.h b/include/asm-mips/socket.h
index 0bb31e5aaca6a23f93ffcf7aaa02ae41118e6be5..36ebe4e186a7a635970909c46f03cd8b394bc367 100644
--- a/include/asm-mips/socket.h
+++ b/include/asm-mips/socket.h
@@ -69,6 +69,7 @@ To add: #define SO_REUSEPORT 0x0200	/* Allow local address and port reuse.  */
 #define SO_PEERSEC		30
 #define SO_SNDBUFFORCE		31
 #define SO_RCVBUFFORCE		33
+#define SO_PASSSEC		34
 
 #ifdef __KERNEL__
 
diff --git a/include/asm-parisc/socket.h b/include/asm-parisc/socket.h
index 1bf54dc53c101337200deeaafa7adcf27daf97ff..ce2eae1708b5ec84ad7976c83984c35ceb5b2122 100644
--- a/include/asm-parisc/socket.h
+++ b/include/asm-parisc/socket.h
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN		0x401c
 
 #define SO_PEERSEC		0x401d
+#define SO_PASSSEC		0x401e
 
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-powerpc/socket.h b/include/asm-powerpc/socket.h
index e4b8177d4acc48313dbb905bbf59400d659f0253..c8b1da50e72db7df8be5c61b36d8f6694461fd55 100644
--- a/include/asm-powerpc/socket.h
+++ b/include/asm-powerpc/socket.h
@@ -55,5 +55,6 @@
 #define SO_ACCEPTCONN		30
 
 #define SO_PEERSEC		31
+#define SO_PASSSEC		34
 
 #endif	/* _ASM_POWERPC_SOCKET_H */
diff --git a/include/asm-s390/socket.h b/include/asm-s390/socket.h
index 15a5298c8744bf1401be8b0cb736b406b410d55d..1778a49a74c5b0fd24facee8d5d49fc3657f3600 100644
--- a/include/asm-s390/socket.h
+++ b/include/asm-s390/socket.h
@@ -56,5 +56,6 @@
 #define SO_ACCEPTCONN		30
 
 #define SO_PEERSEC		31
+#define SO_PASSSEC		34
 
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-sh/socket.h b/include/asm-sh/socket.h
index 553904ff9336c2e26304810e0f0db20e0f4a4220..ca70362eb563bf7224d743340dde1364dc824242 100644
--- a/include/asm-sh/socket.h
+++ b/include/asm-sh/socket.h
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN		30
 
 #define SO_PEERSEC		31
+#define SO_PASSSEC		34
 
 #endif /* __ASM_SH_SOCKET_H */
diff --git a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h
index 4e0ce3a35ea9d48b62a5195b49daba535fa1e596..f6c4e5baf3f7bd4ea9c065b25c9d49d723de1ace 100644
--- a/include/asm-sparc/socket.h
+++ b/include/asm-sparc/socket.h
@@ -48,6 +48,7 @@
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
 #define SO_PEERSEC		0x001e
+#define SO_PASSSEC		0x001f
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		0x5001
diff --git a/include/asm-sparc64/socket.h b/include/asm-sparc64/socket.h
index 59987dad3359912059a37039512dafc807c5d2df..754d46a50af30af85564808262592cc16f59fe48 100644
--- a/include/asm-sparc64/socket.h
+++ b/include/asm-sparc64/socket.h
@@ -48,6 +48,7 @@
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
 #define SO_PEERSEC		0x001e
+#define SO_PASSSEC		0x001f
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		0x5001
diff --git a/include/asm-v850/socket.h b/include/asm-v850/socket.h
index 0240d366a0a4db32672c6e20c734efe21e32aa17..0dfe55ac2ef2acf1deeb4e72e8ca112a770d8c8a 100644
--- a/include/asm-v850/socket.h
+++ b/include/asm-v850/socket.h
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN		30
 
 #define SO_PEERSEC		31
+#define SO_PASSSEC		34
 
 #endif /* __V850_SOCKET_H__ */
diff --git a/include/asm-x86_64/socket.h b/include/asm-x86_64/socket.h
index f2cdbeae5d5ba17e453f24aa172f6076f9441f9b..b46702607933ddedf9e5dc323da8d4c787799e94 100644
--- a/include/asm-x86_64/socket.h
+++ b/include/asm-x86_64/socket.h
@@ -48,5 +48,6 @@
 #define SO_ACCEPTCONN		30
 
 #define SO_PEERSEC             31
+#define SO_PASSSEC		34
 
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-xtensa/socket.h b/include/asm-xtensa/socket.h
index 00f83f3a6d72194ad0b0f3059897cecde2d61e0f..971d231be60ebe095f9a5b29e21831662df2e1f8 100644
--- a/include/asm-xtensa/socket.h
+++ b/include/asm-xtensa/socket.h
@@ -59,5 +59,6 @@
 
 #define SO_ACCEPTCONN		30
 #define SO_PEERSEC		31
+#define SO_PASSSEC		34
 
 #endif	/* _XTENSA_SOCKET_H */
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index 1eb238affb124fe8d657cda89f55b2a627142eb8..41788a31c4382b86698cf7a16875588d470bf069 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -7,6 +7,7 @@
 #define LINUX_ATMDEV_H
 
 
+#include <linux/device.h>
 #include <linux/atmapi.h>
 #include <linux/atm.h>
 #include <linux/atmioc.h>
@@ -358,6 +359,7 @@ struct atm_dev {
 	struct proc_dir_entry *proc_entry; /* proc entry */
 	char *proc_name;		/* proc entry name */
 #endif
+	struct class_device class_dev;	/* sysfs class device */
 	struct list_head dev_list;	/* linkage */
 };
 
@@ -459,7 +461,7 @@ static inline void atm_dev_put(struct atm_dev *dev)
 		BUG_ON(!test_bit(ATM_DF_REMOVED, &dev->flags));
 		if (dev->ops->dev_close)
 			dev->ops->dev_close(dev);
-		kfree(dev);
+		class_device_put(&dev->class_dev);
 	}
 }
 
diff --git a/include/linux/net.h b/include/linux/net.h
index 385e68f5bd93264c96f1e29c3f720f3b3921a8be..b20c53c744130384ae7ad28a9b8a6d1bdf5ff716 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -61,6 +61,7 @@ typedef enum {
 #define SOCK_ASYNC_WAITDATA	1
 #define SOCK_NOSPACE		2
 #define SOCK_PASSCRED		3
+#define SOCK_PASSSEC		4
 
 #ifndef ARCH_HAS_SOCKET_TYPES
 /**
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 03cd7551a7a100b2ba0079f40b26e957e531b5cf..aa2d3c12c4d80cffdb6a011ee1d01a0ca57f8af9 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -315,6 +315,8 @@ struct net_device
 #define NETIF_F_GSO_SHIFT	16
 #define NETIF_F_TSO		(SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
 #define NETIF_F_UFO		(SKB_GSO_UDPV4 << NETIF_F_GSO_SHIFT)
+#define NETIF_F_GSO_ROBUST	(SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
+#define NETIF_F_TSO_ECN		(SKB_GSO_TCPV4_ECN << NETIF_F_GSO_SHIFT)
 
 #define NETIF_F_GEN_CSUM	(NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
 #define NETIF_F_ALL_CSUM	(NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
@@ -543,7 +545,8 @@ struct packet_type {
 					 struct net_device *,
 					 struct packet_type *,
 					 struct net_device *);
-	struct sk_buff		*(*gso_segment)(struct sk_buff *skb, int sg);
+	struct sk_buff		*(*gso_segment)(struct sk_buff *skb,
+						int features);
 	void			*af_packet_priv;
 	struct list_head	list;
 };
@@ -968,7 +971,7 @@ extern int		netdev_max_backlog;
 extern int		weight_p;
 extern int		netdev_set_master(struct net_device *dev, struct net_device *master);
 extern int skb_checksum_help(struct sk_buff *skb, int inward);
-extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg);
+extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features);
 #ifdef CONFIG_BUG
 extern void netdev_rx_csum_fault(struct net_device *dev);
 #else
@@ -988,11 +991,16 @@ extern void dev_seq_stop(struct seq_file *seq, void *v);
 
 extern void linkwatch_run_queue(void);
 
+static inline int skb_gso_ok(struct sk_buff *skb, int features)
+{
+	int feature = skb_shinfo(skb)->gso_size ?
+		      skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0;
+	return (features & feature) == feature;
+}
+
 static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
 {
-	int feature = skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT;
-	return skb_shinfo(skb)->gso_size &&
-	       (dev->features & feature) != feature;
+	return !skb_gso_ok(skb, dev->features);
 }
 
 #endif /* __KERNEL__ */
diff --git a/include/linux/security.h b/include/linux/security.h
index 51805806f9741bf63da2d7d344f05a9ee7cf3821..c7ea15716dce5cdcc5c293c120471a99248fa669 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -67,7 +67,7 @@ struct xfrm_state;
 struct xfrm_user_sec_ctx;
 
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
-extern int cap_netlink_recv(struct sk_buff *skb);
+extern int cap_netlink_recv(struct sk_buff *skb, int cap);
 
 /*
  * Values used in the task_security_ops calls
@@ -656,6 +656,7 @@ struct swap_info_struct;
  *	Check permission before processing the received netlink message in
  *	@skb.
  *	@skb contains the sk_buff structure for the netlink message.
+ *	@cap indicates the capability required
  *	Return 0 if permission is granted.
  *
  * Security hooks for Unix domain networking.
@@ -1266,7 +1267,7 @@ struct security_operations {
 			  struct sembuf * sops, unsigned nsops, int alter);
 
 	int (*netlink_send) (struct sock * sk, struct sk_buff * skb);
-	int (*netlink_recv) (struct sk_buff * skb);
+	int (*netlink_recv) (struct sk_buff * skb, int cap);
 
 	/* allow module stacking */
 	int (*register_security) (const char *name,
@@ -2032,9 +2033,9 @@ static inline int security_netlink_send(struct sock *sk, struct sk_buff * skb)
 	return security_ops->netlink_send(sk, skb);
 }
 
-static inline int security_netlink_recv(struct sk_buff * skb)
+static inline int security_netlink_recv(struct sk_buff * skb, int cap)
 {
-	return security_ops->netlink_recv(skb);
+	return security_ops->netlink_recv(skb, cap);
 }
 
 /* prototypes */
@@ -2670,9 +2671,9 @@ static inline int security_netlink_send (struct sock *sk, struct sk_buff *skb)
 	return cap_netlink_send (sk, skb);
 }
 
-static inline int security_netlink_recv (struct sk_buff *skb)
+static inline int security_netlink_recv (struct sk_buff *skb, int cap)
 {
-	return cap_netlink_recv (skb);
+	return cap_netlink_recv (skb, cap);
 }
 
 static inline struct dentry *securityfs_create_dir(const char *name,
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 16eef03ce0eb2dba578c52cc136e1b80b068fa99..59918be91d0a95c203e43356ae95371861e97132 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -172,6 +172,12 @@ enum {
 enum {
 	SKB_GSO_TCPV4 = 1 << 0,
 	SKB_GSO_UDPV4 = 1 << 1,
+
+	/* This indicates the skb is from an untrusted source. */
+	SKB_GSO_DODGY = 1 << 2,
+
+	/* This indicates the tcp segment has CWR set. */
+	SKB_GSO_TCPV4_ECN = 1 << 3,
 };
 
 /** 
@@ -1298,8 +1304,7 @@ extern void	       skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
 extern void	       skb_split(struct sk_buff *skb,
 				 struct sk_buff *skb1, const u32 len);
 
-extern void	       skb_release_data(struct sk_buff *skb);
-extern struct sk_buff *skb_segment(struct sk_buff *skb, int sg);
+extern struct sk_buff *skb_segment(struct sk_buff *skb, int features);
 
 static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
 				       int len, void *buffer)
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 795f81f9ec7ff9c4e064e085d6c491d351a39f19..5ba72d95280c3f87a4aa3f434805e375f69dc9e6 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -53,10 +53,16 @@ struct unix_address {
 struct unix_skb_parms {
 	struct ucred		creds;		/* Skb credentials	*/
 	struct scm_fp_list	*fp;		/* Passed files		*/
+#ifdef CONFIG_SECURITY_NETWORK
+	char			*secdata;	/* Security context	*/
+	u32			seclen;		/* Security length	*/
+#endif
 };
 
 #define UNIXCB(skb) 	(*(struct unix_skb_parms*)&((skb)->cb))
 #define UNIXCREDS(skb)	(&UNIXCB((skb)).creds)
+#define UNIXSECDATA(skb)	(&UNIXCB((skb)).secdata)
+#define UNIXSECLEN(skb)		(&UNIXCB((skb)).seclen)
 
 #define unix_state_rlock(s)	spin_lock(&unix_sk(s)->lock)
 #define unix_state_runlock(s)	spin_unlock(&unix_sk(s)->lock)
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index 75b5b9333fc75cc3b4289c80870b8a77ed6f0892..1925c65e617b9eddae6e199f660a72232e750235 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -169,17 +169,23 @@ psched_tod_diff(int delta_sec, int bound)
 
 #define PSCHED_TADD2(tv, delta, tv_res) \
 ({ \
-	   int __delta = (tv).tv_usec + (delta); \
-	   (tv_res).tv_sec = (tv).tv_sec; \
-	   if (__delta > USEC_PER_SEC) { (tv_res).tv_sec++; __delta -= USEC_PER_SEC; } \
+	   int __delta = (delta); \
+	   (tv_res) = (tv); \
+	   while(__delta >= USEC_PER_SEC){ \
+		 (tv_res).tv_sec++; \
+		 __delta -= USEC_PER_SEC; \
+	   } \
 	   (tv_res).tv_usec = __delta; \
 })
 
 #define PSCHED_TADD(tv, delta) \
 ({ \
-	   (tv).tv_usec += (delta); \
-	   if ((tv).tv_usec > USEC_PER_SEC) { (tv).tv_sec++; \
-		 (tv).tv_usec -= USEC_PER_SEC; } \
+	   int __delta = (delta); \
+	   while(__delta >= USEC_PER_SEC){ \
+		 (tv).tv_sec++; \
+		 __delta -= USEC_PER_SEC; \
+	   } \
+	   (tv).tv_usec = __delta; \
 })
 
 /* Set/check that time is in the "past perfect";
diff --git a/include/net/protocol.h b/include/net/protocol.h
index 3b6dc15c68a58fcd0c19996a4f058a1f6879588b..40b6b9c9973f5dd2756fd3dc4c6439d7676784e6 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -36,7 +36,8 @@
 struct net_protocol {
 	int			(*handler)(struct sk_buff *skb);
 	void			(*err_handler)(struct sk_buff *skb, u32 info);
-	struct sk_buff	       *(*gso_segment)(struct sk_buff *skb, int sg);
+	struct sk_buff	       *(*gso_segment)(struct sk_buff *skb,
+					       int features);
 	int			no_policy;
 };
 
diff --git a/include/net/scm.h b/include/net/scm.h
index 540619cb7160f20e590471110ce63811c1d6e267..02daa097cdcd0cefcf81be18e75667a910ccf1a6 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -19,6 +19,10 @@ struct scm_cookie
 {
 	struct ucred		creds;		/* Skb credentials	*/
 	struct scm_fp_list	*fp;		/* Passed files		*/
+#ifdef CONFIG_SECURITY_NETWORK
+	char			*secdata;	/* Security context	*/
+	u32			seclen;		/* Security length	*/
+#endif
 	unsigned long		seq;		/* Connection seqno	*/
 };
 
@@ -48,6 +52,17 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
 	return __scm_send(sock, msg, scm);
 }
 
+#ifdef CONFIG_SECURITY_NETWORK
+static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
+{
+	if (test_bit(SOCK_PASSSEC, &sock->flags) && scm->secdata != NULL)
+		put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, scm->seclen, scm->secdata);
+}
+#else
+static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
+{ }
+#endif /* CONFIG_SECURITY_NETWORK */
+
 static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
 				struct scm_cookie *scm, int flags)
 {
@@ -62,6 +77,8 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
 	if (test_bit(SOCK_PASSCRED, &sock->flags))
 		put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
 
+	scm_passec(sock, msg, scm);
+
 	if (!scm->fp)
 		return;
 	
diff --git a/include/net/sock.h b/include/net/sock.h
index 2d8d6adf16161b9dff029cfee3418e66b77d5f1f..7136bae48c2f1d98977542f253d7b0b97a055829 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -383,7 +383,6 @@ enum sock_flags {
 	SOCK_USE_WRITE_QUEUE, /* whether to call sk->sk_write_space in sock_wfree */
 	SOCK_DBG, /* %SO_DEBUG setting */
 	SOCK_RCVTSTAMP, /* %SO_TIMESTAMP setting */
-	SOCK_NO_LARGESEND, /* whether to sent large segments or not */
 	SOCK_LOCALROUTE, /* route locally only, %SO_DONTROUTE setting */
 	SOCK_QUEUE_SHRUNK, /* write queue has been shrunk recently */
 };
@@ -1033,7 +1032,7 @@ static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
 	if (sk->sk_route_caps & NETIF_F_GSO)
 		sk->sk_route_caps |= NETIF_F_TSO;
 	if (sk->sk_route_caps & NETIF_F_TSO) {
-		if (sock_flag(sk, SOCK_NO_LARGESEND) || dst->header_len)
+		if (dst->header_len)
 			sk->sk_route_caps &= ~NETIF_F_TSO;
 		else 
 			sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index ca3d38dfc00bb3911c697dea4a936f36b1edd067..624921e763329d952cf5b68805cc75ca20399d5c 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1086,7 +1086,7 @@ extern struct request_sock_ops tcp_request_sock_ops;
 
 extern int tcp_v4_destroy_sock(struct sock *sk);
 
-extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg);
+extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features);
 
 #ifdef CONFIG_PROC_FS
 extern int  tcp4_proc_init(void);
diff --git a/include/net/tcp_ecn.h b/include/net/tcp_ecn.h
index c6b84397448dac0b810079c96fe1c642773b16fd..7bb366f70934787e19b7dfa2f0ddd05895cd12a0 100644
--- a/include/net/tcp_ecn.h
+++ b/include/net/tcp_ecn.h
@@ -31,10 +31,9 @@ static inline void TCP_ECN_send_syn(struct sock *sk, struct tcp_sock *tp,
 				    struct sk_buff *skb)
 {
 	tp->ecn_flags = 0;
-	if (sysctl_tcp_ecn && !(sk->sk_route_caps & NETIF_F_TSO)) {
+	if (sysctl_tcp_ecn) {
 		TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_ECE|TCPCB_FLAG_CWR;
 		tp->ecn_flags = TCP_ECN_OK;
-		sock_set_flag(sk, SOCK_NO_LARGESEND);
 	}
 }
 
@@ -56,6 +55,9 @@ static inline void TCP_ECN_send(struct sock *sk, struct tcp_sock *tp,
 			if (tp->ecn_flags&TCP_ECN_QUEUE_CWR) {
 				tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR;
 				skb->h.th->cwr = 1;
+				if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
+					skb_shinfo(skb)->gso_type |=
+						SKB_GSO_TCPV4_ECN;
 			}
 		} else {
 			/* ACK or retransmitted segment: clear ECT|CE */
diff --git a/kernel/audit.c b/kernel/audit.c
index 82443fb433efcb9d550126be82dabf80c0308c23..d417ca1db79b02fc3cb2d30a3a2122494afd0f14 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -445,7 +445,7 @@ void audit_send_reply(int pid, int seq, int type, int done, int multi,
  * Check for appropriate CAP_AUDIT_ capabilities on incoming audit
  * control messages.
  */
-static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type)
+static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
 {
 	int err = 0;
 
@@ -459,13 +459,13 @@ static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type)
 	case AUDIT_DEL:
 	case AUDIT_DEL_RULE:
 	case AUDIT_SIGNAL_INFO:
-		if (!cap_raised(eff_cap, CAP_AUDIT_CONTROL))
+		if (security_netlink_recv(skb, CAP_AUDIT_CONTROL))
 			err = -EPERM;
 		break;
 	case AUDIT_USER:
 	case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
 	case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2:
-		if (!cap_raised(eff_cap, CAP_AUDIT_WRITE))
+		if (security_netlink_recv(skb, CAP_AUDIT_WRITE))
 			err = -EPERM;
 		break;
 	default:  /* bad msg */
@@ -488,7 +488,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 	char			*ctx;
 	u32			len;
 
-	err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
+	err = audit_netlink_ok(skb, msg_type);
 	if (err)
 		return err;
 
diff --git a/net/atm/Makefile b/net/atm/Makefile
index d5818751f6ba43d5f7c3ec414c2f8ffe55b13118..89656d6c0b90d3f9310cbf4b5733f1a24102d25a 100644
--- a/net/atm/Makefile
+++ b/net/atm/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the ATM Protocol Families.
 #
 
-atm-y		:= addr.o pvc.o signaling.o svc.o ioctl.o common.o atm_misc.o raw.o resources.o
+atm-y		:= addr.o pvc.o signaling.o svc.o ioctl.o common.o atm_misc.o raw.o resources.o atm_sysfs.o
 mpoa-objs	:= mpc.o mpoa_caches.o mpoa_proc.o
 
 obj-$(CONFIG_ATM) += atm.o
diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c
new file mode 100644
index 0000000000000000000000000000000000000000..5df4b9a068bb2e103315b1e9858c764aea5b06d8
--- /dev/null
+++ b/net/atm/atm_sysfs.c
@@ -0,0 +1,176 @@
+/* ATM driver model support. */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/kobject.h>
+#include <linux/atmdev.h>
+#include "common.h"
+#include "resources.h"
+
+#define to_atm_dev(cldev) container_of(cldev, struct atm_dev, class_dev)
+
+static ssize_t show_type(struct class_device *cdev, char *buf)
+{
+	struct atm_dev *adev = to_atm_dev(cdev);
+	return sprintf(buf, "%s\n", adev->type);
+}
+
+static ssize_t show_address(struct class_device *cdev, char *buf)
+{
+	char *pos = buf;
+	struct atm_dev *adev = to_atm_dev(cdev);
+	int i;
+
+	for (i = 0; i < (ESI_LEN - 1); i++)
+		pos += sprintf(pos, "%02x:", adev->esi[i]);
+	pos += sprintf(pos, "%02x\n", adev->esi[i]);
+
+	return pos - buf;
+}
+
+static ssize_t show_atmaddress(struct class_device *cdev, char *buf)
+{
+        unsigned long flags;
+	char *pos = buf;
+	struct atm_dev *adev = to_atm_dev(cdev);
+        struct atm_dev_addr *aaddr;
+	int bin[] = { 1, 2, 10, 6, 1 }, *fmt = bin;
+	int i, j;
+
+        spin_lock_irqsave(&adev->lock, flags);
+        list_for_each_entry(aaddr, &adev->local, entry) {
+		for(i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) {
+			if (j == *fmt) {
+				pos += sprintf(pos, ".");
+				++fmt;
+				j = 0;
+			}
+			pos += sprintf(pos, "%02x", aaddr->addr.sas_addr.prv[i]);
+		}
+		pos += sprintf(pos, "\n");
+	}
+        spin_unlock_irqrestore(&adev->lock, flags);
+
+	return pos - buf;
+}
+
+static ssize_t show_carrier(struct class_device *cdev, char *buf)
+{
+	char *pos = buf;
+	struct atm_dev *adev = to_atm_dev(cdev);
+
+	pos += sprintf(pos, "%d\n",
+		       adev->signal == ATM_PHY_SIG_LOST ? 0 : 1);
+		
+	return pos - buf;
+}
+
+static ssize_t show_link_rate(struct class_device *cdev, char *buf)
+{
+	char *pos = buf;
+	struct atm_dev *adev = to_atm_dev(cdev);
+	int link_rate;
+
+	/* show the link rate, not the data rate */
+	switch (adev->link_rate) {
+		case ATM_OC3_PCR:
+			link_rate = 155520000;
+			break;
+		case ATM_OC12_PCR:
+			link_rate = 622080000;
+			break;
+		case ATM_25_PCR:
+			link_rate = 25600000;
+			break;
+		default:
+			link_rate = adev->link_rate * 8 * 53;
+	}
+	pos += sprintf(pos, "%d\n", link_rate);
+		
+	return pos - buf;
+}
+
+static CLASS_DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
+static CLASS_DEVICE_ATTR(atmaddress, S_IRUGO, show_atmaddress, NULL);
+static CLASS_DEVICE_ATTR(carrier, S_IRUGO, show_carrier, NULL);
+static CLASS_DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
+static CLASS_DEVICE_ATTR(link_rate, S_IRUGO, show_link_rate, NULL);
+
+static struct class_device_attribute *atm_attrs[] = {
+	&class_device_attr_atmaddress,
+	&class_device_attr_address,
+	&class_device_attr_carrier,
+	&class_device_attr_type,
+	&class_device_attr_link_rate,
+	NULL
+};
+
+static int atm_uevent(struct class_device *cdev, char **envp, int num_envp, char *buf, int size)
+{
+	struct atm_dev *adev;
+	int i = 0, len = 0;
+
+	if (!cdev)
+		return -ENODEV;
+
+	adev = to_atm_dev(cdev);
+	if (!adev)
+		return -ENODEV;
+
+	if (add_uevent_var(envp, num_envp, &i, buf, size, &len,
+			   "NAME=%s%d", adev->type, adev->number))
+		return -ENOMEM;
+
+	envp[i] = NULL;
+	return 0;
+}
+
+static void atm_release(struct class_device *cdev)
+{
+	struct atm_dev *adev = to_atm_dev(cdev);
+
+	kfree(adev);
+}
+
+static struct class atm_class = {
+	.name		= "atm",
+	.release	= atm_release,
+	.uevent		= atm_uevent,
+};
+
+int atm_register_sysfs(struct atm_dev *adev)
+{
+	struct class_device *cdev = &adev->class_dev;
+	int i, err;
+
+	cdev->class = &atm_class;
+	class_set_devdata(cdev, adev);
+
+	snprintf(cdev->class_id, BUS_ID_SIZE, "%s%d", adev->type, adev->number);
+	err = class_device_register(cdev);
+	if (err < 0)
+		return err;
+
+	for (i = 0; atm_attrs[i]; i++)
+		class_device_create_file(cdev, atm_attrs[i]);
+
+	return 0;
+}
+
+void atm_unregister_sysfs(struct atm_dev *adev)
+{
+	struct class_device *cdev = &adev->class_dev;
+
+	class_device_del(cdev);
+}
+
+int __init atm_sysfs_init(void)
+{
+	return class_register(&atm_class);
+}
+
+void __exit atm_sysfs_exit(void)
+{
+	class_unregister(&atm_class);
+}
diff --git a/net/atm/common.c b/net/atm/common.c
index ae002220fa99096aa00edc4ce0fd8df3e5c8694b..35ab1a61e831471407bb0462782cd08bd65a2eba 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -791,8 +791,14 @@ static int __init atm_init(void)
 		printk(KERN_ERR "atm_proc_init() failed with %d\n",error);
 		goto out_atmsvc_exit;
 	}
+        if ((error = atm_sysfs_init()) < 0) {
+		printk(KERN_ERR "atm_sysfs_init() failed with %d\n",error);
+		goto out_atmproc_exit;
+	}
 out:
 	return error;
+out_atmproc_exit:
+	atm_proc_exit();
 out_atmsvc_exit:
 	atmsvc_exit();
 out_atmpvc_exit:
@@ -805,6 +811,7 @@ out_unregister_vcc_proto:
 static void __exit atm_exit(void)
 {
 	atm_proc_exit();
+	atm_sysfs_exit();
 	atmsvc_exit();
 	atmpvc_exit();
 	proto_unregister(&vcc_proto);
diff --git a/net/atm/common.h b/net/atm/common.h
index 4887c317cefe99365576c2812875dc730257aa13..a422da7788fbd44852fadba2261c5c5f1cdd1c0e 100644
--- a/net/atm/common.h
+++ b/net/atm/common.h
@@ -28,6 +28,8 @@ int atmpvc_init(void);
 void atmpvc_exit(void);
 int atmsvc_init(void);
 void atmsvc_exit(void);
+int atm_sysfs_init(void);
+void atm_sysfs_exit(void);
 
 #ifdef CONFIG_PROC_FS
 int atm_proc_init(void);
diff --git a/net/atm/resources.c b/net/atm/resources.c
index 18ac80698f835906cab6cd9f45971892ef42d46b..534baf7040561448324537c50483d80fd97895b5 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -114,14 +114,27 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
 		printk(KERN_ERR "atm_dev_register: "
 		       "atm_proc_dev_register failed for dev %s\n",
 		       type);
-		mutex_unlock(&atm_dev_mutex);
-		kfree(dev);
-		return NULL;
+		goto out_fail;
+	}
+
+	if (atm_register_sysfs(dev) < 0) {
+		printk(KERN_ERR "atm_dev_register: "
+		       "atm_register_sysfs failed for dev %s\n",
+		       type);
+		atm_proc_dev_deregister(dev);
+		goto out_fail;
 	}
+
 	list_add_tail(&dev->dev_list, &atm_devs);
-	mutex_unlock(&atm_dev_mutex);
 
+out:
+	mutex_unlock(&atm_dev_mutex);
 	return dev;
+
+out_fail:
+	kfree(dev);
+	dev = NULL;
+	goto out;
 }
 
 
@@ -140,6 +153,7 @@ void atm_dev_deregister(struct atm_dev *dev)
 	mutex_unlock(&atm_dev_mutex);
 
 	atm_dev_release_vccs(dev);
+	atm_unregister_sysfs(dev);
 	atm_proc_dev_deregister(dev);
 
 	atm_dev_put(dev);
diff --git a/net/atm/resources.h b/net/atm/resources.h
index ac7222fee7a8e38db42aa066ca03a241ab323735..644989980c37f9b173cde5ca1ad3a5988922ff2a 100644
--- a/net/atm/resources.h
+++ b/net/atm/resources.h
@@ -43,4 +43,6 @@ static inline void atm_proc_dev_deregister(struct atm_dev *dev)
 
 #endif /* CONFIG_PROC_FS */
 
+int atm_register_sysfs(struct atm_dev *adev);
+void atm_unregister_sysfs(struct atm_dev *adev);
 #endif
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 2afdc7c0736c48b6baa39c5e9fa37987a7cdb779..f8dbcee80ebad7cdffb110fd87a8796db93643ab 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -184,6 +184,6 @@ void br_dev_setup(struct net_device *dev)
 	dev->set_mac_address = br_set_mac_address;
 	dev->priv_flags = IFF_EBRIDGE;
 
- 	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST
- 		| NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_NO_CSUM;
+ 	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
+ 			NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST;
 }
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 07956ecf545e313775967da4e48570bf33243732..f55ef682ef846e979b7e1b24569399a7c2fbd7da 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -392,7 +392,8 @@ void br_features_recompute(struct net_bridge *br)
 		features &= feature;
 	}
 
-	br->dev->features = features | checksum | NETIF_F_LLTX;
+	br->dev->features = features | checksum | NETIF_F_LLTX |
+			    NETIF_F_GSO_ROBUST;
 }
 
 /* called with RTNL */
diff --git a/net/core/dev.c b/net/core/dev.c
index f1c52cbd6ef7bfa8ae13ff04913b585b0c9be286..08976b08df5b6b6c4d6d88d029179b9f06f981b4 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1190,11 +1190,14 @@ out:
 /**
  *	skb_gso_segment - Perform segmentation on skb.
  *	@skb: buffer to segment
- *	@sg: whether scatter-gather is supported on the target.
+ *	@features: features for the output path (see dev->features)
  *
  *	This function segments the given skb and returns a list of segments.
+ *
+ *	It may return NULL if the skb requires no segmentation.  This is
+ *	only possible when GSO is used for verifying header integrity.
  */
-struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg)
+struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features)
 {
 	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
 	struct packet_type *ptype;
@@ -1210,12 +1213,14 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg)
 	rcu_read_lock();
 	list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
 		if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
-			segs = ptype->gso_segment(skb, sg);
+			segs = ptype->gso_segment(skb, features);
 			break;
 		}
 	}
 	rcu_read_unlock();
 
+	__skb_push(skb, skb->data - skb->mac.raw);
+
 	return segs;
 }
 
@@ -1234,7 +1239,6 @@ void netdev_rx_csum_fault(struct net_device *dev)
 EXPORT_SYMBOL(netdev_rx_csum_fault);
 #endif
 
-#ifdef CONFIG_HIGHMEM
 /* Actually, we should eliminate this check as soon as we know, that:
  * 1. IOMMU is present and allows to map all the memory.
  * 2. No high memory really exists on this machine.
@@ -1242,6 +1246,7 @@ EXPORT_SYMBOL(netdev_rx_csum_fault);
 
 static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
 {
+#ifdef CONFIG_HIGHMEM
 	int i;
 
 	if (dev->features & NETIF_F_HIGHDMA)
@@ -1251,11 +1256,9 @@ static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
 		if (PageHighMem(skb_shinfo(skb)->frags[i].page))
 			return 1;
 
+#endif
 	return 0;
 }
-#else
-#define illegal_highdma(dev, skb)	(0)
-#endif
 
 struct dev_gso_cb {
 	void (*destructor)(struct sk_buff *skb);
@@ -1291,9 +1294,15 @@ static int dev_gso_segment(struct sk_buff *skb)
 {
 	struct net_device *dev = skb->dev;
 	struct sk_buff *segs;
+	int features = dev->features & ~(illegal_highdma(dev, skb) ?
+					 NETIF_F_SG : 0);
+
+	segs = skb_gso_segment(skb, features);
+
+	/* Verifying header integrity only. */
+	if (!segs)
+		return 0;
 
-	segs = skb_gso_segment(skb, dev->features & NETIF_F_SG &&
-				    !illegal_highdma(dev, skb));
 	if (unlikely(IS_ERR(segs)))
 		return PTR_ERR(segs);
 
@@ -1310,13 +1319,17 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		if (netdev_nit)
 			dev_queue_xmit_nit(skb, dev);
 
-		if (!netif_needs_gso(dev, skb))
-			return dev->hard_start_xmit(skb, dev);
+		if (netif_needs_gso(dev, skb)) {
+			if (unlikely(dev_gso_segment(skb)))
+				goto out_kfree_skb;
+			if (skb->next)
+				goto gso;
+		}
 
-		if (unlikely(dev_gso_segment(skb)))
-			goto out_kfree_skb;
+		return dev->hard_start_xmit(skb, dev);
 	}
 
+gso:
 	do {
 		struct sk_buff *nskb = skb->next;
 		int rc;
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 3fcfa9c59e1fb75abfae6c9ad6c27f4cbda0f083..f25aac17497a7e79d8ed4cdcdbc6bdca18c54c8e 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -663,7 +663,7 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
 	sz_idx = type>>2;
 	kind = type&3;
 
-	if (kind != 2 && security_netlink_recv(skb)) {
+	if (kind != 2 && security_netlink_recv(skb, CAP_NET_ADMIN)) {
 		*errp = -EPERM;
 		return -1;
 	}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 6edbb90cbcec303605be4064b2f1da0d56e18eb3..a1c9ecf4f1e077c205a5e383cabce391b0243134 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -272,7 +272,7 @@ static void skb_clone_fraglist(struct sk_buff *skb)
 		skb_get(list);
 }
 
-void skb_release_data(struct sk_buff *skb)
+static void skb_release_data(struct sk_buff *skb)
 {
 	if (!skb->cloned ||
 	    !atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
@@ -1848,13 +1848,13 @@ EXPORT_SYMBOL_GPL(skb_pull_rcsum);
 /**
  *	skb_segment - Perform protocol segmentation on skb.
  *	@skb: buffer to segment
- *	@sg: whether scatter-gather can be used for generated segments
+ *	@features: features for the output path (see dev->features)
  *
  *	This function performs segmentation on the given skb.  It returns
  *	the segment at the given position.  It returns NULL if there are
  *	no more segments to generate, or when an error is encountered.
  */
-struct sk_buff *skb_segment(struct sk_buff *skb, int sg)
+struct sk_buff *skb_segment(struct sk_buff *skb, int features)
 {
 	struct sk_buff *segs = NULL;
 	struct sk_buff *tail = NULL;
@@ -1863,6 +1863,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int sg)
 	unsigned int offset = doffset;
 	unsigned int headroom;
 	unsigned int len;
+	int sg = features & NETIF_F_SG;
 	int nfrags = skb_shinfo(skb)->nr_frags;
 	int err = -ENOMEM;
 	int i = 0;
diff --git a/net/core/sock.c b/net/core/sock.c
index 5d820c3766530a991056050d23be7013107ae20c..204a8dec65cc76503ff6bf209b8ec6c8956ac17e 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -565,6 +565,13 @@ set_rcvbuf:
 			ret = -ENONET;
 			break;
 
+		case SO_PASSSEC:
+			if (valbool)
+				set_bit(SOCK_PASSSEC, &sock->flags);
+			else
+				clear_bit(SOCK_PASSSEC, &sock->flags);
+			break;
+
 		/* We implement the SO_SNDLOWAT etc to
 		   not be settable (1003.1g 5.3) */
 		default:
@@ -723,6 +730,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
 			v.val = sk->sk_state == TCP_LISTEN;
 			break;
 
+		case SO_PASSSEC:
+			v.val = test_bit(SOCK_PASSSEC, &sock->flags) ? 1 : 0;
+			break;
+
 		case SO_PEERSEC:
 			return security_socket_getpeersec_stream(sock, optval, optlen, len);
 
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index 74133ecd77005e4292485c557d97e39a7f12424b..8b99bd33540d53fc072278aa6ade21906a541f90 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -107,7 +107,7 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb)
 	if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
 		return;
 
-	if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
+	if (security_netlink_recv(skb, CAP_NET_ADMIN))
 		RCV_SKB_FAIL(-EPERM);
 
 	/* Eventually we might send routing messages too */
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 461216b47948681791162829e8c4ca2b78e54d87..8d157157bf8e68c65ae3523b62c13ba0486437ab 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1097,7 +1097,7 @@ int inet_sk_rebuild_header(struct sock *sk)
 
 EXPORT_SYMBOL(inet_sk_rebuild_header);
 
-static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg)
+static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	struct iphdr *iph;
@@ -1126,10 +1126,10 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg)
 	rcu_read_lock();
 	ops = rcu_dereference(inet_protos[proto]);
 	if (ops && ops->gso_segment)
-		segs = ops->gso_segment(skb, sg);
+		segs = ops->gso_segment(skb, features);
 	rcu_read_unlock();
 
-	if (IS_ERR(segs))
+	if (!segs || unlikely(IS_ERR(segs)))
 		goto out;
 
 	skb = segs;
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index e1d7f5fbc52634550908485439d6ebbac7d8fb2e..ef0b5aac58382f2132f4912b641af4a7639a2cbd 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -332,7 +332,7 @@ config IP_NF_MATCH_HASHLIMIT
 	help
 	  This option adds a new iptables `hashlimit' match.  
 
-	  As opposed to `limit', this match dynamically crates a hash table
+	  As opposed to `limit', this match dynamically creates a hash table
 	  of limit buckets, based on your selection of source/destination
 	  ip addresses and/or ports.
 
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index d0d19192026d9eb2327cf68a47a4ba1b23dc7fe5..ad39bf640567caaf81e71fd40a83886739611537 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1120,7 +1120,8 @@ int arpt_register_table(struct arpt_table *table,
 		return ret;
 	}
 
-	if (xt_register_table(table, &bootstrap, newinfo) != 0) {
+	ret = xt_register_table(table, &bootstrap, newinfo);
+	if (ret != 0) {
 		xt_free_table_info(newinfo);
 		return ret;
 	}
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index b93f0494362f888785d2dd8af8524d86f67ccdc0..198ac36db861225ec879f21b3ce3b833b082ce0b 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -457,11 +457,19 @@ dev_cmp(struct ipq_queue_entry *entry, unsigned long ifindex)
 	if (entry->info->indev)
 		if (entry->info->indev->ifindex == ifindex)
 			return 1;
-			
 	if (entry->info->outdev)
 		if (entry->info->outdev->ifindex == ifindex)
 			return 1;
-
+#ifdef CONFIG_BRIDGE_NETFILTER
+	if (entry->skb->nf_bridge) {
+		if (entry->skb->nf_bridge->physindev &&
+		    entry->skb->nf_bridge->physindev->ifindex == ifindex)
+			return 1;
+		if (entry->skb->nf_bridge->physoutdev &&
+		    entry->skb->nf_bridge->physoutdev->ifindex == ifindex)
+		    	return 1;
+	}
+#endif
 	return 0;
 }
 
@@ -507,7 +515,7 @@ ipq_rcv_skb(struct sk_buff *skb)
 	if (type <= IPQM_BASE)
 		return;
 		
-	if (security_netlink_recv(skb))
+	if (security_netlink_recv(skb, CAP_NET_ADMIN))
 		RCV_SKB_FAIL(-EPERM);
 	
 	write_lock_bh(&queue_lock);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 706c0025ec5e43768c7c9dadfb30e3782c275d67..7aaaf92efb59ef755a6993a07023cd125a05faa5 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -2113,7 +2113,8 @@ int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
 		return ret;
 	}
 
-	if (xt_register_table(table, &bootstrap, newinfo) != 0) {
+	ret = xt_register_table(table, &bootstrap, newinfo);
+	if (ret != 0) {
 		xt_free_table_info(newinfo);
 		return ret;
 	}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index c04176be7ed12826de51bcf036d2e64cd7f0b17e..0336422c88a03becbf006d26c064b25504b62bf9 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2145,7 +2145,7 @@ int compat_tcp_getsockopt(struct sock *sk, int level, int optname,
 EXPORT_SYMBOL(compat_tcp_getsockopt);
 #endif
 
-struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg)
+struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	struct tcphdr *th;
@@ -2166,10 +2166,14 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg)
 	if (!pskb_may_pull(skb, thlen))
 		goto out;
 
+	segs = NULL;
+	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
+		goto out;
+
 	oldlen = (u16)~skb->len;
 	__skb_pull(skb, thlen);
 
-	segs = skb_segment(skb, sg);
+	segs = skb_segment(skb, features);
 	if (IS_ERR(segs))
 		goto out;
 
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
index c148c1081880a03aa1a7f24a692cb439f7ee3d70..b56399c7cc12ac626372331768a7ac9effd2e946 100644
--- a/net/ipv4/tcp_diag.c
+++ b/net/ipv4/tcp_diag.c
@@ -26,7 +26,10 @@ static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
 	const struct tcp_sock *tp = tcp_sk(sk);
 	struct tcp_info *info = _info;
 
-	r->idiag_rqueue = tp->rcv_nxt - tp->copied_seq;
+	if (sk->sk_state == TCP_LISTEN)
+		r->idiag_rqueue = sk->sk_ack_backlog;
+	else
+		r->idiag_rqueue = tp->rcv_nxt - tp->copied_seq;
 	r->idiag_wqueue = tp->write_seq - tp->snd_una;
 	if (info != NULL)
 		tcp_get_info(sk, info);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 94fe5b1f9dcbeb1b819da503b8d5a09d0c35569c..7fa0b4a8a389c6e08c7eaf51ba1ceb922e1eede9 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4178,8 +4178,6 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
 		 */
 
 		TCP_ECN_rcv_synack(tp, th);
-		if (tp->ecn_flags&TCP_ECN_OK)
-			sock_set_flag(sk, SOCK_NO_LARGESEND);
 
 		tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
 		tcp_ack(sk, skb, FLAG_SLOWPATH);
@@ -4322,8 +4320,6 @@ discard:
 		tp->max_window = tp->snd_wnd;
 
 		TCP_ECN_rcv_syn(tp, th);
-		if (tp->ecn_flags&TCP_ECN_OK)
-			sock_set_flag(sk, SOCK_NO_LARGESEND);
 
 		tcp_mtup_init(sk);
 		tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 25ecc6e2478b5eb9a5ad64b4ed61b4e7a937bc0f..4c6ef47eb1c372d72ba2eab9d877672b7ca9646d 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1726,7 +1726,8 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i)
 	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
 			"%08X %5d %8d %lu %d %p %u %u %u %u %d",
 		i, src, srcp, dest, destp, sp->sk_state,
-		tp->write_seq - tp->snd_una, tp->rcv_nxt - tp->copied_seq,
+		tp->write_seq - tp->snd_una,
+		(sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq),
 		timer_active,
 		jiffies_to_clock_t(timer_expires - jiffies),
 		icsk->icsk_retransmits,
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 2b9b7f6c7f7c101867d1318bcc56d64b995eb0ed..54b2ef7d3efeb26e2fa7866d344604faa47c8bca 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -440,8 +440,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
 			newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len;
 		newtp->rx_opt.mss_clamp = req->mss;
 		TCP_ECN_openreq_child(newtp, req);
-		if (newtp->ecn_flags&TCP_ECN_OK)
-			sock_set_flag(newsk, SOCK_NO_LARGESEND);
 
 		TCP_INC_STATS_BH(TCP_MIB_PASSIVEOPENS);
 	}
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index bdd71db8bf908e3d20dad25ee43ec777970c139c..5a7cb4a9c867f7a0cd4c1edf738dae2138a9e6c6 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -2044,8 +2044,6 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 	memset(th, 0, sizeof(struct tcphdr));
 	th->syn = 1;
 	th->ack = 1;
-	if (dst->dev->features&NETIF_F_TSO)
-		ireq->ecn_ok = 0;
 	TCP_ECN_make_synack(req, th);
 	th->source = inet_sk(sk)->sport;
 	th->dest = ireq->rmt_port;
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index b4b7d441af25411f04af9e7a657cb21488f51370..968a14be0d0578eb17f48e2ea03018845cbd40f8 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -505,7 +505,7 @@ ipq_rcv_skb(struct sk_buff *skb)
 	if (type <= IPQM_BASE)
 		return;
 	
-	if (security_netlink_recv(skb))
+	if (security_netlink_recv(skb, CAP_NET_ADMIN))
 		RCV_SKB_FAIL(-EPERM);	
 
 	write_lock_bh(&queue_lock);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 2e72f89a7019929f2da18cb74ef1ba26e9d1d74b..0b5bd5587a3e67926b9baf2322d7797b1c70dd34 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1281,7 +1281,8 @@ int ip6t_register_table(struct xt_table *table,
 		return ret;
 	}
 
-	if (xt_register_table(table, &bootstrap, newinfo) != 0) {
+	ret = xt_register_table(table, &bootstrap, newinfo);
+	if (ret != 0) {
 		xt_free_table_info(newinfo);
 		return ret;
 	}
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index a50eb306e9e277605e4202cc14cacdf026357b59..b36d5b2e7c30e8a4217b1d3945fe5983dc6bc42d 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1469,7 +1469,8 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
 		   dest->s6_addr32[0], dest->s6_addr32[1],
 		   dest->s6_addr32[2], dest->s6_addr32[3], destp,
 		   sp->sk_state, 
-		   tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq,
+		   tp->write_seq-tp->snd_una,
+		   (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq),
 		   timer_active,
 		   jiffies_to_clock_t(timer_expires - jiffies),
 		   icsk->icsk_retransmits,
diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c
index f8e6cb0db04bc79712e17f406af1bf8e40bcaadc..95cf1234ea17ff2e88a088c3da5766361bbaa7e4 100644
--- a/net/irda/irlan/irlan_client.c
+++ b/net/irda/irlan/irlan_client.c
@@ -173,13 +173,14 @@ void irlan_client_discovery_indication(discinfo_t *discovery,
 	rcu_read_lock();
 	self = irlan_get_any();
 	if (self) {
-		IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+		IRDA_ASSERT(self->magic == IRLAN_MAGIC, goto out;);
 
 		IRDA_DEBUG(1, "%s(), Found instance (%08x)!\n", __FUNCTION__ ,
 		      daddr);
 		
 		irlan_client_wakeup(self, saddr, daddr);
 	}
+IRDA_ASSERT_LABEL(out:)
 	rcu_read_unlock();
 }
 	
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index b1622b7de1cfb0a6f3b4c0cf496622321b668cd6..42a178aa30f9fde82b434b48ece146e8b1e27b98 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -411,7 +411,10 @@ config NETFILTER_XT_MATCH_STATISTIC
 	tristate '"statistic" match support'
 	depends on NETFILTER_XTABLES
 	help
-	  statistic module
+	  This option adds a `statistic' match, which allows you to match
+	  on packets periodically or randomly with a given percentage.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
 
 config NETFILTER_XT_MATCH_STRING
 	tristate  '"string" match support'
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index b8c7c567c9df5a0c3a27e6cbf01680854a7b8914..af4845971f70606d568e731093118b74c0fbf104 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -29,6 +29,7 @@
 #include <linux/errno.h>
 #include <linux/netlink.h>
 #include <linux/spinlock.h>
+#include <linux/interrupt.h>
 #include <linux/notifier.h>
 
 #include <linux/netfilter.h>
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 0c6da496cfa9fc5311115b81b26b1b8176fcaa9d..0839b701b9309f3fd9a98e58c31c0f1a4e897406 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -28,6 +28,8 @@
 #include <linux/sctp.h>
 #include <linux/string.h>
 #include <linux/seq_file.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
 
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_protocol.h>
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index b88e82a1a987461dfae03f7686bdd348cc3c6d26..ec9f0efea6bb58e18bb7bcf9dbab66b333029fac 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -229,7 +229,7 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb,
 		 NFNL_SUBSYS_ID(nlh->nlmsg_type),
 		 NFNL_MSG_TYPE(nlh->nlmsg_type));
 
-	if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) {
+	if (security_netlink_recv(skb, CAP_NET_ADMIN)) {
 		DEBUGP("missing CAP_NET_ADMIN\n");
 		*errp = -EPERM;
 		return -1;
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 86a4ac33de3495791e5e465a5352afe79690c3cf..49ef41e34c48309eb3d7dc6553056a822e6fb112 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -680,11 +680,19 @@ dev_cmp(struct nfqnl_queue_entry *entry, unsigned long ifindex)
 	if (entinf->indev)
 		if (entinf->indev->ifindex == ifindex)
 			return 1;
-			
 	if (entinf->outdev)
 		if (entinf->outdev->ifindex == ifindex)
 			return 1;
-
+#ifdef CONFIG_BRIDGE_NETFILTER
+	if (entry->skb->nf_bridge) {
+		if (entry->skb->nf_bridge->physindev &&
+		    entry->skb->nf_bridge->physindev->ifindex == ifindex)
+			return 1;
+		if (entry->skb->nf_bridge->physoutdev &&
+		    entry->skb->nf_bridge->physoutdev->ifindex == ifindex)
+			return 1;
+	}
+#endif
 	return 0;
 }
 
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index 9316c753692fef1bbbd81f71a381000d6edbb024..843383e01d4155179c66928fafd08e5e64f2f8ac 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -151,7 +151,7 @@ match(const struct sk_buff *skb,
 		&& SCCHECK(((ntohs(sh->dest) >= info->dpts[0]) 
 			&& (ntohs(sh->dest) <= info->dpts[1])), 
 			XT_SCTP_DEST_PORTS, info->flags, info->invflags)
-		&& SCCHECK(match_packet(skb, protoff,
+		&& SCCHECK(match_packet(skb, protoff + sizeof (sctp_sctphdr_t),
 					info->chunkmap, info->chunk_match_type,
  					info->flag_info, info->flag_count, 
 					hotdrop),
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index 1b61dac9c873f2d82ec29812f96f6d134b8bfc67..a9a63aa6893692a774b52c1cae9441262c2c1602 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -260,7 +260,7 @@ static int __init xt_tcpudp_init(void)
 	return ret;
 
 out_unreg_udp:
-	xt_unregister_match(&tcp_matchstruct);
+	xt_unregister_match(&udp_matchstruct);
 out_unreg_tcp6:
 	xt_unregister_match(&tcp6_matchstruct);
 out_unreg_tcp:
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index f329b72578f568440d8e0ef331210eb6408a9bb8..edf084becd5ecafccb25a99ddc0c8cd997336125 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -320,7 +320,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
 		goto errout;
 	}
 
-	if ((ops->flags & GENL_ADMIN_PERM) && security_netlink_recv(skb)) {
+	if ((ops->flags & GENL_ADMIN_PERM) && security_netlink_recv(skb, CAP_NET_ADMIN)) {
 		err = -EPERM;
 		goto errout;
 	}
diff --git a/net/tipc/core.c b/net/tipc/core.c
index 5003acb1591975c995ed92decb6ab412dc988b1a..0539a8362858997cbe6baa2d2445c75c081e3996 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -191,7 +191,8 @@ static int __init tipc_init(void)
 	int res;
 
 	tipc_log_reinit(CONFIG_TIPC_LOG);
-	info("Activated (compiled " __DATE__ " " __TIME__ ")\n");
+	info("Activated (version " TIPC_MOD_VER 
+	     " compiled " __DATE__ " " __TIME__ ")\n");
 
 	tipc_own_addr = 0;
 	tipc_remote_management = 1;
diff --git a/net/tipc/link.c b/net/tipc/link.c
index d64658053746f093d4429cdcd076666bf4bf99ce..c6831c75cfa4dd9ec9c03fb3da7cb451928f7a0c 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -2,7 +2,7 @@
  * net/tipc/link.c: TIPC link code
  * 
  * Copyright (c) 1996-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 2004-2006, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -988,17 +988,18 @@ static int link_bundle_buf(struct link *l_ptr,
 	struct tipc_msg *bundler_msg = buf_msg(bundler);
 	struct tipc_msg *msg = buf_msg(buf);
 	u32 size = msg_size(msg);
-	u32 to_pos = align(msg_size(bundler_msg));
-	u32 rest = link_max_pkt(l_ptr) - to_pos;
+	u32 bundle_size = msg_size(bundler_msg);
+	u32 to_pos = align(bundle_size);
+	u32 pad = to_pos - bundle_size;
 
 	if (msg_user(bundler_msg) != MSG_BUNDLER)
 		return 0;
 	if (msg_type(bundler_msg) != OPEN_MSG)
 		return 0;
-	if (rest < align(size))
+	if (skb_tailroom(bundler) < (pad + size))
 		return 0;
 
-	skb_put(bundler, (to_pos - msg_size(bundler_msg)) + size);
+	skb_put(bundler, pad + size);
 	memcpy(bundler->data + to_pos, buf->data, size);
 	msg_set_size(bundler_msg, to_pos + size);
 	msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 861322b935daf1be3aee4ac4e5eca284c4a7c89a..fc6d09630ccd5e114afca1e631845778d0d21525 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -2,7 +2,7 @@
  * net/tipc/node.c: TIPC node management routines
  * 
  * Copyright (c) 2000-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005-2006, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -592,6 +592,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
 	struct sk_buff *buf;
 	struct node *n_ptr;
         struct tipc_node_info node_info;
+	u32 payload_size;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
 		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
@@ -608,8 +609,11 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
 	/* For now, get space for all other nodes 
 	   (will need to modify this when slave nodes are supported */
 
-	buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(node_info)) *
-				   (tipc_max_nodes - 1));
+	payload_size = TLV_SPACE(sizeof(node_info)) * (tipc_max_nodes - 1);
+	if (payload_size > 32768u)
+		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+						   " (too many nodes)");
+	buf = tipc_cfg_reply_alloc(payload_size);
 	if (!buf)
 		return NULL;
 
@@ -633,6 +637,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
 	struct sk_buff *buf;
 	struct node *n_ptr;
         struct tipc_link_info link_info;
+	u32 payload_size;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
 		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
@@ -645,12 +650,15 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
 
         if (!tipc_nodes)
                 return tipc_cfg_reply_none();
-
-	/* For now, get space for 2 links to all other nodes + bcast link 
-	   (will need to modify this when slave nodes are supported */
-
-	buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(link_info)) *
-				   (2 * (tipc_max_nodes - 1) + 1));
+	
+	/* Get space for all unicast links + multicast link */
+
+	payload_size = TLV_SPACE(sizeof(link_info)) *
+		(tipc_net.zones[tipc_zone(tipc_own_addr)]->links + 1);
+	if (payload_size > 32768u)
+		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+						   " (too many links)");
+	buf = tipc_cfg_reply_alloc(payload_size);
 	if (!buf)
 		return NULL;
 
diff --git a/net/tipc/zone.h b/net/tipc/zone.h
index 267999c5a240fb570fa9e52e4694b482b2e7f700..5ab3d08602e2528d31dc45f9cea84c656b9dbfb3 100644
--- a/net/tipc/zone.h
+++ b/net/tipc/zone.h
@@ -2,7 +2,7 @@
  * net/tipc/zone.h: Include file for TIPC zone management routines
  * 
  * Copyright (c) 2000-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005-2006, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,7 +45,7 @@
  * struct _zone - TIPC zone structure
  * @addr: network address of zone
  * @clusters: array of pointers to all clusters within zone
- * @links: (used for inter-zone communication)
+ * @links: number of (unicast) links to zone
  */
  
 struct _zone {
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index d901465ce0135093276d55adabbb7691591097c3..fd11d4048b5223c1fe7b39e4dc66f82b0f988f67 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -128,6 +128,30 @@ static atomic_t unix_nr_socks = ATOMIC_INIT(0);
 
 #define UNIX_ABSTRACT(sk)	(unix_sk(sk)->addr->hash != UNIX_HASH_SIZE)
 
+#ifdef CONFIG_SECURITY_NETWORK
+static void unix_get_peersec_dgram(struct sk_buff *skb)
+{
+	int err;
+
+	err = security_socket_getpeersec_dgram(skb, UNIXSECDATA(skb),
+					       UNIXSECLEN(skb));
+	if (err)
+		*(UNIXSECDATA(skb)) = NULL;
+}
+
+static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
+{
+	scm->secdata = *UNIXSECDATA(skb);
+	scm->seclen = *UNIXSECLEN(skb);
+}
+#else
+static void unix_get_peersec_dgram(struct sk_buff *skb)
+{ }
+
+static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
+{ }
+#endif /* CONFIG_SECURITY_NETWORK */
+
 /*
  *  SMP locking strategy:
  *    hash table is protected with spinlock unix_table_lock
@@ -1291,6 +1315,8 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
 	if (siocb->scm->fp)
 		unix_attach_fds(siocb->scm, skb);
 
+	unix_get_peersec_dgram(skb);
+
 	skb->h.raw = skb->data;
 	err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
 	if (err)
@@ -1570,6 +1596,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
 		memset(&tmp_scm, 0, sizeof(tmp_scm));
 	}
 	siocb->scm->creds = *UNIXCREDS(skb);
+	unix_set_secdata(siocb->scm, skb);
 
 	if (!(flags & MSG_PEEK))
 	{
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 17b29ec3c41779d70562113ed1219e68ff3ae5fc..43f00fc28a3d14e724ba70af6915c73680e28d0b 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1164,8 +1164,6 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
 	return res;
 }
 
-EXPORT_SYMBOL(xfrm_state_mtu);
-
 int xfrm_init_state(struct xfrm_state *x)
 {
 	struct xfrm_state_afinfo *afinfo;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index c21dc26141eae947f921e881016cbd64da735c64..3e6a722d072ed8b75c0561b82617abd5a2d3adcd 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1435,7 +1435,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *err
 	link = &xfrm_dispatch[type];
 
 	/* All operations require privileges, even GET */
-	if (security_netlink_recv(skb)) {
+	if (security_netlink_recv(skb, CAP_NET_ADMIN)) {
 		*errp = -EPERM;
 		return -1;
 	}
diff --git a/security/commoncap.c b/security/commoncap.c
index 841eb4e5c62b6e91b0e799802791289366bfb45d..57673ee07ceb59b45a05167ab1766eb551ad4ac8 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -33,9 +33,9 @@ int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
 
 EXPORT_SYMBOL(cap_netlink_send);
 
-int cap_netlink_recv(struct sk_buff *skb)
+int cap_netlink_recv(struct sk_buff *skb, int cap)
 {
-	if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
+	if (!cap_raised(NETLINK_CB(skb).eff_cap, cap))
 		return -EPERM;
 	return 0;
 }
diff --git a/security/dummy.c b/security/dummy.c
index 310fcdf7b7495ce07e50c393e5d810817a4e7817..9135408085770e604dde12f53e32afdc898b8b72 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -675,9 +675,9 @@ static int dummy_netlink_send (struct sock *sk, struct sk_buff *skb)
 	return 0;
 }
 
-static int dummy_netlink_recv (struct sk_buff *skb)
+static int dummy_netlink_recv (struct sk_buff *skb, int cap)
 {
-	if (!cap_raised (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN))
+	if (!cap_raised (NETLINK_CB (skb).eff_cap, cap))
 		return -EPERM;
 	return 0;
 }
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 28832e689800b9c9250b54cc4c0be918adebb51d..b85afcf3852774166aeb5b9b65200388e8ee4a72 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -69,6 +69,7 @@
 #include <linux/sysctl.h>
 #include <linux/audit.h>
 #include <linux/string.h>
+#include <linux/selinux.h>
 
 #include "avc.h"
 #include "objsec.h"
@@ -3420,7 +3421,13 @@ out:
 static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen)
 {
 	int err = 0;
-	u32 peer_sid = selinux_socket_getpeer_dgram(skb);
+	u32 peer_sid;
+
+	if (skb->sk->sk_family == PF_UNIX)
+		selinux_get_inode_sid(SOCK_INODE(skb->sk->sk_socket),
+				      &peer_sid);
+	else
+		peer_sid = selinux_socket_getpeer_dgram(skb);
 
 	if (peer_sid == SECSID_NULL)
 		return -EINVAL;
@@ -3432,8 +3439,6 @@ static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata,
 	return 0;
 }
 
-
-
 static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
 {
 	return sk_alloc_security(sk, family, priority);
@@ -3641,32 +3646,32 @@ static unsigned int selinux_ipv6_postroute_last(unsigned int hooknum,
 
 static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
 {
-	struct task_security_struct *tsec;
-	struct av_decision avd;
 	int err;
 
 	err = secondary_ops->netlink_send(sk, skb);
 	if (err)
 		return err;
 
-	tsec = current->security;
-
-	avd.allowed = 0;
-	avc_has_perm_noaudit(tsec->sid, tsec->sid,
-				SECCLASS_CAPABILITY, ~0, &avd);
-	cap_mask(NETLINK_CB(skb).eff_cap, avd.allowed);
-
 	if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS)
 		err = selinux_nlmsg_perm(sk, skb);
 
 	return err;
 }
 
-static int selinux_netlink_recv(struct sk_buff *skb)
+static int selinux_netlink_recv(struct sk_buff *skb, int capability)
 {
-	if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
-		return -EPERM;
-	return 0;
+	int err;
+	struct avc_audit_data ad;
+
+	err = secondary_ops->netlink_recv(skb, capability);
+	if (err)
+		return err;
+
+	AVC_AUDIT_DATA_INIT(&ad, CAP);
+	ad.u.cap = capability;
+
+	return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
+	                    SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
 }
 
 static int ipc_alloc_security(struct task_struct *task,