提交 cb1817b3 编写于 作者: L Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (30 commits)
  xfrm: Restrict extended sequence numbers to esp
  xfrm: Check for esn buffer len in xfrm_new_ae
  xfrm: Assign esn pointers when cloning a state
  xfrm: Move the test on replay window size into the replay check functions
  netdev: bfin_mac: document TE setting in RMII modes
  drivers net: Fix declaration ordering in inline functions.
  cxgb3: Apply interrupt coalescing settings to all queues
  net: Always allocate at least 16 skb frags regardless of page size
  ipv4: Don't ip_rt_put() an error pointer in RAW sockets.
  net: fix ethtool->set_flags not intended -EINVAL return value
  mlx4_en: Fix loss of promiscuity
  tg3: Fix inline keyword usage
  tg3: use <linux/io.h> and <linux/uaccess.h> instead <asm/io.h> and <asm/uaccess.h>
  net: use CHECKSUM_NONE instead of magic number
  Net / jme: Do not use legacy PCI power management
  myri10ge: small rx_done refactoring
  bridge: notify applications if address of bridge device changes
  ipv4: Fix IP timestamp option (IPOPT_TS_PRESPEC) handling in ip_options_echo()
  can: c_can: Fix tx_bytes accounting
  can: c_can_platform: fix irq check in probe
  ...
...@@ -1237,8 +1237,17 @@ static int bfin_mac_enable(struct phy_device *phydev) ...@@ -1237,8 +1237,17 @@ static int bfin_mac_enable(struct phy_device *phydev)
if (phydev->interface == PHY_INTERFACE_MODE_RMII) { if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
opmode |= RMII; /* For Now only 100MBit are supported */ opmode |= RMII; /* For Now only 100MBit are supported */
#if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) && CONFIG_BF_REV_0_2 #if defined(CONFIG_BF537) || defined(CONFIG_BF536)
opmode |= TE; if (__SILICON_REVISION__ < 3) {
/*
* This isn't publicly documented (fun times!), but in
* silicon <=0.2, the RX and TX pins are clocked together.
* So in order to recv, we must enable the transmit side
* as well. This will cause a spurious TX interrupt too,
* but we can easily consume that.
*/
opmode |= TE;
}
#endif #endif
} }
......
...@@ -8317,7 +8317,7 @@ static const struct net_device_ops bnx2_netdev_ops = { ...@@ -8317,7 +8317,7 @@ static const struct net_device_ops bnx2_netdev_ops = {
#endif #endif
}; };
static void inline vlan_features_add(struct net_device *dev, u32 flags) static inline void vlan_features_add(struct net_device *dev, u32 flags)
{ {
dev->vlan_features |= flags; dev->vlan_features |= flags;
} }
......
...@@ -588,14 +588,9 @@ static void c_can_chip_config(struct net_device *dev) ...@@ -588,14 +588,9 @@ static void c_can_chip_config(struct net_device *dev)
{ {
struct c_can_priv *priv = netdev_priv(dev); struct c_can_priv *priv = netdev_priv(dev);
if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) /* enable automatic retransmission */
/* disable automatic retransmission */ priv->write_reg(priv, &priv->regs->control,
priv->write_reg(priv, &priv->regs->control, CONTROL_ENABLE_AR);
CONTROL_DISABLE_AR);
else
/* enable automatic retransmission */
priv->write_reg(priv, &priv->regs->control,
CONTROL_ENABLE_AR);
if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY & if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY &
CAN_CTRLMODE_LOOPBACK)) { CAN_CTRLMODE_LOOPBACK)) {
...@@ -704,7 +699,6 @@ static void c_can_do_tx(struct net_device *dev) ...@@ -704,7 +699,6 @@ static void c_can_do_tx(struct net_device *dev)
for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
msg_obj_no = get_tx_echo_msg_obj(priv); msg_obj_no = get_tx_echo_msg_obj(priv);
c_can_inval_msg_object(dev, 0, msg_obj_no);
val = c_can_read_reg32(priv, &priv->regs->txrqst1); val = c_can_read_reg32(priv, &priv->regs->txrqst1);
if (!(val & (1 << msg_obj_no))) { if (!(val & (1 << msg_obj_no))) {
can_get_echo_skb(dev, can_get_echo_skb(dev,
...@@ -713,6 +707,7 @@ static void c_can_do_tx(struct net_device *dev) ...@@ -713,6 +707,7 @@ static void c_can_do_tx(struct net_device *dev)
&priv->regs->ifregs[0].msg_cntrl) &priv->regs->ifregs[0].msg_cntrl)
& IF_MCONT_DLC_MASK; & IF_MCONT_DLC_MASK;
stats->tx_packets++; stats->tx_packets++;
c_can_inval_msg_object(dev, 0, msg_obj_no);
} }
} }
...@@ -1112,8 +1107,7 @@ struct net_device *alloc_c_can_dev(void) ...@@ -1112,8 +1107,7 @@ struct net_device *alloc_c_can_dev(void)
priv->can.bittiming_const = &c_can_bittiming_const; priv->can.bittiming_const = &c_can_bittiming_const;
priv->can.do_set_mode = c_can_set_mode; priv->can.do_set_mode = c_can_set_mode;
priv->can.do_get_berr_counter = c_can_get_berr_counter; priv->can.do_get_berr_counter = c_can_get_berr_counter;
priv->can.ctrlmode_supported = CAN_CTRLMODE_ONE_SHOT | priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
CAN_CTRLMODE_LOOPBACK |
CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_BERR_REPORTING; CAN_CTRLMODE_BERR_REPORTING;
......
...@@ -73,7 +73,8 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) ...@@ -73,7 +73,8 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
void __iomem *addr; void __iomem *addr;
struct net_device *dev; struct net_device *dev;
struct c_can_priv *priv; struct c_can_priv *priv;
struct resource *mem, *irq; struct resource *mem;
int irq;
#ifdef CONFIG_HAVE_CLK #ifdef CONFIG_HAVE_CLK
struct clk *clk; struct clk *clk;
...@@ -88,8 +89,8 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) ...@@ -88,8 +89,8 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
/* get the platform data */ /* get the platform data */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); irq = platform_get_irq(pdev, 0);
if (!mem || (irq <= 0)) { if (!mem || irq <= 0) {
ret = -ENODEV; ret = -ENODEV;
goto exit_free_clk; goto exit_free_clk;
} }
...@@ -117,7 +118,7 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) ...@@ -117,7 +118,7 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
priv = netdev_priv(dev); priv = netdev_priv(dev);
dev->irq = irq->start; dev->irq = irq;
priv->regs = addr; priv->regs = addr;
#ifdef CONFIG_HAVE_CLK #ifdef CONFIG_HAVE_CLK
priv->can.clock.freq = clk_get_rate(clk); priv->can.clock.freq = clk_get_rate(clk);
......
...@@ -1983,14 +1983,20 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c) ...@@ -1983,14 +1983,20 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
{ {
struct port_info *pi = netdev_priv(dev); struct port_info *pi = netdev_priv(dev);
struct adapter *adapter = pi->adapter; struct adapter *adapter = pi->adapter;
struct qset_params *qsp = &adapter->params.sge.qset[0]; struct qset_params *qsp;
struct sge_qset *qs = &adapter->sge.qs[0]; struct sge_qset *qs;
int i;
if (c->rx_coalesce_usecs * 10 > M_NEWTIMER) if (c->rx_coalesce_usecs * 10 > M_NEWTIMER)
return -EINVAL; return -EINVAL;
qsp->coalesce_usecs = c->rx_coalesce_usecs; for (i = 0; i < pi->nqsets; i++) {
t3_update_qset_coalesce(qs, qsp); qsp = &adapter->params.sge.qset[i];
qs = &adapter->sge.qs[i];
qsp->coalesce_usecs = c->rx_coalesce_usecs;
t3_update_qset_coalesce(qs, qsp);
}
return 0; return 0;
} }
......
...@@ -273,7 +273,7 @@ jme_clear_pm(struct jme_adapter *jme) ...@@ -273,7 +273,7 @@ jme_clear_pm(struct jme_adapter *jme)
{ {
jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs); jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs);
pci_set_power_state(jme->pdev, PCI_D0); pci_set_power_state(jme->pdev, PCI_D0);
pci_enable_wake(jme->pdev, PCI_D0, false); device_set_wakeup_enable(&jme->pdev->dev, false);
} }
static int static int
...@@ -2538,6 +2538,8 @@ jme_set_wol(struct net_device *netdev, ...@@ -2538,6 +2538,8 @@ jme_set_wol(struct net_device *netdev,
jwrite32(jme, JME_PMCS, jme->reg_pmcs); jwrite32(jme, JME_PMCS, jme->reg_pmcs);
device_set_wakeup_enable(&jme->pdev->dev, jme->reg_pmcs);
return 0; return 0;
} }
...@@ -3172,9 +3174,9 @@ jme_shutdown(struct pci_dev *pdev) ...@@ -3172,9 +3174,9 @@ jme_shutdown(struct pci_dev *pdev)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int static int jme_suspend(struct device *dev)
jme_suspend(struct pci_dev *pdev, pm_message_t state)
{ {
struct pci_dev *pdev = to_pci_dev(dev);
struct net_device *netdev = pci_get_drvdata(pdev); struct net_device *netdev = pci_get_drvdata(pdev);
struct jme_adapter *jme = netdev_priv(netdev); struct jme_adapter *jme = netdev_priv(netdev);
...@@ -3206,22 +3208,18 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -3206,22 +3208,18 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state)
tasklet_hi_enable(&jme->rxclean_task); tasklet_hi_enable(&jme->rxclean_task);
tasklet_hi_enable(&jme->rxempty_task); tasklet_hi_enable(&jme->rxempty_task);
pci_save_state(pdev);
jme_powersave_phy(jme); jme_powersave_phy(jme);
pci_enable_wake(jme->pdev, PCI_D3hot, true);
pci_set_power_state(pdev, PCI_D3hot);
return 0; return 0;
} }
static int static int jme_resume(struct device *dev)
jme_resume(struct pci_dev *pdev)
{ {
struct pci_dev *pdev = to_pci_dev(dev);
struct net_device *netdev = pci_get_drvdata(pdev); struct net_device *netdev = pci_get_drvdata(pdev);
struct jme_adapter *jme = netdev_priv(netdev); struct jme_adapter *jme = netdev_priv(netdev);
jme_clear_pm(jme); jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs);
pci_restore_state(pdev);
jme_phy_on(jme); jme_phy_on(jme);
if (test_bit(JME_FLAG_SSET, &jme->flags)) if (test_bit(JME_FLAG_SSET, &jme->flags))
...@@ -3238,6 +3236,13 @@ jme_resume(struct pci_dev *pdev) ...@@ -3238,6 +3236,13 @@ jme_resume(struct pci_dev *pdev)
return 0; return 0;
} }
static SIMPLE_DEV_PM_OPS(jme_pm_ops, jme_suspend, jme_resume);
#define JME_PM_OPS (&jme_pm_ops)
#else
#define JME_PM_OPS NULL
#endif #endif
static DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = { static DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = {
...@@ -3251,11 +3256,8 @@ static struct pci_driver jme_driver = { ...@@ -3251,11 +3256,8 @@ static struct pci_driver jme_driver = {
.id_table = jme_pci_tbl, .id_table = jme_pci_tbl,
.probe = jme_init_one, .probe = jme_init_one,
.remove = __devexit_p(jme_remove_one), .remove = __devexit_p(jme_remove_one),
#ifdef CONFIG_PM
.suspend = jme_suspend,
.resume = jme_resume,
#endif /* CONFIG_PM */
.shutdown = jme_shutdown, .shutdown = jme_shutdown,
.driver.pm = JME_PM_OPS,
}; };
static int __init static int __init
......
...@@ -4898,7 +4898,7 @@ static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -4898,7 +4898,7 @@ static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev)
goto unlock; goto unlock;
} }
skb_copy_and_csum_dev(org_skb, skb->data); skb_copy_and_csum_dev(org_skb, skb->data);
org_skb->ip_summed = 0; org_skb->ip_summed = CHECKSUM_NONE;
skb->len = org_skb->len; skb->len = org_skb->len;
copy_old_skb(org_skb, skb); copy_old_skb(org_skb, skb);
} }
......
...@@ -742,6 +742,9 @@ int mlx4_en_start_port(struct net_device *dev) ...@@ -742,6 +742,9 @@ int mlx4_en_start_port(struct net_device *dev)
0, MLX4_PROT_ETH)) 0, MLX4_PROT_ETH))
mlx4_warn(mdev, "Failed Attaching Broadcast\n"); mlx4_warn(mdev, "Failed Attaching Broadcast\n");
/* Must redo promiscuous mode setup. */
priv->flags &= ~(MLX4_EN_FLAG_PROMISC | MLX4_EN_FLAG_MC_PROMISC);
/* Schedule multicast task to populate multicast list */ /* Schedule multicast task to populate multicast list */
queue_work(mdev->workqueue, &priv->mcast_task); queue_work(mdev->workqueue, &priv->mcast_task);
......
...@@ -1312,17 +1312,26 @@ myri10ge_unmap_rx_page(struct pci_dev *pdev, ...@@ -1312,17 +1312,26 @@ myri10ge_unmap_rx_page(struct pci_dev *pdev,
* page into an skb */ * page into an skb */
static inline int static inline int
myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx, myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum,
int bytes, int len, __wsum csum) int lro_enabled)
{ {
struct myri10ge_priv *mgp = ss->mgp; struct myri10ge_priv *mgp = ss->mgp;
struct sk_buff *skb; struct sk_buff *skb;
struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME]; struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME];
int i, idx, hlen, remainder; struct myri10ge_rx_buf *rx;
int i, idx, hlen, remainder, bytes;
struct pci_dev *pdev = mgp->pdev; struct pci_dev *pdev = mgp->pdev;
struct net_device *dev = mgp->dev; struct net_device *dev = mgp->dev;
u8 *va; u8 *va;
if (len <= mgp->small_bytes) {
rx = &ss->rx_small;
bytes = mgp->small_bytes;
} else {
rx = &ss->rx_big;
bytes = mgp->big_bytes;
}
len += MXGEFW_PAD; len += MXGEFW_PAD;
idx = rx->cnt & rx->mask; idx = rx->cnt & rx->mask;
va = page_address(rx->info[idx].page) + rx->info[idx].page_offset; 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,7 +1350,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx,
remainder -= MYRI10GE_ALLOC_SIZE; remainder -= MYRI10GE_ALLOC_SIZE;
} }
if (dev->features & NETIF_F_LRO) { if (lro_enabled) {
rx_frags[0].page_offset += MXGEFW_PAD; rx_frags[0].page_offset += MXGEFW_PAD;
rx_frags[0].size -= MXGEFW_PAD; rx_frags[0].size -= MXGEFW_PAD;
len -= MXGEFW_PAD; len -= MXGEFW_PAD;
...@@ -1463,7 +1472,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) ...@@ -1463,7 +1472,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
{ {
struct myri10ge_rx_done *rx_done = &ss->rx_done; struct myri10ge_rx_done *rx_done = &ss->rx_done;
struct myri10ge_priv *mgp = ss->mgp; struct myri10ge_priv *mgp = ss->mgp;
struct net_device *netdev = mgp->dev;
unsigned long rx_bytes = 0; unsigned long rx_bytes = 0;
unsigned long rx_packets = 0; unsigned long rx_packets = 0;
unsigned long rx_ok; unsigned long rx_ok;
...@@ -1474,18 +1483,18 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) ...@@ -1474,18 +1483,18 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
u16 length; u16 length;
__wsum checksum; __wsum checksum;
/*
* Prevent compiler from generating more than one ->features memory
* access to avoid theoretical race condition with functions that
* change NETIF_F_LRO flag at runtime.
*/
bool lro_enabled = ACCESS_ONCE(mgp->dev->features) & NETIF_F_LRO;
while (rx_done->entry[idx].length != 0 && work_done < budget) { while (rx_done->entry[idx].length != 0 && work_done < budget) {
length = ntohs(rx_done->entry[idx].length); length = ntohs(rx_done->entry[idx].length);
rx_done->entry[idx].length = 0; rx_done->entry[idx].length = 0;
checksum = csum_unfold(rx_done->entry[idx].checksum); checksum = csum_unfold(rx_done->entry[idx].checksum);
if (length <= mgp->small_bytes) rx_ok = myri10ge_rx_done(ss, length, checksum, lro_enabled);
rx_ok = myri10ge_rx_done(ss, &ss->rx_small,
mgp->small_bytes,
length, checksum);
else
rx_ok = myri10ge_rx_done(ss, &ss->rx_big,
mgp->big_bytes,
length, checksum);
rx_packets += rx_ok; rx_packets += rx_ok;
rx_bytes += rx_ok * (unsigned long)length; rx_bytes += rx_ok * (unsigned long)length;
cnt++; cnt++;
...@@ -1497,7 +1506,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) ...@@ -1497,7 +1506,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
ss->stats.rx_packets += rx_packets; ss->stats.rx_packets += rx_packets;
ss->stats.rx_bytes += rx_bytes; ss->stats.rx_bytes += rx_bytes;
if (netdev->features & NETIF_F_LRO) if (lro_enabled)
lro_flush_all(&rx_done->lro_mgr); lro_flush_all(&rx_done->lro_mgr);
/* restock receive rings if needed */ /* restock receive rings if needed */
......
...@@ -871,7 +871,7 @@ static int netxen_nic_set_flags(struct net_device *netdev, u32 data) ...@@ -871,7 +871,7 @@ static int netxen_nic_set_flags(struct net_device *netdev, u32 data)
struct netxen_adapter *adapter = netdev_priv(netdev); struct netxen_adapter *adapter = netdev_priv(netdev);
int hw_lro; int hw_lro;
if (data & ~ETH_FLAG_LRO) if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
return -EINVAL; return -EINVAL;
if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO)) if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO))
......
...@@ -1003,7 +1003,7 @@ static int qlcnic_set_flags(struct net_device *netdev, u32 data) ...@@ -1003,7 +1003,7 @@ static int qlcnic_set_flags(struct net_device *netdev, u32 data)
struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_adapter *adapter = netdev_priv(netdev);
int hw_lro; int hw_lro;
if (data & ~ETH_FLAG_LRO) if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
return -EINVAL; return -EINVAL;
if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)) if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO))
......
...@@ -6726,7 +6726,7 @@ static int s2io_ethtool_set_flags(struct net_device *dev, u32 data) ...@@ -6726,7 +6726,7 @@ static int s2io_ethtool_set_flags(struct net_device *dev, u32 data)
int rc = 0; int rc = 0;
int changed = 0; int changed = 0;
if (data & ~ETH_FLAG_LRO) if (ethtool_invalid_flags(dev, data, ETH_FLAG_LRO))
return -EINVAL; return -EINVAL;
if (data & ETH_FLAG_LRO) { if (data & ETH_FLAG_LRO) {
......
...@@ -48,9 +48,9 @@ ...@@ -48,9 +48,9 @@
#include <net/ip.h> #include <net/ip.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <linux/io.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/uaccess.h> #include <linux/uaccess.h>
#ifdef CONFIG_SPARC #ifdef CONFIG_SPARC
#include <asm/idprom.h> #include <asm/idprom.h>
...@@ -13118,7 +13118,7 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) ...@@ -13118,7 +13118,7 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
static struct pci_dev * __devinit tg3_find_peer(struct tg3 *); static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
static void inline vlan_features_add(struct net_device *dev, unsigned long flags) static inline void vlan_features_add(struct net_device *dev, unsigned long flags)
{ {
dev->vlan_features |= flags; dev->vlan_features |= flags;
} }
......
...@@ -304,8 +304,8 @@ vmxnet3_set_flags(struct net_device *netdev, u32 data) ...@@ -304,8 +304,8 @@ vmxnet3_set_flags(struct net_device *netdev, u32 data)
u8 lro_present = (netdev->features & NETIF_F_LRO) == 0 ? 0 : 1; u8 lro_present = (netdev->features & NETIF_F_LRO) == 0 ? 0 : 1;
unsigned long flags; unsigned long flags;
if (data & ~ETH_FLAG_LRO) if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
return -EOPNOTSUPP; return -EINVAL;
if (lro_requested ^ lro_present) { if (lro_requested ^ lro_present) {
/* toggle the LRO feature*/ /* toggle the LRO feature*/
......
...@@ -1117,8 +1117,8 @@ static int vxge_set_flags(struct net_device *dev, u32 data) ...@@ -1117,8 +1117,8 @@ static int vxge_set_flags(struct net_device *dev, u32 data)
struct vxgedev *vdev = netdev_priv(dev); struct vxgedev *vdev = netdev_priv(dev);
enum vxge_hw_status status; enum vxge_hw_status status;
if (data & ~ETH_FLAG_RXHASH) if (ethtool_invalid_flags(dev, data, ETH_FLAG_RXHASH))
return -EOPNOTSUPP; return -EINVAL;
if (!!(data & ETH_FLAG_RXHASH) == vdev->devh->config.rth_en) if (!!(data & ETH_FLAG_RXHASH) == vdev->devh->config.rth_en)
return 0; return 0;
......
...@@ -36,10 +36,10 @@ ...@@ -36,10 +36,10 @@
* @prot: pointer to struct proto structure. * @prot: pointer to struct proto structure.
*/ */
struct can_proto { struct can_proto {
int type; int type;
int protocol; int protocol;
struct proto_ops *ops; const struct proto_ops *ops;
struct proto *prot; struct proto *prot;
}; };
/* function prototypes for the CAN networklayer core (af_can.c) */ /* 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,5 +58,6 @@ extern void can_rx_unregister(struct net_device *dev, canid_t can_id,
void *data); void *data);
extern int can_send(struct sk_buff *skb, int loop); extern int can_send(struct sk_buff *skb, int loop);
extern int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
#endif /* CAN_CORE_H */ #endif /* CAN_CORE_H */
...@@ -680,6 +680,7 @@ int ethtool_op_set_ufo(struct net_device *dev, u32 data); ...@@ -680,6 +680,7 @@ int ethtool_op_set_ufo(struct net_device *dev, u32 data);
u32 ethtool_op_get_flags(struct net_device *dev); u32 ethtool_op_get_flags(struct net_device *dev);
int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported); int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported);
void ethtool_ntuple_flush(struct net_device *dev); void ethtool_ntuple_flush(struct net_device *dev);
bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
/** /**
* &ethtool_ops - Alter and report network device settings * &ethtool_ops - Alter and report network device settings
......
...@@ -122,8 +122,14 @@ struct sk_buff_head { ...@@ -122,8 +122,14 @@ struct sk_buff_head {
struct sk_buff; struct sk_buff;
/* To allow 64K frame to be packed as single skb without frag_list */ /* To allow 64K frame to be packed as single skb without frag_list. Since
* GRO uses frags we allocate at least 16 regardless of page size.
*/
#if (65536/PAGE_SIZE + 2) < 16
#define MAX_SKB_FRAGS 16
#else
#define MAX_SKB_FRAGS (65536/PAGE_SIZE + 2) #define MAX_SKB_FRAGS (65536/PAGE_SIZE + 2)
#endif
typedef struct skb_frag_struct skb_frag_t; typedef struct skb_frag_struct skb_frag_t;
......
...@@ -345,7 +345,7 @@ static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev) ...@@ -345,7 +345,7 @@ static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev)
static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb)
{ {
struct dst_entry *child = skb_dst(skb)->child; struct dst_entry *child = dst_clone(skb_dst(skb)->child);
skb_dst_drop(skb); skb_dst_drop(skb);
return child; return child;
......
...@@ -14,6 +14,12 @@ ...@@ -14,6 +14,12 @@
#define ROSE_MIN_LEN 3 #define ROSE_MIN_LEN 3
#define ROSE_CALL_REQ_ADDR_LEN_OFF 3
#define ROSE_CALL_REQ_ADDR_LEN_VAL 0xAA /* each address is 10 digits */
#define ROSE_CALL_REQ_DEST_ADDR_OFF 4
#define ROSE_CALL_REQ_SRC_ADDR_OFF 9
#define ROSE_CALL_REQ_FACILITIES_OFF 14
#define ROSE_GFI 0x10 #define ROSE_GFI 0x10
#define ROSE_Q_BIT 0x80 #define ROSE_Q_BIT 0x80
#define ROSE_D_BIT 0x40 #define ROSE_D_BIT 0x40
...@@ -214,7 +220,7 @@ extern void rose_requeue_frames(struct sock *); ...@@ -214,7 +220,7 @@ extern void rose_requeue_frames(struct sock *);
extern int rose_validate_nr(struct sock *, unsigned short); extern int rose_validate_nr(struct sock *, unsigned short);
extern void rose_write_internal(struct sock *, int); extern void rose_write_internal(struct sock *, int);
extern int rose_decode(struct sk_buff *, int *, int *, int *, int *, int *); extern int rose_decode(struct sk_buff *, int *, int *, int *, int *, int *);
extern int rose_parse_facilities(unsigned char *, struct rose_facilities_struct *); extern int rose_parse_facilities(unsigned char *, unsigned int, struct rose_facilities_struct *);
extern void rose_disconnect(struct sock *, int, int, int); extern void rose_disconnect(struct sock *, int, int, int);
/* rose_timer.c */ /* rose_timer.c */
......
...@@ -1601,6 +1601,28 @@ static inline int xfrm_replay_state_esn_len(struct xfrm_replay_state_esn *replay ...@@ -1601,6 +1601,28 @@ static inline int xfrm_replay_state_esn_len(struct xfrm_replay_state_esn *replay
} }
#ifdef CONFIG_XFRM_MIGRATE #ifdef CONFIG_XFRM_MIGRATE
static inline int xfrm_replay_clone(struct xfrm_state *x,
struct xfrm_state *orig)
{
x->replay_esn = kzalloc(xfrm_replay_state_esn_len(orig->replay_esn),
GFP_KERNEL);
if (!x->replay_esn)
return -ENOMEM;
x->replay_esn->bmp_len = orig->replay_esn->bmp_len;
x->replay_esn->replay_window = orig->replay_esn->replay_window;
x->preplay_esn = kmemdup(x->replay_esn,
xfrm_replay_state_esn_len(x->replay_esn),
GFP_KERNEL);
if (!x->preplay_esn) {
kfree(x->replay_esn);
return -ENOMEM;
}
return 0;
}
static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig) static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig)
{ {
return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL); return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL);
......
...@@ -389,6 +389,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) ...@@ -389,6 +389,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
{ {
struct net_bridge_port *p; struct net_bridge_port *p;
int err = 0; int err = 0;
bool changed_addr;
/* Don't allow bridging non-ethernet like devices */ /* Don't allow bridging non-ethernet like devices */
if ((dev->flags & IFF_LOOPBACK) || if ((dev->flags & IFF_LOOPBACK) ||
...@@ -446,7 +447,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) ...@@ -446,7 +447,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
list_add_rcu(&p->list, &br->port_list); list_add_rcu(&p->list, &br->port_list);
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
br_stp_recalculate_bridge_id(br); changed_addr = br_stp_recalculate_bridge_id(br);
br_features_recompute(br); br_features_recompute(br);
if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && 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,6 +457,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
br_ifinfo_notify(RTM_NEWLINK, p); br_ifinfo_notify(RTM_NEWLINK, p);
if (changed_addr)
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
dev_set_mtu(br->dev, br_min_mtu(br)); dev_set_mtu(br->dev, br_min_mtu(br));
kobject_uevent(&p->kobj, KOBJ_ADD); kobject_uevent(&p->kobj, KOBJ_ADD);
......
...@@ -497,7 +497,7 @@ extern void br_stp_disable_bridge(struct net_bridge *br); ...@@ -497,7 +497,7 @@ extern void br_stp_disable_bridge(struct net_bridge *br);
extern void br_stp_set_enabled(struct net_bridge *br, unsigned long val); extern void br_stp_set_enabled(struct net_bridge *br, unsigned long val);
extern void br_stp_enable_port(struct net_bridge_port *p); extern void br_stp_enable_port(struct net_bridge_port *p);
extern void br_stp_disable_port(struct net_bridge_port *p); extern void br_stp_disable_port(struct net_bridge_port *p);
extern void br_stp_recalculate_bridge_id(struct net_bridge *br); extern bool br_stp_recalculate_bridge_id(struct net_bridge *br);
extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a); extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a);
extern void br_stp_set_bridge_priority(struct net_bridge *br, extern void br_stp_set_bridge_priority(struct net_bridge *br,
u16 newprio); u16 newprio);
......
...@@ -204,7 +204,7 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) ...@@ -204,7 +204,7 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr)
static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1]; static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1];
/* called under bridge lock */ /* called under bridge lock */
void br_stp_recalculate_bridge_id(struct net_bridge *br) bool br_stp_recalculate_bridge_id(struct net_bridge *br)
{ {
const unsigned char *br_mac_zero = const unsigned char *br_mac_zero =
(const unsigned char *)br_mac_zero_aligned; (const unsigned char *)br_mac_zero_aligned;
...@@ -222,8 +222,11 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br) ...@@ -222,8 +222,11 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br)
} }
if (compare_ether_addr(br->bridge_id.addr, addr)) if (compare_ether_addr(br->bridge_id.addr, addr) == 0)
br_stp_change_bridge_id(br, addr); return false; /* no change */
br_stp_change_bridge_id(br, addr);
return true;
} }
/* called under bridge lock */ /* called under bridge lock */
......
...@@ -95,7 +95,7 @@ struct s_pstats can_pstats; /* receive list statistics */ ...@@ -95,7 +95,7 @@ struct s_pstats can_pstats; /* receive list statistics */
* af_can socket functions * af_can socket functions
*/ */
static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
...@@ -108,6 +108,7 @@ static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -108,6 +108,7 @@ static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
} }
EXPORT_SYMBOL(can_ioctl);
static void can_sock_destruct(struct sock *sk) static void can_sock_destruct(struct sock *sk)
{ {
...@@ -698,13 +699,9 @@ int can_proto_register(struct can_proto *cp) ...@@ -698,13 +699,9 @@ int can_proto_register(struct can_proto *cp)
printk(KERN_ERR "can: protocol %d already registered\n", printk(KERN_ERR "can: protocol %d already registered\n",
proto); proto);
err = -EBUSY; err = -EBUSY;
} else { } else
proto_tab[proto] = cp; proto_tab[proto] = cp;
/* use generic ioctl function if not defined by module */
if (!cp->ops->ioctl)
cp->ops->ioctl = can_ioctl;
}
spin_unlock(&proto_tab_lock); spin_unlock(&proto_tab_lock);
if (err < 0) if (err < 0)
......
...@@ -1569,7 +1569,7 @@ static int bcm_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1569,7 +1569,7 @@ static int bcm_recvmsg(struct kiocb *iocb, struct socket *sock,
return size; return size;
} }
static struct proto_ops bcm_ops __read_mostly = { static const struct proto_ops bcm_ops = {
.family = PF_CAN, .family = PF_CAN,
.release = bcm_release, .release = bcm_release,
.bind = sock_no_bind, .bind = sock_no_bind,
...@@ -1578,7 +1578,7 @@ static struct proto_ops bcm_ops __read_mostly = { ...@@ -1578,7 +1578,7 @@ static struct proto_ops bcm_ops __read_mostly = {
.accept = sock_no_accept, .accept = sock_no_accept,
.getname = sock_no_getname, .getname = sock_no_getname,
.poll = datagram_poll, .poll = datagram_poll,
.ioctl = NULL, /* use can_ioctl() from af_can.c */ .ioctl = can_ioctl, /* use can_ioctl() from af_can.c */
.listen = sock_no_listen, .listen = sock_no_listen,
.shutdown = sock_no_shutdown, .shutdown = sock_no_shutdown,
.setsockopt = sock_no_setsockopt, .setsockopt = sock_no_setsockopt,
......
...@@ -742,7 +742,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -742,7 +742,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
return size; return size;
} }
static struct proto_ops raw_ops __read_mostly = { static const struct proto_ops raw_ops = {
.family = PF_CAN, .family = PF_CAN,
.release = raw_release, .release = raw_release,
.bind = raw_bind, .bind = raw_bind,
...@@ -751,7 +751,7 @@ static struct proto_ops raw_ops __read_mostly = { ...@@ -751,7 +751,7 @@ static struct proto_ops raw_ops __read_mostly = {
.accept = sock_no_accept, .accept = sock_no_accept,
.getname = raw_getname, .getname = raw_getname,
.poll = datagram_poll, .poll = datagram_poll,
.ioctl = NULL, /* use can_ioctl() from af_can.c */ .ioctl = can_ioctl, /* use can_ioctl() from af_can.c */
.listen = sock_no_listen, .listen = sock_no_listen,
.shutdown = sock_no_shutdown, .shutdown = sock_no_shutdown,
.setsockopt = raw_setsockopt, .setsockopt = raw_setsockopt,
......
...@@ -1140,9 +1140,6 @@ static int __dev_open(struct net_device *dev) ...@@ -1140,9 +1140,6 @@ static int __dev_open(struct net_device *dev)
ASSERT_RTNL(); ASSERT_RTNL();
/*
* Is it even present?
*/
if (!netif_device_present(dev)) if (!netif_device_present(dev))
return -ENODEV; return -ENODEV;
...@@ -1151,9 +1148,6 @@ static int __dev_open(struct net_device *dev) ...@@ -1151,9 +1148,6 @@ static int __dev_open(struct net_device *dev)
if (ret) if (ret)
return ret; return ret;
/*
* Call device private open method
*/
set_bit(__LINK_STATE_START, &dev->state); set_bit(__LINK_STATE_START, &dev->state);
if (ops->ndo_validate_addr) if (ops->ndo_validate_addr)
...@@ -1162,31 +1156,12 @@ static int __dev_open(struct net_device *dev) ...@@ -1162,31 +1156,12 @@ static int __dev_open(struct net_device *dev)
if (!ret && ops->ndo_open) if (!ret && ops->ndo_open)
ret = ops->ndo_open(dev); ret = ops->ndo_open(dev);
/*
* If it went open OK then:
*/
if (ret) if (ret)
clear_bit(__LINK_STATE_START, &dev->state); clear_bit(__LINK_STATE_START, &dev->state);
else { else {
/*
* Set the flags.
*/
dev->flags |= IFF_UP; dev->flags |= IFF_UP;
/*
* Enable NET_DMA
*/
net_dmaengine_get(); net_dmaengine_get();
/*
* Initialize multicasting status
*/
dev_set_rx_mode(dev); dev_set_rx_mode(dev);
/*
* Wakeup transmit queue engine
*/
dev_activate(dev); dev_activate(dev);
} }
...@@ -1209,22 +1184,13 @@ int dev_open(struct net_device *dev) ...@@ -1209,22 +1184,13 @@ int dev_open(struct net_device *dev)
{ {
int ret; int ret;
/*
* Is it already up?
*/
if (dev->flags & IFF_UP) if (dev->flags & IFF_UP)
return 0; return 0;
/*
* Open device
*/
ret = __dev_open(dev); ret = __dev_open(dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
/*
* ... and announce new interface.
*/
rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
call_netdevice_notifiers(NETDEV_UP, dev); call_netdevice_notifiers(NETDEV_UP, dev);
...@@ -1240,10 +1206,6 @@ static int __dev_close_many(struct list_head *head) ...@@ -1240,10 +1206,6 @@ static int __dev_close_many(struct list_head *head)
might_sleep(); might_sleep();
list_for_each_entry(dev, head, unreg_list) { list_for_each_entry(dev, head, unreg_list) {
/*
* Tell people we are going down, so that they can
* prepare to death, when device is still operating.
*/
call_netdevice_notifiers(NETDEV_GOING_DOWN, dev); call_netdevice_notifiers(NETDEV_GOING_DOWN, dev);
clear_bit(__LINK_STATE_START, &dev->state); clear_bit(__LINK_STATE_START, &dev->state);
...@@ -1272,15 +1234,7 @@ static int __dev_close_many(struct list_head *head) ...@@ -1272,15 +1234,7 @@ static int __dev_close_many(struct list_head *head)
if (ops->ndo_stop) if (ops->ndo_stop)
ops->ndo_stop(dev); ops->ndo_stop(dev);
/*
* Device is now down.
*/
dev->flags &= ~IFF_UP; dev->flags &= ~IFF_UP;
/*
* Shutdown NET_DMA
*/
net_dmaengine_put(); net_dmaengine_put();
} }
...@@ -1309,9 +1263,6 @@ static int dev_close_many(struct list_head *head) ...@@ -1309,9 +1263,6 @@ static int dev_close_many(struct list_head *head)
__dev_close_many(head); __dev_close_many(head);
/*
* Tell people we are down
*/
list_for_each_entry(dev, head, unreg_list) { list_for_each_entry(dev, head, unreg_list) {
rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
call_netdevice_notifiers(NETDEV_DOWN, dev); call_netdevice_notifiers(NETDEV_DOWN, dev);
...@@ -1371,11 +1322,6 @@ EXPORT_SYMBOL(dev_disable_lro); ...@@ -1371,11 +1322,6 @@ EXPORT_SYMBOL(dev_disable_lro);
static int dev_boot_phase = 1; static int dev_boot_phase = 1;
/*
* Device change register/unregister. These are not inline or static
* as we export them to the world.
*/
/** /**
* register_netdevice_notifier - register a network notifier block * register_netdevice_notifier - register a network notifier block
* @nb: notifier * @nb: notifier
...@@ -1477,6 +1423,7 @@ int call_netdevice_notifiers(unsigned long val, struct net_device *dev) ...@@ -1477,6 +1423,7 @@ int call_netdevice_notifiers(unsigned long val, struct net_device *dev)
ASSERT_RTNL(); ASSERT_RTNL();
return raw_notifier_call_chain(&netdev_chain, val, dev); return raw_notifier_call_chain(&netdev_chain, val, dev);
} }
EXPORT_SYMBOL(call_netdevice_notifiers);
/* When > 0 there are consumers of rx skb time stamps */ /* When > 0 there are consumers of rx skb time stamps */
static atomic_t netstamp_needed = ATOMIC_INIT(0); static atomic_t netstamp_needed = ATOMIC_INIT(0);
......
...@@ -141,9 +141,24 @@ u32 ethtool_op_get_flags(struct net_device *dev) ...@@ -141,9 +141,24 @@ u32 ethtool_op_get_flags(struct net_device *dev)
} }
EXPORT_SYMBOL(ethtool_op_get_flags); EXPORT_SYMBOL(ethtool_op_get_flags);
/* Check if device can enable (or disable) particular feature coded in "data"
* argument. Flags "supported" describe features that can be toggled by device.
* If feature can not be toggled, it state (enabled or disabled) must match
* hardcoded device features state, otherwise flags are marked as invalid.
*/
bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported)
{
u32 features = dev->features & flags_dup_features;
/* "data" can contain only flags_dup_features bits,
* see __ethtool_set_flags */
return (features & ~supported) != (data & ~supported);
}
EXPORT_SYMBOL(ethtool_invalid_flags);
int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported) int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported)
{ {
if (data & ~supported) if (ethtool_invalid_flags(dev, data, supported))
return -EINVAL; return -EINVAL;
dev->features = ((dev->features & ~flags_dup_features) | dev->features = ((dev->features & ~flags_dup_features) |
......
...@@ -1365,9 +1365,9 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l, ...@@ -1365,9 +1365,9 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
err = fib_props[fa->fa_type].error; err = fib_props[fa->fa_type].error;
if (err) { if (err) {
#ifdef CONFIG_IP_FIB_TRIE_STATS #ifdef CONFIG_IP_FIB_TRIE_STATS
t->stats.semantic_match_miss++; t->stats.semantic_match_passed++;
#endif #endif
return 1; return err;
} }
if (fi->fib_flags & RTNH_F_DEAD) if (fi->fib_flags & RTNH_F_DEAD)
continue; continue;
......
...@@ -140,11 +140,11 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) ...@@ -140,11 +140,11 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
} else { } else {
dopt->ts_needtime = 0; dopt->ts_needtime = 0;
if (soffset + 8 <= optlen) { if (soffset + 7 <= optlen) {
__be32 addr; __be32 addr;
memcpy(&addr, sptr+soffset-1, 4); memcpy(&addr, dptr+soffset-1, 4);
if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_LOCAL) { if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_UNICAST) {
dopt->ts_needtime = 1; dopt->ts_needtime = 1;
soffset += 8; soffset += 8;
} }
......
...@@ -569,6 +569,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, ...@@ -569,6 +569,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
rt = ip_route_output_flow(sock_net(sk), &fl4, sk); rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
if (IS_ERR(rt)) { if (IS_ERR(rt)) {
err = PTR_ERR(rt); err = PTR_ERR(rt);
rt = NULL;
goto done; goto done;
} }
} }
......
...@@ -663,7 +663,7 @@ static int pim6_rcv(struct sk_buff *skb) ...@@ -663,7 +663,7 @@ static int pim6_rcv(struct sk_buff *skb)
skb_pull(skb, (u8 *)encap - skb->data); skb_pull(skb, (u8 *)encap - skb->data);
skb_reset_network_header(skb); skb_reset_network_header(skb);
skb->protocol = htons(ETH_P_IPV6); skb->protocol = htons(ETH_P_IPV6);
skb->ip_summed = 0; skb->ip_summed = CHECKSUM_NONE;
skb->pkt_type = PACKET_HOST; skb->pkt_type = PACKET_HOST;
skb_tunnel_rx(skb, reg_dev); skb_tunnel_rx(skb, reg_dev);
......
...@@ -656,10 +656,16 @@ static void iriap_getvaluebyclass_indication(struct iriap_cb *self, ...@@ -656,10 +656,16 @@ static void iriap_getvaluebyclass_indication(struct iriap_cb *self,
n = 1; n = 1;
name_len = fp[n++]; name_len = fp[n++];
IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;);
memcpy(name, fp+n, name_len); n+=name_len; memcpy(name, fp+n, name_len); n+=name_len;
name[name_len] = '\0'; name[name_len] = '\0';
attr_len = fp[n++]; attr_len = fp[n++];
IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;);
memcpy(attr, fp+n, attr_len); n+=attr_len; memcpy(attr, fp+n, attr_len); n+=attr_len;
attr[attr_len] = '\0'; attr[attr_len] = '\0';
......
...@@ -105,6 +105,9 @@ irnet_ctrl_write(irnet_socket * ap, ...@@ -105,6 +105,9 @@ irnet_ctrl_write(irnet_socket * ap,
while(isspace(start[length - 1])) while(isspace(start[length - 1]))
length--; length--;
DABORT(length < 5 || length > NICKNAME_MAX_LEN + 5,
-EINVAL, CTRL_ERROR, "Invalid nickname.\n");
/* Copy the name for later reuse */ /* Copy the name for later reuse */
memcpy(ap->rname, start + 5, length - 5); memcpy(ap->rname, start + 5, length - 5);
ap->rname[length - 5] = '\0'; ap->rname[length - 5] = '\0';
......
...@@ -978,7 +978,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros ...@@ -978,7 +978,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros
struct sock *make; struct sock *make;
struct rose_sock *make_rose; struct rose_sock *make_rose;
struct rose_facilities_struct facilities; struct rose_facilities_struct facilities;
int n, len; int n;
skb->sk = NULL; /* Initially we don't know who it's for */ skb->sk = NULL; /* Initially we don't know who it's for */
...@@ -987,9 +987,9 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros ...@@ -987,9 +987,9 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros
*/ */
memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); memset(&facilities, 0x00, sizeof(struct rose_facilities_struct));
len = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1; if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF,
len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1; skb->len - ROSE_CALL_REQ_FACILITIES_OFF,
if (!rose_parse_facilities(skb->data + len + 4, &facilities)) { &facilities)) {
rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76); rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76);
return 0; return 0;
} }
......
...@@ -73,9 +73,20 @@ static void rose_loopback_timer(unsigned long param) ...@@ -73,9 +73,20 @@ static void rose_loopback_timer(unsigned long param)
unsigned int lci_i, lci_o; unsigned int lci_i, lci_o;
while ((skb = skb_dequeue(&loopback_queue)) != NULL) { while ((skb = skb_dequeue(&loopback_queue)) != NULL) {
if (skb->len < ROSE_MIN_LEN) {
kfree_skb(skb);
continue;
}
lci_i = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); lci_i = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
frametype = skb->data[2]; frametype = skb->data[2];
dest = (rose_address *)(skb->data + 4); if (frametype == ROSE_CALL_REQUEST &&
(skb->len <= ROSE_CALL_REQ_FACILITIES_OFF ||
skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] !=
ROSE_CALL_REQ_ADDR_LEN_VAL)) {
kfree_skb(skb);
continue;
}
dest = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF);
lci_o = ROSE_DEFAULT_MAXVC + 1 - lci_i; lci_o = ROSE_DEFAULT_MAXVC + 1 - lci_i;
skb_reset_transport_header(skb); skb_reset_transport_header(skb);
......
...@@ -861,7 +861,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) ...@@ -861,7 +861,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
unsigned int lci, new_lci; unsigned int lci, new_lci;
unsigned char cause, diagnostic; unsigned char cause, diagnostic;
struct net_device *dev; struct net_device *dev;
int len, res = 0; int res = 0;
char buf[11]; char buf[11];
#if 0 #if 0
...@@ -869,10 +869,17 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) ...@@ -869,10 +869,17 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
return res; return res;
#endif #endif
if (skb->len < ROSE_MIN_LEN)
return res;
frametype = skb->data[2]; frametype = skb->data[2];
lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
src_addr = (rose_address *)(skb->data + 9); if (frametype == ROSE_CALL_REQUEST &&
dest_addr = (rose_address *)(skb->data + 4); (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF ||
skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] !=
ROSE_CALL_REQ_ADDR_LEN_VAL))
return res;
src_addr = (rose_address *)(skb->data + ROSE_CALL_REQ_SRC_ADDR_OFF);
dest_addr = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF);
spin_lock_bh(&rose_neigh_list_lock); spin_lock_bh(&rose_neigh_list_lock);
spin_lock_bh(&rose_route_list_lock); spin_lock_bh(&rose_route_list_lock);
...@@ -1010,12 +1017,11 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) ...@@ -1010,12 +1017,11 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
goto out; goto out;
} }
len = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1;
len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1;
memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); memset(&facilities, 0x00, sizeof(struct rose_facilities_struct));
if (!rose_parse_facilities(skb->data + len + 4, &facilities)) { if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF,
skb->len - ROSE_CALL_REQ_FACILITIES_OFF,
&facilities)) {
rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76); rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76);
goto out; goto out;
} }
......
...@@ -142,7 +142,7 @@ void rose_write_internal(struct sock *sk, int frametype) ...@@ -142,7 +142,7 @@ void rose_write_internal(struct sock *sk, int frametype)
*dptr++ = ROSE_GFI | lci1; *dptr++ = ROSE_GFI | lci1;
*dptr++ = lci2; *dptr++ = lci2;
*dptr++ = frametype; *dptr++ = frametype;
*dptr++ = 0xAA; *dptr++ = ROSE_CALL_REQ_ADDR_LEN_VAL;
memcpy(dptr, &rose->dest_addr, ROSE_ADDR_LEN); memcpy(dptr, &rose->dest_addr, ROSE_ADDR_LEN);
dptr += ROSE_ADDR_LEN; dptr += ROSE_ADDR_LEN;
memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN); 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,12 +246,16 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct *
do { do {
switch (*p & 0xC0) { switch (*p & 0xC0) {
case 0x00: case 0x00:
if (len < 2)
return -1;
p += 2; p += 2;
n += 2; n += 2;
len -= 2; len -= 2;
break; break;
case 0x40: case 0x40:
if (len < 3)
return -1;
if (*p == FAC_NATIONAL_RAND) if (*p == FAC_NATIONAL_RAND)
facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF); facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF);
p += 3; p += 3;
...@@ -260,40 +264,61 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct * ...@@ -260,40 +264,61 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct *
break; break;
case 0x80: case 0x80:
if (len < 4)
return -1;
p += 4; p += 4;
n += 4; n += 4;
len -= 4; len -= 4;
break; break;
case 0xC0: case 0xC0:
if (len < 2)
return -1;
l = p[1]; l = p[1];
if (len < 2 + l)
return -1;
if (*p == FAC_NATIONAL_DEST_DIGI) { if (*p == FAC_NATIONAL_DEST_DIGI) {
if (!fac_national_digis_received) { if (!fac_national_digis_received) {
if (l < AX25_ADDR_LEN)
return -1;
memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN); memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN);
facilities->source_ndigis = 1; facilities->source_ndigis = 1;
} }
} }
else if (*p == FAC_NATIONAL_SRC_DIGI) { else if (*p == FAC_NATIONAL_SRC_DIGI) {
if (!fac_national_digis_received) { if (!fac_national_digis_received) {
if (l < AX25_ADDR_LEN)
return -1;
memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN); memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN);
facilities->dest_ndigis = 1; facilities->dest_ndigis = 1;
} }
} }
else if (*p == FAC_NATIONAL_FAIL_CALL) { else if (*p == FAC_NATIONAL_FAIL_CALL) {
if (l < AX25_ADDR_LEN)
return -1;
memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN); memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN);
} }
else if (*p == FAC_NATIONAL_FAIL_ADD) { else if (*p == FAC_NATIONAL_FAIL_ADD) {
if (l < 1 + ROSE_ADDR_LEN)
return -1;
memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN); memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN);
} }
else if (*p == FAC_NATIONAL_DIGIS) { else if (*p == FAC_NATIONAL_DIGIS) {
if (l % AX25_ADDR_LEN)
return -1;
fac_national_digis_received = 1; fac_national_digis_received = 1;
facilities->source_ndigis = 0; facilities->source_ndigis = 0;
facilities->dest_ndigis = 0; facilities->dest_ndigis = 0;
for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) { for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) {
if (pt[6] & AX25_HBIT) if (pt[6] & AX25_HBIT) {
if (facilities->dest_ndigis >= ROSE_MAX_DIGIS)
return -1;
memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN); memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN);
else } else {
if (facilities->source_ndigis >= ROSE_MAX_DIGIS)
return -1;
memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN); memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN);
}
} }
} }
p += l + 2; p += l + 2;
...@@ -314,25 +339,38 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac ...@@ -314,25 +339,38 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac
do { do {
switch (*p & 0xC0) { switch (*p & 0xC0) {
case 0x00: case 0x00:
if (len < 2)
return -1;
p += 2; p += 2;
n += 2; n += 2;
len -= 2; len -= 2;
break; break;
case 0x40: case 0x40:
if (len < 3)
return -1;
p += 3; p += 3;
n += 3; n += 3;
len -= 3; len -= 3;
break; break;
case 0x80: case 0x80:
if (len < 4)
return -1;
p += 4; p += 4;
n += 4; n += 4;
len -= 4; len -= 4;
break; break;
case 0xC0: case 0xC0:
if (len < 2)
return -1;
l = p[1]; l = p[1];
/* Prevent overflows*/
if (l < 10 || l > 20)
return -1;
if (*p == FAC_CCITT_DEST_NSAP) { if (*p == FAC_CCITT_DEST_NSAP) {
memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN);
memcpy(callsign, p + 12, l - 10); memcpy(callsign, p + 12, l - 10);
...@@ -355,45 +393,44 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac ...@@ -355,45 +393,44 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac
return n; return n;
} }
int rose_parse_facilities(unsigned char *p, int rose_parse_facilities(unsigned char *p, unsigned packet_len,
struct rose_facilities_struct *facilities) struct rose_facilities_struct *facilities)
{ {
int facilities_len, len; int facilities_len, len;
facilities_len = *p++; facilities_len = *p++;
if (facilities_len == 0) if (facilities_len == 0 || (unsigned)facilities_len > packet_len)
return 0; return 0;
while (facilities_len > 0) { while (facilities_len >= 3 && *p == 0x00) {
if (*p == 0x00) { facilities_len--;
facilities_len--; p++;
p++;
switch (*p) {
switch (*p) { case FAC_NATIONAL: /* National */
case FAC_NATIONAL: /* National */ len = rose_parse_national(p + 1, facilities, facilities_len - 1);
len = rose_parse_national(p + 1, facilities, facilities_len - 1); break;
facilities_len -= len + 1;
p += len + 1; case FAC_CCITT: /* CCITT */
break; len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1);
break;
case FAC_CCITT: /* CCITT */
len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1); default:
facilities_len -= len + 1; printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p);
p += len + 1; len = 1;
break; break;
}
default:
printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p); if (len < 0)
facilities_len--; return 0;
p++; if (WARN_ON(len >= facilities_len))
break; return 0;
} facilities_len -= len + 1;
} else p += len + 1;
break; /* Error in facilities format */
} }
return 1; return facilities_len == 0;
} }
static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose) static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose)
......
...@@ -173,7 +173,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) ...@@ -173,7 +173,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
goto drop_unlock; goto drop_unlock;
} }
if (x->props.replay_window && x->repl->check(x, skb, seq)) { if (x->repl->check(x, skb, seq)) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR);
goto drop_unlock; goto drop_unlock;
} }
...@@ -190,6 +190,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) ...@@ -190,6 +190,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
XFRM_SKB_CB(skb)->seq.input.low = seq; XFRM_SKB_CB(skb)->seq.input.low = seq;
XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; XFRM_SKB_CB(skb)->seq.input.hi = seq_hi;
skb_dst_force(skb);
nexthdr = x->type->input(x, skb); nexthdr = x->type->input(x, skb);
if (nexthdr == -EINPROGRESS) if (nexthdr == -EINPROGRESS)
......
...@@ -78,6 +78,8 @@ static int xfrm_output_one(struct sk_buff *skb, int err) ...@@ -78,6 +78,8 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
spin_unlock_bh(&x->lock); spin_unlock_bh(&x->lock);
skb_dst_force(skb);
err = x->type->output(x, skb); err = x->type->output(x, skb);
if (err == -EINPROGRESS) if (err == -EINPROGRESS)
goto out_exit; goto out_exit;
...@@ -94,7 +96,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err) ...@@ -94,7 +96,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
err = -EHOSTUNREACH; err = -EHOSTUNREACH;
goto error_nolock; goto error_nolock;
} }
skb_dst_set(skb, dst_clone(dst)); skb_dst_set(skb, dst);
x = dst->xfrm; x = dst->xfrm;
} while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
......
...@@ -118,6 +118,9 @@ static int xfrm_replay_check(struct xfrm_state *x, ...@@ -118,6 +118,9 @@ static int xfrm_replay_check(struct xfrm_state *x,
u32 diff; u32 diff;
u32 seq = ntohl(net_seq); u32 seq = ntohl(net_seq);
if (!x->props.replay_window)
return 0;
if (unlikely(seq == 0)) if (unlikely(seq == 0))
goto err; goto err;
...@@ -193,9 +196,14 @@ static int xfrm_replay_check_bmp(struct xfrm_state *x, ...@@ -193,9 +196,14 @@ static int xfrm_replay_check_bmp(struct xfrm_state *x,
{ {
unsigned int bitnr, nr; unsigned int bitnr, nr;
struct xfrm_replay_state_esn *replay_esn = x->replay_esn; struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
u32 pos;
u32 seq = ntohl(net_seq); u32 seq = ntohl(net_seq);
u32 diff = replay_esn->seq - seq; u32 diff = replay_esn->seq - seq;
u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window;
if (!replay_esn->replay_window)
return 0;
pos = (replay_esn->seq - 1) % replay_esn->replay_window;
if (unlikely(seq == 0)) if (unlikely(seq == 0))
goto err; goto err;
...@@ -373,12 +381,17 @@ static int xfrm_replay_check_esn(struct xfrm_state *x, ...@@ -373,12 +381,17 @@ static int xfrm_replay_check_esn(struct xfrm_state *x,
unsigned int bitnr, nr; unsigned int bitnr, nr;
u32 diff; u32 diff;
struct xfrm_replay_state_esn *replay_esn = x->replay_esn; struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
u32 pos;
u32 seq = ntohl(net_seq); u32 seq = ntohl(net_seq);
u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window;
u32 wsize = replay_esn->replay_window; u32 wsize = replay_esn->replay_window;
u32 top = replay_esn->seq; u32 top = replay_esn->seq;
u32 bottom = top - wsize + 1; u32 bottom = top - wsize + 1;
if (!wsize)
return 0;
pos = (replay_esn->seq - 1) % replay_esn->replay_window;
if (unlikely(seq == 0 && replay_esn->seq_hi == 0 && if (unlikely(seq == 0 && replay_esn->seq_hi == 0 &&
(replay_esn->seq < replay_esn->replay_window - 1))) (replay_esn->seq < replay_esn->replay_window - 1)))
goto err; goto err;
......
...@@ -1181,6 +1181,12 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) ...@@ -1181,6 +1181,12 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
goto error; goto error;
} }
if (orig->replay_esn) {
err = xfrm_replay_clone(x, orig);
if (err)
goto error;
}
memcpy(&x->mark, &orig->mark, sizeof(x->mark)); memcpy(&x->mark, &orig->mark, sizeof(x->mark));
err = xfrm_init_state(x); err = xfrm_init_state(x);
......
...@@ -127,6 +127,9 @@ static inline int verify_replay(struct xfrm_usersa_info *p, ...@@ -127,6 +127,9 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
if (!rt) if (!rt)
return 0; return 0;
if (p->id.proto != IPPROTO_ESP)
return -EINVAL;
if (p->replay_window != 0) if (p->replay_window != 0)
return -EINVAL; return -EINVAL;
...@@ -360,6 +363,23 @@ static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props, ...@@ -360,6 +363,23 @@ static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props,
return 0; return 0;
} }
static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_esn,
struct nlattr *rp)
{
struct xfrm_replay_state_esn *up;
if (!replay_esn || !rp)
return 0;
up = nla_data(rp);
if (xfrm_replay_state_esn_len(replay_esn) !=
xfrm_replay_state_esn_len(up))
return -EINVAL;
return 0;
}
static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn, static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn,
struct xfrm_replay_state_esn **preplay_esn, struct xfrm_replay_state_esn **preplay_esn,
struct nlattr *rta) struct nlattr *rta)
...@@ -1766,6 +1786,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1766,6 +1786,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
if (x->km.state != XFRM_STATE_VALID) if (x->km.state != XFRM_STATE_VALID)
goto out; goto out;
err = xfrm_replay_verify_len(x->replay_esn, rp);
if (err)
goto out;
spin_lock_bh(&x->lock); spin_lock_bh(&x->lock);
xfrm_update_ae_params(x, attrs); xfrm_update_ae_params(x, attrs);
spin_unlock_bh(&x->lock); spin_unlock_bh(&x->lock);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册