1
0
Fork 0

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: (40 commits)
  pxa168_eth: fix race in transmit path.
  ipv4, ping: Remove duplicate icmp.h include
  netxen: fix race in skb->len access
  sgi-xp: fix a use after free
  hp100: fix an skb->len race
  netpoll: copy dev name of slaves to struct netpoll
  ipv4: fix multicast losses
  r8169: fix static initializers.
  inet_diag: fix inet_diag_bc_audit()
  gigaset: call module_put before restart of if_open()
  farsync: add module_put to error path in fst_open()
  net: rfs: enable RFS before first data packet is received
  fs_enet: fix freescale FCC ethernet dp buffer alignment
  netdev: bfin_mac: fix memory leak when freeing dma descriptors
  vlan: don't call ndo_vlan_rx_register on hardware that doesn't have vlan support
  caif: Bugfix - XOFF removed channel from caif-mux
  tun: teach the tun/tap driver to support netpoll
  dp83640: drop PHY status frames in the driver.
  dp83640: fix phy status frame event parsing
  phylib: Allow BCM63XX PHY to be selected only on BCM63XX.
  ...
hifive-unleashed-5.1
Linus Torvalds 2011-06-20 20:10:18 -07:00
commit 6e158d2198
48 changed files with 563 additions and 77 deletions

View File

@ -2291,8 +2291,7 @@ F: drivers/scsi/eata_pio.*
EBTABLES EBTABLES
M: Bart De Schuymer <bart.de.schuymer@pandora.be> M: Bart De Schuymer <bart.de.schuymer@pandora.be>
L: ebtables-user@lists.sourceforge.net L: netfilter-devel@vger.kernel.org
L: ebtables-devel@lists.sourceforge.net
W: http://ebtables.sourceforge.net/ W: http://ebtables.sourceforge.net/
S: Maintained S: Maintained
F: include/linux/netfilter_bridge/ebt_*.h F: include/linux/netfilter_bridge/ebt_*.h

View File

@ -64,6 +64,8 @@ static ssize_t btmrvl_hscfgcmd_write(struct file *file,
return -EFAULT; return -EFAULT;
ret = strict_strtol(buf, 10, &result); ret = strict_strtol(buf, 10, &result);
if (ret)
return ret;
priv->btmrvl_dev.hscfgcmd = result; priv->btmrvl_dev.hscfgcmd = result;
@ -108,6 +110,8 @@ static ssize_t btmrvl_psmode_write(struct file *file, const char __user *ubuf,
return -EFAULT; return -EFAULT;
ret = strict_strtol(buf, 10, &result); ret = strict_strtol(buf, 10, &result);
if (ret)
return ret;
priv->btmrvl_dev.psmode = result; priv->btmrvl_dev.psmode = result;
@ -147,6 +151,8 @@ static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
return -EFAULT; return -EFAULT;
ret = strict_strtol(buf, 10, &result); ret = strict_strtol(buf, 10, &result);
if (ret)
return ret;
priv->btmrvl_dev.pscmd = result; priv->btmrvl_dev.pscmd = result;
@ -191,6 +197,8 @@ static ssize_t btmrvl_gpiogap_write(struct file *file, const char __user *ubuf,
return -EFAULT; return -EFAULT;
ret = strict_strtol(buf, 16, &result); ret = strict_strtol(buf, 16, &result);
if (ret)
return ret;
priv->btmrvl_dev.gpio_gap = result; priv->btmrvl_dev.gpio_gap = result;
@ -230,6 +238,8 @@ static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
return -EFAULT; return -EFAULT;
ret = strict_strtol(buf, 10, &result); ret = strict_strtol(buf, 10, &result);
if (ret)
return ret;
priv->btmrvl_dev.hscmd = result; priv->btmrvl_dev.hscmd = result;
if (priv->btmrvl_dev.hscmd) { if (priv->btmrvl_dev.hscmd) {
@ -272,6 +282,8 @@ static ssize_t btmrvl_hsmode_write(struct file *file, const char __user *ubuf,
return -EFAULT; return -EFAULT;
ret = strict_strtol(buf, 10, &result); ret = strict_strtol(buf, 10, &result);
if (ret)
return ret;
priv->btmrvl_dev.hsmode = result; priv->btmrvl_dev.hsmode = result;

View File

@ -156,8 +156,10 @@ static int if_open(struct tty_struct *tty, struct file *filp)
if (!cs || !try_module_get(cs->driver->owner)) if (!cs || !try_module_get(cs->driver->owner))
return -ENODEV; return -ENODEV;
if (mutex_lock_interruptible(&cs->mutex)) if (mutex_lock_interruptible(&cs->mutex)) {
module_put(cs->driver->owner);
return -ERESTARTSYS; return -ERESTARTSYS;
}
tty->driver_data = cs; tty->driver_data = cs;
++cs->open_count; ++cs->open_count;

View File

@ -495,14 +495,14 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
} }
} }
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
if (atomic_dec_return(&queued_msg->use_count) == 0) { if (atomic_dec_return(&queued_msg->use_count) == 0) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
kfree(queued_msg); kfree(queued_msg);
} }
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }

View File

