Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH v2] bonding: Fix corrupted queue_mapping
From: Neil Horman @ 2012-06-13  0:26 UTC (permalink / raw)
  To: David Miller; +Cc: eric.dumazet, netdev, therbert, john.r.fastabend, roland
In-Reply-To: <20120612.153058.508089648695433178.davem@davemloft.net>

On Tue, Jun 12, 2012 at 03:30:58PM -0700, David Miller wrote:
> From: Neil Horman <nhorman@tuxdriver.com>
> Date: Tue, 12 Jun 2012 13:16:08 -0400
> 
> > On Tue, Jun 12, 2012 at 06:03:51PM +0200, Eric Dumazet wrote:
> >> From: Eric Dumazet <edumazet@google.com>
> >> 
> >> In the transmit path of the bonding driver, skb->cb is used to
> >> stash the skb->queue_mapping so that the bonding device can set its
> >> own queue mapping.  This value becomes corrupted since the skb->cb is
> >> also used in __dev_xmit_skb.
> >> 
> >> When transmitting through bonding driver, bond_select_queue is
> >> called from dev_queue_xmit.  In bond_select_queue the original
> >> skb->queue_mapping is copied into skb->cb (via bond_queue_mapping)
> >> and skb->queue_mapping is overwritten with the bond driver queue.
> >> 
> >> Subsequently in dev_queue_xmit, __dev_xmit_skb is called which writes
> >> the packet length into skb->cb, thereby overwriting the stashed
> >> queue mappping.  In bond_dev_queue_xmit (called from hard_start_xmit),
> >> the queue mapping for the skb is set to the stashed value which is now
> >> the skb length and hence is an invalid queue for the slave device.
> >> 
> >> If we want to save skb->queue_mapping into skb->cb[], best place is to
> >> add a field in struct qdisc_skb_cb, to make sure it wont conflict with
> >> other layers (eg : Qdiscc, Infiniband...)
> >> 
> >> This patchs also makes sure (struct qdisc_skb_cb)->data is aligned on 8
> >> bytes :
> >> 
> >> netem qdisc for example assumes it can store an u64 in it, without
> >> misalignment penalty.
> >> 
> >> Note : we only have 20 bytes left in (struct qdisc_skb_cb)->data[].
> >> The largest user is CHOKe and it fills it.
> >> 
> >> Based on a previous patch from Tom Herbert.
> >> 
> >> Signed-off-by: Eric Dumazet <edumazet@google.com>
> >> Reported-by: Tom Herbert <therbert@google.com>
> >> Cc: John Fastabend <john.r.fastabend@intel.com>
> >> Cc: Roland Dreier <roland@kernel.org>
> > Acked-by: Neil Horman <nhorman@tuxdriver.com>
> > 
> > Looking at this, it would be really nice if we could have some sort of layer
> > independent space in an skb.  It seems we're often looking to shoehorn more
> > stuff into the control bock.
> 
> Applied.
> 
> The problem is that we always have layers that want to record something before
> the packet goes through the scheduler, then be able to retrieve it afterwards.
> Even more problematic are entities that can encapsulte multiple times for a
> single packet.
> 
Yeah, those are both problematic, although perhaps not insurmountable.  I know
Eric has attempted to implement a destructor chain in the past.  I was more
interested in just being able to get per-context scratch space on an skb as a
start, but clearly the two go hand in hand.
 
> If we supported bonds of bonds, even Eric's patch here is insufficient.
> 
Agreed.  I think I'm going to try my hand at putting something together though,
just out of curiosity.  I'll try have something RFC in a few weeks.

Thanks & Regards
Neil

^ permalink raw reply

* ethtool: allow ETHTOOL_GSSET_INFO for users
From: Ben Hutchings @ 2012-06-12 23:27 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Michał Mirosław

Please consider this for stable 3.0.y and 3.2.y:

commit f80400a26a2e8bff541de12834a1134358bb6642
Author: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Date:   Sun Jan 22 00:20:40 2012 +0000

    ethtool: allow ETHTOOL_GSSET_INFO for users
    
    Allow ETHTOOL_GSSET_INFO ethtool ioctl() for unprivileged users.
    ETHTOOL_GSTRINGS is already allowed, but is unusable without this one.
    
    Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
    Acked-by: Ben Hutchings <bhutchings@solarflare.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* [PATCH net-next] ethtool: Make more commands available to unprivileged processes
From: Ben Hutchings @ 2012-06-12 23:05 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-net-drivers

'Get' commands should generally not require CAP_NET_ADMIN, with
the exception of those that expose internal state.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
The one command I'm not sure about is ETHTOOL_STATS.  It might reveal
too much detail about network traffic.  That said, /proc/net/dev and
/sys/class/net/*/statistics are already world-readable.

Ben.

 net/core/ethtool.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index c73d0a5..cbf033d 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1443,6 +1443,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	case ETHTOOL_GSET:
 	case ETHTOOL_GDRVINFO:
 	case ETHTOOL_GMSGLVL:
+	case ETHTOOL_GLINK:
 	case ETHTOOL_GCOALESCE:
 	case ETHTOOL_GRINGPARAM:
 	case ETHTOOL_GPAUSEPARAM:
@@ -1451,6 +1452,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	case ETHTOOL_GSG:
 	case ETHTOOL_GSSET_INFO:
 	case ETHTOOL_GSTRINGS:
+	case ETHTOOL_GSTATS:
 	case ETHTOOL_GTSO:
 	case ETHTOOL_GPERMADDR:
 	case ETHTOOL_GUFO:
@@ -1463,8 +1465,11 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	case ETHTOOL_GRXCLSRLCNT:
 	case ETHTOOL_GRXCLSRULE:
 	case ETHTOOL_GRXCLSRLALL:
+	case ETHTOOL_GRXFHINDIR:
 	case ETHTOOL_GFEATURES:
+	case ETHTOOL_GCHANNELS:
 	case ETHTOOL_GET_TS_INFO:
+	case ETHTOOL_GEEE:
 		break;
 	default:
 		if (!capable(CAP_NET_ADMIN))
-- 
1.7.7.6


-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply related

* Re: [PATCH 7/7] netfilter: add user-space connection tracking helper infrastructure
From: David Miller @ 2012-06-12 22:46 UTC (permalink / raw)
  To: pablo; +Cc: netfilter-devel, netdev
In-Reply-To: <1339524380-2707-8-git-send-email-pablo@netfilter.org>

From: pablo@netfilter.org
Date: Tue, 12 Jun 2012 20:06:20 +0200

> +	pr_info("nfnl_cthelper: registering with nfnetlink.\n");
 ...
> +	pr_info("nfnl_cthelper: unregistering from nfnetlink.\n");

These messages are fine during development, but not for the copy you
actually finally commit into your tree :-)

^ permalink raw reply

* Re: [PATCH 2/7] netfilter: nf_ct_ext: support variable length extensions
From: David Miller @ 2012-06-12 22:35 UTC (permalink / raw)
  To: pablo; +Cc: netfilter-devel, netdev
In-Reply-To: <1339524380-2707-3-git-send-email-pablo@netfilter.org>

From: pablo@netfilter.org
Date: Tue, 12 Jun 2012 20:06:15 +0200

> @@ -79,11 +79,16 @@ static inline void nf_ct_ext_free(struct nf_conn *ct)
>  		kfree(ct->ext);
>  }
>  
> +void *__nf_ct_ext_add_length(struct nf_conn *ct, enum nf_ct_ext_id id,
> +			     size_t var_alloc_len, gfp_t gfp);
> +
>  /* Add this type, returns pointer to data or NULL. */
>  void *
>  __nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp);

You should remove this extern declaration for __nf_ct_ext_add() since you
are removing, or rather renaming, it in this patch.

^ permalink raw reply

* Re: [PATCH v2] bonding: Fix corrupted queue_mapping
From: David Miller @ 2012-06-12 22:30 UTC (permalink / raw)
  To: nhorman; +Cc: eric.dumazet, netdev, therbert, john.r.fastabend, roland
In-Reply-To: <20120612171608.GC15984@hmsreliant.think-freely.org>

From: Neil Horman <nhorman@tuxdriver.com>
Date: Tue, 12 Jun 2012 13:16:08 -0400

> On Tue, Jun 12, 2012 at 06:03:51PM +0200, Eric Dumazet wrote:
>> From: Eric Dumazet <edumazet@google.com>
>> 
>> In the transmit path of the bonding driver, skb->cb is used to
>> stash the skb->queue_mapping so that the bonding device can set its
>> own queue mapping.  This value becomes corrupted since the skb->cb is
>> also used in __dev_xmit_skb.
>> 
>> When transmitting through bonding driver, bond_select_queue is
>> called from dev_queue_xmit.  In bond_select_queue the original
>> skb->queue_mapping is copied into skb->cb (via bond_queue_mapping)
>> and skb->queue_mapping is overwritten with the bond driver queue.
>> 
>> Subsequently in dev_queue_xmit, __dev_xmit_skb is called which writes
>> the packet length into skb->cb, thereby overwriting the stashed
>> queue mappping.  In bond_dev_queue_xmit (called from hard_start_xmit),
>> the queue mapping for the skb is set to the stashed value which is now
>> the skb length and hence is an invalid queue for the slave device.
>> 
>> If we want to save skb->queue_mapping into skb->cb[], best place is to
>> add a field in struct qdisc_skb_cb, to make sure it wont conflict with
>> other layers (eg : Qdiscc, Infiniband...)
>> 
>> This patchs also makes sure (struct qdisc_skb_cb)->data is aligned on 8
>> bytes :
>> 
>> netem qdisc for example assumes it can store an u64 in it, without
>> misalignment penalty.
>> 
>> Note : we only have 20 bytes left in (struct qdisc_skb_cb)->data[].
>> The largest user is CHOKe and it fills it.
>> 
>> Based on a previous patch from Tom Herbert.
>> 
>> Signed-off-by: Eric Dumazet <edumazet@google.com>
>> Reported-by: Tom Herbert <therbert@google.com>
>> Cc: John Fastabend <john.r.fastabend@intel.com>
>> Cc: Roland Dreier <roland@kernel.org>
> Acked-by: Neil Horman <nhorman@tuxdriver.com>
> 
> Looking at this, it would be really nice if we could have some sort of layer
> independent space in an skb.  It seems we're often looking to shoehorn more
> stuff into the control bock.

Applied.

The problem is that we always have layers that want to record something before
the packet goes through the scheduler, then be able to retrieve it afterwards.
Even more problematic are entities that can encapsulte multiple times for a
single packet.

If we supported bonds of bonds, even Eric's patch here is insufficient.

^ permalink raw reply

* Re: [PATCHv2 net-next] ipv4: Add interface option to enable routing of 127.0.0.0/8
From: David Miller @ 2012-06-12 22:26 UTC (permalink / raw)
  To: nhorman; +Cc: netdev
In-Reply-To: <20120612123238.GB15984@hmsreliant.think-freely.org>

From: Neil Horman <nhorman@tuxdriver.com>
Date: Tue, 12 Jun 2012 08:32:38 -0400

> On Tue, Jun 12, 2012 at 07:31:15AM -0400, Thomas Graf wrote:
>> On Tue, Jun 12, 2012 at 07:14:44AM -0400, Neil Horman wrote:
>> > Just out of curiosity, would it be more efficient to implement this by
>> > optionally adding a prohibit route to the local table for 127.0.0.0/8 to every
>> > interface that was brought up, based on weather or not that interfaces
>> > route_localnet bool was true or not?  It would save the additional checks in the
>> > routing path I think.  Not sure how much a savings that is, but I thought I
>> > would ask.
>> 
>> It's not that simple because we also use the local table for source
>> address selection and local address verification. So we would have to
>> exclude/include such routes conditionally based on some route lookup
>> purpose indicator. Such a prohibit route would have to be valid only
>> in the output context.
> 
> ah, understood, so that doesn't really save us anything, it just moves the point
> at which we do the check.
> 
> Acked-by: Neil Horman <nhorman@tuxdriver.com>

Applied, thanks guys.

^ permalink raw reply

* Re: [PATCH net 1/3] bonding:record primary when modify it via sysfs
From: David Miller @ 2012-06-12 22:24 UTC (permalink / raw)
  To: nicolas.2p.debian; +Cc: fubar, wpan, netdev
In-Reply-To: <4FD7A111.9040004@gmail.com>

From: Nicolas de Pesloüan <nicolas.2p.debian@gmail.com>
Date: Tue, 12 Jun 2012 22:05:37 +0200

> I think this patch (http://patchwork.ozlabs.org/patch/164100/) was
> erroneously flagged as "Changes Requested". Despite my suggestion to
> add a "possible typo" warning, I acked the patch and so do Jay. We
> eventually decided not to add the "possible typo" warning, so the
> patch should be accepted.

Thanks for bringing this to my attention.

Applied and pushed out.

^ permalink raw reply

* Re: [PATCH 0/2] netfilter updates for net tree (3.5-rc2)
From: David Miller @ 2012-06-12 22:20 UTC (permalink / raw)
  To: pablo; +Cc: netfilter-devel, netdev
In-Reply-To: <1339522563-9227-1-git-send-email-pablo@netfilter.org>

From: pablo@netfilter.org
Date: Tue, 12 Jun 2012 19:36:01 +0200

> You can pull these two changes from:
> 
> git://1984.lsi.us.es/net master

Pulled, thanks Pablo.

^ permalink raw reply

* Re: pull request: wireless-next 2012-06-12
From: David Miller @ 2012-06-12 22:15 UTC (permalink / raw)
  To: linville-2XuSBdqkA4R54TAoqtyWWQ
  Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20120612200500.GC1932-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>

From: "John W. Linville" <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
Date: Tue, 12 Jun 2012 16:05:01 -0400

> This is the first big wireless pull request intended for 3.6.
> This includes big updates for the ti bits (expecially regarding
> wl18xx support), a large batch of NFC changes (particularly for
> pn533 hardware support), and the usual large amount of updates for
> ath9k and iwlwifi, as well as a variety of other bits here and there.
> In order to fix/avoid some merge problems, this also includes a pull
> of some wireless fixes that have already been sent for 3.5.
> 
> Please let me know if there are problems!

Pulled, thanks John.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [Bug 43327] New: IP routing: cached route is applied to wrong network interface
From: David Miller @ 2012-06-12 20:39 UTC (permalink / raw)
  To: shemminger; +Cc: netdev
In-Reply-To: <20120531174641.2809b5c4@nehalam.linuxnetplumber.net>

From: Stephen Hemminger <shemminger@vyatta.com>
Date: Thu, 31 May 2012 17:46:41 -0700

> https://bugzilla.kernel.org/show_bug.cgi?id=43327
> 
>            Summary: IP routing: cached route is applied to wrong network
>                     interface

This should now be fixed in net-next, inetpeer trees are rooted in the
FIB rules, so should handle arbitrary route lookup key situations.

^ permalink raw reply

* Re: [PATCH 2/5] ipv4: Kill ip_rt_frag_needed().
From: David Miller @ 2012-06-12 20:33 UTC (permalink / raw)
  To: steffen.klassert; +Cc: netdev
In-Reply-To: <20120612114440.GM27795@secunet.com>

From: Steffen Klassert <steffen.klassert@secunet.com>
Date: Tue, 12 Jun 2012 13:44:40 +0200

> On Mon, Jun 11, 2012 at 04:02:58PM -0700, David Miller wrote:
>> UDP works by notifying userspace of PMTU events.  And this is
>> mandatory, if we're setting DF we have to get the user to decrease the
>> size of it's datagram writes below the reported PMTU value.
>> 
>> As a consequence I believe RAW sockets should also work via
>> notifications.
>> 
>> And therefore it can be argued that in neither case should we update
>> the routing cache PMTU information.  
> 
> Should be ok as long as all userspace applications that use UDP or
> RAW sockets handle pmtu event notifications properly.

I am convinced that they absolutely must, if they use IP_PMTUDISC_DO.

Otherwise they will continue making larger-than-PMTU sendmsg()
requests.  As these are datagram sockets, we can't simply segment the
data.

> ping might be a special case, but now the behaviour of a big
> sized ping (say 1400 byte on a network that has a router with
> mtu 1300 along the path) with IP_PMTUDISC_WANT might depend on
> whether the cached pmtu informations are updated by a recent
> tcp connection.
> 
> If we had no tcp connection before, we see the behaviour that
> I described in my first mail. All packets have the DF bit set.
> 
> If a tcp connection updated the cached pmtu informations recently,
> the packets don't have the DF bit set. They are fragmented according
> the cached pmtu informations instead.
> 
> Other applications that do not care for pmtu event notifications
> might be in a similar situation. So perhaps we need the kind of
> patch you are suggested.

We can't do exactly as my patch did, because it allows remote entities
to easily poison PMTU information.  All they have to know is that
there is some UDP or RAW socket open with a certain ID and then send
forged ICMP to us.

What we possibly could do is adjust the socket's IP_PMTUDISC_* setting
from IP_PMTUDISC_WANT to IP_PMTUDISC_DONT in response to PMTU
messages.

This seems to solve all the problems.  Individual RAW and UDP sockets
get the behavior they did before, and route cache PMTU poisoning is
less of an issue.

^ permalink raw reply

* [PATCH 1/1] net-next: add dev_loopback_xmit() to avoid duplicate code
From: Michel Machado @ 2012-06-12 20:16 UTC (permalink / raw)
  To: netdev, linux-kernel
  Cc: David S. Miller, Alexey Kuznetsov, James Morris,
	Hideaki YOSHIFUJI, Patrick McHardy, Eric Dumazet, Jiri Pirko,
	Michał Mirosław, Ben Hutchings

Add dev_loopback_xmit() in order to deduplicate functions
ip_dev_loopback_xmit() (in net/ipv4/ip_output.c) and
ip6_dev_loopback_xmit() (in net/ipv6/ip6_output.c).

I was about to reinvent the wheel when I noticed that
ip_dev_loopback_xmit() and ip6_dev_loopback_xmit() do exactly what I
need and are not IP-only functions, but they were not available to reuse
elsewhere.

ip6_dev_loopback_xmit() does not have line "skb_dst_force(skb);", but I
understand that this is harmless, and should be in dev_loopback_xmit().

Signed-off-by: Michel Machado <michel@digirati.com.br>
CC: "David S. Miller" <davem@davemloft.net>
CC: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
CC: James Morris <jmorris@namei.org>
CC: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
CC: Patrick McHardy <kaber@trash.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jpirko@redhat.com>
CC: "Michał Mirosław" <mirq-linux@rere.qmqm.pl>
CC: Ben Hutchings <bhutchings@solarflare.com>
---

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index e7fd468..1c49c21 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1626,6 +1626,7 @@ extern int		dev_alloc_name(struct net_device *dev, const char *name);
 extern int		dev_open(struct net_device *dev);
 extern int		dev_close(struct net_device *dev);
 extern void		dev_disable_lro(struct net_device *dev);
+extern int		dev_loopback_xmit(struct sk_buff *newskb);
 extern int		dev_queue_xmit(struct sk_buff *skb);
 extern int		register_netdevice(struct net_device *dev);
 extern void		unregister_netdevice_queue(struct net_device *dev,
diff --git a/net/core/dev.c b/net/core/dev.c
index cd09819..c6e29ea6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2476,6 +2476,23 @@ static DEFINE_PER_CPU(int, xmit_recursion);
 #define RECURSION_LIMIT 10
 
 /**
+ *	dev_loopback_xmit - loop back @skb
+ *	@skb: buffer to transmit
+ */
+int dev_loopback_xmit(struct sk_buff *skb)
+{
+	skb_reset_mac_header(skb);
+	__skb_pull(skb, skb_network_offset(skb));
+	skb->pkt_type = PACKET_LOOPBACK;
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+	WARN_ON(!skb_dst(skb));
+	skb_dst_force(skb);
+	netif_rx_ni(skb);
+	return 0;
+}
+EXPORT_SYMBOL(dev_loopback_xmit);
+
+/**
  *	dev_queue_xmit - transmit a buffer
  *	@skb: buffer to transmit
  *
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 451f97c..d34ddde 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -113,19 +113,6 @@ int ip_local_out(struct sk_buff *skb)
 }
 EXPORT_SYMBOL_GPL(ip_local_out);
 
-/* dev_loopback_xmit for use with netfilter. */
-static int ip_dev_loopback_xmit(struct sk_buff *newskb)
-{
-	skb_reset_mac_header(newskb);
-	__skb_pull(newskb, skb_network_offset(newskb));
-	newskb->pkt_type = PACKET_LOOPBACK;
-	newskb->ip_summed = CHECKSUM_UNNECESSARY;
-	WARN_ON(!skb_dst(newskb));
-	skb_dst_force(newskb);
-	netif_rx_ni(newskb);
-	return 0;
-}
-
 static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst)
 {
 	int ttl = inet->uc_ttl;
@@ -281,7 +268,7 @@ int ip_mc_output(struct sk_buff *skb)
 			if (newskb)
 				NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING,
 					newskb, NULL, newskb->dev,
-					ip_dev_loopback_xmit);
+					dev_loopback_xmit);
 		}
 
 		/* Multicasts with ttl 0 must not go beyond the host */
