Commit 90a5a895 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull networking fixes from David Miller:

 1) Validate iov ranges before feeding them into iov_iter_init(), from
    Al Viro.

 2) We changed copy_from_msghdr_from_user() to zero out the msg_namelen
    is a NULL pointer is given for the msg_name.  Do the same in the
    compat code too.  From Catalin Marinas.

 3) Fix partially initialized tuples in netfilter conntrack helper, from
    Ian Wilson.

 4) Missing continue; statement in nft_hash walker can lead to crashes,
    from Herbert Xu.

 5) tproxy_tg6_check looks for IP6T_INV_PROTO in ->flags instead of
    ->invflags, fix from Pablo Neira Ayuso.

 6) Incorrect memory account of TCP FINs can result in negative socket
    memory accounting values.  Fix from Josh Hunt.

 7) Don't allow virtual functions to enable VLAN promiscuous mode in
    be2net driver, from Vasundhara Volam.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
  netfilter: nft_compat: set IP6T_F_PROTO flag if protocol is set
  cx82310_eth: wait for firmware to become ready
  net: validate the range we feed to iov_iter_init() in sys_sendto/sys_recvfrom
  net: compat: Update get_compat_msghdr() to match copy_msghdr_from_user() behaviour
  be2net: use PCI MMIO read instead of config read for errors
  be2net: restrict MODIFY_EQ_DELAY cmd to a max of 8 EQs
  be2net: Prevent VFs from enabling VLAN promiscuous mode
  tcp: fix tcp fin memory accounting
  ipv6: fix backtracking for throw routes
  net: ethernet: pcnet32: Setup the SRAM and NOUFLO on Am79C97{3, 5}
  ipv6: call ipv6_proxy_select_ident instead of ipv6_select_ident in udp6_ufo_fragment
  netfilter: xt_TPROXY: fix invflags check in tproxy_tg6_check()
  netfilter: restore rule tracing via nfnetlink_log
  netfilter: nf_tables: allow to change chain policy without hook if it exists
  netfilter: Fix potential crash in nft_hash walker
  netfilter: Zero the tuple in nfnl_cthelper_parse_tuple()