@ -412,7 +412,7 @@ el2_open(struct net_device *dev)
outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR); outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
outb_p(0x00, E33G_IDCFR); outb_p(0x00, E33G_IDCFR);
msleep(1); msleep(1);
free_irq(*irqp, el2_probe_interrupt); free_irq(*irqp, &seen);
if (!seen) if (!seen)
continue; continue;
@ -422,6 +422,7 @@ el2_open(struct net_device *dev)
continue; continue;
if (retval < 0) if (retval < 0)
goto err_disable; goto err_disable;
break;
} while (*++irqp); } while (*++irqp);
if (*irqp == 0) { if (*irqp == 0) {

View File

@ -52,13 +52,13 @@ MODULE_DESCRIPTION(DRV_DESC);
MODULE_ALIAS("platform:bfin_mac"); MODULE_ALIAS("platform:bfin_mac");
#if defined(CONFIG_BFIN_MAC_USE_L1) #if defined(CONFIG_BFIN_MAC_USE_L1)
# define bfin_mac_alloc(dma_handle, size) l1_data_sram_zalloc(size) # define bfin_mac_alloc(dma_handle, size, num) l1_data_sram_zalloc(size*num)
# define bfin_mac_free(dma_handle, ptr) l1_data_sram_free(ptr) # define bfin_mac_free(dma_handle, ptr, num) l1_data_sram_free(ptr)
#else #else
# define bfin_mac_alloc(dma_handle, size) \ # define bfin_mac_alloc(dma_handle, size, num) \
dma_alloc_coherent(NULL, size, dma_handle, GFP_KERNEL) dma_alloc_coherent(NULL, size*num, dma_handle, GFP_KERNEL)
# define bfin_mac_free(dma_handle, ptr) \ # define bfin_mac_free(dma_handle, ptr, num) \
dma_free_coherent(NULL, sizeof(*ptr), ptr, dma_handle) dma_free_coherent(NULL, sizeof(*ptr)*num, ptr, dma_handle)
#endif #endif
#define PKT_BUF_SZ 1580 #define PKT_BUF_SZ 1580
@ -95,7 +95,7 @@ static void desc_list_free(void)
t = t->next; t = t->next;
} }
} }
bfin_mac_free(dma_handle, tx_desc); bfin_mac_free(dma_handle, tx_desc, CONFIG_BFIN_TX_DESC_NUM);
} }
if (rx_desc) { if (rx_desc) {
@ -109,7 +109,7 @@ static void desc_list_free(void)
r = r->next; r = r->next;
} }
} }
bfin_mac_free(dma_handle, rx_desc); bfin_mac_free(dma_handle, rx_desc, CONFIG_BFIN_RX_DESC_NUM);
} }
} }
@ -126,13 +126,13 @@ static int desc_list_init(void)
#endif #endif
tx_desc = bfin_mac_alloc(&dma_handle, tx_desc = bfin_mac_alloc(&dma_handle,
sizeof(struct net_dma_desc_tx) * sizeof(struct net_dma_desc_tx),
CONFIG_BFIN_TX_DESC_NUM); CONFIG_BFIN_TX_DESC_NUM);
if (tx_desc == NULL) if (tx_desc == NULL)
goto init_error; goto init_error;
rx_desc = bfin_mac_alloc(&dma_handle, rx_desc = bfin_mac_alloc(&dma_handle,
sizeof(struct net_dma_desc_rx) * sizeof(struct net_dma_desc_rx),
CONFIG_BFIN_RX_DESC_NUM); CONFIG_BFIN_RX_DESC_NUM);
if (rx_desc == NULL) if (rx_desc == NULL)
goto init_error; goto init_error;

View File