@@ -296,7 +283,7 @@ int ip_mc_output(struct sk_buff *skb)
 		struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
 		if (newskb)
 			NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, newskb,
-				NULL, newskb->dev, ip_dev_loopback_xmit);
+				NULL, newskb->dev, dev_loopback_xmit);
 	}
 
 	return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, NULL,
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index d99fdc6..8443c00 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -83,19 +83,6 @@ int ip6_local_out(struct sk_buff *skb)
 }
 EXPORT_SYMBOL_GPL(ip6_local_out);
 
-/* dev_loopback_xmit for use with netfilter. */
-static int ip6_dev_loopback_xmit(struct sk_buff *newskb)
-{
-	skb_reset_mac_header(newskb);
-	__skb_pull(newskb, skb_network_offset(newskb));
-	newskb->pkt_type = PACKET_LOOPBACK;
-	newskb->ip_summed = CHECKSUM_UNNECESSARY;
-	WARN_ON(!skb_dst(newskb));
-
-	netif_rx_ni(newskb);
-	return 0;
-}
-
 static int ip6_finish_output2(struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb_dst(skb);
@@ -121,7 +108,7 @@ static int ip6_finish_output2(struct sk_buff *skb)
 			if (newskb)
 				NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING,
 					newskb, NULL, newskb->dev,
-					ip6_dev_loopback_xmit);
+					dev_loopback_xmit);
 
 			if (ipv6_hdr(skb)->hop_limit == 0) {
 				IP6_INC_STATS(dev_net(dev), idev,

^ permalink raw reply related

* [PATCH] NFC: only put local on destruction if it was created before
From: Sasha Levin @ 2012-06-12 20:08 UTC (permalink / raw)
  To: lauro.venancio-430g2QfJUUCGglJvpFV4uA,
	aloisio.almeida-430g2QfJUUCGglJvpFV4uA,
	sameo-VuQAYsv1563Yd54FQh9/CA, linville-2XuSBdqkA4R54TAoqtyWWQ
  Cc: davej-H+wXaHxf7aLQT0dZR+AlfA,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Sasha Levin

Not having 'local' is a valid case when a socket was created but never
bound or connected to anything, so avoid putting 'local' if it was
never created.

Signed-off-by: Sasha Levin <levinsasha928-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 net/nfc/llcp/sock.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 2c0b317..54daa10 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -710,7 +710,8 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
 
 	sock->parent = NULL;
 
-	nfc_llcp_local_put(sock->local);
+	if (sock->local)
+		nfc_llcp_local_put(sock->local);
 }
 
 static int llcp_sock_create(struct net *net, struct socket *sock,
-- 
1.7.8.6

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* pull request: wireless-next 2012-06-12
From: John W. Linville @ 2012-06-12 20:05 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA

commit 0440507bbc44149e63bbfb9df730ba3820371904

Dave,

This is the first big wireless pull request intended for 3.6.
This includes big updates for the ti bits (expecially regarding
wl18xx support), a large batch of NFC changes (particularly for
pn533 hardware support), and the usual large amount of updates for
ath9k and iwlwifi, as well as a variety of other bits here and there.
In order to fix/avoid some merge problems, this also includes a pull
of some wireless fixes that have already been sent for 3.5.

Please let me know if there are problems!

John

---

The following changes since commit 8d242488ce4627dd7e6333caab56df11ea25e239:

  phy: Use pr_<level> (2012-06-11 16:58:24 -0700)

are available in the git repository at:
  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next.git for-davem

Albert Pool (1):
      rt2800usb: 2001:3c17 is an RT3370 device

Alex Hung (1):
      rfkill: Add the capability to switch all devices of all type in __rfkill_switch_all().

Amitkumar Karwar (2):
      mwifiex: fix simultaneous scan and Tx traffic problem
      mwifiex: scan less channels per scan command to improve Tx traffic

Arik Nemtsov (44):
      wl18xx: create per-chip-family private storage
      wl18xx: set the number of Tx descriptors
      wl18xx: set normal/GEM Tx spare block counts
      wl18xx: implement hw op for calculating hw block count per packet
      wl18xx: implement hw op for setting blocks in hw_tx_desc
      wl18xx: implement hw op for setting frame length in tx_hw_desc
      wl18xx: define HW-rate translation elements/tables
      wl18xx: add fw_status private data
      wl18xx: set Rx block-size alignment quirk
      wl18xx: implement hw op for getting rx buffer data alignment
      wl18xx: implement hw op for getting rx packet data length
      wl18xx: implement immediate Tx completion
      wlcore/wl18xx: add hw op for setting Tx HW checksum
      wlcore/wl18xx: add hw op for Rx HW checksum
      wlcore: track current channel type per vif
      wl18xx: send channel type to FW on role start
      wl18xx: ipmlement ap_rate_mask hw op
      wlcore: support peer MIMO rates
      wlcore/wl18xx: enable MIMO/wide-chan rates in AP-mode rate config
      wl18xx: set HT capabilities
      wl18xx: add module param for overriding HT caps
      wl18xx: read FW pc on recovery
      wl18xx: disable FW log functionality
      wl18xx: implement hw op to read PG version
      wl18xx: init Tx-released index to 0 on HW init
      wl18xx: don't upload NVS to FW
      wl18xx: change board type enum according to new FW
      wlcore/wl12xx/18xx: split fw_status struct into two
      wlcore: fix sparse warnings related to static functions
      wlcore: fix dynamic_ps_timeout time regression
      wlcore: fixes for connection_loss_work
      wl18xx: add dependency on mac80211
      wlcore: remove duplicate BUG_ON during recovery
      mac80211: allow low-level drivers to set netdev feature bits
      wlcore/wl12xx/wl18xx: introduce quirk to remove TKIP header space
      wlcore/wl12xx/wl18xx: handle spare blocks spacial cases per arch
      wlcore: add stop reason bitmap for waking/starting queues
      wlcore: stop queues on Tx flush
      wlcore/wl12xx/wl18xx: implement op_set_key per HW arch
      mac80211: add stations after AP start on reconfig
      wl18xx: allow FW-log by default for PG2.0
      wl18xx: align wl18xx_conf_phy with FW variant and remove it
      wl18xx: clean up phy module parameters
      wlcore/wl12xx/wl18xx: make NVS file optional for wl18xx

Assaf Azulay (2):
      wl18xx: change default tcp_checksum to false
      wlcore: increase number of BA sessions to 3

Avinash Patil (2):
      mwifiex: invalidate bss config before setting channel for uAP
      mwifiex: support NL80211_HIDDEN_SSID_ZERO_LEN for uAP

Ben Greear (1):
      ath9k: Support ethtool getstats api.

Bing Zhao (1):
      mwifiex: shorten per channel scan time

Chris Yungmann (1):
      brcm80211: brcmsmac: fixed checkpatch and sparse warnings

Chun-Yeow Yeoh (1):
      mac80211: Add missing mesh parameter dot11MeshForwarding for debugfs

Dan Carpenter (2):
      brcm80211: remove an unneeded NULL check
      brcm80211: brcmu_pkt_buf_free_skb() should handle NULL

Don Fry (1):
      iwlwifi: implement dynamic opmode loading

Eliad Peller (13):
      wlcore: use the original elp time in forced_ps mode
      wlcore: use correct link for bcast/multicast frames
      wlcore: flush before stopping AP
      wlcore: set wl->ht_cap per-band
      wlcore: flush tx on CHANGE_CHANNEL
      wlcore: increase WL1271_EVENT_TIMEOUT
      mac80211: use offchannel queue only when supported
      mac80211: fail authentication when AP denied authentication
      nl80211: add new rssi event to indicate beacon loss
      mac80211: remove ieee80211_get_operstate()
      wl12xx: send beacon loss events to userspace
      wl12xx/wl18xx: add erp protection IE to the beacon filter
      wlcore: compare ssid_len before comparing ssids

Emmanuel Grumbach (12):
      iwlwifi: fix prints in iwl_rx_handle
      iwlwifi: s/iwlagn_txq_free_tfd/iwl_txq_free_tfd
      iwlwifi: s/iwlagn_unmap_tfd/iwl_unmap_tfd
      iwlwifi: SCD_INT_MSK is obsolete - don't update it
      iwlwifi: first config the SCD queues, then activate them
      iwlwifi: use iwl_trans_set_wr_ptrs to init the queues
      iwlwifi: s/txq_agg_disable/txq_disable
      iwlwifi: s/txq_setup/txq_enable
      iwlwifi: update mask value for SCD queue config
      iwlwifi: allocate Tx cmd pool per device
      iwlwifi: fix rf configuration
      iwlwifi: configure the SKU in the HW

Eyal Shapira (2):
      wlcore: add support macros to easily add conf debugfs entries
      wlcore: add debugfs control over rx interrupt pacing

Grant Erickson (1):
      wl12xx: Add support for an external 26 MHz crystal source

Gregory Greenman (1):
      iwlwifi: Move IWL_MASK macro to transport.

Hauke Mehrtens (1):
      ssb: recognize ARM Cortex M3

Holger Schurig (1):
      mac80211: send beacon loss events to userspace

Ido Reis (6):
      wl18xx: fix PHY_INIT addresses mem size
      wl18xx: support PG2 version of the chip
      wl18xx: FW/PHY arguments added for PG2
      wl18xx: PG2.0 HW Watch dog interrupt support
      wl18xx: pad only last frame in aggregration buffer for PG2
      wl18xx: update fw statistics

Igal Chernobelsky (1):
      wlcore: modify bss loss parameters

Ilan Peer (3):
      iwlwifi: Check BSS ctx active before call mac80211
      iwlwifi: handle race condition in ROC flow
      iwlwifi: clear STATUS_SCAN_HW when PAN_PARAMS fails

Joe Perches (3):
      net: mac80211: Convert printk(KERN_DEBUG to pr_debug
      net: mac80211: Add and use ht_vdbg debugging macro
      net: mac80211: Add and use ibss_vdbg debugging macro

Johannes Berg (36):
      iwlwifi: add __printf argument checking
      iwlwifi: properly handle device_set_wakeup_enable
      iwlwifi: move IWL_CMD_FAILED_MSK
      iwlwifi: move notification wait into core
      iwlwifi: clean up coding style in PCIe transport
      wireless: remove wext sysfs
      cfg80211: deprecate CFG80211_WEXT
      mac80211: simplify association HT parameters
      mac80211: clean up ieee80211_set_channel
      mac80211: move ieee80211_set_channel function
      cfg80211: simplify cfg80211_can_beacon_sec_chan API
      cfg80211: provide channel to start_ap function
      cfg80211: disallow setting channel on WDS interfaces
      cfg80211: provide channel to join_mesh function
      iwlwifi: make a lot of functions static
      iwlwifi: use mac80211 channel in connection init
      iwlwifi: trust mac80211 channel setting
      iwlwifi: use mac80211 channels for reset scan
      iwlwifi: use mac80211 channel for radar check
      iwlwifi: give HT format to mac80211/radiotap
      iwlwifi: move PCIe into subdirectory
      iwlwifi: trust mac80211 HT40 setting
      iwlwifi: move DVM code into subdirectory
      iwlwifi: unify tx_chains_num setting
      iwlwifi: move ht40 bitmap into config
      iwlwifi: add iwl_set_bits_mask
      iwlwifi: refactor EEPROM reading/parsing
      iwlwifi: configure PHY version for 1000 series
      iwlwifi: move RF config into NIC config
      iwlwifi: remove extern opmode ops declarations
      cfg80211: clarify set_channel APIs
      mac80211: print info when disabling HT
      cfg80211: validate remain-on-channel time better
      wireless: update wireless URLs
      mac80211: do remain-on-channel while idle
      mac80211: unify SW/offload remain-on-channel

John W. Linville (5):
      Merge branch 'master' of git://git.kernel.org/.../linville/wireless
      wl18xx: avoid some -Wformat warnings
      Merge tag 'nfc-next-3.6-1' of git://git.kernel.org/.../sameo/nfc-3.0
      Merge branch 'for-john' of git://git.kernel.org/.../iwlwifi/iwlwifi-next
      Merge branch 'master' of git://git.kernel.org/.../linville/wireless-next into for-davem

Jonas Gorski (1):
      ssb: add missing PCI ID for b/g/n single band BCM4322

Luciano Coelho (58):
      wl18xx: add new module
      wlcore_sdio/wl18xx: use SDIO revision number to identify wl18xx chips
      wl18xx: add empty operations struct
      wl18xx: add partition table
      wl18xx: add register table
      wl18xx: add identify chip operation
      wl18xx: add some boot operations and hw-specific configurations
      wl18xx: add trigger command and ack event operations
      wl18xx: add hw_init operation
      wl18xx: add runtime configuration parameters
      wl18xx: add board type module argument
      wl18xx: translate and write the board type to SCR_PAD2
      wl18xx: read clock frequency and do top init accordingly
      wlcore: rename wl12xx.h to wlcore_i.h
      wlcore/wl12xx: move ref_clock and tcxo_clock elements to wl12xx
      wlcore/wl12xx: move rx_mem_pool_addr element to wl12xx
      wlcore/wl12xx: add plt_init op and move the code to wl12xx
      wl18xx: add plt_init operation
      wl18xx: change the low_band_component_type for HDK boards
      wl18xx: add number of antennas and dc2dc type as module params
      wl18xx: add module parameter to disable TCP checksum
      wl18xx: derive the MAC address from the BD_ADDR in fuse ROM
      wl18xx: add a module parameter to control 11a support
      wlcore: add module parameter to dump SDIO reads and writes
      wl18xx: copy the default configuration before checking the board_type
      wl18xx: changed default board_type to HDK
      wlcore: add space for private area when allocating fw_status
      wl18xx: change low_band_component_type value for COM8
      wlcore: reorder identify_chip and get_hw_info
      wl18xx: disable MCS_13 for wl18xx PG 1.0
      wlcore: update beacon and probe_resp templates when rates change
      wlcore: use all AP basic rates as default
      wlcore: abstract debugfs fw_stats to be handled by the lower drivers
      wlcore: add debugfs macro to help print fw statistics arrays
      wl12xx: implement fw status debugfs entries
      wl18xx: implement fw status debugfs entries
      wlcore: create private static_data area and add operation to parse it
      wl18xx: print the PHY firmware version from the private static data
      wlcore: print the interrupt status when recovery is triggered
      wl18xx: don't use MIMO when ht_mode is set to wide
      wlcore: use proper values for supported local rates
      wl18xx: add module parameter to force SISO 20MHz
      wl18xx: add power limit reference value to mac_and_phy settings
      wl18xx: export low/high band component values as module params
      wl18xx: export pwr_limit_reference_11_abg value as a module parameter
      wlcore/wl12xx/wl18xx: move lower driver debugfs to a subdir
      wlcore: increase aggregation buffer size by one page
      wl18xx: increase tx_ba_win_size to 64
      wl18xx: use new fw stats structures
      wlcore/wl12xx/wl18xx: don't use TX align quirk for wl127x
      wl18xx: add support to clear FW statistics
      wlcore: export raw binary with the FW statistics in debugfs
      wlcore/wl18xx/wl12xx: use u8 instead of bool for host_fast_wakeup_support
      wlcore: use u8 instead of enum for bcn_filt_mode
      wlcore/wl18xx: the conf structs must be packed so they can be exported
      wlcore/wl18xx: export conf struct in a debugfs file
      wl18xx: read configuration structure from a binary file
      Merge branch 'wl12xx-next' into for-linville

Meenakshi Venkataraman (2):
      iwlwifi: fix debug print in iwl_sta_calc_ht_flags
      iwlwifi: add debugging to shadow registers and fix typo

Mohammed Shafi Shajakhan (1):
      ath9k: Fix modal EEPROM dump

Paul Bolle (1):
      iwlwifi: fix typo 'IWL_WATCHHDOG_DISABLED'

Pontus Fuchs (1):
      mac80211: Clear wowlan flag when drv_suspend returns failure

Rajkumar Manoharan (10):
      ath9k_hw: update ar9462 initval table to fix rx
      ath9k: cleanup MCI indentation
      ath9k_hw: fix IQ calibration chain index
      ath9k_hw: program BT to control SPDT
      ath9k_hw: configure ar9462 switching regulator
      ath9k_hw: fix BT RF performance
      ath9k: BT coex performance tuning for AR9462
      ath: do not update cycle counters with sleep mode
      ath9k_hw: fix power state for MCI
      ath9k: improve BT FTP/PAN performance

Samuel Ortiz (29):
      NFC: Take a reference on the LLCP local pointer when creating a socket
      NFC: Socket linked list
      NFC: Move LLCP receiver window value to socket structure
      NFC: Move LLCP MIU extension value to socket structure
      NFC: LLCP's MIUX is 10 bytes long, not 7
      NFC: Export LLCP general bytes getter
      NFC: Add target mode protocols to the polling loop startup routine
      NFC: Implement pn533 target mode polling loop
      NFC: Add target mode activation netlink event
      NFC: Set the NFC device RF mode appropriately
      NFC: Introduce target mode tx ops
      NFC: Introduce target mode rx data callback
      NFC: Implement the pn533 target mode data fetching routine
      NFC: Implement the pn533 target mode Tx op
      NFC: Don't hold a NULL connecting LLCP socket lock
      NFC: Call the DEP link down ops even when in target mode
      NFC: Reset poll mod list when stopping pn533 poll
      NFC: Unregister device if pn533 initial configuration fails
      NFC: Configure pn533 RF timings
      NFC: Add passive initiator data for pn533
      NFC: Add type A and type F parameters for pn533 target mode
      NFC: Implement pn533 polling loop
      NFC: Requeue lost LLCP frames
      NFC: Send a receiver ready frame only to reply to an I frame
      NFC: Switch to Initiator mode when getting NFC_ATTR_PROTOCOLS
      NFC: Destroy LLCP timout workqueue when releasing the link
      NFC: Set the proper baud rate when trying to activate pn533 targets
      NFC: Convert pn533 from semaphore to mutex
      NFC: Monitor pn533 target mode

Stanislav Yakovlev (1):
      net/wireless: ipw2200: introduce ipw_read_eeprom function

Stanislaw Gruszka (3):
      rt2x00: claim RSN IBSS support
      iwl4965: claim RSN IBSS support
      mac80211: configure 11b/g channel access rules for legacy APs

Sujith Manoharan (18):
      ath9k: Prune ath9k_init_device
      ath9k: Handle ASPM properly
      ath9k: Setup MCI interrupts properly
      ath9k_hw: Fix AR_RTC_KEEP_AWAKE usage
      ath9k_hw: Fix MCI usage
      ath9k_hw: Cleanup power mode API
      ath9k: Add MCI interrupt to debugfs statistics
      ath9k_hw: Fix variable usage
      ath9k: Remove SC_OP_OFFCHANNEL
      ath9k: Use separate operational flags for BTCOEX
      ath9k: Group link monitoring logic
      ath9k: Fix work handling
      ath9k: Move LNA code to antenna.c
      ath9k: Use atomic operations
      ath9k: Handle fatal interrupts properly
      ath9k: Fix powersave locking
      ath9k: Resync beacons properly
      ath9k_hw: Initvals update for AR9462

Thomas Pedersen (1):
      mac80211: allow channel change while mesh is down

Victor Goldenshtein (5):
      wl12xx: fix fm_coex parameters configuration
      wl18xx: fix fm_coex parameters configuration
      wlcore: don't enable BET for high basic rates
      wlcore: wait for roc complete only for the first roc command
      wlcore: set channels 12-14 as pactive for sched scan

Vivek Natarajan (1):
      ath9k: Ensure a fair beacon distribution in IBSS mode

Yoni Divinsky (5):
      wlcore: use psd_type indexing according to spec
      wl12xx: set the irq polarity before loading the fw
      wlcore: fix the CONF_TX_AC_ANY_TID to be 0xff
      wlcore: do not send stop fwlog cmd if fw is hanged
      wlcore: add role_id to all the sched_scan commands

Zefir Kurtisi (1):
      ath9k: fix/add bits for spectral scanning

Zero.Lin (1):
      rt2x00:Add RT5392 chipset support

villacis-5itmuRygkZmgSpxsJD1C4w@public.gmane.org (1):
      rt2x00: Add support for RT5360 based PCI devices.

 Documentation/feature-removal-schedule.txt         |   22 +-
 MAINTAINERS                                        |   18 +-
 drivers/net/wireless/ath/ath6kl/cfg80211.c         |   36 +-
 drivers/net/wireless/ath/ath6kl/core.h             |    3 -
 drivers/net/wireless/ath/ath6kl/main.c             |    1 -
 drivers/net/wireless/ath/ath9k/Makefile            |    4 +-
 drivers/net/wireless/ath/ath9k/ahb.c               |    2 +-
 drivers/net/wireless/ath/ath9k/antenna.c           |  776 +++++++++++
 drivers/net/wireless/ath/ath9k/ar9003_calib.c      |   20 +-
 drivers/net/wireless/ath/ath9k/ar9003_eeprom.c     |    5 +-
 drivers/net/wireless/ath/ath9k/ar9003_mci.c        |  457 ++++---
 drivers/net/wireless/ath/ath9k/ar9003_mci.h        |   10 +-
 drivers/net/wireless/ath/ath9k/ar9003_phy.c        |    4 +
 drivers/net/wireless/ath/ath9k/ar9003_phy.h        |   32 +-
 .../net/wireless/ath/ath9k/ar9462_2p0_initvals.h   |    5 +-
 drivers/net/wireless/ath/ath9k/ath9k.h             |   49 +-
 drivers/net/wireless/ath/ath9k/beacon.c            |   23 +-
 drivers/net/wireless/ath/ath9k/btcoex.c            |   10 +-
 drivers/net/wireless/ath/ath9k/btcoex.h            |    4 +
 drivers/net/wireless/ath/ath9k/debug.c             |    9 +-
 drivers/net/wireless/ath/ath9k/debug.h             |    1 +
 drivers/net/wireless/ath/ath9k/eeprom_4k.c         |    2 +-
 drivers/net/wireless/ath/ath9k/eeprom_9287.c       |    2 +-
 drivers/net/wireless/ath/ath9k/eeprom_def.c        |    4 +-
 drivers/net/wireless/ath/ath9k/gpio.c              |   36 +-
 drivers/net/wireless/ath/ath9k/hw.c                |  212 ++--
 drivers/net/wireless/ath/ath9k/hw.h                |   10 +-
 drivers/net/wireless/ath/ath9k/init.c              |   18 +-
 drivers/net/wireless/ath/ath9k/link.c              |  502 +++++++
 drivers/net/wireless/ath/ath9k/main.c              |  692 +++-------
 drivers/net/wireless/ath/ath9k/mci.c               |   65 +-
 drivers/net/wireless/ath/ath9k/mci.h               |   11 +-
 drivers/net/wireless/ath/ath9k/pci.c               |    7 +-
 drivers/net/wireless/ath/ath9k/recv.c              |  768 +----------
 drivers/net/wireless/ath/ath9k/reg.h               |    2 +
 drivers/net/wireless/ath/ath9k/xmit.c              |   51 +-
 drivers/net/wireless/b43legacy/main.c              |    2 +-
 drivers/net/wireless/brcm80211/brcmsmac/aiutils.c  |    3 +-
 drivers/net/wireless/brcm80211/brcmsmac/aiutils.h  |    2 +-
 .../net/wireless/brcm80211/brcmsmac/phy/phy_n.c    |    2 +-
 drivers/net/wireless/brcm80211/brcmutil/utils.c    |    2 +
 drivers/net/wireless/ipw2x00/ipw2200.c             |   23 +-
 drivers/net/wireless/iwlegacy/4965-mac.c           |   13 +-
 drivers/net/wireless/iwlwifi/Kconfig               |    5 +
 drivers/net/wireless/iwlwifi/Makefile              |   32 +-
 drivers/net/wireless/iwlwifi/dvm/Makefile          |   13 +
 .../net/wireless/iwlwifi/{iwl-agn.h => dvm/agn.h}  |   94 +--
 .../iwlwifi/{iwl-agn-calib.c => dvm/calib.c}       |   24 +-
 .../iwlwifi/{iwl-agn-calib.h => dvm/calib.h}       |    4 +-
 .../iwlwifi/{iwl-commands.h => dvm/commands.h}     |    7 +-
 .../iwlwifi/{iwl-debugfs.c => dvm/debugfs.c}       |   31 +-
 .../net/wireless/iwlwifi/{iwl-dev.h => dvm/dev.h}  |  148 +--
 .../iwlwifi/{iwl-agn-devices.c => dvm/devices.c}   |  178 +---
 .../net/wireless/iwlwifi/{iwl-led.c => dvm/led.c}  |    5 +-
 .../net/wireless/iwlwifi/{iwl-led.h => dvm/led.h}  |    0
 .../wireless/iwlwifi/{iwl-agn-lib.c => dvm/lib.c}  |   18 +-
 .../iwlwifi/{iwl-mac80211.c => dvm/mac80211.c}     |  144 +-
 .../net/wireless/iwlwifi/{iwl-agn.c => dvm/main.c} |  420 ++----
 .../wireless/iwlwifi/{iwl-power.c => dvm/power.c}  |   11 +-
 .../wireless/iwlwifi/{iwl-power.h => dvm/power.h}  |    2 +-
 .../wireless/iwlwifi/{iwl-agn-rs.c => dvm/rs.c}    |   50 +-
 .../wireless/iwlwifi/{iwl-agn-rs.h => dvm/rs.h}    |    3 +-
 .../wireless/iwlwifi/{iwl-agn-rx.c => dvm/rx.c}    |   10 +-
 .../iwlwifi/{iwl-agn-rxon.c => dvm/rxon.c}         |   52 +-
 .../wireless/iwlwifi/{iwl-scan.c => dvm/scan.c}    |  111 +-
 .../wireless/iwlwifi/{iwl-agn-sta.c => dvm/sta.c}  |   60 +-
 .../iwlwifi/{iwl-testmode.c => dvm/testmode.c}     |   21 +-
 .../iwlwifi/{iwl-testmode.h => dvm/testmode.h}     |    0
 .../wireless/iwlwifi/{iwl-agn-tt.c => dvm/tt.c}    |   13 +-
 .../wireless/iwlwifi/{iwl-agn-tt.h => dvm/tt.h}    |    2 +-
 .../wireless/iwlwifi/{iwl-agn-tx.c => dvm/tx.c}    |   58 +-
 .../wireless/iwlwifi/{iwl-ucode.c => dvm/ucode.c}  |   34 +-
 drivers/net/wireless/iwlwifi/iwl-config.h          |   28 +-
 drivers/net/wireless/iwlwifi/iwl-csr.h             |   28 +-
 drivers/net/wireless/iwlwifi/iwl-debug.c           |    6 +
 drivers/net/wireless/iwlwifi/iwl-debug.h           |   17 +-
 drivers/net/wireless/iwlwifi/iwl-devtrace.c        |    5 +
 drivers/net/wireless/iwlwifi/iwl-devtrace.h        |    1 +
 drivers/net/wireless/iwlwifi/iwl-drv.c             |  115 ++-
 drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c    |  900 ++++++++++++
 drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h    |  138 ++
 drivers/net/wireless/iwlwifi/iwl-eeprom-read.c     |  463 +++++++
 drivers/net/wireless/iwlwifi/iwl-eeprom-read.h     |   70 +
 drivers/net/wireless/iwlwifi/iwl-eeprom.c          | 1148 ---------------
 drivers/net/wireless/iwlwifi/iwl-eeprom.h          |  269 ----
 drivers/net/wireless/iwlwifi/iwl-io.c              |   37 +
 drivers/net/wireless/iwlwifi/iwl-io.h              |    2 +
 drivers/net/wireless/iwlwifi/iwl-notif-wait.c      |    8 +-
 drivers/net/wireless/iwlwifi/iwl-op-mode.h         |    8 +-
 drivers/net/wireless/iwlwifi/iwl-prph.h            |    2 +-
 drivers/net/wireless/iwlwifi/iwl-trans.h           |   56 +-
 .../wireless/iwlwifi/{iwl-1000.c => pcie/1000.c}   |   19 +-
 .../wireless/iwlwifi/{iwl-2000.c => pcie/2000.c}   |   22 +-
 .../wireless/iwlwifi/{iwl-5000.c => pcie/5000.c}   |   20 +-
 .../wireless/iwlwifi/{iwl-6000.c => pcie/6000.c}   |   24 +-
 .../net/wireless/iwlwifi/{iwl-cfg.h => pcie/cfg.h} |    0
 .../net/wireless/iwlwifi/{iwl-pci.c => pcie/drv.c} |    5 +-
 .../{iwl-trans-pcie-int.h => pcie/internal.h}      |   21 +-
 .../iwlwifi/{iwl-trans-pcie-rx.c => pcie/rx.c}     |   75 +-
 .../iwlwifi/{iwl-trans-pcie.c => pcie/trans.c}     |  293 ++---
 .../iwlwifi/{iwl-trans-pcie-tx.c => pcie/tx.c}     |  147 ++-
 drivers/net/wireless/libertas/cfg.c                |   39 +-
 drivers/net/wireless/libertas/dev.h                |    1 +
 drivers/net/wireless/libertas/mesh.c               |    7 +-
 drivers/net/wireless/mwifiex/init.c                |   65 +
 drivers/net/wireless/mwifiex/main.c                |    4 +-
 drivers/net/wireless/mwifiex/main.h                |   11 +-
 drivers/net/wireless/mwifiex/scan.c                |   59 +-
 drivers/net/wireless/orinoco/cfg.c                 |    9 +-
 drivers/net/wireless/rt2x00/rt2800.h               |    8 +
 drivers/net/wireless/rt2x00/rt2800lib.c            |   27 +-
 drivers/net/wireless/rt2x00/rt2800pci.c            |    1 +
 drivers/net/wireless/rt2x00/rt2800usb.c            |    3 +-
 drivers/net/wireless/rt2x00/rt2x00dev.c            |    2 +
 drivers/net/wireless/rt2x00/rt2x00mac.c            |   14 +-
 drivers/net/wireless/ti/Kconfig                    |    1 +
 drivers/net/wireless/ti/Makefile                   |    1 +
 drivers/net/wireless/ti/wl12xx/Makefile            |    2 +-
 drivers/net/wireless/ti/wl12xx/acx.h               |  237 ++++
 drivers/net/wireless/ti/wl12xx/cmd.c               |    8 +-
 drivers/net/wireless/ti/wl12xx/debugfs.c           |  243 ++++
 drivers/net/wireless/ti/wl12xx/debugfs.h           |   28 +
 drivers/net/wireless/ti/wl12xx/main.c              |  242 +++-
 drivers/net/wireless/ti/wl12xx/wl12xx.h            |    8 +
 drivers/net/wireless/ti/wl18xx/Kconfig             |    7 +
 drivers/net/wireless/ti/wl18xx/Makefile            |    3 +
 drivers/net/wireless/ti/wl18xx/acx.c               |  111 ++
 drivers/net/wireless/ti/wl18xx/acx.h               |  291 ++++
 drivers/net/wireless/ti/wl18xx/conf.h              |   92 ++
 drivers/net/wireless/ti/wl18xx/debugfs.c           |  403 ++++++
 drivers/net/wireless/ti/wl18xx/debugfs.h           |   28 +
 drivers/net/wireless/ti/wl18xx/io.c                |   60 +
 drivers/net/wireless/ti/wl18xx/io.h                |   28 +
 drivers/net/wireless/ti/wl18xx/main.c              | 1463 ++++++++++++++++++++
 drivers/net/wireless/ti/wl18xx/reg.h               |  191 +++
 drivers/net/wireless/ti/wl18xx/tx.c                |  127 ++
 drivers/net/wireless/ti/wl18xx/tx.h                |   46 +
 drivers/net/wireless/ti/wl18xx/wl18xx.h            |   88 ++
 drivers/net/wireless/ti/wlcore/acx.c               |    8 +-
 drivers/net/wireless/ti/wlcore/acx.h               |  254 +----
 drivers/net/wireless/ti/wlcore/boot.c              |   57 +-
 drivers/net/wireless/ti/wlcore/boot.h              |    1 +
 drivers/net/wireless/ti/wlcore/cmd.c               |   62 +-
 drivers/net/wireless/ti/wlcore/cmd.h               |   13 +-
 drivers/net/wireless/ti/wlcore/conf.h              |   93 +-
 drivers/net/wireless/ti/wlcore/debugfs.c           |  390 ++----
 drivers/net/wireless/ti/wlcore/debugfs.h           |   87 ++
 drivers/net/wireless/ti/wlcore/event.c             |   24 +-
 drivers/net/wireless/ti/wlcore/hw_ops.h            |   78 ++
 drivers/net/wireless/ti/wlcore/init.c              |    3 +
 drivers/net/wireless/ti/wlcore/main.c              |  504 ++++----
 drivers/net/wireless/ti/wlcore/ps.c                |   21 +-
 drivers/net/wireless/ti/wlcore/rx.c                |   11 +-
 drivers/net/wireless/ti/wlcore/rx.h                |    7 +-
 drivers/net/wireless/ti/wlcore/scan.c              |   52 +-
 drivers/net/wireless/ti/wlcore/scan.h              |   19 +-
 drivers/net/wireless/ti/wlcore/sdio.c              |   35 +-
 drivers/net/wireless/ti/wlcore/tx.c                |  185 ++-
 drivers/net/wireless/ti/wlcore/tx.h                |   49 +-
 drivers/net/wireless/ti/wlcore/wlcore.h            |   70 +-
 .../wireless/ti/wlcore/{wl12xx.h => wlcore_i.h}    |   44 +-
 drivers/nfc/pn533.c                                |  662 ++++++++--
 drivers/nfc/pn544_hci.c                            |   10 +-
 drivers/ssb/b43_pci_bridge.c                       |    1 +
 drivers/ssb/scan.c                                 |    2 +
 include/linux/nfc.h                                |   12 +
 include/linux/nl80211.h                            |    8 +
 include/linux/ssb/ssb.h                            |    1 +
 include/net/cfg80211.h                             |   45 +-
 include/net/mac80211.h                             |   44 +-
 include/net/nfc/hci.h                              |    3 +-
 include/net/nfc/nfc.h                              |   14 +-
 include/net/nfc/shdlc.h                            |    3 +-
 net/core/net-sysfs.c                               |   74 -
 net/mac80211/Makefile                              |    1 -
 net/mac80211/agg-rx.c                              |   30 +-
 net/mac80211/agg-tx.c                              |  109 +--
 net/mac80211/cfg.c                                 |  579 +++++----
 net/mac80211/chan.c                                |    4 +
 net/mac80211/debugfs_netdev.c                      |    3 +-
 net/mac80211/ibss.c                                |  114 +-
 net/mac80211/ieee80211_i.h                         |   92 +-
 net/mac80211/iface.c                               |   42 +-
 net/mac80211/main.c                                |   17 +-
 net/mac80211/mesh.c                                |    3 +-
 net/mac80211/mesh_hwmp.c                           |    2 +-
 net/mac80211/mesh_pathtbl.c                        |    2 +-
 net/mac80211/mesh_plink.c                          |    2 +-
 net/mac80211/mesh_sync.c                           |    2 +-
 net/mac80211/mlme.c                                |  189 ++--
 net/mac80211/offchannel.c                          |  280 ++++-
 net/mac80211/pm.c                                  |    1 +
 net/mac80211/rx.c                                  |   22 +-
 net/mac80211/scan.c                                |    4 +-
 net/mac80211/sta_info.c                            |   23 +-
 net/mac80211/status.c                              |   30 +-
 net/mac80211/tkip.c                                |   21 +-
 net/mac80211/tx.c                                  |   14 +-
 net/mac80211/util.c                                |  117 +-
 net/mac80211/work.c                                |  370 -----
 net/nfc/core.c                                     |  119 ++-
 net/nfc/hci/core.c                                 |   13 +-
 net/nfc/hci/shdlc.c                                |    6 +-
 net/nfc/llcp/commands.c                            |   54 +-
 net/nfc/llcp/llcp.c                                |  421 ++++---
 net/nfc/llcp/llcp.h                                |   26 +-
 net/nfc/llcp/sock.c                                |   47 +-
 net/nfc/nci/core.c                                 |   15 +-
 net/nfc/netlink.c                                  |   81 +-
 net/nfc/nfc.h                                      |   12 +-
 net/rfkill/core.c                                  |    2 +-
 net/wireless/Kconfig                               |   14 -
 net/wireless/chan.c                                |   55 +-
 net/wireless/core.h                                |   12 +-
 net/wireless/mesh.c                                |   91 ++-
 net/wireless/mlme.c                                |    2 -
 net/wireless/nl80211.c                             |  129 ++-
 net/wireless/wext-compat.c                         |   21 +-
 net/wireless/wext-sme.c                            |   10 +-
 219 files changed, 12126 insertions(+), 7378 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath9k/antenna.c
 create mode 100644 drivers/net/wireless/ath/ath9k/link.c
 create mode 100644 drivers/net/wireless/iwlwifi/dvm/Makefile
 rename drivers/net/wireless/iwlwifi/{iwl-agn.h => dvm/agn.h} (81%)
 rename drivers/net/wireless/iwlwifi/{iwl-agn-calib.c => dvm/calib.c} (98%)
 rename drivers/net/wireless/iwlwifi/{iwl-agn-calib.h => dvm/calib.h} (98%)
 rename drivers/net/wireless/iwlwifi/{iwl-commands.h => dvm/commands.h} (99%)
 rename drivers/net/wireless/iwlwifi/{iwl-debugfs.c => dvm/debugfs.c} (99%)
 rename drivers/net/wireless/iwlwifi/{iwl-dev.h => dvm/dev.h} (84%)
 rename drivers/net/wireless/iwlwifi/{iwl-agn-devices.c => dvm/devices.c} (78%)
 rename drivers/net/wireless/iwlwifi/{iwl-led.c => dvm/led.c} (99%)
 rename drivers/net/wireless/iwlwifi/{iwl-led.h => dvm/led.h} (100%)
 rename drivers/net/wireless/iwlwifi/{iwl-agn-lib.c => dvm/lib.c} (98%)
 rename drivers/net/wireless/iwlwifi/{iwl-mac80211.c => dvm/mac80211.c} (92%)
 rename drivers/net/wireless/iwlwifi/{iwl-agn.c => dvm/main.c} (87%)
 rename drivers/net/wireless/iwlwifi/{iwl-power.c => dvm/power.c} (99%)
 rename drivers/net/wireless/iwlwifi/{iwl-power.h => dvm/power.h} (98%)
 rename drivers/net/wireless/iwlwifi/{iwl-agn-rs.c => dvm/rs.c} (98%)
 rename drivers/net/wireless/iwlwifi/{iwl-agn-rs.h => dvm/rs.h} (99%)
 rename drivers/net/wireless/iwlwifi/{iwl-agn-rx.c => dvm/rx.c} (99%)
 rename drivers/net/wireless/iwlwifi/{iwl-agn-rxon.c => dvm/rxon.c} (97%)
 rename drivers/net/wireless/iwlwifi/{iwl-scan.c => dvm/scan.c} (94%)
 rename drivers/net/wireless/iwlwifi/{iwl-agn-sta.c => dvm/sta.c} (97%)
 rename drivers/net/wireless/iwlwifi/{iwl-testmode.c => dvm/testmode.c} (99%)
 rename drivers/net/wireless/iwlwifi/{iwl-testmode.h => dvm/testmode.h} (100%)
 rename drivers/net/wireless/iwlwifi/{iwl-agn-tt.c => dvm/tt.c} (99%)
 rename drivers/net/wireless/iwlwifi/{iwl-agn-tt.h => dvm/tt.h} (99%)
 rename drivers/net/wireless/iwlwifi/{iwl-agn-tx.c => dvm/tx.c} (96%)
 rename drivers/net/wireless/iwlwifi/{iwl-ucode.c => dvm/ucode.c} (93%)
 create mode 100644 drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
 create mode 100644 drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h
 create mode 100644 drivers/net/wireless/iwlwifi/iwl-eeprom-read.c
 create mode 100644 drivers/net/wireless/iwlwifi/iwl-eeprom-read.h
 delete mode 100644 drivers/net/wireless/iwlwifi/iwl-eeprom.c
 delete mode 100644 drivers/net/wireless/iwlwifi/iwl-eeprom.h
 rename drivers/net/wireless/iwlwifi/{iwl-1000.c => pcie/1000.c} (89%)
 rename drivers/net/wireless/iwlwifi/{iwl-2000.c => pcie/2000.c} (92%)
 rename drivers/net/wireless/iwlwifi/{iwl-5000.c => pcie/5000.c} (90%)
 rename drivers/net/wireless/iwlwifi/{iwl-6000.c => pcie/6000.c} (93%)
 rename drivers/net/wireless/iwlwifi/{iwl-cfg.h => pcie/cfg.h} (100%)
 rename drivers/net/wireless/iwlwifi/{iwl-pci.c => pcie/drv.c} (99%)
 rename drivers/net/wireless/iwlwifi/{iwl-trans-pcie-int.h => pcie/internal.h} (95%)
 rename drivers/net/wireless/iwlwifi/{iwl-trans-pcie-rx.c => pcie/rx.c} (96%)
 rename drivers/net/wireless/iwlwifi/{iwl-trans-pcie.c => pcie/trans.c} (91%)
 rename drivers/net/wireless/iwlwifi/{iwl-trans-pcie-tx.c => pcie/tx.c} (88%)
 create mode 100644 drivers/net/wireless/ti/wl12xx/debugfs.c
 create mode 100644 drivers/net/wireless/ti/wl12xx/debugfs.h
 create mode 100644 drivers/net/wireless/ti/wl18xx/Kconfig
 create mode 100644 drivers/net/wireless/ti/wl18xx/Makefile
 create mode 100644 drivers/net/wireless/ti/wl18xx/acx.c
 create mode 100644 drivers/net/wireless/ti/wl18xx/acx.h
 create mode 100644 drivers/net/wireless/ti/wl18xx/conf.h
 create mode 100644 drivers/net/wireless/ti/wl18xx/debugfs.c
 create mode 100644 drivers/net/wireless/ti/wl18xx/debugfs.h
 create mode 100644 drivers/net/wireless/ti/wl18xx/io.c
 create mode 100644 drivers/net/wireless/ti/wl18xx/io.h
 create mode 100644 drivers/net/wireless/ti/wl18xx/main.c
 create mode 100644 drivers/net/wireless/ti/wl18xx/reg.h
 create mode 100644 drivers/net/wireless/ti/wl18xx/tx.c
 create mode 100644 drivers/net/wireless/ti/wl18xx/tx.h
 create mode 100644 drivers/net/wireless/ti/wl18xx/wl18xx.h
 rename drivers/net/wireless/ti/wlcore/{wl12xx.h => wlcore_i.h} (95%)
 delete mode 100644 net/mac80211/work.c

-- 
John W. Linville		Someday the world will need a hero, and you
linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org			might be all we have.  Be ready.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH net 1/3] bonding:record primary when modify it via sysfs
From: Nicolas de Pesloüan @ 2012-06-12 20:05 UTC (permalink / raw)
  To: David Miller; +Cc: Jay Vosburgh, Weiping Pan, netdev
In-Reply-To: <31624.1339447734@death.nxdomain>

Le 11/06/2012 22:48, Jay Vosburgh a écrit :
> Nicolas de Pesloüan 	<nicolas.2p.debian@gmail.com>  wrote:
>
>> Le 11/06/2012 11:00, Weiping Pan a écrit :
>>> If we modify primary via sysfs and it is not a valid slave,
>>> we should record it for future use, and this behavior is the same with
>>> bond_check_params().
>>>
>>> Signed-off-by: Weiping Pan<wpan@redhat.com>
>>> ---
>>>    drivers/net/bonding/bond_sysfs.c |    8 ++++++--
>>>    1 files changed, 6 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
>>> index aef42f0..485bedb 100644
>>> --- a/drivers/net/bonding/bond_sysfs.c
>>> +++ b/drivers/net/bonding/bond_sysfs.c
>>> @@ -1082,8 +1082,12 @@ static ssize_t bonding_store_primary(struct device *d,
>>>    		}
>>>    	}
>>>
>>> -	pr_info("%s: Unable to set %.*s as primary slave.\n",
>>> -		bond->dev->name, (int)strlen(buf) - 1, buf);
>>> +	strncpy(bond->params.primary, ifname, IFNAMSIZ);
>>> +	bond->params.primary[IFNAMSIZ - 1] = 0;
>>> +
>>> +	pr_info("%s: Recording %s as primary, "
>>> +		"but it has not been enslaved to %s yet.\n",
>>> +		bond->dev->name, ifname, bond->dev->name);
>>>    out:
>>>    	write_unlock_bh(&bond->curr_slave_lock);
>>>    	read_unlock(&bond->lock);
>>
>> I like this one, because it tend to relax the current constraints one
>> should respect on the order to write into sysfs to setup bonding.
>>
>> May I suggest we have a better info message, suggesting there might have a
>> typo on the name of the primary ?
>>
>>> +	pr_info("%s: Recording %s as primary, "
>>> +		"but it has not been enslaved to %s yet. Possible typo?\n",
>>> +		bond->dev->name, ifname, bond->dev->name);
>>
>> Except from this cosmetic,
>>
>> Acked-by: Nicolas de Pesloüan<nicolas.2p.debian@free.fr>
>
> 	Agreed, except that I can go either way on the "typo" warning.
>
> Signed-off-by: Jay Vosburgh<fubar@us.ibm.com>

David,

I think this patch (http://patchwork.ozlabs.org/patch/164100/) was erroneously flagged as "Changes 
Requested". Despite my suggestion to add a "possible typo" warning, I acked the patch and so do Jay. 
We eventually decided not to add the "possible typo" warning, so the patch should be accepted.

Thanks,

	Nicolas.

^ permalink raw reply

* Re: [PATCHv2 net-next] ipv4: Add interface option to enable routing of 127.0.0.0/8
From: Thomas Graf @ 2012-06-12 19:50 UTC (permalink / raw)
  To: Rick Jones; +Cc: netdev, tgraf, David Miller
In-Reply-To: <4FD786B8.3030205@hp.com>

On Tue, Jun 12, 2012 at 11:13:12AM -0700, Rick Jones wrote:
> I'd go beyond "traditionally forbidden" and call it something
> considered fundamental.  That 127.0.0.1 (et al) can only be reached
> by entities on the same system is rather deeply ingrained in the
> collective consciousness after 30-odd years.

I absolutely agree with regard to 127.0.0.1 but I do not fully
agree with regard to 127/8 in general.

> This change would make 127/8 a de facto RFC 1918 address right?  It
> would not be publicly routable.  Are there actually entities who
> have exhausted 10/8, 172.16/12 and 192.168/16?

This is not about enabling 127/8 to become publicly routeable.
This is about enabling 127/8 for host internal routing, f.e.
virtual bridges, ifb devices, or dummy devices.

The problem with 10/8, 172.162/12 and 192.168/16 is that these
ranges are often in use by VPNs and thus unavailable. None of these
addresses are guaranteed to be available on a random system.

An example for such usage would be virtualization where you want
to assign addresses to guests which are guaranteed to be available
in host scope as well.

Yes, if someone enables this on a publicly facing interface that
will enable the possibility to violate the RFC but he might as well
do that by using a raw socket.

> Are there any other stacks which can do this, or would this be an
> "RFC 1918" network between (newer)Linux systems only?  (Assuming
> non-newer-linux-based routers would be happy with it)

AFAIK none but I could be wrong. Again, this option is not intended
to be used on any public interfaces. However, if you want to enable
this in your own private network, fine with me again.

^ permalink raw reply

* [PATCH] sfc: Use standard __{clear,set}_bit_le() functions
From: Ben Hutchings @ 2012-06-12 19:23 UTC (permalink / raw)
  To: Takuya Yoshikawa
  Cc: grundler, arnd, avi, mtosatti, linux-net-drivers, netdev,
	linux-kernel, linux-arch, kvm, takuya.yoshikawa
In-Reply-To: <20120611212901.2b4d0a17.yoshikawa.takuya@oss.ntt.co.jp>

There are now standard functions for dealing with little-endian bit
arrays, so use them instead of our own implementations.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
Please use this version instead.

Ben.

 drivers/net/ethernet/sfc/efx.c        |    4 ++--
 drivers/net/ethernet/sfc/net_driver.h |   12 ------------
 drivers/net/ethernet/sfc/nic.c        |    4 ++--
 3 files changed, 4 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index b95f2e1..ca2a348 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1976,14 +1976,14 @@ static void efx_set_rx_mode(struct net_device *net_dev)
 		netdev_for_each_mc_addr(ha, net_dev) {
 			crc = ether_crc_le(ETH_ALEN, ha->addr);
 			bit = crc & (EFX_MCAST_HASH_ENTRIES - 1);
-			set_bit_le(bit, mc_hash->byte);
+			__set_bit_le(bit, mc_hash);
 		}
 
 		/* Broadcast packets go through the multicast hash filter.
 		 * ether_crc_le() of the broadcast address is 0xbe2612ff
 		 * so we always add bit 0xff to the mask.
 		 */
-		set_bit_le(0xff, mc_hash->byte);
+		__set_bit_le(0xff, mc_hash);
 	}
 
 	if (efx->port_enabled)
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 0e57535..6f1a7f7 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -1080,18 +1080,6 @@ static inline struct efx_rx_buffer *efx_rx_buffer(struct efx_rx_queue *rx_queue,
 	return &rx_queue->buffer[index];
 }
 
-/* Set bit in a little-endian bitfield */
-static inline void set_bit_le(unsigned nr, unsigned char *addr)
-{
-	addr[nr / 8] |= (1 << (nr % 8));
-}
-
-/* Clear bit in a little-endian bitfield */
-static inline void clear_bit_le(unsigned nr, unsigned char *addr)
-{
-	addr[nr / 8] &= ~(1 << (nr % 8));
-}
-
 
 /**
  * EFX_MAX_FRAME_LEN - calculate maximum frame length
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 4a9a5be..bb0172d 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -473,9 +473,9 @@ void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
 
 		efx_reado(efx, &reg, FR_AA_TX_CHKSM_CFG);
 		if (tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD)
-			clear_bit_le(tx_queue->queue, (void *)&reg);
+			__clear_bit_le(tx_queue->queue, &reg);
 		else
-			set_bit_le(tx_queue->queue, (void *)&reg);
+			__set_bit_le(tx_queue->queue, &reg);
 		efx_writeo(efx, &reg, FR_AA_TX_CHKSM_CFG);
 	}
 
-- 
1.7.7.6


-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply related

* Re: [PATCH] iwlwifi: re-order module_init order to prevent NULL ptr deref
From: Johannes Berg @ 2012-06-12 19:17 UTC (permalink / raw)
  To: Sasha Levin
  Cc: wey-yi.w.guy, linville, ilw, linux-wireless, netdev, linux-kernel
In-Reply-To: <1339528412-4163-1-git-send-email-levinsasha928@gmail.com>

On Tue, 2012-06-12 at 21:13 +0200, Sasha Levin wrote:
> We need to make sure iwl_drv_init is called before iwl_init, since otherwise
> iwl_init will NULL ptr deref when trying to add a new mode.
> 
> Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
> ---
>  drivers/net/wireless/iwlwifi/Makefile |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
> index 98c8f64..16e39a4 100644
> --- a/drivers/net/wireless/iwlwifi/Makefile
> +++ b/drivers/net/wireless/iwlwifi/Makefile
> @@ -1,5 +1,3 @@
> -obj-$(CONFIG_IWLDVM)	+= dvm/
> -

Thanks! I already have a patch like this in my tree, will send a pull
request soon:

http://git.kernel.org/?p=linux/kernel/git/iwlwifi/iwlwifi-next.git;a=commit;h=4b75b1e49568dd6a30a1dddc47408cc6fde55608

johannes

^ permalink raw reply

* [PATCH] iwlwifi: re-order module_init order to prevent NULL ptr deref
From: Sasha Levin @ 2012-06-12 19:13 UTC (permalink / raw)
  To: johannes.berg, wey-yi.w.guy, linville
  Cc: ilw, linux-wireless, netdev, linux-kernel, Sasha Levin

We need to make sure iwl_drv_init is called before iwl_init, since otherwise
iwl_init will NULL ptr deref when trying to add a new mode.

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 drivers/net/wireless/iwlwifi/Makefile |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 98c8f64..16e39a4 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -1,5 +1,3 @@
-obj-$(CONFIG_IWLDVM)	+= dvm/
-
 CFLAGS_iwl-devtrace.o := -I$(src)
 
 # common
@@ -14,4 +12,6 @@ iwlwifi-objs		+= pcie/1000.o pcie/2000.o pcie/5000.o pcie/6000.o
 
 iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
 
+obj-$(CONFIG_IWLDVM)    += dvm/
+
 ccflags-y += -D__CHECK_ENDIAN__ -I$(src)
-- 
1.7.8.6

^ permalink raw reply related

* Re: [PATCH net-next 4/4] 6lowpan: len field is not stored and accessed properly
From: Alexander Smirnov @ 2012-06-12 18:20 UTC (permalink / raw)
  To: Tony Cheneau; +Cc: netdev, linux-zigbee-devel
In-Reply-To: <20120611004025.6f6129ca@dualbox>

2012/6/11 Tony Cheneau <tony.cheneauh@amnesiak.org>:
> Lenght field should be encoded (and accessed) the other way around.
> As it is currently written, it could lead to interroperability issues.

What kind of "interroperability issues" can occur? Please describe it
in details, I can't read your mind. And again, can these problems be
caused by the byte-order mismatch?

>
> Also, I rewrote the code so that iphc0 argument of
> lowpan_alloc_new_frame could be removed.
> ---
>  net/ieee802154/6lowpan.c |   20 ++++++++++++--------
>  1 files changed, 12 insertions(+), 8 deletions(-)
>
> diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
> index af2f12e..b400156 100644
> --- a/net/ieee802154/6lowpan.c
> +++ b/net/ieee802154/6lowpan.c
> @@ -654,7 +654,7 @@ static void lowpan_fragment_timer_expired(unsigned
> long entry_addr) }
>
>  static struct lowpan_fragment *
> -lowpan_alloc_new_frame(struct sk_buff *skb, u8 iphc0, u8 len, u16 tag)
> +lowpan_alloc_new_frame(struct sk_buff *skb, u16 len, u16 tag)
>  {
>        struct lowpan_fragment *frame;
>
> @@ -665,7 +665,7 @@ lowpan_alloc_new_frame(struct sk_buff *skb, u8
> iphc0, u8 len, u16 tag)
>        INIT_LIST_HEAD(&frame->list);
>
> -       frame->length = (iphc0 & 7) | (len << 3);
> +       frame->length = len;
>        frame->tag = tag;
>
>        /* allocate buffer for frame assembling */
> @@ -721,13 +721,17 @@ lowpan_process_data(struct sk_buff *skb)
>        case LOWPAN_DISPATCH_FRAGN:
>        {
>                struct lowpan_fragment *frame;
> -               u8 len, offset;
> -               u16 tag;
> +               /* slen stores the rightmost 8 bits of the 11 bits
> length */
> +               u8 slen, offset;
> +               u16 len, tag;
>                bool found = false;
>
> -               len = lowpan_fetch_skb_u8(skb); /* frame length */
> +               slen = lowpan_fetch_skb_u8(skb); /* frame length */
>                tag = lowpan_fetch_skb_u16(skb);
>
> +               /* adds the 3 MSB to the 8 LSB to retrieve the 11 bits
> length */
> +               len = ((iphc0 & 7) << 8) | slen;
> +
>                /*
>                 * check if frame assembling with the same tag is
>                 * already in progress
> @@ -742,7 +746,7 @@ lowpan_process_data(struct sk_buff *skb)
>
>                /* alloc new frame structure */
>                if (!found) {
> -                       frame = lowpan_alloc_new_frame(skb, iphc0,
> len, tag);
> +                       frame = lowpan_alloc_new_frame(skb, len, tag);
>                        if (!frame)
>                                goto unlock_and_drop;
>                }
> @@ -1000,8 +1004,8 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
>        tag = fragment_tag++;
>
>        /* first fragment header */
> -       head[0] = LOWPAN_DISPATCH_FRAG1 | (payload_length & 0x7);
> -       head[1] = (payload_length >> 3) & 0xff;
> +       head[0] = LOWPAN_DISPATCH_FRAG1 | ((payload_length >> 8) &
> 0x7);
> +       head[1] = payload_length & 0xff;
>        head[2] = tag >> 8;
>        head[3] = tag & 0xff;
>
> --
> 1.7.3.4
>

^ permalink raw reply

* Re: [PATCH 4/7] usbnet: remove EVENT_DEV_OPEN flag
From: Oliver Neukum @ 2012-06-12 18:14 UTC (permalink / raw)
  To: Ming Lei
  Cc: David S. Miller, Greg Kroah-Hartman,
	netdev-u79uwXL29TY76Z2rM5mHXA, linux-usb-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1339463985-9006-5-git-send-email-tom.leiming-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Am Dienstag, 12. Juni 2012, 03:19:42 schrieb Ming Lei:
> EVENT_DEV_OPEN is introduced to mark if the interface is opened or
> not, but we already have IFF_UP to handle it, so just
> remove the flag and use IFF_UP.

When is IFF_UP cleared? The flag is tested in usbnet_resume(),
so it must be cleared before usbnet_stop() is called.

	Regards
		Oliver
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCHv2 net-next] ipv4: Add interface option to enable routing of 127.0.0.0/8
From: Rick Jones @ 2012-06-12 18:13 UTC (permalink / raw)
  To: netdev, tgraf; +Cc: David Miller
In-Reply-To: <20120612104401.GH28598@canuck.infradead.org>

On 06/12/2012 03:44 AM, Thomas Graf wrote:
> Routing of 127/8 is tradtionally forbidden, we consider
> packets from that address block martian when routing and do
> not process corresponding ARP requests.

I'd go beyond "traditionally forbidden" and call it something considered 
fundamental.  That 127.0.0.1 (et al) can only be reached by entities on 
the same system is rather deeply ingrained in the collective 
consciousness after 30-odd years.

> This is a sane default but renders a huge address space practically
> unuseable.

This change would make 127/8 a de facto RFC 1918 address right?  It 
would not be publicly routable.  Are there actually entities who have 
exhausted 10/8, 172.16/12 and 192.168/16?

Are there any other stacks which can do this, or would this be an "RFC 
1918" network between (newer)Linux systems only?  (Assuming 
non-newer-linux-based routers would be happy with it)

