The following commit has been merged in the merge/master branch: commit 6338a53a2bd02d5878ab449371323364b7cc7694 Merge: 8064b3cf750e71fdaf306abb4433a93d0f45f4c9 18cf0d0784b4a634472ed24d0d7ca1c721d93e90 Author: David S. Miller davem@davemloft.net Date: Mon Feb 18 23:32:49 2013 -0500
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net into net
Pull in 'net' to take in the bug fixes that didn't make it into 3.8-final.
Also, deal with the semantic conflict of the change made to net/ipv6/xfrm6_policy.c A missing rt6->n neighbour release was added to 'net', but in 'net-next' we no longer cache the neighbour entries in the ipv6 routes so that change is not appropriate there.
Signed-off-by: David S. Miller davem@davemloft.net
diff --combined MAINTAINERS index 5abc10e,b61e9b1..8bbd949 --- a/MAINTAINERS +++ b/MAINTAINERS @@@ -2974,6 -2974,11 +2974,6 @@@ S: Maintaine F: include/linux/netfilter_bridge/ F: net/bridge/
-ETHERTEAM 16I DRIVER -M: Mika Kuoppala miku@iki.fi -S: Maintained -F: drivers/net/ethernet/fujitsu/eth16i.c - EXT2 FILE SYSTEM M: Jan Kara jack@suse.cz L: linux-ext4@vger.kernel.org @@@ -5364,6 -5369,13 +5364,6 @@@ F: include/linux/sunrpc F: include/uapi/linux/nfs* F: include/uapi/linux/sunrpc/
-NI5010 NETWORK DRIVER -M: Jan-Pascal van Best janpascal@vanbest.org -M: Andreas Mohr andi@lisas.de -L: netdev@vger.kernel.org -S: Maintained -F: drivers/net/ethernet/racal/ni5010.* - NILFS2 FILESYSTEM M: KONISHI Ryusuke konishi.ryusuke@lab.ntt.co.jp L: linux-nilfs@vger.kernel.org @@@ -7524,7 -7536,7 +7524,7 @@@ S: Maintaine F: drivers/media/tuners/tea5767.*
TEAM DRIVER - M: Jiri Pirko jpirko@redhat.com + M: Jiri Pirko jiri@resnulli.us L: netdev@vger.kernel.org S: Supported F: drivers/net/team/ diff --combined drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 571b514,0035c01..8f33315 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@@ -21,7 -21,7 +21,7 @@@
#include "atl1c.h"
- #define ATL1C_DRV_VERSION "1.0.1.0-NAPI" + #define ATL1C_DRV_VERSION "1.0.1.1-NAPI" char atl1c_driver_name[] = "atl1c"; char atl1c_driver_version[] = ATL1C_DRV_VERSION;
@@@ -472,6 -472,7 +472,6 @@@ static int atl1c_set_mac_addr(struct ne
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); - netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr);
@@@ -982,9 -983,11 +982,9 @@@ static int atl1c_setup_ring_resources(s size = sizeof(struct atl1c_buffer) * (tpd_ring->count * 2 + rfd_ring->count); tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL); - if (unlikely(!tpd_ring->buffer_info)) { - dev_err(&pdev->dev, "kzalloc failed, size = %d\n", - size); + if (unlikely(!tpd_ring->buffer_info)) goto err_nomem; - } + for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) { tpd_ring[i].buffer_info = (tpd_ring->buffer_info + count); @@@ -1649,6 -1652,7 +1649,7 @@@ static int atl1c_alloc_rx_buffer(struc u16 num_alloc = 0; u16 rfd_next_to_use, next_next; struct atl1c_rx_free_desc *rfd_desc; + dma_addr_t mapping;
next_next = rfd_next_to_use = rfd_ring->next_to_use; if (++next_next == rfd_ring->count) @@@ -1675,9 -1679,18 +1676,18 @@@ ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); buffer_info->skb = skb; buffer_info->length = adapter->rx_buffer_len; - buffer_info->dma = pci_map_single(pdev, vir_addr, + mapping = pci_map_single(pdev, vir_addr, buffer_info->length, PCI_DMA_FROMDEVICE); + if (unlikely(pci_dma_mapping_error(pdev, mapping))) { + dev_kfree_skb(skb); + buffer_info->skb = NULL; + buffer_info->length = 0; + ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); + netif_warn(adapter, rx_err, adapter->netdev, "RX pci_map_single failed"); + break; + } + buffer_info->dma = mapping; ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, ATL1C_PCIMAP_FROMDEVICE); rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); @@@ -2012,7 -2025,29 +2022,29 @@@ check_sum return 0; }
- static void atl1c_tx_map(struct atl1c_adapter *adapter, + static void atl1c_tx_rollback(struct atl1c_adapter *adpt, + struct atl1c_tpd_desc *first_tpd, + enum atl1c_trans_queue type) + { + struct atl1c_tpd_ring *tpd_ring = &adpt->tpd_ring[type]; + struct atl1c_buffer *buffer_info; + struct atl1c_tpd_desc *tpd; + u16 first_index, index; + + first_index = first_tpd - (struct atl1c_tpd_desc *)tpd_ring->desc; + index = first_index; + while (index != tpd_ring->next_to_use) { + tpd = ATL1C_TPD_DESC(tpd_ring, index); + buffer_info = &tpd_ring->buffer_info[index]; + atl1c_clean_buffer(adpt->pdev, buffer_info, 0); + memset(tpd, 0, sizeof(struct atl1c_tpd_desc)); + if (++index == tpd_ring->count) + index = 0; + } + tpd_ring->next_to_use = first_index; + } + + static int atl1c_tx_map(struct atl1c_adapter *adapter, struct sk_buff *skb, struct atl1c_tpd_desc *tpd, enum atl1c_trans_queue type) { @@@ -2037,7 -2072,10 +2069,10 @@@ buffer_info->length = map_len; buffer_info->dma = pci_map_single(adapter->pdev, skb->data, hdr_len, PCI_DMA_TODEVICE); - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); + if (unlikely(pci_dma_mapping_error(adapter->pdev, + buffer_info->dma))) + goto err_dma; + ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, ATL1C_PCIMAP_TODEVICE); mapped_len += map_len; @@@ -2059,6 -2097,10 +2094,10 @@@ buffer_info->dma = pci_map_single(adapter->pdev, skb->data + mapped_len, buffer_info->length, PCI_DMA_TODEVICE); + if (unlikely(pci_dma_mapping_error(adapter->pdev, + buffer_info->dma))) + goto err_dma; + ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, ATL1C_PCIMAP_TODEVICE); @@@ -2080,6 -2122,9 +2119,9 @@@ frag, 0, buffer_info->length, DMA_TO_DEVICE); + if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma)) + goto err_dma; + ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE, ATL1C_PCIMAP_TODEVICE); @@@ -2092,6 -2137,13 +2134,13 @@@ /* The last buffer info contain the skb address, so it will be free after unmap */ buffer_info->skb = skb; + + return 0; + + err_dma: + buffer_info->dma = 0; + buffer_info->length = 0; + return -1; }
static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb, @@@ -2154,10 -2206,18 +2203,18 @@@ static netdev_tx_t atl1c_xmit_frame(str if (skb_network_offset(skb) != ETH_HLEN) tpd->word1 |= 1 << TPD_ETH_TYPE_SHIFT; /* Ethernet frame */
- atl1c_tx_map(adapter, skb, tpd, type); - atl1c_tx_queue(adapter, skb, tpd, type); + if (atl1c_tx_map(adapter, skb, tpd, type) < 0) { + netif_info(adapter, tx_done, adapter->netdev, + "tx-skb droppted due to dma error\n"); + /* roll back tpd/buffer */ + atl1c_tx_rollback(adapter, tpd, type); + spin_unlock_irqrestore(&adapter->tx_lock, flags); + dev_kfree_skb(skb); + } else { + atl1c_tx_queue(adapter, skb, tpd, type); + spin_unlock_irqrestore(&adapter->tx_lock, flags); + }
- spin_unlock_irqrestore(&adapter->tx_lock, flags); return NETDEV_TX_OK; }
@@@ -2537,9 -2597,10 +2594,9 @@@ static int atl1c_probe(struct pci_dev * } if (atl1c_read_mac_addr(&adapter->hw)) { /* got a random MAC address, set NET_ADDR_RANDOM to netdev */ - netdev->addr_assign_type |= NET_ADDR_RANDOM; + netdev->addr_assign_type = NET_ADDR_RANDOM; } memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); - memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len); if (netif_msg_probe(adapter)) dev_dbg(&pdev->dev, "mac address : %pM\n", adapter->hw.mac_addr); diff --combined drivers/net/ethernet/cadence/macb.c index 352190b,b9d4bb9..7903943 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@@ -287,7 -287,7 +287,7 @@@ static int macb_mii_probe(struct net_de }
/* attach the mac to the phy */ - ret = phy_connect_direct(dev, phydev, &macb_handle_link_change, 0, + ret = phy_connect_direct(dev, phydev, &macb_handle_link_change, bp->phy_interface); if (ret) { netdev_err(dev, "Could not attach to PHY\n"); @@@ -693,6 -693,11 +693,11 @@@ static int macb_poll(struct napi_struc * get notified when new packets arrive. */ macb_writel(bp, IER, MACB_RX_INT_FLAGS); + + /* Packets received while interrupts were disabled */ + status = macb_readl(bp, RSR); + if (unlikely(status)) + napi_reschedule(napi); }
/* TODO: Handle errors */ diff --combined drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index d185a50,601dd84..39c6c55 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@@ -428,7 -428,8 +428,7 @@@ static int stmmac_init_phy(struct net_d priv->plat->phy_addr); pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id_fmt);
- phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, 0, - interface); + phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface);
if (IS_ERR(phydev)) { pr_err("%s: Could not attach to PHY\n", dev->name); @@@ -530,18 -531,17 +530,18 @@@ static void init_dma_desc_rings(struct DBG(probe, INFO, "stmmac: txsize %d, rxsize %d, bfsize %d\n", txsize, rxsize, bfsize);
- priv->rx_skbuff_dma = kmalloc(rxsize * sizeof(dma_addr_t), GFP_KERNEL); - priv->rx_skbuff = - kmalloc(sizeof(struct sk_buff *) * rxsize, GFP_KERNEL); + priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t), + GFP_KERNEL); + priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *), + GFP_KERNEL); priv->dma_rx = (struct dma_desc *)dma_alloc_coherent(priv->device, rxsize * sizeof(struct dma_desc), &priv->dma_rx_phy, GFP_KERNEL); - priv->tx_skbuff = kmalloc(sizeof(struct sk_buff *) * txsize, - GFP_KERNEL); + priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *), + GFP_KERNEL); priv->dma_tx = (struct dma_desc *)dma_alloc_coherent(priv->device, txsize * @@@ -2254,7 -2254,7 +2254,7 @@@ static int __init stmmac_cmdline_opt(ch } else if (!strncmp(opt, "pause:", 6)) { if (kstrtoint(opt + 6, 0, &pause)) goto err; - } else if (!strncmp(opt, "eee_timer:", 6)) { + } else if (!strncmp(opt, "eee_timer:", 10)) { if (kstrtoint(opt + 10, 0, &eee_timer)) goto err; } diff --combined drivers/net/usb/cdc_ncm.c index d7115ec,6d25439..4a8c25a --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@@ -65,9 -65,9 +65,9 @@@ cdc_ncm_get_drvinfo(struct net_device * { struct usbnet *dev = netdev_priv(net);
- strncpy(info->driver, dev->driver_name, sizeof(info->driver)); - strncpy(info->version, DRIVER_VERSION, sizeof(info->version)); - strncpy(info->fw_version, dev->driver_info->description, + strlcpy(info->driver, dev->driver_name, sizeof(info->driver)); + strlcpy(info->version, DRIVER_VERSION, sizeof(info->version)); + strlcpy(info->fw_version, dev->driver_info->description, sizeof(info->fw_version)); usb_make_path(dev->udev, info->bus_info, sizeof(info->bus_info)); } @@@ -576,9 -576,14 +576,14 @@@ static int cdc_ncm_bind(struct usbnet * if ((intf->num_altsetting == 2) && !usb_set_interface(dev->udev, intf->cur_altsetting->desc.bInterfaceNumber, - CDC_NCM_COMM_ALTSETTING_MBIM) && - cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) - return -ENODEV; + CDC_NCM_COMM_ALTSETTING_MBIM)) { + if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) + return -ENODEV; + else + usb_set_interface(dev->udev, + intf->cur_altsetting->desc.bInterfaceNumber, + CDC_NCM_COMM_ALTSETTING_NCM); + } #endif
/* NCM data altsetting is always 1 */ diff --combined drivers/net/xen-netback/interface.c index fc1b8d7,221f426..d984141 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@@ -132,6 -132,7 +132,7 @@@ static void xenvif_up(struct xenvif *vi static void xenvif_down(struct xenvif *vif) { disable_irq(vif->irq); + del_timer_sync(&vif->credit_timeout); xen_netbk_deschedule_xenvif(vif); xen_netbk_remove_xenvif(vif); } @@@ -238,8 -239,6 +239,8 @@@ static const struct net_device_ops xenv .ndo_stop = xenvif_close, .ndo_change_mtu = xenvif_change_mtu, .ndo_fix_features = xenvif_fix_features, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, };
struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, @@@ -365,8 -364,6 +366,6 @@@ void xenvif_disconnect(struct xenvif *v atomic_dec(&vif->refcnt); wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0);
- del_timer_sync(&vif->credit_timeout); - if (vif->irq) unbind_from_irqhandler(vif->irq, vif);
diff --combined include/net/sock.h index a340ab4,25afaa0..a66caa2 --- a/include/net/sock.h +++ b/include/net/sock.h @@@ -140,7 -140,6 +140,7 @@@ typedef __u64 __bitwise __addrpair * @skc_family: network address family * @skc_state: Connection state * @skc_reuse: %SO_REUSEADDR setting + * @skc_reuseport: %SO_REUSEPORT setting * @skc_bound_dev_if: bound device index if != 0 * @skc_bind_node: bind hash linkage for various protocol lookup tables * @skc_portaddr_node: second hash linkage for UDP/UDP-Lite protocol @@@ -180,8 -179,7 +180,8 @@@ struct sock_common
unsigned short skc_family; volatile unsigned char skc_state; - unsigned char skc_reuse; + unsigned char skc_reuse:4; + unsigned char skc_reuseport:4; int skc_bound_dev_if; union { struct hlist_node skc_bind_node; @@@ -299,7 -297,6 +299,7 @@@ struct sock #define sk_family __sk_common.skc_family #define sk_state __sk_common.skc_state #define sk_reuse __sk_common.skc_reuse +#define sk_reuseport __sk_common.skc_reuseport #define sk_bound_dev_if __sk_common.skc_bound_dev_if #define sk_bind_node __sk_common.skc_bind_node #define sk_prot __sk_common.skc_prot @@@ -340,7 -337,7 +340,7 @@@ #endif unsigned long sk_flags; struct dst_entry *sk_rx_dst; - struct dst_entry *sk_dst_cache; + struct dst_entry __rcu *sk_dst_cache; spinlock_t sk_dst_lock; atomic_t sk_wmem_alloc; atomic_t sk_omem_alloc; @@@ -667,7 -664,6 +667,7 @@@ enum sock_flags * Will use last 4 bytes of packet sent from * user-space instead. */ + SOCK_FILTER_LOCKED, /* Filter cannot be changed anymore */ };
static inline void sock_copy_flags(struct sock *nsk, struct sock *osk) @@@ -1041,7 -1037,7 +1041,7 @@@ static inline void sk_refcnt_debug_dec( sk->sk_prot->name, sk, atomic_read(&sk->sk_prot->socks)); }
- inline void sk_refcnt_debug_release(const struct sock *sk) + static inline void sk_refcnt_debug_release(const struct sock *sk) { if (atomic_read(&sk->sk_refcnt) != 1) printk(KERN_DEBUG "Destruction of the %s socket %p delayed, refcnt=%d\n", diff --combined net/batman-adv/distributed-arp-table.c index ea0bd31,5539215..761a590 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@@ -1,4 -1,4 +1,4 @@@ -/* Copyright (C) 2011-2012 B.A.T.M.A.N. contributors: +/* Copyright (C) 2011-2013 B.A.T.M.A.N. contributors: * * Antonio Quartulli * @@@ -440,7 -440,7 +440,7 @@@ static bool batadv_is_orig_node_eligibl /* this is an hash collision with the temporary selected node. Choose * the one with the lowest address */ - if ((tmp_max == max) && + if ((tmp_max == max) && max_orig_node && (batadv_compare_eth(candidate->orig, max_orig_node->orig) > 0)) goto out;
diff --combined net/ipv6/netfilter/nf_conntrack_reasm.c index b89a8c3,0156d07..54087e9 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@@ -97,9 -97,9 +97,9 @@@ static int nf_ct_frag6_sysctl_register( if (table == NULL) goto err_alloc;
- table[0].data = &net->ipv6.frags.high_thresh; - table[1].data = &net->ipv6.frags.low_thresh; - table[2].data = &net->ipv6.frags.timeout; + table[0].data = &net->nf_frag.frags.timeout; + table[1].data = &net->nf_frag.frags.low_thresh; + table[2].data = &net->nf_frag.frags.high_thresh; }
hdr = register_net_sysctl(net, "net/netfilter", table); @@@ -319,7 -319,7 +319,7 @@@ found fq->q.meat += skb->len; if (payload_len > fq->q.max_size) fq->q.max_size = payload_len; - atomic_add(skb->truesize, &fq->q.net->mem); + add_frag_mem_limit(&fq->q, skb->truesize);
/* The first fragment. * nhoffset is obtained from the first fragment, of course. @@@ -328,8 -328,9 +328,8 @@@ fq->nhoffset = nhoff; fq->q.last_in |= INET_FRAG_FIRST_IN; } - write_lock(&nf_frags.lock); - list_move_tail(&fq->q.lru_list, &fq->q.net->lru_list); - write_unlock(&nf_frags.lock); + + inet_frag_lru_move(&fq->q); return 0;
discard_fq: @@@ -368,7 -369,7 +368,7 @@@ nf_ct_frag6_reasm(struct frag_queue *fq }
/* Head of list must not be cloned. */ - if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC)) { + if (skb_unclone(head, GFP_ATOMIC)) { pr_debug("skb is cloned but can't expand head"); goto out_oom; } @@@ -397,7 -398,7 +397,7 @@@ clone->ip_summed = head->ip_summed;
NFCT_FRAG6_CB(clone)->orig = NULL; - atomic_add(clone->truesize, &fq->q.net->mem); + add_frag_mem_limit(&fq->q, clone->truesize); }
/* We have to remove fragment header from datagram and to relocate @@@ -421,7 -422,7 +421,7 @@@ head->csum = csum_add(head->csum, fp->csum); head->truesize += fp->truesize; } - atomic_sub(head->truesize, &fq->q.net->mem); + sub_frag_mem_limit(&fq->q, head->truesize);
head->local_df = 1; head->next = NULL; diff --combined net/netfilter/nf_conntrack_helper.c index 2f380f7,91527d5..1343a4b --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@@ -236,7 -236,9 +236,9 @@@ int __nf_ct_try_assign_helper(struct nf /* We only allow helper re-assignment of the same sort since * we cannot reallocate the helper extension area. */ - if (help->helper != helper) { + struct nf_conntrack_helper *tmp = rcu_dereference(help->helper); + + if (tmp && tmp->help != helper->help) { RCU_INIT_POINTER(help->helper, NULL); goto out; } @@@ -423,41 -425,44 +425,41 @@@ static struct nf_ct_ext_type helper_ext .id = NF_CT_EXT_HELPER, };
-int nf_conntrack_helper_init(struct net *net) +int nf_conntrack_helper_pernet_init(struct net *net) { - int err; - net->ct.auto_assign_helper_warned = false; net->ct.sysctl_auto_assign_helper = nf_ct_auto_assign_helper; + return nf_conntrack_helper_init_sysctl(net); +}
- if (net_eq(net, &init_net)) { - nf_ct_helper_hsize = 1; /* gets rounded up to use one page */ - nf_ct_helper_hash = - nf_ct_alloc_hashtable(&nf_ct_helper_hsize, 0); - if (!nf_ct_helper_hash) - return -ENOMEM; +void nf_conntrack_helper_pernet_fini(struct net *net) +{ + nf_conntrack_helper_fini_sysctl(net); +}
- err = nf_ct_extend_register(&helper_extend); - if (err < 0) - goto err1; +int nf_conntrack_helper_init(void) +{ + int ret; + nf_ct_helper_hsize = 1; /* gets rounded up to use one page */ + nf_ct_helper_hash = + nf_ct_alloc_hashtable(&nf_ct_helper_hsize, 0); + if (!nf_ct_helper_hash) + return -ENOMEM; + + ret = nf_ct_extend_register(&helper_extend); + if (ret < 0) { + pr_err("nf_ct_helper: Unable to register helper extension.\n"); + goto out_extend; }
- err = nf_conntrack_helper_init_sysctl(net); - if (err < 0) - goto out_sysctl; - return 0; - -out_sysctl: - if (net_eq(net, &init_net)) - nf_ct_extend_unregister(&helper_extend); -err1: +out_extend: nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize); - return err; + return ret; }
-void nf_conntrack_helper_fini(struct net *net) +void nf_conntrack_helper_fini(void) { - nf_conntrack_helper_fini_sysctl(net); - if (net_eq(net, &init_net)) { - nf_ct_extend_unregister(&helper_extend); - nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize); - } + nf_ct_extend_unregister(&helper_extend); + nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize); } diff --combined net/netfilter/nf_conntrack_netlink.c index 2334cc5,a081915..79c2d50 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@@ -43,7 -43,6 +43,7 @@@ #include <net/netfilter/nf_conntrack_acct.h> #include <net/netfilter/nf_conntrack_zones.h> #include <net/netfilter/nf_conntrack_timestamp.h> +#include <net/netfilter/nf_conntrack_labels.h> #ifdef CONFIG_NF_NAT_NEEDED #include <net/netfilter/nf_nat_core.h> #include <net/netfilter/nf_nat_l4proto.h> @@@ -324,40 -323,6 +324,40 @@@ nla_put_failure #define ctnetlink_dump_secctx(a, b) (0) #endif
+#ifdef CONFIG_NF_CONNTRACK_LABELS +static int ctnetlink_label_size(const struct nf_conn *ct) +{ + struct nf_conn_labels *labels = nf_ct_labels_find(ct); + + if (!labels) + return 0; + return nla_total_size(labels->words * sizeof(long)); +} + +static int +ctnetlink_dump_labels(struct sk_buff *skb, const struct nf_conn *ct) +{ + struct nf_conn_labels *labels = nf_ct_labels_find(ct); + unsigned int len, i; + + if (!labels) + return 0; + + len = labels->words * sizeof(long); + i = 0; + do { + if (labels->bits[i] != 0) + return nla_put(skb, CTA_LABELS, len, labels->bits); + i++; + } while (i < labels->words); + + return 0; +} +#else +#define ctnetlink_dump_labels(a, b) (0) +#define ctnetlink_label_size(a) (0) +#endif + #define master_tuple(ct) &(ct->master->tuplehash[IP_CT_DIR_ORIGINAL].tuple)
static inline int @@@ -498,7 -463,6 +498,7 @@@ ctnetlink_fill_info(struct sk_buff *skb ctnetlink_dump_helpinfo(skb, ct) < 0 || ctnetlink_dump_mark(skb, ct) < 0 || ctnetlink_dump_secctx(skb, ct) < 0 || + ctnetlink_dump_labels(skb, ct) < 0 || ctnetlink_dump_id(skb, ct) < 0 || ctnetlink_dump_use(skb, ct) < 0 || ctnetlink_dump_master(skb, ct) < 0 || @@@ -597,7 -561,6 +597,7 @@@ ctnetlink_nlmsg_size(const struct nf_co + nla_total_size(sizeof(u_int32_t)) /* CTA_MARK */ #endif + ctnetlink_proto_size(ct) + + ctnetlink_label_size(ct) ; }
@@@ -699,9 -662,6 +699,9 @@@ ctnetlink_conntrack_event(unsigned int && ctnetlink_dump_secctx(skb, ct) < 0) goto nla_put_failure; #endif + if (events & (1 << IPCT_LABEL) && + ctnetlink_dump_labels(skb, ct) < 0) + goto nla_put_failure;
if (events & (1 << IPCT_RELATED) && ctnetlink_dump_master(skb, ct) < 0) @@@ -961,7 -921,6 +961,7 @@@ ctnetlink_parse_help(const struct nlatt return 0; }
+#define __CTA_LABELS_MAX_LENGTH ((XT_CONNLABEL_MAXBIT + 1) / BITS_PER_BYTE) static const struct nla_policy ct_nla_policy[CTA_MAX+1] = { [CTA_TUPLE_ORIG] = { .type = NLA_NESTED }, [CTA_TUPLE_REPLY] = { .type = NLA_NESTED }, @@@ -978,10 -937,6 +978,10 @@@ [CTA_NAT_SEQ_ADJ_REPLY] = { .type = NLA_NESTED }, [CTA_ZONE] = { .type = NLA_U16 }, [CTA_MARK_MASK] = { .type = NLA_U32 }, + [CTA_LABELS] = { .type = NLA_BINARY, + .len = __CTA_LABELS_MAX_LENGTH }, + [CTA_LABELS_MASK] = { .type = NLA_BINARY, + .len = __CTA_LABELS_MAX_LENGTH }, };
static int @@@ -1510,31 -1465,6 +1510,31 @@@ ctnetlink_change_nat_seq_adj(struct nf_ #endif
static int +ctnetlink_attach_labels(struct nf_conn *ct, const struct nlattr * const cda[]) +{ +#ifdef CONFIG_NF_CONNTRACK_LABELS + size_t len = nla_len(cda[CTA_LABELS]); + const void *mask = cda[CTA_LABELS_MASK]; + + if (len & (sizeof(u32)-1)) /* must be multiple of u32 */ + return -EINVAL; + + if (mask) { + if (nla_len(cda[CTA_LABELS_MASK]) == 0 || + nla_len(cda[CTA_LABELS_MASK]) != len) + return -EINVAL; + mask = nla_data(cda[CTA_LABELS_MASK]); + } + + len /= sizeof(u32); + + return nf_connlabels_replace(ct, nla_data(cda[CTA_LABELS]), mask, len); +#else + return -EOPNOTSUPP; +#endif +} + +static int ctnetlink_change_conntrack(struct nf_conn *ct, const struct nlattr * const cda[]) { @@@ -1580,11 -1510,6 +1580,11 @@@ return err; } #endif + if (cda[CTA_LABELS]) { + err = ctnetlink_attach_labels(ct, cda); + if (err < 0) + return err; + }
return 0; } @@@ -1673,8 -1598,6 +1673,8 @@@ ctnetlink_create_conntrack(struct net * nf_ct_acct_ext_add(ct, GFP_ATOMIC); nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC); + nf_ct_labels_ext_add(ct); + /* we must add conntrack extensions before confirmation. */ ct->status |= IPS_CONFIRMED;
@@@ -1782,6 -1705,9 +1782,9 @@@ ctnetlink_new_conntrack(struct sock *ct if (nlh->nlmsg_flags & NLM_F_CREATE) { enum ip_conntrack_events events;
+ if (!cda[CTA_TUPLE_ORIG] || !cda[CTA_TUPLE_REPLY]) + return -EINVAL; + ct = ctnetlink_create_conntrack(net, zone, cda, &otuple, &rtuple, u3); if (IS_ERR(ct)) @@@ -1793,10 -1719,6 +1796,10 @@@ else events = IPCT_NEW;
+ if (cda[CTA_LABELS] && + ctnetlink_attach_labels(ct, cda) == 0) + events |= (1 << IPCT_LABEL); + nf_conntrack_eventmask_report((1 << IPCT_REPLY) | (1 << IPCT_ASSURED) | (1 << IPCT_HELPER) | @@@ -2064,8 -1986,6 +2067,8 @@@ ctnetlink_nfqueue_build(struct sk_buff if (ct->mark && ctnetlink_dump_mark(skb, ct) < 0) goto nla_put_failure; #endif + if (ctnetlink_dump_labels(skb, ct) < 0) + goto nla_put_failure; rcu_read_unlock(); return 0;
@@@ -2094,11 -2014,6 +2097,11 @@@ ctnetlink_nfqueue_parse_ct(const struc if (err < 0) return err; } + if (cda[CTA_LABELS]) { + err = ctnetlink_attach_labels(ct, cda); + if (err < 0) + return err; + } #if defined(CONFIG_NF_CONNTRACK_MARK) if (cda[CTA_MARK]) ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));