Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] Add prefetches in net/ipv4/route.c
From: David S. Miller @ 2005-07-28 20:58 UTC (permalink / raw)
  To: dada1; +Cc: netdev
In-Reply-To: <42E94680.8060309@cosmosbay.com>

From: Eric Dumazet <dada1@cosmosbay.com>
Date: Thu, 28 Jul 2005 22:56:32 +0200

> But in case of DDOS, prefetches are a win.

Numbers please, I'm simply curious.

^ permalink raw reply

* Re: [PATCH] Add prefetches in net/ipv4/route.c
From: Eric Dumazet @ 2005-07-28 21:24 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <20050728.135826.63129319.davem@davemloft.net>

David S. Miller a écrit :
> From: Eric Dumazet <dada1@cosmosbay.com>
> Date: Thu, 28 Jul 2005 22:56:32 +0200
> 
> 
>>But in case of DDOS, prefetches are a win.
> 
> 
> Numbers please, I'm simply curious.
> 
> 

I have no profiling info for this exact patch, I'm sorry David.

On a dual opteron machine, this thing from ip_route_input() is very expensive :

  RT_CACHE_STAT_INC(in_hlist_search);

ip_route_input() use a total of 3.4563 % of one cpu, but this 'increment' takes 1.20 % !!!

0.0047   mov    2123529(%rip),%rax        # ffffffff804b4a60 <rt_cache_stat>
1.1898   not    %rax
          mov    %gs:0x34,%edx
0.0042   movslq %edx,%rdx
          mov    (%rax,%rdx,8),%rax
          incl   0x38(%rax)

Sometime I wonder if oprofile can be trusted :(

Maybe we should increment a counter on the stack and do a final
    if (counter != 0)
        RT_CACHE_STAT_ADD(in_hlist_search, counter);

Eric

^ permalink raw reply

* [2.6 patch] net: Spelling mistakes threshoulds -> thresholds
From: Adrian Bunk @ 2005-07-28 22:04 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel, Baruch Even

Just simple spelling mistake fixes.

From: aruch Even <baruch@ev-en.org>

Signed-Off-By: Baruch Even <baruch@ev-en.org>
Signed-off-by: Adrian Bunk <bunk@stusta.de>

---

This patch was already sent on:
- 12 Jul 2005

This patch was sent by Baruch Even on:
- 05 Apr 2005

--- 2.6.11.orig/include/net/tcp.h	2005-03-16 00:09:00.000000000 +0000
+++ 2.6.11/include/net/tcp.h	2005-04-05 14:33:13.473828484 +0100
@@ -1351,7 +1351,7 @@ static inline void tcp_cwnd_validate(str
 	}
 }
 
-/* Set slow start threshould and cwnd not falling to slow start */
+/* Set slow start threshold and cwnd not falling to slow start */
 static inline void __tcp_enter_cwr(struct tcp_sock *tp)
 {
 	tp->undo_marker = 0;
diff -Nurp -X dontdiff 2.6.11.orig/net/ipv4/ipmr.c 2.6.11/net/ipv4/ipmr.c
--- 2.6.11.orig/net/ipv4/ipmr.c	2005-03-16 00:09:06.000000000 +0000
+++ 2.6.11/net/ipv4/ipmr.c	2005-04-05 14:33:13.541817170 +0100
@@ -359,7 +359,7 @@ out:
 
 /* Fill oifs list. It is called under write locked mrt_lock. */
 
-static void ipmr_update_threshoulds(struct mfc_cache *cache, unsigned char *ttls)
+static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls)
 {
 	int vifi;
 
@@ -721,7 +721,7 @@ static int ipmr_mfc_add(struct mfcctl *m
 	if (c != NULL) {
 		write_lock_bh(&mrt_lock);
 		c->mfc_parent = mfc->mfcc_parent;
-		ipmr_update_threshoulds(c, mfc->mfcc_ttls);
+		ipmr_update_thresholds(c, mfc->mfcc_ttls);
 		if (!mrtsock)
 			c->mfc_flags |= MFC_STATIC;
 		write_unlock_bh(&mrt_lock);
@@ -738,7 +738,7 @@ static int ipmr_mfc_add(struct mfcctl *m
 	c->mfc_origin=mfc->mfcc_origin.s_addr;
 	c->mfc_mcastgrp=mfc->mfcc_mcastgrp.s_addr;
 	c->mfc_parent=mfc->mfcc_parent;
-	ipmr_update_threshoulds(c, mfc->mfcc_ttls);
+	ipmr_update_thresholds(c, mfc->mfcc_ttls);
 	if (!mrtsock)
 		c->mfc_flags |= MFC_STATIC;
 

^ permalink raw reply

* Re: [PATCH] Add prefetches in net/ipv4/route.c
From: David S. Miller @ 2005-07-28 22:44 UTC (permalink / raw)
  To: dada1; +Cc: netdev
In-Reply-To: <42E94D11.4090002@cosmosbay.com>

From: Eric Dumazet <dada1@cosmosbay.com>
Date: Thu, 28 Jul 2005 23:24:33 +0200

> On a dual opteron machine, this thing from ip_route_input() is very expensive :
> 
>   RT_CACHE_STAT_INC(in_hlist_search);

That's amazing since it's per-cpu.  I don't have any suggestions
besides your idea to increment it once using an accumulation local
variable.

^ permalink raw reply

* Re: [2.6 patch] net: Spelling mistakes threshoulds -> thresholds
From: David S. Miller @ 2005-07-29  3:30 UTC (permalink / raw)
  To: bunk; +Cc: netdev, linux-kernel, baruch
In-Reply-To: <20050728220410.GG4790@stusta.de>

From: Adrian Bunk <bunk@stusta.de>
Date: Fri, 29 Jul 2005 00:04:10 +0200

> Just simple spelling mistake fixes.
> 
> From: aruch Even <baruch@ev-en.org>
> 
> Signed-Off-By: Baruch Even <baruch@ev-en.org>
> Signed-off-by: Adrian Bunk <bunk@stusta.de>

The include/net/tcp.h part of this patch no longer
applies cleanly.

^ permalink raw reply

* Re: [2.6 patch] net: Spelling mistakes threshoulds -> thresholds
From: Baruch Even @ 2005-07-29 10:21 UTC (permalink / raw)
  To: David S. Miller; +Cc: bunk, netdev, linux-kernel
In-Reply-To: <20050728.203021.35467760.davem@davemloft.net>

[-- Attachment #1: Type: text/plain, Size: 84 bytes --]

Just simple spelling mistake fixes.

Signed-Off-By: Baruch Even <baruch@ev-en.org>


[-- Attachment #2: threshould.diff --]
[-- Type: text/plain, Size: 1676 bytes --]

diff -Nurp 2.6.13-rc4-orig/include/net/tcp.h 2.6.13-rc4/include/net/tcp.h
--- 2.6.13-rc4-orig/include/net/tcp.h	2005-07-29 11:17:25.000000000 +0100
+++ 2.6.13-rc4/include/net/tcp.h	2005-07-29 11:14:28.000000000 +0100
@@ -1236,7 +1236,7 @@ static inline void tcp_sync_left_out(str
 	tp->left_out = tp->sacked_out + tp->lost_out;
 }
 
-/* Set slow start threshould and cwnd not falling to slow start */
+/* Set slow start threshold and cwnd not falling to slow start */
 static inline void __tcp_enter_cwr(struct tcp_sock *tp)
 {
 	tp->undo_marker = 0;
diff -Nurp 2.6.13-rc4-orig/net/ipv4/ipmr.c 2.6.13-rc4/net/ipv4/ipmr.c
--- 2.6.13-rc4-orig/net/ipv4/ipmr.c	2005-07-29 11:17:25.000000000 +0100
+++ 2.6.13-rc4/net/ipv4/ipmr.c	2005-07-29 11:14:28.000000000 +0100
@@ -362,7 +362,7 @@ out:
 
 /* Fill oifs list. It is called under write locked mrt_lock. */
 
-static void ipmr_update_threshoulds(struct mfc_cache *cache, unsigned char *ttls)
+static void ipmr_update_thresholds(struct mfc_cache *cache, unsigned char *ttls)
 {
 	int vifi;
 
@@ -727,7 +727,7 @@ static int ipmr_mfc_add(struct mfcctl *m
 	if (c != NULL) {
 		write_lock_bh(&mrt_lock);
 		c->mfc_parent = mfc->mfcc_parent;
-		ipmr_update_threshoulds(c, mfc->mfcc_ttls);
+		ipmr_update_thresholds(c, mfc->mfcc_ttls);
 		if (!mrtsock)
 			c->mfc_flags |= MFC_STATIC;
 		write_unlock_bh(&mrt_lock);
@@ -744,7 +744,7 @@ static int ipmr_mfc_add(struct mfcctl *m
 	c->mfc_origin=mfc->mfcc_origin.s_addr;
 	c->mfc_mcastgrp=mfc->mfcc_mcastgrp.s_addr;
 	c->mfc_parent=mfc->mfcc_parent;
-	ipmr_update_threshoulds(c, mfc->mfcc_ttls);
+	ipmr_update_thresholds(c, mfc->mfcc_ttls);
 	if (!mrtsock)
 		c->mfc_flags |= MFC_STATIC;
 

^ permalink raw reply

* Re: [PATCH] Add prefetches in net/ipv4/route.c
From: Robert Olsson @ 2005-07-29 14:50 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David S. Miller, netdev
In-Reply-To: <42E94D11.4090002@cosmosbay.com>


Eric Dumazet writes:

 > I have no profiling info for this exact patch, I'm sorry David.
 > On a dual opteron machine, this thing from ip_route_input() is very expensive :
 > 
 >   RT_CACHE_STAT_INC(in_hlist_search);
 > 
 > ip_route_input() use a total of 3.4563 % of one cpu, but this 'increment' takes 1.20 % !!!

 Very weird if the statscounter taking a third of ip_route_input.

 > Sometime I wonder if oprofile can be trusted :(
 > 
 > Maybe we should increment a counter on the stack and do a final
 >     if (counter != 0)
 >         RT_CACHE_STAT_ADD(in_hlist_search, counter);

 My experiences from playing with prefetching eth_type_trans in this 
 case. One must look in the total performance not just were the 
 prefetching is done. In this case I was able to get eth_type_trans
 down in the profile list but other functions increased so performance
 was the same or lower. This needs to be sorted out... 

 Cheers.
					--ro

^ permalink raw reply

* Re: [hipl-users] Re: [PATCH 2.6.12.2] XFRM: BEET IPsec mode for Linux
From: Diego Beltrami @ 2005-07-29 15:33 UTC (permalink / raw)
  To: herbert; +Cc: infrahip, netdev
In-Reply-To: <E1Dy6gb-00044G-00@gondolin.me.apana.org.au>

> Diego Beltrami <diego.beltrami@hiit.fi> wrote:
> > 
> > we have been working for three months to implement a new IPsec mode,
> > the "BEET" mode, for Linux. Below is a link to the BEET specification
> > and
> > the abstract:
> > 
> > http://www.ietf.org/internet-drafts/draft-nikander-esp-beet-mode-03.txt
> 
> Thanks for the patch guys, this is really interesting.

Thanks Herbert for your feedback!


> > extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type);
> > diff -urN linux-2.6.12.2/net/ipv4/esp4.c
> > linux-beet-2.6.12.2/net/ipv4/esp4.c
> > --- linux-2.6.12.2/net/ipv4/esp4.c      2005-06-30 02:00:53.000000000 +0300
> > +++ linux-beet-2.6.12.2/net/ipv4/esp4.c 2005-07-25 14:39:11.000000000
> 
> Although the document only talks about ESP, as far as I can see
> the encapsulation can be applied to AH/IPComp just as well.
> So how about moving this stuff to the generic xfrm_input/xfrm_output
> functions?

The BEET code is already present in xfrm_input/xfrm_output functions and
it applies ESP encapsulation merely because of SA and SP set by means
setkey. As a consequence, if SA and SP are correctly set for AH the flow
goes through the AH functions. 

The modifications in the ESP functions are due to the hybrid cases when
Inner and Outer address families are different; in those cases the
values returned by espX functions are not coherent.

I tried to change SA and SP so that AH is used and the flow correctly
goes through AH functions but the problem has been revealed to be
something else. In particular, it seems that the AH functions deal with
the pointers contained in skb (skb->data, skb->nh, skb->h etc) in a
slightly different way than ESP functions. (Can anyone say more?)

Surely BEET will work also for AH with minor changes, even though we
only tried the ESP encapsulation.
This will require some time to inspect and analyze the exact situation.

In any case, as a result, I would say the code is already generic
itself.


On the other hand I don't know about IPComp, so I wouldn't say anything.
Hence if You could please give some hints, they will be more than
appreciated.

> 
> Also, if you're going to do cross-family transforms, it should be
> done for both BEET and plain tunnel-mode.

Potentially it could be possible also for plain tunnel-mode: this will
require further analysis.

For further discussion and advice, please give feedback.
Thank You very much!

Cheers,

--Diego

^ permalink raw reply

* Re: [Infrahip] Re: [hipl-users] Re: [PATCH 2.6.12.2] XFRM: BEET IPsec mode for Linux
From: Pekka Nikander @ 2005-07-29 15:45 UTC (permalink / raw)
  To: diego.beltrami; +Cc: herbert, netdev, infrahip
In-Reply-To: <1122651216.25842.67.camel@odysse>

> Surely BEET will work also for AH with minor changes, even though we
> only tried the ESP encapsulation.

I wouldn't be so sure.  IIRC, tunnel mode is not specified for AH but  
for ESP only.  Consequently, defining BEET mode for AH might be  
pretty tricky.  OTOH, I don't know the linux IPsec implementation so  
that it might be possible to make BEET to "work" for AH, for some  
value of "work", but it probably would require some careful thinking  
to define the exact semantics, like what addresses (inner or outer)  
are covered by the AH integrity protection, what does the integrity  
protection really assert, etc.

--Pekka

^ permalink raw reply

* RE: [PATCH 2.6.12.1 5/12] S2io: Performance improvements
From: Ravinandan Arakali @ 2005-07-29 16:37 UTC (permalink / raw)
  To: 'David S. Miller'
  Cc: hch, raghavendra.koushik, jgarzik, netdev, leonid.grossman,
	rapuru.sriram
In-Reply-To: <20050712.140411.41107257.davem@davemloft.net>

David,
We are trying to use the "default" directive in Kconfig. We tried
using an unconditional directive(just to test it out) such as
"default y" and a conditional one such as "default y if
CONFIG_IA64_SGI_SN2".

But when we run "make menuconfig", it does not seem to pickup any of these
changes from Kconfig.
Any idea what we might be missing ?

Once this is fixed, we'll send out a patch to address comments from
previous 12 patches as well as couple of issues we found in the
meantime.

Thanks,
Ravi

-----Original Message-----
From: David S. Miller [mailto:davem@davemloft.net]
Sent: Tuesday, July 12, 2005 2:04 PM
To: ravinandan.arakali@neterion.com
Cc: hch@infradead.org; raghavendra.koushik@neterion.com;
jgarzik@pobox.com; netdev@oss.sgi.com; leonid.grossman@neterion.com;
rapuru.sriram@neterion.com
Subject: Re: [PATCH 2.6.12.1 5/12] S2io: Performance improvements


From: "Ravinandan Arakali" <ravinandan.arakali@neterion.com>
Subject: RE: [PATCH 2.6.12.1 5/12] S2io: Performance improvements
Date: Tue, 12 Jul 2005 14:00:52 -0700

> The two-buffer mode was added as a configurable option
> to Kconfig file several months ago. Hence the macro
> is CONFIG_2BUFF_MODE.

We're saying that you should choose CONFIG_2BUFF_MODE, when
CONFIG_IA64_SGI_SN2 is set, inside the Kconfig file using the
"default" Kconfig directive.

You should never change the setting of CONFIG_* macros in C source.

^ permalink raw reply

* Re: [PATCH] Add prefetches in net/ipv4/route.c
From: Rick Jones @ 2005-07-29 17:06 UTC (permalink / raw)
  To: netdev
In-Reply-To: <17130.16951.581026.863431@robur.slu.se>

Robert Olsson wrote:
> Eric Dumazet writes:
> 
>  > I have no profiling info for this exact patch, I'm sorry David.
>  > On a dual opteron machine, this thing from ip_route_input() is very expensive :
>  > 
>  >   RT_CACHE_STAT_INC(in_hlist_search);
>  > 
>  > ip_route_input() use a total of 3.4563 % of one cpu, but this 'increment' takes 1.20 % !!!
> 
>  Very weird if the statscounter taking a third of ip_route_input.
> 
>  > Sometime I wonder if oprofile can be trusted :(
>  > 
>  > Maybe we should increment a counter on the stack and do a final
>  >     if (counter != 0)
>  >         RT_CACHE_STAT_ADD(in_hlist_search, counter);
> 
>  My experiences from playing with prefetching eth_type_trans in this 
>  case. One must look in the total performance not just were the 
>  prefetching is done. In this case I was able to get eth_type_trans
>  down in the profile list but other functions increased so performance
>  was the same or lower. This needs to be sorted out... 

How many of the architectures have PMU's that can give us cache miss statistics? 
  Itanium does, and can go so far as to tell us which addresses and instructions 
are involved - do the others?

That sort of data would seem to be desirable in this sort of situation.

rick jones

^ permalink raw reply

* Re: [PATCH] Add prefetches in net/ipv4/route.c
From: Robert Olsson @ 2005-07-29 17:44 UTC (permalink / raw)
  To: Rick Jones; +Cc: netdev
In-Reply-To: <42EA6202.703@hp.com>


Rick Jones writes:

 > >  My experiences from playing with prefetching eth_type_trans in this 
 > >  case. One must look in the total performance not just were the 
 > >  prefetching is done. In this case I was able to get eth_type_trans
 > >  down in the profile list but other functions increased so performance
 > >  was the same or lower. This needs to be sorted out... 
 > 
 > How many of the architectures have PMU's that can give us cache miss statistics? 
 >   Itanium does, and can go so far as to tell us which addresses and instructions 
 > are involved - do the others?

 I've seem XEON and Opterons has performance counters for this that can 
 be used with oprofile. Intel has a document (was it an application note?) 
 describing prefetching. Really a lot of things to consider to become 
 successful.

 > That sort of data would seem to be desirable in this sort of situation.

 Also what scenario code patch and load we optimizing for Eric mentioned 
 this briefly. 

 Cheers.
					--ro


 

^ permalink raw reply

* Re: [PATCH] Add prefetches in net/ipv4/route.c
From: Eric Dumazet @ 2005-07-29 17:57 UTC (permalink / raw)
  To: Rick Jones; +Cc: netdev, David S. Miller, Robert Olsson
In-Reply-To: <42EA6202.703@hp.com>

Rick Jones a écrit :
> Robert Olsson wrote:
> 
>> Eric Dumazet writes:
>>
>>  > I have no profiling info for this exact patch, I'm sorry David.
>>  > On a dual opteron machine, this thing from ip_route_input() is very 
>> expensive :
>>  >  >   RT_CACHE_STAT_INC(in_hlist_search);
>>  >  > ip_route_input() use a total of 3.4563 % of one cpu, but this 
>> 'increment' takes 1.20 % !!!
>>
>>  Very weird if the statscounter taking a third of ip_route_input.
>>
>>  > Sometime I wonder if oprofile can be trusted :(
>>  >  > Maybe we should increment a counter on the stack and do a final
>>  >     if (counter != 0)
>>  >         RT_CACHE_STAT_ADD(in_hlist_search, counter);
>>
>>  My experiences from playing with prefetching eth_type_trans in this 
>>  case. One must look in the total performance not just were the 
>>  prefetching is done. In this case I was able to get eth_type_trans
>>  down in the profile list but other functions increased so performance
>>  was the same or lower. This needs to be sorted out... 
> 
> 
> How many of the architectures have PMU's that can give us cache miss 
> statistics?  Itanium does, and can go so far as to tell us which 
> addresses and instructions are involved - do the others?
> 
> That sort of data would seem to be desirable in this sort of situation.
> 
> rick jones
> 
> 

oprofile on AMD64 can gather lots of data, DATA_CACHE_MISSES for example...

But I think I know what happens...

nm -v /usr/src/linux/vmlinux | grep -5 rt_cache_stat

ffffffff804c6a80 b rover.5
ffffffff804c6a88 b last_gc.2
ffffffff804c6a90 b rover.3
ffffffff804c6a94 b equilibrium.4
ffffffff804c6a98 b ip_fallback_id.7
ffffffff804c6aa0 B rt_cache_stat
ffffffff804c6aa8 b ip_rt_max_size
ffffffff804c6aac b ip_rt_debug
ffffffff804c6ab0 b rt_deadline

So rt_cache_stat (which is a read only pointer) is in the middle of a hot cache line (some parts of it are written over and over), that 
probably ping pong between CPUS.

Time to provide a patch to carefully place all the static data from net/ipv4/route.c into 2 parts : mostly readonly, and others... :)

Eric

^ permalink raw reply

* Re: [PATCH] Add prefetches in net/ipv4/route.c
From: Rick Jones @ 2005-07-29 18:25 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev, David S. Miller, Robert Olsson
In-Reply-To: <42EA6E0F.8060705@cosmosbay.com>


> oprofile on AMD64 can gather lots of data, DATA_CACHE_MISSES for example...
> 
> But I think I know what happens...
> 
> nm -v /usr/src/linux/vmlinux | grep -5 rt_cache_stat
> 
> ffffffff804c6a80 b rover.5
> ffffffff804c6a88 b last_gc.2
> ffffffff804c6a90 b rover.3
> ffffffff804c6a94 b equilibrium.4
> ffffffff804c6a98 b ip_fallback_id.7
> ffffffff804c6aa0 B rt_cache_stat
> ffffffff804c6aa8 b ip_rt_max_size
> ffffffff804c6aac b ip_rt_debug
> ffffffff804c6ab0 b rt_deadline
> 
> So rt_cache_stat (which is a read only pointer) is in the middle of a 
> hot cache line (some parts of it are written over and over), that 
> probably ping pong between CPUS.
> 
> Time to provide a patch to carefully place all the static data from 
> net/ipv4/route.c into 2 parts : mostly readonly, and others... :)

Which of course begs the question - what cache line size should be ass-u-me-d 
when blocking these things?  I'll put-forth 128 bytes.

rick jones

^ permalink raw reply

* Re: [patch] net/tulip: LAN driver for ULI M5261/M5263
From: Jeff Garzik @ 2005-07-29 19:37 UTC (permalink / raw)
  To: Peer.Chen; +Cc: alan, Clear.Zhang, linux-kernel, Emily.Jiang, Netdev List
In-Reply-To: <OF9922119A.7A6623CD-ON4825704D.0040B00E@uli.com.tw>

Peer.Chen@uli.com.tw wrote:
> We want to extract our LAN card driver from tulip core driver and make a
> new file uli526x.c at tulip folder,
> because we have added some ethtool interface support and non-eprom support
> in our driver and may be other change
> in the futher. If our controllers support are still contained in the tulip
> core driver, I think it'll increase the
> complexity of maintenance,


After some thought, I agree with this assessment.

It has been my goal for a long time to separate out the various chips 
from the tulip driver, for easier maintenance.  One of the reasons I 
have not applied a "fix tulip for ULi" patch is that it changes PHY 
details that I am not sure are OK for the myriad tulip clones.  A 
separate driver eliminates this objection.

I have applied your patch to the new 'uli-tulip' branch of git 
repository 
rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git

Please now do the following tasks:

1) Submit an incremental patch addressing Alexey Dobriyan's minor complaints

2) Submit a patch removing all ULi support from the 'tulip' driver


I will then conduct a final review, and probably request another patch, 
with more updates.

After that, your driver will be sent upstream, to be included in the 
official 2.6.x kernel.

Thanks and regards,

	Jeff

^ permalink raw reply

* Re: [PATCH RFC]: PHY Abstraction Layer III
From: Jeff Garzik @ 2005-07-29 21:46 UTC (permalink / raw)
  To: Andy Fleming; +Cc: netdev, Embedded PPC Linux list
In-Reply-To: <23F9076F-9FBB-43C8-83CD-F630E694203D@freescale.com>

Andy Fleming wrote:
> Here's the latest version of the patch, done against a cogito  linux-2.6 
> branch.  It has a handful of small changes, which I hope  will speed 
> acceptance:
> 
> * Interrupts are no longer requested at interrupt time
> * There is a function to print out PHY status
> * The PHY drivers' probe function now serves only to initialize  driver 
> state
> * A new config_init functor has been created to configure PHY state  
> just after reset (so that the PHYs will be returned to a sane state  if 
> they don't start up that way)
> * Stephen Hemminger's patch to allow better module support in the  
> drivers has been included

OK, DaveM and I are OK with merging this.

Send me a single One Big Patch which adds all the new files and such, 
I'll give it a final review, and queue it for 2.6.14.

	Jeff

^ permalink raw reply

* Re: [Infrahip] Re: [hipl-users] Re: [PATCH 2.6.12.2] XFRM: BEET IPsec mode for Linux
From: Herbert Xu @ 2005-07-29 23:48 UTC (permalink / raw)
  To: Pekka Nikander; +Cc: diego.beltrami, netdev, infrahip
In-Reply-To: <B9CA81E3-5A80-4629-8D32-42A8C37142E2@nomadiclab.com>

On Fri, Jul 29, 2005 at 05:45:24PM +0200, Pekka Nikander wrote:
> >Surely BEET will work also for AH with minor changes, even though we
> >only tried the ESP encapsulation.
> 
> I wouldn't be so sure.  IIRC, tunnel mode is not specified for AH but  
> for ESP only.  Consequently, defining BEET mode for AH might be  

Well plain tunnel mode certainly is specified for AH as well as IPComp.
But you're right the semantics of BEET mode for AH needs to be thought
out.

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH] add new nfnetlink_log subsystem
From: Harald Welte @ 2005-07-30 10:30 UTC (permalink / raw)
  To: David Miller; +Cc: Linux Netdev List, Netfilter Development Mailinglist


[-- Attachment #1.1: Type: text/plain, Size: 688 bytes --]

Hi Dave!

This (long-awaited) patch adds the generic nfnetlink-based userspace
logging.  nfnetlink_log can be used for any protocol family, and
supports upt to 65535 logging groups (that could go to separate logging
daemons, e.g.).

The patch is incremental to my nf_log update in
<20050728200434.GA3763@rama.de.gnumonks.org>.

Please apply to net-2.6.14,
	thanks.
-- 
- Harald Welte <laforge@gnumonks.org>          	        http://gnumonks.org/
============================================================================
"Privacy in residential applications is a desirable marketing option."
                                                  (ETSI EN 300 175-7 Ch. A6)

[-- Attachment #1.2: 17-nfnetlink_log.patch --]
[-- Type: text/plain, Size: 29793 bytes --]

[NETFILTER] Add new "nfnetlink_log" userspace packet logging facility

This is a generic (layer3 independent) version of what ipt_ULOG is already
doing for IPv4 today.  ipt_ULOG, ebt_ulog and finally also ip[6]t_LOG will
be deprecated by this mechanism in the long term.

Signed-off-by: Harald Welte <laforge@netfilter.org>

---
commit 66ad9b079da5c6a181506fba350aa33d26417431
tree 4b4bda3788bf34d1946ff0239100a4f235cfa120
parent 3770e25a01055bfa8bee52ed16666db1f3a5141f
author laforge <laforge@netfilter.org> Sa, 30 Jul 2005 12:11:19 +0200
committer laforge <laforge@netfilter.org> Sa, 30 Jul 2005 12:11:19 +0200

 include/linux/netfilter/nfnetlink_log.h |   85 +++
 net/netfilter/Kconfig                   |   11 
 net/netfilter/Makefile                  |    1 
 net/netfilter/nfnetlink_log.c           |  992 +++++++++++++++++++++++++++++++
 4 files changed, 1089 insertions(+), 0 deletions(-)

diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h
new file mode 100644
--- /dev/null
+++ b/include/linux/netfilter/nfnetlink_log.h
@@ -0,0 +1,85 @@
+#ifndef _NFNETLINK_LOG_H
+#define _NFNETLINK_LOG_H
+
+/* This file describes the netlink messages (i.e. 'protocol packets'),
+ * and not any kind of function definitions.  It is shared between kernel and
+ * userspace.  Don't put kernel specific stuff in here */
+
+#include <linux/netfilter/nfnetlink.h>
+
+enum nfulnl_msg_types {
+	NFULNL_MSG_PACKET,		/* packet from kernel to userspace */
+	NFULNL_MSG_CONFIG,		/* connect to a particular queue */
+
+	NFULNL_MSG_MAX
+};
+
+struct nfulnl_msg_packet_hdr {
+	u_int16_t	hw_protocol;	/* hw protocol (network order) */
+	u_int8_t	hook;		/* netfilter hook */
+	u_int8_t	_pad;
+} __attribute__ ((packed));
+
+struct nfulnl_msg_packet_hw {
+	u_int16_t	hw_addrlen;
+	u_int16_t	_pad;
+	u_int8_t	hw_addr[8];
+} __attribute__ ((packed));
+
+struct nfulnl_msg_packet_timestamp {
+	u_int64_t	sec;
+	u_int64_t	usec;
+} __attribute__ ((packed));
+
+#define NFULNL_PREFIXLEN	30	/* just like old log target */
+
+enum nfulnl_attr_type {
+	NFULA_UNSPEC,
+	NFULA_PACKET_HDR,
+	NFULA_MARK,			/* u_int32_t nfmark */
+	NFULA_TIMESTAMP,		/* nfulnl_msg_packet_timestamp */
+	NFULA_IFINDEX_INDEV,		/* u_int32_t ifindex */
+	NFULA_IFINDEX_OUTDEV,		/* u_int32_t ifindex */
+	NFULA_HWADDR,			/* nfulnl_msg_packet_hw */
+	NFULA_PAYLOAD,			/* opaque data payload */
+	NFULA_PREFIX,			/* string prefix */
+	NFULA_UID,			/* user id of socket */
+
+	__NFULA_MAX
+};
+#define NFULA_MAX (__NFULA_MAX - 1)
+
+enum nfulnl_msg_config_cmds {
+	NFULNL_CFG_CMD_NONE,
+	NFULNL_CFG_CMD_BIND,
+	NFULNL_CFG_CMD_UNBIND,
+	NFULNL_CFG_CMD_PF_BIND,
+	NFULNL_CFG_CMD_PF_UNBIND,
+};
+
+struct nfulnl_msg_config_cmd {
+	u_int8_t	command;	/* nfulnl_msg_config_cmds */
+} __attribute__ ((packed));
+
+struct nfulnl_msg_config_mode {
+	u_int32_t	copy_range;
+	u_int8_t	copy_mode;
+	u_int8_t	_pad;
+} __attribute__ ((packed));
+
+enum nfulnl_attr_config {
+	NFULA_CFG_UNSPEC,
+	NFULA_CFG_CMD,			/* nfulnl_msg_config_cmd */
+	NFULA_CFG_MODE,			/* nfulnl_msg_config_mode */
+	NFULA_CFG_NLBUFSIZ,		/* u_int32_t buffer size */
+	NFULA_CFG_TIMEOUT,		/* u_int32_t in 1/100 s */
+	NFULA_CFG_QTHRESH,		/* u_int32_t */
+	__NFULA_CFG_MAX
+};
+#define NFULA_CFG_MAX (__NFULA_CFG_MAX -1)
+
+#define NFULNL_COPY_NONE	0x00
+#define NFULNL_COPY_META	0x01
+#define NFULNL_COPY_PACKET	0x02
+
+#endif /* _NFNETLINK_LOG_H */
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -11,3 +11,14 @@ config NETFILTER_NETLINK_QUEUE
 	  If this option isenabled, the kernel will include support
 	  for queueing packets via NFNETLINK.
 	  
+config NETFILTER_NETLINK_LOG
+	tristate "Netfilter LOG over NFNETLINK interface"
+	depends on NETFILTER_NETLINK
+	help
+	  If this option is enabled, the kernel will include support
+	  for logging packets via NFNETLINK.
+
+	  This obsoletes the existing ipt_ULOG and ebg_ulog mechanisms,
+	  and is also scheduled to replace the old syslog-based ipt_LOG
+	  and ip6t_LOG modules.
+
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
 obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
+obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
new file mode 100644
--- /dev/null
+++ b/net/netfilter/nfnetlink_log.c
@@ -0,0 +1,992 @@
+/*
+ * This is a module which is used for logging packets to userspace via
+ * nfetlink.
+ *
+ * (C) 2005 by Harald Welte <laforge@netfilter.org>
+ *
+ * Based on the old ipv4-only ipt_ULOG.c:
+ * (C) 2000-2004 by Harald Welte <laforge@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.
+ *
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/netdevice.h>
+#include <linux/netfilter.h>
+#include <linux/netlink.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_log.h>
+#include <linux/spinlock.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/security.h>
+#include <linux/list.h>
+#include <linux/jhash.h>
+#include <linux/random.h>
+#include <net/sock.h>
+
+#include <asm/atomic.h>
+
+#define NFULNL_NLBUFSIZ_DEFAULT	4096
+#define NFULNL_TIMEOUT_DEFAULT 	100	/* every second */
+#define NFULNL_QTHRESH_DEFAULT 	100	/* 100 packets */
+
+#define PRINTR(x, args ...)	do { if (net_ratelimit()) \
+				     printk(x, ## args); } while (0);
+
+#if 0
+#define UDEBUG(x, args ...)	printk(KERN_DEBUG "%s(%d):%s():	" x, 	   \
+					__FILE__, __LINE__, __FUNCTION__,  \
+					## args)
+#else
+#define UDEBUG(x, ...)
+#endif
+
+struct nfulnl_instance {
+	struct hlist_node hlist;	/* global list of instances */
+	spinlock_t lock;
+	atomic_t use;			/* use count */
+
+	unsigned int qlen;		/* number of nlmsgs in skb */
+	struct sk_buff *skb;		/* pre-allocatd skb */
+	struct nlmsghdr *lastnlh;	/* netlink header of last msg in skb */
+	struct timer_list timer;
+	int peer_pid;			/* PID of the peer process */
+
+	/* configurable parameters */
+	unsigned int flushtimeout;	/* timeout until queue flush */
+	unsigned int nlbufsiz;		/* netlink buffer allocation size */
+	unsigned int qthreshold;	/* threshold of the queue */
+	u_int32_t copy_range;
+	u_int16_t group_num;		/* number of this queue */
+	u_int8_t copy_mode;	
+};
+
+static DEFINE_RWLOCK(instances_lock);
+
+#define INSTANCE_BUCKETS	16
+static struct hlist_head instance_table[INSTANCE_BUCKETS];
+static unsigned int hash_init;
+
+static inline u_int8_t instance_hashfn(u_int16_t group_num)
+{
+	return ((group_num & 0xff) % INSTANCE_BUCKETS);
+}
+
+static struct nfulnl_instance *
+__instance_lookup(u_int16_t group_num)
+{
+	struct hlist_head *head;
+	struct hlist_node *pos;
+	struct nfulnl_instance *inst;
+
+	UDEBUG("entering (group_num=%u)\n", group_num);
+
+	head = &instance_table[instance_hashfn(group_num)];
+	hlist_for_each_entry(inst, pos, head, hlist) {
+		if (inst->group_num == group_num)
+			return inst;
+	}
+	return NULL;
+}
+
+static inline void
+instance_get(struct nfulnl_instance *inst)
+{
+	atomic_inc(&inst->use);
+}
+
+static struct nfulnl_instance *
+instance_lookup_get(u_int16_t group_num)
+{
+	struct nfulnl_instance *inst;
+
+	read_lock_bh(&instances_lock);
+	inst = __instance_lookup(group_num);
+	if (inst)
+		instance_get(inst);
+	read_unlock_bh(&instances_lock);
+
+	return inst;
+}
+
+static void
+instance_put(struct nfulnl_instance *inst)
+{
+	if (inst && atomic_dec_and_test(&inst->use)) {
+		UDEBUG("kfree(inst=%p)\n", inst);
+		kfree(inst);
+	}
+}
+
+static void nfulnl_timer(unsigned long data);
+
+static struct nfulnl_instance *
+instance_create(u_int16_t group_num, int pid)
+{
+	struct nfulnl_instance *inst;
+
+	UDEBUG("entering (group_num=%u, pid=%d)\n", group_num,
+		pid);
+
+	write_lock_bh(&instances_lock);	
+	if (__instance_lookup(group_num)) {
+		inst = NULL;
+		UDEBUG("aborting, instance already exists\n");
+		goto out_unlock;
+	}
+
+	inst = kmalloc(sizeof(*inst), GFP_ATOMIC);
+	if (!inst)
+		goto out_unlock;
+
+	memset(inst, 0, sizeof(*inst));
+	INIT_HLIST_NODE(&inst->hlist);
+	inst->lock = SPIN_LOCK_UNLOCKED;
+	/* needs to be two, since we _put() after creation */
+	atomic_set(&inst->use, 2);
+
+	init_timer(&inst->timer);
+	inst->timer.function = nfulnl_timer;
+	inst->timer.data = (unsigned long)inst;
+	/* don't start timer yet. (re)start it  with every packet */
+
+	inst->peer_pid = pid;
+	inst->group_num = group_num;
+
+	inst->qthreshold 	= NFULNL_QTHRESH_DEFAULT;
+	inst->flushtimeout 	= NFULNL_TIMEOUT_DEFAULT;
+	inst->nlbufsiz 		= NFULNL_NLBUFSIZ_DEFAULT;
+	inst->copy_mode 	= NFULNL_COPY_PACKET;
+	inst->copy_range 	= 0xffff;
+
+	if (!try_module_get(THIS_MODULE))
+		goto out_free;
+
+	hlist_add_head(&inst->hlist, 
+		       &instance_table[instance_hashfn(group_num)]);
+
+	UDEBUG("newly added node: %p, next=%p\n", &inst->hlist, 
+		inst->hlist.next);
+
+	write_unlock_bh(&instances_lock);
+
+	return inst;
+
+out_free:
+	instance_put(inst);
+out_unlock:
+	write_unlock_bh(&instances_lock);
+	return NULL;
+}
+
+static int __nfulnl_send(struct nfulnl_instance *inst);
+
+static void
+_instance_destroy2(struct nfulnl_instance *inst, int lock)
+{
+	/* first pull it out of the global list */
+	if (lock)
+		write_lock_bh(&instances_lock);
+
+	UDEBUG("removing instance %p (queuenum=%u) from hash\n",
+		inst, inst->group_num);
+
+	hlist_del(&inst->hlist);
+
+	if (lock)
+		write_unlock_bh(&instances_lock);
+
+	/* then flush all pending packets from skb */
+
+	spin_lock_bh(&inst->lock);
+	if (inst->skb) {
+		if (inst->qlen)
+			__nfulnl_send(inst);
+		if (inst->skb) {
+			kfree_skb(inst->skb);
+			inst->skb = NULL;
+		}
+	}
+	spin_unlock_bh(&inst->lock);
+
+	/* and finally put the refcount */
+	instance_put(inst);
+
+	module_put(THIS_MODULE);
+}
+
+static inline void
+__instance_destroy(struct nfulnl_instance *inst)
+{
+	_instance_destroy2(inst, 0);
+}
+
+static inline void
+instance_destroy(struct nfulnl_instance *inst)
+{
+	_instance_destroy2(inst, 1);
+}
+
+static int
+nfulnl_set_mode(struct nfulnl_instance *inst, u_int8_t mode,
+		  unsigned int range)
+{
+	int status = 0;
+
+	spin_lock_bh(&inst->lock);
+	
+	switch (mode) {
+	case NFULNL_COPY_NONE:
+	case NFULNL_COPY_META:
+		inst->copy_mode = mode;
+		inst->copy_range = 0;
+		break;
+		
+	case NFULNL_COPY_PACKET:
+		inst->copy_mode = mode;
+		/* we're using struct nfattr which has 16bit nfa_len */
+		if (range > 0xffff)
+			inst->copy_range = 0xffff;
+		else
+			inst->copy_range = range;
+		break;
+		
+	default:
+		status = -EINVAL;
+		break;
+	}
+
+	spin_unlock_bh(&inst->lock);
+
+	return status;
+}
+
+static int
+nfulnl_set_nlbufsiz(struct nfulnl_instance *inst, u_int32_t nlbufsiz)
+{
+	int status;
+
+	spin_lock_bh(&inst->lock);
+	if (nlbufsiz < NFULNL_NLBUFSIZ_DEFAULT)
+		status = -ERANGE;
+	else if (nlbufsiz > 131072)
+		status = -ERANGE;
+	else {
+		inst->nlbufsiz = nlbufsiz;
+		status = 0;
+	}
+	spin_unlock_bh(&inst->lock);
+
+	return status;
+}
+
+static int
+nfulnl_set_timeout(struct nfulnl_instance *inst, u_int32_t timeout)
+{
+	spin_lock_bh(&inst->lock);
+	inst->flushtimeout = timeout;
+	spin_unlock_bh(&inst->lock);
+
+	return 0;
+}
+
+static int
+nfulnl_set_qthresh(struct nfulnl_instance *inst, u_int32_t qthresh)
+{
+	spin_lock_bh(&inst->lock);
+	inst->qthreshold = qthresh;
+	spin_unlock_bh(&inst->lock);
+
+	return 0;
+}
+
+static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size, 
+					unsigned int pkt_size)
+{
+	struct sk_buff *skb;
+
+	UDEBUG("entered (%u, %u)\n", inst_size, pkt_size);
+
+	/* alloc skb whihc should be big enough for a whole multipart
+	 * message.  WARNING: has to be <= 128k due to slab restrictions */
+
+	skb = alloc_skb(inst_size, GFP_ATOMIC);
+	if (!skb) {
+		PRINTR("nfnetlink_log: can't alloc whole buffer (%u bytes)\n",
+			inst_size);
+
+		/* try to allocate only as much as we need for current
+		 * packet */
+
+		skb = alloc_skb(pkt_size, GFP_ATOMIC);
+		if (!skb)
+			PRINTR("nfnetlink_log: can't even alloc %u bytes\n",
+				pkt_size);
+	}
+
+	return skb;
+}
+
+static int
+__nfulnl_send(struct nfulnl_instance *inst)
+{
+	int status;
+
+	if (timer_pending(&inst->timer))
+		del_timer(&inst->timer);
+
+	if (inst->qlen > 1)
+		inst->lastnlh->nlmsg_type = NLMSG_DONE;
+
+	status = nfnetlink_unicast(inst->skb, inst->peer_pid, MSG_DONTWAIT);
+	if (status < 0) {
+		UDEBUG("netlink_unicast() failed\n");
+		/* FIXME: statistics */
+	}
+
+	inst->qlen = 0;
+	inst->skb = NULL;
+	inst->lastnlh = NULL;
+
+	return status;
+}
+
+static void nfulnl_timer(unsigned long data)
+{
+	struct nfulnl_instance *inst = (struct nfulnl_instance *)data; 
+
+	UDEBUG("timer function called, flushing buffer\n");
+
+	spin_lock_bh(&inst->lock);
+	__nfulnl_send(inst);
+	instance_put(inst);
+	spin_unlock_bh(&inst->lock);
+}
+
+static inline int 
+__build_packet_message(struct nfulnl_instance *inst,
+			const struct sk_buff *skb, 
+			unsigned int data_len,
+			unsigned int pf,
+			unsigned int hooknum,
+			const struct net_device *indev,
+			const struct net_device *outdev,
+			const struct nf_loginfo *li,
+			const char *prefix)
+{
+	unsigned char *old_tail;
+	struct nfulnl_msg_packet_hdr pmsg;
+	struct nlmsghdr *nlh;
+	struct nfgenmsg *nfmsg;
+	u_int32_t tmp_uint;
+
+	UDEBUG("entered\n");
+		
+	old_tail = inst->skb->tail;
+	nlh = NLMSG_PUT(inst->skb, 0, 0, 
+			NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET,
+			sizeof(struct nfgenmsg));
+	nfmsg = NLMSG_DATA(nlh);
+	nfmsg->nfgen_family = pf;
+	nfmsg->version = NFNETLINK_V0;
+	nfmsg->res_id = htons(inst->group_num);
+
+	pmsg.hw_protocol	= htons(skb->protocol);
+	pmsg.hook		= hooknum;
+
+	NFA_PUT(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg);
+
+	if (prefix) {
+		int slen = strlen(prefix);
+		if (slen > NFULNL_PREFIXLEN)
+			slen = NFULNL_PREFIXLEN;
+		NFA_PUT(inst->skb, NFULA_PREFIX, slen, prefix);
+	}
+
+	if (indev) {
+		tmp_uint = htonl(indev->ifindex);
+		NFA_PUT(inst->skb, NFULA_IFINDEX_INDEV, sizeof(tmp_uint),
+			&tmp_uint);
+	}
+
+	if (outdev) {
+		tmp_uint = htonl(outdev->ifindex);
+		NFA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV, sizeof(tmp_uint),
+			&tmp_uint);
+	}
+
+	if (skb->nfmark) {
+		tmp_uint = htonl(skb->nfmark);
+		NFA_PUT(inst->skb, NFULA_MARK, sizeof(tmp_uint), &tmp_uint);
+	}
+
+	if (indev && skb->dev && skb->dev->hard_header_parse) {
+		struct nfulnl_msg_packet_hw phw;
+
+		phw.hw_addrlen = 
+			skb->dev->hard_header_parse((struct sk_buff *)skb, 
+						    phw.hw_addr);
+		phw.hw_addrlen = htons(phw.hw_addrlen);
+		NFA_PUT(inst->skb, NFULA_HWADDR, sizeof(phw), &phw);
+	}
+
+	if (skb->stamp.tv_sec) {
+		struct nfulnl_msg_packet_timestamp ts;
+
+		ts.sec = cpu_to_be64(skb->stamp.tv_sec);
+		ts.usec = cpu_to_be64(skb->stamp.tv_usec);
+
+		NFA_PUT(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts);
+	}
+
+	/* UID */
+	if (skb->sk) {
+		read_lock_bh(&skb->sk->sk_callback_lock);
+		if (skb->sk->sk_socket && skb->sk->sk_socket->file) {
+			u_int32_t uid = htonl(skb->sk->sk_socket->file->f_uid);
+			/* need to unlock here since NFA_PUT may goto */
+			read_unlock_bh(&skb->sk->sk_callback_lock);
+			NFA_PUT(inst->skb, NFULA_UID, sizeof(uid), &uid);
+		} else
+			read_unlock_bh(&skb->sk->sk_callback_lock);
+	}
+
+	if (data_len) {
+		struct nfattr *nfa;
+		int size = NFA_LENGTH(data_len);
+
+		if (skb_tailroom(inst->skb) < (int)NFA_SPACE(data_len)) {
+			printk(KERN_WARNING "nfnetlink_log: no tailroom!\n");
+			goto nlmsg_failure;
+		}
+
+		nfa = (struct nfattr *)skb_put(inst->skb, NFA_ALIGN(size));
+		nfa->nfa_type = NFULA_PAYLOAD;
+		nfa->nfa_len = size;
+
+		if (skb_copy_bits(skb, 0, NFA_DATA(nfa), data_len))
+			BUG();
+	}
+		
+	nlh->nlmsg_len = inst->skb->tail - old_tail;
+	return 0;
+
+nlmsg_failure:
+	UDEBUG("nlmsg_failure\n");
+nfattr_failure:
+	PRINTR(KERN_ERR "nfnetlink_log: error creating log nlmsg\n");
+	return -1;
+}
+
+#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
+
+static struct nf_loginfo default_loginfo = {
+	.type =		NF_LOG_TYPE_ULOG,
+	.u.ulog = {
+		.copy_len	= 0xffff,
+		.group		= 0,
+		.qthreshold	= 1,
+	},
+};
+
+/* log handler for internal netfilter logging api */
+static void
+nfulnl_log_packet(unsigned int pf,
+		  unsigned int hooknum,
+		  const struct sk_buff *skb,
+		  const struct net_device *in,
+		  const struct net_device *out,
+		  const struct nf_loginfo *li_user,
+		  const char *prefix)
+{
+	unsigned int size, data_len;
+	struct nfulnl_instance *inst;
+	const struct nf_loginfo *li;
+	unsigned int qthreshold;
+	unsigned int nlbufsiz;
+
+	if (li_user && li_user->type == NF_LOG_TYPE_ULOG) 
+		li = li_user;
+	else
+		li = &default_loginfo;
+
+	inst = instance_lookup_get(li->u.ulog.group);
+	if (!inst)
+		inst = instance_lookup_get(0);
+	if (!inst) {
+		PRINTR("nfnetlink_log: trying to log packet, "
+			"but no instance for group %u\n", li->u.ulog.group);
+		return;
+	}
+
+	/* all macros expand to constant values at compile time */
+	/* FIXME: do we want to make the size calculation conditional based on
+	 * what is actually present?  way more branches and checks, but more
+	 * memory efficient... */
+	size =    NLMSG_SPACE(sizeof(struct nfgenmsg))
+		+ NFA_SPACE(sizeof(struct nfulnl_msg_packet_hdr))
+		+ NFA_SPACE(sizeof(u_int32_t))	/* ifindex */
+		+ NFA_SPACE(sizeof(u_int32_t))	/* ifindex */
+		+ NFA_SPACE(sizeof(u_int32_t))	/* mark */
+		+ NFA_SPACE(sizeof(u_int32_t))	/* uid */
+		+ NFA_SPACE(NFULNL_PREFIXLEN)	/* prefix */
+		+ NFA_SPACE(sizeof(struct nfulnl_msg_packet_hw))
+		+ NFA_SPACE(sizeof(struct nfulnl_msg_packet_timestamp));
+
+	UDEBUG("initial size=%u\n", size);
+
+	spin_lock_bh(&inst->lock);
+
+	qthreshold = inst->qthreshold;
+	/* per-rule qthreshold overrides per-instance */
+	if (qthreshold > li->u.ulog.qthreshold)
+		qthreshold = li->u.ulog.qthreshold;
+	
+	switch (inst->copy_mode) {
+	case NFULNL_COPY_META:
+	case NFULNL_COPY_NONE:
+		data_len = 0;
+		break;
+	
+	case NFULNL_COPY_PACKET:
+		if (inst->copy_range == 0 
+		    || inst->copy_range > skb->len)
+			data_len = skb->len;
+		else
+			data_len = inst->copy_range;
+		
+		size += NFA_SPACE(data_len);
+		UDEBUG("copy_packet, therefore size now %u\n", size);
+		break;
+	
+	default:
+		spin_unlock_bh(&inst->lock);
+		instance_put(inst);
+		return;
+	}
+
+	if (size > inst->nlbufsiz)
+		nlbufsiz = size;
+	else
+		nlbufsiz = inst->nlbufsiz;
+
+	if (!inst->skb) {
+		if (!(inst->skb = nfulnl_alloc_skb(nlbufsiz, size))) {
+			UDEBUG("error in nfulnl_alloc_skb(%u, %u)\n",
+				inst->nlbufsiz, size);
+			goto alloc_failure;
+		}
+	} else if (inst->qlen >= qthreshold ||
+		   size > skb_tailroom(inst->skb)) {
+		/* either the queue len is too high or we don't have
+		 * enough room in the skb left. flush to userspace. */
+		UDEBUG("flushing old skb\n");
+
+		__nfulnl_send(inst);
+
+		if (!(inst->skb = nfulnl_alloc_skb(nlbufsiz, size))) {
+			UDEBUG("error in nfulnl_alloc_skb(%u, %u)\n",
+				inst->nlbufsiz, size);
+			goto alloc_failure;
+		}
+	}
+
+	UDEBUG("qlen %d, qthreshold %d\n", inst->qlen, qthreshold);
+	inst->qlen++;
+
+	__build_packet_message(inst, skb, data_len, pf,
+				hooknum, in, out, li, prefix);
+
+	/* timer_pending always called within inst->lock, so there
+	 * is no chance of a race here */
+	if (!timer_pending(&inst->timer)) {
+		instance_get(inst);
+		inst->timer.expires = jiffies + (inst->flushtimeout*HZ/100);
+		add_timer(&inst->timer);
+	}
+	spin_unlock_bh(&inst->lock);
+
+	return;
+
+alloc_failure:
+	spin_unlock_bh(&inst->lock);
+	instance_put(inst);
+	UDEBUG("error allocating skb\n");
+	/* FIXME: statistics */
+}
+
+static int
+nfulnl_rcv_nl_event(struct notifier_block *this,
+		   unsigned long event, void *ptr)
+{
+	struct netlink_notify *n = ptr;
+
+	if (event == NETLINK_URELEASE &&
+	    n->protocol == NETLINK_NETFILTER && n->pid) {
+		int i;
+
+		/* destroy all instances for this pid */
+		write_lock_bh(&instances_lock);
+		for  (i = 0; i < INSTANCE_BUCKETS; i++) {
+			struct hlist_node *tmp, *t2;
+			struct nfulnl_instance *inst;
+			struct hlist_head *head = &instance_table[i];
+
+			hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
+				UDEBUG("node = %p\n", inst);
+				if (n->pid == inst->peer_pid)
+					__instance_destroy(inst);
+			}
+		}
+		write_unlock_bh(&instances_lock);
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block nfulnl_rtnl_notifier = {
+	.notifier_call	= nfulnl_rcv_nl_event,
+};
+
+static int
+nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb,
+		  struct nlmsghdr *nlh, struct nfattr *nfqa[], int *errp)
+{
+	return -ENOTSUPP;
+}
+
+static struct nf_logger nfulnl_logger = {
+	.name	= "nfnetlink_log",
+	.logfn	= &nfulnl_log_packet,
+	.me	= THIS_MODULE,
+};
+
+static const int nfula_min[NFULA_MAX] = {
+	[NFULA_PACKET_HDR-1]	= sizeof(struct nfulnl_msg_packet_hdr),
+	[NFULA_MARK-1]		= sizeof(u_int32_t),
+	[NFULA_TIMESTAMP-1]	= sizeof(struct nfulnl_msg_packet_timestamp),
+	[NFULA_IFINDEX_INDEV-1]	= sizeof(u_int32_t),
+	[NFULA_IFINDEX_OUTDEV-1]= sizeof(u_int32_t),
+	[NFULA_HWADDR-1]	= sizeof(struct nfulnl_msg_packet_hw),
+	[NFULA_PAYLOAD-1]	= 0,
+	[NFULA_PREFIX-1]	= 0,
+	[NFULA_UID-1]		= sizeof(u_int32_t),
+};
+
+static const int nfula_cfg_min[NFULA_CFG_MAX] = {
+	[NFULA_CFG_CMD-1]	= sizeof(struct nfulnl_msg_config_cmd),
+	[NFULA_CFG_MODE-1]	= sizeof(struct nfulnl_msg_config_mode),
+	[NFULA_CFG_TIMEOUT-1]	= sizeof(u_int32_t),
+	[NFULA_CFG_QTHRESH-1]	= sizeof(u_int32_t),
+	[NFULA_CFG_NLBUFSIZ-1]	= sizeof(u_int32_t),
+};
+
+static int
+nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
+		   struct nlmsghdr *nlh, struct nfattr *nfula[], int *errp)
+{
+	struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+	u_int16_t group_num = ntohs(nfmsg->res_id);
+	struct nfulnl_instance *inst;
+	int ret = 0;
+
+	UDEBUG("entering for msg %u\n", NFNL_MSG_TYPE(nlh->nlmsg_type));
+
+	if (nfattr_bad_size(nfula, NFULA_CFG_MAX, nfula_cfg_min)) {
+		UDEBUG("bad attribute size\n");
+		return -EINVAL;
+	}
+
+	inst = instance_lookup_get(group_num);
+	if (nfula[NFULA_CFG_CMD-1]) {
+		u_int8_t pf = nfmsg->nfgen_family;
+		struct nfulnl_msg_config_cmd *cmd;
+		cmd = NFA_DATA(nfula[NFULA_CFG_CMD-1]);
+		UDEBUG("found CFG_CMD for\n");
+
+		switch (cmd->command) {
+		case NFULNL_CFG_CMD_BIND:
+			if (inst) {
+				ret = -EBUSY;
+				goto out_put;
+			}
+
+			inst = instance_create(group_num,
+					       NETLINK_CB(skb).pid);
+			if (!inst) {
+				ret = -EINVAL;
+				goto out_put;
+			}
+			break;
+		case NFULNL_CFG_CMD_UNBIND:
+			if (!inst) {
+				ret = -ENODEV;
+				goto out_put;
+			}
+
+			if (inst->peer_pid != NETLINK_CB(skb).pid) {
+				ret = -EPERM;
+				goto out_put;
+			}
+
+			instance_destroy(inst);
+			break;
+		case NFULNL_CFG_CMD_PF_BIND:
+			UDEBUG("registering log handler for pf=%u\n", pf);
+			ret = nf_log_register(pf, &nfulnl_logger);
+			break;
+		case NFULNL_CFG_CMD_PF_UNBIND:
+			UDEBUG("unregistering log handler for pf=%u\n", pf);
+			/* This is a bug and a feature.  We cannot unregister
+			 * other handlers, like nfnetlink_inst can */
+			nf_log_unregister_pf(pf);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+	} else {
+		if (!inst) {
+			UDEBUG("no config command, and no instance for "
+				"group=%u pid=%u =>ENOENT\n",
+				group_num, NETLINK_CB(skb).pid);
+			ret = -ENOENT;
+			goto out_put;
+		}
+
+		if (inst->peer_pid != NETLINK_CB(skb).pid) {
+			UDEBUG("no config command, and wrong pid\n");
+			ret = -EPERM;
+			goto out_put;
+		}
+	}
+
+	if (nfula[NFULA_CFG_MODE-1]) {
+		struct nfulnl_msg_config_mode *params;
+		params = NFA_DATA(nfula[NFULA_CFG_MODE-1]);
+
+		nfulnl_set_mode(inst, params->copy_mode,
+				ntohs(params->copy_range));
+	}
+
+	if (nfula[NFULA_CFG_TIMEOUT-1]) {
+		u_int32_t timeout = 
+			*(u_int32_t *)NFA_DATA(nfula[NFULA_CFG_TIMEOUT-1]);
+
+		nfulnl_set_timeout(inst, ntohl(timeout));
+	}
+
+	if (nfula[NFULA_CFG_NLBUFSIZ-1]) {
+		u_int32_t nlbufsiz = 
+			*(u_int32_t *)NFA_DATA(nfula[NFULA_CFG_NLBUFSIZ-1]);
+
+		nfulnl_set_nlbufsiz(inst, ntohl(nlbufsiz));
+	}
+
+	if (nfula[NFULA_CFG_QTHRESH-1]) {
+		u_int32_t qthresh = 
+			*(u_int16_t *)NFA_DATA(nfula[NFULA_CFG_QTHRESH-1]);
+
+		nfulnl_set_qthresh(inst, ntohl(qthresh));
+	}
+
+out_put:
+	instance_put(inst);
+	return ret;
+}
+
+static struct nfnl_callback nfulnl_cb[NFULNL_MSG_MAX] = {
+	[NFULNL_MSG_PACKET]	= { .call = nfulnl_recv_unsupp,
+				    .cap_required = CAP_NET_ADMIN },
+	[NFULNL_MSG_CONFIG]	= { .call = nfulnl_recv_config,
+				    .cap_required = CAP_NET_ADMIN },
+};
+
+static struct nfnetlink_subsystem nfulnl_subsys = {
+	.name		= "log",
+	.subsys_id	= NFNL_SUBSYS_ULOG,
+	.cb_count	= NFULNL_MSG_MAX,
+	.attr_count	= NFULA_MAX,
+	.cb		= nfulnl_cb,
+};
+
+#ifdef CONFIG_PROC_FS
+struct iter_state {
+	unsigned int bucket;
+};
+
+static struct hlist_node *get_first(struct seq_file *seq)
+{
+	struct iter_state *st = seq->private;
+
+	if (!st)
+		return NULL;
+
+	for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
+		if (!hlist_empty(&instance_table[st->bucket]))
+			return instance_table[st->bucket].first;
+	}
+	return NULL;
+}
+
+static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h)
+{
+	struct iter_state *st = seq->private;
+
+	h = h->next;
+	while (!h) {
+		if (++st->bucket >= INSTANCE_BUCKETS)
+			return NULL;
+
+		h = instance_table[st->bucket].first;
+	}
+	return h;
+}
+
+static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct hlist_node *head;
+	head = get_first(seq);
+
+	if (head)
+		while (pos && (head = get_next(seq, head)))
+			pos--;
+	return pos ? NULL : head;
+}
+
+static void *seq_start(struct seq_file *seq, loff_t *pos)
+{
+	read_lock_bh(&instances_lock);
+	return get_idx(seq, *pos);
+}
+
+static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return get_next(s, v);
+}
+
+static void seq_stop(struct seq_file *s, void *v)
+{
+	read_unlock_bh(&instances_lock);
+}
+
+static int seq_show(struct seq_file *s, void *v)
+{
+	const struct nfulnl_instance *inst = v;
+
+	return seq_printf(s, "%5d %6d %5d %1d %5d %6d %2d\n", 
+			  inst->group_num,
+			  inst->peer_pid, inst->qlen, 
+			  inst->copy_mode, inst->copy_range,
+			  inst->flushtimeout, atomic_read(&inst->use));
+}
+
+static struct seq_operations nful_seq_ops = {
+	.start	= seq_start,
+	.next	= seq_next,
+	.stop	= seq_stop,
+	.show	= seq_show,
+};
+
+static int nful_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	struct iter_state *is;
+	int ret;
+
+	is = kmalloc(sizeof(*is), GFP_KERNEL);
+	if (!is)
+		return -ENOMEM;
+	memset(is, 0, sizeof(*is));
+	ret = seq_open(file, &nful_seq_ops);
+	if (ret < 0)
+		goto out_free;
+	seq = file->private_data;
+	seq->private = is;
+	return ret;
+out_free:
+	kfree(is);
+	return ret;
+}
+
+static struct file_operations nful_file_ops = {
+	.owner	 = THIS_MODULE,
+	.open	 = nful_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = seq_release_private,
+};
+
+#endif /* PROC_FS */
+
+static int
+init_or_cleanup(int init)
+{
+	int i, status = -ENOMEM;
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry *proc_nful;
+#endif
+	
+	if (!init)
+		goto cleanup;
+
+	for (i = 0; i < INSTANCE_BUCKETS; i++)
+		INIT_HLIST_HEAD(&instance_table[i]);
+	
+	/* it's not really all that important to have a random value, so
+	 * we can do this from the init function, even if there hasn't
+	 * been that much entropy yet */
+	get_random_bytes(&hash_init, sizeof(hash_init));
+
+	netlink_register_notifier(&nfulnl_rtnl_notifier);
+	status = nfnetlink_subsys_register(&nfulnl_subsys);
+	if (status < 0) {
+		printk(KERN_ERR "log: failed to create netlink socket\n");
+		goto cleanup_netlink_notifier;
+	}
+
+#ifdef CONFIG_PROC_FS
+	proc_nful = create_proc_entry("nfnetlink_log", 0440,
+				      proc_net_netfilter);
+	if (!proc_nful)
+		goto cleanup_subsys;
+	proc_nful->proc_fops = &nful_file_ops;
+#endif
+
+	return status;
+
+cleanup:
+	nf_log_unregister_logger(&nfulnl_logger);
+#ifdef CONFIG_PROC_FS
+cleanup_subsys:
+#endif
+	nfnetlink_subsys_unregister(&nfulnl_subsys);
+cleanup_netlink_notifier:
+	netlink_unregister_notifier(&nfulnl_rtnl_notifier);
+	return status;
+}
+
+static int __init init(void)
+{
+	
+	return init_or_cleanup(1);
+}
+
+static void __exit fini(void)
+{
+	init_or_cleanup(0);
+}
+
+MODULE_DESCRIPTION("netfilter userspace logging");
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_LICENSE("GPL");
+
+module_init(init);
+module_exit(fini);

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH] add refcounting and /proc to nfnetlink_queue
From: Harald Welte @ 2005-07-30 10:32 UTC (permalink / raw)
  To: David Miller; +Cc: Linux Netdev List, Netfilter Development Mailinglist


[-- Attachment #1.1: Type: text/plain, Size: 546 bytes --]

Hi Dave!

This patch is against nfnetlink_queue (which is already in your
net-2.6.14 tree).  Since it adds a file to /proc/net/netfilter, it also
depends on <20050728200434.GA3763@rama.de.gnumonks.org>.

Please apply, thanks.

-- 
- Harald Welte <laforge@gnumonks.org>          	        http://gnumonks.org/
============================================================================
"Privacy in residential applications is a desirable marketing option."
                                                  (ETSI EN 300 175-7 Ch. A6)

[-- Attachment #1.2: 18-nfnetlink_queue-refcount.patch --]
[-- Type: text/plain, Size: 12351 bytes --]

[NETFILTER] Add refcounting and /proc/net/netfilter interface to
	    nfnetlink_queue

Signed-off-by: Harald Welte <laforge@netfilter.org>

---
commit f00815c7d2b718eccbc3e7ec77592faff45e9ccc
tree 3af9c34bcc5bfb11f1a71f20694f4cae78f40cb4
parent 66ad9b079da5c6a181506fba350aa33d26417431
author laforge <laforge@netfilter.org> Sa, 30 Jul 2005 12:12:26 +0200
committer laforge <laforge@netfilter.org> Sa, 30 Jul 2005 12:12:26 +0200

 include/linux/netfilter/nfnetlink_queue.h |    1 
 net/netfilter/nfnetlink_queue.c           |  248 ++++++++++++++++++++++++++---
 2 files changed, 221 insertions(+), 28 deletions(-)

diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h
--- a/include/linux/netfilter/nfnetlink_queue.h
+++ b/include/linux/netfilter/nfnetlink_queue.h
@@ -81,5 +81,6 @@ enum nfqnl_attr_config {
 	NFQA_CFG_PARAMS,		/* nfqnl_msg_config_params */
 	__NFQA_CFG_MAX
 };
+#define NFQA_CFG_MAX (__NFQA_CFG_MAX-1)
 
 #endif /* _NFNETLINK_QUEUE_H */
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -20,6 +20,7 @@
 #include <linux/notifier.h>
 #include <linux/netdevice.h>
 #include <linux/netfilter.h>
+#include <linux/proc_fs.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
 #include <linux/netfilter/nfnetlink.h>
@@ -48,6 +49,7 @@ struct nfqnl_queue_entry {
 
 struct nfqnl_instance {
 	struct hlist_node hlist;		/* global list of queues */
+	atomic_t use;
 
 	int peer_pid;
 	unsigned int queue_maxlen;
@@ -105,17 +107,28 @@ __instance_lookup(u_int16_t queue_num)
 }
 
 static struct nfqnl_instance *
-instance_lookup(u_int16_t queue_num)
+instance_lookup_get(u_int16_t queue_num)
 {
 	struct nfqnl_instance *inst;
 
 	read_lock_bh(&instances_lock);
 	inst = __instance_lookup(queue_num);
+	if (inst)
+		atomic_inc(&inst->use);
 	read_unlock_bh(&instances_lock);
 
 	return inst;
 }
 
+static void
+instance_put(struct nfqnl_instance *inst)
+{
+	if (inst && atomic_dec_and_test(&inst->use)) {
+		QDEBUG("kfree(inst=%p)\n", inst);
+		kfree(inst);
+	}
+}
+
 static struct nfqnl_instance *
 instance_create(u_int16_t queue_num, int pid)
 {
@@ -141,6 +154,8 @@ instance_create(u_int16_t queue_num, int
 	inst->copy_range = 0xfffff;
 	inst->copy_mode = NFQNL_COPY_NONE;
 	atomic_set(&inst->id_sequence, 0);
+	/* needs to be two, since we _put() after creation */
+	atomic_set(&inst->use, 2);
 	inst->lock = SPIN_LOCK_UNLOCKED;
 	INIT_LIST_HEAD(&inst->queue_list);
 
@@ -182,8 +197,8 @@ _instance_destroy2(struct nfqnl_instance
 	/* then flush all pending skbs from the queue */
 	nfqnl_flush(inst, NF_DROP);
 
-	/* and finally free the data structure */
-	kfree(inst);
+	/* and finally put the refcount */
+	instance_put(inst);
 
 	module_put(THIS_MODULE);
 }
@@ -471,7 +486,7 @@ nfqnl_enqueue_packet(struct sk_buff *skb
 
 	QDEBUG("entered\n");
 
-	queue = instance_lookup(queuenum);
+	queue = instance_lookup_get(queuenum);
 	if (!queue) {
 		QDEBUG("no queue instance matching\n");
 		return -EINVAL;
@@ -479,7 +494,8 @@ nfqnl_enqueue_packet(struct sk_buff *skb
 
 	if (queue->copy_mode == NFQNL_COPY_NONE) {
 		QDEBUG("mode COPY_NONE, aborting\n");
-		return -EAGAIN;
+		status = -EAGAIN;
+		goto err_out_put;
 	}
 
 	entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
@@ -487,7 +503,8 @@ nfqnl_enqueue_packet(struct sk_buff *skb
 		if (net_ratelimit())
 			printk(KERN_ERR 
 				"nf_queue: OOM in nfqnl_enqueue_packet()\n");
-		return -ENOMEM;
+		status = -ENOMEM;
+		goto err_out_put;
 	}
 
 	entry->info = info;
@@ -523,6 +540,7 @@ nfqnl_enqueue_packet(struct sk_buff *skb
 	__enqueue_entry(queue, entry);
 
 	spin_unlock_bh(&queue->lock);
+	instance_put(queue);
 	return status;
 
 err_out_free_nskb:
@@ -533,6 +551,8 @@ err_out_unlock:
 
 err_out_free:
 	kfree(entry);
+err_out_put:
+	instance_put(queue);
 	return status;
 }
 
@@ -685,6 +705,12 @@ static struct notifier_block nfqnl_rtnl_
 	.notifier_call	= nfqnl_rcv_nl_event,
 };
 
+static const int nfqa_verdict_min[NFQA_MAX] = {
+	[NFQA_VERDICT_HDR-1]	= sizeof(struct nfqnl_msg_verdict_hdr),
+	[NFQA_MARK-1]		= sizeof(u_int32_t),
+	[NFQA_PAYLOAD-1]	= 0,
+};
+
 static int
 nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
 		   struct nlmsghdr *nlh, struct nfattr *nfqa[], int *errp)
@@ -696,26 +722,40 @@ nfqnl_recv_verdict(struct sock *ctnl, st
 	struct nfqnl_instance *queue;
 	unsigned int verdict;
 	struct nfqnl_queue_entry *entry;
+	int err;
 
-	queue = instance_lookup(queue_num);
+	if (nfattr_bad_size(nfqa, NFQA_MAX, nfqa_verdict_min)) {
+		QDEBUG("bad attribute size\n");
+		return -EINVAL;
+	}
+
+	queue = instance_lookup_get(queue_num);
 	if (!queue)
 		return -ENODEV;
 
-	if (queue->peer_pid != NETLINK_CB(skb).pid)
-		return -EPERM;
+	if (queue->peer_pid != NETLINK_CB(skb).pid) {
+		err = -EPERM;
+		goto err_out_put;
+	}
 
-	if (!nfqa[NFQA_VERDICT_HDR-1])
-		return -EINVAL;
+	if (!nfqa[NFQA_VERDICT_HDR-1]) {
+		err = -EINVAL;
+		goto err_out_put;
+	}
 
 	vhdr = NFA_DATA(nfqa[NFQA_VERDICT_HDR-1]);
 	verdict = ntohl(vhdr->verdict);
 
-	if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT)
-		return -EINVAL;
+	if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT) {
+		err = -EINVAL;
+		goto err_out_put;
+	}
 
 	entry = find_dequeue_entry(queue, id_cmp, ntohl(vhdr->id));
-	if (entry == NULL)
-		return -ENOENT;
+	if (entry == NULL) {
+		err = -ENOENT;
+		goto err_out_put;
+	}
 
 	if (nfqa[NFQA_PAYLOAD-1]) {
 		if (nfqnl_mangle(NFA_DATA(nfqa[NFQA_PAYLOAD-1]),
@@ -727,7 +767,12 @@ nfqnl_recv_verdict(struct sock *ctnl, st
 		skb->nfmark = ntohl(*(u_int32_t *)NFA_DATA(nfqa[NFQA_MARK-1]));
 		
 	issue_verdict(entry, verdict);
+	instance_put(queue);
 	return 0;
+
+err_out_put:
+	instance_put(queue);
+	return err;
 }
 
 static int
@@ -737,6 +782,11 @@ nfqnl_recv_unsupp(struct sock *ctnl, str
 	return -ENOTSUPP;
 }
 
+static const int nfqa_cfg_min[NFQA_CFG_MAX] = {
+	[NFQA_CFG_CMD-1]	= sizeof(struct nfqnl_msg_config_cmd),
+	[NFQA_CFG_PARAMS-1]	= sizeof(struct nfqnl_msg_config_params),
+};
+
 static int
 nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
 		  struct nlmsghdr *nlh, struct nfattr *nfqa[], int *errp)
@@ -744,10 +794,16 @@ nfqnl_recv_config(struct sock *ctnl, str
 	struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
 	u_int16_t queue_num = ntohs(nfmsg->res_id);
 	struct nfqnl_instance *queue;
+	int ret = 0;
 
 	QDEBUG("entering for msg %u\n", NFNL_MSG_TYPE(nlh->nlmsg_type));
 
-	queue = instance_lookup(queue_num);
+	if (nfattr_bad_size(nfqa, NFQA_CFG_MAX, nfqa_cfg_min)) {
+		QDEBUG("bad attribute size\n");
+		return -EINVAL;
+	}
+
+	queue = instance_lookup_get(queue_num);
 	if (nfqa[NFQA_CFG_CMD-1]) {
 		struct nfqnl_msg_config_cmd *cmd;
 		cmd = NFA_DATA(nfqa[NFQA_CFG_CMD-1]);
@@ -766,17 +822,19 @@ nfqnl_recv_config(struct sock *ctnl, str
 			if (!queue)
 				return -ENODEV;
 
-			if (queue->peer_pid != NETLINK_CB(skb).pid)
-				return -EPERM;
+			if (queue->peer_pid != NETLINK_CB(skb).pid) {
+				ret = -EPERM;
+				goto out_put;
+			}
 
 			instance_destroy(queue);
 			break;
 		case NFQNL_CFG_CMD_PF_BIND:
 			QDEBUG("registering queue handler for pf=%u\n",
 				ntohs(cmd->pf));
-			return nf_register_queue_handler(ntohs(cmd->pf),
-							 nfqnl_enqueue_packet,
-							 NULL);
+			ret = nf_register_queue_handler(ntohs(cmd->pf),
+							nfqnl_enqueue_packet,
+							NULL);
 
 			break;
 		case NFQNL_CFG_CMD_PF_UNBIND:
@@ -784,20 +842,23 @@ nfqnl_recv_config(struct sock *ctnl, str
 				ntohs(cmd->pf));
 			/* This is a bug and a feature.  We can unregister
 			 * other handlers(!) */
-			return nf_unregister_queue_handler(ntohs(cmd->pf));
+			ret = nf_unregister_queue_handler(ntohs(cmd->pf));
 			break;
 		default:
-			return -EINVAL;
+			ret = -EINVAL;
+			break;
 		}
 	} else {
 		if (!queue) {
 			QDEBUG("no config command, and no instance ENOENT\n");
-			return -ENOENT;
+			ret = -ENOENT;
+			goto out_put;
 		}
 
 		if (queue->peer_pid != NETLINK_CB(skb).pid) {
 			QDEBUG("no config command, and wrong pid\n");
-			return -EPERM;
+			ret = -EPERM;
+			goto out_put;
 		}
 	}
 
@@ -809,7 +870,9 @@ nfqnl_recv_config(struct sock *ctnl, str
 				ntohl(params->copy_range));
 	}
 
-	return 0;
+out_put:
+	instance_put(queue);
+	return ret;
 }
 
 static struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = {
@@ -829,14 +892,132 @@ static struct nfnetlink_subsystem nfqnl_
 	.cb		= nfqnl_cb,
 };
 
+#ifdef CONFIG_PROC_FS
+struct iter_state {
+	unsigned int bucket;
+};
+
+static struct hlist_node *get_first(struct seq_file *seq)
+{
+	struct iter_state *st = seq->private;
+
+	if (!st)
+		return NULL;
+
+	for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
+		if (!hlist_empty(&instance_table[st->bucket]))
+			return instance_table[st->bucket].first;
+	}
+	return NULL;
+}
+
+static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h)
+{
+	struct iter_state *st = seq->private;
+
+	h = h->next;
+	while (!h) {
+		if (++st->bucket >= INSTANCE_BUCKETS)
+			return NULL;
+
+		h = instance_table[st->bucket].first;
+	}
+	return h;
+}
+
+static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct hlist_node *head;
+	head = get_first(seq);
+
+	if (head)
+		while (pos && (head = get_next(seq, head)))
+			pos--;
+	return pos ? NULL : head;
+}
+
+static void *seq_start(struct seq_file *seq, loff_t *pos)
+{
+	read_lock_bh(&instances_lock);
+	return get_idx(seq, *pos);
+}
+
+static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return get_next(s, v);
+}
+
+static void seq_stop(struct seq_file *s, void *v)
+{
+	read_unlock_bh(&instances_lock);
+}
+
+static int seq_show(struct seq_file *s, void *v)
+{
+	const struct nfqnl_instance *inst = v;
+
+	return seq_printf(s, "%5d %6d %5d %1d %5d %5d %5d %8d %2d\n",
+			  inst->queue_num,
+			  inst->peer_pid, inst->queue_total,
+			  inst->copy_mode, inst->copy_range,
+			  inst->queue_dropped, inst->queue_user_dropped,
+			  atomic_read(&inst->id_sequence),
+			  atomic_read(&inst->use));
+}
+
+static struct seq_operations nfqnl_seq_ops = {
+	.start	= seq_start,
+	.next	= seq_next,
+	.stop	= seq_stop,
+	.show	= seq_show,
+};
+
+static int nfqnl_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	struct iter_state *is;
+	int ret;
+
+	is = kmalloc(sizeof(*is), GFP_KERNEL);
+	if (!is)
+		return -ENOMEM;
+	memset(is, 0, sizeof(*is));
+	ret = seq_open(file, &nfqnl_seq_ops);
+	if (ret < 0)
+		goto out_free;
+	seq = file->private_data;
+	seq->private = is;
+	return ret;
+out_free:
+	kfree(is);
+	return ret;
+}
+
+static struct file_operations nfqnl_file_ops = {
+	.owner	 = THIS_MODULE,
+	.open	 = nfqnl_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = seq_release_private,
+};
+
+#endif /* PROC_FS */
+
 static int
 init_or_cleanup(int init)
 {
-	int status = -ENOMEM;
+	int i, status = -ENOMEM;
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry *proc_nfqueue;
+#endif
 	
 	if (!init)
 		goto cleanup;
 
+	for (i = 0; i < INSTANCE_BUCKETS; i++)
+		INIT_HLIST_HEAD(&instance_table[i]);
+
 	netlink_register_notifier(&nfqnl_rtnl_notifier);
 	status = nfnetlink_subsys_register(&nfqnl_subsys);
 	if (status < 0) {
@@ -844,14 +1025,25 @@ init_or_cleanup(int init)
 		goto cleanup_netlink_notifier;
 	}
 
+#ifdef CONFIG_PROC_FS
+	proc_nfqueue = create_proc_entry("nfnetlink_queue", 0440,
+					 proc_net_netfilter);
+	if (!proc_nfqueue)
+		goto cleanup_subsys;
+	proc_nfqueue->proc_fops = &nfqnl_file_ops;
+#endif
+
 	register_netdevice_notifier(&nfqnl_dev_notifier);
+
 	return status;
 
 cleanup:
 	nf_unregister_queue_handlers(nfqnl_enqueue_packet);
 	unregister_netdevice_notifier(&nfqnl_dev_notifier);
+#ifdef CONFIG_PROC_FS
+cleanup_subsys:
+#endif	
 	nfnetlink_subsys_unregister(&nfqnl_subsys);
-	
 cleanup_netlink_notifier:
 	netlink_unregister_notifier(&nfqnl_rtnl_notifier);
 	return status;

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: [PATCH 2.6.12.2] XFRM: BEET IPsec mode for Linux
From: Diego Beltrami @ 2005-07-30 11:01 UTC (permalink / raw)
  To: Herbert Xu; +Cc: Pekka Nikander, netdev, infrahip, hipl-users, hipsec
In-Reply-To: <20050729234859.GA27325@gondor.apana.org.au>

> On Fri, Jul 29, 2005 at 05:45:24PM +0200, Pekka Nikander wrote:
> > >Surely BEET will work also for AH with minor changes, even though we
> > >only tried the ESP encapsulation.
> > 
> > I wouldn't be so sure.  IIRC, tunnel mode is not specified for AH but  
> > for ESP only.  Consequently, defining BEET mode for AH might be  
> 
> Well plain tunnel mode certainly is specified for AH as well as IPComp.
> But you're right the semantics of BEET mode for AH needs to be thought
> out.
> 

The Linux patch which has been presented (see URL: 
http://infrahip.hiit.fi/beet/beet-patch-v1.0-2.6.12.2 ), has been
developed based upon the design given by the draft

http://www.ietf.org/internet-drafts/draft-nikander-esp-beet-mode-03.txt

As a result BEET patch considers the ESP encapsulation as it has been
designed.

OTOH we believe the implementation is usable more or less as it is now
for AH and perhaps IPComp in the future. But, as already mentioned both
by Pekka and Herbert, this would need more thinking and designing.

The implementation is flexible enough to finetune once the semantics for
similar optimizations have been considered for AH and IPComp.

--Diego

^ permalink raw reply

* Re: [hipl-users] Re: [PATCH 2.6.12.2] XFRM: BEET IPsec mode for Linux
From: Herbert Xu @ 2005-07-30 11:15 UTC (permalink / raw)
  To: diego.beltrami; +Cc: herbert, infrahip, netdev
In-Reply-To: <1122651216.25842.67.camel@odysse>

Diego Beltrami <diego.beltrami@hiit.fi> wrote:
> 
> The modifications in the ESP functions are due to the hybrid cases when
> Inner and Outer address families are different; in those cases the
> values returned by espX functions are not coherent.

I see.  However, this is really a consequence of us not implementing
interfamily transforms for plain old tunnel mode.  Had we implemented
that, it would be a piece of cake to extend this to BEET without
touching ESP.

>> Also, if you're going to do cross-family transforms, it should be
>> done for both BEET and plain tunnel-mode.
> 
> Potentially it could be possible also for plain tunnel-mode: this will
> require further analysis.

It definitely does need further analysis even for BEET mode.  The rcv
path for interfamily transforms is straightforward since we pass through
netif_rx.  However, on the outbound path things aren't that simple.

I suggest that you remove the interfamily support for the initial merge
of the BEET implementation.  We can then readd it for both plain tunnel
and BEET mode.

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH] MASQUERADE: inherit masq_index to slave connections
From: Harald Welte @ 2005-07-30 13:55 UTC (permalink / raw)
  To: David Miller; +Cc: Linux Netdev List, Netfilter Development Mailinglist


[-- Attachment #1.1: Type: text/plain, Size: 606 bytes --]

Hi Dave!

This fixes a bug with MASQUERADE and nat helpers.  The fix applies to
both net-2.6.14 and Linus' current git tree.

I'll send a 2.4.31 version of the patch directly to Marcelo (will Cc
you).

Please apply, thanks.

-- 
- Harald Welte <laforge@netfilter.org>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

[-- Attachment #1.2: 19-masq_index-inheritance.patch --]
[-- Type: text/plain, Size: 1391 bytes --]

[NETFILTER] Inherit masq_index to slave connections

masq_index is used for cleanup in case the interface address changes
(such as a dialup ppp link with dynamic addreses).  Without this patch,
slave connections are not evicted in such a case, since they don't inherit
masq_index.

Signed-off-by: Harald Welte <laforge@netfilter.org>

---
commit bd4123d85f932f9bd60da9d2ed3523dc7b792075
tree a0218fc4d42630d33d99b4167f6dccf209cfd091
parent f00815c7d2b718eccbc3e7ec77592faff45e9ccc
author laforge <laforge@netfilter.org> Sa, 30 Jul 2005 15:35:35 +0200
committer laforge <laforge@netfilter.org> Sa, 30 Jul 2005 15:35:35 +0200

 net/ipv4/netfilter/ip_conntrack_core.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -726,6 +726,11 @@ init_conntrack(struct ip_conntrack_tuple
 #if CONFIG_IP_NF_CONNTRACK_MARK
 		conntrack->mark = exp->master->mark;
 #endif
+#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
+    defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
+		/* this is ugly, but there is no other place where to put it */
+		conntrack->nat.masq_index = exp->master->nat.masq_index;
+#endif
 		nf_conntrack_get(&conntrack->master->ct_general);
 		CONNTRACK_STAT_INC(expect_new);
 	} else {

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH] MASQUERADE: inherit masq_index to slave connections
From: Harald Welte @ 2005-07-30 14:00 UTC (permalink / raw)
  To: Marcelo Tossati; +Cc: Linux Netdev List, Netfilter Development Mailinglist


[-- Attachment #1.1: Type: text/plain, Size: 514 bytes --]

Hi Marcelo!

Pleae apply the following trivial fix to your 2.4.x tree.  I've already
submitted a 2.6.x fix for this to davem.

Thanks!

-- 
- Harald Welte <laforge@netfilter.org>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

[-- Attachment #1.2: 19-masq_index-inheritance.patch --]
[-- Type: text/plain, Size: 1183 bytes --]

[NETFILTER] Inherit masq_index to slave connections

masq_index is used for cleanup in case the interface address changes
(such as a dialup ppp link with dynamic addreses).  Without this patch,
slave connections are not evicted in such a case, since they don't inherit
masq_index.

Signed-off-by: Harald Welte <laforge@netfilter.org>

Index: linux-2.4.31/net/ipv4/netfilter/ip_conntrack_core.c
===================================================================
--- linux-2.4.31.orig/net/ipv4/netfilter/ip_conntrack_core.c	2005-04-04 03:42:20.000000000 +0200
+++ linux-2.4.31/net/ipv4/netfilter/ip_conntrack_core.c	2005-07-30 15:59:41.000000000 +0200
@@ -741,6 +741,11 @@
 		/* Welcome, Mr. Bond.  We've been expecting you... */
 		__set_bit(IPS_EXPECTED_BIT, &conntrack->status);
 		conntrack->master = expected;
+#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
+    defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
+		/* this is ugly, but there is no other place where to put it */
+		conntrack->nat.masq_index = expected->expectant->nat.masq_index;
+#endif
 		expected->sibling = conntrack;
 		LIST_DELETE(&ip_conntrack_expect_list, expected);
 		expected->expectant->expecting--;

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: [PATCH] add new nfnetlink_log subsystem
From: Sven Schuster @ 2005-07-30 16:41 UTC (permalink / raw)
  To: Harald Welte, David Miller, Linux Netdev List,
	Netfilter Development Mailinglist
In-Reply-To: <20050730103005.GB6620@rama.de.gnumonks.org>

[-- Attachment #1: Type: text/plain, Size: 1456 bytes --]


Hi Harald,

On Sat, Jul 30, 2005 at 12:30:05PM +0200, Harald Welte told us:
> diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
> new file mode 100644
> --- /dev/null
> +++ b/net/netfilter/nfnetlink_log.c
> @@ -0,0 +1,992 @@
...
> +static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size, 
> +					unsigned int pkt_size)
> +{
> +	struct sk_buff *skb;
> +
> +	UDEBUG("entered (%u, %u)\n", inst_size, pkt_size);
> +
> +	/* alloc skb whihc should be big enough for a whole multipart

typo, which

> +	 * message.  WARNING: has to be <= 128k due to slab restrictions */
> +

...

> +
> +static int
> +init_or_cleanup(int init)
> +{

...

> +#ifdef CONFIG_PROC_FS
> +	proc_nful = create_proc_entry("nfnetlink_log", 0440,
> +				      proc_net_netfilter);
> +	if (!proc_nful)
> +		goto cleanup_subsys;
> +	proc_nful->proc_fops = &nful_file_ops;
> +#endif
> +
> +	return status;
> +
> +cleanup:
> +	nf_log_unregister_logger(&nfulnl_logger);
> +#ifdef CONFIG_PROC_FS
> +cleanup_subsys:

no remove_proc_entry??

> +#endif
> +	nfnetlink_subsys_unregister(&nfulnl_subsys);
> +cleanup_netlink_notifier:
> +	netlink_unregister_notifier(&nfulnl_rtnl_notifier);
> +	return status;
> +}
> +

Kind regards,

Sven

-- 
Linux zion 2.6.13-rc3-mm1 #17 PREEMPT Thu Jul 28 02:56:37 CEST 2005 i686 athlon i386 GNU/Linux
 18:34:22 up 19:35,  2 users,  load average: 0.28, 0.11, 0.03

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: [PATCH] add new nfnetlink_log subsystem
From: Harald Welte @ 2005-07-30 17:33 UTC (permalink / raw)
  To: Sven Schuster; +Cc: Linux Netdev List, Netfilter Development Mailinglist
In-Reply-To: <20050730164121.GA14794@zion.homelinux.com>


[-- Attachment #1.1: Type: text/plain, Size: 543 bytes --]

Thanks for your comments, Sven.

Dave: Please apply the attached patch on top of all other patches I sent
you. It also fixes the same bug in nfnetlink_queue. Thanks!

-- 
- Harald Welte <laforge@netfilter.org>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

[-- Attachment #1.2: 20-proc_net_remove.patch --]
[-- Type: text/plain, Size: 1894 bytes --]

[NETFILTER] add proc_net_remove() to nfnetlink_queue and nfnetlink_log

Also fixes a typo inside a comment.
Thanks to Sven Schuster <schuster.sven@gmx.de>

Signed-off-by: Harald Welte <laforge@netfilter.org>

---
commit a04a82e4fe4be531383909217bcb2d4ad096ecda
tree 1424e9d687c2b5217d82bcf04abb97a2f8aced69
parent bd4123d85f932f9bd60da9d2ed3523dc7b792075
author laforge <laforge@netfilter.org> Sa, 30 Jul 2005 19:30:32 +0200
committer laforge <laforge@netfilter.org> Sa, 30 Jul 2005 19:30:32 +0200

 net/netfilter/nfnetlink_log.c   |    3 ++-
 net/netfilter/nfnetlink_queue.c |    1 +
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -314,7 +314,7 @@ static struct sk_buff *nfulnl_alloc_skb(
 
 	UDEBUG("entered (%u, %u)\n", inst_size, pkt_size);
 
-	/* alloc skb whihc should be big enough for a whole multipart
+	/* alloc skb which should be big enough for a whole multipart
 	 * message.  WARNING: has to be <= 128k due to slab restrictions */
 
 	skb = alloc_skb(inst_size, GFP_ATOMIC);
@@ -965,6 +965,7 @@ init_or_cleanup(int init)
 cleanup:
 	nf_log_unregister_logger(&nfulnl_logger);
 #ifdef CONFIG_PROC_FS
+	remove_proc_entry("nfnetlink_log", proc_net_netfilter);
 cleanup_subsys:
 #endif
 	nfnetlink_subsys_unregister(&nfulnl_subsys);
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -1041,6 +1041,7 @@ cleanup:
 	nf_unregister_queue_handlers(nfqnl_enqueue_packet);
 	unregister_netdevice_notifier(&nfqnl_dev_notifier);
 #ifdef CONFIG_PROC_FS
+	remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
 cleanup_subsys:
 #endif	
 	nfnetlink_subsys_unregister(&nfqnl_subsys);

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply


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