I cannot say that I'm all that good about practicing the preaching, but 
IPv6 cannot be held-off indefinitely.

rick jones

^ permalink raw reply

* [PATCH 7/7] netfilter: add user-space connection tracking helper infrastructure
From: pablo @ 2012-06-12 18:06 UTC (permalink / raw)
  To: netfilter-devel; +Cc: netdev
In-Reply-To: <1339524380-2707-1-git-send-email-pablo@netfilter.org>

From: Pablo Neira Ayuso <pablo@netfilter.org>

There are good reasons to supports helpers in user-space instead:

* Rapid connection tracking helper development, as developing code
  in user-space is usually faster.

* Reliability: A buggy helper does not crash the kernel. Moreover,
  we can monitor the helper process and restart it in case of problems.

* Security: Avoid complex string matching and mangling in kernel-space
  running in privileged mode. Going further, we can even think about
  running user-space helpers as a non-root process.

* Extensibility: It allows the development of very specific helpers (most
  likely non-standard proprietary protocols) that are very likely not to be
  accepted for mainline inclusion in the form of kernel-space connection
  tracking helpers.

This patch adds the infrastructure to allow the implementation of
user-space conntrack helpers by means of the new nfnetlink subsystem
`nfnetlink_cthelper' and the existing queueing infrastructure
(nfnetlink_queue).

I had to add the new hook NF_IP6_PRI_CONNTRACK_HELPER to register
ipv[4|6]_helper which results from splitting ipv[4|6]_confirm into
two pieces. This change is required not to break NAT sequence
adjustment and conntrack confirmation for traffic that is enqueued
to our user-space conntrack helpers.

Basic operation, in a few steps:

1) Register user-space helper by means of `nfct':

 nfct helper add ftp inet

 [ It must be a valid existing helper supported by conntrack-tools.

2) Add rules to enable the FTP user-space helper which is
   used to track traffic going to TCP port 21.

