Commit fca83168 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) Fix erroneous netfilter drop of SIP packets generated by some Cisco
    phones, from Patrick McHardy.

 2) Fix netfilter IPSET refcounting in list_set_add(), from Jozsef
    Kadlecsik.

 3) Fix TCP syncookies route lookup key, we don't use the same values we
    would use for the usual SYN receive processing, from Dmitry Popov.

 4) Fix NULL deref in bond_slave_netdev_event(), from Nikolay
    Aleksandrov.

 5) When bonding enslave fails, we can forget to clear the IFF_BONDING
    bit, fix also from Nikolay Aleksandrov.

 6) skb->csum_start is 16-bits, which is almost always just fine.  But
    if we reallocate the headroom of an SKB this can push the
    skb->csum_start value outside of it's valid range.  This can easily
    happen when collapsing multiple SKBs from the retransmit queue
    together.

    Fix from Thomas Graf.

 7) Fix NULL deref in be2net driver due to missing check of
    __vlan_put_tag() return value, from Ivan Vecera.

 8) tun_set_iff() returns zero instead of error code on failure, fix
    from Wei Yongjun.

 9) Like GARP, 802 MRP needs to hold the app->lock when adding MAD
    events and queueing PDUs.  Fix from David Ward.

10) Build fix, MVMDIO needs PHYLIB, from Thomas Petazzoni..

11) Fix mac80211 static with ipv6 modular build, from Cong Wang.

12) If userland specifies a path cost explicitly, do not override it
    when the carrier state changes.  From Stephen Hemminger.

13) mvnets calculates the TX queue to use incorrectly resulting in
    garbage pointer derefs and crashes, fix from Willy Tarreau.

14) cdc_mbim does erroneous sizeof(ETH_HLEN).  Fix from Bjorn Mork.

15) IP fragmentation can leak a refcount-less route out from an RCU
    protected section.  This results in crashes and all sorts of hard to
    diagnose behavior.  Fix from Eric Dumazet.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (24 commits)
  qlcnic: fix beaconing test for 82xx adapter
  net: drop dst before queueing fragments
  net: fec: fix regression in link change accounting
  net: cdc_mbim: remove bogus sizeof()
  drivers: net: ethernet: cpsw: get slave VLAN id from slave node instead of cpsw node
  net: mvneta: fix improper tx queue usage in mvneta_tx()
  esp4: fix error return code in esp_output()
  bridge: make user modified path cost sticky
  ipv6: statically link register_inet6addr_notifier()
  net: mvmdio: add select PHYLIB
  net/802/mrp: fix possible race condition when calling mrp_pdu_queue()
  tuntap: fix error return code in tun_set_iff()
  be2net: take care of __vlan_put_tag return value
  can: sja1000: fix handling on dt properties on little endian systems
  can: mcp251x: add missing IRQF_ONESHOT to request_threaded_irq
  netfilter: nf_nat: fix race when unloading protocol modules
  tcp: Reallocate headroom if it would overflow csum_start
  stmmac: prevent interrupt loop with MMC RX IPC Counter
  bonding: IFF_BONDING is not stripped on enslave failure
  bonding: fix netdev event NULL pointer dereference
  ...
parents 4f2e2903 361cd29c
...@@ -1906,6 +1906,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1906,6 +1906,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
write_unlock_bh(&bond->lock); write_unlock_bh(&bond->lock);
err_close: err_close:
slave_dev->priv_flags &= ~IFF_BONDING;
dev_close(slave_dev); dev_close(slave_dev);
err_unset_master: err_unset_master:
...@@ -3168,11 +3169,20 @@ static int bond_slave_netdev_event(unsigned long event, ...@@ -3168,11 +3169,20 @@ static int bond_slave_netdev_event(unsigned long event,
struct net_device *slave_dev) struct net_device *slave_dev)
{ {
struct slave *slave = bond_slave_get_rtnl(slave_dev); struct slave *slave = bond_slave_get_rtnl(slave_dev);
struct bonding *bond = slave->bond; struct bonding *bond;
struct net_device *bond_dev = slave->bond->dev; struct net_device *bond_dev;
u32 old_speed; u32 old_speed;
u8 old_duplex; u8 old_duplex;
/* A netdev event can be generated while enslaving a device
* before netdev_rx_handler_register is called in which case
* slave will be NULL
*/
if (!slave)
return NOTIFY_DONE;
bond_dev = slave->bond->dev;
bond = slave->bond;
switch (event) { switch (event) {
case NETDEV_UNREGISTER: case NETDEV_UNREGISTER:
if (bond->setup_by_slave) if (bond->setup_by_slave)
......
...@@ -929,6 +929,7 @@ static int mcp251x_open(struct net_device *net) ...@@ -929,6 +929,7 @@ static int mcp251x_open(struct net_device *net)
struct mcp251x_priv *priv = netdev_priv(net); struct mcp251x_priv *priv = netdev_priv(net);
struct spi_device *spi = priv->spi; struct spi_device *spi = priv->spi;
struct mcp251x_platform_data *pdata = spi->dev.platform_data; struct mcp251x_platform_data *pdata = spi->dev.platform_data;
unsigned long flags;
int ret; int ret;
ret = open_candev(net); ret = open_candev(net);
...@@ -945,9 +946,14 @@ static int mcp251x_open(struct net_device *net) ...@@ -945,9 +946,14 @@ static int mcp251x_open(struct net_device *net)
priv->tx_skb = NULL; priv->tx_skb = NULL;
priv->tx_len = 0; priv->tx_len = 0;
flags = IRQF_ONESHOT;
if (pdata->irq_flags)
flags |= pdata->irq_flags;
else
flags |= IRQF_TRIGGER_FALLING;
ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist, ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist,
pdata->irq_flags ? pdata->irq_flags : IRQF_TRIGGER_FALLING, flags, DEVICE_NAME, priv);
DEVICE_NAME, priv);
if (ret) { if (ret) {
dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq); dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
if (pdata->transceiver_enable) if (pdata->transceiver_enable)
......
...@@ -96,8 +96,8 @@ static int sja1000_ofp_probe(struct platform_device *ofdev) ...@@ -96,8 +96,8 @@ static int sja1000_ofp_probe(struct platform_device *ofdev)
struct net_device *dev; struct net_device *dev;
struct sja1000_priv *priv; struct sja1000_priv *priv;
struct resource res; struct resource res;
const u32 *prop; u32 prop;
int err, irq, res_size, prop_size; int err, irq, res_size;
void __iomem *base; void __iomem *base;
err = of_address_to_resource(np, 0, &res); err = of_address_to_resource(np, 0, &res);
...@@ -138,27 +138,27 @@ static int sja1000_ofp_probe(struct platform_device *ofdev) ...@@ -138,27 +138,27 @@ static int sja1000_ofp_probe(struct platform_device *ofdev)
priv->read_reg = sja1000_ofp_read_reg; priv->read_reg = sja1000_ofp_read_reg;
priv->write_reg = sja1000_ofp_write_reg; priv->write_reg = sja1000_ofp_write_reg;
prop = of_get_property(np, "nxp,external-clock-frequency", &prop_size); err = of_property_read_u32(np, "nxp,external-clock-frequency", &prop);
if (prop && (prop_size == sizeof(u32))) if (!err)
priv->can.clock.freq = *prop / 2; priv->can.clock.freq = prop / 2;
else else
priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK; /* default */ priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK; /* default */
prop = of_get_property(np, "nxp,tx-output-mode", &prop_size); err = of_property_read_u32(np, "nxp,tx-output-mode", &prop);
if (prop && (prop_size == sizeof(u32))) if (!err)
priv->ocr |= *prop & OCR_MODE_MASK; priv->ocr |= prop & OCR_MODE_MASK;
else else
priv->ocr |= OCR_MODE_NORMAL; /* default */ priv->ocr |= OCR_MODE_NORMAL; /* default */
prop = of_get_property(np, "nxp,tx-output-config", &prop_size); err = of_property_read_u32(np, "nxp,tx-output-config", &prop);
if (prop && (prop_size == sizeof(u32))) if (!err)
priv->ocr |= (*prop << OCR_TX_SHIFT) & OCR_TX_MASK; priv->ocr |= (prop << OCR_TX_SHIFT) & OCR_TX_MASK;
else else
priv->ocr |= OCR_TX0_PULLDOWN; /* default */ priv->ocr |= OCR_TX0_PULLDOWN; /* default */
prop = of_get_property(np, "nxp,clock-out-frequency", &prop_size); err = of_property_read_u32(np, "nxp,clock-out-frequency", &prop);
if (prop && (prop_size == sizeof(u32)) && *prop) { if (!err && prop) {
u32 divider = priv->can.clock.freq * 2 / *prop; u32 divider = priv->can.clock.freq * 2 / prop;
if (divider > 1) if (divider > 1)
priv->cdr |= divider / 2 - 1; priv->cdr |= divider / 2 - 1;
...@@ -168,8 +168,7 @@ static int sja1000_ofp_probe(struct platform_device *ofdev) ...@@ -168,8 +168,7 @@ static int sja1000_ofp_probe(struct platform_device *ofdev)
priv->cdr |= CDR_CLK_OFF; /* default */ priv->cdr |= CDR_CLK_OFF; /* default */
} }
prop = of_get_property(np, "nxp,no-comparator-bypass", NULL); if (!of_property_read_bool(np, "nxp,no-comparator-bypass"))
if (!prop)
priv->cdr |= CDR_CBP; /* default */ priv->cdr |= CDR_CBP; /* default */
priv->irq_flags = IRQF_SHARED; priv->irq_flags = IRQF_SHARED;
......
...@@ -759,8 +759,9 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter, ...@@ -759,8 +759,9 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter,
if (vlan_tx_tag_present(skb)) { if (vlan_tx_tag_present(skb)) {
vlan_tag = be_get_tx_vlan_tag(adapter, skb); vlan_tag = be_get_tx_vlan_tag(adapter, skb);
__vlan_put_tag(skb, vlan_tag); skb = __vlan_put_tag(skb, vlan_tag);
skb->vlan_tci = 0; if (skb)
skb->vlan_tci = 0;
} }
return skb; return skb;
......
...@@ -1002,6 +1002,7 @@ static void fec_enet_adjust_link(struct net_device *ndev) ...@@ -1002,6 +1002,7 @@ static void fec_enet_adjust_link(struct net_device *ndev)
} else { } else {
if (fep->link) { if (fep->link) {
fec_stop(ndev); fec_stop(ndev);
fep->link = phy_dev->link;
status_change = 1; status_change = 1;
} }
} }
......
...@@ -33,6 +33,7 @@ config MV643XX_ETH ...@@ -33,6 +33,7 @@ config MV643XX_ETH
config MVMDIO config MVMDIO
tristate "Marvell MDIO interface support" tristate "Marvell MDIO interface support"
select PHYLIB
---help--- ---help---
This driver supports the MDIO interface found in the network This driver supports the MDIO interface found in the network
interface units of the Marvell EBU SoCs (Kirkwood, Orion5x, interface units of the Marvell EBU SoCs (Kirkwood, Orion5x,
...@@ -45,7 +46,6 @@ config MVMDIO ...@@ -45,7 +46,6 @@ config MVMDIO
config MVNETA config MVNETA
tristate "Marvell Armada 370/XP network interface support" tristate "Marvell Armada 370/XP network interface support"
depends on MACH_ARMADA_370_XP depends on MACH_ARMADA_370_XP
select PHYLIB
select MVMDIO select MVMDIO
---help--- ---help---
This driver supports the network interface units in the This driver supports the network interface units in the
......
...@@ -374,7 +374,6 @@ static int rxq_number = 8; ...@@ -374,7 +374,6 @@ static int rxq_number = 8;
static int txq_number = 8; static int txq_number = 8;
static int rxq_def; static int rxq_def;
static int txq_def;
#define MVNETA_DRIVER_NAME "mvneta" #define MVNETA_DRIVER_NAME "mvneta"
#define MVNETA_DRIVER_VERSION "1.0" #define MVNETA_DRIVER_VERSION "1.0"
...@@ -1475,7 +1474,8 @@ static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb, ...@@ -1475,7 +1474,8 @@ static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb,
static int mvneta_tx(struct sk_buff *skb, struct net_device *dev) static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)
{ {
struct mvneta_port *pp = netdev_priv(dev); struct mvneta_port *pp = netdev_priv(dev);
struct mvneta_tx_queue *txq = &pp->txqs[txq_def]; u16 txq_id = skb_get_queue_mapping(skb);
struct mvneta_tx_queue *txq = &pp->txqs[txq_id];
struct mvneta_tx_desc *tx_desc; struct mvneta_tx_desc *tx_desc;
struct netdev_queue *nq; struct netdev_queue *nq;
int frags = 0; int frags = 0;
...@@ -1485,7 +1485,7 @@ static int mvneta_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -1485,7 +1485,7 @@ static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)
goto out; goto out;
frags = skb_shinfo(skb)->nr_frags + 1; frags = skb_shinfo(skb)->nr_frags + 1;
nq = netdev_get_tx_queue(dev, txq_def); nq = netdev_get_tx_queue(dev, txq_id);
/* Get a descriptor for the first part of the packet */ /* Get a descriptor for the first part of the packet */
tx_desc = mvneta_txq_next_desc_get(txq); tx_desc = mvneta_txq_next_desc_get(txq);
...@@ -2689,7 +2689,7 @@ static int mvneta_probe(struct platform_device *pdev) ...@@ -2689,7 +2689,7 @@ static int mvneta_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
dev = alloc_etherdev_mq(sizeof(struct mvneta_port), 8); dev = alloc_etherdev_mqs(sizeof(struct mvneta_port), txq_number, rxq_number);
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;
...@@ -2844,4 +2844,3 @@ module_param(rxq_number, int, S_IRUGO); ...@@ -2844,4 +2844,3 @@ module_param(rxq_number, int, S_IRUGO);
module_param(txq_number, int, S_IRUGO); module_param(txq_number, int, S_IRUGO);
module_param(rxq_def, int, S_IRUGO); module_param(rxq_def, int, S_IRUGO);
module_param(txq_def, int, S_IRUGO);
...@@ -200,10 +200,10 @@ static ssize_t qlcnic_store_beacon(struct device *dev, ...@@ -200,10 +200,10 @@ static ssize_t qlcnic_store_beacon(struct device *dev,
} }
err = qlcnic_config_led(adapter, b_state, b_rate); err = qlcnic_config_led(adapter, b_state, b_rate);
if (!err) if (!err) {
err = len; err = len;
else
ahw->beacon_state = b_state; ahw->beacon_state = b_state;
}
if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
qlcnic_diag_free_res(adapter->netdev, max_sds_rings); qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
......
...@@ -149,6 +149,7 @@ void dwmac_mmc_intr_all_mask(void __iomem *ioaddr) ...@@ -149,6 +149,7 @@ void dwmac_mmc_intr_all_mask(void __iomem *ioaddr)
{ {
writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_INTR_MASK); writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_INTR_MASK);
writel(MMC_DEFAULT_MASK, ioaddr + MMC_TX_INTR_MASK); writel(MMC_DEFAULT_MASK, ioaddr + MMC_TX_INTR_MASK);
writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_IPC_INTR_MASK);
} }
/* This reads the MAC core counters (if actaully supported). /* This reads the MAC core counters (if actaully supported).
......
...@@ -1380,7 +1380,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, ...@@ -1380,7 +1380,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN); memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
if (data->dual_emac) { if (data->dual_emac) {
if (of_property_read_u32(node, "dual_emac_res_vlan", if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
&prop)) { &prop)) {
pr_err("Missing dual_emac_res_vlan in DT.\n"); pr_err("Missing dual_emac_res_vlan in DT.\n");
slave_data->dual_emac_res_vlan = i+1; slave_data->dual_emac_res_vlan = i+1;
......
...@@ -1594,7 +1594,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) ...@@ -1594,7 +1594,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
if (tun->flags & TUN_TAP_MQ && if (tun->flags & TUN_TAP_MQ &&
(tun->numqueues + tun->numdisabled > 1)) (tun->numqueues + tun->numdisabled > 1))
return err; return -EBUSY;
} }
else { else {
char *name; char *name;
......
...@@ -134,7 +134,7 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb ...@@ -134,7 +134,7 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
goto error; goto error;
if (skb) { if (skb) {
if (skb->len <= sizeof(ETH_HLEN)) if (skb->len <= ETH_HLEN)
goto error; goto error;
/* mapping VLANs to MBIM sessions: /* mapping VLANs to MBIM sessions:
......
...@@ -291,6 +291,7 @@ ip_set_hash_destroy(struct ip_set *set) ...@@ -291,6 +291,7 @@ ip_set_hash_destroy(struct ip_set *set)
#define type_pf_data_tlist TOKEN(TYPE, PF, _data_tlist) #define type_pf_data_tlist TOKEN(TYPE, PF, _data_tlist)
#define type_pf_data_next TOKEN(TYPE, PF, _data_next) #define type_pf_data_next TOKEN(TYPE, PF, _data_next)
#define type_pf_data_flags TOKEN(TYPE, PF, _data_flags) #define type_pf_data_flags TOKEN(TYPE, PF, _data_flags)
#define type_pf_data_reset_flags TOKEN(TYPE, PF, _data_reset_flags)
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
#define type_pf_data_match TOKEN(TYPE, PF, _data_match) #define type_pf_data_match TOKEN(TYPE, PF, _data_match)
#else #else
...@@ -385,9 +386,9 @@ type_pf_resize(struct ip_set *set, bool retried) ...@@ -385,9 +386,9 @@ type_pf_resize(struct ip_set *set, bool retried)
struct ip_set_hash *h = set->data; struct ip_set_hash *h = set->data;
struct htable *t, *orig = h->table; struct htable *t, *orig = h->table;
u8 htable_bits = orig->htable_bits; u8 htable_bits = orig->htable_bits;
const struct type_pf_elem *data; struct type_pf_elem *data;
struct hbucket *n, *m; struct hbucket *n, *m;
u32 i, j; u32 i, j, flags = 0;
int ret; int ret;
retry: retry:
...@@ -412,9 +413,16 @@ type_pf_resize(struct ip_set *set, bool retried) ...@@ -412,9 +413,16 @@ type_pf_resize(struct ip_set *set, bool retried)
n = hbucket(orig, i); n = hbucket(orig, i);
for (j = 0; j < n->pos; j++) { for (j = 0; j < n->pos; j++) {
data = ahash_data(n, j); data = ahash_data(n, j);
#ifdef IP_SET_HASH_WITH_NETS
flags = 0;
type_pf_data_reset_flags(data, &flags);
#endif
m = hbucket(t, HKEY(data, h->initval, htable_bits)); m = hbucket(t, HKEY(data, h->initval, htable_bits));
ret = type_pf_elem_add(m, data, AHASH_MAX(h), 0); ret = type_pf_elem_add(m, data, AHASH_MAX(h), flags);
if (ret < 0) { if (ret < 0) {
#ifdef IP_SET_HASH_WITH_NETS
type_pf_data_flags(data, flags);
#endif
read_unlock_bh(&set->lock); read_unlock_bh(&set->lock);
ahash_destroy(t); ahash_destroy(t);
if (ret == -EAGAIN) if (ret == -EAGAIN)
...@@ -836,9 +844,9 @@ type_pf_tresize(struct ip_set *set, bool retried) ...@@ -836,9 +844,9 @@ type_pf_tresize(struct ip_set *set, bool retried)
struct ip_set_hash *h = set->data; struct ip_set_hash *h = set->data;
struct htable *t, *orig = h->table; struct htable *t, *orig = h->table;
u8 htable_bits = orig->htable_bits; u8 htable_bits = orig->htable_bits;
const struct type_pf_elem *data; struct type_pf_elem *data;
struct hbucket *n, *m; struct hbucket *n, *m;
u32 i, j; u32 i, j, flags = 0;
int ret; int ret;
/* Try to cleanup once */ /* Try to cleanup once */
...@@ -873,10 +881,17 @@ type_pf_tresize(struct ip_set *set, bool retried) ...@@ -873,10 +881,17 @@ type_pf_tresize(struct ip_set *set, bool retried)
n = hbucket(orig, i); n = hbucket(orig, i);
for (j = 0; j < n->pos; j++) { for (j = 0; j < n->pos; j++) {
data = ahash_tdata(n, j); data = ahash_tdata(n, j);
#ifdef IP_SET_HASH_WITH_NETS
flags = 0;
type_pf_data_reset_flags(data, &flags);
#endif
m = hbucket(t, HKEY(data, h->initval, htable_bits)); m = hbucket(t, HKEY(data, h->initval, htable_bits));
ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), 0, ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), flags,
ip_set_timeout_get(type_pf_data_timeout(data))); ip_set_timeout_get(type_pf_data_timeout(data)));
if (ret < 0) { if (ret < 0) {
#ifdef IP_SET_HASH_WITH_NETS
type_pf_data_flags(data, flags);
#endif
read_unlock_bh(&set->lock); read_unlock_bh(&set->lock);
ahash_destroy(t); ahash_destroy(t);
if (ret == -EAGAIN) if (ret == -EAGAIN)
...@@ -1187,6 +1202,7 @@ type_pf_gc_init(struct ip_set *set) ...@@ -1187,6 +1202,7 @@ type_pf_gc_init(struct ip_set *set)
#undef type_pf_data_tlist #undef type_pf_data_tlist
#undef type_pf_data_next #undef type_pf_data_next
#undef type_pf_data_flags #undef type_pf_data_flags
#undef type_pf_data_reset_flags
#undef type_pf_data_match #undef type_pf_data_match
#undef type_pf_elem #undef type_pf_elem
......
...@@ -199,6 +199,7 @@ extern bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev, ...@@ -199,6 +199,7 @@ extern bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
/* Device notifier */ /* Device notifier */
extern int register_inet6addr_notifier(struct notifier_block *nb); extern int register_inet6addr_notifier(struct notifier_block *nb);
extern int unregister_inet6addr_notifier(struct notifier_block *nb); extern int unregister_inet6addr_notifier(struct notifier_block *nb);
extern int inet6addr_notifier_call_chain(unsigned long val, void *v);
extern void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex, extern void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
struct ipv6_devconf *devconf); struct ipv6_devconf *devconf);
......
...@@ -870,8 +870,12 @@ void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *appl) ...@@ -870,8 +870,12 @@ void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *appl)
* all pending messages before the applicant is gone. * all pending messages before the applicant is gone.
*/ */
del_timer_sync(&app->join_timer); del_timer_sync(&app->join_timer);
spin_lock(&app->lock);
mrp_mad_event(app, MRP_EVENT_TX); mrp_mad_event(app, MRP_EVENT_TX);
mrp_pdu_queue(app); mrp_pdu_queue(app);
spin_unlock(&app->lock);
mrp_queue_xmit(app); mrp_queue_xmit(app);
dev_mc_del(dev, appl->group_address); dev_mc_del(dev, appl->group_address);
......
...@@ -67,7 +67,8 @@ void br_port_carrier_check(struct net_bridge_port *p) ...@@ -67,7 +67,8 @@ void br_port_carrier_check(struct net_bridge_port *p)
struct net_device *dev = p->dev; struct net_device *dev = p->dev;
struct net_bridge *br = p->br; struct net_bridge *br = p->br;
if (netif_running(dev) && netif_oper_up(dev)) if (!(p->flags & BR_ADMIN_COST) &&
netif_running(dev) && netif_oper_up(dev))
p->path_cost = port_cost(dev); p->path_cost = port_cost(dev);
if (!netif_running(br->dev)) if (!netif_running(br->dev))
......
...@@ -156,6 +156,7 @@ struct net_bridge_port ...@@ -156,6 +156,7 @@ struct net_bridge_port
#define BR_BPDU_GUARD 0x00000002 #define BR_BPDU_GUARD 0x00000002
#define BR_ROOT_BLOCK 0x00000004 #define BR_ROOT_BLOCK 0x00000004
#define BR_MULTICAST_FAST_LEAVE 0x00000008 #define BR_MULTICAST_FAST_LEAVE 0x00000008
#define BR_ADMIN_COST 0x00000010
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
u32 multicast_startup_queries_sent; u32 multicast_startup_queries_sent;
......
...@@ -288,6 +288,7 @@ int br_stp_set_path_cost(struct net_bridge_port *p, unsigned long path_cost) ...@@ -288,6 +288,7 @@ int br_stp_set_path_cost(struct net_bridge_port *p, unsigned long path_cost)
path_cost > BR_MAX_PATH_COST) path_cost > BR_MAX_PATH_COST)
return -ERANGE; return -ERANGE;
p->flags |= BR_ADMIN_COST;
p->path_cost = path_cost; p->path_cost = path_cost;
br_configuration_update(p->br); br_configuration_update(p->br);
br_port_state_selection(p->br); br_port_state_selection(p->br);
......
...@@ -139,8 +139,6 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) ...@@ -139,8 +139,6 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
/* skb is pure payload to encrypt */ /* skb is pure payload to encrypt */
err = -ENOMEM;
esp = x->data; esp = x->data;
aead = esp->aead; aead = esp->aead;
alen = crypto_aead_authsize(aead); alen = crypto_aead_authsize(aead);
...@@ -176,8 +174,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) ...@@ -176,8 +174,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
} }
tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen); tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen);
if (!tmp) if (!tmp) {
err = -ENOMEM;
goto error; goto error;
}
seqhi = esp_tmp_seqhi(tmp); seqhi = esp_tmp_seqhi(tmp);
iv = esp_tmp_iv(aead, tmp, seqhilen); iv = esp_tmp_iv(aead, tmp, seqhilen);
......
...@@ -248,8 +248,7 @@ static void ip_expire(unsigned long arg) ...@@ -248,8 +248,7 @@ static void ip_expire(unsigned long arg)
if (!head->dev) if (!head->dev)
goto out_rcu_unlock; goto out_rcu_unlock;
/* skb dst is stale, drop it, and perform route lookup again */ /* skb has no dst, perform route lookup again */
skb_dst_drop(head);
iph = ip_hdr(head); iph = ip_hdr(head);
err = ip_route_input_noref(head, iph->daddr, iph->saddr, err = ip_route_input_noref(head, iph->daddr, iph->saddr,
iph->tos, head->dev); iph->tos, head->dev);
...@@ -523,9 +522,16 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) ...@@ -523,9 +522,16 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
qp->q.max_size = skb->len + ihl; qp->q.max_size = skb->len + ihl;
if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
qp->q.meat == qp->q.len) qp->q.meat == qp->q.len) {
return ip_frag_reasm(qp, prev, dev); unsigned long orefdst = skb->_skb_refdst;
skb->_skb_refdst = 0UL;
err = ip_frag_reasm(qp, prev, dev);
skb->_skb_refdst = orefdst;
return err;
}
skb_dst_drop(skb);
inet_frag_lru_move(&qp->q); inet_frag_lru_move(&qp->q);
return -EINPROGRESS; return -EINPROGRESS;
......
...@@ -349,8 +349,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, ...@@ -349,8 +349,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
* hasn't changed since we received the original syn, but I see * hasn't changed since we received the original syn, but I see
* no easy way to do this. * no easy way to do this.
*/ */
flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk), flowi4_init_output(&fl4, sk->sk_bound_dev_if, sk->sk_mark,
RT_SCOPE_UNIVERSE, IPPROTO_TCP, RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP,
inet_sk_flowi_flags(sk), inet_sk_flowi_flags(sk),
(opt && opt->srr) ? opt->faddr : ireq->rmt_addr, (opt && opt->srr) ? opt->faddr : ireq->rmt_addr,
ireq->loc_addr, th->source, th->dest); ireq->loc_addr, th->source, th->dest);
......
...@@ -2388,8 +2388,12 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) ...@@ -2388,8 +2388,12 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
*/ */
TCP_SKB_CB(skb)->when = tcp_time_stamp; TCP_SKB_CB(skb)->when = tcp_time_stamp;
/* make sure skb->data is aligned on arches that require it */ /* make sure skb->data is aligned on arches that require it
if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) { * and check if ack-trimming & collapsing extended the headroom
* beyond what csum_start can cover.
*/
if (unlikely((NET_IP_ALIGN && ((unsigned long)skb->data & 3)) ||
skb_headroom(skb) >= 0xFFFF)) {
struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER, struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER,
GFP_ATOMIC); GFP_ATOMIC);
return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) : return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
......
...@@ -168,8 +168,6 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, ...@@ -168,8 +168,6 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
struct net_device *dev); struct net_device *dev);
static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
static struct ipv6_devconf ipv6_devconf __read_mostly = { static struct ipv6_devconf ipv6_devconf __read_mostly = {
.forwarding = 0, .forwarding = 0,
.hop_limit = IPV6_DEFAULT_HOPLIMIT, .hop_limit = IPV6_DEFAULT_HOPLIMIT,
...@@ -837,7 +835,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, ...@@ -837,7 +835,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
rcu_read_unlock_bh(); rcu_read_unlock_bh();
if (likely(err == 0)) if (likely(err == 0))
atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa); inet6addr_notifier_call_chain(NETDEV_UP, ifa);
else { else {
kfree(ifa); kfree(ifa);
ifa = ERR_PTR(err); ifa = ERR_PTR(err);
...@@ -927,7 +925,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) ...@@ -927,7 +925,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
ipv6_ifa_notify(RTM_DELADDR, ifp); ipv6_ifa_notify(RTM_DELADDR, ifp);
atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifp); inet6addr_notifier_call_chain(NETDEV_DOWN, ifp);
/* /*
* Purge or update corresponding prefix * Purge or update corresponding prefix
...@@ -2988,7 +2986,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) ...@@ -2988,7 +2986,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
if (state != INET6_IFADDR_STATE_DEAD) { if (state != INET6_IFADDR_STATE_DEAD) {
__ipv6_ifa_notify(RTM_DELADDR, ifa); __ipv6_ifa_notify(RTM_DELADDR, ifa);
atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); inet6addr_notifier_call_chain(NETDEV_DOWN, ifa);
} }
in6_ifa_put(ifa); in6_ifa_put(ifa);
...@@ -4869,22 +4867,6 @@ static struct pernet_operations addrconf_ops = { ...@@ -4869,22 +4867,6 @@ static struct pernet_operations addrconf_ops = {
.exit = addrconf_exit_net, .exit = addrconf_exit_net,
}; };
/*
* Device notifier
*/
int register_inet6addr_notifier(struct notifier_block *nb)
{
return atomic_notifier_chain_register(&inet6addr_chain, nb);
}
EXPORT_SYMBOL(register_inet6addr_notifier);
int unregister_inet6addr_notifier(struct notifier_block *nb)
{
return atomic_notifier_chain_unregister(&inet6addr_chain, nb);
}
EXPORT_SYMBOL(unregister_inet6addr_notifier);
static struct rtnl_af_ops inet6_ops = { static struct rtnl_af_ops inet6_ops = {
.family = AF_INET6, .family = AF_INET6,
.fill_link_af = inet6_fill_link_af, .fill_link_af = inet6_fill_link_af,
......
...@@ -78,3 +78,22 @@ int __ipv6_addr_type(const struct in6_addr *addr) ...@@ -78,3 +78,22 @@ int __ipv6_addr_type(const struct in6_addr *addr)
} }
EXPORT_SYMBOL(__ipv6_addr_type); EXPORT_SYMBOL(__ipv6_addr_type);
static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
int register_inet6addr_notifier(struct notifier_block *nb)
{
return atomic_notifier_chain_register(&inet6addr_chain, nb);
}
EXPORT_SYMBOL(register_inet6addr_notifier);
int unregister_inet6addr_notifier(struct notifier_block *nb)
{
return atomic_notifier_chain_unregister(&inet6addr_chain, nb);
}
EXPORT_SYMBOL(unregister_inet6addr_notifier);
int inet6addr_notifier_call_chain(unsigned long val, void *v)
{
return atomic_notifier_call_chain(&inet6addr_chain, val, v);
}
EXPORT_SYMBOL(inet6addr_notifier_call_chain);
...@@ -330,9 +330,17 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, ...@@ -330,9 +330,17 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
} }
if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
fq->q.meat == fq->q.len) fq->q.meat == fq->q.len) {
return ip6_frag_reasm(fq, prev, dev); int res;
unsigned long orefdst = skb->_skb_refdst;
skb->_skb_refdst = 0UL;
res = ip6_frag_reasm(fq, prev, dev);
skb->_skb_refdst = orefdst;
return res;
}
skb_dst_drop(skb);
inet_frag_lru_move(&fq->q); inet_frag_lru_move(&fq->q);
return -1; return -1;
......
...@@ -104,6 +104,15 @@ hash_ipportnet4_data_flags(struct hash_ipportnet4_elem *dst, u32 flags) ...@@ -104,6 +104,15 @@ hash_ipportnet4_data_flags(struct hash_ipportnet4_elem *dst, u32 flags)
dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
} }
static inline void
hash_ipportnet4_data_reset_flags(struct hash_ipportnet4_elem *dst, u32 *flags)
{
if (dst->nomatch) {
*flags = IPSET_FLAG_NOMATCH;
dst->nomatch = 0;
}
}
static inline int static inline int
hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem) hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem)
{ {
...@@ -414,6 +423,15 @@ hash_ipportnet6_data_flags(struct hash_ipportnet6_elem *dst, u32 flags) ...@@ -414,6 +423,15 @@ hash_ipportnet6_data_flags(struct hash_ipportnet6_elem *dst, u32 flags)
dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
} }
static inline void
hash_ipportnet6_data_reset_flags(struct hash_ipportnet6_elem *dst, u32 *flags)
{
if (dst->nomatch) {
*flags = IPSET_FLAG_NOMATCH;
dst->nomatch = 0;
}
}
static inline int static inline int
hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem) hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem)
{ {
......
...@@ -87,7 +87,16 @@ hash_net4_data_copy(struct hash_net4_elem *dst, ...@@ -87,7 +87,16 @@ hash_net4_data_copy(struct hash_net4_elem *dst,
static inline void static inline void
hash_net4_data_flags(struct hash_net4_elem *dst, u32 flags) hash_net4_data_flags(struct hash_net4_elem *dst, u32 flags)
{ {
dst->nomatch = flags & IPSET_FLAG_NOMATCH; dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
}
static inline void
hash_net4_data_reset_flags(struct hash_net4_elem *dst, u32 *flags)
{
if (dst->nomatch) {
*flags = IPSET_FLAG_NOMATCH;
dst->nomatch = 0;
}
} }
static inline int static inline int
...@@ -308,7 +317,16 @@ hash_net6_data_copy(struct hash_net6_elem *dst, ...@@ -308,7 +317,16 @@ hash_net6_data_copy(struct hash_net6_elem *dst,
static inline void static inline void
hash_net6_data_flags(struct hash_net6_elem *dst, u32 flags) hash_net6_data_flags(struct hash_net6_elem *dst, u32 flags)
{ {
dst->nomatch = flags & IPSET_FLAG_NOMATCH; dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
}
static inline void
hash_net6_data_reset_flags(struct hash_net6_elem *dst, u32 *flags)
{
if (dst->nomatch) {
*flags = IPSET_FLAG_NOMATCH;
dst->nomatch = 0;
}
} }
static inline int static inline int
......
...@@ -198,7 +198,16 @@ hash_netiface4_data_copy(struct hash_netiface4_elem *dst, ...@@ -198,7 +198,16 @@ hash_netiface4_data_copy(struct hash_netiface4_elem *dst,
static inline void static inline void
hash_netiface4_data_flags(struct hash_netiface4_elem *dst, u32 flags) hash_netiface4_data_flags(struct hash_netiface4_elem *dst, u32 flags)
{ {
dst->nomatch = flags & IPSET_FLAG_NOMATCH; dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
}
static inline void
hash_netiface4_data_reset_flags(struct hash_netiface4_elem *dst, u32 *flags)
{
if (dst->nomatch) {
*flags = IPSET_FLAG_NOMATCH;
dst->nomatch = 0;
}
} }
static inline int static inline int
...@@ -494,7 +503,7 @@ hash_netiface6_data_copy(struct hash_netiface6_elem *dst, ...@@ -494,7 +503,7 @@ hash_netiface6_data_copy(struct hash_netiface6_elem *dst,
static inline void static inline void
hash_netiface6_data_flags(struct hash_netiface6_elem *dst, u32 flags) hash_netiface6_data_flags(struct hash_netiface6_elem *dst, u32 flags)
{ {
dst->nomatch = flags & IPSET_FLAG_NOMATCH; dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
} }
static inline int static inline int
...@@ -503,6 +512,15 @@ hash_netiface6_data_match(const struct hash_netiface6_elem *elem) ...@@ -503,6 +512,15 @@ hash_netiface6_data_match(const struct hash_netiface6_elem *elem)
return elem->nomatch ? -ENOTEMPTY : 1; return elem->nomatch ? -ENOTEMPTY : 1;
} }
static inline void
hash_netiface6_data_reset_flags(struct hash_netiface6_elem *dst, u32 *flags)
{
if (dst->nomatch) {
*flags = IPSET_FLAG_NOMATCH;
dst->nomatch = 0;
}
}
static inline void static inline void
hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem) hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
{ {
......
...@@ -104,6 +104,15 @@ hash_netport4_data_flags(struct hash_netport4_elem *dst, u32 flags) ...@@ -104,6 +104,15 @@ hash_netport4_data_flags(struct hash_netport4_elem *dst, u32 flags)
dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
} }
static inline void
hash_netport4_data_reset_flags(struct hash_netport4_elem *dst, u32 *flags)
{
if (dst->nomatch) {
*flags = IPSET_FLAG_NOMATCH;
dst->nomatch = 0;
}
}
static inline int static inline int
hash_netport4_data_match(const struct hash_netport4_elem *elem) hash_netport4_data_match(const struct hash_netport4_elem *elem)
{ {
...@@ -375,6 +384,15 @@ hash_netport6_data_flags(struct hash_netport6_elem *dst, u32 flags) ...@@ -375,6 +384,15 @@ hash_netport6_data_flags(struct hash_netport6_elem *dst, u32 flags)
dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
} }
static inline void
hash_netport6_data_reset_flags(struct hash_netport6_elem *dst, u32 *flags)
{
if (dst->nomatch) {
*flags = IPSET_FLAG_NOMATCH;
dst->nomatch = 0;
}
}
static inline int static inline int
hash_netport6_data_match(const struct hash_netport6_elem *elem) hash_netport6_data_match(const struct hash_netport6_elem *elem)
{ {
......
...@@ -174,9 +174,13 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id, ...@@ -174,9 +174,13 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id,
{ {
const struct set_elem *e = list_set_elem(map, i); const struct set_elem *e = list_set_elem(map, i);
if (i == map->size - 1 && e->id != IPSET_INVALID_ID) if (e->id != IPSET_INVALID_ID) {
/* Last element replaced: e.g. add new,before,last */ const struct set_elem *x = list_set_elem(map, map->size - 1);
ip_set_put_byindex(e->id);
/* Last element replaced or pushed off */
if (x->id != IPSET_INVALID_ID)
ip_set_put_byindex(x->id);
}
if (with_timeout(map->timeout)) if (with_timeout(map->timeout))
list_elem_tadd(map, i, id, ip_set_timeout_set(timeout)); list_elem_tadd(map, i, id, ip_set_timeout_set(timeout));
else else
......
...@@ -1593,10 +1593,8 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, ...@@ -1593,10 +1593,8 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
end += strlen("\r\n\r\n") + clen; end += strlen("\r\n\r\n") + clen;
msglen = origlen = end - dptr; msglen = origlen = end - dptr;
if (msglen > datalen) { if (msglen > datalen)
nf_ct_helper_log(skb, ct, "incomplete/bad SIP message"); return NF_ACCEPT;
return NF_DROP;
}
ret = process_sip_msg(skb, ct, protoff, dataoff, ret = process_sip_msg(skb, ct, protoff, dataoff,
&dptr, &msglen); &dptr, &msglen);
......
...@@ -467,33 +467,22 @@ EXPORT_SYMBOL_GPL(nf_nat_packet); ...@@ -467,33 +467,22 @@ EXPORT_SYMBOL_GPL(nf_nat_packet);
struct nf_nat_proto_clean { struct nf_nat_proto_clean {
u8 l3proto; u8 l3proto;
u8 l4proto; u8 l4proto;
bool hash;
}; };
/* Clear NAT section of all conntracks, in case we're loaded again. */ /* kill conntracks with affected NAT section */
static int nf_nat_proto_clean(struct nf_conn *i, void *data) static int nf_nat_proto_remove(struct nf_conn *i, void *data)
{ {
const struct nf_nat_proto_clean *clean = data; const struct nf_nat_proto_clean *clean = data;
struct nf_conn_nat *nat = nfct_nat(i); struct nf_conn_nat *nat = nfct_nat(i);
if (!nat) if (!nat)
return 0; return 0;
if (!(i->status & IPS_SRC_NAT_DONE))
return 0;
if ((clean->l3proto && nf_ct_l3num(i) != clean->l3proto) || if ((clean->l3proto && nf_ct_l3num(i) != clean->l3proto) ||
(clean->l4proto && nf_ct_protonum(i) != clean->l4proto)) (clean->l4proto && nf_ct_protonum(i) != clean->l4proto))
return 0; return 0;
if (clean->hash) { return i->status & IPS_NAT_MASK ? 1 : 0;
spin_lock_bh(&nf_nat_lock);
hlist_del_rcu(&nat->bysource);
spin_unlock_bh(&nf_nat_lock);
} else {
memset(nat, 0, sizeof(*nat));
i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK |
IPS_SEQ_ADJUST);
}
return 0;
} }
static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto) static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto)
...@@ -505,16 +494,8 @@ static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto) ...@@ -505,16 +494,8 @@ static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto)
struct net *net; struct net *net;
rtnl_lock(); rtnl_lock();
/* Step 1 - remove from bysource hash */
clean.hash = true;
for_each_net(net) for_each_net(net)
nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean); nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean);
synchronize_rcu();
/* Step 2 - clean NAT section */
clean.hash = false;
for_each_net(net)
nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
rtnl_unlock(); rtnl_unlock();
} }
...@@ -526,16 +507,9 @@ static void nf_nat_l3proto_clean(u8 l3proto) ...@@ -526,16 +507,9 @@ static void nf_nat_l3proto_clean(u8 l3proto)
struct net *net; struct net *net;
rtnl_lock(); rtnl_lock();
/* Step 1 - remove from bysource hash */
clean.hash = true;
for_each_net(net)
nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
synchronize_rcu();
/* Step 2 - clean NAT section */
clean.hash = false;
for_each_net(net) for_each_net(net)
nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean); nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean);
rtnl_unlock(); rtnl_unlock();
} }
...@@ -773,7 +747,7 @@ static void __net_exit nf_nat_net_exit(struct net *net) ...@@ -773,7 +747,7 @@ static void __net_exit nf_nat_net_exit(struct net *net)
{ {
struct nf_nat_proto_clean clean = {}; struct nf_nat_proto_clean clean = {};
nf_ct_iterate_cleanup(net, &nf_nat_proto_clean, &clean); nf_ct_iterate_cleanup(net, &nf_nat_proto_remove, &clean);
synchronize_rcu(); synchronize_rcu();
nf_ct_free_hashtable(net->ct.nat_bysource, net->ct.nat_htable_size); nf_ct_free_hashtable(net->ct.nat_bysource, net->ct.nat_htable_size);
} }
......
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