mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-30 07:34:12 +08:00
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 ...
This commit is contained in:
commit
cb1817b373
@ -1237,8 +1237,17 @@ static int bfin_mac_enable(struct phy_device *phydev)
|
||||
|
||||
if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
|
||||
opmode |= RMII; /* For Now only 100MBit are supported */
|
||||
#if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) && CONFIG_BF_REV_0_2
|
||||
opmode |= TE;
|
||||
#if defined(CONFIG_BF537) || defined(CONFIG_BF536)
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -8317,7 +8317,7 @@ static const struct net_device_ops bnx2_netdev_ops = {
|
||||
#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;
|
||||
}
|
||||
|
@ -588,14 +588,9 @@ static void c_can_chip_config(struct net_device *dev)
|
||||
{
|
||||
struct c_can_priv *priv = netdev_priv(dev);
|
||||
|
||||
if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
|
||||
/* disable automatic retransmission */
|
||||
priv->write_reg(priv, &priv->regs->control,
|
||||
CONTROL_DISABLE_AR);
|
||||
else
|
||||
/* enable automatic retransmission */
|
||||
priv->write_reg(priv, &priv->regs->control,
|
||||
CONTROL_ENABLE_AR);
|
||||
/* enable automatic retransmission */
|
||||
priv->write_reg(priv, &priv->regs->control,
|
||||
CONTROL_ENABLE_AR);
|
||||
|
||||
if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY &
|
||||
CAN_CTRLMODE_LOOPBACK)) {
|
||||
@ -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++) {
|
||||
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);
|
||||
if (!(val & (1 << msg_obj_no))) {
|
||||
can_get_echo_skb(dev,
|
||||
@ -713,6 +707,7 @@ static void c_can_do_tx(struct net_device *dev)
|
||||
&priv->regs->ifregs[0].msg_cntrl)
|
||||
& IF_MCONT_DLC_MASK;
|
||||
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)
|
||||
priv->can.bittiming_const = &c_can_bittiming_const;
|
||||
priv->can.do_set_mode = c_can_set_mode;
|
||||
priv->can.do_get_berr_counter = c_can_get_berr_counter;
|
||||
priv->can.ctrlmode_supported = CAN_CTRLMODE_ONE_SHOT |
|
||||
CAN_CTRLMODE_LOOPBACK |
|
||||
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
|
||||
CAN_CTRLMODE_LISTENONLY |
|
||||
CAN_CTRLMODE_BERR_REPORTING;
|
||||
|
||||
|
@ -73,7 +73,8 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
|
||||
void __iomem *addr;
|
||||
struct net_device *dev;
|
||||
struct c_can_priv *priv;
|
||||
struct resource *mem, *irq;
|
||||
struct resource *mem;
|
||||
int irq;
|
||||
#ifdef CONFIG_HAVE_CLK
|
||||
struct clk *clk;
|
||||
|
||||
@ -88,8 +89,8 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
|
||||
|
||||
/* get the platform data */
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (!mem || (irq <= 0)) {
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (!mem || irq <= 0) {
|
||||
ret = -ENODEV;
|
||||
goto exit_free_clk;
|
||||
}
|
||||
@ -117,7 +118,7 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
|
||||
|
||||
priv = netdev_priv(dev);
|
||||
|
||||
dev->irq = irq->start;
|
||||
dev->irq = irq;
|
||||
priv->regs = addr;
|
||||
#ifdef CONFIG_HAVE_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)
|
||||
{
|
||||
struct port_info *pi = netdev_priv(dev);
|
||||
struct adapter *adapter = pi->adapter;
|
||||
struct qset_params *qsp = &adapter->params.sge.qset[0];
|
||||
struct sge_qset *qs = &adapter->sge.qs[0];
|
||||
struct qset_params *qsp;
|
||||
struct sge_qset *qs;
|
||||
int i;
|
||||
|
||||
if (c->rx_coalesce_usecs * 10 > M_NEWTIMER)
|
||||
return -EINVAL;
|
||||
|
||||
qsp->coalesce_usecs = c->rx_coalesce_usecs;
|
||||
t3_update_qset_coalesce(qs, qsp);
|
||||
for (i = 0; i < pi->nqsets; i++) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -273,7 +273,7 @@ jme_clear_pm(struct jme_adapter *jme)
|
||||
{
|
||||
jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs);
|
||||
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
|
||||
@ -2538,6 +2538,8 @@ jme_set_wol(struct net_device *netdev,
|
||||
|
||||
jwrite32(jme, JME_PMCS, jme->reg_pmcs);
|
||||
|
||||
device_set_wakeup_enable(&jme->pdev->dev, jme->reg_pmcs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3172,9 +3174,9 @@ jme_shutdown(struct pci_dev *pdev)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int
|
||||
jme_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
static int jme_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||
struct jme_adapter *jme = netdev_priv(netdev);
|
||||
|
||||
@ -3206,22 +3208,18 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
tasklet_hi_enable(&jme->rxclean_task);
|
||||
tasklet_hi_enable(&jme->rxempty_task);
|
||||
|
||||
pci_save_state(pdev);
|
||||
jme_powersave_phy(jme);
|
||||
pci_enable_wake(jme->pdev, PCI_D3hot, true);
|
||||
pci_set_power_state(pdev, PCI_D3hot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
jme_resume(struct pci_dev *pdev)
|
||||
static int jme_resume(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||
struct jme_adapter *jme = netdev_priv(netdev);
|
||||
|
||||
jme_clear_pm(jme);
|
||||
pci_restore_state(pdev);
|
||||
jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs);
|
||||
|
||||
jme_phy_on(jme);
|
||||
if (test_bit(JME_FLAG_SSET, &jme->flags))
|
||||
@ -3238,6 +3236,13 @@ jme_resume(struct pci_dev *pdev)
|
||||
|
||||
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
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = {
|
||||
@ -3251,11 +3256,8 @@ static struct pci_driver jme_driver = {
|
||||
.id_table = jme_pci_tbl,
|
||||
.probe = jme_init_one,
|
||||
.remove = __devexit_p(jme_remove_one),
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = jme_suspend,
|
||||
.resume = jme_resume,
|
||||
#endif /* CONFIG_PM */
|
||||
.shutdown = jme_shutdown,
|
||||
.driver.pm = JME_PM_OPS,
|
||||
};
|
||||
|
||||
static int __init
|
||||
|
@ -4898,7 +4898,7 @@ static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
goto unlock;
|
||||
}
|
||||
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;
|
||||
copy_old_skb(org_skb, skb);
|
||||
}
|
||||
|
@ -742,6 +742,9 @@ int mlx4_en_start_port(struct net_device *dev)
|
||||
0, MLX4_PROT_ETH))
|
||||
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 */
|
||||
queue_work(mdev->workqueue, &priv->mcast_task);
|
||||
|
||||
|
@ -1312,17 +1312,26 @@ myri10ge_unmap_rx_page(struct pci_dev *pdev,
|
||||
* page into an skb */
|
||||
|
||||
static inline int
|
||||
myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx,
|
||||
int bytes, int len, __wsum csum)
|
||||
myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum,
|
||||
int lro_enabled)
|
||||
{
|
||||
struct myri10ge_priv *mgp = ss->mgp;
|
||||
struct sk_buff *skb;
|
||||
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 net_device *dev = mgp->dev;
|
||||
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;
|
||||
idx = rx->cnt & rx->mask;
|
||||
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,
|
||||
remainder -= MYRI10GE_ALLOC_SIZE;
|
||||
}
|
||||
|
||||
if (dev->features & NETIF_F_LRO) {
|
||||
if (lro_enabled) {
|
||||
rx_frags[0].page_offset += MXGEFW_PAD;
|
||||
rx_frags[0].size -= MXGEFW_PAD;
|
||||
len -= MXGEFW_PAD;
|
||||
@ -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_priv *mgp = ss->mgp;
|
||||
struct net_device *netdev = mgp->dev;
|
||||
|
||||
unsigned long rx_bytes = 0;
|
||||
unsigned long rx_packets = 0;
|
||||
unsigned long rx_ok;
|
||||
@ -1474,18 +1483,18 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
|
||||
u16 length;
|
||||
__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) {
|
||||
length = ntohs(rx_done->entry[idx].length);
|
||||
rx_done->entry[idx].length = 0;
|
||||
checksum = csum_unfold(rx_done->entry[idx].checksum);
|
||||
if (length <= mgp->small_bytes)
|
||||
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_ok = myri10ge_rx_done(ss, length, checksum, lro_enabled);
|
||||
rx_packets += rx_ok;
|
||||
rx_bytes += rx_ok * (unsigned long)length;
|
||||
cnt++;
|
||||
@ -1497,7 +1506,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
|
||||
ss->stats.rx_packets += rx_packets;
|
||||
ss->stats.rx_bytes += rx_bytes;
|
||||
|
||||
if (netdev->features & NETIF_F_LRO)
|
||||
if (lro_enabled)
|
||||
lro_flush_all(&rx_done->lro_mgr);
|
||||
|
||||
/* restock receive rings if needed */
|
||||
|
@ -871,7 +871,7 @@ static int netxen_nic_set_flags(struct net_device *netdev, u32 data)
|
||||
struct netxen_adapter *adapter = netdev_priv(netdev);
|
||||
int hw_lro;
|
||||
|
||||
if (data & ~ETH_FLAG_LRO)
|
||||
if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
|
||||
return -EINVAL;
|
||||
|
||||
if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO))
|
||||
|
@ -1003,7 +1003,7 @@ static int qlcnic_set_flags(struct net_device *netdev, u32 data)
|
||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||
int hw_lro;
|
||||
|
||||
if (data & ~ETH_FLAG_LRO)
|
||||
if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
|
||||
return -EINVAL;
|
||||
|
||||
if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO))
|
||||
|
@ -6726,7 +6726,7 @@ static int s2io_ethtool_set_flags(struct net_device *dev, u32 data)
|
||||
int rc = 0;
|
||||
int changed = 0;
|
||||
|
||||
if (data & ~ETH_FLAG_LRO)
|
||||
if (ethtool_invalid_flags(dev, data, ETH_FLAG_LRO))
|
||||
return -EINVAL;
|
||||
|
||||
if (data & ETH_FLAG_LRO) {
|
||||
|
@ -48,9 +48,9 @@
|
||||
#include <net/ip.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#ifdef CONFIG_SPARC
|
||||
#include <asm/idprom.h>
|
||||
@ -13118,7 +13118,7 @@ done:
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -304,8 +304,8 @@ vmxnet3_set_flags(struct net_device *netdev, u32 data)
|
||||
u8 lro_present = (netdev->features & NETIF_F_LRO) == 0 ? 0 : 1;
|
||||
unsigned long flags;
|
||||
|
||||
if (data & ~ETH_FLAG_LRO)
|
||||
return -EOPNOTSUPP;
|
||||
if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
|
||||
return -EINVAL;
|
||||
|
||||
if (lro_requested ^ lro_present) {
|
||||
/* toggle the LRO feature*/
|
||||
|
@ -1117,8 +1117,8 @@ static int vxge_set_flags(struct net_device *dev, u32 data)
|
||||
struct vxgedev *vdev = netdev_priv(dev);
|
||||
enum vxge_hw_status status;
|
||||
|
||||
if (data & ~ETH_FLAG_RXHASH)
|
||||
return -EOPNOTSUPP;
|
||||
if (ethtool_invalid_flags(dev, data, ETH_FLAG_RXHASH))
|
||||
return -EINVAL;
|
||||
|
||||
if (!!(data & ETH_FLAG_RXHASH) == vdev->devh->config.rth_en)
|
||||
return 0;
|
||||
|
@ -36,10 +36,10 @@
|
||||
* @prot: pointer to struct proto structure.
|
||||
*/
|
||||
struct can_proto {
|
||||
int type;
|
||||
int protocol;
|
||||
struct proto_ops *ops;
|
||||
struct proto *prot;
|
||||
int type;
|
||||
int protocol;
|
||||
const struct proto_ops *ops;
|
||||
struct proto *prot;
|
||||
};
|
||||
|
||||
/* 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,
|
||||
void *data);
|
||||
|
||||
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 */
|
||||
|
@ -680,6 +680,7 @@ int ethtool_op_set_ufo(struct net_device *dev, u32 data);
|
||||
u32 ethtool_op_get_flags(struct net_device *dev);
|
||||
int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported);
|
||||
void ethtool_ntuple_flush(struct net_device *dev);
|
||||
bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
|
||||
|
||||
/**
|
||||
* ðtool_ops - Alter and report network device settings
|
||||
|
@ -122,8 +122,14 @@ struct sk_buff_head {
|
||||
|
||||
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)
|
||||
#endif
|
||||
|
||||
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)
|
||||
|
||||
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);
|
||||
return child;
|
||||
|
@ -14,6 +14,12 @@
|
||||
|
||||
#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_Q_BIT 0x80
|
||||
#define ROSE_D_BIT 0x40
|
||||
@ -214,7 +220,7 @@ extern void rose_requeue_frames(struct sock *);
|
||||
extern int rose_validate_nr(struct sock *, unsigned short);
|
||||
extern void rose_write_internal(struct sock *, 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);
|
||||
|
||||
/* rose_timer.c */
|
||||
|
@ -1601,6 +1601,28 @@ static inline int xfrm_replay_state_esn_len(struct xfrm_replay_state_esn *replay
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
struct net_bridge_port *p;
|
||||
int err = 0;
|
||||
bool changed_addr;
|
||||
|
||||
/* Don't allow bridging non-ethernet like devices */
|
||||
if ((dev->flags & IFF_LOOPBACK) ||
|
||||
@ -446,7 +447,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
|
||||
list_add_rcu(&p->list, &br->port_list);
|
||||
|
||||
spin_lock_bh(&br->lock);
|
||||
br_stp_recalculate_bridge_id(br);
|
||||
changed_addr = br_stp_recalculate_bridge_id(br);
|
||||
br_features_recompute(br);
|
||||
|
||||
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)
|
||||
|
||||
br_ifinfo_notify(RTM_NEWLINK, p);
|
||||
|
||||
if (changed_addr)
|
||||
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
|
||||
|
||||
dev_set_mtu(br->dev, br_min_mtu(br));
|
||||
|
||||
kobject_uevent(&p->kobj, KOBJ_ADD);
|
||||
|
@ -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_enable_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_set_bridge_priority(struct net_bridge *br,
|
||||
u16 newprio);
|
||||
|
@ -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];
|
||||
|
||||
/* 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_aligned;
|
||||
@ -222,8 +222,11 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br)
|
||||
|
||||
}
|
||||
|
||||
if (compare_ether_addr(br->bridge_id.addr, addr))
|
||||
br_stp_change_bridge_id(br, addr);
|
||||
if (compare_ether_addr(br->bridge_id.addr, addr) == 0)
|
||||
return false; /* no change */
|
||||
|
||||
br_stp_change_bridge_id(br, addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* called under bridge lock */
|
||||
|
@ -95,7 +95,7 @@ struct s_pstats can_pstats; /* receive list statistics */
|
||||
* 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;
|
||||
|
||||
@ -108,6 +108,7 @@ static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(can_ioctl);
|
||||
|
||||
static void can_sock_destruct(struct sock *sk)
|
||||
{
|
||||
@ -698,13 +699,9 @@ int can_proto_register(struct can_proto *cp)
|
||||
printk(KERN_ERR "can: protocol %d already registered\n",
|
||||
proto);
|
||||
err = -EBUSY;
|
||||
} else {
|
||||
} else
|
||||
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);
|
||||
|
||||
if (err < 0)
|
||||
|
@ -1569,7 +1569,7 @@ static int bcm_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
return size;
|
||||
}
|
||||
|
||||
static struct proto_ops bcm_ops __read_mostly = {
|
||||
static const struct proto_ops bcm_ops = {
|
||||
.family = PF_CAN,
|
||||
.release = bcm_release,
|
||||
.bind = sock_no_bind,
|
||||
@ -1578,7 +1578,7 @@ static struct proto_ops bcm_ops __read_mostly = {
|
||||
.accept = sock_no_accept,
|
||||
.getname = sock_no_getname,
|
||||
.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,
|
||||
.shutdown = sock_no_shutdown,
|
||||
.setsockopt = sock_no_setsockopt,
|
||||
|
@ -742,7 +742,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
return size;
|
||||
}
|
||||
|
||||
static struct proto_ops raw_ops __read_mostly = {
|
||||
static const struct proto_ops raw_ops = {
|
||||
.family = PF_CAN,
|
||||
.release = raw_release,
|
||||
.bind = raw_bind,
|
||||
@ -751,7 +751,7 @@ static struct proto_ops raw_ops __read_mostly = {
|
||||
.accept = sock_no_accept,
|
||||
.getname = raw_getname,
|
||||
.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,
|
||||
.shutdown = sock_no_shutdown,
|
||||
.setsockopt = raw_setsockopt,
|
||||
|
@ -1140,9 +1140,6 @@ static int __dev_open(struct net_device *dev)
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
/*
|
||||
* Is it even present?
|
||||
*/
|
||||
if (!netif_device_present(dev))
|
||||
return -ENODEV;
|
||||
|
||||
@ -1151,9 +1148,6 @@ static int __dev_open(struct net_device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Call device private open method
|
||||
*/
|
||||
set_bit(__LINK_STATE_START, &dev->state);
|
||||
|
||||
if (ops->ndo_validate_addr)
|
||||
@ -1162,31 +1156,12 @@ static int __dev_open(struct net_device *dev)
|
||||
if (!ret && ops->ndo_open)
|
||||
ret = ops->ndo_open(dev);
|
||||
|
||||
/*
|
||||
* If it went open OK then:
|
||||
*/
|
||||
|
||||
if (ret)
|
||||
clear_bit(__LINK_STATE_START, &dev->state);
|
||||
else {
|
||||
/*
|
||||
* Set the flags.
|
||||
*/
|
||||
dev->flags |= IFF_UP;
|
||||
|
||||
/*
|
||||
* Enable NET_DMA
|
||||
*/
|
||||
net_dmaengine_get();
|
||||
|
||||
/*
|
||||
* Initialize multicasting status
|
||||
*/
|
||||
dev_set_rx_mode(dev);
|
||||
|
||||
/*
|
||||
* Wakeup transmit queue engine
|
||||
*/
|
||||
dev_activate(dev);
|
||||
}
|
||||
|
||||
@ -1209,22 +1184,13 @@ int dev_open(struct net_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Is it already up?
|
||||
*/
|
||||
if (dev->flags & IFF_UP)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Open device
|
||||
*/
|
||||
ret = __dev_open(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* ... and announce new interface.
|
||||
*/
|
||||
rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
|
||||
call_netdevice_notifiers(NETDEV_UP, dev);
|
||||
|
||||
@ -1240,10 +1206,6 @@ static int __dev_close_many(struct list_head *head)
|
||||
might_sleep();
|
||||
|
||||
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);
|
||||
|
||||
clear_bit(__LINK_STATE_START, &dev->state);
|
||||
@ -1272,15 +1234,7 @@ static int __dev_close_many(struct list_head *head)
|
||||
if (ops->ndo_stop)
|
||||
ops->ndo_stop(dev);
|
||||
|
||||
/*
|
||||
* Device is now down.
|
||||
*/
|
||||
|
||||
dev->flags &= ~IFF_UP;
|
||||
|
||||
/*
|
||||
* Shutdown NET_DMA
|
||||
*/
|
||||
net_dmaengine_put();
|
||||
}
|
||||
|
||||
@ -1309,9 +1263,6 @@ static int dev_close_many(struct list_head *head)
|
||||
|
||||
__dev_close_many(head);
|
||||
|
||||
/*
|
||||
* Tell people we are down
|
||||
*/
|
||||
list_for_each_entry(dev, head, unreg_list) {
|
||||
rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
|
||||
call_netdevice_notifiers(NETDEV_DOWN, dev);
|
||||
@ -1371,11 +1322,6 @@ EXPORT_SYMBOL(dev_disable_lro);
|
||||
|
||||
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
|
||||
* @nb: notifier
|
||||
@ -1477,6 +1423,7 @@ int call_netdevice_notifiers(unsigned long val, struct net_device *dev)
|
||||
ASSERT_RTNL();
|
||||
return raw_notifier_call_chain(&netdev_chain, val, dev);
|
||||
}
|
||||
EXPORT_SYMBOL(call_netdevice_notifiers);
|
||||
|
||||
/* When > 0 there are consumers of rx skb time stamps */
|
||||
static atomic_t netstamp_needed = ATOMIC_INIT(0);
|
||||
|
@ -141,9 +141,24 @@ u32 ethtool_op_get_flags(struct net_device *dev)
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (data & ~supported)
|
||||
if (ethtool_invalid_flags(dev, data, supported))
|
||||
return -EINVAL;
|
||||
|
||||
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,
|
||||
err = fib_props[fa->fa_type].error;
|
||||
if (err) {
|
||||
#ifdef CONFIG_IP_FIB_TRIE_STATS
|
||||
t->stats.semantic_match_miss++;
|
||||
t->stats.semantic_match_passed++;
|
||||
#endif
|
||||
return 1;
|
||||
return err;
|
||||
}
|
||||
if (fi->fib_flags & RTNH_F_DEAD)
|
||||
continue;
|
||||
|
@ -140,11 +140,11 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb)
|
||||
} else {
|
||||
dopt->ts_needtime = 0;
|
||||
|
||||
if (soffset + 8 <= optlen) {
|
||||
if (soffset + 7 <= optlen) {
|
||||
__be32 addr;
|
||||
|
||||
memcpy(&addr, sptr+soffset-1, 4);
|
||||
if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_LOCAL) {
|
||||
memcpy(&addr, dptr+soffset-1, 4);
|
||||
if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_UNICAST) {
|
||||
dopt->ts_needtime = 1;
|
||||
soffset += 8;
|
||||
}
|
||||
|
@ -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);
|
||||
if (IS_ERR(rt)) {
|
||||
err = PTR_ERR(rt);
|
||||
rt = NULL;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
@ -663,7 +663,7 @@ static int pim6_rcv(struct sk_buff *skb)
|
||||
skb_pull(skb, (u8 *)encap - skb->data);
|
||||
skb_reset_network_header(skb);
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
skb->ip_summed = 0;
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
skb->pkt_type = PACKET_HOST;
|
||||
|
||||
skb_tunnel_rx(skb, reg_dev);
|
||||
|
@ -656,10 +656,16 @@ static void iriap_getvaluebyclass_indication(struct iriap_cb *self,
|
||||
n = 1;
|
||||
|
||||
name_len = fp[n++];
|
||||
|
||||
IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;);
|
||||
|
||||
memcpy(name, fp+n, name_len); n+=name_len;
|
||||
name[name_len] = '\0';
|
||||
|
||||
attr_len = fp[n++];
|
||||
|
||||
IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;);
|
||||
|
||||
memcpy(attr, fp+n, attr_len); n+=attr_len;
|
||||
attr[attr_len] = '\0';
|
||||
|
||||
|
@ -105,6 +105,9 @@ irnet_ctrl_write(irnet_socket * ap,
|
||||
while(isspace(start[length - 1]))
|
||||
length--;
|
||||
|
||||
DABORT(length < 5 || length > NICKNAME_MAX_LEN + 5,
|
||||
-EINVAL, CTRL_ERROR, "Invalid nickname.\n");
|
||||
|
||||
/* Copy the name for later reuse */
|
||||
memcpy(ap->rname, start + 5, length - 5);
|
||||
ap->rname[length - 5] = '\0';
|
||||
|
@ -978,7 +978,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros
|
||||
struct sock *make;
|
||||
struct rose_sock *make_rose;
|
||||
struct rose_facilities_struct facilities;
|
||||
int n, len;
|
||||
int n;
|
||||
|
||||
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
|
||||
*/
|
||||
memset(&facilities, 0x00, sizeof(struct rose_facilities_struct));
|
||||
|
||||
len = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1;
|
||||
len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1;
|
||||
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(neigh, lci, ROSE_INVALID_FACILITY, 76);
|
||||
return 0;
|
||||
}
|
||||
|
@ -73,9 +73,20 @@ static void rose_loopback_timer(unsigned long param)
|
||||
unsigned int lci_i, lci_o;
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
skb_reset_transport_header(skb);
|
||||
|
@ -861,7 +861,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
|
||||
unsigned int lci, new_lci;
|
||||
unsigned char cause, diagnostic;
|
||||
struct net_device *dev;
|
||||
int len, res = 0;
|
||||
int res = 0;
|
||||
char buf[11];
|
||||
|
||||
#if 0
|
||||
@ -869,10 +869,17 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
|
||||
return res;
|
||||
#endif
|
||||
|
||||
if (skb->len < ROSE_MIN_LEN)
|
||||
return res;
|
||||
frametype = skb->data[2];
|
||||
lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
|
||||
src_addr = (rose_address *)(skb->data + 9);
|
||||
dest_addr = (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))
|
||||
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_route_list_lock);
|
||||
@ -1010,12 +1017,11 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
|
||||
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));
|
||||
|
||||
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);
|
||||
goto out;
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ void rose_write_internal(struct sock *sk, int frametype)
|
||||
*dptr++ = ROSE_GFI | lci1;
|
||||
*dptr++ = lci2;
|
||||
*dptr++ = frametype;
|
||||
*dptr++ = 0xAA;
|
||||
*dptr++ = ROSE_CALL_REQ_ADDR_LEN_VAL;
|
||||
memcpy(dptr, &rose->dest_addr, ROSE_ADDR_LEN);
|
||||
dptr += 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 *
|
||||
do {
|
||||
switch (*p & 0xC0) {
|
||||
case 0x00:
|
||||
if (len < 2)
|
||||
return -1;
|
||||
p += 2;
|
||||
n += 2;
|
||||
len -= 2;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
if (len < 3)
|
||||
return -1;
|
||||
if (*p == FAC_NATIONAL_RAND)
|
||||
facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF);
|
||||
p += 3;
|
||||
@ -260,40 +264,61 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct *
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
if (len < 4)
|
||||
return -1;
|
||||
p += 4;
|
||||
n += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
|
||||
case 0xC0:
|
||||
if (len < 2)
|
||||
return -1;
|
||||
l = p[1];
|
||||
if (len < 2 + l)
|
||||
return -1;
|
||||
if (*p == FAC_NATIONAL_DEST_DIGI) {
|
||||
if (!fac_national_digis_received) {
|
||||
if (l < AX25_ADDR_LEN)
|
||||
return -1;
|
||||
memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN);
|
||||
facilities->source_ndigis = 1;
|
||||
}
|
||||
}
|
||||
else if (*p == FAC_NATIONAL_SRC_DIGI) {
|
||||
if (!fac_national_digis_received) {
|
||||
if (l < AX25_ADDR_LEN)
|
||||
return -1;
|
||||
memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN);
|
||||
facilities->dest_ndigis = 1;
|
||||
}
|
||||
}
|
||||
else if (*p == FAC_NATIONAL_FAIL_CALL) {
|
||||
if (l < AX25_ADDR_LEN)
|
||||
return -1;
|
||||
memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN);
|
||||
}
|
||||
else if (*p == FAC_NATIONAL_FAIL_ADD) {
|
||||
if (l < 1 + ROSE_ADDR_LEN)
|
||||
return -1;
|
||||
memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN);
|
||||
}
|
||||
else if (*p == FAC_NATIONAL_DIGIS) {
|
||||
if (l % AX25_ADDR_LEN)
|
||||
return -1;
|
||||
fac_national_digis_received = 1;
|
||||
facilities->source_ndigis = 0;
|
||||
facilities->dest_ndigis = 0;
|
||||
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);
|
||||
else
|
||||
} else {
|
||||
if (facilities->source_ndigis >= ROSE_MAX_DIGIS)
|
||||
return -1;
|
||||
memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
p += l + 2;
|
||||
@ -314,25 +339,38 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac
|
||||
do {
|
||||
switch (*p & 0xC0) {
|
||||
case 0x00:
|
||||
if (len < 2)
|
||||
return -1;
|
||||
p += 2;
|
||||
n += 2;
|
||||
len -= 2;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
if (len < 3)
|
||||
return -1;
|
||||
p += 3;
|
||||
n += 3;
|
||||
len -= 3;
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
if (len < 4)
|
||||
return -1;
|
||||
p += 4;
|
||||
n += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
|
||||
case 0xC0:
|
||||
if (len < 2)
|
||||
return -1;
|
||||
l = p[1];
|
||||
|
||||
/* Prevent overflows*/
|
||||
if (l < 10 || l > 20)
|
||||
return -1;
|
||||
|
||||
if (*p == FAC_CCITT_DEST_NSAP) {
|
||||
memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN);
|
||||
memcpy(callsign, p + 12, l - 10);
|
||||
@ -355,45 +393,44 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac
|
||||
return n;
|
||||
}
|
||||
|
||||
int rose_parse_facilities(unsigned char *p,
|
||||
int rose_parse_facilities(unsigned char *p, unsigned packet_len,
|
||||
struct rose_facilities_struct *facilities)
|
||||
{
|
||||
int facilities_len, len;
|
||||
|
||||
facilities_len = *p++;
|
||||
|
||||
if (facilities_len == 0)
|
||||
if (facilities_len == 0 || (unsigned)facilities_len > packet_len)
|
||||
return 0;
|
||||
|
||||
while (facilities_len > 0) {
|
||||
if (*p == 0x00) {
|
||||
facilities_len--;
|
||||
p++;
|
||||
while (facilities_len >= 3 && *p == 0x00) {
|
||||
facilities_len--;
|
||||
p++;
|
||||
|
||||
switch (*p) {
|
||||
case FAC_NATIONAL: /* National */
|
||||
len = rose_parse_national(p + 1, facilities, facilities_len - 1);
|
||||
facilities_len -= len + 1;
|
||||
p += len + 1;
|
||||
break;
|
||||
switch (*p) {
|
||||
case FAC_NATIONAL: /* National */
|
||||
len = rose_parse_national(p + 1, facilities, facilities_len - 1);
|
||||
break;
|
||||
|
||||
case FAC_CCITT: /* CCITT */
|
||||
len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1);
|
||||
facilities_len -= len + 1;
|
||||
p += len + 1;
|
||||
break;
|
||||
case FAC_CCITT: /* CCITT */
|
||||
len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p);
|
||||
facilities_len--;
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
break; /* Error in facilities format */
|
||||
default:
|
||||
printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p);
|
||||
len = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (len < 0)
|
||||
return 0;
|
||||
if (WARN_ON(len >= facilities_len))
|
||||
return 0;
|
||||
facilities_len -= len + 1;
|
||||
p += len + 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return facilities_len == 0;
|
||||
}
|
||||
|
||||
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)
|
||||
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);
|
||||
goto drop_unlock;
|
||||
}
|
||||
@ -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.hi = seq_hi;
|
||||
|
||||
skb_dst_force(skb);
|
||||
|
||||
nexthdr = x->type->input(x, skb);
|
||||
|
||||
if (nexthdr == -EINPROGRESS)
|
||||
|
@ -78,6 +78,8 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
|
||||
|
||||
spin_unlock_bh(&x->lock);
|
||||
|
||||
skb_dst_force(skb);
|
||||
|
||||
err = x->type->output(x, skb);
|
||||
if (err == -EINPROGRESS)
|
||||
goto out_exit;
|
||||
@ -94,7 +96,7 @@ resume:
|
||||
err = -EHOSTUNREACH;
|
||||
goto error_nolock;
|
||||
}
|
||||
skb_dst_set(skb, dst_clone(dst));
|
||||
skb_dst_set(skb, dst);
|
||||
x = dst->xfrm;
|
||||
} while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
|
||||
|
||||
|
@ -118,6 +118,9 @@ static int xfrm_replay_check(struct xfrm_state *x,
|
||||
u32 diff;
|
||||
u32 seq = ntohl(net_seq);
|
||||
|
||||
if (!x->props.replay_window)
|
||||
return 0;
|
||||
|
||||
if (unlikely(seq == 0))
|
||||
goto err;
|
||||
|
||||
@ -193,9 +196,14 @@ static int xfrm_replay_check_bmp(struct xfrm_state *x,
|
||||
{
|
||||
unsigned int bitnr, nr;
|
||||
struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
|
||||
u32 pos;
|
||||
u32 seq = ntohl(net_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))
|
||||
goto err;
|
||||
@ -373,12 +381,17 @@ static int xfrm_replay_check_esn(struct xfrm_state *x,
|
||||
unsigned int bitnr, nr;
|
||||
u32 diff;
|
||||
struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
|
||||
u32 pos;
|
||||
u32 seq = ntohl(net_seq);
|
||||
u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window;
|
||||
u32 wsize = replay_esn->replay_window;
|
||||
u32 top = replay_esn->seq;
|
||||
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 &&
|
||||
(replay_esn->seq < replay_esn->replay_window - 1)))
|
||||
goto err;
|
||||
|
@ -1181,6 +1181,12 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (orig->replay_esn) {
|
||||
err = xfrm_replay_clone(x, orig);
|
||||
if (err)
|
||||
goto error;
|
||||
}
|
||||
|
||||
memcpy(&x->mark, &orig->mark, sizeof(x->mark));
|
||||
|
||||
err = xfrm_init_state(x);
|
||||
|
@ -127,6 +127,9 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
|
||||
if (!rt)
|
||||
return 0;
|
||||
|
||||
if (p->id.proto != IPPROTO_ESP)
|
||||
return -EINVAL;
|
||||
|
||||
if (p->replay_window != 0)
|
||||
return -EINVAL;
|
||||
|
||||
@ -360,6 +363,23 @@ static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props,
|
||||
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,
|
||||
struct xfrm_replay_state_esn **preplay_esn,
|
||||
struct nlattr *rta)
|
||||
@ -1766,6 +1786,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
if (x->km.state != XFRM_STATE_VALID)
|
||||
goto out;
|
||||
|
||||
err = xfrm_replay_verify_len(x->replay_esn, rp);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
spin_lock_bh(&x->lock);
|
||||
xfrm_update_ae_params(x, attrs);
|
||||
spin_unlock_bh(&x->lock);
|
||||
|
Loading…
Reference in New Issue
Block a user