For locally generated packets:

 iptables -I OUTPUT -t raw -p tcp --dport 21 -j CT --helper ftp

For non-locally generated packets:

 iptables -I PREROUTING -t raw -p tcp --dport 21 -j CT --helper ftp

3) Run the test conntrackd in helper mode (see example files under
   doc/helper/conntrackd.conf

 conntrackd

4) Generate FTP traffic going, if everything is OK, then conntrackd
   should create expectations (you can check that with `conntrack':

 conntrack -E expect

    [NEW] 301 proto=6 src=192.168.1.136 dst=130.89.148.12 sport=0 dport=54037 mask-src=255.255.255.255 mask-dst=255.255.255.255 sport=0 dport=65535 master-src=192.168.1.136 master-dst=130.89.148.12 sport=57127 dport=21 class=0 helper=ftp
[DESTROY] 301 proto=6 src=192.168.1.136 dst=130.89.148.12 sport=0 dport=54037 mask-src=255.255.255.255 mask-dst=255.255.255.255 sport=0 dport=65535 master-src=192.168.1.136 master-dst=130.89.148.12 sport=57127 dport=21 class=0 helper=ftp

This confirms that our test helper is receiving packets including the
conntrack information, and adding expectations in kernel-space.

The user-space helper can also store its private tracking information
in the conntrack structure in the kernel via the CTA_HELP_INFO. The
kernel will consider this a binary blob whose layout is unknown. This
information will be included in the information that is transfered
to user-space via glue code that integrates nfnetlink_queue and
ctnetlink.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/linux/netfilter/Kbuild                 |    1 +
 include/linux/netfilter/nfnetlink.h            |    3 +-
 include/linux/netfilter/nfnetlink_cthelper.h   |   55 ++
 include/linux/netfilter_ipv4.h                 |    1 +
 include/linux/netfilter_ipv6.h                 |    1 +
 include/net/netfilter/nf_conntrack_helper.h    |   11 +
 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c |   49 +-
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c |   49 +-
 net/netfilter/Kconfig                          |    8 +
 net/netfilter/Makefile                         |    1 +
 net/netfilter/nf_conntrack_helper.c            |   21 +-
 net/netfilter/nfnetlink_cthelper.c             |  674 ++++++++++++++++++++++++
 12 files changed, 848 insertions(+), 26 deletions(-)
 create mode 100644 include/linux/netfilter/nfnetlink_cthelper.h
 create mode 100644 net/netfilter/nfnetlink_cthelper.c

diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
index 1697036..874ae8f 100644
--- a/include/linux/netfilter/Kbuild
+++ b/include/linux/netfilter/Kbuild
@@ -10,6 +10,7 @@ header-y += nfnetlink.h
 header-y += nfnetlink_acct.h
 header-y += nfnetlink_compat.h
 header-y += nfnetlink_conntrack.h
+header-y += nfnetlink_cthelper.h
 header-y += nfnetlink_cttimeout.h
 header-y += nfnetlink_log.h
 header-y += nfnetlink_queue.h
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
index a1048c1..18341cd 100644
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -50,7 +50,8 @@ struct nfgenmsg {
 #define NFNL_SUBSYS_IPSET		6
 #define NFNL_SUBSYS_ACCT		7
 #define NFNL_SUBSYS_CTNETLINK_TIMEOUT	8
-#define NFNL_SUBSYS_COUNT		9
+#define NFNL_SUBSYS_CTHELPER		9
+#define NFNL_SUBSYS_COUNT		10
 
 #ifdef __KERNEL__
 
diff --git a/include/linux/netfilter/nfnetlink_cthelper.h b/include/linux/netfilter/nfnetlink_cthelper.h
new file mode 100644
index 0000000..33659f6
--- /dev/null
+++ b/include/linux/netfilter/nfnetlink_cthelper.h
@@ -0,0 +1,55 @@
+#ifndef _NFNL_CTHELPER_H_
+#define _NFNL_CTHELPER_H_
+
+#define NFCT_HELPER_STATUS_DISABLED	0
+#define NFCT_HELPER_STATUS_ENABLED	1
+
+enum nfnl_acct_msg_types {
+	NFNL_MSG_CTHELPER_NEW,
+	NFNL_MSG_CTHELPER_GET,
+	NFNL_MSG_CTHELPER_DEL,
+	NFNL_MSG_CTHELPER_MAX
+};
+
+enum nfnl_cthelper_type {
+	NFCTH_UNSPEC,
+	NFCTH_NAME,
+	NFCTH_TUPLE,
+	NFCTH_QUEUE_NUM,
+	NFCTH_POLICY,
+	NFCTH_PRIV_DATA_LEN,
+	NFCTH_STATUS,
+	__NFCTH_MAX
+};
+#define NFCTH_MAX (__NFCTH_MAX - 1)
+
+enum nfnl_cthelper_policy_type {
+	NFCTH_POLICY_SET_UNSPEC,
+	NFCTH_POLICY_SET_NUM,
+	NFCTH_POLICY_SET,
+	NFCTH_POLICY_SET1	= NFCTH_POLICY_SET,
+	NFCTH_POLICY_SET2,
+	NFCTH_POLICY_SET3,
+	NFCTH_POLICY_SET4,
+	__NFCTH_POLICY_SET_MAX
+};
+#define NFCTH_POLICY_SET_MAX (__NFCTH_POLICY_SET_MAX - 1)
+
+enum nfnl_cthelper_pol_type {
+	NFCTH_POLICY_UNSPEC,
+	NFCTH_POLICY_NAME,
+	NFCTH_POLICY_EXPECT_MAX,
+	NFCTH_POLICY_EXPECT_TIMEOUT,
+	__NFCTH_POLICY_MAX
+};
+#define NFCTH_POLICY_MAX (__NFCTH_POLICY_MAX - 1)
+
+enum nfnl_cthelper_tuple_type {
+	NFCTH_TUPLE_UNSPEC,
+	NFCTH_TUPLE_L3PROTONUM,
+	NFCTH_TUPLE_L4PROTONUM,
+	__NFCTH_TUPLE_MAX,
+};
+#define NFCTH_TUPLE_MAX (__NFCTH_TUPLE_MAX - 1)
+
+#endif /* _NFNL_CTHELPER_H */
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index fa0946c..e2b1280 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -66,6 +66,7 @@ enum nf_ip_hook_priorities {
 	NF_IP_PRI_SECURITY = 50,
 	NF_IP_PRI_NAT_SRC = 100,
 	NF_IP_PRI_SELINUX_LAST = 225,
+	NF_IP_PRI_CONNTRACK_HELPER = 300,
 	NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
 	NF_IP_PRI_LAST = INT_MAX,
 };
diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
index 57c0251..7c8a513 100644
--- a/include/linux/netfilter_ipv6.h
+++ b/include/linux/netfilter_ipv6.h
@@ -71,6 +71,7 @@ enum nf_ip6_hook_priorities {
 	NF_IP6_PRI_SECURITY = 50,
 	NF_IP6_PRI_NAT_SRC = 100,
 	NF_IP6_PRI_SELINUX_LAST = 225,
+	NF_IP6_PRI_CONNTRACK_HELPER = 300,
 	NF_IP6_PRI_LAST = INT_MAX,
 };
 
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 84b24c3..9aad956 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -15,6 +15,11 @@
 
 struct module;
 
+enum nf_ct_helper_flags {
+	NF_CT_HELPER_F_USERSPACE	= (1 << 0),
+	NF_CT_HELPER_F_CONFIGURED	= (1 << 1),
+};
+
 #define NF_CT_HELPER_NAME_LEN	16
 
 struct nf_conntrack_helper {
@@ -42,6 +47,9 @@ struct nf_conntrack_helper {
 	int (*from_nlattr)(struct nlattr *attr, struct nf_conn *ct);
 	int (*to_nlattr)(struct sk_buff *skb, const struct nf_conn *ct);
 	unsigned int expect_class_max;
+
+	unsigned int flags;
+	unsigned int queue_num;		/* For user-space helpers. */
 };
 
 extern struct nf_conntrack_helper *
@@ -96,4 +104,7 @@ nf_ct_helper_expectfn_find_by_name(const char *name);
 struct nf_ct_helper_expectfn *
 nf_ct_helper_expectfn_find_by_symbol(const void *symbol);
 
+extern struct hlist_head *nf_ct_helper_hash;
+extern unsigned int nf_ct_helper_hsize;
+
 #endif /*_NF_CONNTRACK_HELPER_H*/
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index d79b961..8227edc 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -95,11 +95,11 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
 	return NF_ACCEPT;
 }
 
-static unsigned int ipv4_confirm(unsigned int hooknum,
-				 struct sk_buff *skb,
-				 const struct net_device *in,
-				 const struct net_device *out,
-				 int (*okfn)(struct sk_buff *))
+static unsigned int ipv4_helper(unsigned int hooknum,
+				struct sk_buff *skb,
+				const struct net_device *in,
+				const struct net_device *out,
+				int (*okfn)(struct sk_buff *))
 {
 	struct nf_conn *ct;
 	enum ip_conntrack_info ctinfo;
@@ -110,24 +110,38 @@ static unsigned int ipv4_confirm(unsigned int hooknum,
 	/* This is where we call the helper: as the packet goes out. */
 	ct = nf_ct_get(skb, &ctinfo);
 	if (!ct || ctinfo == IP_CT_RELATED_REPLY)
-		goto out;
+		return NF_ACCEPT;
 
 	help = nfct_help(ct);
 	if (!help)
-		goto out;
+		return NF_ACCEPT;
 
 	/* rcu_read_lock()ed by nf_hook_slow */
 	helper = rcu_dereference(help->helper);
 	if (!helper)
-		goto out;
+		return NF_ACCEPT;
 
 	ret = helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
 			   ct, ctinfo);
-	if (ret != NF_ACCEPT) {
+	if (ret != NF_ACCEPT && (ret & NF_VERDICT_MASK) != NF_QUEUE) {
 		nf_log_packet(NFPROTO_IPV4, hooknum, skb, in, out, NULL,
 			      "nf_ct_%s: dropping packet", helper->name);
-		return ret;
 	}
+	return ret;
+}
+
+static unsigned int ipv4_confirm(unsigned int hooknum,
+				 struct sk_buff *skb,
+				 const struct net_device *in,
+				 const struct net_device *out,
+				 int (*okfn)(struct sk_buff *))
+{
+	struct nf_conn *ct;
+	enum ip_conntrack_info ctinfo;
+
+	ct = nf_ct_get(skb, &ctinfo);
+	if (!ct || ctinfo == IP_CT_RELATED_REPLY)
+		return NF_ACCEPT;
 
 	/* adjust seqs for loopback traffic only in outgoing direction */
 	if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) &&
@@ -140,7 +154,6 @@ static unsigned int ipv4_confirm(unsigned int hooknum,
 			return NF_DROP;
 		}
 	}
-out:
 	/* We've seen it coming out the other side: confirm it */
 	return nf_conntrack_confirm(skb);
 }
@@ -185,6 +198,13 @@ static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
 		.priority	= NF_IP_PRI_CONNTRACK,
 	},
 	{
+		.hook		= ipv4_helper,
+		.owner		= THIS_MODULE,
+		.pf		= NFPROTO_IPV4,
+		.hooknum	= NF_INET_POST_ROUTING,
+		.priority	= NF_IP_PRI_CONNTRACK_HELPER,
+	},
+	{
 		.hook		= ipv4_confirm,
 		.owner		= THIS_MODULE,
 		.pf		= NFPROTO_IPV4,
@@ -192,6 +212,13 @@ static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
 		.priority	= NF_IP_PRI_CONNTRACK_CONFIRM,
 	},
 	{
+		.hook		= ipv4_helper,
+		.owner		= THIS_MODULE,
+		.pf		= NFPROTO_IPV4,
+		.hooknum	= NF_INET_LOCAL_IN,
+		.priority	= NF_IP_PRI_CONNTRACK_HELPER,
+	},
+	{
 		.hook		= ipv4_confirm,
 		.owner		= THIS_MODULE,
 		.pf		= NFPROTO_IPV4,
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index fca10da..b656d06 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -143,11 +143,11 @@ static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
 	return NF_ACCEPT;
 }
 
-static unsigned int ipv6_confirm(unsigned int hooknum,
-				 struct sk_buff *skb,
-				 const struct net_device *in,
-				 const struct net_device *out,
-				 int (*okfn)(struct sk_buff *))
+static unsigned int ipv6_helper(unsigned int hooknum,
+				struct sk_buff *skb,
+				const struct net_device *in,
+				const struct net_device *out,
+				int (*okfn)(struct sk_buff *))
 {
 	struct nf_conn *ct;
 	const struct nf_conn_help *help;
@@ -161,15 +161,15 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
 	/* This is where we call the helper: as the packet goes out. */
 	ct = nf_ct_get(skb, &ctinfo);
 	if (!ct || ctinfo == IP_CT_RELATED_REPLY)
-		goto out;
+		return NF_ACCEPT;
 
 	help = nfct_help(ct);
 	if (!help)
-		goto out;
+		return NF_ACCEPT;
 	/* rcu_read_lock()ed by nf_hook_slow */
 	helper = rcu_dereference(help->helper);
 	if (!helper)
-		goto out;
+		return NF_ACCEPT;
 
 	protoff = nf_ct_ipv6_skip_exthdr(skb, extoff, &pnum,
 					 skb->len - extoff);
@@ -179,12 +179,27 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
 	}
 
 	ret = helper->help(skb, protoff, ct, ctinfo);
-	if (ret != NF_ACCEPT) {
+	if (ret != NF_ACCEPT && (ret & NF_VERDICT_MASK) != NF_QUEUE) {
 		nf_log_packet(NFPROTO_IPV6, hooknum, skb, in, out, NULL,
 			      "nf_ct_%s: dropping packet", helper->name);
 		return ret;
 	}
-out:
+	return ret;
+}
+
+static unsigned int ipv6_confirm(unsigned int hooknum,
+				 struct sk_buff *skb,
+				 const struct net_device *in,
+				 const struct net_device *out,
+				 int (*okfn)(struct sk_buff *))
+{
+	struct nf_conn *ct;
+	enum ip_conntrack_info ctinfo;
+
+	ct = nf_ct_get(skb, &ctinfo);
+	if (!ct || ctinfo == IP_CT_RELATED_REPLY)
+		return NF_ACCEPT;
+
 	/* We've seen it coming out the other side: confirm it */
 	return nf_conntrack_confirm(skb);
 }
@@ -254,6 +269,13 @@ static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
 		.priority	= NF_IP6_PRI_CONNTRACK,
 	},
 	{
+		.hook		= ipv6_helper,
+		.owner		= THIS_MODULE,
+		.pf		= NFPROTO_IPV6,
+		.hooknum	= NF_INET_POST_ROUTING,
+		.priority	= NF_IP6_PRI_CONNTRACK_HELPER,
+	},
+	{
 		.hook		= ipv6_confirm,
 		.owner		= THIS_MODULE,
 		.pf		= NFPROTO_IPV6,
@@ -261,6 +283,13 @@ static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
 		.priority	= NF_IP6_PRI_LAST,
 	},
 	{
+		.hook		= ipv6_helper,
+		.owner		= THIS_MODULE,
+		.pf		= NFPROTO_IPV6,
+		.hooknum	= NF_INET_LOCAL_IN,
+		.priority	= NF_IP6_PRI_CONNTRACK_HELPER,
+	},
+	{
 		.hook		= ipv6_confirm,
 		.owner		= THIS_MODULE,
 		.pf		= NFPROTO_IPV6,
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 209c1ed..aae6c62 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -12,6 +12,14 @@ tristate "Netfilter NFACCT over NFNETLINK interface"
 	  If this option is enabled, the kernel will include support
 	  for extended accounting via NFNETLINK.
 
+config NETFILTER_NETLINK_CTHELPER
+tristate "Netfilter CTHELPER over NFNETLINK interface"
+	depends on NETFILTER_ADVANCED
+	select NETFILTER_NETLINK
+	help
+	  If this option is enabled, the kernel will include support
+	  for user-space connection tracking helpers via NFNETLINK.
+
 config NETFILTER_NETLINK_QUEUE
 	tristate "Netfilter NFQUEUE over NFNETLINK interface"
 	depends on NETFILTER_ADVANCED
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 4e7960c..2f3bc0f 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_NETFILTER) = netfilter.o
 
 obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
 obj-$(CONFIG_NETFILTER_NETLINK_ACCT) += nfnetlink_acct.o
+obj-$(CONFIG_NETFILTER_NETLINK_CTHELPER) += nfnetlink_cthelper.o
 obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
 obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
 
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 9c18ecb..2918ec2 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -30,8 +30,10 @@
 #include <net/netfilter/nf_conntrack_extend.h>
 
 static DEFINE_MUTEX(nf_ct_helper_mutex);
-static struct hlist_head *nf_ct_helper_hash __read_mostly;
-static unsigned int nf_ct_helper_hsize __read_mostly;
+struct hlist_head *nf_ct_helper_hash __read_mostly;
+EXPORT_SYMBOL_GPL(nf_ct_helper_hash);
+unsigned int nf_ct_helper_hsize __read_mostly;
+EXPORT_SYMBOL_GPL(nf_ct_helper_hsize);
 static unsigned int nf_ct_helper_count __read_mostly;
 
 static bool nf_ct_auto_assign_helper __read_mostly = true;
@@ -322,6 +324,9 @@ EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_symbol);
 
 int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
 {
+	int ret = 0;
+	struct nf_conntrack_helper *cur;
+	struct hlist_node *n;
 	unsigned int h = helper_hash(&me->tuple);
 
 	BUG_ON(me->expect_policy == NULL);
@@ -329,11 +334,19 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
 	BUG_ON(strlen(me->name) > NF_CT_HELPER_NAME_LEN - 1);
 
 	mutex_lock(&nf_ct_helper_mutex);
+	hlist_for_each_entry(cur, n, &nf_ct_helper_hash[h], hnode) {
+		if (strncmp(cur->name, me->name, NF_CT_HELPER_NAME_LEN) == 0 &&
+		    cur->tuple.src.l3num == me->tuple.src.l3num &&
+		    cur->tuple.dst.protonum == me->tuple.dst.protonum) {
+			ret = -EEXIST;
+			goto out;
+		}
+	}
 	hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]);
 	nf_ct_helper_count++;
+out:
 	mutex_unlock(&nf_ct_helper_mutex);
-
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_helper_register);
 
diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c
new file mode 100644
index 0000000..f399b46
--- /dev/null
+++ b/net/netfilter/nfnetlink_cthelper.c
@@ -0,0 +1,674 @@
+/*
+ * (C) 2012 Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation (or any later at your option).
+ *
+ * This software has been sponsored by Vyatta Inc. <http://www.vyatta.com>
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/rculist.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <net/netlink.h>
+#include <net/sock.h>
+
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
+
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+#include <linux/netfilter/nfnetlink_cthelper.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
+MODULE_DESCRIPTION("nfnl_cthelper: User-space connection tracking helpers");
+
+static int
+nfnl_userspace_cthelper(struct sk_buff *skb, unsigned int protoff,
+			struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+{
+	const struct nf_conn_help *help;
+	struct nf_conntrack_helper *helper;
+
+	help = nfct_help(ct);
+	if (help == NULL)
+		return NF_DROP;
+
+	/* rcu_read_lock()ed by nf_hook_slow */
+	helper = rcu_dereference(help->helper);
+	if (helper == NULL)
+		return NF_DROP;
+
+	/* This is an user-space helper not yet configured, skip. */
+	if ((helper->flags &
+	    (NF_CT_HELPER_F_USERSPACE | NF_CT_HELPER_F_CONFIGURED)) ==
+	     NF_CT_HELPER_F_USERSPACE)
+		return NF_ACCEPT;
+
+	/* If the user-space helper is not available, don't block traffic. */
+	return NF_QUEUE_NR(helper->queue_num) | NF_VERDICT_FLAG_QUEUE_BYPASS;
+}
+
+static const struct nla_policy nfnl_cthelper_tuple_pol[NFCTH_TUPLE_MAX+1] = {
+	[NFCTH_TUPLE_L3PROTONUM] = { .type = NLA_U16, },
+	[NFCTH_TUPLE_L4PROTONUM] = { .type = NLA_U8, },
+};
+
+static int
+nfnl_cthelper_parse_tuple(struct nf_conntrack_tuple *tuple,
+			  const struct nlattr *attr)
+{
+	struct nlattr *tb[NFCTH_TUPLE_MAX+1];
+
+	nla_parse_nested(tb, NFCTH_TUPLE_MAX, attr, nfnl_cthelper_tuple_pol);
+
+	if (!tb[NFCTH_TUPLE_L3PROTONUM] || !tb[NFCTH_TUPLE_L4PROTONUM])
+		return -EINVAL;
+
+	tuple->src.l3num = ntohs(nla_get_u16(tb[NFCTH_TUPLE_L3PROTONUM]));
+	tuple->dst.protonum = nla_get_u8(tb[NFCTH_TUPLE_L4PROTONUM]);
+
+	return 0;
+}
+
+static int
+nfnl_cthelper_from_nlattr(struct nlattr *attr, struct nf_conn *ct)
+{
+	const struct nf_conn_help *help = nfct_help(ct);
+
+	if (help->helper->data_len == 0)
+		return -EINVAL;
+
+	memcpy(&help->data, nla_data(attr), help->helper->data_len);
+	return 0;
+}
+
+static int
+nfnl_cthelper_to_nlattr(struct sk_buff *skb, const struct nf_conn *ct)
+{
+	const struct nf_conn_help *help = nfct_help(ct);
+
+	if (help->helper->data_len &&
+	    nla_put(skb, CTA_HELP_INFO, help->helper->data_len, &help->data))
+		goto nla_put_failure;
+
+	return 0;
+
+nla_put_failure:
+	return -ENOSPC;
+}
+
+static const struct nla_policy nfnl_cthelper_expect_pol[NFCTH_POLICY_MAX+1] = {
+	[NFCTH_POLICY_NAME] = { .type = NLA_NUL_STRING,
+				.len = NF_CT_HELPER_NAME_LEN-1 },
+	[NFCTH_POLICY_EXPECT_MAX] = { .type = NLA_U32, },
+	[NFCTH_POLICY_EXPECT_TIMEOUT] = { .type = NLA_U32, },
+};
+
+static int
+nfnl_cthelper_expect_policy(struct nf_conntrack_expect_policy *expect_policy,
+			    const struct nlattr *attr)
+{
+	struct nlattr *tb[NFCTH_POLICY_MAX+1];
+
+	nla_parse_nested(tb, NFCTH_POLICY_MAX, attr, nfnl_cthelper_expect_pol);
+
+	if (!tb[NFCTH_POLICY_NAME] ||
+	    !tb[NFCTH_POLICY_EXPECT_MAX] ||
+	    !tb[NFCTH_POLICY_EXPECT_TIMEOUT])
+		return -EINVAL;
+
+	strncpy(expect_policy->name,
+		nla_data(tb[NFCTH_POLICY_NAME]), NF_CT_HELPER_NAME_LEN);
+	expect_policy->max_expected =
+		ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_MAX]));
+	expect_policy->timeout =
+		ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_TIMEOUT]));
+
+	return 0;
+}
+
+static const struct nla_policy
+nfnl_cthelper_expect_policy_set[NFCTH_POLICY_SET_MAX+1] = {
+	[NFCTH_POLICY_SET_NUM] = { .type = NLA_U32, },
+};
+
+static int
+nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper,
+				  const struct nlattr *attr)
+{
+	int i, ret;
+	struct nf_conntrack_expect_policy *expect_policy;
+	struct nlattr *tb[NFCTH_POLICY_SET_MAX+1];
+
+	nla_parse_nested(tb, NFCTH_POLICY_SET_MAX, attr,
+					nfnl_cthelper_expect_policy_set);
+
+	if (!tb[NFCTH_POLICY_SET_NUM])
+		return -EINVAL;
+
+	helper->expect_class_max =
+		ntohl(nla_get_be32(tb[NFCTH_POLICY_SET_NUM]));
+
+	if (helper->expect_class_max != 0 &&
+	    helper->expect_class_max > NF_CT_MAX_EXPECT_CLASSES)
+		return -EOVERFLOW;
+
+	expect_policy = kzalloc(sizeof(struct nf_conntrack_expect_policy) *
+				helper->expect_class_max, GFP_KERNEL);
+	if (expect_policy == NULL)
+		return -ENOMEM;
+
+	for (i=0; i<helper->expect_class_max; i++) {
+		if (!tb[NFCTH_POLICY_SET+i])
+			goto err;
+
+		ret = nfnl_cthelper_expect_policy(&expect_policy[i],
+						  tb[NFCTH_POLICY_SET+i]);
+		if (ret < 0)
+			goto err;
+	}
+	helper->expect_policy = expect_policy;
+	return 0;
+err:
+	kfree(expect_policy);
+	return -EINVAL;
+}
+
+static int
+nfnl_cthelper_create(const struct nlattr * const tb[],
+		     struct nf_conntrack_tuple *tuple)
+{
+	struct nf_conntrack_helper *helper;
+	int ret;
+
+	if (!tb[NFCTH_TUPLE] || !tb[NFCTH_POLICY] || !tb[NFCTH_PRIV_DATA_LEN])
+		return -EINVAL;
+
+	helper = kzalloc(sizeof(struct nf_conntrack_helper), GFP_KERNEL);
+	if (helper == NULL)
+		return -ENOMEM;
+
+	ret = nfnl_cthelper_parse_expect_policy(helper, tb[NFCTH_POLICY]);
+	if (ret < 0)
+		goto err;
+
+	strncpy(helper->name, nla_data(tb[NFCTH_NAME]), NF_CT_HELPER_NAME_LEN);
+	helper->data_len = ntohl(nla_get_be32(tb[NFCTH_PRIV_DATA_LEN]));
+	helper->flags |= NF_CT_HELPER_F_USERSPACE;
+	memcpy(&helper->tuple, tuple, sizeof(struct nf_conntrack_tuple));
+
+	helper->me = THIS_MODULE;
+	helper->help = nfnl_userspace_cthelper;
+	helper->from_nlattr = nfnl_cthelper_from_nlattr;
+	helper->to_nlattr = nfnl_cthelper_to_nlattr;
+
+	/* Default to queue number zero, this can be updated at any time. */
+	if (tb[NFCTH_QUEUE_NUM])
+		helper->queue_num = ntohl(nla_get_be32(tb[NFCTH_QUEUE_NUM]));
+
+	if (tb[NFCTH_STATUS]) {
+		int status = ntohl(nla_get_be32(tb[NFCTH_STATUS]));
+
+		switch(status) {
+		case NFCT_HELPER_STATUS_ENABLED:
+			helper->flags |= NF_CT_HELPER_F_CONFIGURED;
+			break;
+		case NFCT_HELPER_STATUS_DISABLED:
+			helper->flags &= ~NF_CT_HELPER_F_CONFIGURED;
+			break;
+		}
+	}
+
+	ret = nf_conntrack_helper_register(helper);
+	if (ret < 0)
+		goto err;
+
+	return 0;
+err:
+	kfree(helper);
+	return ret;
+}
+
+static int
+nfnl_cthelper_update(const struct nlattr * const tb[],
+		     struct nf_conntrack_helper *helper)
+{
+	int ret;
+
+	if (tb[NFCTH_PRIV_DATA_LEN])
+		return -EBUSY;
+
+	if (tb[NFCTH_POLICY]) {
+		ret = nfnl_cthelper_parse_expect_policy(helper,
+							tb[NFCTH_POLICY]);
+		if (ret < 0)
+			return ret;
+	}
+	if (tb[NFCTH_QUEUE_NUM])
+		helper->queue_num = ntohl(nla_get_be32(tb[NFCTH_QUEUE_NUM]));
+
+	if (tb[NFCTH_STATUS]) {
+		int status = ntohl(nla_get_be32(tb[NFCTH_STATUS]));
+
+		switch(status) {
+		case NFCT_HELPER_STATUS_ENABLED:
+			helper->flags |= NF_CT_HELPER_F_CONFIGURED;
+			break;
+		case NFCT_HELPER_STATUS_DISABLED:
+			helper->flags &= ~NF_CT_HELPER_F_CONFIGURED;
+			break;
+		}
+	}
+	return 0;
+}
+
+static int
+nfnl_cthelper_new(struct sock *nfnl, struct sk_buff *skb,
+		  const struct nlmsghdr *nlh, const struct nlattr * const tb[])
+{
+	const char *helper_name;
+	struct nf_conntrack_helper *cur, *helper = NULL;
+	struct nf_conntrack_tuple tuple;
+	struct hlist_node *n;
+	int ret = 0, i;
+
+	if (!tb[NFCTH_NAME] || !tb[NFCTH_TUPLE])
+		return -EINVAL;
+
+	helper_name = nla_data(tb[NFCTH_NAME]);
+
+	ret = nfnl_cthelper_parse_tuple(&tuple, tb[NFCTH_TUPLE]);
+	if (ret < 0)
+		return ret;
+
+	rcu_read_lock();
+	for (i = 0; i < nf_ct_helper_hsize && !helper; i++) {
+		hlist_for_each_entry_rcu(cur, n, &nf_ct_helper_hash[i], hnode) {
+
+			/* skip non-userspace conntrack helpers. */
+			if (!(cur->flags & NF_CT_HELPER_F_USERSPACE))
+				continue;
+
+			if (strncmp(cur->name, helper_name,
+					NF_CT_HELPER_NAME_LEN) != 0)
+				continue;
+
+			if ((tuple.src.l3num != cur->tuple.src.l3num ||
+			     tuple.dst.protonum != cur->tuple.dst.protonum))
+				continue;
+
+			if (nlh->nlmsg_flags & NLM_F_EXCL) {
+				ret = -EEXIST;
+				goto err;
+			}
+			helper = cur;
+			break;
+		}
+	}
+	rcu_read_unlock();
+
+	if (helper == NULL)
+		ret = nfnl_cthelper_create(tb, &tuple);
+	else
+		ret = nfnl_cthelper_update(tb, helper);
+
+	return ret;
+err:
+	rcu_read_unlock();
+	return ret;
+}
+
+static int
+nfnl_cthelper_dump_tuple(struct sk_buff *skb,
+			 struct nf_conntrack_helper *helper)
+{
+	struct nlattr *nest_parms;
+
+	nest_parms = nla_nest_start(skb, NFCTH_TUPLE | NLA_F_NESTED);
+	if (nest_parms == NULL)
+		goto nla_put_failure;
+
+	if (nla_put_be16(skb, NFCTH_TUPLE_L3PROTONUM,
+			 htons(helper->tuple.src.l3num)))
+		goto nla_put_failure;
+
+	if (nla_put_u8(skb, NFCTH_TUPLE_L4PROTONUM, helper->tuple.dst.protonum))
+		goto nla_put_failure;
+
+	nla_nest_end(skb, nest_parms);
+	return 0;
+
+nla_put_failure:
+	return -1;
+}
+
+static int
+nfnl_cthelper_dump_policy(struct sk_buff *skb,
+			struct nf_conntrack_helper *helper)
+{
+	int i;
+	struct nlattr *nest_parms1, *nest_parms2;
+
+	nest_parms1 = nla_nest_start(skb, NFCTH_POLICY | NLA_F_NESTED);
+	if (nest_parms1 == NULL)
+		goto nla_put_failure;
+
+	if (nla_put_be32(skb, NFCTH_POLICY_SET_NUM,
+			 htonl(helper->expect_class_max)))
+		goto nla_put_failure;
+
+	for (i=0; i<helper->expect_class_max; i++) {
+		nest_parms2 = nla_nest_start(skb,
+				(NFCTH_POLICY_SET+i) | NLA_F_NESTED);
+		if (nest_parms2 == NULL)
+			goto nla_put_failure;
+
+		if (nla_put_string(skb, NFCTH_POLICY_NAME,
+				   helper->expect_policy[i].name))
+			goto nla_put_failure;
+
+		if (nla_put_be32(skb, NFCTH_POLICY_EXPECT_MAX,
+				 htonl(helper->expect_policy[i].max_expected)))
+			goto nla_put_failure;
+
+		if (nla_put_be32(skb, NFCTH_POLICY_EXPECT_TIMEOUT,
+				 htonl(helper->expect_policy[i].timeout)))
+			goto nla_put_failure;
+
+		nla_nest_end(skb, nest_parms2);
+	}
+	nla_nest_end(skb, nest_parms1);
+	return 0;
+
+nla_put_failure:
+	return -1;
+}
+
+static int
+nfnl_cthelper_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type,
+			int event, struct nf_conntrack_helper *helper)
+{
+	struct nlmsghdr *nlh;
+	struct nfgenmsg *nfmsg;
+	unsigned int flags = pid ? NLM_F_MULTI : 0;
+	int status;
+
+	event |= NFNL_SUBSYS_CTHELPER << 8;
+	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags);
+	if (nlh == NULL)
+		goto nlmsg_failure;
+
+	nfmsg = nlmsg_data(nlh);
+	nfmsg->nfgen_family = AF_UNSPEC;
+	nfmsg->version = NFNETLINK_V0;
+	nfmsg->res_id = 0;
+
+	if (nla_put_string(skb, NFCTH_NAME, helper->name))
+		goto nla_put_failure;
+
+	if (nla_put_be32(skb, NFCTH_QUEUE_NUM, htonl(helper->queue_num)))
+		goto nla_put_failure;
+
+	if (nfnl_cthelper_dump_tuple(skb, helper) < 0)
+		goto nla_put_failure;
+
+	if (nfnl_cthelper_dump_policy(skb, helper) < 0)
+		goto nla_put_failure;
+
+	if (nla_put_be32(skb, NFCTH_PRIV_DATA_LEN, htonl(helper->data_len)))
+		goto nla_put_failure;
+
+	if (helper->flags & NF_CT_HELPER_F_CONFIGURED)
+		status = NFCT_HELPER_STATUS_ENABLED;
+	else
+		status = NFCT_HELPER_STATUS_DISABLED;
+
+	if (nla_put_be32(skb, NFCTH_STATUS, htonl(status)))
+		goto nla_put_failure;
+
+	nlmsg_end(skb, nlh);
+	return skb->len;
+
+nlmsg_failure:
+nla_put_failure:
+	nlmsg_cancel(skb, nlh);
+	return -1;
+}
+
+static int
+nfnl_cthelper_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct nf_conntrack_helper *cur, *last;
+	struct hlist_node *n;
+
+	rcu_read_lock();
+	last = (struct nf_conntrack_helper *)cb->args[1];
+	for (; cb->args[0] < nf_ct_helper_hsize; cb->args[0]++) {
+restart:
+		hlist_for_each_entry_rcu(cur, n,
+				&nf_ct_helper_hash[cb->args[0]], hnode) {
+
+			/* skip non-userspace conntrack helpers. */
+			if (!(cur->flags & NF_CT_HELPER_F_USERSPACE))
+				continue;
+
+			if (cb->args[1]) {
+				if (cur != last)
+					continue;
+				cb->args[1] = 0;
+			}
+			if (nfnl_cthelper_fill_info(skb,
+					    NETLINK_CB(cb->skb).pid,
+					    cb->nlh->nlmsg_seq,
+					    NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
+					    NFNL_MSG_CTHELPER_NEW, cur) < 0) {
+				cb->args[1] = (unsigned long)cur;
+				goto out;
+			}
+		}
+	}
+	if (cb->args[1]) {
+		cb->args[1] = 0;
+		goto restart;
+	}
+out:
+	rcu_read_unlock();
+	return skb->len;
+}
+
+static int
+nfnl_cthelper_get(struct sock *nfnl, struct sk_buff *skb,
+		  const struct nlmsghdr *nlh, const struct nlattr * const tb[])
+{
+	int ret = -ENOENT, i;
+	struct nf_conntrack_helper *cur;
+	struct hlist_node *n;
+	struct sk_buff *skb2;
+	char *helper_name = NULL;
+	struct nf_conntrack_tuple tuple;
+	bool tuple_set = false;
+
+	if (nlh->nlmsg_flags & NLM_F_DUMP) {
+		struct netlink_dump_control c = {
+			.dump = nfnl_cthelper_dump_table,
+		};
+		return netlink_dump_start(nfnl, skb, nlh, &c);
+	}
+
+	if (tb[NFCTH_NAME])
+		helper_name = nla_data(tb[NFCTH_NAME]);
+
+	if (tb[NFCTH_TUPLE]) {
+		ret = nfnl_cthelper_parse_tuple(&tuple, tb[NFCTH_TUPLE]);
+		if (ret < 0)
+			return ret;
+
+		tuple_set = true;
+	}
+
+	for (i = 0; i < nf_ct_helper_hsize; i++) {
+		hlist_for_each_entry_rcu(cur, n, &nf_ct_helper_hash[i], hnode) {
+
+			/* skip non-userspace conntrack helpers. */
+			if (!(cur->flags & NF_CT_HELPER_F_USERSPACE))
+				continue;
+
+			if (helper_name && strncmp(cur->name, helper_name,
+						NF_CT_HELPER_NAME_LEN) != 0) {
+				continue;
+			}
+			if (tuple_set &&
+			    (tuple.src.l3num != cur->tuple.src.l3num ||
+			     tuple.dst.protonum != cur->tuple.dst.protonum))
+				continue;
+
+			skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+			if (skb2 == NULL) {
+				ret = -ENOMEM;
+				break;
+			}
+
+			ret = nfnl_cthelper_fill_info(skb2, NETLINK_CB(skb).pid,
+						nlh->nlmsg_seq,
+						NFNL_MSG_TYPE(nlh->nlmsg_type),
+						NFNL_MSG_CTHELPER_NEW, cur);
+			if (ret <= 0) {
+				kfree_skb(skb2);
+				break;
+			}
+
+			ret = netlink_unicast(nfnl, skb2, NETLINK_CB(skb).pid,
+						MSG_DONTWAIT);
+			if (ret > 0)
+				ret = 0;
+
+			/* this avoids a loop in nfnetlink. */
+			return ret == -EAGAIN ? -ENOBUFS : ret;
+		}
+	}
+	return ret;
+}
+
+static int
+nfnl_cthelper_del(struct sock *nfnl, struct sk_buff *skb,
+	     const struct nlmsghdr *nlh, const struct nlattr * const tb[])
+{
+	char *helper_name = NULL;
+	struct nf_conntrack_helper *cur;
+	struct hlist_node *n, *tmp;
+	struct nf_conntrack_tuple tuple;
+	bool tuple_set = false, found = false;
+	int i, j = 0, ret;
+
+	if (tb[NFCTH_NAME])
+		helper_name = nla_data(tb[NFCTH_NAME]);
+
+	if (tb[NFCTH_TUPLE]) {
+		ret = nfnl_cthelper_parse_tuple(&tuple, tb[NFCTH_TUPLE]);
+		if (ret < 0)
+			return ret;
+
+		tuple_set = true;
+	}
+
+	for (i = 0; i < nf_ct_helper_hsize; i++) {
+		hlist_for_each_entry_safe(cur, n, tmp, &nf_ct_helper_hash[i],
+								hnode) {
+			/* skip non-userspace conntrack helpers. */
+			if (!(cur->flags & NF_CT_HELPER_F_USERSPACE))
+				continue;
+
+			j++;
+
+			if (helper_name && strncmp(cur->name, helper_name,
+						NF_CT_HELPER_NAME_LEN) != 0) {
+				continue;
+			}
+			if (tuple_set &&
+			    (tuple.src.l3num != cur->tuple.src.l3num ||
+			     tuple.dst.protonum != cur->tuple.dst.protonum))
+				continue;
+
+			found = true;
+			nf_conntrack_helper_unregister(cur);
+		}
+	}
+	/* Make sure we return success if we flush and there is no helpers */
+	return (found || j == 0) ? 0 : -ENOENT;
+}
+
+static const struct nla_policy nfnl_cthelper_policy[NFCTH_MAX+1] = {
+	[NFCTH_NAME] = { .type = NLA_NUL_STRING,
+			 .len = NF_CT_HELPER_NAME_LEN-1 },
+	[NFCTH_QUEUE_NUM] = { .type = NLA_U32, },
+};
+
+static const struct nfnl_callback nfnl_cthelper_cb[NFNL_MSG_CTHELPER_MAX] = {
+	[NFNL_MSG_CTHELPER_NEW]		= { .call = nfnl_cthelper_new,
+					    .attr_count = NFCTH_MAX,
+					    .policy = nfnl_cthelper_policy },
+	[NFNL_MSG_CTHELPER_GET]		= { .call = nfnl_cthelper_get,
+					    .attr_count = NFCTH_MAX,
+					    .policy = nfnl_cthelper_policy },
+	[NFNL_MSG_CTHELPER_DEL]		= { .call = nfnl_cthelper_del,
+					    .attr_count = NFCTH_MAX,
+					    .policy = nfnl_cthelper_policy },
+};
+
+static const struct nfnetlink_subsystem nfnl_cthelper_subsys = {
+	.name				= "cthelper",
+	.subsys_id			= NFNL_SUBSYS_CTHELPER,
+	.cb_count			= NFNL_MSG_CTHELPER_MAX,
+	.cb				= nfnl_cthelper_cb,
+};
+
+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTHELPER);
+
+static int __init nfnl_cthelper_init(void)
+{
+	int ret;
+
+	pr_info("nfnl_cthelper: registering with nfnetlink.\n");
+	ret = nfnetlink_subsys_register(&nfnl_cthelper_subsys);
+	if (ret < 0) {
+		pr_err("nfnl_cthelper: cannot register with nfnetlink.\n");
+		goto err_out;
+	}
+	return 0;
+err_out:
+	return ret;
+}
+
+static void __exit nfnl_cthelper_exit(void)
+{
+	struct nf_conntrack_helper *cur;
+	struct hlist_node *n, *tmp;
+	int i;
+
+	pr_info("nfnl_cthelper: unregistering from nfnetlink.\n");
+	nfnetlink_subsys_unregister(&nfnl_cthelper_subsys);
+
+	for (i=0; i<nf_ct_helper_hsize; i++) {
+		hlist_for_each_entry_safe(cur, n, tmp, &nf_ct_helper_hash[i],
+									hnode) {
+			/* skip non-userspace conntrack helpers. */
+			if (!(cur->flags & NF_CT_HELPER_F_USERSPACE))
+				continue;
+
+			nf_conntrack_helper_unregister(cur);
+		}
+	}
+}
+
+module_init(nfnl_cthelper_init);
+module_exit(nfnl_cthelper_exit);
-- 
1.7.10

^ permalink raw reply related

* [PATCH 4/7] netfilter: add glue code to integrate nfnetlink_queue and ctnetlink
From: pablo @ 2012-06-12 18:06 UTC (permalink / raw)
  To: netfilter-devel; +Cc: netdev
In-Reply-To: <1339524380-2707-1-git-send-email-pablo@netfilter.org>

From: Pablo Neira Ayuso <pablo@netfilter.org>

This patch allows you to include the conntrack information together
with the packet that is sent to user-space via NFQUEUE.

Previously, there was no integration between ctnetlink and
nfnetlink_queue. If you wanted to access conntrack information
from your libnetfilter_queue program, you required to query
ctnetlink from user-space to obtain it. Thus, delaying the packet
processing even more.

Including the conntrack information is optional, you can set it
via NFQA_CFG_F_CONNTRACK flag with the new NFQA_CFG_FLAGS attribute.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/linux/netfilter.h                 |   10 ++
 include/linux/netfilter/nfnetlink_queue.h |    3 +
 net/netfilter/core.c                      |    4 +
 net/netfilter/nf_conntrack_netlink.c      |  146 ++++++++++++++++++++++++++++-
 net/netfilter/nfnetlink_queue.c           |   47 ++++++++++
 5 files changed, 209 insertions(+), 1 deletion(-)

diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 4541f33..ba65bfb 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -393,6 +393,16 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
 extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *) __rcu;
 extern void nf_ct_attach(struct sk_buff *, struct sk_buff *);
 extern void (*nf_ct_destroy)(struct nf_conntrack *) __rcu;
+
+struct nf_conn;
+struct nlattr;
+
+struct nfq_ct_hook {
+	size_t (*build_size)(const struct nf_conn *ct);
+	int (*build)(struct sk_buff *skb, struct nf_conn *ct);
+	int (*parse)(const struct nlattr *attr, struct nf_conn *ct);
+};
+extern struct nfq_ct_hook *nfq_ct_hook;
 #else
 static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
 #endif
diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h
index a6c1dda..e0d8fd8 100644
--- a/include/linux/netfilter/nfnetlink_queue.h
+++ b/include/linux/netfilter/nfnetlink_queue.h
@@ -42,6 +42,8 @@ enum nfqnl_attr_type {
 	NFQA_IFINDEX_PHYSOUTDEV,	/* __u32 ifindex */
 	NFQA_HWADDR,			/* nfqnl_msg_packet_hw */
 	NFQA_PAYLOAD,			/* opaque data payload */
+	NFQA_CT,			/* nf_conntrack_netlink.h */
+	NFQA_CT_INFO,			/* enum ip_conntrack_info */
 
 	__NFQA_MAX
 };
@@ -92,5 +94,6 @@ enum nfqnl_attr_config {
 
 /* Flags for NFQA_CFG_FLAGS */
 #define NFQA_CFG_F_FAIL_OPEN			(1 << 0)
+#define NFQA_CFG_F_CONNTRACK			(1 << 1)
 
 #endif /* _NFNETLINK_QUEUE_H */
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index e19f365..7eef845 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -264,6 +264,10 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct)
 	rcu_read_unlock();
 }
 EXPORT_SYMBOL(nf_conntrack_destroy);
+
+struct nfq_ct_hook *nfq_ct_hook;
+EXPORT_SYMBOL_GPL(nfq_ct_hook);
+
 #endif /* CONFIG_NF_CONNTRACK */
 
 #ifdef CONFIG_PROC_FS
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index a088920..3b03a86 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1620,6 +1620,140 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
 	return err;
 }
 
+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) ||	\
+    defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE)
+static size_t
+ctnetlink_nfqueue_build_size(const struct nf_conn *ct)
+{
+	return 3 * nla_total_size(0) /* CTA_TUPLE_ORIG|REPL|MASTER */
+	       + 3 * nla_total_size(0) /* CTA_TUPLE_IP */
+	       + 3 * nla_total_size(0) /* CTA_TUPLE_PROTO */
+	       + 3 * nla_total_size(sizeof(u_int8_t)) /* CTA_PROTO_NUM */
+	       + nla_total_size(sizeof(u_int32_t)) /* CTA_ID */
+	       + nla_total_size(sizeof(u_int32_t)) /* CTA_STATUS */
+	       + nla_total_size(sizeof(u_int32_t)) /* CTA_TIMEOUT */
+	       + nla_total_size(0) /* CTA_PROTOINFO */
+	       + nla_total_size(0) /* CTA_HELP */
+	       + nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */
+	       + ctnetlink_secctx_size(ct)
+#ifdef CONFIG_NF_NAT_NEEDED
+	       + 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */
+	       + 6 * nla_total_size(sizeof(u_int32_t)) /* CTA_NAT_SEQ_OFFSET */
+#endif
+#ifdef CONFIG_NF_CONNTRACK_MARK
+	       + nla_total_size(sizeof(u_int32_t)) /* CTA_MARK */
+#endif
+	       + ctnetlink_proto_size(ct)
+	       ;
+}
+
+static int
+ctnetlink_nfqueue_build(struct sk_buff *skb, struct nf_conn *ct)
+{
+	struct nlattr *nest_parms;
+
+	rcu_read_lock();
+	nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED);
+	if (!nest_parms)
+		goto nla_put_failure;
+	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
+		goto nla_put_failure;
+	nla_nest_end(skb, nest_parms);
+
+	nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY | NLA_F_NESTED);
+	if (!nest_parms)
+		goto nla_put_failure;
+	if (ctnetlink_dump_tuples(skb, nf_ct_tuple(ct, IP_CT_DIR_REPLY)) < 0)
+		goto nla_put_failure;
+	nla_nest_end(skb, nest_parms);
+
+	if (nf_ct_zone(ct)) {
+		if (nla_put_be16(skb, CTA_ZONE, htons(nf_ct_zone(ct))))
+			goto nla_put_failure;
+	}
+
+	if (ctnetlink_dump_id(skb, ct) < 0)
+		goto nla_put_failure;
+
+	if (ctnetlink_dump_status(skb, ct) < 0)
+		goto nla_put_failure;
+
+	if (ctnetlink_dump_timeout(skb, ct) < 0)
+		goto nla_put_failure;
+
+	if (ctnetlink_dump_protoinfo(skb, ct) < 0)
+		goto nla_put_failure;
+
+	if (ctnetlink_dump_helpinfo(skb, ct) < 0)
+		goto nla_put_failure;
+
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+	if (ct->secmark && ctnetlink_dump_secctx(skb, ct) < 0)
+		goto nla_put_failure;
+#endif
+	if (ct->master && ctnetlink_dump_master(skb, ct) < 0)
+		goto nla_put_failure;
+
+	if ((ct->status & IPS_SEQ_ADJUST) &&
+	    ctnetlink_dump_nat_seq_adj(skb, ct) < 0)
+		goto nla_put_failure;
+
+#ifdef CONFIG_NF_CONNTRACK_MARK
+	if (ct->mark && ctnetlink_dump_mark(skb, ct) < 0)
+		goto nla_put_failure;
+#endif
+	rcu_read_unlock();
+	return 0;
+
+nla_put_failure:
+	rcu_read_unlock();
+	return -ENOSPC;
+}
+
+static int
+ctnetlink_nfqueue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)
+{
+	int err;
+
+	if (cda[CTA_TIMEOUT]) {
+		err = ctnetlink_change_timeout(ct, cda);
+		if (err < 0)
+			return err;
+	}
+	if (cda[CTA_STATUS]) {
+		err = ctnetlink_change_status(ct, cda);
+		if (err < 0)
+			return err;
+	}
+	if (cda[CTA_HELP]) {
+		err = ctnetlink_change_helper(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]));
+#endif
+	return 0;
+}
+
+static int
+ctnetlink_nfqueue_parse(const struct nlattr *attr, struct nf_conn *ct)
+{
+	struct nlattr *cda[CTA_MAX+1];
+
+	nla_parse_nested(cda, CTA_MAX, attr, ct_nla_policy);
+
+	return ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct);
+}
+
+static struct nfq_ct_hook ctnetlink_nfqueue_hook = {
+	.build_size	= ctnetlink_nfqueue_build_size,
+	.build		= ctnetlink_nfqueue_build,
+	.parse		= ctnetlink_nfqueue_parse,
+};
+#endif /* CONFIG_NETFILTER_NETLINK_QUEUE */
+
 /***********************************************************************
  * EXPECT
  ***********************************************************************/
@@ -2424,7 +2558,12 @@ static int __init ctnetlink_init(void)
 		pr_err("ctnetlink_init: cannot register pernet operations\n");
 		goto err_unreg_exp_subsys;
 	}
-
+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) ||	\
+    defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE)
+	/* setup interaction between nf_queue and nf_conntrack_netlink. */
+	RCU_INIT_POINTER(nfq_ct_hook, &ctnetlink_nfqueue_hook);
+	printk("registering nf_queue and ctnetlink interaction\n");
+#endif
 	return 0;
 
 err_unreg_exp_subsys:
@@ -2442,6 +2581,11 @@ static void __exit ctnetlink_exit(void)
 	unregister_pernet_subsys(&ctnetlink_net_ops);
 	nfnetlink_subsys_unregister(&ctnl_exp_subsys);
 	nfnetlink_subsys_unregister(&ctnl_subsys);
+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) ||	\
+    defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE)
+	RCU_INIT_POINTER(nfq_ct_hook, NULL);
+	printk("unregistering nf_queue and ctnetlink interaction\n");
+#endif
 }
 
 module_init(ctnetlink_init);
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 630da3d..ab1fd1c 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -30,6 +30,7 @@
 #include <linux/list.h>
 #include <net/sock.h>
 #include <net/netfilter/nf_queue.h>
+#include <net/netfilter/nf_conntrack.h>
 
 #include <linux/atomic.h>
 
@@ -233,6 +234,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
 	struct sk_buff *entskb = entry->skb;
 	struct net_device *indev;
 	struct net_device *outdev;
+	struct nfq_ct_hook *nfq_ct;
+	struct nf_conn *ct = NULL;
+	enum ip_conntrack_info uninitialized_var(ctinfo);
 
 	size =    NLMSG_SPACE(sizeof(struct nfgenmsg))
 		+ nla_total_size(sizeof(struct nfqnl_msg_packet_hdr))
@@ -266,6 +270,17 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
 		break;
 	}
 
+	/* rcu_read_lock()ed by __nf_queue already. */
+	nfq_ct = rcu_dereference(nfq_ct_hook);
+	if (nfq_ct != NULL && (queue->flags & NFQA_CFG_F_CONNTRACK)) {
+		ct = nf_ct_get(entskb, &ctinfo);
+		if (ct) {
+			if (!nf_ct_is_untracked(ct))
+				size += nfq_ct->build_size(ct);
+			else
+				ct = NULL;
+		}
+	}
 
 	skb = alloc_skb(size, GFP_ATOMIC);
 	if (!skb)
@@ -389,6 +404,24 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
 			BUG();
 	}
 
+	if (ct) {
+		struct nlattr *nest_parms;
+		u_int32_t tmp;
+
+		nest_parms = nla_nest_start(skb, NFQA_CT | NLA_F_NESTED);
+		if (!nest_parms)
+			goto nla_put_failure;
+
+		if (nfq_ct->build(skb, ct) < 0)
+			goto nla_put_failure;
+
+		nla_nest_end(skb, nest_parms);
+
+		tmp = ctinfo;
+		if (nla_put_u32(skb, NFQA_CT_INFO, htonl(ctinfo)))
+			goto nla_put_failure;
+	}
+
 	nlh->nlmsg_len = skb->tail - old_tail;
 	return skb;
 
@@ -732,6 +765,7 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
 	struct nfqnl_instance *queue;
 	unsigned int verdict;
 	struct nf_queue_entry *entry;
+	struct nfq_ct_hook *nfq_ct;
 
 	queue = instance_lookup(queue_num);
 	if (!queue)
@@ -750,6 +784,19 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
 	if (entry == NULL)
 		return -ENOENT;
 
+	rcu_read_lock();
+	nfq_ct = rcu_dereference(nfq_ct_hook);
+	if (nfq_ct != NULL &&
+	    (queue->flags & NFQA_CFG_F_CONNTRACK) && nfqa[NFQA_CT]) {
+		enum ip_conntrack_info ctinfo;
+		struct nf_conn *ct;
+
+		ct = nf_ct_get(entry->skb, &ctinfo);
+		if (ct && !nf_ct_is_untracked(ct))
+			nfq_ct->parse(nfqa[NFQA_CT], ct);
+	}
+	rcu_read_unlock();
+
 	if (nfqa[NFQA_PAYLOAD]) {
 		if (nfqnl_mangle(nla_data(nfqa[NFQA_PAYLOAD]),
 				 nla_len(nfqa[NFQA_PAYLOAD]), entry) < 0)
-- 
1.7.10

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox