diff options
44 files changed, 329 insertions, 192 deletions
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 22abfb39d81..68d45ba2d9b 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c | |||
| @@ -1237,8 +1237,17 @@ static int bfin_mac_enable(struct phy_device *phydev) | |||
| 1237 | 1237 | ||
| 1238 | if (phydev->interface == PHY_INTERFACE_MODE_RMII) { | 1238 | if (phydev->interface == PHY_INTERFACE_MODE_RMII) { |
| 1239 | opmode |= RMII; /* For Now only 100MBit are supported */ | 1239 | opmode |= RMII; /* For Now only 100MBit are supported */ |
| 1240 | #if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) && CONFIG_BF_REV_0_2 | 1240 | #if defined(CONFIG_BF537) || defined(CONFIG_BF536) |
| 1241 | opmode |= TE; | 1241 | if (__SILICON_REVISION__ < 3) { |
| 1242 | /* | ||
| 1243 | * This isn't publicly documented (fun times!), but in | ||
| 1244 | * silicon <=0.2, the RX and TX pins are clocked together. | ||
| 1245 | * So in order to recv, we must enable the transmit side | ||
| 1246 | * as well. This will cause a spurious TX interrupt too, | ||
| 1247 | * but we can easily consume that. | ||
| 1248 | */ | ||
| 1249 | opmode |= TE; | ||
| 1250 | } | ||
| 1242 | #endif | 1251 | #endif |
| 1243 | } | 1252 | } |
| 1244 | 1253 | ||
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index d1865cc9731..8e6d618b530 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
| @@ -8317,7 +8317,7 @@ static const struct net_device_ops bnx2_netdev_ops = { | |||
| 8317 | #endif | 8317 | #endif |
| 8318 | }; | 8318 | }; |
| 8319 | 8319 | ||
| 8320 | static void inline vlan_features_add(struct net_device *dev, u32 flags) | 8320 | static inline void vlan_features_add(struct net_device *dev, u32 flags) |
| 8321 | { | 8321 | { |
| 8322 | dev->vlan_features |= flags; | 8322 | dev->vlan_features |= flags; |
| 8323 | } | 8323 | } |
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 110eda01843..31552959aed 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c | |||
| @@ -588,14 +588,9 @@ static void c_can_chip_config(struct net_device *dev) | |||
| 588 | { | 588 | { |
| 589 | struct c_can_priv *priv = netdev_priv(dev); | 589 | struct c_can_priv *priv = netdev_priv(dev); |
| 590 | 590 | ||
| 591 | if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) | 591 | /* enable automatic retransmission */ |
| 592 | /* disable automatic retransmission */ | 592 | priv->write_reg(priv, &priv->regs->control, |
| 593 | priv->write_reg(priv, &priv->regs->control, | 593 | CONTROL_ENABLE_AR); |
| 594 | CONTROL_DISABLE_AR); | ||
| 595 | else | ||
| 596 | /* enable automatic retransmission */ | ||
| 597 | priv->write_reg(priv, &priv->regs->control, | ||
| 598 | CONTROL_ENABLE_AR); | ||
| 599 | 594 | ||
| 600 | if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY & | 595 | if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY & |
| 601 | CAN_CTRLMODE_LOOPBACK)) { | 596 | CAN_CTRLMODE_LOOPBACK)) { |
| @@ -704,7 +699,6 @@ static void c_can_do_tx(struct net_device *dev) | |||
| 704 | 699 | ||
| 705 | for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { | 700 | for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { |
| 706 | msg_obj_no = get_tx_echo_msg_obj(priv); | 701 | msg_obj_no = get_tx_echo_msg_obj(priv); |
| 707 | c_can_inval_msg_object(dev, 0, msg_obj_no); | ||
| 708 | val = c_can_read_reg32(priv, &priv->regs->txrqst1); | 702 | val = c_can_read_reg32(priv, &priv->regs->txrqst1); |
| 709 | if (!(val & (1 << msg_obj_no))) { | 703 | if (!(val & (1 << msg_obj_no))) { |
| 710 | can_get_echo_skb(dev, | 704 | can_get_echo_skb(dev, |
| @@ -713,6 +707,7 @@ static void c_can_do_tx(struct net_device *dev) | |||
| 713 | &priv->regs->ifregs[0].msg_cntrl) | 707 | &priv->regs->ifregs[0].msg_cntrl) |
| 714 | & IF_MCONT_DLC_MASK; | 708 | & IF_MCONT_DLC_MASK; |
| 715 | stats->tx_packets++; | 709 | stats->tx_packets++; |
| 710 | c_can_inval_msg_object(dev, 0, msg_obj_no); | ||
| 716 | } | 711 | } |
| 717 | } | 712 | } |
| 718 | 713 | ||
| @@ -1112,8 +1107,7 @@ struct net_device *alloc_c_can_dev(void) | |||
| 1112 | priv->can.bittiming_const = &c_can_bittiming_const; | 1107 | priv->can.bittiming_const = &c_can_bittiming_const; |
| 1113 | priv->can.do_set_mode = c_can_set_mode; | 1108 | priv->can.do_set_mode = c_can_set_mode; |
| 1114 | priv->can.do_get_berr_counter = c_can_get_berr_counter; | 1109 | priv->can.do_get_berr_counter = c_can_get_berr_counter; |
| 1115 | priv->can.ctrlmode_supported = CAN_CTRLMODE_ONE_SHOT | | 1110 | priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | |
| 1116 | CAN_CTRLMODE_LOOPBACK | | ||
| 1117 | CAN_CTRLMODE_LISTENONLY | | 1111 | CAN_CTRLMODE_LISTENONLY | |
| 1118 | CAN_CTRLMODE_BERR_REPORTING; | 1112 | CAN_CTRLMODE_BERR_REPORTING; |
| 1119 | 1113 | ||
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index e629b961ae2..cc90824f2c9 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c | |||
| @@ -73,7 +73,8 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) | |||
| 73 | void __iomem *addr; | 73 | void __iomem *addr; |
| 74 | struct net_device *dev; | 74 | struct net_device *dev; |
| 75 | struct c_can_priv *priv; | 75 | struct c_can_priv *priv; |
| 76 | struct resource *mem, *irq; | 76 | struct resource *mem; |
| 77 | int irq; | ||
| 77 | #ifdef CONFIG_HAVE_CLK | 78 | #ifdef CONFIG_HAVE_CLK |
| 78 | struct clk *clk; | 79 | struct clk *clk; |
| 79 | 80 | ||
| @@ -88,8 +89,8 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) | |||
| 88 | 89 | ||
| 89 | /* get the platform data */ | 90 | /* get the platform data */ |
| 90 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 91 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 91 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 92 | irq = platform_get_irq(pdev, 0); |
| 92 | if (!mem || (irq <= 0)) { | 93 | if (!mem || irq <= 0) { |
| 93 | ret = -ENODEV; | 94 | ret = -ENODEV; |
| 94 | goto exit_free_clk; | 95 | goto exit_free_clk; |
| 95 | } | 96 | } |
| @@ -117,7 +118,7 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) | |||
| 117 | 118 | ||
| 118 | priv = netdev_priv(dev); | 119 | priv = netdev_priv(dev); |
| 119 | 120 | ||
| 120 | dev->irq = irq->start; | 121 | dev->irq = irq; |
| 121 | priv->regs = addr; | 122 | priv->regs = addr; |
| 122 | #ifdef CONFIG_HAVE_CLK | 123 | #ifdef CONFIG_HAVE_CLK |
| 123 | priv->can.clock.freq = clk_get_rate(clk); | 124 | priv->can.clock.freq = clk_get_rate(clk); |
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 4d538a4e9d5..91089314329 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
| @@ -1983,14 +1983,20 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c) | |||
| 1983 | { | 1983 | { |
| 1984 | struct port_info *pi = netdev_priv(dev); | 1984 | struct port_info *pi = netdev_priv(dev); |
| 1985 | struct adapter *adapter = pi->adapter; | 1985 | struct adapter *adapter = pi->adapter; |
| 1986 | struct qset_params *qsp = &adapter->params.sge.qset[0]; | 1986 | struct qset_params *qsp; |
| 1987 | struct sge_qset *qs = &adapter->sge.qs[0]; | 1987 | struct sge_qset *qs; |
| 1988 | int i; | ||
| 1988 | 1989 | ||
| 1989 | if (c->rx_coalesce_usecs * 10 > M_NEWTIMER) | 1990 | if (c->rx_coalesce_usecs * 10 > M_NEWTIMER) |
| 1990 | return -EINVAL; | 1991 | return -EINVAL; |
| 1991 | 1992 | ||
| 1992 | qsp->coalesce_usecs = c->rx_coalesce_usecs; | 1993 | for (i = 0; i < pi->nqsets; i++) { |
| 1993 | t3_update_qset_coalesce(qs, qsp); | 1994 | qsp = &adapter->params.sge.qset[i]; |
| 1995 | qs = &adapter->sge.qs[i]; | ||
| 1996 | qsp->coalesce_usecs = c->rx_coalesce_usecs; | ||
| 1997 | t3_update_qset_coalesce(qs, qsp); | ||
| 1998 | } | ||
| 1999 | |||
| 1994 | return 0; | 2000 | return 0; |
| 1995 | } | 2001 | } |
| 1996 | 2002 | ||
diff --git a/drivers/net/jme.c b/drivers/net/jme.c index f690474f440..994c80939c7 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c | |||
| @@ -273,7 +273,7 @@ jme_clear_pm(struct jme_adapter *jme) | |||
| 273 | { | 273 | { |
| 274 | jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs); | 274 | jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs); |
| 275 | pci_set_power_state(jme->pdev, PCI_D0); | 275 | pci_set_power_state(jme->pdev, PCI_D0); |
| 276 | pci_enable_wake(jme->pdev, PCI_D0, false); | 276 | device_set_wakeup_enable(&jme->pdev->dev, false); |
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | static int | 279 | static int |
| @@ -2538,6 +2538,8 @@ jme_set_wol(struct net_device *netdev, | |||
| 2538 | 2538 | ||
| 2539 | jwrite32(jme, JME_PMCS, jme->reg_pmcs); | 2539 | jwrite32(jme, JME_PMCS, jme->reg_pmcs); |
| 2540 | 2540 | ||
| 2541 | device_set_wakeup_enable(&jme->pdev->dev, jme->reg_pmcs); | ||
| 2542 | |||
| 2541 | return 0; | 2543 | return 0; |
| 2542 | } | 2544 | } |
| 2543 | 2545 | ||
| @@ -3172,9 +3174,9 @@ jme_shutdown(struct pci_dev *pdev) | |||
| 3172 | } | 3174 | } |
| 3173 | 3175 | ||
| 3174 | #ifdef CONFIG_PM | 3176 | #ifdef CONFIG_PM |
| 3175 | static int | 3177 | static int jme_suspend(struct device *dev) |
| 3176 | jme_suspend(struct pci_dev *pdev, pm_message_t state) | ||
| 3177 | { | 3178 | { |
| 3179 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 3178 | struct net_device *netdev = pci_get_drvdata(pdev); | 3180 | struct net_device *netdev = pci_get_drvdata(pdev); |
| 3179 | struct jme_adapter *jme = netdev_priv(netdev); | 3181 | struct jme_adapter *jme = netdev_priv(netdev); |
| 3180 | 3182 | ||
| @@ -3206,22 +3208,18 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 3206 | tasklet_hi_enable(&jme->rxclean_task); | 3208 | tasklet_hi_enable(&jme->rxclean_task); |
| 3207 | tasklet_hi_enable(&jme->rxempty_task); | 3209 | tasklet_hi_enable(&jme->rxempty_task); |
| 3208 | 3210 | ||
| 3209 | pci_save_state(pdev); | ||
| 3210 | jme_powersave_phy(jme); | 3211 | jme_powersave_phy(jme); |
| 3211 | pci_enable_wake(jme->pdev, PCI_D3hot, true); | ||
| 3212 | pci_set_power_state(pdev, PCI_D3hot); | ||
| 3213 | 3212 | ||
| 3214 | return 0; | 3213 | return 0; |
| 3215 | } | 3214 | } |
| 3216 | 3215 | ||
| 3217 | static int | 3216 | static int jme_resume(struct device *dev) |
| 3218 | jme_resume(struct pci_dev *pdev) | ||
| 3219 | { | 3217 | { |
| 3218 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 3220 | struct net_device *netdev = pci_get_drvdata(pdev); | 3219 | struct net_device *netdev = pci_get_drvdata(pdev); |
| 3221 | struct jme_adapter *jme = netdev_priv(netdev); | 3220 | struct jme_adapter *jme = netdev_priv(netdev); |
| 3222 | 3221 | ||
| 3223 | jme_clear_pm(jme); | 3222 | jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs); |
| 3224 | pci_restore_state(pdev); | ||
| 3225 | 3223 | ||
| 3226 | jme_phy_on(jme); | 3224 | jme_phy_on(jme); |
| 3227 | if (test_bit(JME_FLAG_SSET, &jme->flags)) | 3225 | if (test_bit(JME_FLAG_SSET, &jme->flags)) |
| @@ -3238,6 +3236,13 @@ jme_resume(struct pci_dev *pdev) | |||
| 3238 | 3236 | ||
| 3239 | return 0; | 3237 | return 0; |
| 3240 | } | 3238 | } |
| 3239 | |||
| 3240 | static SIMPLE_DEV_PM_OPS(jme_pm_ops, jme_suspend, jme_resume); | ||
| 3241 | #define JME_PM_OPS (&jme_pm_ops) | ||
| 3242 | |||
| 3243 | #else | ||
| 3244 | |||
| 3245 | #define JME_PM_OPS NULL | ||
| 3241 | #endif | 3246 | #endif |
| 3242 | 3247 | ||
| 3243 | static DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = { | 3248 | static DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = { |
| @@ -3251,11 +3256,8 @@ static struct pci_driver jme_driver = { | |||
| 3251 | .id_table = jme_pci_tbl, | 3256 | .id_table = jme_pci_tbl, |
| 3252 | .probe = jme_init_one, | 3257 | .probe = jme_init_one, |
| 3253 | .remove = __devexit_p(jme_remove_one), | 3258 | .remove = __devexit_p(jme_remove_one), |
| 3254 | #ifdef CONFIG_PM | ||
| 3255 | .suspend = jme_suspend, | ||
| 3256 | .resume = jme_resume, | ||
| 3257 | #endif /* CONFIG_PM */ | ||
| 3258 | .shutdown = jme_shutdown, | 3259 | .shutdown = jme_shutdown, |
| 3260 | .driver.pm = JME_PM_OPS, | ||
| 3259 | }; | 3261 | }; |
| 3260 | 3262 | ||
| 3261 | static int __init | 3263 | static int __init |
diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c index 540a8dcbcc4..7f7d5708a65 100644 --- a/drivers/net/ksz884x.c +++ b/drivers/net/ksz884x.c | |||
| @@ -4898,7 +4898,7 @@ static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev) | |||
| 4898 | goto unlock; | 4898 | goto unlock; |
| 4899 | } | 4899 | } |
| 4900 | skb_copy_and_csum_dev(org_skb, skb->data); | 4900 | skb_copy_and_csum_dev(org_skb, skb->data); |
| 4901 | org_skb->ip_summed = 0; | 4901 | org_skb->ip_summed = CHECKSUM_NONE; |
| 4902 | skb->len = org_skb->len; | 4902 | skb->len = org_skb->len; |
| 4903 | copy_old_skb(org_skb, skb); | 4903 | copy_old_skb(org_skb, skb); |
| 4904 | } | 4904 | } |
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 5762ebde445..4f158baa024 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c | |||
| @@ -742,6 +742,9 @@ int mlx4_en_start_port(struct net_device *dev) | |||
| 742 | 0, MLX4_PROT_ETH)) | 742 | 0, MLX4_PROT_ETH)) |
| 743 | mlx4_warn(mdev, "Failed Attaching Broadcast\n"); | 743 | mlx4_warn(mdev, "Failed Attaching Broadcast\n"); |
| 744 | 744 | ||
| 745 | /* Must redo promiscuous mode setup. */ | ||
| 746 | priv->flags &= ~(MLX4_EN_FLAG_PROMISC | MLX4_EN_FLAG_MC_PROMISC); | ||
| 747 | |||
| 745 | /* Schedule multicast task to populate multicast list */ | 748 | /* Schedule multicast task to populate multicast list */ |
| 746 | queue_work(mdev->workqueue, &priv->mcast_task); | 749 | queue_work(mdev->workqueue, &priv->mcast_task); |
| 747 | 750 | ||
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 1f4e8680a96..673dc600c89 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
| @@ -1312,17 +1312,26 @@ myri10ge_unmap_rx_page(struct pci_dev *pdev, | |||
| 1312 | * page into an skb */ | 1312 | * page into an skb */ |
| 1313 | 1313 | ||
| 1314 | static inline int | 1314 | static inline int |
| 1315 | myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx, | 1315 | myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum, |
| 1316 | int bytes, int len, __wsum csum) | 1316 | int lro_enabled) |
| 1317 | { | 1317 | { |
| 1318 | struct myri10ge_priv *mgp = ss->mgp; | 1318 | struct myri10ge_priv *mgp = ss->mgp; |
| 1319 | struct sk_buff *skb; | 1319 | struct sk_buff *skb; |
| 1320 | struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME]; | 1320 | struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME]; |
| 1321 | int i, idx, hlen, remainder; | 1321 | struct myri10ge_rx_buf *rx; |
| 1322 | int i, idx, hlen, remainder, bytes; | ||
| 1322 | struct pci_dev *pdev = mgp->pdev; | 1323 | struct pci_dev *pdev = mgp->pdev; |
| 1323 | struct net_device *dev = mgp->dev; | 1324 | struct net_device *dev = mgp->dev; |
| 1324 | u8 *va; | 1325 | u8 *va; |
| 1325 | 1326 | ||
| 1327 | if (len <= mgp->small_bytes) { | ||
| 1328 | rx = &ss->rx_small; | ||
| 1329 | bytes = mgp->small_bytes; | ||
| 1330 | } else { | ||
| 1331 | rx = &ss->rx_big; | ||
| 1332 | bytes = mgp->big_bytes; | ||
| 1333 | } | ||
| 1334 | |||
| 1326 | len += MXGEFW_PAD; | 1335 | len += MXGEFW_PAD; |
| 1327 | idx = rx->cnt & rx->mask; | 1336 | idx = rx->cnt & rx->mask; |
| 1328 | va = page_address(rx->info[idx].page) + rx->info[idx].page_offset; | 1337 | va = page_address(rx->info[idx].page) + rx->info[idx].page_offset; |
| @@ -1341,7 +1350,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx, | |||
| 1341 | remainder -= MYRI10GE_ALLOC_SIZE; | 1350 | remainder -= MYRI10GE_ALLOC_SIZE; |
| 1342 | } | 1351 | } |
| 1343 | 1352 | ||
| 1344 | if (dev->features & NETIF_F_LRO) { | 1353 | if (lro_enabled) { |
| 1345 | rx_frags[0].page_offset += MXGEFW_PAD; | 1354 | rx_frags[0].page_offset += MXGEFW_PAD; |
| 1346 | rx_frags[0].size -= MXGEFW_PAD; | 1355 | rx_frags[0].size -= MXGEFW_PAD; |
| 1347 | len -= MXGEFW_PAD; | 1356 | len -= MXGEFW_PAD; |
| @@ -1463,7 +1472,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) | |||
| 1463 | { | 1472 | { |
| 1464 | struct myri10ge_rx_done *rx_done = &ss->rx_done; | 1473 | struct myri10ge_rx_done *rx_done = &ss->rx_done; |
| 1465 | struct myri10ge_priv *mgp = ss->mgp; | 1474 | struct myri10ge_priv *mgp = ss->mgp; |
| 1466 | struct net_device *netdev = mgp->dev; | 1475 | |
| 1467 | unsigned long rx_bytes = 0; | 1476 | unsigned long rx_bytes = 0; |
| 1468 | unsigned long rx_packets = 0; | 1477 | unsigned long rx_packets = 0; |
| 1469 | unsigned long rx_ok; | 1478 | unsigned long rx_ok; |
| @@ -1474,18 +1483,18 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) | |||
| 1474 | u16 length; | 1483 | u16 length; |
| 1475 | __wsum checksum; | 1484 | __wsum checksum; |
| 1476 | 1485 | ||
| 1486 | /* | ||
| 1487 | * Prevent compiler from generating more than one ->features memory | ||
| 1488 | * access to avoid theoretical race condition with functions that | ||
| 1489 | * change NETIF_F_LRO flag at runtime. | ||
| 1490 | */ | ||
| 1491 | bool lro_enabled = ACCESS_ONCE(mgp->dev->features) & NETIF_F_LRO; | ||
| 1492 | |||
| 1477 | while (rx_done->entry[idx].length != 0 && work_done < budget) { | 1493 | while (rx_done->entry[idx].length != 0 && work_done < budget) { |
| 1478 | length = ntohs(rx_done->entry[idx].length); | 1494 | length = ntohs(rx_done->entry[idx].length); |
| 1479 | rx_done->entry[idx].length = 0; | 1495 | rx_done->entry[idx].length = 0; |
| 1480 | checksum = csum_unfold(rx_done->entry[idx].checksum); | 1496 | checksum = csum_unfold(rx_done->entry[idx].checksum); |
| 1481 | if (length <= mgp->small_bytes) | 1497 | rx_ok = myri10ge_rx_done(ss, length, checksum, lro_enabled); |
| 1482 | rx_ok = myri10ge_rx_done(ss, &ss->rx_small, | ||
| 1483 | mgp->small_bytes, | ||
| 1484 | length, checksum); | ||
| 1485 | else | ||
| 1486 | rx_ok = myri10ge_rx_done(ss, &ss->rx_big, | ||
| 1487 | mgp->big_bytes, | ||
| 1488 | length, checksum); | ||
| 1489 | rx_packets += rx_ok; | 1498 | rx_packets += rx_ok; |
| 1490 | rx_bytes += rx_ok * (unsigned long)length; | 1499 | rx_bytes += rx_ok * (unsigned long)length; |
| 1491 | cnt++; | 1500 | cnt++; |
| @@ -1497,7 +1506,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) | |||
| 1497 | ss->stats.rx_packets += rx_packets; | 1506 | ss->stats.rx_packets += rx_packets; |
| 1498 | ss->stats.rx_bytes += rx_bytes; | 1507 | ss->stats.rx_bytes += rx_bytes; |
| 1499 | 1508 | ||
| 1500 | if (netdev->features & NETIF_F_LRO) | 1509 | if (lro_enabled) |
| 1501 | lro_flush_all(&rx_done->lro_mgr); | 1510 | lro_flush_all(&rx_done->lro_mgr); |
| 1502 | 1511 | ||
| 1503 | /* restock receive rings if needed */ | 1512 | /* restock receive rings if needed */ |
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 653d308e0f5..3bdcc803ec6 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c | |||
| @@ -871,7 +871,7 @@ static int netxen_nic_set_flags(struct net_device *netdev, u32 data) | |||
| 871 | struct netxen_adapter *adapter = netdev_priv(netdev); | 871 | struct netxen_adapter *adapter = netdev_priv(netdev); |
| 872 | int hw_lro; | 872 | int hw_lro; |
| 873 | 873 | ||
| 874 | if (data & ~ETH_FLAG_LRO) | 874 | if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO)) |
| 875 | return -EINVAL; | 875 | return -EINVAL; |
| 876 | 876 | ||
| 877 | if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO)) | 877 | if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO)) |
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 4c14510e2a8..45b2755d6cb 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c | |||
| @@ -1003,7 +1003,7 @@ static int qlcnic_set_flags(struct net_device *netdev, u32 data) | |||
| 1003 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 1003 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
| 1004 | int hw_lro; | 1004 | int hw_lro; |
| 1005 | 1005 | ||
| 1006 | if (data & ~ETH_FLAG_LRO) | 1006 | if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO)) |
| 1007 | return -EINVAL; | 1007 | return -EINVAL; |
| 1008 | 1008 | ||
| 1009 | if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)) | 1009 | if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)) |
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 2ad6364103e..356e74d20b8 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c | |||
| @@ -6726,7 +6726,7 @@ static int s2io_ethtool_set_flags(struct net_device *dev, u32 data) | |||
| 6726 | int rc = 0; | 6726 | int rc = 0; |
| 6727 | int changed = 0; | 6727 | int changed = 0; |
| 6728 | 6728 | ||
| 6729 | if (data & ~ETH_FLAG_LRO) | 6729 | if (ethtool_invalid_flags(dev, data, ETH_FLAG_LRO)) |
| 6730 | return -EINVAL; | 6730 | return -EINVAL; |
| 6731 | 6731 | ||
| 6732 | if (data & ETH_FLAG_LRO) { | 6732 | if (data & ETH_FLAG_LRO) { |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ebec88882c3..73c942d85f0 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
| @@ -48,9 +48,9 @@ | |||
| 48 | #include <net/ip.h> | 48 | #include <net/ip.h> |
| 49 | 49 | ||
| 50 | #include <asm/system.h> | 50 | #include <asm/system.h> |
| 51 | #include <asm/io.h> | 51 | #include <linux/io.h> |
| 52 | #include <asm/byteorder.h> | 52 | #include <asm/byteorder.h> |
| 53 | #include <asm/uaccess.h> | 53 | #include <linux/uaccess.h> |
| 54 | 54 | ||
| 55 | #ifdef CONFIG_SPARC | 55 | #ifdef CONFIG_SPARC |
| 56 | #include <asm/idprom.h> | 56 | #include <asm/idprom.h> |
| @@ -13118,7 +13118,7 @@ done: | |||
| 13118 | 13118 | ||
| 13119 | static struct pci_dev * __devinit tg3_find_peer(struct tg3 *); | 13119 | static struct pci_dev * __devinit tg3_find_peer(struct tg3 *); |
| 13120 | 13120 | ||
| 13121 | static void inline vlan_features_add(struct net_device *dev, unsigned long flags) | 13121 | static inline void vlan_features_add(struct net_device *dev, unsigned long flags) |
| 13122 | { | 13122 | { |
| 13123 | dev->vlan_features |= flags; | 13123 | dev->vlan_features |= flags; |
| 13124 | } | 13124 | } |
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c index 81254be85b9..51f2ef142a5 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c | |||
| @@ -304,8 +304,8 @@ vmxnet3_set_flags(struct net_device *netdev, u32 data) | |||
| 304 | u8 lro_present = (netdev->features & NETIF_F_LRO) == 0 ? 0 : 1; | 304 | u8 lro_present = (netdev->features & NETIF_F_LRO) == 0 ? 0 : 1; |
| 305 | unsigned long flags; | 305 | unsigned long flags; |
| 306 | 306 | ||
| 307 | if (data & ~ETH_FLAG_LRO) | 307 | if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO)) |
| 308 | return -EOPNOTSUPP; | 308 | return -EINVAL; |
| 309 | 309 | ||
| 310 | if (lro_requested ^ lro_present) { | 310 | if (lro_requested ^ lro_present) { |
| 311 | /* toggle the LRO feature*/ | 311 | /* toggle the LRO feature*/ |
diff --git a/drivers/net/vxge/vxge-ethtool.c b/drivers/net/vxge/vxge-ethtool.c index 1dd3a21b3a4..c5eb034107f 100644 --- a/drivers/net/vxge/vxge-ethtool.c +++ b/drivers/net/vxge/vxge-ethtool.c | |||
| @@ -1117,8 +1117,8 @@ static int vxge_set_flags(struct net_device *dev, u32 data) | |||
| 1117 | struct vxgedev *vdev = netdev_priv(dev); | 1117 | struct vxgedev *vdev = netdev_priv(dev); |
| 1118 | enum vxge_hw_status status; | 1118 | enum vxge_hw_status status; |
| 1119 | 1119 | ||
| 1120 | if (data & ~ETH_FLAG_RXHASH) | 1120 | if (ethtool_invalid_flags(dev, data, ETH_FLAG_RXHASH)) |
| 1121 | return -EOPNOTSUPP; | 1121 | return -EINVAL; |
| 1122 | 1122 | ||
| 1123 | if (!!(data & ETH_FLAG_RXHASH) == vdev->devh->config.rth_en) | 1123 | if (!!(data & ETH_FLAG_RXHASH) == vdev->devh->config.rth_en) |
| 1124 | return 0; | 1124 | return 0; |
diff --git a/include/linux/can/core.h b/include/linux/can/core.h index 6c507bea275..6f70a6d3a16 100644 --- a/include/linux/can/core.h +++ b/include/linux/can/core.h | |||
| @@ -36,10 +36,10 @@ | |||
| 36 | * @prot: pointer to struct proto structure. | 36 | * @prot: pointer to struct proto structure. |
| 37 | */ | 37 | */ |
| 38 | struct can_proto { | 38 | struct can_proto { |
| 39 | int type; | 39 | int type; |
| 40 | int protocol; | 40 | int protocol; |
| 41 | struct proto_ops *ops; | 41 | const struct proto_ops *ops; |
| 42 | struct proto *prot; | 42 | struct proto *prot; |
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | /* function prototypes for the CAN networklayer core (af_can.c) */ | 45 | /* function prototypes for the CAN networklayer core (af_can.c) */ |
| @@ -58,5 +58,6 @@ extern void can_rx_unregister(struct net_device *dev, canid_t can_id, | |||
| 58 | void *data); | 58 | void *data); |
| 59 | 59 | ||
| 60 | extern int can_send(struct sk_buff *skb, int loop); | 60 | extern int can_send(struct sk_buff *skb, int loop); |
| 61 | extern int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); | ||
| 61 | 62 | ||
| 62 | #endif /* CAN_CORE_H */ | 63 | #endif /* CAN_CORE_H */ |
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index ae757bcf128..c8fcbdd2b0e 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h | |||
| @@ -680,6 +680,7 @@ int ethtool_op_set_ufo(struct net_device *dev, u32 data); | |||
| 680 | u32 ethtool_op_get_flags(struct net_device *dev); | 680 | u32 ethtool_op_get_flags(struct net_device *dev); |
| 681 | int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported); | 681 | int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported); |
| 682 | void ethtool_ntuple_flush(struct net_device *dev); | 682 | void ethtool_ntuple_flush(struct net_device *dev); |
| 683 | bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported); | ||
| 683 | 684 | ||
| 684 | /** | 685 | /** |
| 685 | * ðtool_ops - Alter and report network device settings | 686 | * ðtool_ops - Alter and report network device settings |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 24cfa626931..239083bfea1 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
| @@ -122,8 +122,14 @@ struct sk_buff_head { | |||
| 122 | 122 | ||
| 123 | struct sk_buff; | 123 | struct sk_buff; |
| 124 | 124 | ||
| 125 | /* To allow 64K frame to be packed as single skb without frag_list */ | 125 | /* To allow 64K frame to be packed as single skb without frag_list. Since |
| 126 | * GRO uses frags we allocate at least 16 regardless of page size. | ||
| 127 | */ | ||
| 128 | #if (65536/PAGE_SIZE + 2) < 16 | ||
| 129 | #define MAX_SKB_FRAGS 16 | ||
| 130 | #else | ||
| 126 | #define MAX_SKB_FRAGS (65536/PAGE_SIZE + 2) | 131 | #define MAX_SKB_FRAGS (65536/PAGE_SIZE + 2) |
| 132 | #endif | ||
| 127 | 133 | ||
| 128 | typedef struct skb_frag_struct skb_frag_t; | 134 | typedef struct skb_frag_struct skb_frag_t; |
| 129 | 135 | ||
diff --git a/include/net/dst.h b/include/net/dst.h index 2a46cbaef92..75b95df4afe 100644 --- a/include/net/dst.h +++ b/include/net/dst.h | |||
| @@ -345,7 +345,7 @@ static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev) | |||
| 345 | 345 | ||
| 346 | static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) | 346 | static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) |
| 347 | { | 347 | { |
| 348 | struct dst_entry *child = skb_dst(skb)->child; | 348 | struct dst_entry *child = dst_clone(skb_dst(skb)->child); |
| 349 | 349 | ||
| 350 | skb_dst_drop(skb); | 350 | skb_dst_drop(skb); |
| 351 | return child; | 351 | return child; |
diff --git a/include/net/rose.h b/include/net/rose.h index 5ba9f02731e..555dd198aab 100644 --- a/include/net/rose.h +++ b/include/net/rose.h | |||
| @@ -14,6 +14,12 @@ | |||
| 14 | 14 | ||
| 15 | #define ROSE_MIN_LEN 3 | 15 | #define ROSE_MIN_LEN 3 |
| 16 | 16 | ||
| 17 | #define ROSE_CALL_REQ_ADDR_LEN_OFF 3 | ||
| 18 | #define ROSE_CALL_REQ_ADDR_LEN_VAL 0xAA /* each address is 10 digits */ | ||
| 19 | #define ROSE_CALL_REQ_DEST_ADDR_OFF 4 | ||
| 20 | #define ROSE_CALL_REQ_SRC_ADDR_OFF 9 | ||
| 21 | #define ROSE_CALL_REQ_FACILITIES_OFF 14 | ||
| 22 | |||
| 17 | #define ROSE_GFI 0x10 | 23 | #define ROSE_GFI 0x10 |
| 18 | #define ROSE_Q_BIT 0x80 | 24 | #define ROSE_Q_BIT 0x80 |
| 19 | #define ROSE_D_BIT 0x40 | 25 | #define ROSE_D_BIT 0x40 |
| @@ -214,7 +220,7 @@ extern void rose_requeue_frames(struct sock *); | |||
| 214 | extern int rose_validate_nr(struct sock *, unsigned short); | 220 | extern int rose_validate_nr(struct sock *, unsigned short); |
| 215 | extern void rose_write_internal(struct sock *, int); | 221 | extern void rose_write_internal(struct sock *, int); |
| 216 | extern int rose_decode(struct sk_buff *, int *, int *, int *, int *, int *); | 222 | extern int rose_decode(struct sk_buff *, int *, int *, int *, int *, int *); |
| 217 | extern int rose_parse_facilities(unsigned char *, struct rose_facilities_struct *); | 223 | extern int rose_parse_facilities(unsigned char *, unsigned int, struct rose_facilities_struct *); |
| 218 | extern void rose_disconnect(struct sock *, int, int, int); | 224 | extern void rose_disconnect(struct sock *, int, int, int); |
| 219 | 225 | ||
| 220 | /* rose_timer.c */ | 226 | /* rose_timer.c */ |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index cffa5dc6644..6ae4bc5ce8a 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
| @@ -1601,6 +1601,28 @@ static inline int xfrm_replay_state_esn_len(struct xfrm_replay_state_esn *replay | |||
| 1601 | } | 1601 | } |
| 1602 | 1602 | ||
| 1603 | #ifdef CONFIG_XFRM_MIGRATE | 1603 | #ifdef CONFIG_XFRM_MIGRATE |
| 1604 | static inline int xfrm_replay_clone(struct xfrm_state *x, | ||
| 1605 | struct xfrm_state *orig) | ||
| 1606 | { | ||
| 1607 | x->replay_esn = kzalloc(xfrm_replay_state_esn_len(orig->replay_esn), | ||
| 1608 | GFP_KERNEL); | ||
| 1609 | if (!x->replay_esn) | ||
| 1610 | return -ENOMEM; | ||
| 1611 | |||
| 1612 | x->replay_esn->bmp_len = orig->replay_esn->bmp_len; | ||
| 1613 | x->replay_esn->replay_window = orig->replay_esn->replay_window; | ||
| 1614 | |||
| 1615 | x->preplay_esn = kmemdup(x->replay_esn, | ||
| 1616 | xfrm_replay_state_esn_len(x->replay_esn), | ||
| 1617 | GFP_KERNEL); | ||
| 1618 | if (!x->preplay_esn) { | ||
| 1619 | kfree(x->replay_esn); | ||
| 1620 | return -ENOMEM; | ||
| 1621 | } | ||
| 1622 | |||
| 1623 | return 0; | ||
| 1624 | } | ||
| 1625 | |||
| 1604 | static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig) | 1626 | static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig) |
| 1605 | { | 1627 | { |
| 1606 | return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL); | 1628 | return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL); |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index dce8f0009a1..718b60366df 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
| @@ -389,6 +389,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
| 389 | { | 389 | { |
| 390 | struct net_bridge_port *p; | 390 | struct net_bridge_port *p; |
| 391 | int err = 0; | 391 | int err = 0; |
| 392 | bool changed_addr; | ||
| 392 | 393 | ||
| 393 | /* Don't allow bridging non-ethernet like devices */ | 394 | /* Don't allow bridging non-ethernet like devices */ |
| 394 | if ((dev->flags & IFF_LOOPBACK) || | 395 | if ((dev->flags & IFF_LOOPBACK) || |
| @@ -446,7 +447,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
| 446 | list_add_rcu(&p->list, &br->port_list); | 447 | list_add_rcu(&p->list, &br->port_list); |
| 447 | 448 | ||
| 448 | spin_lock_bh(&br->lock); | 449 | spin_lock_bh(&br->lock); |
| 449 | br_stp_recalculate_bridge_id(br); | 450 | changed_addr = br_stp_recalculate_bridge_id(br); |
| 450 | br_features_recompute(br); | 451 | br_features_recompute(br); |
| 451 | 452 | ||
| 452 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && | 453 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && |
| @@ -456,6 +457,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
| 456 | 457 | ||
| 457 | br_ifinfo_notify(RTM_NEWLINK, p); | 458 | br_ifinfo_notify(RTM_NEWLINK, p); |
| 458 | 459 | ||
| 460 | if (changed_addr) | ||
| 461 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | ||
| 462 | |||
| 459 | dev_set_mtu(br->dev, br_min_mtu(br)); | 463 | dev_set_mtu(br->dev, br_min_mtu(br)); |
| 460 | 464 | ||
| 461 | kobject_uevent(&p->kobj, KOBJ_ADD); | 465 | kobject_uevent(&p->kobj, KOBJ_ADD); |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 19e2f46ed08..387013d3374 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -497,7 +497,7 @@ extern void br_stp_disable_bridge(struct net_bridge *br); | |||
| 497 | extern void br_stp_set_enabled(struct net_bridge *br, unsigned long val); | 497 | extern void br_stp_set_enabled(struct net_bridge *br, unsigned long val); |
| 498 | extern void br_stp_enable_port(struct net_bridge_port *p); | 498 | extern void br_stp_enable_port(struct net_bridge_port *p); |
| 499 | extern void br_stp_disable_port(struct net_bridge_port *p); | 499 | extern void br_stp_disable_port(struct net_bridge_port *p); |
| 500 | extern void br_stp_recalculate_bridge_id(struct net_bridge *br); | 500 | extern bool br_stp_recalculate_bridge_id(struct net_bridge *br); |
| 501 | extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a); | 501 | extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a); |
| 502 | extern void br_stp_set_bridge_priority(struct net_bridge *br, | 502 | extern void br_stp_set_bridge_priority(struct net_bridge *br, |
| 503 | u16 newprio); | 503 | u16 newprio); |
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 79372d4a405..5593f5aec94 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
| @@ -204,7 +204,7 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) | |||
| 204 | static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1]; | 204 | static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1]; |
| 205 | 205 | ||
| 206 | /* called under bridge lock */ | 206 | /* called under bridge lock */ |
| 207 | void br_stp_recalculate_bridge_id(struct net_bridge *br) | 207 | bool br_stp_recalculate_bridge_id(struct net_bridge *br) |
| 208 | { | 208 | { |
| 209 | const unsigned char *br_mac_zero = | 209 | const unsigned char *br_mac_zero = |
| 210 | (const unsigned char *)br_mac_zero_aligned; | 210 | (const unsigned char *)br_mac_zero_aligned; |
| @@ -222,8 +222,11 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br) | |||
| 222 | 222 | ||
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | if (compare_ether_addr(br->bridge_id.addr, addr)) | 225 | if (compare_ether_addr(br->bridge_id.addr, addr) == 0) |
| 226 | br_stp_change_bridge_id(br, addr); | 226 | return false; /* no change */ |
| 227 | |||
| 228 | br_stp_change_bridge_id(br, addr); | ||
| 229 | return true; | ||
| 227 | } | 230 | } |
| 228 | 231 | ||
| 229 | /* called under bridge lock */ | 232 | /* called under bridge lock */ |
diff --git a/net/can/af_can.c b/net/can/af_can.c index 702be5a2c95..733d66f1b05 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c | |||
| @@ -95,7 +95,7 @@ struct s_pstats can_pstats; /* receive list statistics */ | |||
| 95 | * af_can socket functions | 95 | * af_can socket functions |
| 96 | */ | 96 | */ |
| 97 | 97 | ||
| 98 | static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 98 | int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
| 99 | { | 99 | { |
| 100 | struct sock *sk = sock->sk; | 100 | struct sock *sk = sock->sk; |
| 101 | 101 | ||
| @@ -108,6 +108,7 @@ static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
| 108 | return -ENOIOCTLCMD; | 108 | return -ENOIOCTLCMD; |
| 109 | } | 109 | } |
| 110 | } | 110 | } |
| 111 | EXPORT_SYMBOL(can_ioctl); | ||
| 111 | 112 | ||
| 112 | static void can_sock_destruct(struct sock *sk) | 113 | static void can_sock_destruct(struct sock *sk) |
| 113 | { | 114 | { |
| @@ -698,13 +699,9 @@ int can_proto_register(struct can_proto *cp) | |||
| 698 | printk(KERN_ERR "can: protocol %d already registered\n", | 699 | printk(KERN_ERR "can: protocol %d already registered\n", |
| 699 | proto); | 700 | proto); |
| 700 | err = -EBUSY; | 701 | err = -EBUSY; |
| 701 | } else { | 702 | } else |
| 702 | proto_tab[proto] = cp; | 703 | proto_tab[proto] = cp; |
| 703 | 704 | ||
| 704 | /* use generic ioctl function if not defined by module */ | ||
| 705 | if (!cp->ops->ioctl) | ||
| 706 | cp->ops->ioctl = can_ioctl; | ||
| 707 | } | ||
| 708 | spin_unlock(&proto_tab_lock); | 705 | spin_unlock(&proto_tab_lock); |
| 709 | 706 | ||
| 710 | if (err < 0) | 707 | if (err < 0) |
diff --git a/net/can/bcm.c b/net/can/bcm.c index 092dc88a7c6..871a0ad5102 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
| @@ -1569,7 +1569,7 @@ static int bcm_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1569 | return size; | 1569 | return size; |
| 1570 | } | 1570 | } |
| 1571 | 1571 | ||
| 1572 | static struct proto_ops bcm_ops __read_mostly = { | 1572 | static const struct proto_ops bcm_ops = { |
| 1573 | .family = PF_CAN, | 1573 | .family = PF_CAN, |
| 1574 | .release = bcm_release, | 1574 | .release = bcm_release, |
| 1575 | .bind = sock_no_bind, | 1575 | .bind = sock_no_bind, |
| @@ -1578,7 +1578,7 @@ static struct proto_ops bcm_ops __read_mostly = { | |||
| 1578 | .accept = sock_no_accept, | 1578 | .accept = sock_no_accept, |
| 1579 | .getname = sock_no_getname, | 1579 | .getname = sock_no_getname, |
| 1580 | .poll = datagram_poll, | 1580 | .poll = datagram_poll, |
| 1581 | .ioctl = NULL, /* use can_ioctl() from af_can.c */ | 1581 | .ioctl = can_ioctl, /* use can_ioctl() from af_can.c */ |
| 1582 | .listen = sock_no_listen, | 1582 | .listen = sock_no_listen, |
| 1583 | .shutdown = sock_no_shutdown, | 1583 | .shutdown = sock_no_shutdown, |
| 1584 | .setsockopt = sock_no_setsockopt, | 1584 | .setsockopt = sock_no_setsockopt, |
diff --git a/net/can/raw.c b/net/can/raw.c index 883e9d74fdd..649acfa7c70 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
| @@ -742,7 +742,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 742 | return size; | 742 | return size; |
| 743 | } | 743 | } |
| 744 | 744 | ||
| 745 | static struct proto_ops raw_ops __read_mostly = { | 745 | static const struct proto_ops raw_ops = { |
| 746 | .family = PF_CAN, | 746 | .family = PF_CAN, |
| 747 | .release = raw_release, | 747 | .release = raw_release, |
| 748 | .bind = raw_bind, | 748 | .bind = raw_bind, |
| @@ -751,7 +751,7 @@ static struct proto_ops raw_ops __read_mostly = { | |||
| 751 | .accept = sock_no_accept, | 751 | .accept = sock_no_accept, |
| 752 | .getname = raw_getname, | 752 | .getname = raw_getname, |
| 753 | .poll = datagram_poll, | 753 | .poll = datagram_poll, |
| 754 | .ioctl = NULL, /* use can_ioctl() from af_can.c */ | 754 | .ioctl = can_ioctl, /* use can_ioctl() from af_can.c */ |
| 755 | .listen = sock_no_listen, | 755 | .listen = sock_no_listen, |
| 756 | .shutdown = sock_no_shutdown, | 756 | .shutdown = sock_no_shutdown, |
| 757 | .setsockopt = raw_setsockopt, | 757 | .setsockopt = raw_setsockopt, |
diff --git a/net/core/dev.c b/net/core/dev.c index f453370131a..563ddc28139 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -1140,9 +1140,6 @@ static int __dev_open(struct net_device *dev) | |||
| 1140 | 1140 | ||
| 1141 | ASSERT_RTNL(); | 1141 | ASSERT_RTNL(); |
| 1142 | 1142 | ||
| 1143 | /* | ||
| 1144 | * Is it even present? | ||
| 1145 | */ | ||
| 1146 | if (!netif_device_present(dev)) | 1143 | if (!netif_device_present(dev)) |
| 1147 | return -ENODEV; | 1144 | return -ENODEV; |
| 1148 | 1145 | ||
| @@ -1151,9 +1148,6 @@ static int __dev_open(struct net_device *dev) | |||
| 1151 | if (ret) | 1148 | if (ret) |
| 1152 | return ret; | 1149 | return ret; |
| 1153 | 1150 | ||
| 1154 | /* | ||
| 1155 | * Call device private open method | ||
| 1156 | */ | ||
| 1157 | set_bit(__LINK_STATE_START, &dev->state); | 1151 | set_bit(__LINK_STATE_START, &dev->state); |
| 1158 | 1152 | ||
| 1159 | if (ops->ndo_validate_addr) | 1153 | if (ops->ndo_validate_addr) |
| @@ -1162,31 +1156,12 @@ static int __dev_open(struct net_device *dev) | |||
| 1162 | if (!ret && ops->ndo_open) | 1156 | if (!ret && ops->ndo_open) |
| 1163 | ret = ops->ndo_open(dev); | 1157 | ret = ops->ndo_open(dev); |
| 1164 | 1158 | ||
| 1165 | /* | ||
| 1166 | * If it went open OK then: | ||
| 1167 | */ | ||
| 1168 | |||
| 1169 | if (ret) | 1159 | if (ret) |
| 1170 | clear_bit(__LINK_STATE_START, &dev->state); | 1160 | clear_bit(__LINK_STATE_START, &dev->state); |
| 1171 | else { | 1161 | else { |
| 1172 | /* | ||
| 1173 | * Set the flags. | ||
| 1174 | */ | ||
| 1175 | dev->flags |= IFF_UP; | 1162 | dev->flags |= IFF_UP; |
| 1176 | |||
| 1177 | /* | ||
| 1178 | * Enable NET_DMA | ||
| 1179 | */ | ||
| 1180 | net_dmaengine_get(); | 1163 | net_dmaengine_get(); |
| 1181 | |||
| 1182 | /* | ||
| 1183 | * Initialize multicasting status | ||
| 1184 | */ | ||
| 1185 | dev_set_rx_mode(dev); | 1164 | dev_set_rx_mode(dev); |
| 1186 | |||
| 1187 | /* | ||
| 1188 | * Wakeup transmit queue engine | ||
| 1189 | */ | ||
| 1190 | dev_activate(dev); | 1165 | dev_activate(dev); |
| 1191 | } | 1166 | } |
| 1192 | 1167 | ||
| @@ -1209,22 +1184,13 @@ int dev_open(struct net_device *dev) | |||
| 1209 | { | 1184 | { |
| 1210 | int ret; | 1185 | int ret; |
| 1211 | 1186 | ||
| 1212 | /* | ||
| 1213 | * Is it already up? | ||
| 1214 | */ | ||
| 1215 | if (dev->flags & IFF_UP) | 1187 | if (dev->flags & IFF_UP) |
| 1216 | return 0; | 1188 | return 0; |
| 1217 | 1189 | ||
| 1218 | /* | ||
| 1219 | * Open device | ||
| 1220 | */ | ||
| 1221 | ret = __dev_open(dev); | 1190 | ret = __dev_open(dev); |
| 1222 | if (ret < 0) | 1191 | if (ret < 0) |
| 1223 | return ret; | 1192 | return ret; |
| 1224 | 1193 | ||
| 1225 | /* | ||
| 1226 | * ... and announce new interface. | ||
| 1227 | */ | ||
| 1228 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); | 1194 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); |
| 1229 | call_netdevice_notifiers(NETDEV_UP, dev); | 1195 | call_netdevice_notifiers(NETDEV_UP, dev); |
| 1230 | 1196 | ||
| @@ -1240,10 +1206,6 @@ static int __dev_close_many(struct list_head *head) | |||
| 1240 | might_sleep(); | 1206 | might_sleep(); |
| 1241 | 1207 | ||
| 1242 | list_for_each_entry(dev, head, unreg_list) { | 1208 | list_for_each_entry(dev, head, unreg_list) { |
| 1243 | /* | ||
| 1244 | * Tell people we are going down, so that they can | ||
| 1245 | * prepare to death, when device is still operating. | ||
| 1246 | */ | ||
| 1247 | call_netdevice_notifiers(NETDEV_GOING_DOWN, dev); | 1209 | call_netdevice_notifiers(NETDEV_GOING_DOWN, dev); |
| 1248 | 1210 | ||
| 1249 | clear_bit(__LINK_STATE_START, &dev->state); | 1211 | clear_bit(__LINK_STATE_START, &dev->state); |
| @@ -1272,15 +1234,7 @@ static int __dev_close_many(struct list_head *head) | |||
| 1272 | if (ops->ndo_stop) | 1234 | if (ops->ndo_stop) |
| 1273 | ops->ndo_stop(dev); | 1235 | ops->ndo_stop(dev); |
| 1274 | 1236 | ||
| 1275 | /* | ||
| 1276 | * Device is now down. | ||
| 1277 | */ | ||
| 1278 | |||
| 1279 | dev->flags &= ~IFF_UP; | 1237 | dev->flags &= ~IFF_UP; |
| 1280 | |||
| 1281 | /* | ||
| 1282 | * Shutdown NET_DMA | ||
| 1283 | */ | ||
| 1284 | net_dmaengine_put(); | 1238 | net_dmaengine_put(); |
| 1285 | } | 1239 | } |
| 1286 | 1240 | ||
| @@ -1309,9 +1263,6 @@ static int dev_close_many(struct list_head *head) | |||
| 1309 | 1263 | ||
| 1310 | __dev_close_many(head); | 1264 | __dev_close_many(head); |
| 1311 | 1265 | ||
| 1312 | /* | ||
| 1313 | * Tell people we are down | ||
| 1314 | */ | ||
| 1315 | list_for_each_entry(dev, head, unreg_list) { | 1266 | list_for_each_entry(dev, head, unreg_list) { |
| 1316 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); | 1267 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); |
| 1317 | call_netdevice_notifiers(NETDEV_DOWN, dev); | 1268 | call_netdevice_notifiers(NETDEV_DOWN, dev); |
| @@ -1371,11 +1322,6 @@ EXPORT_SYMBOL(dev_disable_lro); | |||
| 1371 | 1322 | ||
| 1372 | static int dev_boot_phase = 1; | 1323 | static int dev_boot_phase = 1; |
| 1373 | 1324 | ||
| 1374 | /* | ||
| 1375 | * Device change register/unregister. These are not inline or static | ||
| 1376 | * as we export them to the world. | ||
| 1377 | */ | ||
| 1378 | |||
| 1379 | /** | 1325 | /** |
| 1380 | * register_netdevice_notifier - register a network notifier block | 1326 | * register_netdevice_notifier - register a network notifier block |
| 1381 | * @nb: notifier | 1327 | * @nb: notifier |
| @@ -1477,6 +1423,7 @@ int call_netdevice_notifiers(unsigned long val, struct net_device *dev) | |||
| 1477 | ASSERT_RTNL(); | 1423 | ASSERT_RTNL(); |
| 1478 | return raw_notifier_call_chain(&netdev_chain, val, dev); | 1424 | return raw_notifier_call_chain(&netdev_chain, val, dev); |
| 1479 | } | 1425 | } |
| 1426 | EXPORT_SYMBOL(call_netdevice_notifiers); | ||
| 1480 | 1427 | ||
| 1481 | /* When > 0 there are consumers of rx skb time stamps */ | 1428 | /* When > 0 there are consumers of rx skb time stamps */ |
| 1482 | static atomic_t netstamp_needed = ATOMIC_INIT(0); | 1429 | static atomic_t netstamp_needed = ATOMIC_INIT(0); |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 24bd57493c0..74ead9eca12 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
| @@ -141,9 +141,24 @@ u32 ethtool_op_get_flags(struct net_device *dev) | |||
| 141 | } | 141 | } |
| 142 | EXPORT_SYMBOL(ethtool_op_get_flags); | 142 | EXPORT_SYMBOL(ethtool_op_get_flags); |
| 143 | 143 | ||
| 144 | /* Check if device can enable (or disable) particular feature coded in "data" | ||
| 145 | * argument. Flags "supported" describe features that can be toggled by device. | ||
| 146 | * If feature can not be toggled, it state (enabled or disabled) must match | ||
| 147 | * hardcoded device features state, otherwise flags are marked as invalid. | ||
| 148 | */ | ||
| 149 | bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported) | ||
| 150 | { | ||
| 151 | u32 features = dev->features & flags_dup_features; | ||
| 152 | /* "data" can contain only flags_dup_features bits, | ||
| 153 | * see __ethtool_set_flags */ | ||
| 154 | |||
| 155 | return (features & ~supported) != (data & ~supported); | ||
| 156 | } | ||
| 157 | EXPORT_SYMBOL(ethtool_invalid_flags); | ||
| 158 | |||
| 144 | int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported) | 159 | int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported) |
| 145 | { | 160 | { |
| 146 | if (data & ~supported) | 161 | if (ethtool_invalid_flags(dev, data, supported)) |
| 147 | return -EINVAL; | 162 | return -EINVAL; |
| 148 | 163 | ||
| 149 | dev->features = ((dev->features & ~flags_dup_features) | | 164 | dev->features = ((dev->features & ~flags_dup_features) | |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 90a3ff60559..b92c86f6e9b 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
| @@ -1365,9 +1365,9 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l, | |||
| 1365 | err = fib_props[fa->fa_type].error; | 1365 | err = fib_props[fa->fa_type].error; |
| 1366 | if (err) { | 1366 | if (err) { |
| 1367 | #ifdef CONFIG_IP_FIB_TRIE_STATS | 1367 | #ifdef CONFIG_IP_FIB_TRIE_STATS |
| 1368 | t->stats.semantic_match_miss++; | 1368 | t->stats.semantic_match_passed++; |
| 1369 | #endif | 1369 | #endif |
| 1370 | return 1; | 1370 | return err; |
| 1371 | } | 1371 | } |
| 1372 | if (fi->fib_flags & RTNH_F_DEAD) | 1372 | if (fi->fib_flags & RTNH_F_DEAD) |
| 1373 | continue; | 1373 | continue; |
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 1906fa35860..28a736f3442 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c | |||
| @@ -140,11 +140,11 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) | |||
| 140 | } else { | 140 | } else { |
| 141 | dopt->ts_needtime = 0; | 141 | dopt->ts_needtime = 0; |
| 142 | 142 | ||
| 143 | if (soffset + 8 <= optlen) { | 143 | if (soffset + 7 <= optlen) { |
| 144 | __be32 addr; | 144 | __be32 addr; |
| 145 | 145 | ||
| 146 | memcpy(&addr, sptr+soffset-1, 4); | 146 | memcpy(&addr, dptr+soffset-1, 4); |
| 147 | if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_LOCAL) { | 147 | if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_UNICAST) { |
| 148 | dopt->ts_needtime = 1; | 148 | dopt->ts_needtime = 1; |
| 149 | soffset += 8; | 149 | soffset += 8; |
| 150 | } | 150 | } |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index e837ffd3edc..2d3c72e5bbb 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
| @@ -569,6 +569,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
| 569 | rt = ip_route_output_flow(sock_net(sk), &fl4, sk); | 569 | rt = ip_route_output_flow(sock_net(sk), &fl4, sk); |
| 570 | if (IS_ERR(rt)) { | 570 | if (IS_ERR(rt)) { |
| 571 | err = PTR_ERR(rt); | 571 | err = PTR_ERR(rt); |
| 572 | rt = NULL; | ||
| 572 | goto done; | 573 | goto done; |
| 573 | } | 574 | } |
| 574 | } | 575 | } |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 7ff0343e05c..29e48593bf2 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
| @@ -663,7 +663,7 @@ static int pim6_rcv(struct sk_buff *skb) | |||
| 663 | skb_pull(skb, (u8 *)encap - skb->data); | 663 | skb_pull(skb, (u8 *)encap - skb->data); |
| 664 | skb_reset_network_header(skb); | 664 | skb_reset_network_header(skb); |
| 665 | skb->protocol = htons(ETH_P_IPV6); | 665 | skb->protocol = htons(ETH_P_IPV6); |
| 666 | skb->ip_summed = 0; | 666 | skb->ip_summed = CHECKSUM_NONE; |
| 667 | skb->pkt_type = PACKET_HOST; | 667 | skb->pkt_type = PACKET_HOST; |
| 668 | 668 | ||
| 669 | skb_tunnel_rx(skb, reg_dev); | 669 | skb_tunnel_rx(skb, reg_dev); |
diff --git a/net/irda/iriap.c b/net/irda/iriap.c index 5b743bdd89b..36477538cea 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c | |||
| @@ -656,10 +656,16 @@ static void iriap_getvaluebyclass_indication(struct iriap_cb *self, | |||
| 656 | n = 1; | 656 | n = 1; |
| 657 | 657 | ||
| 658 | name_len = fp[n++]; | 658 | name_len = fp[n++]; |
| 659 | |||
| 660 | IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;); | ||
| 661 | |||
| 659 | memcpy(name, fp+n, name_len); n+=name_len; | 662 | memcpy(name, fp+n, name_len); n+=name_len; |
| 660 | name[name_len] = '\0'; | 663 | name[name_len] = '\0'; |
| 661 | 664 | ||
| 662 | attr_len = fp[n++]; | 665 | attr_len = fp[n++]; |
| 666 | |||
| 667 | IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;); | ||
| 668 | |||
| 663 | memcpy(attr, fp+n, attr_len); n+=attr_len; | 669 | memcpy(attr, fp+n, attr_len); n+=attr_len; |
| 664 | attr[attr_len] = '\0'; | 670 | attr[attr_len] = '\0'; |
| 665 | 671 | ||
diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c index 7c567b8aa89..2bb2beb6a37 100644 --- a/net/irda/irnet/irnet_ppp.c +++ b/net/irda/irnet/irnet_ppp.c | |||
| @@ -105,6 +105,9 @@ irnet_ctrl_write(irnet_socket * ap, | |||
| 105 | while(isspace(start[length - 1])) | 105 | while(isspace(start[length - 1])) |
| 106 | length--; | 106 | length--; |
| 107 | 107 | ||
| 108 | DABORT(length < 5 || length > NICKNAME_MAX_LEN + 5, | ||
| 109 | -EINVAL, CTRL_ERROR, "Invalid nickname.\n"); | ||
| 110 | |||
| 108 | /* Copy the name for later reuse */ | 111 | /* Copy the name for later reuse */ |
| 109 | memcpy(ap->rname, start + 5, length - 5); | 112 | memcpy(ap->rname, start + 5, length - 5); |
| 110 | ap->rname[length - 5] = '\0'; | 113 | ap->rname[length - 5] = '\0'; |
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 5ee0c62046a..a80aef6e3d1 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
| @@ -978,7 +978,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros | |||
| 978 | struct sock *make; | 978 | struct sock *make; |
| 979 | struct rose_sock *make_rose; | 979 | struct rose_sock *make_rose; |
| 980 | struct rose_facilities_struct facilities; | 980 | struct rose_facilities_struct facilities; |
| 981 | int n, len; | 981 | int n; |
| 982 | 982 | ||
| 983 | skb->sk = NULL; /* Initially we don't know who it's for */ | 983 | skb->sk = NULL; /* Initially we don't know who it's for */ |
| 984 | 984 | ||
| @@ -987,9 +987,9 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros | |||
| 987 | */ | 987 | */ |
| 988 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); | 988 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); |
| 989 | 989 | ||
| 990 | len = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1; | 990 | if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF, |
| 991 | len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1; | 991 | skb->len - ROSE_CALL_REQ_FACILITIES_OFF, |
| 992 | if (!rose_parse_facilities(skb->data + len + 4, &facilities)) { | 992 | &facilities)) { |
| 993 | rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76); | 993 | rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76); |
| 994 | return 0; | 994 | return 0; |
| 995 | } | 995 | } |
diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.c index ae4a9d99aec..344456206b7 100644 --- a/net/rose/rose_loopback.c +++ b/net/rose/rose_loopback.c | |||
| @@ -73,9 +73,20 @@ static void rose_loopback_timer(unsigned long param) | |||
| 73 | unsigned int lci_i, lci_o; | 73 | unsigned int lci_i, lci_o; |
| 74 | 74 | ||
| 75 | while ((skb = skb_dequeue(&loopback_queue)) != NULL) { | 75 | while ((skb = skb_dequeue(&loopback_queue)) != NULL) { |
| 76 | if (skb->len < ROSE_MIN_LEN) { | ||
| 77 | kfree_skb(skb); | ||
| 78 | continue; | ||
| 79 | } | ||
| 76 | lci_i = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); | 80 | lci_i = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); |
| 77 | frametype = skb->data[2]; | 81 | frametype = skb->data[2]; |
| 78 | dest = (rose_address *)(skb->data + 4); | 82 | if (frametype == ROSE_CALL_REQUEST && |
| 83 | (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF || | ||
| 84 | skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] != | ||
| 85 | ROSE_CALL_REQ_ADDR_LEN_VAL)) { | ||
| 86 | kfree_skb(skb); | ||
| 87 | continue; | ||
| 88 | } | ||
| 89 | dest = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF); | ||
| 79 | lci_o = ROSE_DEFAULT_MAXVC + 1 - lci_i; | 90 | lci_o = ROSE_DEFAULT_MAXVC + 1 - lci_i; |
| 80 | 91 | ||
| 81 | skb_reset_transport_header(skb); | 92 | skb_reset_transport_header(skb); |
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 88a77e90e7e..08dcd2f29cd 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c | |||
| @@ -861,7 +861,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
| 861 | unsigned int lci, new_lci; | 861 | unsigned int lci, new_lci; |
| 862 | unsigned char cause, diagnostic; | 862 | unsigned char cause, diagnostic; |
| 863 | struct net_device *dev; | 863 | struct net_device *dev; |
| 864 | int len, res = 0; | 864 | int res = 0; |
| 865 | char buf[11]; | 865 | char buf[11]; |
| 866 | 866 | ||
| 867 | #if 0 | 867 | #if 0 |
| @@ -869,10 +869,17 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
| 869 | return res; | 869 | return res; |
| 870 | #endif | 870 | #endif |
| 871 | 871 | ||
| 872 | if (skb->len < ROSE_MIN_LEN) | ||
| 873 | return res; | ||
| 872 | frametype = skb->data[2]; | 874 | frametype = skb->data[2]; |
| 873 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); | 875 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); |
| 874 | src_addr = (rose_address *)(skb->data + 9); | 876 | if (frametype == ROSE_CALL_REQUEST && |
| 875 | dest_addr = (rose_address *)(skb->data + 4); | 877 | (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF || |
| 878 | skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] != | ||
| 879 | ROSE_CALL_REQ_ADDR_LEN_VAL)) | ||
| 880 | return res; | ||
| 881 | src_addr = (rose_address *)(skb->data + ROSE_CALL_REQ_SRC_ADDR_OFF); | ||
| 882 | dest_addr = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF); | ||
| 876 | 883 | ||
| 877 | spin_lock_bh(&rose_neigh_list_lock); | 884 | spin_lock_bh(&rose_neigh_list_lock); |
| 878 | spin_lock_bh(&rose_route_list_lock); | 885 | spin_lock_bh(&rose_route_list_lock); |
| @@ -1010,12 +1017,11 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
| 1010 | goto out; | 1017 | goto out; |
| 1011 | } | 1018 | } |
| 1012 | 1019 | ||
| 1013 | len = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1; | ||
| 1014 | len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1; | ||
| 1015 | |||
| 1016 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); | 1020 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); |
| 1017 | 1021 | ||
| 1018 | if (!rose_parse_facilities(skb->data + len + 4, &facilities)) { | 1022 | if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF, |
| 1023 | skb->len - ROSE_CALL_REQ_FACILITIES_OFF, | ||
| 1024 | &facilities)) { | ||
| 1019 | rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76); | 1025 | rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76); |
| 1020 | goto out; | 1026 | goto out; |
| 1021 | } | 1027 | } |
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index 1734abba26a..f6c71caa94b 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c | |||
| @@ -142,7 +142,7 @@ void rose_write_internal(struct sock *sk, int frametype) | |||
| 142 | *dptr++ = ROSE_GFI | lci1; | 142 | *dptr++ = ROSE_GFI | lci1; |
| 143 | *dptr++ = lci2; | 143 | *dptr++ = lci2; |
| 144 | *dptr++ = frametype; | 144 | *dptr++ = frametype; |
| 145 | *dptr++ = 0xAA; | 145 | *dptr++ = ROSE_CALL_REQ_ADDR_LEN_VAL; |
| 146 | memcpy(dptr, &rose->dest_addr, ROSE_ADDR_LEN); | 146 | memcpy(dptr, &rose->dest_addr, ROSE_ADDR_LEN); |
| 147 | dptr += ROSE_ADDR_LEN; | 147 | dptr += ROSE_ADDR_LEN; |
| 148 | memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN); | 148 | memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN); |
| @@ -246,12 +246,16 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct * | |||
| 246 | do { | 246 | do { |
| 247 | switch (*p & 0xC0) { | 247 | switch (*p & 0xC0) { |
| 248 | case 0x00: | 248 | case 0x00: |
| 249 | if (len < 2) | ||
| 250 | return -1; | ||
| 249 | p += 2; | 251 | p += 2; |
| 250 | n += 2; | 252 | n += 2; |
| 251 | len -= 2; | 253 | len -= 2; |
| 252 | break; | 254 | break; |
| 253 | 255 | ||
| 254 | case 0x40: | 256 | case 0x40: |
| 257 | if (len < 3) | ||
| 258 | return -1; | ||
| 255 | if (*p == FAC_NATIONAL_RAND) | 259 | if (*p == FAC_NATIONAL_RAND) |
| 256 | facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF); | 260 | facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF); |
| 257 | p += 3; | 261 | p += 3; |
| @@ -260,40 +264,61 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct * | |||
| 260 | break; | 264 | break; |
| 261 | 265 | ||
| 262 | case 0x80: | 266 | case 0x80: |
| 267 | if (len < 4) | ||
| 268 | return -1; | ||
| 263 | p += 4; | 269 | p += 4; |
| 264 | n += 4; | 270 | n += 4; |
| 265 | len -= 4; | 271 | len -= 4; |
| 266 | break; | 272 | break; |
| 267 | 273 | ||
| 268 | case 0xC0: | 274 | case 0xC0: |
| 275 | if (len < 2) | ||
| 276 | return -1; | ||
| 269 | l = p[1]; | 277 | l = p[1]; |
| 278 | if (len < 2 + l) | ||
| 279 | return -1; | ||
| 270 | if (*p == FAC_NATIONAL_DEST_DIGI) { | 280 | if (*p == FAC_NATIONAL_DEST_DIGI) { |
| 271 | if (!fac_national_digis_received) { | 281 | if (!fac_national_digis_received) { |
| 282 | if (l < AX25_ADDR_LEN) | ||
| 283 | return -1; | ||
| 272 | memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN); | 284 | memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN); |
| 273 | facilities->source_ndigis = 1; | 285 | facilities->source_ndigis = 1; |
| 274 | } | 286 | } |
| 275 | } | 287 | } |
| 276 | else if (*p == FAC_NATIONAL_SRC_DIGI) { | 288 | else if (*p == FAC_NATIONAL_SRC_DIGI) { |
| 277 | if (!fac_national_digis_received) { | 289 | if (!fac_national_digis_received) { |
| 290 | if (l < AX25_ADDR_LEN) | ||
| 291 | return -1; | ||
| 278 | memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN); | 292 | memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN); |
| 279 | facilities->dest_ndigis = 1; | 293 | facilities->dest_ndigis = 1; |
| 280 | } | 294 | } |
| 281 | } | 295 | } |
| 282 | else if (*p == FAC_NATIONAL_FAIL_CALL) { | 296 | else if (*p == FAC_NATIONAL_FAIL_CALL) { |
| 297 | if (l < AX25_ADDR_LEN) | ||
| 298 | return -1; | ||
| 283 | memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN); | 299 | memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN); |
| 284 | } | 300 | } |
| 285 | else if (*p == FAC_NATIONAL_FAIL_ADD) { | 301 | else if (*p == FAC_NATIONAL_FAIL_ADD) { |
| 302 | if (l < 1 + ROSE_ADDR_LEN) | ||
| 303 | return -1; | ||
| 286 | memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN); | 304 | memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN); |
| 287 | } | 305 | } |
| 288 | else if (*p == FAC_NATIONAL_DIGIS) { | 306 | else if (*p == FAC_NATIONAL_DIGIS) { |
| 307 | if (l % AX25_ADDR_LEN) | ||
| 308 | return -1; | ||
| 289 | fac_national_digis_received = 1; | 309 | fac_national_digis_received = 1; |
| 290 | facilities->source_ndigis = 0; | 310 | facilities->source_ndigis = 0; |
| 291 | facilities->dest_ndigis = 0; | 311 | facilities->dest_ndigis = 0; |
| 292 | for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) { | 312 | for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) { |
| 293 | if (pt[6] & AX25_HBIT) | 313 | if (pt[6] & AX25_HBIT) { |
| 314 | if (facilities->dest_ndigis >= ROSE_MAX_DIGIS) | ||
| 315 | return -1; | ||
| 294 | memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN); | 316 | memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN); |
| 295 | else | 317 | } else { |
| 318 | if (facilities->source_ndigis >= ROSE_MAX_DIGIS) | ||
| 319 | return -1; | ||
| 296 | memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN); | 320 | memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN); |
| 321 | } | ||
| 297 | } | 322 | } |
| 298 | } | 323 | } |
| 299 | p += l + 2; | 324 | p += l + 2; |
| @@ -314,25 +339,38 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac | |||
| 314 | do { | 339 | do { |
| 315 | switch (*p & 0xC0) { | 340 | switch (*p & 0xC0) { |
| 316 | case 0x00: | 341 | case 0x00: |
| 342 | if (len < 2) | ||
| 343 | return -1; | ||
| 317 | p += 2; | 344 | p += 2; |
| 318 | n += 2; | 345 | n += 2; |
| 319 | len -= 2; | 346 | len -= 2; |
| 320 | break; | 347 | break; |
| 321 | 348 | ||
| 322 | case 0x40: | 349 | case 0x40: |
| 350 | if (len < 3) | ||
| 351 | return -1; | ||
| 323 | p += 3; | 352 | p += 3; |
| 324 | n += 3; | 353 | n += 3; |
| 325 | len -= 3; | 354 | len -= 3; |
| 326 | break; | 355 | break; |
| 327 | 356 | ||
| 328 | case 0x80: | 357 | case 0x80: |
| 358 | if (len < 4) | ||
| 359 | return -1; | ||
| 329 | p += 4; | 360 | p += 4; |
| 330 | n += 4; | 361 | n += 4; |
| 331 | len -= 4; | 362 | len -= 4; |
| 332 | break; | 363 | break; |
| 333 | 364 | ||
| 334 | case 0xC0: | 365 | case 0xC0: |
| 366 | if (len < 2) | ||
| 367 | return -1; | ||
| 335 | l = p[1]; | 368 | l = p[1]; |
| 369 | |||
| 370 | /* Prevent overflows*/ | ||
| 371 | if (l < 10 || l > 20) | ||
| 372 | return -1; | ||
| 373 | |||
| 336 | if (*p == FAC_CCITT_DEST_NSAP) { | 374 | if (*p == FAC_CCITT_DEST_NSAP) { |
| 337 | memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); | 375 | memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); |
| 338 | memcpy(callsign, p + 12, l - 10); | 376 | memcpy(callsign, p + 12, l - 10); |
| @@ -355,45 +393,44 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac | |||
| 355 | return n; | 393 | return n; |
| 356 | } | 394 | } |
| 357 | 395 | ||
| 358 | int rose_parse_facilities(unsigned char *p, | 396 | int rose_parse_facilities(unsigned char *p, unsigned packet_len, |
| 359 | struct rose_facilities_struct *facilities) | 397 | struct rose_facilities_struct *facilities) |
| 360 | { | 398 | { |
| 361 | int facilities_len, len; | 399 | int facilities_len, len; |
| 362 | 400 | ||
| 363 | facilities_len = *p++; | 401 | facilities_len = *p++; |
| 364 | 402 | ||
| 365 | if (facilities_len == 0) | 403 | if (facilities_len == 0 || (unsigned)facilities_len > packet_len) |
| 366 | return 0; | 404 | return 0; |
| 367 | 405 | ||
| 368 | while (facilities_len > 0) { | 406 | while (facilities_len >= 3 && *p == 0x00) { |
| 369 | if (*p == 0x00) { | 407 | facilities_len--; |
| 370 | facilities_len--; | 408 | p++; |
| 371 | p++; | 409 | |
| 372 | 410 | switch (*p) { | |
| 373 | switch (*p) { | 411 | case FAC_NATIONAL: /* National */ |
| 374 | case FAC_NATIONAL: /* National */ | 412 | len = rose_parse_national(p + 1, facilities, facilities_len - 1); |
| 375 | len = rose_parse_national(p + 1, facilities, facilities_len - 1); | 413 | break; |
| 376 | facilities_len -= len + 1; | 414 | |
| 377 | p += len + 1; | 415 | case FAC_CCITT: /* CCITT */ |
| 378 | break; | 416 | len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1); |
| 379 | 417 | break; | |
| 380 | case FAC_CCITT: /* CCITT */ | 418 | |
| 381 | len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1); | 419 | default: |
| 382 | facilities_len -= len + 1; | 420 | printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p); |
| 383 | p += len + 1; | 421 | len = 1; |
| 384 | break; | 422 | break; |
| 385 | 423 | } | |
| 386 | default: | 424 | |
| 387 | printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p); | 425 | if (len < 0) |
| 388 | facilities_len--; | 426 | return 0; |
| 389 | p++; | 427 | if (WARN_ON(len >= facilities_len)) |
| 390 | break; | 428 | return 0; |
| 391 | } | 429 | facilities_len -= len + 1; |
| 392 | } else | 430 | p += len + 1; |
| 393 | break; /* Error in facilities format */ | ||
| 394 | } | 431 | } |
| 395 | 432 | ||
| 396 | return 1; | 433 | return facilities_len == 0; |
| 397 | } | 434 | } |
| 398 | 435 | ||
| 399 | static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose) | 436 | static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose) |
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 872065ca7f8..a026b0ef244 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c | |||
| @@ -173,7 +173,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
| 173 | goto drop_unlock; | 173 | goto drop_unlock; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | if (x->props.replay_window && x->repl->check(x, skb, seq)) { | 176 | if (x->repl->check(x, skb, seq)) { |
| 177 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); | 177 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); |
| 178 | goto drop_unlock; | 178 | goto drop_unlock; |
| 179 | } | 179 | } |
| @@ -190,6 +190,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
| 190 | XFRM_SKB_CB(skb)->seq.input.low = seq; | 190 | XFRM_SKB_CB(skb)->seq.input.low = seq; |
| 191 | XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; | 191 | XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; |
| 192 | 192 | ||
| 193 | skb_dst_force(skb); | ||
| 194 | |||
| 193 | nexthdr = x->type->input(x, skb); | 195 | nexthdr = x->type->input(x, skb); |
| 194 | 196 | ||
| 195 | if (nexthdr == -EINPROGRESS) | 197 | if (nexthdr == -EINPROGRESS) |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 1aba03f449c..47bacd8c025 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
| @@ -78,6 +78,8 @@ static int xfrm_output_one(struct sk_buff *skb, int err) | |||
| 78 | 78 | ||
| 79 | spin_unlock_bh(&x->lock); | 79 | spin_unlock_bh(&x->lock); |
| 80 | 80 | ||
| 81 | skb_dst_force(skb); | ||
| 82 | |||
| 81 | err = x->type->output(x, skb); | 83 | err = x->type->output(x, skb); |
| 82 | if (err == -EINPROGRESS) | 84 | if (err == -EINPROGRESS) |
| 83 | goto out_exit; | 85 | goto out_exit; |
| @@ -94,7 +96,7 @@ resume: | |||
| 94 | err = -EHOSTUNREACH; | 96 | err = -EHOSTUNREACH; |
| 95 | goto error_nolock; | 97 | goto error_nolock; |
| 96 | } | 98 | } |
| 97 | skb_dst_set(skb, dst_clone(dst)); | 99 | skb_dst_set(skb, dst); |
| 98 | x = dst->xfrm; | 100 | x = dst->xfrm; |
| 99 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); | 101 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); |
| 100 | 102 | ||
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 2f5be5b1574..f218385950c 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c | |||
| @@ -118,6 +118,9 @@ static int xfrm_replay_check(struct xfrm_state *x, | |||
| 118 | u32 diff; | 118 | u32 diff; |
| 119 | u32 seq = ntohl(net_seq); | 119 | u32 seq = ntohl(net_seq); |
| 120 | 120 | ||
| 121 | if (!x->props.replay_window) | ||
| 122 | return 0; | ||
| 123 | |||
| 121 | if (unlikely(seq == 0)) | 124 | if (unlikely(seq == 0)) |
| 122 | goto err; | 125 | goto err; |
| 123 | 126 | ||
| @@ -193,9 +196,14 @@ static int xfrm_replay_check_bmp(struct xfrm_state *x, | |||
| 193 | { | 196 | { |
| 194 | unsigned int bitnr, nr; | 197 | unsigned int bitnr, nr; |
| 195 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; | 198 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; |
| 199 | u32 pos; | ||
| 196 | u32 seq = ntohl(net_seq); | 200 | u32 seq = ntohl(net_seq); |
| 197 | u32 diff = replay_esn->seq - seq; | 201 | u32 diff = replay_esn->seq - seq; |
| 198 | u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window; | 202 | |
| 203 | if (!replay_esn->replay_window) | ||
| 204 | return 0; | ||
| 205 | |||
| 206 | pos = (replay_esn->seq - 1) % replay_esn->replay_window; | ||
| 199 | 207 | ||
| 200 | if (unlikely(seq == 0)) | 208 | if (unlikely(seq == 0)) |
| 201 | goto err; | 209 | goto err; |
| @@ -373,12 +381,17 @@ static int xfrm_replay_check_esn(struct xfrm_state *x, | |||
| 373 | unsigned int bitnr, nr; | 381 | unsigned int bitnr, nr; |
| 374 | u32 diff; | 382 | u32 diff; |
| 375 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; | 383 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; |
| 384 | u32 pos; | ||
| 376 | u32 seq = ntohl(net_seq); | 385 | u32 seq = ntohl(net_seq); |
| 377 | u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window; | ||
| 378 | u32 wsize = replay_esn->replay_window; | 386 | u32 wsize = replay_esn->replay_window; |
| 379 | u32 top = replay_esn->seq; | 387 | u32 top = replay_esn->seq; |
| 380 | u32 bottom = top - wsize + 1; | 388 | u32 bottom = top - wsize + 1; |
| 381 | 389 | ||
| 390 | if (!wsize) | ||
| 391 | return 0; | ||
| 392 | |||
| 393 | pos = (replay_esn->seq - 1) % replay_esn->replay_window; | ||
| 394 | |||
| 382 | if (unlikely(seq == 0 && replay_esn->seq_hi == 0 && | 395 | if (unlikely(seq == 0 && replay_esn->seq_hi == 0 && |
| 383 | (replay_esn->seq < replay_esn->replay_window - 1))) | 396 | (replay_esn->seq < replay_esn->replay_window - 1))) |
| 384 | goto err; | 397 | goto err; |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index f83a3d1da81..dd78536d40d 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -1181,6 +1181,12 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | |||
| 1181 | goto error; | 1181 | goto error; |
| 1182 | } | 1182 | } |
| 1183 | 1183 | ||
| 1184 | if (orig->replay_esn) { | ||
| 1185 | err = xfrm_replay_clone(x, orig); | ||
| 1186 | if (err) | ||
| 1187 | goto error; | ||
| 1188 | } | ||
| 1189 | |||
| 1184 | memcpy(&x->mark, &orig->mark, sizeof(x->mark)); | 1190 | memcpy(&x->mark, &orig->mark, sizeof(x->mark)); |
| 1185 | 1191 | ||
| 1186 | err = xfrm_init_state(x); | 1192 | err = xfrm_init_state(x); |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index fc152d28753..3d15d3e1b2c 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
| @@ -127,6 +127,9 @@ static inline int verify_replay(struct xfrm_usersa_info *p, | |||
| 127 | if (!rt) | 127 | if (!rt) |
| 128 | return 0; | 128 | return 0; |
| 129 | 129 | ||
| 130 | if (p->id.proto != IPPROTO_ESP) | ||
| 131 | return -EINVAL; | ||
| 132 | |||
| 130 | if (p->replay_window != 0) | 133 | if (p->replay_window != 0) |
| 131 | return -EINVAL; | 134 | return -EINVAL; |
| 132 | 135 | ||
| @@ -360,6 +363,23 @@ static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props, | |||
| 360 | return 0; | 363 | return 0; |
| 361 | } | 364 | } |
| 362 | 365 | ||
| 366 | static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_esn, | ||
| 367 | struct nlattr *rp) | ||
| 368 | { | ||
| 369 | struct xfrm_replay_state_esn *up; | ||
| 370 | |||
| 371 | if (!replay_esn || !rp) | ||
| 372 | return 0; | ||
| 373 | |||
| 374 | up = nla_data(rp); | ||
| 375 | |||
| 376 | if (xfrm_replay_state_esn_len(replay_esn) != | ||
| 377 | xfrm_replay_state_esn_len(up)) | ||
| 378 | return -EINVAL; | ||
| 379 | |||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | |||
| 363 | static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn, | 383 | static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn, |
| 364 | struct xfrm_replay_state_esn **preplay_esn, | 384 | struct xfrm_replay_state_esn **preplay_esn, |
| 365 | struct nlattr *rta) | 385 | struct nlattr *rta) |
| @@ -1766,6 +1786,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 1766 | if (x->km.state != XFRM_STATE_VALID) | 1786 | if (x->km.state != XFRM_STATE_VALID) |
| 1767 | goto out; | 1787 | goto out; |
| 1768 | 1788 | ||
| 1789 | err = xfrm_replay_verify_len(x->replay_esn, rp); | ||
| 1790 | if (err) | ||
| 1791 | goto out; | ||
| 1792 | |||
| 1769 | spin_lock_bh(&x->lock); | 1793 | spin_lock_bh(&x->lock); |
| 1770 | xfrm_update_ae_params(x, attrs); | 1794 | xfrm_update_ae_params(x, attrs); |
| 1771 | spin_unlock_bh(&x->lock); | 1795 | spin_unlock_bh(&x->lock); |