parents d5049617 c0e41fa7
...@@ -1543,7 +1543,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) ...@@ -1543,7 +1543,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
{ {
struct pcnet32_private *lp; struct pcnet32_private *lp;
int i, media; int i, media;
int fdx, mii, fset, dxsuflo; int fdx, mii, fset, dxsuflo, sram;
int chip_version; int chip_version;
char *chipname; char *chipname;
struct net_device *dev; struct net_device *dev;
...@@ -1580,7 +1580,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) ...@@ -1580,7 +1580,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
} }
/* initialize variables */ /* initialize variables */
fdx = mii = fset = dxsuflo = 0; fdx = mii = fset = dxsuflo = sram = 0;
chip_version = (chip_version >> 12) & 0xffff; chip_version = (chip_version >> 12) & 0xffff;
switch (chip_version) { switch (chip_version) {
...@@ -1613,6 +1613,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) ...@@ -1613,6 +1613,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
chipname = "PCnet/FAST III 79C973"; /* PCI */ chipname = "PCnet/FAST III 79C973"; /* PCI */
fdx = 1; fdx = 1;
mii = 1; mii = 1;
sram = 1;
break; break;
case 0x2626: case 0x2626:
chipname = "PCnet/Home 79C978"; /* PCI */ chipname = "PCnet/Home 79C978"; /* PCI */
...@@ -1636,6 +1637,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) ...@@ -1636,6 +1637,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
chipname = "PCnet/FAST III 79C975"; /* PCI */ chipname = "PCnet/FAST III 79C975"; /* PCI */
fdx = 1; fdx = 1;
mii = 1; mii = 1;
sram = 1;
break; break;
case 0x2628: case 0x2628:
chipname = "PCnet/PRO 79C976"; chipname = "PCnet/PRO 79C976";
...@@ -1664,6 +1666,31 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) ...@@ -1664,6 +1666,31 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
dxsuflo = 1; dxsuflo = 1;
} }
/*
* The Am79C973/Am79C975 controllers come with 12K of SRAM
* which we can use for the Tx/Rx buffers but most importantly,
* the use of SRAM allow us to use the BCR18:NOUFLO bit to avoid
* Tx fifo underflows.
*/
if (sram) {
/*
* The SRAM is being configured in two steps. First we
* set the SRAM size in the BCR25:SRAM_SIZE bits. According
* to the datasheet, each bit corresponds to a 512-byte
* page so we can have at most 24 pages. The SRAM_SIZE
* holds the value of the upper 8 bits of the 16-bit SRAM size.
* The low 8-bits start at 0x00 and end at 0xff. So the
* address range is from 0x0000 up to 0x17ff. Therefore,
* the SRAM_SIZE is set to 0x17. The next step is to set
* the BCR26:SRAM_BND midway through so the Tx and Rx
* buffers can share the SRAM equally.
*/
a->write_bcr(ioaddr, 25, 0x17);
a->write_bcr(ioaddr, 26, 0xc);
/* And finally enable the NOUFLO bit */
a->write_bcr(ioaddr, 18, a->read_bcr(ioaddr, 18) | (1 << 11));
}
dev = alloc_etherdev(sizeof(*lp)); dev = alloc_etherdev(sizeof(*lp));
if (!dev) { if (!dev) {
ret = -ENOMEM; ret = -ENOMEM;
......
...@@ -354,6 +354,7 @@ struct be_vf_cfg { ...@@ -354,6 +354,7 @@ struct be_vf_cfg {
u16 vlan_tag; u16 vlan_tag;
u32 tx_rate; u32 tx_rate;
u32 plink_tracking; u32 plink_tracking;
u32 privileges;
}; };
enum vf_state { enum vf_state {
...@@ -423,6 +424,7 @@ struct be_adapter { ...@@ -423,6 +424,7 @@ struct be_adapter {
u8 __iomem *csr; /* CSR BAR used only for BE2/3 */ u8 __iomem *csr; /* CSR BAR used only for BE2/3 */
u8 __iomem *db; /* Door Bell */ u8 __iomem *db; /* Door Bell */
u8 __iomem *pcicfg; /* On SH,BEx only. Shadow of PCI config space */
struct mutex mbox_lock; /* For serializing mbox cmds to BE card */ struct mutex mbox_lock; /* For serializing mbox cmds to BE card */
struct be_dma_mem mbox_mem; struct be_dma_mem mbox_mem;
......
...@@ -1902,23 +1902,19 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd, ...@@ -1902,23 +1902,19 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *set_eqd,
{ {
int num_eqs, i = 0; int num_eqs, i = 0;
if (lancer_chip(adapter) && num > 8) {
while (num) { while (num) {
num_eqs = min(num, 8); num_eqs = min(num, 8);
__be_cmd_modify_eqd(adapter, &set_eqd[i], num_eqs); __be_cmd_modify_eqd(adapter, &set_eqd[i], num_eqs);
i += num_eqs; i += num_eqs;
num -= num_eqs; num -= num_eqs;
} }
} else {
__be_cmd_modify_eqd(adapter, set_eqd, num);
}
return 0; return 0;
} }
/* Uses sycnhronous mcc */ /* Uses sycnhronous mcc */
int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
u32 num) u32 num, u32 domain)
{ {
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
struct be_cmd_req_vlan_config *req; struct be_cmd_req_vlan_config *req;
...@@ -1936,6 +1932,7 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, ...@@ -1936,6 +1932,7 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req), OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req),
wrb, NULL); wrb, NULL);
req->hdr.domain = domain;
req->interface_id = if_id; req->interface_id = if_id;
req->untagged = BE_IF_FLAGS_UNTAGGED & be_if_cap_flags(adapter) ? 1 : 0; req->untagged = BE_IF_FLAGS_UNTAGGED & be_if_cap_flags(adapter) ? 1 : 0;
......
...@@ -2256,7 +2256,7 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter, ...@@ -2256,7 +2256,7 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
int be_cmd_get_fw_ver(struct be_adapter *adapter); int be_cmd_get_fw_ver(struct be_adapter *adapter);
int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *, int num); int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *, int num);
int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
u32 num); u32 num, u32 domain);
int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 status); int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 status);
int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc); int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc);
int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc); int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc);
......
...@@ -1171,7 +1171,7 @@ static int be_vid_config(struct be_adapter *adapter) ...@@ -1171,7 +1171,7 @@ static int be_vid_config(struct be_adapter *adapter)
for_each_set_bit(i, adapter->vids, VLAN_N_VID) for_each_set_bit(i, adapter->vids, VLAN_N_VID)
vids[num++] = cpu_to_le16(i); vids[num++] = cpu_to_le16(i);
status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num); status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num, 0);
if (status) { if (status) {
dev_err(dev, "Setting HW VLAN filtering failed\n"); dev_err(dev, "Setting HW VLAN filtering failed\n");
/* Set to VLAN promisc mode as setting VLAN filter failed */ /* Set to VLAN promisc mode as setting VLAN filter failed */
...@@ -1380,11 +1380,67 @@ static int be_get_vf_config(struct net_device *netdev, int vf, ...@@ -1380,11 +1380,67 @@ static int be_get_vf_config(struct net_device *netdev, int vf,
return 0; return 0;
} }
static int be_set_vf_tvt(struct be_adapter *adapter, int vf, u16 vlan)
{
struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
u16 vids[BE_NUM_VLANS_SUPPORTED];
int vf_if_id = vf_cfg->if_handle;
int status;
/* Enable Transparent VLAN Tagging */
status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, vf_if_id, 0);
if (status)
return status;
/* Clear pre-programmed VLAN filters on VF if any, if TVT is enabled */
vids[0] = 0;
status = be_cmd_vlan_config(adapter, vf_if_id, vids, 1, vf + 1);
if (!status)
dev_info(&adapter->pdev->dev,
"Cleared guest VLANs on VF%d", vf);
/* After TVT is enabled, disallow VFs to program VLAN filters */
if (vf_cfg->privileges & BE_PRIV_FILTMGMT) {
status = be_cmd_set_fn_privileges(adapter, vf_cfg->privileges &
~BE_PRIV_FILTMGMT, vf + 1);
if (!status)
vf_cfg->privileges &= ~BE_PRIV_FILTMGMT;
}
return 0;
}
static int be_clear_vf_tvt(struct be_adapter *adapter, int vf)
{
struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
struct device *dev = &adapter->pdev->dev;
int status;
/* Reset Transparent VLAN Tagging. */
status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID, vf + 1,
vf_cfg->if_handle, 0);
if (status)
return status;
/* Allow VFs to program VLAN filtering */
if (!(vf_cfg->privileges & BE_PRIV_FILTMGMT)) {
status = be_cmd_set_fn_privileges(adapter, vf_cfg->privileges |
BE_PRIV_FILTMGMT, vf + 1);
if (!status) {
vf_cfg->privileges |= BE_PRIV_FILTMGMT;
dev_info(dev, "VF%d: FILTMGMT priv enabled", vf);
}
}
dev_info(dev,
"Disable/re-enable i/f in VM to clear Transparent VLAN tag");
return 0;
}
static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
{ {
struct be_adapter *adapter = netdev_priv(netdev); struct be_adapter *adapter = netdev_priv(netdev);
struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
int status = 0; int status;
if (!sriov_enabled(adapter)) if (!sriov_enabled(adapter))
return -EPERM; return -EPERM;
...@@ -1394,24 +1450,19 @@ static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) ...@@ -1394,24 +1450,19 @@ static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
if (vlan || qos) { if (vlan || qos) {
vlan |= qos << VLAN_PRIO_SHIFT; vlan |= qos << VLAN_PRIO_SHIFT;
if (vf_cfg->vlan_tag != vlan) status = be_set_vf_tvt(adapter, vf, vlan);
status = be_cmd_set_hsw_config(adapter, vlan, vf + 1,
vf_cfg->if_handle, 0);
} else { } else {
/* Reset Transparent Vlan Tagging. */ status = be_clear_vf_tvt(adapter, vf);
status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID,
vf + 1, vf_cfg->if_handle, 0);
} }
if (status) { if (status) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"VLAN %d config on VF %d failed : %#x\n", vlan, "VLAN %d config on VF %d failed : %#x\n", vlan, vf,
vf, status); status);
return be_cmd_status(status); return be_cmd_status(status);
} }
vf_cfg->vlan_tag = vlan; vf_cfg->vlan_tag = vlan;
return 0; return 0;
} }
...@@ -2772,14 +2823,12 @@ void be_detect_error(struct be_adapter *adapter) ...@@ -2772,14 +2823,12 @@ void be_detect_error(struct be_adapter *adapter)
} }
} }
} else { } else {
pci_read_config_dword(adapter->pdev, ue_lo = ioread32(adapter->pcicfg + PCICFG_UE_STATUS_LOW);
PCICFG_UE_STATUS_LOW, &ue_lo); ue_hi = ioread32(adapter->pcicfg + PCICFG_UE_STATUS_HIGH);
pci_read_config_dword(adapter->pdev, ue_lo_mask = ioread32(adapter->pcicfg +
PCICFG_UE_STATUS_HIGH, &ue_hi); PCICFG_UE_STATUS_LOW_MASK);
pci_read_config_dword(adapter->pdev, ue_hi_mask = ioread32(adapter->pcicfg +
PCICFG_UE_STATUS_LOW_MASK, &ue_lo_mask); PCICFG_UE_STATUS_HI_MASK);
pci_read_config_dword(adapter->pdev,
PCICFG_UE_STATUS_HI_MASK, &ue_hi_mask);
ue_lo = (ue_lo & ~ue_lo_mask); ue_lo = (ue_lo & ~ue_lo_mask);
ue_hi = (ue_hi & ~ue_hi_mask); ue_hi = (ue_hi & ~ue_hi_mask);
...@@ -3339,7 +3388,6 @@ static int be_if_create(struct be_adapter *adapter, u32 *if_handle, ...@@ -3339,7 +3388,6 @@ static int be_if_create(struct be_adapter *adapter, u32 *if_handle,
u32 cap_flags, u32 vf) u32 cap_flags, u32 vf)
{ {
u32 en_flags; u32 en_flags;
int status;
en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS | BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS |
...@@ -3347,10 +3395,7 @@ static int be_if_create(struct be_adapter *adapter, u32 *if_handle, ...@@ -3347,10 +3395,7 @@ static int be_if_create(struct be_adapter *adapter, u32 *if_handle,
en_flags &= cap_flags; en_flags &= cap_flags;
status = be_cmd_if_create(adapter, cap_flags, en_flags, return be_cmd_if_create(adapter, cap_flags, en_flags, if_handle, vf);
if_handle, vf);
return status;
} }
static int be_vfs_if_create(struct be_adapter *adapter) static int be_vfs_if_create(struct be_adapter *adapter)
...@@ -3368,8 +3413,13 @@ static int be_vfs_if_create(struct be_adapter *adapter) ...@@ -3368,8 +3413,13 @@ static int be_vfs_if_create(struct be_adapter *adapter)
if (!BE3_chip(adapter)) { if (!BE3_chip(adapter)) {
status = be_cmd_get_profile_config(adapter, &res, status = be_cmd_get_profile_config(adapter, &res,
vf + 1); vf + 1);
if (!status) if (!status) {
cap_flags = res.if_cap_flags; cap_flags = res.if_cap_flags;
/* Prevent VFs from enabling VLAN promiscuous
* mode
*/
cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS;
}
} }
status = be_if_create(adapter, &vf_cfg->if_handle, status = be_if_create(adapter, &vf_cfg->if_handle,
...@@ -3403,7 +3453,6 @@ static int be_vf_setup(struct be_adapter *adapter) ...@@ -3403,7 +3453,6 @@ static int be_vf_setup(struct be_adapter *adapter)
struct device *dev = &adapter->pdev->dev; struct device *dev = &adapter->pdev->dev;
struct be_vf_cfg *vf_cfg; struct be_vf_cfg *vf_cfg;
int status, old_vfs, vf; int status, old_vfs, vf;
u32 privileges;
old_vfs = pci_num_vf(adapter->pdev); old_vfs = pci_num_vf(adapter->pdev);
...@@ -3433,16 +3482,19 @@ static int be_vf_setup(struct be_adapter *adapter) ...@@ -3433,16 +3482,19 @@ static int be_vf_setup(struct be_adapter *adapter)
for_all_vfs(adapter, vf_cfg, vf) { for_all_vfs(adapter, vf_cfg, vf) {
/* Allow VFs to programs MAC/VLAN filters */ /* Allow VFs to programs MAC/VLAN filters */
status = be_cmd_get_fn_privileges(adapter, &privileges, vf + 1); status = be_cmd_get_fn_privileges(adapter, &vf_cfg->privileges,
if (!status && !(privileges & BE_PRIV_FILTMGMT)) { vf + 1);
if (!status && !(vf_cfg->privileges & BE_PRIV_FILTMGMT)) {
status = be_cmd_set_fn_privileges(adapter, status = be_cmd_set_fn_privileges(adapter,
privileges | vf_cfg->privileges |
BE_PRIV_FILTMGMT, BE_PRIV_FILTMGMT,
vf + 1); vf + 1);
if (!status) if (!status) {
vf_cfg->privileges |= BE_PRIV_FILTMGMT;
dev_info(dev, "VF%d has FILTMGMT privilege\n", dev_info(dev, "VF%d has FILTMGMT privilege\n",
vf); vf);
} }
}
/* Allow full available bandwidth */ /* Allow full available bandwidth */
if (!old_vfs) if (!old_vfs)
...@@ -4820,24 +4872,37 @@ static int be_roce_map_pci_bars(struct be_adapter *adapter) ...@@ -4820,24 +4872,37 @@ static int be_roce_map_pci_bars(struct be_adapter *adapter)
static int be_map_pci_bars(struct be_adapter *adapter) static int be_map_pci_bars(struct be_adapter *adapter)
{ {
struct pci_dev *pdev = adapter->pdev;
u8 __iomem *addr; u8 __iomem *addr;
if (BEx_chip(adapter) && be_physfn(adapter)) { if (BEx_chip(adapter) && be_physfn(adapter)) {
adapter->csr = pci_iomap(adapter->pdev, 2, 0); adapter->csr = pci_iomap(pdev, 2, 0);
if (!adapter->csr) if (!adapter->csr)
return -ENOMEM; return -ENOMEM;
} }
addr = pci_iomap(adapter->pdev, db_bar(adapter), 0); addr = pci_iomap(pdev, db_bar(adapter), 0);
if (!addr) if (!addr)
goto pci_map_err; goto pci_map_err;
adapter->db = addr; adapter->db = addr;
if (skyhawk_chip(adapter) || BEx_chip(adapter)) {
if (be_physfn(adapter)) {
/* PCICFG is the 2nd BAR in BE2 */
addr = pci_iomap(pdev, BE2_chip(adapter) ? 1 : 0, 0);
if (!addr)
goto pci_map_err;
adapter->pcicfg = addr;
} else {
adapter->pcicfg = adapter->db + SRIOV_VF_PCICFG_OFFSET;
}
}
be_roce_map_pci_bars(adapter); be_roce_map_pci_bars(adapter);
return 0; return 0;
pci_map_err: pci_map_err:
dev_err(&adapter->pdev->dev, "Error in mapping PCI BARs\n"); dev_err(&pdev->dev, "Error in mapping PCI BARs\n");
be_unmap_pci_bars(adapter); be_unmap_pci_bars(adapter);
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -46,8 +46,7 @@ enum cx82310_status { ...@@ -46,8 +46,7 @@ enum cx82310_status {
}; };
#define CMD_PACKET_SIZE 64 #define CMD_PACKET_SIZE 64
/* first command after power on can take around 8 seconds */ #define CMD_TIMEOUT 100
#define CMD_TIMEOUT 15000
#define CMD_REPLY_RETRY 5 #define CMD_REPLY_RETRY 5
#define CX82310_MTU 1514 #define CX82310_MTU 1514
...@@ -78,6 +77,7 @@ static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply, ...@@ -78,6 +77,7 @@ static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply,
ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, CMD_EP), buf, ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, CMD_EP), buf,
CMD_PACKET_SIZE, &actual_len, CMD_TIMEOUT); CMD_PACKET_SIZE, &actual_len, CMD_TIMEOUT);
if (ret < 0) { if (ret < 0) {
if (cmd != CMD_GET_LINK_STATUS)
dev_err(&dev->udev->dev, "send command %#x: error %d\n", dev_err(&dev->udev->dev, "send command %#x: error %d\n",
cmd, ret); cmd, ret);
goto end; goto end;
...@@ -90,8 +90,10 @@ static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply, ...@@ -90,8 +90,10 @@ static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply,
buf, CMD_PACKET_SIZE, &actual_len, buf, CMD_PACKET_SIZE, &actual_len,
CMD_TIMEOUT); CMD_TIMEOUT);
if (ret < 0) { if (ret < 0) {
if (cmd != CMD_GET_LINK_STATUS)
dev_err(&dev->udev->dev, dev_err(&dev->udev->dev,
"reply receive error %d\n", ret); "reply receive error %d\n",
ret);
goto end; goto end;
} }
if (actual_len > 0) if (actual_len > 0)
...@@ -134,6 +136,8 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf) ...@@ -134,6 +136,8 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
int ret; int ret;
char buf[15]; char buf[15];
struct usb_device *udev = dev->udev; struct usb_device *udev = dev->udev;
u8 link[3];
int timeout = 50;
/* avoid ADSL modems - continue only if iProduct is "USB NET CARD" */ /* avoid ADSL modems - continue only if iProduct is "USB NET CARD" */
if (usb_string(udev, udev->descriptor.iProduct, buf, sizeof(buf)) > 0 if (usb_string(udev, udev->descriptor.iProduct, buf, sizeof(buf)) > 0
...@@ -160,6 +164,20 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf) ...@@ -160,6 +164,20 @@ static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
if (!dev->partial_data) if (!dev->partial_data)
return -ENOMEM; return -ENOMEM;
/* wait for firmware to become ready (indicated by the link being up) */
while (--timeout) {
ret = cx82310_cmd(dev, CMD_GET_LINK_STATUS, true, NULL, 0,
link, sizeof(link));
/* the command can time out during boot - it's not an error */
if (!ret && link[0] == 1 && link[2] == 1)
break;
msleep(500);
};
if (!timeout) {
dev_err(&udev->dev, "firmware not ready in time\n");
return -ETIMEDOUT;
}
/* enable ethernet mode (?) */ /* enable ethernet mode (?) */
ret = cx82310_cmd(dev, CMD_ETHERNET_MODE, true, "\x01", 1, NULL, 0); ret = cx82310_cmd(dev, CMD_ETHERNET_MODE, true, "\x01", 1, NULL, 0);
if (ret) { if (ret) {
......
...@@ -79,6 +79,16 @@ void nf_log_packet(struct net *net, ...@@ -79,6 +79,16 @@ void nf_log_packet(struct net *net,
const struct nf_loginfo *li, const struct nf_loginfo *li,
const char *fmt, ...); const char *fmt, ...);
__printf(8, 9)
void nf_log_trace(struct net *net,
u_int8_t pf,
unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const struct nf_loginfo *li,
const char *fmt, ...);
struct nf_log_buf; struct nf_log_buf;
struct nf_log_buf *nf_log_buf_open(void); struct nf_log_buf *nf_log_buf_open(void);
......
...@@ -49,6 +49,13 @@ ssize_t get_compat_msghdr(struct msghdr *kmsg, ...@@ -49,6 +49,13 @@ ssize_t get_compat_msghdr(struct msghdr *kmsg,
__get_user(kmsg->msg_controllen, &umsg->msg_controllen) || __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
__get_user(kmsg->msg_flags, &umsg->msg_flags)) __get_user(kmsg->msg_flags, &umsg->msg_flags))
return -EFAULT; return -EFAULT;
if (!uaddr)
kmsg->msg_namelen = 0;
if (kmsg->msg_namelen < 0)
return -EINVAL;
if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
kmsg->msg_namelen = sizeof(struct sockaddr_storage); kmsg->msg_namelen = sizeof(struct sockaddr_storage);
kmsg->msg_control = compat_ptr(tmp3); kmsg->msg_control = compat_ptr(tmp3);
......
...@@ -272,7 +272,7 @@ static void trace_packet(const struct sk_buff *skb, ...@@ -272,7 +272,7 @@ static void trace_packet(const struct sk_buff *skb,
&chainname, &comment, &rulenum) != 0) &chainname, &comment, &rulenum) != 0)
break; break;
nf_log_packet(net, AF_INET, hook, skb, in, out, &trace_loginfo, nf_log_trace(net, AF_INET, hook, skb, in, out, &trace_loginfo,
"TRACE: %s:%s:%s:%u ", "TRACE: %s:%s:%s:%u ",
tablename, chainname, comment, rulenum); tablename, chainname, comment, rulenum);
} }
......
...@@ -2773,15 +2773,11 @@ void tcp_send_fin(struct sock *sk) ...@@ -2773,15 +2773,11 @@ void tcp_send_fin(struct sock *sk)
} else { } else {
/* Socket is locked, keep trying until memory is available. */ /* Socket is locked, keep trying until memory is available. */
for (;;) { for (;;) {
skb = alloc_skb_fclone(MAX_TCP_HEADER, skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation);
sk->sk_allocation);
if (skb) if (skb)
break; break;
yield(); yield();
} }
/* Reserve space for headers and prepare control bits. */
skb_reserve(skb, MAX_TCP_HEADER);
/* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */ /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
tcp_init_nondata_skb(skb, tp->write_seq, tcp_init_nondata_skb(skb, tp->write_seq,
TCPHDR_ACK | TCPHDR_FIN); TCPHDR_ACK | TCPHDR_FIN);
......
...@@ -104,6 +104,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, ...@@ -104,6 +104,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
goto again; goto again;
flp6->saddr = saddr; flp6->saddr = saddr;
} }
err = rt->dst.error;
goto out; goto out;
} }
again: again:
......
...@@ -298,7 +298,7 @@ static void trace_packet(const struct sk_buff *skb, ...@@ -298,7 +298,7 @@ static void trace_packet(const struct sk_buff *skb,
&chainname, &comment, &rulenum) != 0) &chainname, &comment, &rulenum) != 0)
break; break;
nf_log_packet(net, AF_INET6, hook, skb, in, out, &trace_loginfo, nf_log_trace(net, AF_INET6, hook, skb, in, out, &trace_loginfo,
"TRACE: %s:%s:%s:%u ", "TRACE: %s:%s:%s:%u ",
tablename, chainname, comment, rulenum); tablename, chainname, comment, rulenum);
} }
......
...@@ -112,11 +112,9 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, ...@@ -112,11 +112,9 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
fptr->nexthdr = nexthdr; fptr->nexthdr = nexthdr;
fptr->reserved = 0; fptr->reserved = 0;
if (skb_shinfo(skb)->ip6_frag_id) if (!skb_shinfo(skb)->ip6_frag_id)
ipv6_proxy_select_ident(skb);
fptr->identification = skb_shinfo(skb)->ip6_frag_id; fptr->identification = skb_shinfo(skb)->ip6_frag_id;
else
ipv6_select_ident(fptr,
(struct rt6_info *)skb_dst(skb));
/* Fragment the skb. ipv6 header and the remaining fields of the /* Fragment the skb. ipv6 header and the remaining fields of the
* fragment header are updated in ipv6_gso_segment() * fragment header are updated in ipv6_gso_segment()
......
...@@ -212,6 +212,30 @@ void nf_log_packet(struct net *net, ...@@ -212,6 +212,30 @@ void nf_log_packet(struct net *net,
} }
EXPORT_SYMBOL(nf_log_packet); EXPORT_SYMBOL(nf_log_packet);
void nf_log_trace(struct net *net,
u_int8_t pf,
unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const struct nf_loginfo *loginfo, const char *fmt, ...)
{
va_list args;
char prefix[NF_LOG_PREFIXLEN];
const struct nf_logger *logger;
rcu_read_lock();
logger = rcu_dereference(net->nf.nf_loggers[pf]);
if (logger) {
va_start(args, fmt);
vsnprintf(prefix, sizeof(prefix), fmt, args);
va_end(args);
logger->logfn(net, pf, hooknum, skb, in, out, loginfo, prefix);
}
rcu_read_unlock();
}
EXPORT_SYMBOL(nf_log_trace);
#define S_SIZE (1024 - (sizeof(unsigned int) + 1)) #define S_SIZE (1024 - (sizeof(unsigned int) + 1))
struct nf_log_buf { struct nf_log_buf {
......
...@@ -1225,7 +1225,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, ...@@ -1225,7 +1225,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
if (nla[NFTA_CHAIN_POLICY]) { if (nla[NFTA_CHAIN_POLICY]) {
if ((chain != NULL && if ((chain != NULL &&
!(chain->flags & NFT_BASE_CHAIN)) || !(chain->flags & NFT_BASE_CHAIN)))
return -EOPNOTSUPP;
if (chain == NULL &&
nla[NFTA_CHAIN_HOOK] == NULL) nla[NFTA_CHAIN_HOOK] == NULL)
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
...@@ -94,7 +94,7 @@ static void nft_trace_packet(const struct nft_pktinfo *pkt, ...@@ -94,7 +94,7 @@ static void nft_trace_packet(const struct nft_pktinfo *pkt,
{ {
struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
nf_log_packet(net, pkt->xt.family, pkt->ops->hooknum, pkt->skb, pkt->in, nf_log_trace(net, pkt->xt.family, pkt->ops->hooknum, pkt->skb, pkt->in,
pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ", pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ",
chain->table->name, chain->name, comments[type], chain->table->name, chain->name, comments[type],
rulenum); rulenum);
......
...@@ -77,6 +77,9 @@ nfnl_cthelper_parse_tuple(struct nf_conntrack_tuple *tuple, ...@@ -77,6 +77,9 @@ nfnl_cthelper_parse_tuple(struct nf_conntrack_tuple *tuple,
if (!tb[NFCTH_TUPLE_L3PROTONUM] || !tb[NFCTH_TUPLE_L4PROTONUM]) if (!tb[NFCTH_TUPLE_L3PROTONUM] || !tb[NFCTH_TUPLE_L4PROTONUM])
return -EINVAL; return -EINVAL;
/* Not all fields are initialized so first zero the tuple */
memset(tuple, 0, sizeof(struct nf_conntrack_tuple));
tuple->src.l3num = ntohs(nla_get_be16(tb[NFCTH_TUPLE_L3PROTONUM])); tuple->src.l3num = ntohs(nla_get_be16(tb[NFCTH_TUPLE_L3PROTONUM]));
tuple->dst.protonum = nla_get_u8(tb[NFCTH_TUPLE_L4PROTONUM]); tuple->dst.protonum = nla_get_u8(tb[NFCTH_TUPLE_L4PROTONUM]);
......
...@@ -133,6 +133,9 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par, ...@@ -133,6 +133,9 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0; entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0;
break; break;
case AF_INET6: case AF_INET6:
if (proto)
entry->e6.ipv6.flags |= IP6T_F_PROTO;
entry->e6.ipv6.proto = proto; entry->e6.ipv6.proto = proto;
entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0;
break; break;
...@@ -344,6 +347,9 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx, ...@@ -344,6 +347,9 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0; entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0;
break; break;
case AF_INET6: case AF_INET6:
if (proto)
entry->e6.ipv6.flags |= IP6T_F_PROTO;
entry->e6.ipv6.proto = proto; entry->e6.ipv6.proto = proto;
entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0;
break; break;
......
...@@ -153,6 +153,8 @@ static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set, ...@@ -153,6 +153,8 @@ static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set,
iter->err = err; iter->err = err;
goto out; goto out;
} }
continue;
} }
if (iter->count < iter->skip) if (iter->count < iter->skip)
......
...@@ -513,8 +513,8 @@ static int tproxy_tg6_check(const struct xt_tgchk_param *par) ...@@ -513,8 +513,8 @@ static int tproxy_tg6_check(const struct xt_tgchk_param *par)
{ {
const struct ip6t_ip6 *i = par->entryinfo; const struct ip6t_ip6 *i = par->entryinfo;
if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) &&
&& !(i->flags & IP6T_INV_PROTO)) !(i->invflags & IP6T_INV_PROTO))
return 0; return 0;
pr_info("Can be used only in combination with " pr_info("Can be used only in combination with "
......
...@@ -1702,6 +1702,8 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, ...@@ -1702,6 +1702,8 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
if (len > INT_MAX) if (len > INT_MAX)
len = INT_MAX; len = INT_MAX;
if (unlikely(!access_ok(VERIFY_READ, buff, len)))
return -EFAULT;
sock = sockfd_lookup_light(fd, &err, &fput_needed); sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock) if (!sock)
goto out; goto out;
...@@ -1760,6 +1762,8 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, ...@@ -1760,6 +1762,8 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
if (size > INT_MAX) if (size > INT_MAX)
size = INT_MAX; size = INT_MAX;
if (unlikely(!access_ok(VERIFY_WRITE, ubuf, size)))
return -EFAULT;
sock = sockfd_lookup_light(fd, &err, &fput_needed); sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock) if (!sock)
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment