From c63eddb200690023e7c67f4dd9f132ad91660517 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 10 Apr 2008 15:06:14 -0500 Subject: [PATCH 01/31] sky2: missing chip name for Yukon Supreme Any usage of sky2 on new Yukon Supreme would cause a NULL dereference. The chip is very new, so the support is still untested; vendor has not sent any eval hardware. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 853bce0ac478..f226bcac7d17 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -154,6 +154,7 @@ static const char *yukon2_name[] = { "EC", /* 0xb6 */ "FE", /* 0xb7 */ "FE+", /* 0xb8 */ + "Supreme", /* 0xb9 */ }; static void sky2_set_multicast(struct net_device *dev); From 9a3c243d7d87f401682247dbeff94067d814c192 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 11 Apr 2008 14:05:50 +0200 Subject: [PATCH 02/31] fs_enet: Don't call NAPI functions when NAPI is not used. fs_enet_close() calls napi_disable() unconditionally. This patch skips the call when use_napi isn't set. Signed-off-by: Laurent Pinchart Signed-off-by: Jeff Garzik --- drivers/net/fs_enet/fs_enet-main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index af869cf9ae7d..940e2041ba38 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -835,7 +835,8 @@ static int fs_enet_close(struct net_device *dev) netif_stop_queue(dev); netif_carrier_off(dev); - napi_disable(&fep->napi); + if (fep->fpi->use_napi) + napi_disable(&fep->napi); phy_stop(fep->phydev); spin_lock_irqsave(&fep->lock, flags); From 3d137fdd16b26be31a653f83d6ce4d3a1ed8701e Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Fri, 11 Apr 2008 00:54:43 +0200 Subject: [PATCH 03/31] ucc_geth: fix non-functional fixed phy support The new Fixed PHY method, fixed-link property, isn't impl. for ucc_geth which makes fixed PHYs non functional. Add support for the new method to restore the Fixed PHY functionality. Signed-off-by: Joakim Tjernlund Signed-off-by: Li Yang Signed-off-by: Jeff Garzik --- drivers/net/ucc_geth.c | 53 ++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 8cc316653a39..0ee4c168e4c0 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3833,6 +3833,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma struct device_node *phy; int err, ucc_num, max_speed = 0; const phandle *ph; + const u32 *fixed_link; const unsigned int *prop; const char *sprop; const void *mac_addr; @@ -3923,18 +3924,38 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma ug_info->uf_info.regs = res.start; ug_info->uf_info.irq = irq_of_parse_and_map(np, 0); + fixed_link = of_get_property(np, "fixed-link", NULL); + if (fixed_link) { + ug_info->mdio_bus = 0; + ug_info->phy_address = fixed_link[0]; + phy = NULL; + } else { + ph = of_get_property(np, "phy-handle", NULL); + phy = of_find_node_by_phandle(*ph); - ph = of_get_property(np, "phy-handle", NULL); - phy = of_find_node_by_phandle(*ph); + if (phy == NULL) + return -ENODEV; - if (phy == NULL) - return -ENODEV; + /* set the PHY address */ + prop = of_get_property(phy, "reg", NULL); + if (prop == NULL) + return -1; + ug_info->phy_address = *prop; - /* set the PHY address */ - prop = of_get_property(phy, "reg", NULL); - if (prop == NULL) - return -1; - ug_info->phy_address = *prop; + /* Set the bus id */ + mdio = of_get_parent(phy); + + if (mdio == NULL) + return -1; + + err = of_address_to_resource(mdio, 0, &res); + of_node_put(mdio); + + if (err) + return -1; + + ug_info->mdio_bus = res.start; + } /* get the phy interface type, or default to MII */ prop = of_get_property(np, "phy-connection-type", NULL); @@ -3979,20 +4000,6 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_4; } - /* Set the bus id */ - mdio = of_get_parent(phy); - - if (mdio == NULL) - return -1; - - err = of_address_to_resource(mdio, 0, &res); - of_node_put(mdio); - - if (err) - return -1; - - ug_info->mdio_bus = res.start; - if (netif_msg_probe(&debug)) printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n", ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs, From 84b7901f8d5a17536ef2df7fd628ab865df8fe3a Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Thu, 10 Apr 2008 23:30:07 +0900 Subject: [PATCH 04/31] macb: Call phy_disconnect on removing Call phy_disconnect() on remove routine. Otherwise the phy timer causes a kernel crash when unloading. Signed-off-by: Atsushi Nemoto Signed-off-by: Jeff Garzik --- drivers/net/macb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 1d210ed46130..10fcea59755e 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -1257,6 +1257,8 @@ static int __exit macb_remove(struct platform_device *pdev) if (dev) { bp = netdev_priv(dev); + if (bp->phy_dev) + phy_disconnect(bp->phy_dev); mdiobus_unregister(&bp->mii_bus); kfree(bp->mii_bus.irq); unregister_netdev(dev); From 72cfe92266540d8510946921a599f140a3d4aaa8 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sat, 12 Apr 2008 00:58:14 +0900 Subject: [PATCH 05/31] macb: Use semicolon instead of comma for statement It seems no good reason to use comma here. Signed-off-by: Atsushi Nemoto Signed-off-by: Jeff Garzik --- drivers/net/macb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 10fcea59755e..489c7c3b90d9 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -242,12 +242,12 @@ static int macb_mii_init(struct macb *bp) /* Enable managment port */ macb_writel(bp, NCR, MACB_BIT(MPE)); - bp->mii_bus.name = "MACB_mii_bus", - bp->mii_bus.read = &macb_mdio_read, - bp->mii_bus.write = &macb_mdio_write, - bp->mii_bus.reset = &macb_mdio_reset, - bp->mii_bus.id = bp->pdev->id, - bp->mii_bus.priv = bp, + bp->mii_bus.name = "MACB_mii_bus"; + bp->mii_bus.read = &macb_mdio_read; + bp->mii_bus.write = &macb_mdio_write; + bp->mii_bus.reset = &macb_mdio_reset; + bp->mii_bus.id = bp->pdev->id; + bp->mii_bus.priv = bp; bp->mii_bus.dev = &bp->dev->dev; pdata = bp->pdev->dev.platform_data; From a376e79c6079c2ba6c5fadb0e85a3bb7e465ad89 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Thu, 10 Apr 2008 21:30:35 -0700 Subject: [PATCH 06/31] forcedeth: mac address fix This critical patch fixes a mac address issue recently introduced. If the device's mac address was in correct order and the flag NVREG_TRANSMITPOLL_MAC_ADDR_REV was set, during nv_remove the flag would get cleared. During next load, the mac address would get reversed because the flag is missing. As it has been indicated previously, the flag is cleared across a low power transition. Therefore, the driver should set the mac address back into the reversed order when clearing the flag. Also, the driver should set back the flag after a low power transition to protect against kexec command calling nv_probe a second time. Signed-off-by: Ayaz Abdulla Cc: "Yinghai Lu" Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 419f533006ab..9f088a47d8b1 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -5316,8 +5316,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i /* check the workaround bit for correct mac address order */ txreg = readl(base + NvRegTransmitPoll); - if ((txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) || - (id->driver_data & DEV_HAS_CORRECT_MACADDR)) { + if (id->driver_data & DEV_HAS_CORRECT_MACADDR) { /* mac address is already in correct order */ dev->dev_addr[0] = (np->orig_mac[0] >> 0) & 0xff; dev->dev_addr[1] = (np->orig_mac[0] >> 8) & 0xff; @@ -5325,6 +5324,22 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i dev->dev_addr[3] = (np->orig_mac[0] >> 24) & 0xff; dev->dev_addr[4] = (np->orig_mac[1] >> 0) & 0xff; dev->dev_addr[5] = (np->orig_mac[1] >> 8) & 0xff; + } else if (txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) { + /* mac address is already in correct order */ + dev->dev_addr[0] = (np->orig_mac[0] >> 0) & 0xff; + dev->dev_addr[1] = (np->orig_mac[0] >> 8) & 0xff; + dev->dev_addr[2] = (np->orig_mac[0] >> 16) & 0xff; + dev->dev_addr[3] = (np->orig_mac[0] >> 24) & 0xff; + dev->dev_addr[4] = (np->orig_mac[1] >> 0) & 0xff; + dev->dev_addr[5] = (np->orig_mac[1] >> 8) & 0xff; + /* + * Set orig mac address back to the reversed version. + * This flag will be cleared during low power transition. + * Therefore, we should always put back the reversed address. + */ + np->orig_mac[0] = (dev->dev_addr[5] << 0) + (dev->dev_addr[4] << 8) + + (dev->dev_addr[3] << 16) + (dev->dev_addr[2] << 24); + np->orig_mac[1] = (dev->dev_addr[1] << 0) + (dev->dev_addr[0] << 8); } else { /* need to reverse mac address to correct order */ dev->dev_addr[0] = (np->orig_mac[1] >> 8) & 0xff; @@ -5595,7 +5610,9 @@ out: static int nv_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); + u8 __iomem *base = get_hwbase(dev); int rc = 0; + u32 txreg; if (!netif_running(dev)) goto out; @@ -5606,6 +5623,11 @@ static int nv_resume(struct pci_dev *pdev) pci_restore_state(pdev); pci_enable_wake(pdev, PCI_D0, 0); + /* restore mac address reverse flag */ + txreg = readl(base + NvRegTransmitPoll); + txreg |= NVREG_TRANSMITPOLL_MAC_ADDR_REV; + writel(txreg, base + NvRegTransmitPoll); + rc = nv_open(dev); out: return rc; From c500cb265e35c76d741714a61bc635e0f02d64d2 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 10 Apr 2008 21:30:37 -0700 Subject: [PATCH 07/31] smc91x driver: fix bug: print warning only in interrupt mode http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_item_id=3956 Signed-off-by: Sonic Zhang Signed-off-by: Bryan Wu Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/smc91x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 4020e9e955b3..63a54e29d563 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -1326,9 +1326,11 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id) SMC_SET_INT_MASK(mask); spin_unlock(&lp->lock); +#ifndef CONFIG_NET_POLL_CONTROLLER if (timeout == MAX_IRQ_LOOPS) PRINTK("%s: spurious interrupt (mask = 0x%02x)\n", dev->name, mask); +#endif DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, MAX_IRQ_LOOPS - timeout); From 5a81f14330ce70bc256b624593768fd1b4170d27 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 10 Apr 2008 21:30:38 -0700 Subject: [PATCH 08/31] sc92031: sysfs link missing Add missing sysfs device association. Compile tested only -ENOHW. Addresses http://bugzilla.kernel.org/show_bug.cgi?id=10380 Signed-off-by: Stephen Hemminger Cc: Cesar Eduardo Barros Cc: Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/sc92031.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 37b42394560d..15fcee55284e 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -1446,6 +1446,7 @@ static int __devinit sc92031_probe(struct pci_dev *pdev, } pci_set_drvdata(pdev, dev); + SET_NETDEV_DEV(dev, &pdev->dev); #if SC92031_USE_BAR == 0 dev->mem_start = pci_resource_start(pdev, SC92031_USE_BAR); From 44fb3126d7e6fb411775551b4653643f1d28ebe9 Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Fri, 4 Apr 2008 15:04:53 +0200 Subject: [PATCH 09/31] ehea: Fix DLPAR memory add support This patch fixes two weaknesses in send/receive packet handling which may lead to kernel panics during DLPAR memory add operations. Signed-off-by: Thomas Klein Signed-off-by: Jeff Garzik --- drivers/net/ehea/ehea.h | 3 ++- drivers/net/ehea/ehea_main.c | 24 ++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 93b7fb246960..a8d3280923e8 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0089" +#define DRV_VERSION "EHEA_0090" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 @@ -371,6 +371,7 @@ struct ehea_port_res { struct ehea_q_skb_arr rq2_skba; struct ehea_q_skb_arr rq3_skba; struct ehea_q_skb_arr sq_skba; + int sq_skba_size; spinlock_t netif_queue; int queue_stopped; int swqe_refill_th; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 07c742dd3f09..f460b623c077 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -349,7 +349,8 @@ static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes) pr->rq1_skba.os_skbs = 0; if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) { - pr->rq1_skba.index = index; + if (nr_of_wqes > 0) + pr->rq1_skba.index = index; pr->rq1_skba.os_skbs = fill_wqes; return; } @@ -1464,7 +1465,9 @@ static int ehea_init_port_res(struct ehea_port *port, struct ehea_port_res *pr, init_attr->act_nr_rwqes_rq2, init_attr->act_nr_rwqes_rq3); - ret = ehea_init_q_skba(&pr->sq_skba, init_attr->act_nr_send_wqes + 1); + pr->sq_skba_size = init_attr->act_nr_send_wqes + 1; + + ret = ehea_init_q_skba(&pr->sq_skba, pr->sq_skba_size); ret |= ehea_init_q_skba(&pr->rq1_skba, init_attr->act_nr_rwqes_rq1 + 1); ret |= ehea_init_q_skba(&pr->rq2_skba, init_attr->act_nr_rwqes_rq2 + 1); ret |= ehea_init_q_skba(&pr->rq3_skba, init_attr->act_nr_rwqes_rq3 + 1); @@ -2621,6 +2624,22 @@ void ehea_purge_sq(struct ehea_qp *orig_qp) } } +void ehea_flush_sq(struct ehea_port *port) +{ + int i; + + for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) { + struct ehea_port_res *pr = &port->port_res[i]; + int swqe_max = pr->sq_skba_size - 2 - pr->swqe_ll_count; + int k = 0; + while (atomic_read(&pr->swqe_avail) < swqe_max) { + msleep(5); + if (++k == 20) + break; + } + } +} + int ehea_stop_qps(struct net_device *dev) { struct ehea_port *port = netdev_priv(dev); @@ -2845,6 +2864,7 @@ static void ehea_rereg_mrs(struct work_struct *work) if (dev->flags & IFF_UP) { down(&port->port_lock); netif_stop_queue(dev); + ehea_flush_sq(port); ret = ehea_stop_qps(dev); if (ret) { up(&port->port_lock); From 16a79142e51f9eedbf3ae9a20d9cdb2f88c86acc Mon Sep 17 00:00:00 2001 From: Krzysztof Halasa Date: Sat, 12 Apr 2008 10:10:40 +0200 Subject: [PATCH 10/31] Mark generic HDLC + PPP as broken. PPP support in generic HDLC in Linux 2.6.25 is broken and will cause a kernel panic when a device configured in PPP mode is activated. It will be replaced by new PPP implementation after Linux 2.6.25 is released. This affects only PPP support in generic HDLC (mostly Hitachi SCA and SCA-II based drivers, wanxl, and few others). Standalone syncppp and async PPP support are not affected. Signed-off-by: Krzysztof Halasa Signed-off-by: Jeff Garzik --- drivers/net/wan/Kconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index a3df09ee729f..8005dd16fb4e 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -150,9 +150,13 @@ config HDLC_FR config HDLC_PPP tristate "Synchronous Point-to-Point Protocol (PPP) support" - depends on HDLC + depends on HDLC && BROKEN help Generic HDLC driver supporting PPP over WAN connections. + This module is currently broken and will cause a kernel panic + when a device configured in PPP mode is activated. + + It will be replaced by new PPP implementation in Linux 2.6.26. If unsure, say N. From 2de58e30db3f7e83592e22fb459dd6695b648889 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 12 Apr 2008 18:30:58 -0700 Subject: [PATCH 11/31] tg3: fix MMIO for PPC 44x platforms The driver stores the PCI resource addresses into 'unsigned long' variable before calling ioremap_nocache() on them. This warrants kernel oops when the registers are accessed on PPC 44x platforms which (being 32-bit) have PCI memory space mapped beyond 4 GB. The arch/ppc/ kernel has a fixup in ioremap() that creates an illusion that the PCI memory resource is mapped below 4 GB, but arch/powerpc/ code got rid of this trick, having instead CONFIG_RESOURCES_64BIT enabled. [ Bump driver version and release date -DaveM ] Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/tg3.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index d4655b2d1f3f..96043c5746d0 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -64,8 +64,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.89" -#define DRV_MODULE_RELDATE "April 03, 2008" +#define DRV_MODULE_VERSION "3.90" +#define DRV_MODULE_RELDATE "April 12, 2008" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -12578,7 +12578,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int tg3_version_printed = 0; - unsigned long tg3reg_base, tg3reg_len; + resource_size_t tg3reg_base; + unsigned long tg3reg_len; struct net_device *dev; struct tg3 *tp; int err, pm_cap; From ae1b6a31b1f9ef2c7ba5ef89799f210a9ba6937c Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Sat, 12 Apr 2008 18:33:50 -0700 Subject: [PATCH 12/31] [AX25]: Potential ax25_uid_assoc-s leaks on module unload. The ax25_uid_free call walks the ax25_uid_list and releases entries from it. The problem is that after the fisrt call to hlist_del_init the hlist_for_each_entry (which hides behind the ax25_uid_for_each) will consider the current position to be the last and will return. Thus, the whole list will be left not freed. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller --- net/ax25/ax25_uid.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c index 5f4eb73fb9d3..57aeba729bae 100644 --- a/net/ax25/ax25_uid.c +++ b/net/ax25/ax25_uid.c @@ -218,9 +218,11 @@ void __exit ax25_uid_free(void) struct hlist_node *node; write_lock(&ax25_uid_lock); +again: ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) { hlist_del_init(&ax25_uid->uid_node); ax25_uid_put(ax25_uid); + goto again; } write_unlock(&ax25_uid_lock); } From 028b027524b162eef90839a92ba4b8bddf23e06c Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 12 Apr 2008 18:35:41 -0700 Subject: [PATCH 13/31] [DCCP]: Fix skb->cb conflicts with IP dev_queue_xmit() and the other IP output functions expect to get a skb with clear or properly initialized skb->cb. Unlike TCP and UDP, the dccp_skb_cb doesn't contain a struct inet_skb_parm at the beginning, so the DCCP-specific data is interpreted by the IP output functions. This can cause false negatives for the conditional POST_ROUTING hook invocation, making the packet bypass the hook. Add a inet_skb_parm/inet6_skb_parm union to the beginning of dccp_skb_cb to avoid clashes. Also add a BUILD_BUG_ON to make sure it fits in the cb. [ Combined with patch from Gerrit Renker to remove two now unnecessary memsets of IPCB(skb)->opt ] Signed-off-by: Patrick McHardy Acked-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- net/dccp/dccp.h | 6 ++++++ net/dccp/ipv4.c | 1 - net/dccp/output.c | 1 - net/dccp/proto.c | 3 +++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 287a62bc2e0f..ba2ef94a2302 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -325,6 +325,12 @@ static inline int dccp_bad_service_code(const struct sock *sk, * This is used for transmission as well as for reception. */ struct dccp_skb_cb { + union { + struct inet_skb_parm h4; +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + struct inet6_skb_parm h6; +#endif + } header; __u8 dccpd_type:4; __u8 dccpd_ccval:4; __u8 dccpd_reset_code, diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 474075adbde4..b33704415555 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -489,7 +489,6 @@ static int dccp_v4_send_response(struct sock *sk, struct request_sock *req, dh->dccph_checksum = dccp_v4_csum_finish(skb, ireq->loc_addr, ireq->rmt_addr); - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, ireq->rmt_addr, ireq->opt); diff --git a/net/dccp/output.c b/net/dccp/output.c index 3b763db3d863..3d7d628d870d 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -126,7 +126,6 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) DCCP_INC_STATS(DCCP_MIB_OUTSEGS); - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); err = icsk->icsk_af_ops->queue_xmit(skb, 0); return net_xmit_eval(err); } diff --git a/net/dccp/proto.c b/net/dccp/proto.c index e3f5d37b84be..c91d3c1fd30d 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -1057,6 +1057,9 @@ static int __init dccp_init(void) int ehash_order, bhash_order, i; int rc = -ENOBUFS; + BUILD_BUG_ON(sizeof(struct dccp_skb_cb) > + FIELD_SIZEOF(struct sk_buff, cb)); + dccp_hashinfo.bind_bucket_cachep = kmem_cache_create("dccp_bind_bucket", sizeof(struct inet_bind_bucket), 0, From e56cfad132f2ae269082359d279c17230c987e74 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Sat, 12 Apr 2008 18:37:13 -0700 Subject: [PATCH 14/31] [NET_SCHED] cls_u32: refcounting fix for u32_delete() Deleting of nonroot hnodes mostly doesn't work in u32_delete(): refcnt == 1 is expected, but such hnodes' refcnts are initialized with 0 and charged only with "link" nodes. Now they'll start with 1 like usual. Thanks to Patrick McHardy for an improving suggestion. Signed-off-by: Jarek Poplawski Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/sched/cls_u32.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index c5c16b4b6e98..4d755444c449 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -411,8 +411,10 @@ static void u32_destroy(struct tcf_proto *tp) } } - for (ht=tp_c->hlist; ht; ht = ht->next) + for (ht = tp_c->hlist; ht; ht = ht->next) { + ht->refcnt--; u32_clear_hnode(tp, ht); + } while ((ht = tp_c->hlist) != NULL) { tp_c->hlist = ht->next; @@ -441,8 +443,12 @@ static int u32_delete(struct tcf_proto *tp, unsigned long arg) if (tp->root == ht) return -EINVAL; - if (--ht->refcnt == 0) + if (ht->refcnt == 1) { + ht->refcnt--; u32_destroy_hnode(tp, ht); + } else { + return -EBUSY; + } return 0; } @@ -568,7 +574,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, if (ht == NULL) return -ENOBUFS; ht->tp_c = tp_c; - ht->refcnt = 0; + ht->refcnt = 1; ht->divisor = divisor; ht->handle = handle; ht->prio = tp->prio; From 72da7b3860cabf427590b4982bc880bafab4d5c8 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 12 Apr 2008 18:39:19 -0700 Subject: [PATCH 15/31] [SCTP]: Add check for hmac_algo parameter in sctp_verify_param() RFC 4890 has the following text: The HMAC algorithm based on SHA-1 MUST be supported and included in the HMAC-ALGO parameter. As a result, we need to check in sctp_verify_param() that HMAC_SHA1 is present in the list. If not, we should probably treat this as a protocol violation. It should also be a protocol violation if the HMAC parameter is empty. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/sm_make_chunk.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 578630e8e00d..36ebb392472e 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1982,7 +1982,10 @@ static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc, struct sctp_chunk *chunk, struct sctp_chunk **err_chunk) { + struct sctp_hmac_algo_param *hmacs; int retval = SCTP_IERROR_NO_ERROR; + __u16 n_elt, id = 0; + int i; /* FIXME - This routine is not looking at each parameter per the * chunk type, i.e., unrecognized parameters should be further @@ -2056,9 +2059,29 @@ static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc, break; case SCTP_PARAM_HMAC_ALGO: - if (sctp_auth_enable) - break; - /* Fall Through */ + if (!sctp_auth_enable) + goto fallthrough; + + hmacs = (struct sctp_hmac_algo_param *)param.p; + n_elt = (ntohs(param.p->length) - sizeof(sctp_paramhdr_t)) >> 1; + + /* SCTP-AUTH: Section 6.1 + * The HMAC algorithm based on SHA-1 MUST be supported and + * included in the HMAC-ALGO parameter. + */ + for (i = 0; i < n_elt; i++) { + id = ntohs(hmacs->hmac_ids[i]); + + if (id == SCTP_AUTH_HMAC_ID_SHA1) + break; + } + + if (id != SCTP_AUTH_HMAC_ID_SHA1) { + sctp_process_inv_paramlength(asoc, param.p, chunk, + err_chunk); + retval = SCTP_IERROR_ABORT; + } + break; fallthrough: default: SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n", From f4ad85ca3ef8a1ede76c5020a28a8f4057b4d24f Mon Sep 17 00:00:00 2001 From: Gui Jianfeng Date: Sat, 12 Apr 2008 18:39:34 -0700 Subject: [PATCH 16/31] [SCTP]: Fix protocol violation when receiving an error lenght INIT-ACK When receiving an error length INIT-ACK during COOKIE-WAIT, a 0-vtag ABORT will be responsed. This action violates the protocol apparently. This patch achieves the following things. 1 If the INIT-ACK contains all the fixed parameters, use init-tag recorded from INIT-ACK as vtag. 2 If the INIT-ACK doesn't contain all the fixed parameters, just reflect its vtag. Signed-off-by: Gui Jianfeng Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/command.h | 1 + net/sctp/outqueue.c | 3 +++ net/sctp/sm_sideeffect.c | 3 +++ net/sctp/sm_statefuns.c | 18 ++++++++++++++++++ 4 files changed, 25 insertions(+) diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h index 10ae2da6f93b..35b1e83fb96a 100644 --- a/include/net/sctp/command.h +++ b/include/net/sctp/command.h @@ -104,6 +104,7 @@ typedef enum { SCTP_CMD_ADAPTATION_IND, /* generate and send adaptation event */ SCTP_CMD_ASSOC_SHKEY, /* generate the association shared keys */ SCTP_CMD_T1_RETRAN, /* Mark for retransmission after T1 timeout */ + SCTP_CMD_UPDATE_INITTAG, /* Update peer inittag */ SCTP_CMD_LAST } sctp_verb_t; diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 1bb3c5c35d2a..c0714469233c 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -793,6 +793,9 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) break; case SCTP_CID_ABORT: + if (sctp_test_T_bit(chunk)) { + packet->vtag = asoc->c.my_vtag; + } case SCTP_CID_SACK: case SCTP_CID_HEARTBEAT: case SCTP_CID_HEARTBEAT_ACK: diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 28eb38eb6083..a4763fd24fd8 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1536,6 +1536,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, error = sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC); break; + case SCTP_CMD_UPDATE_INITTAG: + asoc->peer.i.init_tag = cmd->obj.u32; + break; default: printk(KERN_WARNING "Impossible command: %u, %p\n", diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index f2ed6473feef..3ef97499df0d 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -4144,6 +4144,24 @@ static sctp_disposition_t sctp_sf_abort_violation( goto nomem; if (asoc) { + /* Treat INIT-ACK as a special case during COOKIE-WAIT. */ + if (chunk->chunk_hdr->type == SCTP_CID_INIT_ACK && + !asoc->peer.i.init_tag) { + sctp_initack_chunk_t *initack; + + initack = (sctp_initack_chunk_t *)chunk->chunk_hdr; + if (!sctp_chunk_length_valid(chunk, + sizeof(sctp_initack_chunk_t))) + abort->chunk_hdr->flags |= SCTP_CHUNK_FLAG_T; + else { + unsigned int inittag; + + inittag = ntohl(initack->init_hdr.init_tag); + sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_INITTAG, + SCTP_U32(inittag)); + } + } + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); From ab38fb04c9f8928cfaf6f4966633d783419906a1 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Sat, 12 Apr 2008 18:40:06 -0700 Subject: [PATCH 17/31] [SCTP]: Fix compiler warning about const qualifiers Fix 3 warnings about discarding const qualifiers: net/sctp/ulpevent.c:862: warning: passing argument 1 of 'sctp_event2skb' discards qualifiers from pointer target type net/sctp/sm_statefuns.c:4393: warning: passing argument 1 of 'SCTP_ASOC' discards qualifiers from pointer target type net/sctp/socket.c:5874: warning: passing argument 1 of 'cmsg_nxthdr' discards qualifiers from pointer target type Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/ulpevent.h | 2 +- net/sctp/sm_statefuns.c | 5 +++-- net/sctp/socket.c | 5 +++-- net/sctp/ulpevent.c | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h index 9bcfc12275e8..7ea12e8e6676 100644 --- a/include/net/sctp/ulpevent.h +++ b/include/net/sctp/ulpevent.h @@ -67,7 +67,7 @@ struct sctp_ulpevent { }; /* Retrieve the skb this event sits inside of. */ -static inline struct sk_buff *sctp_event2skb(struct sctp_ulpevent *ev) +static inline struct sk_buff *sctp_event2skb(const struct sctp_ulpevent *ev) { return container_of((void *)ev, struct sk_buff, cb); } diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 3ef97499df0d..07194c2a32df 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -4367,6 +4367,7 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const struct sctp_endpoint *ep, sctp_cmd_seq_t *commands) { struct sctp_chunk *repl; + struct sctp_association* my_asoc; /* The comment below says that we enter COOKIE-WAIT AFTER * sending the INIT, but that doesn't actually work in our @@ -4390,8 +4391,8 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const struct sctp_endpoint *ep, /* Cast away the const modifier, as we want to just * rerun it through as a sideffect. */ - sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, - SCTP_ASOC((struct sctp_association *) asoc)); + my_asoc = (struct sctp_association *)asoc; + sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(my_asoc)); /* Choose transport for INIT. */ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, diff --git a/net/sctp/socket.c b/net/sctp/socket.c index d994d822900d..998e63a31311 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -5868,11 +5868,12 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs) { struct cmsghdr *cmsg; + struct msghdr *my_msg = (struct msghdr *)msg; for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; - cmsg = CMSG_NXTHDR((struct msghdr*)msg, cmsg)) { - if (!CMSG_OK(msg, cmsg)) + cmsg = CMSG_NXTHDR(my_msg, cmsg)) { + if (!CMSG_OK(my_msg, cmsg)) return -EINVAL; /* Should we parse this header or ignore? */ diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index b43f1f110f87..ce6cda6b6994 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -859,7 +859,7 @@ __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event) union sctp_notification *notification; struct sk_buff *skb; - skb = sctp_event2skb((struct sctp_ulpevent *)event); + skb = sctp_event2skb(event); notification = (union sctp_notification *) skb->data; return notification->sn_header.sn_type; } From a40a7d15ba602b547f56b7b19e0282fe4fc3dee3 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Sat, 12 Apr 2008 18:40:38 -0700 Subject: [PATCH 18/31] [SCTP]: IPv4 vs IPv6 addresses mess in sctp_inet[6]addr_event. All IP addresses that are present in a system are duplicated on struct sctp_sockaddr_entry. They are linked in the global list called sctp_local_addr_list. And this struct unions IPv4 and IPv6 addresses. So, there can be rare case, when a sockaddr_in.sin_addr coincides with the corresponding part of the sockaddr_in6 and the notifier for IPv4 will carry away an IPv6 entry. The fix is to check the family before comparing the addresses. Signed-off-by: Pavel Emelyanov Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/ipv6.c | 5 +++-- net/sctp/protocol.c | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index b1e05d719f9b..85f1495e0edc 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -110,8 +110,9 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev, spin_lock_bh(&sctp_local_addr_lock); list_for_each_entry_safe(addr, temp, &sctp_local_addr_list, list) { - if (ipv6_addr_equal(&addr->a.v6.sin6_addr, - &ifa->addr)) { + if (addr->a.sa.sa_family == AF_INET6 && + ipv6_addr_equal(&addr->a.v6.sin6_addr, + &ifa->addr)) { found = 1; addr->valid = 0; list_del_rcu(&addr->list); diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index f90091a1b9ce..c2dd65d9f38d 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -647,7 +647,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, spin_lock_bh(&sctp_local_addr_lock); list_for_each_entry_safe(addr, temp, &sctp_local_addr_list, list) { - if (addr->a.v4.sin_addr.s_addr == ifa->ifa_local) { + if (addr->a.sa.sa_family == AF_INET && + addr->a.v4.sin_addr.s_addr == + ifa->ifa_local) { found = 1; addr->valid = 0; list_del_rcu(&addr->list); From 14daa02139dcb3193b2b0250c0720a23ef610c49 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 12 Apr 2008 18:48:58 -0700 Subject: [PATCH 19/31] net: make struct tun_struct private to tun.c There's no reason for this to be in the header, and it just hurts recompile time. Signed-off-by: Rusty Russell Acked-by: Max Krasnyanskiy Signed-off-by: David S. Miller --- drivers/net/tun.c | 33 +++++++++++++++++++++++++++++++++ include/linux/Kbuild | 2 +- include/linux/if_tun.h | 39 --------------------------------------- 3 files changed, 34 insertions(+), 40 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 7b816a032957..970ec4793442 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -67,10 +67,43 @@ #include #include +/* Uncomment to enable debugging */ +/* #define TUN_DEBUG 1 */ + #ifdef TUN_DEBUG static int debug; + +#define DBG if(tun->debug)printk +#define DBG1 if(debug==2)printk +#else +#define DBG( a... ) +#define DBG1( a... ) #endif +struct tun_struct { + struct list_head list; + unsigned long flags; + int attached; + uid_t owner; + gid_t group; + + wait_queue_head_t read_wait; + struct sk_buff_head readq; + + struct net_device *dev; + + struct fasync_struct *fasync; + + unsigned long if_flags; + u8 dev_addr[ETH_ALEN]; + u32 chr_filter[2]; + u32 net_filter[2]; + +#ifdef TUN_DEBUG + int debug; +#endif +}; + /* Network device part of the driver */ static LIST_HEAD(tun_dev_list); diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 9cdd12a9e843..cedbbd806bf6 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -86,6 +86,7 @@ header-y += if_plip.h header-y += if_ppp.h header-y += if_slip.h header-y += if_strip.h +header-y += if_tun.h header-y += if_tunnel.h header-y += in6.h header-y += in_route.h @@ -229,7 +230,6 @@ unifdef-y += if_link.h unifdef-y += if_pppol2tp.h unifdef-y += if_pppox.h unifdef-y += if_tr.h -unifdef-y += if_tun.h unifdef-y += if_vlan.h unifdef-y += if_wanpipe.h unifdef-y += igmp.h diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h index 72f1c5f47be3..8c71fe2fb1f5 100644 --- a/include/linux/if_tun.h +++ b/include/linux/if_tun.h @@ -18,47 +18,8 @@ #ifndef __IF_TUN_H #define __IF_TUN_H -/* Uncomment to enable debugging */ -/* #define TUN_DEBUG 1 */ - #include -#ifdef __KERNEL__ - -#ifdef TUN_DEBUG -#define DBG if(tun->debug)printk -#define DBG1 if(debug==2)printk -#else -#define DBG( a... ) -#define DBG1( a... ) -#endif - -struct tun_struct { - struct list_head list; - unsigned long flags; - int attached; - uid_t owner; - gid_t group; - - wait_queue_head_t read_wait; - struct sk_buff_head readq; - - struct net_device *dev; - - struct fasync_struct *fasync; - - unsigned long if_flags; - u8 dev_addr[ETH_ALEN]; - u32 chr_filter[2]; - u32 net_filter[2]; - -#ifdef TUN_DEBUG - int debug; -#endif -}; - -#endif /* __KERNEL__ */ - /* Read queue size */ #define TUN_READQ_SIZE 500 From e01bf1c83332c4653ffd30eed20a94a9c83d82b2 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 12 Apr 2008 18:49:30 -0700 Subject: [PATCH 20/31] net: check for underlength tap writes If the user gives a packet under 14 bytes, we'll end up reading off the end of the skb (not oopsing, just reading off the end). Signed-off-by: Rusty Russell Acked-by: Max Krasnyanskiy Signed-off-by: David S. Miller --- drivers/net/tun.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 970ec4793442..5b5d87585d91 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -286,8 +286,11 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, return -EFAULT; } - if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) + if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { align = NET_IP_ALIGN; + if (unlikely(len < ETH_HLEN)) + return -EINVAL; + } if (!(skb = alloc_skb(len + align, GFP_KERNEL))) { tun->dev->stats.rx_dropped++; From f37f0afb2916ccf287428983026261db78c7661a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 13 Apr 2008 21:39:26 -0700 Subject: [PATCH 21/31] [SOCK] sk_stamp: should be initialized to ktime_set(-1L, 0) Problem spotted by Andrew Brampton Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/sock.c b/net/core/sock.c index 2654c147c004..7a0567b4b2c9 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1725,7 +1725,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; - sk->sk_stamp = ktime_set(-1L, -1L); + sk->sk_stamp = ktime_set(-1L, 0); atomic_set(&sk->sk_refcnt, 1); atomic_set(&sk->sk_drops, 0); From 4c821d753d5c097babd6609bcd85f08e254a3505 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 13 Apr 2008 21:52:48 -0700 Subject: [PATCH 22/31] [NET]: Fix kernel-doc for skb_segment The kernel-doc comment for skb_segment is clearly wrong. This states what it actually does. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- net/core/skbuff.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 0d0fd28a9041..608701339620 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2131,8 +2131,8 @@ EXPORT_SYMBOL_GPL(skb_pull_rcsum); * @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. + * a pointer to the first in a list of new skbs for the segments. + * In case of error it returns ERR_PTR(err). */ struct sk_buff *skb_segment(struct sk_buff *skb, int features) { From d2dcba612b357a4687843ad4f46629d219233fd7 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 13 Apr 2008 22:44:20 -0700 Subject: [PATCH 23/31] [ISDN]: Do not validate ISDN net device address prior to interface-up Commit bada339 (Validate device addr prior to interface-up) caused a regression in the ISDN network code, see: http://bugzilla.kernel.org/show_bug.cgi?id=9923 The trivial fix is to remove the pointer to eth_validate_addr() in the net_device struct in isdn_net_init(). Signed-off-by: Paul Bolle Signed-off-by: David S. Miller --- drivers/isdn/i4l/isdn_net.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index ced83c202cac..ef1a300068dc 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -2010,6 +2010,7 @@ isdn_net_init(struct net_device *ndev) ndev->flags = IFF_NOARP|IFF_POINTOPOINT; ndev->type = ARPHRD_ETHER; ndev->addr_len = ETH_ALEN; + ndev->validate_addr = NULL; /* for clients with MPPP maybe higher values better */ ndev->tx_queue_len = 30; From 2ed9926e16094ad143b96b09c64cba8bcba05ee1 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 13 Apr 2008 22:45:40 -0700 Subject: [PATCH 24/31] [NET]: Return more appropriate error from eth_validate_addr(). Paul Bolle wrote: > http://bugzilla.kernel.org/show_bug.cgi?id=9923 would have been much easier to > track down if eth_validate_addr() would somehow complain aloud if an address > is invalid. Shouldn't it make at least some noise? I guess it should return -EADDRNOTAVAIL similar to eth_mac_addr() when validation fails. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ethernet/eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index a7b417523e9b..a80839b02e3f 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -301,7 +301,7 @@ static int eth_change_mtu(struct net_device *dev, int new_mtu) static int eth_validate_addr(struct net_device *dev) { if (!is_valid_ether_addr(dev->dev_addr)) - return -EINVAL; + return -EADDRNOTAVAIL; return 0; } From b45e9189c058bfa495073951ff461ee0eea968be Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 13 Apr 2008 23:14:15 -0700 Subject: [PATCH 25/31] [IPV6]: Fix ipv6 address fetching in raw6_icmp_error(). Fixes kernel bugzilla 10437 Based almost entirely upon a patch by Dmitry Butskoy. When deciding what raw sockets to deliver the ICMPv6 to, we should use the addresses in the ICMPv6 quoted IPV6 header, not the top-level one. Signed-off-by: David S. Miller --- net/ipv6/raw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 8897ccf8086a..0a6fbc1d1a50 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -372,8 +372,10 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, read_lock(&raw_v6_hashinfo.lock); sk = sk_head(&raw_v6_hashinfo.ht[hash]); if (sk != NULL) { - saddr = &ipv6_hdr(skb)->saddr; - daddr = &ipv6_hdr(skb)->daddr; + struct ipv6hdr *hdr = (struct ipv6hdr *) skb->data; + + saddr = &hdr->saddr; + daddr = &hdr->daddr; net = skb->dev->nd_net; while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, From 7cd636fe9ce5de0051c11283911baca4291868c8 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Sun, 13 Apr 2008 23:33:52 -0700 Subject: [PATCH 26/31] [IPV6]: IPv6 extension header structures need to be packed. struct ipv6_opt_hdr is the common structure for IPv6 extension headers, and it is common to increment the pointer to get the real content. On the other hand, since the structure consists only of 1-byte next-header field and 1-byte length field, size of that structure depends on architecture; 2 or 4. Add "packed" attribute to get 2. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- include/linux/ipv6.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 4aaefc349a4b..134c8e5cf07c 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -53,7 +53,7 @@ struct ipv6_opt_hdr { /* * TLV encoded option data follows. */ -}; +} __attribute__ ((packed)); /* required for some archs */ #define ipv6_destopt_hdr ipv6_opt_hdr #define ipv6_hopopt_hdr ipv6_opt_hdr From e9df2e8fd8fbc95c57dbd1d33dada66c4627b44c Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Sun, 13 Apr 2008 23:40:51 -0700 Subject: [PATCH 27/31] [IPV6]: Use appropriate sock tclass setting for routing lookup. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- include/net/inet_ecn.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h index ba33db053854..7040a782c656 100644 --- a/include/net/inet_ecn.h +++ b/include/net/inet_ecn.h @@ -47,7 +47,7 @@ static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner) } while (0) #define IP6_ECN_flow_xmit(sk, label) do { \ - if (INET_ECN_is_capable(inet_sk(sk)->tos)) \ + if (INET_ECN_is_capable(inet6_sk(sk)->tclass)) \ (label) |= htonl(INET_ECN_ECT_0 << 20); \ } while (0) From b077d7ababdb5433aef18c62bf1f785e8729f49a Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Sun, 13 Apr 2008 23:42:18 -0700 Subject: [PATCH 28/31] [IPV6] ADDRCONF: Ensure disabling multicast RS even if privacy extensions are disabled. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index a65935a9afd9..b9eeb4f51d48 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -371,6 +371,15 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) */ in6_dev_hold(ndev); +#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) + if (dev->type == ARPHRD_SIT && (dev->priv_flags & IFF_ISATAP)) { + printk(KERN_INFO + "%s: Disabled Multicast RS\n", + dev->name); + ndev->cnf.rtr_solicits = 0; + } +#endif + #ifdef CONFIG_IPV6_PRIVACY setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev); if ((dev->flags&IFF_LOOPBACK) || @@ -383,13 +392,6 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) "%s: Disabled Privacy Extensions\n", dev->name); ndev->cnf.use_tempaddr = -1; - - if (dev->type == ARPHRD_SIT && (dev->priv_flags & IFF_ISATAP)) { - printk(KERN_INFO - "%s: Disabled Multicast RS\n", - dev->name); - ndev->cnf.rtr_solicits = 0; - } } else { in6_dev_hold(ndev); ipv6_regen_rndid((unsigned long) ndev); From 9625ed72e8bd619c3984f3024bd37143b7f0c7b0 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Sun, 13 Apr 2008 23:47:11 -0700 Subject: [PATCH 29/31] [IPV6] ADDRCONF: Don't generate temporary address for ip6-ip6 interface. As far as I can remember, I was going to disable privacy extensions on all "tunnel" interfaces. Disable it on ip6-ip6 interface as well. Also, just remove ifdefs for SIT for simplicity. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index b9eeb4f51d48..e08955baedff 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -384,9 +384,8 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev); if ((dev->flags&IFF_LOOPBACK) || dev->type == ARPHRD_TUNNEL || -#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) + dev->type == ARPHRD_TUNNEL6 || dev->type == ARPHRD_SIT || -#endif dev->type == ARPHRD_NONE) { printk(KERN_INFO "%s: Disabled Privacy Extensions\n", From 4dee959723e2bf3a0f9343a46841cd2f0029d424 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Mon, 14 Apr 2008 00:44:52 -0700 Subject: [PATCH 30/31] [NETFILTER]: ipt_CLUSTERIP: fix race between clusterip_config_find_get and _entry_put Consider we are putting a clusterip_config entry with the "entries" count == 1, and on the other CPU there's a clusterip_config_find_get in progress: CPU1: CPU2: clusterip_config_entry_put: clusterip_config_find_get: if (atomic_dec_and_test(&c->entries)) { /* true */ read_lock_bh(&clusterip_lock); c = __clusterip_config_find(clusterip); /* found - it's still in list */ ... atomic_inc(&c->entries); read_unlock_bh(&clusterip_lock); write_lock_bh(&clusterip_lock); list_del(&c->list); write_unlock_bh(&clusterip_lock); ... dev_put(c->dev); Oops! We have an entry returned by the clusterip_config_find_get, which is a) not in list b) has a stale dev pointer. The problems will happen when the CPU2 will release the entry - it will remove it from the list for the 2nd time, thus spoiling it, and will put a stale dev pointer. The fix is to make atomic_dec_and_test under the clusterip_lock. Signed-off-by: Pavel Emelyanov Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ipt_CLUSTERIP.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 52926c8e3cc1..a12dd329e208 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -82,8 +82,8 @@ clusterip_config_put(struct clusterip_config *c) static inline void clusterip_config_entry_put(struct clusterip_config *c) { + write_lock_bh(&clusterip_lock); if (atomic_dec_and_test(&c->entries)) { - write_lock_bh(&clusterip_lock); list_del(&c->list); write_unlock_bh(&clusterip_lock); @@ -96,7 +96,9 @@ clusterip_config_entry_put(struct clusterip_config *c) #ifdef CONFIG_PROC_FS remove_proc_entry(c->pde->name, c->pde->parent); #endif + return; } + write_unlock_bh(&clusterip_lock); } static struct clusterip_config * From 159d83363b629c91d020734207c1bc788b96af5a Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 14 Apr 2008 00:46:01 -0700 Subject: [PATCH 31/31] [BRIDGE]: Fix crash in __ip_route_output_key with bridge netfilter The bridge netfilter code attaches a fake dst_entry with a pointer to a fake net_device structure to skbs it passes up to IPv4 netfilter. This leads to crashes when the skb is passed to __ip_route_output_key when dereferencing the namespace pointer. Since bridging can currently only operate in the init_net namespace, the easiest fix for now is to initialize the nd_net pointer of the fake net_device struct to &init_net. Should fix bugzilla 10323: http://bugzilla.kernel.org/show_bug.cgi?id=10323 Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/bridge/br_netfilter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 1c0efd8ad9f3..af7e8be8d8d2 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -110,7 +110,8 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb) * ipt_REJECT needs it. Future netfilter modules might * require us to fill additional fields. */ static struct net_device __fake_net_device = { - .hard_header_len = ETH_HLEN + .hard_header_len = ETH_HLEN, + .nd_net = &init_net, }; static struct rtable __fake_rtable = {