@ -1297,6 +1297,7 @@ static inline int slave_enable_netpoll(struct slave *slave)
goto out; goto out;
np->dev = slave->dev; np->dev = slave->dev;
strlcpy(np->dev_name, slave->dev->name, IFNAMSIZ);
err = __netpoll_setup(np); err = __netpoll_setup(np);
if (err) { if (err) {
kfree(np); kfree(np);

View File

@ -105,7 +105,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
goto out_ep; goto out_ep;
fep->fcc.mem = (void __iomem *)cpm2_immr; fep->fcc.mem = (void __iomem *)cpm2_immr;
fpi->dpram_offset = cpm_dpalloc(128, 8); fpi->dpram_offset = cpm_dpalloc(128, 32);
if (IS_ERR_VALUE(fpi->dpram_offset)) { if (IS_ERR_VALUE(fpi->dpram_offset)) {
ret = fpi->dpram_offset; ret = fpi->dpram_offset;
goto out_fcccp; goto out_fcccp;

View File

@ -1580,12 +1580,12 @@ static netdev_tx_t hp100_start_xmit_bm(struct sk_buff *skb,
hp100_outl(ringptr->pdl_paddr, TX_PDA_L); /* Low Prio. Queue */ hp100_outl(ringptr->pdl_paddr, TX_PDA_L); /* Low Prio. Queue */
lp->txrcommit++; lp->txrcommit++;
spin_unlock_irqrestore(&lp->lock, flags);
/* Update statistics */
dev->stats.tx_packets++; dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len; dev->stats.tx_bytes += skb->len;
spin_unlock_irqrestore(&lp->lock, flags);
return NETDEV_TX_OK; return NETDEV_TX_OK;
drop: drop:

View File

@ -135,7 +135,7 @@ static void __devexit hplance_remove_one(struct dio_dev *d)
} }
/* Initialise a single lance board at the given DIO device */ /* Initialise a single lance board at the given DIO device */
static void __init hplance_init(struct net_device *dev, struct dio_dev *d) static void __devinit hplance_init(struct net_device *dev, struct dio_dev *d)
{ {
unsigned long va = (d->resource.start + DIO_VIRADDRBASE); unsigned long va = (d->resource.start + DIO_VIRADDRBASE);
struct hplance_private *lp; struct hplance_private *lp;

View File

@ -1965,11 +1965,11 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
netxen_tso_check(netdev, tx_ring, first_desc, skb); netxen_tso_check(netdev, tx_ring, first_desc, skb);
netxen_nic_update_cmd_producer(adapter, tx_ring);
adapter->stats.txbytes += skb->len; adapter->stats.txbytes += skb->len;
adapter->stats.xmitcalled++; adapter->stats.xmitcalled++;
netxen_nic_update_cmd_producer(adapter, tx_ring);
return NETDEV_TX_OK; return NETDEV_TX_OK;
drop_packet: drop_packet:

View File

@ -58,6 +58,7 @@ config BROADCOM_PHY
config BCM63XX_PHY config BCM63XX_PHY
tristate "Drivers for Broadcom 63xx SOCs internal PHY" tristate "Drivers for Broadcom 63xx SOCs internal PHY"
depends on BCM63XX
---help--- ---help---
Currently supports the 6348 and 6358 PHYs. Currently supports the 6348 and 6358 PHYs.

View File

@ -543,11 +543,20 @@ static void recalibrate(struct dp83640_clock *clock)
/* time stamping methods */ /* time stamping methods */
static void decode_evnt(struct dp83640_private *dp83640, static int decode_evnt(struct dp83640_private *dp83640,
struct phy_txts *phy_txts, u16 ests) void *data, u16 ests)
{ {
struct phy_txts *phy_txts;
struct ptp_clock_event event; struct ptp_clock_event event;
int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK; int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK;
u16 ext_status = 0;
if (ests & MULT_EVNT) {
ext_status = *(u16 *) data;
data += sizeof(ext_status);
}
phy_txts = data;
switch (words) { /* fall through in every case */ switch (words) { /* fall through in every case */
case 3: case 3:
@ -565,6 +574,9 @@ static void decode_evnt(struct dp83640_private *dp83640,
event.timestamp = phy2txts(&dp83640->edata); event.timestamp = phy2txts(&dp83640->edata);
ptp_clock_event(dp83640->clock->ptp_clock, &event); ptp_clock_event(dp83640->clock->ptp_clock, &event);
words = ext_status ? words + 2 : words + 1;
return words * sizeof(u16);
} }
static void decode_rxts(struct dp83640_private *dp83640, static void decode_rxts(struct dp83640_private *dp83640,
@ -643,9 +655,7 @@ static void decode_status_frame(struct dp83640_private *dp83640,
} else if (PSF_EVNT == type && len >= sizeof(*phy_txts)) { } else if (PSF_EVNT == type && len >= sizeof(*phy_txts)) {
phy_txts = (struct phy_txts *) ptr; size = decode_evnt(dp83640, ptr, ests);
decode_evnt(dp83640, phy_txts, ests);
size = sizeof(*phy_txts);
} else { } else {
size = 0; size = 0;
@ -1034,8 +1044,8 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
if (is_status_frame(skb, type)) { if (is_status_frame(skb, type)) {
decode_status_frame(dp83640, skb); decode_status_frame(dp83640, skb);
/* Let the stack drop this frame. */ kfree_skb(skb);
return false; return true;
} }
SKB_PTP_TYPE(skb) = type; SKB_PTP_TYPE(skb) = type;

View File

@ -523,7 +523,7 @@ static void ppp_async_process(unsigned long arg)
#define PUT_BYTE(ap, buf, c, islcp) do { \ #define PUT_BYTE(ap, buf, c, islcp) do { \
if ((islcp && c < 0x20) || (ap->xaccm[c >> 5] & (1 << (c & 0x1f)))) {\ if ((islcp && c < 0x20) || (ap->xaccm[c >> 5] & (1 << (c & 0x1f)))) {\
*buf++ = PPP_ESCAPE; \ *buf++ = PPP_ESCAPE; \
*buf++ = c ^ 0x20; \ *buf++ = c ^ PPP_TRANS; \
} else \ } else \
*buf++ = c; \ *buf++ = c; \
} while (0) } while (0)
@ -896,7 +896,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
sp = skb_put(skb, n); sp = skb_put(skb, n);
memcpy(sp, buf, n); memcpy(sp, buf, n);
if (ap->state & SC_ESCAPE) { if (ap->state & SC_ESCAPE) {
sp[0] ^= 0x20; sp[0] ^= PPP_TRANS;
ap->state &= ~SC_ESCAPE; ap->state &= ~SC_ESCAPE;
} }
} }

View File

@ -1273,7 +1273,7 @@ static int pxa168_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
wmb(); wmb();
wrl(pep, SDMA_CMD, SDMA_CMD_TXDH | SDMA_CMD_ERD); wrl(pep, SDMA_CMD, SDMA_CMD_TXDH | SDMA_CMD_ERD);
stats->tx_bytes += skb->len; stats->tx_bytes += length;
stats->tx_packets++; stats->tx_packets++;
dev->trans_start = jiffies; dev->trans_start = jiffies;
if (pep->tx_ring_size - pep->tx_desc_count <= 1) { if (pep->tx_ring_size - pep->tx_desc_count <= 1) {

View File

@ -1621,7 +1621,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
* *
* (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
*/ */
static const struct { static const struct rtl_mac_info {
u32 mask; u32 mask;
u32 val; u32 val;
int mac_version; int mac_version;
@ -1689,7 +1689,8 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
/* Catch-all */ /* Catch-all */
{ 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE }
}, *p = mac_info; };
const struct rtl_mac_info *p = mac_info;
u32 reg; u32 reg;
reg = RTL_R32(TxConfig); reg = RTL_R32(TxConfig);
@ -3681,7 +3682,7 @@ static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz)
static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
{ {
static const struct { static const struct rtl_cfg2_info {
u32 mac_version; u32 mac_version;
u32 clk; u32 clk;
u32 val; u32 val;
@ -3690,7 +3691,8 @@ static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
{ RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
{ RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
{ RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
}, *p = cfg2_info; };
const struct rtl_cfg2_info *p = cfg2_info;
unsigned int i; unsigned int i;
u32 clk; u32 clk;

View File

@ -460,7 +460,23 @@ static u32 tun_net_fix_features(struct net_device *dev, u32 features)
return (features & tun->set_features) | (features & ~TUN_USER_FEATURES); return (features & tun->set_features) | (features & ~TUN_USER_FEATURES);
} }
#ifdef CONFIG_NET_POLL_CONTROLLER
static void tun_poll_controller(struct net_device *dev)
{
/*
* Tun only receives frames when:
* 1) the char device endpoint gets data from user space
* 2) the tun socket gets a sendmsg call from user space
* Since both of those are syncronous operations, we are guaranteed
* never to have pending data when we poll for it
* so theres nothing to do here but return.
* We need this though so netpoll recognizes us as an interface that
* supports polling, which enables bridge devices in virt setups to
* still use netconsole
*/
return;
}
#endif
static const struct net_device_ops tun_netdev_ops = { static const struct net_device_ops tun_netdev_ops = {
.ndo_uninit = tun_net_uninit, .ndo_uninit = tun_net_uninit,
.ndo_open = tun_net_open, .ndo_open = tun_net_open,
@ -468,6 +484,9 @@ static const struct net_device_ops tun_netdev_ops = {
.ndo_start_xmit = tun_net_xmit, .ndo_start_xmit = tun_net_xmit,
.ndo_change_mtu = tun_net_change_mtu, .ndo_change_mtu = tun_net_change_mtu,
.ndo_fix_features = tun_net_fix_features, .ndo_fix_features = tun_net_fix_features,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = tun_poll_controller,
#endif
}; };
static const struct net_device_ops tap_netdev_ops = { static const struct net_device_ops tap_netdev_ops = {
@ -480,6 +499,9 @@ static const struct net_device_ops tap_netdev_ops = {
.ndo_set_multicast_list = tun_net_mclist, .ndo_set_multicast_list = tun_net_mclist,
.ndo_set_mac_address = eth_mac_addr, .ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = tun_poll_controller,
#endif
}; };
/* Initialize net device. */ /* Initialize net device. */

View File

@ -385,6 +385,16 @@ config USB_NET_CX82310_ETH
router with USB ethernet port. This driver is for routers only, router with USB ethernet port. This driver is for routers only,
it will not work with ADSL modems (use cxacru driver instead). it will not work with ADSL modems (use cxacru driver instead).
config USB_NET_KALMIA
tristate "Samsung Kalmia based LTE USB modem"
depends on USB_USBNET
help
Choose this option if you have a Samsung Kalmia based USB modem
as Samsung GT-B3730.
To compile this driver as a module, choose M here: the
module will be called kalmia.
config USB_HSO config USB_HSO
tristate "Option USB High Speed Mobile Devices" tristate "Option USB High Speed Mobile Devices"
depends on USB && RFKILL depends on USB && RFKILL

View File

@ -23,6 +23,7 @@ obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o
obj-$(CONFIG_USB_USBNET) += usbnet.o obj-$(CONFIG_USB_USBNET) += usbnet.o
obj-$(CONFIG_USB_NET_INT51X1) += int51x1.o obj-$(CONFIG_USB_NET_INT51X1) += int51x1.o
obj-$(CONFIG_USB_CDC_PHONET) += cdc-phonet.o obj-$(CONFIG_USB_CDC_PHONET) += cdc-phonet.o
obj-$(CONFIG_USB_NET_KALMIA) += kalmia.o
obj-$(CONFIG_USB_IPHETH) += ipheth.o obj-$(CONFIG_USB_IPHETH) += ipheth.o
obj-$(CONFIG_USB_SIERRA_NET) += sierra_net.o obj-$(CONFIG_USB_SIERRA_NET) += sierra_net.o
obj-$(CONFIG_USB_NET_CX82310_ETH) += cx82310_eth.o obj-$(CONFIG_USB_NET_CX82310_ETH) += cx82310_eth.o

View File

@ -0,0 +1,384 @@
/*
* USB network interface driver for Samsung Kalmia based LTE USB modem like the
* Samsung GT-B3730 and GT-B3710.
*
* Copyright (C) 2011 Marius Bjoernstad Kotsbak <marius@kotsbak.com>
*
* Sponsored by Quicklink Video Distribution Services Ltd.
*
* Based on the cdc_eem module.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ctype.h>
#include <linux/ethtool.h>
#include <linux/workqueue.h>
#include <linux/mii.h>
#include <linux/usb.h>
#include <linux/crc32.h>
#include <linux/usb/cdc.h>
#include <linux/usb/usbnet.h>
#include <linux/gfp.h>
/*
* The Samsung Kalmia based LTE USB modems have a CDC ACM port for modem control
* handled by the "option" module and an ethernet data port handled by this
* module.
*
* The stick must first be switched into modem mode by usb_modeswitch
* or similar tool. Then the modem gets sent two initialization packets by
* this module, which gives the MAC address of the device. User space can then
* connect the modem using AT commands through the ACM port and then use
* DHCP on the network interface exposed by this module. Network packets are
* sent to and from the modem in a proprietary format discovered after watching
* the behavior of the windows driver for the modem.
*
* More information about the use of the modem is available in usb_modeswitch
* forum and the project page:
*
* http://www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?t=465
* https://github.com/mkotsbak/Samsung-GT-B3730-linux-driver
*/
/* #define DEBUG */
/* #define VERBOSE */
#define KALMIA_HEADER_LENGTH 6
#define KALMIA_ALIGN_SIZE 4
#define KALMIA_USB_TIMEOUT 10000
/*-------------------------------------------------------------------------*/
static int
kalmia_send_init_packet(struct usbnet *dev, u8 *init_msg, u8 init_msg_len,
u8 *buffer, u8 expected_len)
{
int act_len;
int status;
netdev_dbg(dev->net, "Sending init packet");
status = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 0x02),
init_msg, init_msg_len, &act_len, KALMIA_USB_TIMEOUT);
if (status != 0) {
netdev_err(dev->net,
"Error sending init packet. Status %i, length %i\n",
status, act_len);
return status;
}
else if (act_len != init_msg_len) {
netdev_err(dev->net,
"Did not send all of init packet. Bytes sent: %i",
act_len);
}
else {
netdev_dbg(dev->net, "Successfully sent init packet.");
}
status = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, 0x81),
buffer, expected_len, &act_len, KALMIA_USB_TIMEOUT);
if (status != 0)
netdev_err(dev->net,
"Error receiving init result. Status %i, length %i\n",
status, act_len);
else if (act_len != expected_len)
netdev_err(dev->net, "Unexpected init result length: %i\n",
act_len);
return status;
}
static int
kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr)
{
char init_msg_1[] =
{ 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
0x00, 0x00 };
char init_msg_2[] =
{ 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf4,
0x00, 0x00 };
char receive_buf[28];
int status;
status = kalmia_send_init_packet(dev, init_msg_1, sizeof(init_msg_1)
/ sizeof(init_msg_1[0]), receive_buf, 24);
if (status != 0)
return status;
status = kalmia_send_init_packet(dev, init_msg_2, sizeof(init_msg_2)
/ sizeof(init_msg_2[0]), receive_buf, 28);
if (status != 0)
return status;
memcpy(ethernet_addr, receive_buf + 10, ETH_ALEN);
return status;
}
static int
kalmia_bind(struct usbnet *dev, struct usb_interface *intf)
{
u8 status;
u8 ethernet_addr[ETH_ALEN];
/* Don't bind to AT command interface */
if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
return -EINVAL;
dev->in = usb_rcvbulkpipe(dev->udev, 0x81 & USB_ENDPOINT_NUMBER_MASK);
dev->out = usb_sndbulkpipe(dev->udev, 0x02 & USB_ENDPOINT_NUMBER_MASK);
dev->status = NULL;
dev->net->hard_header_len += KALMIA_HEADER_LENGTH;
dev->hard_mtu = 1400;
dev->rx_urb_size = dev->hard_mtu * 10; // Found as optimal after testing
status = kalmia_init_and_get_ethernet_addr(dev, ethernet_addr);
if (status < 0) {
usb_set_intfdata(intf, NULL);
usb_driver_release_interface(driver_of(intf), intf);
return status;
}
memcpy(dev->net->dev_addr, ethernet_addr, ETH_ALEN);
memcpy(dev->net->perm_addr, ethernet_addr, ETH_ALEN);
return status;
}
static struct sk_buff *
kalmia_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
{
struct sk_buff *skb2 = NULL;
u16 content_len;
unsigned char *header_start;
unsigned char ether_type_1, ether_type_2;
u8 remainder, padlen = 0;
if (!skb_cloned(skb)) {
int headroom = skb_headroom(skb);
int tailroom = skb_tailroom(skb);
if ((tailroom >= KALMIA_ALIGN_SIZE) && (headroom
>= KALMIA_HEADER_LENGTH))
goto done;
if ((headroom + tailroom) > (KALMIA_HEADER_LENGTH
+ KALMIA_ALIGN_SIZE)) {
skb->data = memmove(skb->head + KALMIA_HEADER_LENGTH,
skb->data, skb->len);
skb_set_tail_pointer(skb, skb->len);
goto done;
}
}
skb2 = skb_copy_expand(skb, KALMIA_HEADER_LENGTH,
KALMIA_ALIGN_SIZE, flags);
if (!skb2)
return NULL;
dev_kfree_skb_any(skb);
skb = skb2;
done: header_start = skb_push(skb, KALMIA_HEADER_LENGTH);
ether_type_1 = header_start[KALMIA_HEADER_LENGTH + 12];
ether_type_2 = header_start[KALMIA_HEADER_LENGTH + 13];
netdev_dbg(dev->net, "Sending etherType: %02x%02x", ether_type_1,
ether_type_2);
/* According to empiric data for data packages */
header_start[0] = 0x57;
header_start[1] = 0x44;
content_len = skb->len - KALMIA_HEADER_LENGTH;
header_start[2] = (content_len & 0xff); /* low byte */
header_start[3] = (content_len >> 8); /* high byte */
header_start[4] = ether_type_1;
header_start[5] = ether_type_2;
/* Align to 4 bytes by padding with zeros */
remainder = skb->len % KALMIA_ALIGN_SIZE;
if (remainder > 0) {
padlen = KALMIA_ALIGN_SIZE - remainder;
memset(skb_put(skb, padlen), 0, padlen);
}
netdev_dbg(
dev->net,
"Sending package with length %i and padding %i. Header: %02x:%02x:%02x:%02x:%02x:%02x.",
content_len, padlen, header_start[0], header_start[1],
header_start[2], header_start[3], header_start[4],
header_start[5]);
return skb;
}
static int
kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
{
/*
* Our task here is to strip off framing, leaving skb with one
* data frame for the usbnet framework code to process.
*/
const u8 HEADER_END_OF_USB_PACKET[] =
{ 0x57, 0x5a, 0x00, 0x00, 0x08, 0x00 };
const u8 EXPECTED_UNKNOWN_HEADER_1[] =
{ 0x57, 0x43, 0x1e, 0x00, 0x15, 0x02 };
const u8 EXPECTED_UNKNOWN_HEADER_2[] =
{ 0x57, 0x50, 0x0e, 0x00, 0x00, 0x00 };
u8 i = 0;
/* incomplete header? */
if (skb->len < KALMIA_HEADER_LENGTH)
return 0;
do {
struct sk_buff *skb2 = NULL;
u8 *header_start;
u16 usb_packet_length, ether_packet_length;
int is_last;
header_start = skb->data;
if (unlikely(header_start[0] != 0x57 || header_start[1] != 0x44)) {
if (!memcmp(header_start, EXPECTED_UNKNOWN_HEADER_1,
sizeof(EXPECTED_UNKNOWN_HEADER_1)) || !memcmp(
header_start, EXPECTED_UNKNOWN_HEADER_2,
sizeof(EXPECTED_UNKNOWN_HEADER_2))) {
netdev_dbg(
dev->net,
"Received expected unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n",
header_start[0], header_start[1],
header_start[2], header_start[3],
header_start[4], header_start[5],
skb->len - KALMIA_HEADER_LENGTH);
}
else {
netdev_err(
dev->net,
"Received unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n",
header_start[0], header_start[1],
header_start[2], header_start[3],
header_start[4], header_start[5],
skb->len - KALMIA_HEADER_LENGTH);
return 0;
}
}
else
netdev_dbg(
dev->net,
"Received header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n",
header_start[0], header_start[1], header_start[2],
header_start[3], header_start[4], header_start[5],
skb->len - KALMIA_HEADER_LENGTH);
/* subtract start header and end header */
usb_packet_length = skb->len - (2 * KALMIA_HEADER_LENGTH);
ether_packet_length = header_start[2] + (header_start[3] << 8);
skb_pull(skb, KALMIA_HEADER_LENGTH);
/* Some small packets misses end marker */
if (usb_packet_length < ether_packet_length) {
ether_packet_length = usb_packet_length
+ KALMIA_HEADER_LENGTH;
is_last = true;
}
else {
netdev_dbg(dev->net, "Correct package length #%i", i
+ 1);
is_last = (memcmp(skb->data + ether_packet_length,
HEADER_END_OF_USB_PACKET,
sizeof(HEADER_END_OF_USB_PACKET)) == 0);
if (!is_last) {
header_start = skb->data + ether_packet_length;
netdev_dbg(
dev->net,
"End header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n",
header_start[0], header_start[1],
header_start[2], header_start[3],
header_start[4], header_start[5],
skb->len - KALMIA_HEADER_LENGTH);
}
}
if (is_last) {
skb2 = skb;
}
else {
skb2 = skb_clone(skb, GFP_ATOMIC);
if (unlikely(!skb2))
return 0;
}
skb_trim(skb2, ether_packet_length);
if (is_last) {
return 1;
}
else {
usbnet_skb_return(dev, skb2);
skb_pull(skb, ether_packet_length);
}
i++;
}
while (skb->len);
return 1;
}
static const struct driver_info kalmia_info = {
.description = "Samsung Kalmia LTE USB dongle",
.flags = FLAG_WWAN,
.bind = kalmia_bind,
.rx_fixup = kalmia_rx_fixup,
.tx_fixup = kalmia_tx_fixup
};
/*-------------------------------------------------------------------------*/
static const struct usb_device_id products[] = {
/* The unswitched USB ID, to get the module auto loaded: */
{ USB_DEVICE(0x04e8, 0x689a) },
/* The stick swithed into modem (by e.g. usb_modeswitch): */
{ USB_DEVICE(0x04e8, 0x6889),
.driver_info = (unsigned long) &kalmia_info, },
{ /* EMPTY == end of list */} };
MODULE_DEVICE_TABLE( usb, products);
static struct usb_driver kalmia_driver = {
.name = "kalmia",
.id_table = products,
.probe = usbnet_probe,
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume
};
static int __init kalmia_init(void)
{
return usb_register(&kalmia_driver);
}
module_init( kalmia_init);
static void __exit kalmia_exit(void)
{
usb_deregister(&kalmia_driver);
}
module_exit( kalmia_exit);
MODULE_AUTHOR("Marius Bjoernstad Kotsbak <marius@kotsbak.com>");
MODULE_DESCRIPTION("Samsung Kalmia USB network driver");
MODULE_LICENSE("GPL");

View File

@ -2203,8 +2203,10 @@ fst_open(struct net_device *dev)
if (port->mode != FST_RAW) { if (port->mode != FST_RAW) {
err = hdlc_open(dev); err = hdlc_open(dev);
if (err) if (err) {
module_put(THIS_MODULE);
return err; return err;
}
} }
fst_openport(port); fst_openport(port);

View File

@ -1288,6 +1288,8 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac,
*(unsigned long *) wdev_priv = (unsigned long) priv; *(unsigned long *) wdev_priv = (unsigned long) priv;
set_wiphy_dev(wdev->wiphy, (struct device *) priv->adapter->dev);
ret = wiphy_register(wdev->wiphy); ret = wiphy_register(wdev->wiphy);
if (ret < 0) { if (ret < 0) {
dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n", dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n",

View File

@ -2474,6 +2474,7 @@ struct mwl8k_cmd_set_hw_spec {
* faster client. * faster client.
*/ */
#define MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY 0x00000400 #define MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY 0x00000400
#define MWL8K_SET_HW_SPEC_FLAG_GENERATE_CCMP_HDR 0x00000200
#define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080
#define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020 #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020
#define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010 #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010
@ -2510,7 +2511,8 @@ static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw)
cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT | cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT |
MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP | MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP |
MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON | MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON |
MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY); MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY |
MWL8K_SET_HW_SPEC_FLAG_GENERATE_CCMP_HDR);
cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS);
cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS);

View File

@ -307,6 +307,12 @@ static inline int nf_ct_is_untracked(const struct nf_conn *ct)
return test_bit(IPS_UNTRACKED_BIT, &ct->status); return test_bit(IPS_UNTRACKED_BIT, &ct->status);
} }
/* Packet is received from loopback */
static inline bool nf_is_loopback_packet(const struct sk_buff *skb)
{
return skb->dev && skb->skb_iif && skb->dev->flags & IFF_LOOPBACK;
}
extern int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp); extern int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp);
extern unsigned int nf_conntrack_htable_size; extern unsigned int nf_conntrack_htable_size;
extern unsigned int nf_conntrack_max; extern unsigned int nf_conntrack_max;

View File

@ -205,7 +205,7 @@ int register_vlan_dev(struct net_device *dev)
grp->nr_vlans++; grp->nr_vlans++;
if (ngrp) { if (ngrp) {
if (ops->ndo_vlan_rx_register) if (ops->ndo_vlan_rx_register && (real_dev->features & NETIF_F_HW_VLAN_RX))
ops->ndo_vlan_rx_register(real_dev, ngrp); ops->ndo_vlan_rx_register(real_dev, ngrp);
rcu_assign_pointer(real_dev->vlgrp, ngrp); rcu_assign_pointer(real_dev->vlgrp, ngrp);
} }

View File

@ -477,14 +477,16 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
* command otherwise */ * command otherwise */
u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
/* Events for 1.2 and newer controllers */ /* CSR 1.1 dongles does not accept any bitfield so don't try to set
if (hdev->lmp_ver > 1) { * any event mask for pre 1.2 devices */
events[4] |= 0x01; /* Flow Specification Complete */ if (hdev->lmp_ver <= 1)
events[4] |= 0x02; /* Inquiry Result with RSSI */ return;
events[4] |= 0x04; /* Read Remote Extended Features Complete */
events[5] |= 0x08; /* Synchronous Connection Complete */ events[4] |= 0x01; /* Flow Specification Complete */
events[5] |= 0x10; /* Synchronous Connection Changed */ events[4] |= 0x02; /* Inquiry Result with RSSI */
} events[4] |= 0x04; /* Read Remote Extended Features Complete */
events[5] |= 0x08; /* Synchronous Connection Complete */
events[5] |= 0x10; /* Synchronous Connection Changed */
if (hdev->features[3] & LMP_RSSI_INQ) if (hdev->features[3] & LMP_RSSI_INQ)
events[4] |= 0x04; /* Inquiry Result with RSSI */ events[4] |= 0x04; /* Inquiry Result with RSSI */

View File

@ -413,6 +413,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
break; break;
} }
memset(&cinfo, 0, sizeof(cinfo));
cinfo.hci_handle = chan->conn->hcon->handle; cinfo.hci_handle = chan->conn->hcon->handle;
memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3); memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);

View File

@ -788,6 +788,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk; l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk;
memset(&cinfo, 0, sizeof(cinfo));
cinfo.hci_handle = conn->hcon->handle; cinfo.hci_handle = conn->hcon->handle;
memcpy(cinfo.dev_class, conn->hcon->dev_class, 3); memcpy(cinfo.dev_class, conn->hcon->dev_class, 3);

View File

@ -369,6 +369,15 @@ static void __sco_sock_close(struct sock *sk)
case BT_CONNECTED: case BT_CONNECTED:
case BT_CONFIG: case BT_CONFIG:
if (sco_pi(sk)->conn) {
sk->sk_state = BT_DISCONN;
sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
hci_conn_put(sco_pi(sk)->conn->hcon);
sco_pi(sk)->conn->hcon = NULL;
} else
sco_chan_del(sk, ECONNRESET);
break;
case BT_CONNECT: case BT_CONNECT:
case BT_DISCONN: case BT_DISCONN:
sco_chan_del(sk, ECONNRESET); sco_chan_del(sk, ECONNRESET);
@ -819,7 +828,9 @@ static void sco_chan_del(struct sock *sk, int err)
conn->sk = NULL; conn->sk = NULL;
sco_pi(sk)->conn = NULL; sco_pi(sk)->conn = NULL;
sco_conn_unlock(conn); sco_conn_unlock(conn);
hci_conn_put(conn->hcon);
if (conn->hcon)
hci_conn_put(conn->hcon);
} }
sk->sk_state = BT_CLOSED; sk->sk_state = BT_CLOSED;

View File

@ -243,6 +243,7 @@ int br_netpoll_enable(struct net_bridge_port *p)
goto out; goto out;
np->dev = p->dev; np->dev = p->dev;
strlcpy(np->dev_name, p->dev->name, IFNAMSIZ);
err = __netpoll_setup(np); err = __netpoll_setup(np);
if (err) { if (err) {

View File

@ -1424,7 +1424,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
switch (ih->type) { switch (ih->type) {
case IGMP_HOST_MEMBERSHIP_REPORT: case IGMP_HOST_MEMBERSHIP_REPORT:
case IGMPV2_HOST_MEMBERSHIP_REPORT: case IGMPV2_HOST_MEMBERSHIP_REPORT:
BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
err = br_ip4_multicast_add_group(br, port, ih->group); err = br_ip4_multicast_add_group(br, port, ih->group);
break; break;
case IGMPV3_HOST_MEMBERSHIP_REPORT: case IGMPV3_HOST_MEMBERSHIP_REPORT:
@ -1543,7 +1543,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
goto out; goto out;
} }
mld = (struct mld_msg *)skb_transport_header(skb2); mld = (struct mld_msg *)skb_transport_header(skb2);
BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
err = br_ip6_multicast_add_group(br, port, &mld->mld_mca); err = br_ip6_multicast_add_group(br, port, &mld->mld_mca);
break; break;
} }

View File

@ -255,7 +255,7 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
if (cfsrvl_phyid_match(layer, phyid) && layer->ctrlcmd) { if (cfsrvl_phyid_match(layer, phyid) && layer->ctrlcmd) {
if ((ctrl == _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND || if ((ctrl == _CAIF_CTRLCMD_PHYIF_DOWN_IND ||
ctrl == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND) && ctrl == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND) &&
layer->id != 0) { layer->id != 0) {

View File

@ -44,7 +44,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid,
pr_debug("%s\n", __func__); pr_debug("%s\n", __func__);
if (!buf) if (!buf)
goto out; return -EMSGSIZE;
hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags, hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags,
IEEE802154_LIST_PHY); IEEE802154_LIST_PHY);
@ -65,6 +65,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid,
pages * sizeof(uint32_t), buf); pages * sizeof(uint32_t), buf);
mutex_unlock(&phy->pib_lock); mutex_unlock(&phy->pib_lock);
kfree(buf);
return genlmsg_end(msg, hdr); return genlmsg_end(msg, hdr);
nla_put_failure: nla_put_failure:

View File

@ -676,6 +676,7 @@ int inet_accept(struct socket *sock, struct socket *newsock, int flags)
lock_sock(sk2); lock_sock(sk2);
sock_rps_record_flow(sk2);
WARN_ON(!((1 << sk2->sk_state) & WARN_ON(!((1 << sk2->sk_state) &
(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE))); (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE)));

View File

@ -437,7 +437,7 @@ static int valid_cc(const void *bc, int len, int cc)
return 0; return 0;
if (cc == len) if (cc == len)
return 1; return 1;
if (op->yes < 4) if (op->yes < 4 || op->yes & 3)
return 0; return 0;
len -= op->yes; len -= op->yes;
bc += op->yes; bc += op->yes;
@ -447,11 +447,11 @@ static int valid_cc(const void *bc, int len, int cc)
static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
{ {
const unsigned char *bc = bytecode; const void *bc = bytecode;
int len = bytecode_len; int len = bytecode_len;
while (len > 0) { while (len > 0) {
struct inet_diag_bc_op *op = (struct inet_diag_bc_op *)bc; const struct inet_diag_bc_op *op = bc;
//printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len); //printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len);
switch (op->code) { switch (op->code) {
@ -462,22 +462,20 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
case INET_DIAG_BC_S_LE: case INET_DIAG_BC_S_LE:
case INET_DIAG_BC_D_GE: case INET_DIAG_BC_D_GE:
case INET_DIAG_BC_D_LE: case INET_DIAG_BC_D_LE:
if (op->yes < 4 || op->yes > len + 4)
return -EINVAL;
case INET_DIAG_BC_JMP: case INET_DIAG_BC_JMP:
if (op->no < 4 || op->no > len + 4) if (op->no < 4 || op->no > len + 4 || op->no & 3)
return -EINVAL; return -EINVAL;
if (op->no < len && if (op->no < len &&
!valid_cc(bytecode, bytecode_len, len - op->no)) !valid_cc(bytecode, bytecode_len, len - op->no))
return -EINVAL; return -EINVAL;
break; break;
case INET_DIAG_BC_NOP: case INET_DIAG_BC_NOP:
if (op->yes < 4 || op->yes > len + 4)
return -EINVAL;
break; break;
default: default:
return -EINVAL; return -EINVAL;
} }
if (op->yes < 4 || op->yes > len + 4 || op->yes & 3)
return -EINVAL;
bc += op->yes; bc += op->yes;
len -= op->yes; len -= op->yes;
} }

View File

@ -203,7 +203,8 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp)
else else
pmsg->outdev_name[0] = '\0'; pmsg->outdev_name[0] = '\0';
if (entry->indev && entry->skb->dev) { if (entry->indev && entry->skb->dev &&
entry->skb->mac_header != entry->skb->network_header) {
pmsg->hw_type = entry->skb->dev->type; pmsg->hw_type = entry->skb->dev->type;
pmsg->hw_addrlen = dev_parse_header(entry->skb, pmsg->hw_addrlen = dev_parse_header(entry->skb,
pmsg->hw_addr); pmsg->hw_addr);

View File

@ -566,7 +566,7 @@ check_entry(const struct ipt_entry *e, const char *name)
const struct xt_entry_target *t; const struct xt_entry_target *t;
if (!ip_checkentry(&e->ip)) { if (!ip_checkentry(&e->ip)) {
duprintf("ip check failed %p %s.\n", e, par->match->name); duprintf("ip check failed %p %s.\n", e, name);
return -EINVAL; return -EINVAL;
} }

View File

@ -25,7 +25,8 @@ MODULE_LICENSE("GPL");
static inline bool match_ip(const struct sk_buff *skb, static inline bool match_ip(const struct sk_buff *skb,
const struct ipt_ecn_info *einfo) const struct ipt_ecn_info *einfo)
{ {
return (ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect; return ((ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect) ^
!!(einfo->invert & IPT_ECN_OP_MATCH_IP);
} }
static inline bool match_tcp(const struct sk_buff *skb, static inline bool match_tcp(const struct sk_buff *skb,
@ -76,8 +77,6 @@ static bool ecn_mt(const struct sk_buff *skb, struct xt_action_param *par)
return false; return false;
if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) { if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) {
if (ip_hdr(skb)->protocol != IPPROTO_TCP)
return false;
if (!match_tcp(skb, info, &par->hotdrop)) if (!match_tcp(skb, info, &par->hotdrop))
return false; return false;
} }
@ -97,7 +96,7 @@ static int ecn_mt_check(const struct xt_mtchk_param *par)
return -EINVAL; return -EINVAL;
if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) && if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) &&
ip->proto != IPPROTO_TCP) { (ip->proto != IPPROTO_TCP || ip->invflags & IPT_INV_PROTO)) {
pr_info("cannot match TCP bits in rule for non-tcp packets\n"); pr_info("cannot match TCP bits in rule for non-tcp packets\n");
return -EINVAL; return -EINVAL;
} }

View File

@ -121,7 +121,9 @@ static unsigned int ipv4_confirm(unsigned int hooknum,
return ret; return ret;
} }
if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { /* adjust seqs for loopback traffic only in outgoing direction */
if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) &&
!nf_is_loopback_packet(skb)) {
typeof(nf_nat_seq_adjust_hook) seq_adjust; typeof(nf_nat_seq_adjust_hook) seq_adjust;
seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook); seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook);

View File

@ -41,7 +41,6 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/ping.h> #include <net/ping.h>
#include <net/icmp.h>
#include <net/udp.h> #include <net/udp.h>
#include <net/route.h> #include <net/route.h>
#include <net/inet_common.h> #include <net/inet_common.h>

View File

@ -1902,9 +1902,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev))); hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev)));
rth = rt_intern_hash(hash, rth, skb, dev->ifindex); rth = rt_intern_hash(hash, rth, skb, dev->ifindex);
err = 0; return IS_ERR(rth) ? PTR_ERR(rth) : 0;
if (IS_ERR(rth))
err = PTR_ERR(rth);
e_nobufs: e_nobufs:
return -ENOBUFS; return -ENOBUFS;

View File

@ -1589,6 +1589,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
goto discard; goto discard;
if (nsk != sk) { if (nsk != sk) {
sock_rps_save_rxhash(nsk, skb->rxhash);
if (tcp_child_process(sk, nsk, skb)) { if (tcp_child_process(sk, nsk, skb)) {
rsk = nsk; rsk = nsk;
goto reset; goto reset;

View File

@ -204,7 +204,8 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp)
else else
pmsg->outdev_name[0] = '\0'; pmsg->outdev_name[0] = '\0';
if (entry->indev && entry->skb->dev) { if (entry->indev && entry->skb->dev &&
entry->skb->mac_header != entry->skb->network_header) {
pmsg->hw_type = entry->skb->dev->type; pmsg->hw_type = entry->skb->dev->type;
pmsg->hw_addrlen = dev_parse_header(entry->skb, pmsg->hw_addr); pmsg->hw_addrlen = dev_parse_header(entry->skb, pmsg->hw_addr);
} }

View File

@ -1644,6 +1644,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
* the new socket.. * the new socket..
*/ */
if(nsk != sk) { if(nsk != sk) {
sock_rps_save_rxhash(nsk, skb->rxhash);
if (tcp_child_process(sk, nsk, skb)) if (tcp_child_process(sk, nsk, skb))
goto reset; goto reset;
if (opt_skb) if (opt_skb)

View File

@ -776,8 +776,16 @@ static void ip_vs_conn_expire(unsigned long data)
if (cp->control) if (cp->control)
ip_vs_control_del(cp); ip_vs_control_del(cp);
if (cp->flags & IP_VS_CONN_F_NFCT) if (cp->flags & IP_VS_CONN_F_NFCT) {
ip_vs_conn_drop_conntrack(cp); ip_vs_conn_drop_conntrack(cp);
/* Do not access conntracks during subsys cleanup
* because nf_conntrack_find_get can not be used after
* conntrack cleanup for the net.
*/
smp_rmb();
if (ipvs->enable)
ip_vs_conn_drop_conntrack(cp);
}
ip_vs_pe_put(cp->pe); ip_vs_pe_put(cp->pe);
kfree(cp->pe_data); kfree(cp->pe_data);

View File

@ -1945,6 +1945,7 @@ static void __net_exit __ip_vs_dev_cleanup(struct net *net)
{ {
EnterFunction(2); EnterFunction(2);
net_ipvs(net)->enable = 0; /* Disable packet reception */ net_ipvs(net)->enable = 0; /* Disable packet reception */
smp_wmb();
__ip_vs_sync_cleanup(net); __ip_vs_sync_cleanup(net);
LeaveFunction(2); LeaveFunction(2);
} }

View File

@ -456,7 +456,8 @@ __build_packet_message(struct nfulnl_instance *inst,
if (skb->mark) if (skb->mark)
NLA_PUT_BE32(inst->skb, NFULA_MARK, htonl(skb->mark)); NLA_PUT_BE32(inst->skb, NFULA_MARK, htonl(skb->mark));
if (indev && skb->dev) { if (indev && skb->dev &&
skb->mac_header != skb->network_header) {
struct nfulnl_msg_packet_hw phw; struct nfulnl_msg_packet_hw phw;
int len = dev_parse_header(skb, phw.hw_addr); int len = dev_parse_header(skb, phw.hw_addr);
if (len > 0) { if (len > 0) {

View File

@ -335,7 +335,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
if (entskb->mark) if (entskb->mark)
NLA_PUT_BE32(skb, NFQA_MARK, htonl(entskb->mark)); NLA_PUT_BE32(skb, NFQA_MARK, htonl(entskb->mark));
if (indev && entskb->dev) { if (indev && entskb->dev &&
entskb->mac_header != entskb->network_header) {
struct nfqnl_msg_packet_hw phw; struct nfqnl_msg_packet_hw phw;
int len = dev_parse_header(entskb, phw.hw_addr); int len = dev_parse_header(entskb, phw.hw_addr);
if (len) { if (len) {