Netdev List
 help / color / mirror / Atom feed
* [PATCH] emac: add support for platform-specific unsupported PHY features
From: Wade Farnsworth @ 2005-08-05 23:32 UTC (permalink / raw)
  To: jgarzik, netdev, Matt Porter; +Cc: Eugene Surovegin

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

Hello,

This patch adds support to the ibm_emac driver for platform-specific
unsupported PHY features.

The patch attempts to determine the highest speed and duplex when
autonegotiation is unsupported.

-Wade Farnsworth

Signed-off-by: Wade Farnsworth <wfarnsworth@mvista.com>

[-- Attachment #2: ibm-emac-phy-feat-unsupp-core.patch --]
[-- Type: text/x-patch, Size: 1887 bytes --]

diff -upr linux-2.6/drivers/net/ibm_emac/ibm_emac_core.c linux-2.6-dev/drivers/net/ibm_emac/ibm_emac_core.c
--- linux-2.6/drivers/net/ibm_emac/ibm_emac_core.c	2005-08-03 13:33:42.000000000 -0700
+++ linux-2.6-dev/drivers/net/ibm_emac/ibm_emac_core.c	2005-08-02 10:42:59.000000000 -0700
@@ -1876,6 +1876,9 @@ static int emac_init_device(struct ocp_d
 		rc = -ENODEV;
 		goto bail;
 	}
+	
+	/* Disable any PHY features not supported by the platform */
+	ep->phy_mii.def->features &= ~emacdata->feat_unsupp;
 
 	/* Setup initial PHY config & startup aneg */
 	if (ep->phy_mii.def->ops->init)
@@ -1883,6 +1886,38 @@ static int emac_init_device(struct ocp_d
 	netif_carrier_off(ndev);
 	if (ep->phy_mii.def->features & SUPPORTED_Autoneg)
 		ep->want_autoneg = 1;
+	else {
+		ep->want_autoneg = 0;
+		
+		/* Select highest supported speed/duplex */
+		if (ep->phy_mii.def->features & SUPPORTED_10000baseT_Full) {
+			ep->phy_mii.speed = SPEED_10000;
+			ep->phy_mii.duplex = DUPLEX_FULL;
+		} else if (ep->phy_mii.def->features & 
+			   SUPPORTED_1000baseT_Full) {
+			ep->phy_mii.speed = SPEED_1000;
+			ep->phy_mii.duplex = DUPLEX_FULL;
+		} else if (ep->phy_mii.def->features & 
+			   SUPPORTED_1000baseT_Half) {
+			ep->phy_mii.speed = SPEED_1000;
+			ep->phy_mii.duplex = DUPLEX_HALF;
+		} else if (ep->phy_mii.def->features & 
+			   SUPPORTED_100baseT_Full) {
+			ep->phy_mii.speed = SPEED_100;
+			ep->phy_mii.duplex = DUPLEX_FULL;
+		} else if (ep->phy_mii.def->features & 
+			   SUPPORTED_100baseT_Half) {
+			ep->phy_mii.speed = SPEED_100;
+			ep->phy_mii.duplex = DUPLEX_HALF;
+		} else if (ep->phy_mii.def->features & 
+			   SUPPORTED_10baseT_Full) {
+			ep->phy_mii.speed = SPEED_10;
+			ep->phy_mii.duplex = DUPLEX_FULL;
+		} else {
+			ep->phy_mii.speed = SPEED_10;
+			ep->phy_mii.duplex = DUPLEX_HALF;
+		}
+	}
 	emac_start_link(ep, NULL);
 
 	/* read the MAC Address */

^ permalink raw reply

* Re: [PATCH] emac: add support for platform-specific unsupported PHY features
From: Eugene Surovegin @ 2005-08-06  0:05 UTC (permalink / raw)
  To: Wade Farnsworth; +Cc: jgarzik, netdev, Matt Porter
In-Reply-To: <1123284725.27880.26.camel@rhino.az.mvista.com>

On Fri, Aug 05, 2005 at 04:32:05PM -0700, Wade Farnsworth wrote:
> Hello,
> 
> This patch adds support to the ibm_emac driver for platform-specific
> unsupported PHY features.
> 
> The patch attempts to determine the highest speed and duplex when
> autonegotiation is unsupported.

Looks good.

> 
> -Wade Farnsworth
> 
> Signed-off-by: Wade Farnsworth <wfarnsworth@mvista.com>

> diff -upr linux-2.6/drivers/net/ibm_emac/ibm_emac_core.c linux-2.6-dev/drivers/net/ibm_emac/ibm_emac_core.c
> --- linux-2.6/drivers/net/ibm_emac/ibm_emac_core.c	2005-08-03 13:33:42.000000000 -0700
> +++ linux-2.6-dev/drivers/net/ibm_emac/ibm_emac_core.c	2005-08-02 10:42:59.000000000 -0700
> @@ -1876,6 +1876,9 @@ static int emac_init_device(struct ocp_d
>  		rc = -ENODEV;
>  		goto bail;
>  	}
> +	
> +	/* Disable any PHY features not supported by the platform */
> +	ep->phy_mii.def->features &= ~emacdata->feat_unsupp;
>  
>  	/* Setup initial PHY config & startup aneg */
>  	if (ep->phy_mii.def->ops->init)
> @@ -1883,6 +1886,38 @@ static int emac_init_device(struct ocp_d
>  	netif_carrier_off(ndev);
>  	if (ep->phy_mii.def->features & SUPPORTED_Autoneg)
>  		ep->want_autoneg = 1;
> +	else {
> +		ep->want_autoneg = 0;
> +		
> +		/* Select highest supported speed/duplex */
> +		if (ep->phy_mii.def->features & SUPPORTED_10000baseT_Full) {
> +			ep->phy_mii.speed = SPEED_10000;
> +			ep->phy_mii.duplex = DUPLEX_FULL;

I think you are being too optimistic here :). EMAC doesn't support 10G 
Ethernet and will never will (at least sanely) given it's 
brain-damaged design. So I think it's safe to drop 
SUPPORTED_10000baseT_Full test.

I'll update my NAPI tree with similar code.

-- 
Eugene

^ permalink raw reply

* Re: ICMP broken in 2.6.13-rc5
From: Harald Welte @ 2005-08-06 16:17 UTC (permalink / raw)
  To: Vladimir B. Savkin; +Cc: akpm, netdev, Netfilter Development Mailinglist
In-Reply-To: <20050806092543.GA596@tentacle.sectorb.msk.ru>


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

On Sat, Aug 06, 2005 at 01:25:43PM +0400, Vladimir B. Savkin wrote:
> On Sat, Aug 06, 2005 at 11:13:37AM +0200, Harald Welte wrote:
> > On Sat, Aug 06, 2005 at 02:08:15AM +0400, Vladimir B. Savkin wrote:
> > > I found that it really is NOTRACK who cause? bogus ICMP errors.
> > 
> > Well, this means that your ICMP errors need to be NAT'ed but they
> > cannot, since the original connection causing the ICMP error did not go
> > through connection tracking.
> 
> How so, when there are no NAT rules that can match either source packets
> or ICMP errors?

Ok, I re-thought.  Given the following assumptions (combined from your
three mails):

1) tcp/udp packets are matched by NOTRACK
2) icmp errors for packets in '1' are matched by NOTRACK
3) there are no NAT rules that affect the packets in '1' and '2'

I see a case where packets get corrupted within iptable_nat.  Please try
the attached (untested) patch attached to my mail.

Still, my initial comments about this being an invalid setup upholds.
The NAT code needs to see all packets/connections in order to learn
about used port/ip tuples.  Otherwise, when allocating a tuple, it could
reuse a tuple that is already used by a non-NAT'ed connection.

So using nat in combination with NOTRACK should be prevented.  I'll hack
up a patch for that, too.

-- 
- 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: untracked.diff --]
[-- Type: text/plain, Size: 1553 bytes --]

[NETFILTER] don't try to do any NAT on untracked connections

With the introduction of 'rustynat' in 2.6.11, the old tricks of preventing
NAT of 'untracked' connections (e.g. NOTRACK target in 'raw' table) are no
longer sufficient.  The ip_conntrack_untracked.status |= IPS_NAT_DONE_MASK
effectively prevents iteration of the 'nat' table, but doesn't prevent
nat_packet() to be executed.  Since nr_manips is gone in 'rustynat',
nat_packet() now implicitly thinks that it has to do NAT on the packet.

This patch fixes that problem by explicitly checking for
ip_conntrack_untracked in ip_nat_fn().

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

---
commit c16fd4ffed6349d0888cd97a75d04394dac42021
tree b4f0e73c7c36f3a52b23593c40f1f49353ba67e3
parent 4d08142e287f852db3f4bfd614f2d73521bd7f07
author Harald Welte <laforge@netfilter.org> Sa, 06 Aug 2005 18:11:00 +0200
committer Harald Welte <laforge@netfilter.org> Sa, 06 Aug 2005 18:11:00 +0200

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

diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -100,6 +100,10 @@ ip_nat_fn(unsigned int hooknum,
 		return NF_ACCEPT;
 	}
 
+	/* Don't try to NAT if this packet is not conntracked */
+	if (ct == &ip_conntrack_untracked)
+		return NF_ACCEPT;
+
 	switch (ctinfo) {
 	case IP_CT_RELATED:
 	case IP_CT_RELATED+IP_CT_IS_REPLY:

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

^ permalink raw reply

* Re: atheros driver - desc
From: Kalle Valo @ 2005-08-06 19:57 UTC (permalink / raw)
  To: Mateusz Berezecki; +Cc: kernel-mentors, netdev
In-Reply-To: <42F2D523.9020702@gmail.com>

Mateusz Berezecki <mateuszb@gmail.com> writes:

> The driver is not yet fully working because I didn't finish kernel
> integration yet. Almost all
> driver I/O ops are reverse engineered independently of openbsd openhal
> which is missing just too much.
>
>
> Ok, enough talking. Most of the atheros 5212 hal is now open :)

This is great news. An open source Atheros driver which could be
included to Linux is really needed.

But how was the reverse engineering done? I noticed that forcedeth
driver was implemented using the clean room design[1] and Linux
Broadcom 4301 driver project[2] seems to be using the same method.

The reason I'm asking this is that I just wouldn't want see the same
happening this with this driver as happened during reverse engineering
of pwc Philips Webcam driver (some parts of the driver were removed
from kernel, but I believe the situation is now solved).

Actually, what are requirements to get a reverse engineered driver
included to Linux? Is clean room design an absolute must? It seems
that reverse engineering is needed if we want Linux support for most
of the WLAN cards on the market :(

[1] http://en.wikipedia.org/wiki/Clean_room_design
[2] http://linux-bcom4301.sourceforge.net/go/progress

-- 
Kalle Valo

^ permalink raw reply

* Re: atheros driver - desc
From: Jeff Garzik @ 2005-08-06 20:53 UTC (permalink / raw)
  To: Kalle Valo; +Cc: kernel-mentors, netdev
In-Reply-To: <8764uig7nm.fsf@litku.valo.iki.fi>


It is certainly preferred that someone write a document describing the
hardware, and then a totally separate team write the driver, based on
that document.

	Jeff

^ permalink raw reply

* Re: atheros driver - desc
From: Mateusz Berezecki @ 2005-08-06 21:38 UTC (permalink / raw)
  To: kernel-mentors, netdev; +Cc: Kalle.Valo
In-Reply-To: <8764uig7nm.fsf@litku.valo.iki.fi>

Kalle Valo <Kalle.Valo@iki.fi> wrote:
| 
| This is great news. An open source Atheros driver which could be
| included to Linux is really needed.
| 
| But how was the reverse engineering done? I noticed that forcedeth
| driver was implemented using the clean room design[1] and Linux
| Broadcom 4301 driver project[2] seems to be using the same method.

  Reverse engineering was done by dissassemblying binary HAL
  and in harder parts by running it in userspace(yes, that is possible)
  and analysing input and produced output. The crucial part was to
  discover the meaning of hidden part of the structure describing
  device state. Once this was done it will be a little if no problem to me
  to provide updates for this driver, unless the whole binary HAL
  changes dramatically. That's one of the reasons I do this work myself.
  
| 
| The reason I'm asking this is that I just wouldn't want see the same
| happening this with this driver as happened during reverse engineering
| of pwc Philips Webcam driver (some parts of the driver were removed
| from kernel, but I believe the situation is now solved).

  If get into trouble I write documentation :-) I promise.


| Actually, what are requirements to get a reverse engineered driver
| included to Linux? Is clean room design an absolute must? It seems
| that reverse engineering is needed if we want Linux support for most
| of the WLAN cards on the market :(
| 

   Sad but true. The problem is not at vendors' side though.
   Look at FCC regulations... :/


   kind regards
   Mateusz

^ permalink raw reply

* Re: atheros driver - desc
From: Harald Welte @ 2005-08-06 21:45 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Kalle Valo, kernel-mentors, netdev
In-Reply-To: <20050806205308.GA25208@havoc.gtf.org>


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

On Sat, Aug 06, 2005 at 04:53:08PM -0400, Jeff Garzik wrote:
> 
> It is certainly preferred that someone write a document describing the
> hardware, and then a totally separate team write the driver, based on
> that document.

No question to that.  However, I think it largely depends on _where_ the
actual re-engineering is done.

Here in Germany, the copyright law is  perfectly fine with reverse
engineering, as long as you don't actually decompile.  The intent of the
law is to prevent you from gaining access to the source code (which
isn't possible in heavily optimized compiled languages anyway).  There
is no problem with trying to learn how the program works and what it
actually does.

All over the EU, the EUCD states that you are explicitly allowed to do
_any_ kind of re-engineering for the purpose of compatibility /
interoperability (and you want to make that card interoperable with
the linux OS...)  All you need to do is to ask the copyright holder for
the required documentation. If they don't produce it within a given
timeframe (IIRC one month), then you can go and start re-engineering
without the approval of the copyright holders.

Also, lots of the low-level driver routines are not copyrightable works
anyway.  If you need to set up the registers of a device in a certain
sequence in order to get it work, then there is no other way of doing
so.  Therefore the corresponding source code is not the result of a
creative process of the author.

I don't want to turn this list into a list of legal discussion, but
since I'm heavily dealing with exactly those issues during my
gpl-violations.org efforts, I thought I share some of the facts.

So in general, at least if you're doing that kind of work within the EU,
I wouldn't be worried all that much.

-- 
- 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: Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
Kernel-mentors mailing list
Kernel-mentors@selenic.com
http://selenic.com/mailman/listinfo/kernel-mentors

^ permalink raw reply

* [PATCH] forcedeth: Initialize link settings in every nv_open()
From: Manfred Spraul @ 2005-08-06 21:47 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Ayaz Abdulla, Netdev, cOzmIc.FI

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

Rüdiger found a bug in nv_open that explains some of the reports
with duplex mismatches:
nv_open calls nv_update_link_speed for initializing the hardware link speed
registers. If current link setting matches the values in np->linkspeed and
np->duplex, then the function does nothing.
Usually, doing nothing is the right thing, but not in nv_open: During
nv_open, the registers must be initialized because the nic was reset.

The attached patch fixes that by setting np->linkspeed to an invalid value
before calling nv_update_link_speed from nv_open.

Signed-Off-By: Manfred Spraul <manfred@colorfullife.com>


[-- Attachment #2: patch-forcedeth-042-forcelinkinit --]
[-- Type: text/plain, Size: 845 bytes --]

--- 2.6/drivers/net/forcedeth.c	2005-08-06 19:59:56.000000000 +0200
+++ build-2.6/drivers/net/forcedeth.c	2005-08-06 19:59:06.000000000 +0200
@@ -93,6 +93,8 @@
  *      0.40: 19 Jul 2005: Add support for mac address change.
  *      0.41: 30 Jul 2005: Write back original MAC in nv_close instead
  *			   of nv_remove
+ *      0.42: 06 Aug 2005: Fix lack of link speed initialization
+ *			   in the second (and later) nv_open call
  *
  * Known bugs:
  * We suspect that on some hardware no TX done interrupts are generated.
@@ -2178,6 +2180,9 @@
 		writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
 		dprintk(KERN_INFO "startup: got 0x%08x.\n", miistat);
 	}
+	/* set linkspeed to invalid value, thus force nv_update_linkspeed
+	 * to init hw */
+	np->linkspeed = 0;
 	ret = nv_update_linkspeed(dev);
 	nv_start_rx(dev);
 	nv_start_tx(dev);

^ permalink raw reply

* Re: atheros driver - desc
From: Kalle Valo @ 2005-08-07  7:32 UTC (permalink / raw)
  To: Harald Welte; +Cc: kernel-mentors, netdev, Jeff Garzik
In-Reply-To: <20050806214544.GA4594@rama.de.gnumonks.org>

Harald Welte <laforge@gnumonks.org> writes:

> I don't want to turn this list into a list of legal discussion, but
> since I'm heavily dealing with exactly those issues during my
> gpl-violations.org efforts, I thought I share some of the facts.

Thanks for your answer, it cleared up things. I also don't want to
discuss legal things here, we can discuss it more privately. But I'll
just ask one more question in public:

> So in general, at least if you're doing that kind of work within the EU,
> I wouldn't be worried all that much.

That's good news. But what about inclusion to the official Linux
kernel? Can a driver reverse-engineered in EU be included to the
kernel? (Big part of Linux is developed in US, I guess.)

-- 
Kalle Valo

^ permalink raw reply

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

* Harald Welte <20050730103005.GB6620@rama.de.gnumonks.org> 2005-07-30 12:30
> 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.).

Same very minor issues as nfnetlink regarding some of the
new netlink message construction policies. I'll "fix" them
during the conversion to the generic netlink attributes.

^ permalink raw reply

* Re: atheros driver - desc
From: Harald Welte @ 2005-08-07 15:01 UTC (permalink / raw)
  To: Kalle Valo; +Cc: kernel-mentors, netdev, Jeff Garzik
In-Reply-To: <87pssqp5hk.fsf@litku.valo.iki.fi>


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

On Sun, Aug 07, 2005 at 10:32:07AM +0300, Kalle Valo wrote:
> Harald Welte <laforge@gnumonks.org> writes:
> 
> > I don't want to turn this list into a list of legal discussion, but
> > since I'm heavily dealing with exactly those issues during my
> > gpl-violations.org efforts, I thought I share some of the facts.
> 
> Thanks for your answer, it cleared up things. I also don't want to
> discuss legal things here, we can discuss it more privately. But I'll
> just ask one more question in public:
> 
> > So in general, at least if you're doing that kind of work within the EU,
> > I wouldn't be worried all that much.
> 
> That's good news. But what about inclusion to the official Linux
> kernel? Can a driver reverse-engineered in EU be included to the
> kernel? (Big part of Linux is developed in US, I guess.)

I will consult my legal counsel about this.  My current naive position
on this is that only the actuall process of the re-engineering matters,
not the result.

I'll get back as soon as I have a reply from my legal counsel.

-- 
- 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: Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
Kernel-mentors mailing list
Kernel-mentors@selenic.com
http://selenic.com/mailman/listinfo/kernel-mentors

^ permalink raw reply

* Re: [PATCH] add new nfnetlink_log subsystem
From: Harald Welte @ 2005-08-07 15:03 UTC (permalink / raw)
  To: Thomas Graf; +Cc: Linux Netdev List, Netfilter Development Mailinglist
In-Reply-To: <20050807112039.GF10481@postel.suug.ch>

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

On Sun, Aug 07, 2005 at 01:20:39PM +0200, Thomas Graf wrote:
> * Harald Welte <20050730103005.GB6620@rama.de.gnumonks.org> 2005-07-30 12:30
> > 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.).
> 
> Same very minor issues as nfnetlink regarding some of the
> new netlink message construction policies. I'll "fix" them
> during the conversion to the generic netlink attributes.

is this supposed to happen soon?  I also need to update the userspace
side in case you make any changes, so I'd appreciate any changes going
in ASAP.  Alternatively just tell me what needs to change and I'll
change it even before the generalization.

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 #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* RE: {Spam?} {Virus?} Geoff@senson.net (verification)
From: Geoff @ 2005-08-07 16:58 UTC (permalink / raw)
  To: netdev
In-Reply-To: <200508071656.j77GucFk015692@host2.lifetimewebsites.com>

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

Geoff here,

I'm protecting myself from receiving junk mail.


Just this once, click the link below so I can receive your emails.
You won't have to do this again.

http://spamarrest.com/a2?BGRjBGN1BwchMKExMKMNo3AmYaAanF5wo20j




Spam Arrest - Take control of your inbox!
http://spamarrest.com/affl?910905

------------------------------------------------------------
You are receiving this message in response to your email to
Geoff, a Spam Arrest customer.

Spam Arrest requests that senders verify themselves before
their email is delivered.

When you click the above link, you will be taken to a page
with a graphic on it. Simply read the word in the graphic,
type it into the form, and you're verified.

You will only need to do this once per Spam Arrest customer.
------------------------------------------------------------
Below are the complete headers of the message that this email 
was generated in response to.

Return-Path: <netdev@oss.sgi.com>
Received: from host2.lifetimewebsites.com (root@localhost)
	by senson.net (8.12.10/8.12.10) with ESMTP id j77Gulna015725
	for <geoff@senson.net>; Sun, 7 Aug 2005 12:56:47 -0400
X-ClientAddr: 68.82.191.214
Received: from oss.sgi.com (pcp01494310pcs.tybout01.de.comcast.net [68.82.191.214])
	by host2.lifetimewebsites.com (8.12.10/8.12.10) with ESMTP id j77GucFk015692
	for <geoff@senson.net>; Sun, 7 Aug 2005 12:56:39 -0400
Message-Id: <200508071656.j77GucFk015692@host2.lifetimewebsites.com>
From: netdev@oss.sgi.com
To: geoff@senson.net
Subject: {Spam?} {Virus?} Geoff@senson.net
Date: Sun, 7 Aug 2005 12:56:48 -0400
MIME-Version: 1.0
Content-Type: multipart/mixed;
	boundary="----=_NextPart_000_0002_AB2ECEEE.C24A2913"
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 6.00.2600.0000
X-MIMEOLE: Produced By Microsoft MimeOLE V6.00.2600.0000
X-Lifetime-Websites-MailScanner-Information: Please contact Lifetime Websites for more information
X-Lifetime-Websites-MailScanner: Infected with a virus
X-Lifetime-Websites-MailScanner-SpamCheck: spam, SBL+XBL,
	SpamAssassin (score=9.799, required 7, FORGED_MUA_OUTLOOK 1.58,
	MIME_BASE64_ILLEGAL 1.72, MSGID_FROM_MTA_SHORT 3.31,
	NO_REAL_NAME 0.28, RCVD_IN_DYNABLOCK 2.55, RCVD_IN_SORBS 0.10,
	UPPERCASE_25_50 0.26)
X-Lifetime-Websites-MailScanner-SpamScore: 9
X-MailScanner-From: netdev@oss.sgi.com
X-Spam-Checker-Version: SpamAssassin 2.63 (2004-01-11) on 
	host2.lifetimewebsites.com
X-Spam-Level: ****
X-Spam-Status: No, hits=4.5 required=5.0 tests=FORGED_MUA_OUTLOOK,
	NO_REAL_NAME,RCVD_IN_DYNABLOCK,RCVD_IN_SORBS autolearn=no version=2.63
Status: 
X-SA-Poll-Id: 4083cedb0000492b..1..1123433808000
X-SA-USERIDNR: 900805
Received-SPF: none(oss.sgi.com: oss.sgi.com does not designate permitted sender hosts)



------------------------------------------------------------
Webmasters help stop spam and make 50%.
http://spamarrest.com/affl?910905/affiliates/index.jsp 

------------------------------------------------------------

[-- Attachment #2: Type: text/html, Size: 4756 bytes --]

^ permalink raw reply

* Re: 2.6.13-rc4-mm1: iptables DROP crashes the computer
From: Adrian Bunk @ 2005-08-07 17:23 UTC (permalink / raw)
  To: Espen Fjellvær Olsen; +Cc: netdev, netfilter-devel, linux, discuss
In-Reply-To: <7aaed09105080710121bba1b5b@mail.gmail.com>

On Sun, Aug 07, 2005 at 07:12:00PM +0200, Espen Fjellvær Olsen wrote:

> After execing "iptables -A INPUT -j DROP" my computer crashes hard. It
> dosent hang immediately, but after a couple of seconds.
> The machine is an amd64, running a clean x86_64 environment.
> uname -a: Linux gentoo 2.6.13-rc4-mm1 #1 PREEMPT Thu Aug 4 01:01:44
> CEST 2005 x86_64 AMD Athlon(tm) 64 Processor 3400+ AuthenticAMD
>...

Is this reproducible or did it happen only once?

Are there any messages that might give a hint where to search for the 
problem?

You are reporting this against 2.6.13-rc4-mm1, but are attaching a 
.config of 2.6.13-rc5-mm1. Which kernels are affected, and which are 
not?

Does it still happen if you compile your kernel with preemption 
disabled?

Please send the output of ./scripts/ver_linux .

> Mvh / Best regards
> Espen Fjellvær Olsen

cu
Adrian

-- 

       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed

^ permalink raw reply

* Re: 2.6.13-rc4-mm1: iptables DROP crashes the computer
From: Espen Fjellvær Olsen @ 2005-08-07 17:43 UTC (permalink / raw)
  To: Adrian Bunk; +Cc: netdev, netfilter-devel, linux, discuss
In-Reply-To: <20050807172333.GF3513@stusta.de>

On 07/08/05, Adrian Bunk <bunk@stusta.de> wrote:
> On Sun, Aug 07, 2005 at 07:12:00PM +0200, Espen Fjellvær Olsen wrote:
> 
> > After execing "iptables -A INPUT -j DROP" my computer crashes hard. It
> > dosent hang immediately, but after a couple of seconds.
> > The machine is an amd64, running a clean x86_64 environment.
> > uname -a: Linux gentoo 2.6.13-rc4-mm1 #1 PREEMPT Thu Aug 4 01:01:44
> > CEST 2005 x86_64 AMD Athlon(tm) 64 Processor 3400+ AuthenticAMD
> >...
> 
> Is this reproducible or did it happen only once?

It is reproducible, happens each time when running "iptables -A INPUT
-j DROP", other rules like "iptables -A INPUT -m --state
ESTABLISHED,RELATED -p tcp --dport 22 -j ACCEPT" works well tho.

> Are there any messages that might give a hint where to search for the
> problem?

The kernel log dont give any messages before the crash, and since the
computer crash hard i cant check for relevant messages after the crash
;)
 
> You are reporting this against 2.6.13-rc4-mm1, but are attaching a
> .config of 2.6.13-rc5-mm1. Which kernels are affected, and which are
> not?

Im sorry about that glitch, recently compiled 2.6.13-rc5-mm1, but i
got a kernel panic at boot, havent looked into that yet, but it might
be related to ACPI.

The config for rc4-mm1 and rc5-mm1 is similar.

> Does it still happen if you compile your kernel with preemption
> disabled?

Havent tried this yet, but ill do it right away.

> Please send the output of ./scripts/ver_linux .

If some fields are empty or look unusual you may have an old version.
Compare to the current minimal requirements in Documentation/Changes.

Linux gentoo 2.6.13-rc4-mm1 #1 PREEMPT Thu Aug 4 01:01:44 CEST 2005
x86_64 AMD Athlon(tm) 64 Processor 3400+ AuthenticAMD GNU/Linux

Gnu C                  3.4.4
Gnu make               3.80
binutils               2.16.1
util-linux             2.12q
mount                  2.12q
module-init-tools      3.2-pre7
e2fsprogs              1.38
reiserfsprogs          line
reiser4progs           line
xfsprogs               2.6.25
Linux C Library        2.3.5
Dynamic linker (ldd)   2.3.5
Procps                 3.2.5
Net-tools              1.60
Kbd                    1.12
Sh-utils               5.2.1
udev                   065
Modules Loaded         iptable_filter ip_tables snd_seq_midi
snd_emu10k1_synth snd_emux_synth snd_seq_virmidi snd_seq_midi_event
snd_seq_midi_emul snd_seq snd_pcm_oss snd_mixer_oss rtc ntfs
snd_emu10k1 snd_rawmidi snd_seq_device snd_ac97_codec snd_pcm
snd_timer snd_page_alloc snd_util_mem snd_hwdep snd soundcore
usb_storage uhci_hcd usbcore


-- 
Mvh / Best regards
Espen Fjellvær Olsen
espenfjo@gmail.com
Norway

^ permalink raw reply

* Re: 2.6.13-rc4-mm1: iptables DROP crashes the computer
From: Patrick McHardy @ 2005-08-07 18:38 UTC (permalink / raw)
  To: Adrian Bunk
  Cc: Espen Fjellvær Olsen, netfilter-devel, linux, discuss,
	netdev
In-Reply-To: <20050807172333.GF3513@stusta.de>

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

Adrian Bunk wrote:
> On Sun, Aug 07, 2005 at 07:12:00PM +0200, Espen Fjellvær Olsen wrote:
> 
> 
>>After execing "iptables -A INPUT -j DROP" my computer crashes hard. It
>>dosent hang immediately, but after a couple of seconds.
>>The machine is an amd64, running a clean x86_64 environment.
>>uname -a: Linux gentoo 2.6.13-rc4-mm1 #1 PREEMPT Thu Aug 4 01:01:44
>>CEST 2005 x86_64 AMD Athlon(tm) 64 Processor 3400+ AuthenticAMD
>>...

Could be related to the refcnt underflow with conntrack event
notifications enabled. If you have CONFIG_IP_NF_CONNTRACK_EVENTS
enabled please try this patch.


[-- Attachment #2: x --]
[-- Type: text/plain, Size: 10692 bytes --]

[NETFILTER]: Fix multiple problems with the conntrack event cache

refcnt underflow: the reference count is decremented when a conntrack
entry is removed from the hash but it is not incremented when entering
new entries.

missing protection of process context against softirq context: all
cache operations need to locally disable softirqs to avoid races.
Additionally the event cache can't be initialized when a packet enteres
the conntrack code but needs to be initialized whenever we cache an event
and the stored conntrack entry doesn't match the current one.

incorrect flushing of the event cache in ip_ct_iterate_cleanup: without
real locking we can't flush the cache for different CPUs without incurring
races. The cache for different CPUs can only be flushed when no packets
are going through the code. ip_ct_iterate_cleanup doesn't need to drop
all references, so flushing is moved to the cleanup path.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit d20d18715b8425060334e879ebb4835202457b3e
tree 3279243f59162c14f8ac145473e1c3f4c586b2fa
parent df2e0392536ecdd6385f4319f746045fd6fae38f
author Patrick McHardy <kaber@trash.net> Wed, 03 Aug 2005 20:33:25 +0200
committer Patrick McHardy <kaber@trash.net> Wed, 03 Aug 2005 20:33:25 +0200

 include/linux/netfilter_ipv4/ip_conntrack.h      |   29 +++---
 include/linux/netfilter_ipv4/ip_conntrack_core.h |   14 +--
 net/ipv4/netfilter/ip_conntrack_core.c           |  107 ++++++++--------------
 net/ipv4/netfilter/ip_conntrack_standalone.c     |    3 -
 4 files changed, 58 insertions(+), 95 deletions(-)

diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -411,6 +411,7 @@ struct ip_conntrack_stat
 
 #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
 #include <linux/notifier.h>
+#include <linux/interrupt.h>
 
 struct ip_conntrack_ecache {
 	struct ip_conntrack *ct;
@@ -445,26 +446,24 @@ ip_conntrack_expect_unregister_notifier(
 	return notifier_chain_unregister(&ip_conntrack_expect_chain, nb);
 }
 
+extern void ip_ct_deliver_cached_events(const struct ip_conntrack *ct);
+extern void __ip_ct_event_cache_init(struct ip_conntrack *ct);
+
 static inline void 
 ip_conntrack_event_cache(enum ip_conntrack_events event,
 			 const struct sk_buff *skb)
 {
-	struct ip_conntrack_ecache *ecache = 
-					&__get_cpu_var(ip_conntrack_ecache);
-
-	if (unlikely((struct ip_conntrack *) skb->nfct != ecache->ct)) {
-		if (net_ratelimit()) {
-			printk(KERN_ERR "ctevent: skb->ct != ecache->ct !!!\n");
-			dump_stack();
-		}
-	}
+	struct ip_conntrack *ct = (struct ip_conntrack *)skb->nfct;
+	struct ip_conntrack_ecache *ecache;
+	
+	local_bh_disable();
+	ecache = &__get_cpu_var(ip_conntrack_ecache);
+	if (ct != ecache->ct)
+		__ip_ct_event_cache_init(ct);
 	ecache->events |= event;
+	local_bh_enable();
 }
 
-extern void 
-ip_conntrack_deliver_cached_events_for(const struct ip_conntrack *ct);
-extern void ip_conntrack_event_cache_init(const struct sk_buff *skb);
-
 static inline void ip_conntrack_event(enum ip_conntrack_events event,
 				      struct ip_conntrack *ct)
 {
@@ -483,9 +482,7 @@ static inline void ip_conntrack_event_ca
 					    const struct sk_buff *skb) {}
 static inline void ip_conntrack_event(enum ip_conntrack_events event, 
 				      struct ip_conntrack *ct) {}
-static inline void ip_conntrack_deliver_cached_events_for(
-						struct ip_conntrack *ct) {}
-static inline void ip_conntrack_event_cache_init(const struct sk_buff *skb) {}
+static inline void ip_ct_deliver_cached_events(const struct ip_conntrack *ct) {}
 static inline void 
 ip_conntrack_expect_event(enum ip_conntrack_expect_events event, 
 			  struct ip_conntrack_expect *exp) {}
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_core.h b/include/linux/netfilter_ipv4/ip_conntrack_core.h
--- a/include/linux/netfilter_ipv4/ip_conntrack_core.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_core.h
@@ -44,18 +44,14 @@ static inline int ip_conntrack_confirm(s
 	struct ip_conntrack *ct = (struct ip_conntrack *)(*pskb)->nfct;
 	int ret = NF_ACCEPT;
 
-	if (ct && !is_confirmed(ct))
-		ret = __ip_conntrack_confirm(pskb);
-	ip_conntrack_deliver_cached_events_for(ct);
-
+	if (ct) {
+		if (!is_confirmed(ct))
+			ret = __ip_conntrack_confirm(pskb);
+		ip_ct_deliver_cached_events(ct);
+	}
 	return ret;
 }
 
-#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
-struct ip_conntrack_ecache;
-extern void __ip_ct_deliver_cached_events(struct ip_conntrack_ecache *ec);
-#endif
-
 extern void __ip_ct_expect_unlink_destroy(struct ip_conntrack_expect *exp);
 
 extern struct list_head *ip_conntrack_hash;
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
@@ -85,73 +85,62 @@ struct notifier_block *ip_conntrack_expe
 
 DEFINE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache);
 
-static inline void __deliver_cached_events(struct ip_conntrack_ecache *ecache)
+/* deliver cached events and clear cache entry - must be called with locally
+ * disabled softirqs */
+static inline void
+__ip_ct_deliver_cached_events(struct ip_conntrack_ecache *ecache)
 {
+	DEBUGP("ecache: delivering events for %p\n", ecache->ct);
 	if (is_confirmed(ecache->ct) && !is_dying(ecache->ct) && ecache->events)
 		notifier_call_chain(&ip_conntrack_chain, ecache->events,
 				    ecache->ct);
 	ecache->events = 0;
-}
-
-void __ip_ct_deliver_cached_events(struct ip_conntrack_ecache *ecache)
-{
-	__deliver_cached_events(ecache);
+	ip_conntrack_put(ecache->ct);
+	ecache->ct = NULL;
 }
 
 /* Deliver all cached events for a particular conntrack. This is called
  * by code prior to async packet handling or freeing the skb */
-void 
-ip_conntrack_deliver_cached_events_for(const struct ip_conntrack *ct)
+void ip_ct_deliver_cached_events(const struct ip_conntrack *ct)
 {
-	struct ip_conntrack_ecache *ecache = 
-					&__get_cpu_var(ip_conntrack_ecache);
-
-	if (!ct)
-		return;
-
-	if (ecache->ct == ct) {
-		DEBUGP("ecache: delivering event for %p\n", ct);
-		__deliver_cached_events(ecache);
-	} else {
-		if (net_ratelimit())
-			printk(KERN_WARNING "ecache: want to deliver for %p, "
-				"but cache has %p\n", ct, ecache->ct);
-	}
-
-	/* signalize that events have already been delivered */
-	ecache->ct = NULL;
+	struct ip_conntrack_ecache *ecache;
+	
+	local_bh_disable();
+	ecache = &__get_cpu_var(ip_conntrack_ecache);
+	if (ecache->ct == ct)
+		__ip_ct_deliver_cached_events(ecache);
+	local_bh_enable();
 }
 
-/* Deliver cached events for old pending events, if current conntrack != old */
-void ip_conntrack_event_cache_init(const struct sk_buff *skb)
+void __ip_ct_event_cache_init(struct ip_conntrack *ct)
 {
-	struct ip_conntrack *ct = (struct ip_conntrack *) skb->nfct;
-	struct ip_conntrack_ecache *ecache = 
-					&__get_cpu_var(ip_conntrack_ecache);
+	struct ip_conntrack_ecache *ecache;
 
 	/* take care of delivering potentially old events */
-	if (ecache->ct != ct) {
-		enum ip_conntrack_info ctinfo;
-		/* we have to check, since at startup the cache is NULL */
-		if (likely(ecache->ct)) {
-			DEBUGP("ecache: entered for different conntrack: "
-			       "ecache->ct=%p, skb->nfct=%p. delivering "
-			       "events\n", ecache->ct, ct);
-			__deliver_cached_events(ecache);
+	ecache = &__get_cpu_var(ip_conntrack_ecache);
+	BUG_ON(ecache->ct == ct);
+	if (ecache->ct)
+		__ip_ct_deliver_cached_events(ecache);
+	/* initialize for this conntrack/packet */
+	ecache->ct = ct;
+	nf_conntrack_get(&ct->ct_general);
+}
+
+/* flush the event cache - touches other CPU's data and must not be called while
+ * packets are still passing through the code */
+static void ip_ct_event_cache_flush(void)
+{
+	struct ip_conntrack_ecache *ecache;
+	int cpu;
+
+	for_each_cpu(cpu) {
+		ecache = &per_cpu(ip_conntrack_ecache, cpu);
+		if (ecache->ct)
 			ip_conntrack_put(ecache->ct);
-		} else {
-			DEBUGP("ecache: entered for conntrack %p, "
-				"cache was clean before\n", ct);
-		}
-
-		/* initialize for this conntrack/packet */
-		ecache->ct = ip_conntrack_get(skb, &ctinfo);
-		/* ecache->events cleared by __deliver_cached_devents() */
-	} else {
-		DEBUGP("ecache: re-entered for conntrack %p.\n", ct);
 	}
 }
-
+#else
+static inline void ip_ct_event_cache_flush(void) {}
 #endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
 
 DEFINE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
@@ -873,8 +862,6 @@ unsigned int ip_conntrack_in(unsigned in
 
 	IP_NF_ASSERT((*pskb)->nfct);
 
-	ip_conntrack_event_cache_init(*pskb);
-
 	ret = proto->packet(ct, *pskb, ctinfo);
 	if (ret < 0) {
 		/* Invalid: inverse of the return code tells
@@ -1273,23 +1260,6 @@ ip_ct_iterate_cleanup(int (*iter)(struct
 
 		ip_conntrack_put(ct);
 	}
-
-#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
-	{
-		/* we need to deliver all cached events in order to drop
-		 * the reference counts */
-		int cpu;
-		for_each_cpu(cpu) {
-			struct ip_conntrack_ecache *ecache = 
-					&per_cpu(ip_conntrack_ecache, cpu);
-			if (ecache->ct) {
-				__ip_ct_deliver_cached_events(ecache);
-				ip_conntrack_put(ecache->ct);
-				ecache->ct = NULL;
-			}
-		}
-	}
-#endif
 }
 
 /* Fast function for those who don't want to parse /proc (and I don't
@@ -1376,6 +1346,7 @@ void ip_conntrack_flush()
            delete... */
 	synchronize_net();
 
+	ip_ct_event_cache_flush();
  i_see_dead_people:
 	ip_ct_iterate_cleanup(kill_all, NULL);
 	if (atomic_read(&ip_conntrack_count) != 0) {
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -401,7 +401,6 @@ static unsigned int ip_confirm(unsigned 
 			       const struct net_device *out,
 			       int (*okfn)(struct sk_buff *))
 {
-	ip_conntrack_event_cache_init(*pskb);
 	/* We've seen it coming out the other side: confirm it */
 	return ip_conntrack_confirm(pskb);
 }
@@ -419,7 +418,6 @@ static unsigned int ip_conntrack_help(un
 	ct = ip_conntrack_get(*pskb, &ctinfo);
 	if (ct && ct->helper) {
 		unsigned int ret;
-		ip_conntrack_event_cache_init(*pskb);
 		ret = ct->helper->help(pskb, ct, ctinfo);
 		if (ret != NF_ACCEPT)
 			return ret;
@@ -978,6 +976,7 @@ EXPORT_SYMBOL_GPL(ip_conntrack_chain);
 EXPORT_SYMBOL_GPL(ip_conntrack_expect_chain);
 EXPORT_SYMBOL_GPL(ip_conntrack_register_notifier);
 EXPORT_SYMBOL_GPL(ip_conntrack_unregister_notifier);
+EXPORT_SYMBOL_GPL(__ip_ct_event_cache_init);
 EXPORT_PER_CPU_SYMBOL_GPL(ip_conntrack_ecache);
 #endif
 EXPORT_SYMBOL(ip_conntrack_protocol_register);

^ permalink raw reply

* RE: [PATCH 2.6.12.1 1/12] S2io: Code cleanup
From: Ravinandan Arakali @ 2005-08-07 20:51 UTC (permalink / raw)
  To: 'Jeff Garzik', raghavendra.koushik
  Cc: netdev, leonid.grossman, rapuru.sriram
In-Reply-To: <42EC5D96.3050304@pobox.com>

Jeff,
The entire set of patches have been resent and an additional
patch13 to address earlier comments.
Pls confirm if these patches apply correctly.

Thanks,
Ravi

-----Original Message-----
From: Jeff Garzik [mailto:jgarzik@pobox.com]
Sent: Saturday, July 30, 2005 10:12 PM
To: raghavendra.koushik@neterion.com
Cc: netdev@oss.sgi.com; ravinandan.arakali@neterion.com;
leonid.grossman@neterion.com; rapuru.sriram@neterion.com
Subject: Re: [PATCH 2.6.12.1 1/12] S2io: Code cleanup


patch doesn't seem to apply :(

Can you please resend the entire series, taking into account the
comments WRT patch #5?

Also, I was unable to include your fixes in my 'fixes' branch, whose
speed to upstream kernel is accelerated, because patch #1 was not bug fixes.

If you want your bug fixes to go upstream as rapidly as possible, make
sure they are ordered before the code cleanups and new features.  This
allows me to send the fixes upstream immediately, while allowing further
review and testing of the cleanup/feature patches.

	Jeff

^ permalink raw reply

* Re: [RFC PATCH] convert ebt_ulog to nfnetlink_log
From: Bart De Schuymer @ 2005-08-07 21:27 UTC (permalink / raw)
  To: Harald Welte; +Cc: Linux Netdev List, Netfilter Development Mailinglist, kaber
In-Reply-To: <20050805171028.GA7855@rama.de.gnumonks.org>

Op vr, 05-08-2005 te 19:10 +0200, schreef Harald Welte:
> What about the following (only compile-tested) patch ?
> 
> [NETFILTER] add phys{in,out}dev support to nfnetlink_log and nfnetlink_queue
> 
> Since bridges don't have a 'reasonable' input and output net_device
> (e.g. 'br0'), we need to add seperate TLV's for the 'physindev' and 'physoutdev'
> to get to the real underlying device (e.g. 'eth0').
> 
> I really hate to have those CONFIG_BRIDGE_NETFILTER ifdef's all over the
> code - but for now we have them almost everywhere, so two more doesn't
> hurt.  At some point we need to get rid of this ugliness and have something
> like an 'input device stack' that can be traversed.

I'm not sure if I understand that, how could this be used to know if
BRIDGE_NETFILTER was configured?


> +#ifdef CONFIG_BRIDGE_NETFILTER
> +		if (indev->br_port) {
> +			tmp_uint = htonl(indev->br_port->br->dev->ifindex);
> +			NFA_PUT(inst->skb, NFULA_IFINDEX_PHYSINDEV,
> +				sizeof(tmp_uint), &tmp_uint);
> +		}

indev->br_port->br->dev->ifindex points to the ifindex of the bridge br0
when indev is a bridge port (eth0). So you need this to fill in the
input device (assuming we agree that the bridge is called the input
device, and the bridge port is called the physical input device).
Filling in the physical input device is done with indev (in case
indev->br_port is not NULL).

I can't easily get access to net-2.6.14, so I can't have a full view on
things. If you were to change ebt_ulog, you must also make sure that the
physindev is used for NFULA_IFINDEX_PHYSINDEV. The input_dev member of
the skb will be eth0 if the physindev is known.

Analogous comments hold for the other similar parts of your patch.

cheers,
Bart

^ permalink raw reply

* Re: [RFC PATCH] convert ebt_ulog to nfnetlink_log
From: Harald Welte @ 2005-08-07 21:33 UTC (permalink / raw)
  To: Bart De Schuymer
  Cc: Linux Netdev List, Netfilter Development Mailinglist, kaber
In-Reply-To: <1123450076.3378.18.camel@localhost.localdomain>

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

On Sun, Aug 07, 2005 at 09:27:56PM +0000, Bart De Schuymer wrote:
> > I really hate to have those CONFIG_BRIDGE_NETFILTER ifdef's all over the
> > code - but for now we have them almost everywhere, so two more doesn't
> > hurt.  At some point we need to get rid of this ugliness and have something
> > like an 'input device stack' that can be traversed.
> 
> I'm not sure if I understand that, how could this be used to know if
> BRIDGE_NETFILTER was configured?

not at all.  It was just my extremely vague idea about something more
generic, like a stack of input devices.  Those ifdefs would basically
disappear, and the history of input devices (let's say the individual
decapsulation layers for tunneling, ...) would be visible via some
common structure that could also be used by bridging.  You can ignore
that comment/rant, it has no practical relevance in the current
discussion ;)

> > +#ifdef CONFIG_BRIDGE_NETFILTER
> > +		if (indev->br_port) {
> > +			tmp_uint = htonl(indev->br_port->br->dev->ifindex);
> > +			NFA_PUT(inst->skb, NFULA_IFINDEX_PHYSINDEV,
> > +				sizeof(tmp_uint), &tmp_uint);
> > +		}
> 
> indev->br_port->br->dev->ifindex points to the ifindex of the bridge br0
> when indev is a bridge port (eth0). So you need this to fill in the
> input device (assuming we agree that the bridge is called the input
> device, and the bridge port is called the physical input device).
> Filling in the physical input device is done with indev (in case
> indev->br_port is not NULL).

I'm not sure if I can follow you.  What basically happens is:

ebt_ulog calls nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, ...) where
"in" and "out" are struct net_device as passed to the ebt_ulog function
(which is part of the ebt_watcher).  

[...]

the code ends up at the function you are quoting above.  "indev"
is "in" and "outdev" is "out", transparently passed from
nf_log_packet().

So I think it should reflect exactly what you currently do in ebt_ulog.
The only diference is that you now get the ifindex and not the device
name string.

Cheers,
	Harald
-- 
- 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 #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: 2.6.13-rc4-mm1: iptables DROP crashes the computer
From: Espen Fjellvær Olsen @ 2005-08-07 21:40 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netdev, netfilter-devel, linux, discuss, Adrian Bunk
In-Reply-To: <42F65513.3080409@trash.net>

On 07/08/05, Patrick McHardy <kaber@trash.net> wrote:
> Could be related to the refcnt underflow with conntrack event
> notifications enabled. If you have CONFIG_IP_NF_CONNTRACK_EVENTS
> enabled please try this patch.
> 

I can confirm that that patch solved my problems, thank you :)

-- 
Mvh / Best regards
Espen Fjellvær Olsen
espenfjo@gmail.com
Norway

^ permalink raw reply

* Moving...  please wait
From: Jeff Garzik @ 2005-08-07 21:51 UTC (permalink / raw)
  To: Ravinandan Arakali, linux-ide, netdev, linux-kernel
  Cc: raghavendra.koushik, leonid.grossman, rapuru.sriram, akpm
In-Reply-To: <000001c59b91$d7f07370$4810100a@pc.s2io.com>

On Sun, Aug 07, 2005 at 01:51:52PM -0700, Ravinandan Arakali wrote:
> Jeff,
> The entire set of patches have been resent and an additional
> patch13 to address earlier comments.
> Pls confirm if these patches apply correctly.


I'm in the process of moving to a new house, and getting a new computer
lab set up.

I have email and can ACK any critical patches, but everything else must
wait for 2.6.14 to open (which fits nicely into the 2.6 release cycle).

	Jeff




^ permalink raw reply

* Re: [PATCH] add new nfnetlink_log subsystem
From: Thomas Graf @ 2005-08-07 21:55 UTC (permalink / raw)
  To: Harald Welte, David Miller, Linux Netdev List,
	Netfilter Development Mailinglist
In-Reply-To: <20050807150358.GD4855@rama.de.gnumonks.org>

* Harald Welte <20050807150358.GD4855@rama.de.gnumonks.org> 2005-08-07 17:03
> On Sun, Aug 07, 2005 at 01:20:39PM +0200, Thomas Graf wrote:
> > Same very minor issues as nfnetlink regarding some of the
> > new netlink message construction policies. I'll "fix" them
> > during the conversion to the generic netlink attributes.
> 
> is this supposed to happen soon?  I also need to update the userspace
> side in case you make any changes, so I'd appreciate any changes going
> in ASAP.  Alternatively just tell me what needs to change and I'll
> change it even before the generalization.

Within the next days. It is compatible to the old macros so
as long as we don't delete the old ones userspace can stay
as-is for the moment.

^ permalink raw reply

* [PATCH] add autoloading support to nfnetlink_log
From: Harald Welte @ 2005-08-07 22:15 UTC (permalink / raw)
  To: David Miller; +Cc: Linux Netdev List, Netfilter Development Mailinglist


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

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: 33-nfnetlink_log-autoload.patch --]
[-- Type: text/plain, Size: 1022 bytes --]

[NETFILTER] fix autoloading of nfnetlink_log

This patch adds the MODULE_ALIAS required for netnlink autoloading of
nfnetlink_log.

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

---
commit 7e42bac6926c9ab54033ddc4695e9a3d30b6b453
tree aae33467661ea95482d218e22ceadfa448cc8a0d
parent c16fd4ffed6349d0888cd97a75d04394dac42021
author Harald Welte <laforge@netfilter.org> So, 07 Aug 2005 19:24:43 +0200
committer Harald Welte <laforge@netfilter.org> So, 07 Aug 2005 19:24:43 +0200

 net/netfilter/nfnetlink_log.c |    1 +
 1 files changed, 1 insertions(+), 0 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
@@ -1013,6 +1013,7 @@ static void __exit fini(void)
 MODULE_DESCRIPTION("netfilter userspace logging");
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ULOG);
 
 module_init(init);
 module_exit(fini);

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

^ permalink raw reply

* [PATCH] split net/core/netfilter.c into net/netfilter/*.c
From: Harald Welte @ 2005-08-07 22:17 UTC (permalink / raw)
  To: David Miller; +Cc: Linux Netdev List, Netfilter Development Mailinglist


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

Hi Dave,

please apply to net-2.6.14

-- 
- 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: 34-netfilter-dirmove.patch --]
[-- Type: text/plain, Size: 43600 bytes --]

[NETFILTER] split net/core/netfilter.c into net/netfilter/*.c

This patch doesn't introduce any code changes, but merely splits the core
netfilter code into four separate files.  It also moves it from it's old
location in net/core/ to the recently-created net/netfilter/ directory.

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

---
commit cfac4409abdf624846d1b97495c4e9c0e4a63658
tree c3b7526dd4aeca3fe6b80e8b0953698881c2ddd8
parent 7e42bac6926c9ab54033ddc4695e9a3d30b6b453
author Harald Welte <laforge@netfilter.org> So, 07 Aug 2005 22:05:00 +0200
committer Harald Welte <laforge@netfilter.org> So, 07 Aug 2005 22:05:00 +0200

 net/core/Makefile            |    1 
 net/core/netfilter.c         |  737 ------------------------------------------
 net/netfilter/Makefile       |    4 
 net/netfilter/core.c         |  216 ++++++++++++
 net/netfilter/nf_internals.h |   39 ++
 net/netfilter/nf_log.c       |  165 +++++++++
 net/netfilter/nf_queue.c     |  273 ++++++++++++++++
 net/netfilter/nf_sockopt.c   |  132 ++++++++
 8 files changed, 829 insertions(+), 738 deletions(-)

diff --git a/net/core/Makefile b/net/core/Makefile
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -12,7 +12,6 @@ obj-y		     += dev.o ethtool.o dev_mcast
 
 obj-$(CONFIG_XFRM) += flow.o
 obj-$(CONFIG_SYSFS) += net-sysfs.o
-obj-$(CONFIG_NETFILTER) += netfilter.o
 obj-$(CONFIG_NET_DIVERT) += dv.o
 obj-$(CONFIG_NET_PKTGEN) += pktgen.o
 obj-$(CONFIG_NET_RADIO) += wireless.o
diff --git a/net/core/netfilter.c b/net/core/netfilter.c
deleted file mode 100644
--- a/net/core/netfilter.c
+++ /dev/null
@@ -1,737 +0,0 @@
-/* netfilter.c: look after the filters for various protocols. 
- * Heavily influenced by the old firewall.c by David Bonn and Alan Cox.
- *
- * Thanks to Rob `CmdrTaco' Malda for not influencing this code in any
- * way.
- *
- * Rusty Russell (C)2000 -- This code is GPL.
- *
- * February 2000: Modified by James Morris to have 1 queue per protocol.
- * 15-Mar-2000:   Added NF_REPEAT --RR.
- * 08-May-2003:	  Internal logging interface added by Jozsef Kadlecsik.
- */
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/netfilter.h>
-#include <net/protocol.h>
-#include <linux/init.h>
-#include <linux/skbuff.h>
-#include <linux/wait.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/if.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/proc_fs.h>
-#include <net/sock.h>
-
-/* In this code, we can be waiting indefinitely for userspace to
- * service a packet if a hook returns NF_QUEUE.  We could keep a count
- * of skbuffs queued for userspace, and not deregister a hook unless
- * this is zero, but that sucks.  Now, we simply check when the
- * packets come back: if the hook is gone, the packet is discarded. */
-#ifdef CONFIG_NETFILTER_DEBUG
-#define NFDEBUG(format, args...)  printk(format , ## args)
-#else
-#define NFDEBUG(format, args...)
-#endif
-
-/* Sockopts only registered and called from user context, so
-   net locking would be overkill.  Also, [gs]etsockopt calls may
-   sleep. */
-static DECLARE_MUTEX(nf_sockopt_mutex);
-
-struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
-static LIST_HEAD(nf_sockopts);
-static DEFINE_SPINLOCK(nf_hook_lock);
-
-/* 
- * A queue handler may be registered for each protocol.  Each is protected by
- * long term mutex.  The handler must provide an an outfn() to accept packets
- * for queueing and must reinject all packets it receives, no matter what.
- */
-static struct nf_queue_handler_t {
-	nf_queue_outfn_t outfn;
-	void *data;
-} queue_handler[NPROTO];
-
-static struct nf_queue_rerouter *queue_rerouter;
-
-static DEFINE_RWLOCK(queue_handler_lock);
-
-int nf_register_hook(struct nf_hook_ops *reg)
-{
-	struct list_head *i;
-
-	spin_lock_bh(&nf_hook_lock);
-	list_for_each(i, &nf_hooks[reg->pf][reg->hooknum]) {
-		if (reg->priority < ((struct nf_hook_ops *)i)->priority)
-			break;
-	}
-	list_add_rcu(&reg->list, i->prev);
-	spin_unlock_bh(&nf_hook_lock);
-
-	synchronize_net();
-	return 0;
-}
-
-void nf_unregister_hook(struct nf_hook_ops *reg)
-{
-	spin_lock_bh(&nf_hook_lock);
-	list_del_rcu(&reg->list);
-	spin_unlock_bh(&nf_hook_lock);
-
-	synchronize_net();
-}
-
-/* Do exclusive ranges overlap? */
-static inline int overlap(int min1, int max1, int min2, int max2)
-{
-	return max1 > min2 && min1 < max2;
-}
-
-/* Functions to register sockopt ranges (exclusive). */
-int nf_register_sockopt(struct nf_sockopt_ops *reg)
-{
-	struct list_head *i;
-	int ret = 0;
-
-	if (down_interruptible(&nf_sockopt_mutex) != 0)
-		return -EINTR;
-
-	list_for_each(i, &nf_sockopts) {
-		struct nf_sockopt_ops *ops = (struct nf_sockopt_ops *)i;
-		if (ops->pf == reg->pf
-		    && (overlap(ops->set_optmin, ops->set_optmax, 
-				reg->set_optmin, reg->set_optmax)
-			|| overlap(ops->get_optmin, ops->get_optmax, 
-				   reg->get_optmin, reg->get_optmax))) {
-			NFDEBUG("nf_sock overlap: %u-%u/%u-%u v %u-%u/%u-%u\n",
-				ops->set_optmin, ops->set_optmax, 
-				ops->get_optmin, ops->get_optmax, 
-				reg->set_optmin, reg->set_optmax,
-				reg->get_optmin, reg->get_optmax);
-			ret = -EBUSY;
-			goto out;
-		}
-	}
-
-	list_add(&reg->list, &nf_sockopts);
-out:
-	up(&nf_sockopt_mutex);
-	return ret;
-}
-
-void nf_unregister_sockopt(struct nf_sockopt_ops *reg)
-{
-	/* No point being interruptible: we're probably in cleanup_module() */
- restart:
-	down(&nf_sockopt_mutex);
-	if (reg->use != 0) {
-		/* To be woken by nf_sockopt call... */
-		/* FIXME: Stuart Young's name appears gratuitously. */
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		reg->cleanup_task = current;
-		up(&nf_sockopt_mutex);
-		schedule();
-		goto restart;
-	}
-	list_del(&reg->list);
-	up(&nf_sockopt_mutex);
-}
-
-/* Call get/setsockopt() */
-static int nf_sockopt(struct sock *sk, int pf, int val, 
-		      char __user *opt, int *len, int get)
-{
-	struct list_head *i;
-	struct nf_sockopt_ops *ops;
-	int ret;
-
-	if (down_interruptible(&nf_sockopt_mutex) != 0)
-		return -EINTR;
-
-	list_for_each(i, &nf_sockopts) {
-		ops = (struct nf_sockopt_ops *)i;
-		if (ops->pf == pf) {
-			if (get) {
-				if (val >= ops->get_optmin
-				    && val < ops->get_optmax) {
-					ops->use++;
-					up(&nf_sockopt_mutex);
-					ret = ops->get(sk, val, opt, len);
-					goto out;
-				}
-			} else {
-				if (val >= ops->set_optmin
-				    && val < ops->set_optmax) {
-					ops->use++;
-					up(&nf_sockopt_mutex);
-					ret = ops->set(sk, val, opt, *len);
-					goto out;
-				}
-			}
-		}
-	}
-	up(&nf_sockopt_mutex);
-	return -ENOPROTOOPT;
-	
- out:
-	down(&nf_sockopt_mutex);
-	ops->use--;
-	if (ops->cleanup_task)
-		wake_up_process(ops->cleanup_task);
-	up(&nf_sockopt_mutex);
-	return ret;
-}
-
-int nf_setsockopt(struct sock *sk, int pf, int val, char __user *opt,
-		  int len)
-{
-	return nf_sockopt(sk, pf, val, opt, &len, 0);
-}
-
-int nf_getsockopt(struct sock *sk, int pf, int val, char __user *opt, int *len)
-{
-	return nf_sockopt(sk, pf, val, opt, len, 1);
-}
-
-static unsigned int nf_iterate(struct list_head *head,
-			       struct sk_buff **skb,
-			       int hook,
-			       const struct net_device *indev,
-			       const struct net_device *outdev,
-			       struct list_head **i,
-			       int (*okfn)(struct sk_buff *),
-			       int hook_thresh)
-{
-	unsigned int verdict;
-
-	/*
-	 * The caller must not block between calls to this
-	 * function because of risk of continuing from deleted element.
-	 */
-	list_for_each_continue_rcu(*i, head) {
-		struct nf_hook_ops *elem = (struct nf_hook_ops *)*i;
-
-		if (hook_thresh > elem->priority)
-			continue;
-
-		/* Optimization: we don't need to hold module
-                   reference here, since function can't sleep. --RR */
-		verdict = elem->hook(hook, skb, indev, outdev, okfn);
-		if (verdict != NF_ACCEPT) {
-#ifdef CONFIG_NETFILTER_DEBUG
-			if (unlikely((verdict & NF_VERDICT_MASK)
-							> NF_MAX_VERDICT)) {
-				NFDEBUG("Evil return from %p(%u).\n",
-				        elem->hook, hook);
-				continue;
-			}
-#endif
-			if (verdict != NF_REPEAT)
-				return verdict;
-			*i = (*i)->prev;
-		}
-	}
-	return NF_ACCEPT;
-}
-
-int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
-{      
-	int ret;
-
-	if (pf >= NPROTO)
-		return -EINVAL;
-
-	write_lock_bh(&queue_handler_lock);
-	if (queue_handler[pf].outfn)
-		ret = -EBUSY;
-	else {
-		queue_handler[pf].outfn = outfn;
-		queue_handler[pf].data = data;
-		ret = 0;
-	}
-	write_unlock_bh(&queue_handler_lock);
-
-	return ret;
-}
-
-/* The caller must flush their queue before this */
-int nf_unregister_queue_handler(int pf)
-{
-	if (pf >= NPROTO)
-		return -EINVAL;
-
-	write_lock_bh(&queue_handler_lock);
-	queue_handler[pf].outfn = NULL;
-	queue_handler[pf].data = NULL;
-	write_unlock_bh(&queue_handler_lock);
-	
-	return 0;
-}
-
-int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer)
-{
-	if (pf >= NPROTO)
-		return -EINVAL;
-
-	write_lock_bh(&queue_handler_lock);
-	memcpy(&queue_rerouter[pf], rer, sizeof(queue_rerouter[pf]));
-	write_unlock_bh(&queue_handler_lock);
-
-	return 0;
-}
-
-int nf_unregister_queue_rerouter(int pf)
-{
-	if (pf >= NPROTO)
-		return -EINVAL;
-
-	write_lock_bh(&queue_handler_lock);
-	memset(&queue_rerouter[pf], 0, sizeof(queue_rerouter[pf]));
-	write_unlock_bh(&queue_handler_lock);
-	return 0;
-}
-
-void nf_unregister_queue_handlers(nf_queue_outfn_t outfn)
-{
-	int pf;
-
-	write_lock_bh(&queue_handler_lock);
-	for (pf = 0; pf < NPROTO; pf++)  {
-		if (queue_handler[pf].outfn == outfn) {
-			queue_handler[pf].outfn = NULL;
-			queue_handler[pf].data = NULL;
-		}
-	}
-	write_unlock_bh(&queue_handler_lock);
-}
-
-/* 
- * Any packet that leaves via this function must come back 
- * through nf_reinject().
- */
-static int nf_queue(struct sk_buff **skb, 
-		    struct list_head *elem, 
-		    int pf, unsigned int hook,
-		    struct net_device *indev,
-		    struct net_device *outdev,
-		    int (*okfn)(struct sk_buff *),
-		    unsigned int queuenum)
-{
-	int status;
-	struct nf_info *info;
-#ifdef CONFIG_BRIDGE_NETFILTER
-	struct net_device *physindev = NULL;
-	struct net_device *physoutdev = NULL;
-#endif
-
-	/* QUEUE == DROP if noone is waiting, to be safe. */
-	read_lock(&queue_handler_lock);
-	if (!queue_handler[pf].outfn) {
-		read_unlock(&queue_handler_lock);
-		kfree_skb(*skb);
-		return 1;
-	}
-
-	info = kmalloc(sizeof(*info)+queue_rerouter[pf].rer_size, GFP_ATOMIC);
-	if (!info) {
-		if (net_ratelimit())
-			printk(KERN_ERR "OOM queueing packet %p\n",
-			       *skb);
-		read_unlock(&queue_handler_lock);
-		kfree_skb(*skb);
-		return 1;
-	}
-
-	*info = (struct nf_info) { 
-		(struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn };
-
-	/* If it's going away, ignore hook. */
-	if (!try_module_get(info->elem->owner)) {
-		read_unlock(&queue_handler_lock);
-		kfree(info);
-		return 0;
-	}
-
-	/* Bump dev refs so they don't vanish while packet is out */
-	if (indev) dev_hold(indev);
-	if (outdev) dev_hold(outdev);
-
-#ifdef CONFIG_BRIDGE_NETFILTER
-	if ((*skb)->nf_bridge) {
-		physindev = (*skb)->nf_bridge->physindev;
-		if (physindev) dev_hold(physindev);
-		physoutdev = (*skb)->nf_bridge->physoutdev;
-		if (physoutdev) dev_hold(physoutdev);
-	}
-#endif
-	if (queue_rerouter[pf].save)
-		queue_rerouter[pf].save(*skb, info);
-
-	status = queue_handler[pf].outfn(*skb, info, queuenum,
-					 queue_handler[pf].data);
-
-	if (status >= 0 && queue_rerouter[pf].reroute)
-		status = queue_rerouter[pf].reroute(skb, info);
-
-	read_unlock(&queue_handler_lock);
-
-	if (status < 0) {
-		/* James M doesn't say fuck enough. */
-		if (indev) dev_put(indev);
-		if (outdev) dev_put(outdev);
-#ifdef CONFIG_BRIDGE_NETFILTER
-		if (physindev) dev_put(physindev);
-		if (physoutdev) dev_put(physoutdev);
-#endif
-		module_put(info->elem->owner);
-		kfree(info);
-		kfree_skb(*skb);
-
-		return 1;
-	}
-
-	return 1;
-}
-
-/* Returns 1 if okfn() needs to be executed by the caller,
- * -EPERM for NF_DROP, 0 otherwise. */
-int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
-		 struct net_device *indev,
-		 struct net_device *outdev,
-		 int (*okfn)(struct sk_buff *),
-		 int hook_thresh)
-{
-	struct list_head *elem;
-	unsigned int verdict;
-	int ret = 0;
-
-	/* We may already have this, but read-locks nest anyway */
-	rcu_read_lock();
-
-	elem = &nf_hooks[pf][hook];
-next_hook:
-	verdict = nf_iterate(&nf_hooks[pf][hook], pskb, hook, indev,
-			     outdev, &elem, okfn, hook_thresh);
-	if (verdict == NF_ACCEPT || verdict == NF_STOP) {
-		ret = 1;
-		goto unlock;
-	} else if (verdict == NF_DROP) {
-		kfree_skb(*pskb);
-		ret = -EPERM;
-	} else if ((verdict & NF_VERDICT_MASK)  == NF_QUEUE) {
-		NFDEBUG("nf_hook: Verdict = QUEUE.\n");
-		if (!nf_queue(pskb, elem, pf, hook, indev, outdev, okfn,
-			      verdict >> NF_VERDICT_BITS))
-			goto next_hook;
-	}
-unlock:
-	rcu_read_unlock();
-	return ret;
-}
-
-void nf_reinject(struct sk_buff *skb, struct nf_info *info,
-		 unsigned int verdict)
-{
-	struct list_head *elem = &info->elem->list;
-	struct list_head *i;
-
-	rcu_read_lock();
-
-	/* Release those devices we held, or Alexey will kill me. */
-	if (info->indev) dev_put(info->indev);
-	if (info->outdev) dev_put(info->outdev);
-#ifdef CONFIG_BRIDGE_NETFILTER
-	if (skb->nf_bridge) {
-		if (skb->nf_bridge->physindev)
-			dev_put(skb->nf_bridge->physindev);
-		if (skb->nf_bridge->physoutdev)
-			dev_put(skb->nf_bridge->physoutdev);
-	}
-#endif
-
-	/* Drop reference to owner of hook which queued us. */
-	module_put(info->elem->owner);
-
-	list_for_each_rcu(i, &nf_hooks[info->pf][info->hook]) {
-		if (i == elem) 
-  			break;
-  	}
-  
-	if (elem == &nf_hooks[info->pf][info->hook]) {
-		/* The module which sent it to userspace is gone. */
-		NFDEBUG("%s: module disappeared, dropping packet.\n",
-			__FUNCTION__);
-		verdict = NF_DROP;
-	}
-
-	/* Continue traversal iff userspace said ok... */
-	if (verdict == NF_REPEAT) {
-		elem = elem->prev;
-		verdict = NF_ACCEPT;
-	}
-
-	if (verdict == NF_ACCEPT) {
-	next_hook:
-		verdict = nf_iterate(&nf_hooks[info->pf][info->hook],
-				     &skb, info->hook, 
-				     info->indev, info->outdev, &elem,
-				     info->okfn, INT_MIN);
-	}
-
-	switch (verdict & NF_VERDICT_MASK) {
-	case NF_ACCEPT:
-		info->okfn(skb);
-		break;
-
-	case NF_QUEUE:
-		if (!nf_queue(&skb, elem, info->pf, info->hook, 
-			      info->indev, info->outdev, info->okfn,
-			      verdict >> NF_VERDICT_BITS))
-			goto next_hook;
-		break;
-	}
-	rcu_read_unlock();
-
-	if (verdict == NF_DROP)
-		kfree_skb(skb);
-
-	kfree(info);
-	return;
-}
-
-int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len)
-{
-	struct sk_buff *nskb;
-
-	if (writable_len > (*pskb)->len)
-		return 0;
-
-	/* Not exclusive use of packet?  Must copy. */
-	if (skb_shared(*pskb) || skb_cloned(*pskb))
-		goto copy_skb;
-
-	return pskb_may_pull(*pskb, writable_len);
-
-copy_skb:
-	nskb = skb_copy(*pskb, GFP_ATOMIC);
-	if (!nskb)
-		return 0;
-	BUG_ON(skb_is_nonlinear(nskb));
-
-	/* Rest of kernel will get very unhappy if we pass it a
-	   suddenly-orphaned skbuff */
-	if ((*pskb)->sk)
-		skb_set_owner_w(nskb, (*pskb)->sk);
-	kfree_skb(*pskb);
-	*pskb = nskb;
-	return 1;
-}
-EXPORT_SYMBOL(skb_make_writable);
-
-/* Internal logging interface, which relies on the real 
-   LOG target modules */
-
-#define NF_LOG_PREFIXLEN		128
-
-static struct nf_logger *nf_logging[NPROTO]; /* = NULL */
-static DEFINE_SPINLOCK(nf_log_lock);
-
-int nf_log_register(int pf, struct nf_logger *logger)
-{
-	int ret = -EBUSY;
-
-	/* Any setup of logging members must be done before
-	 * substituting pointer. */
-	spin_lock(&nf_log_lock);
-	if (!nf_logging[pf]) {
-		rcu_assign_pointer(nf_logging[pf], logger);
-		ret = 0;
-	}
-	spin_unlock(&nf_log_lock);
-	return ret;
-}		
-
-void nf_log_unregister_pf(int pf)
-{
-	spin_lock(&nf_log_lock);
-	nf_logging[pf] = NULL;
-	spin_unlock(&nf_log_lock);
-
-	/* Give time to concurrent readers. */
-	synchronize_net();
-}
-
-void nf_log_unregister_logger(struct nf_logger *logger)
-{
-	int i;
-
-	spin_lock(&nf_log_lock);
-	for (i = 0; i < NPROTO; i++) {
-		if (nf_logging[i] == logger)
-			nf_logging[i] = NULL;
-	}
-	spin_unlock(&nf_log_lock);
-
-	synchronize_net();
-}
-
-void nf_log_packet(int pf,
-		   unsigned int hooknum,
-		   const struct sk_buff *skb,
-		   const struct net_device *in,
-		   const struct net_device *out,
-		   struct nf_loginfo *loginfo,
-		   const char *fmt, ...)
-{
-	va_list args;
-	char prefix[NF_LOG_PREFIXLEN];
-	struct nf_logger *logger;
-	
-	rcu_read_lock();
-	logger = rcu_dereference(nf_logging[pf]);
-	if (logger) {
-		va_start(args, fmt);
-		vsnprintf(prefix, sizeof(prefix), fmt, args);
-		va_end(args);
-		/* We must read logging before nf_logfn[pf] */
-		logger->logfn(pf, hooknum, skb, in, out, loginfo, prefix);
-	} else if (net_ratelimit()) {
-		printk(KERN_WARNING "nf_log_packet: can\'t log since "
-		       "no backend logging module loaded in! Please either "
-		       "load one, or disable logging explicitly\n");
-	}
-	rcu_read_unlock();
-}
-EXPORT_SYMBOL(nf_log_register);
-EXPORT_SYMBOL(nf_log_unregister_pf);
-EXPORT_SYMBOL(nf_log_unregister_logger);
-EXPORT_SYMBOL(nf_log_packet);
-
-#ifdef CONFIG_PROC_FS
-struct proc_dir_entry *proc_net_netfilter;
-EXPORT_SYMBOL(proc_net_netfilter);
-
-static void *seq_start(struct seq_file *seq, loff_t *pos)
-{
-	rcu_read_lock();
-
-	if (*pos >= NPROTO)
-		return NULL;
-
-	return pos;
-}
-
-static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
-	(*pos)++;
-
-	if (*pos >= NPROTO)
-		return NULL;
-
-	return pos;
-}
-
-static void seq_stop(struct seq_file *s, void *v)
-{
-	rcu_read_unlock();
-}
-
-static int seq_show(struct seq_file *s, void *v)
-{
-	loff_t *pos = v;
-	const struct nf_logger *logger;
-
-	logger = rcu_dereference(nf_logging[*pos]);
-
-	if (!logger)
-		return seq_printf(s, "%2lld NONE\n", *pos);
-	
-	return seq_printf(s, "%2lld %s\n", *pos, logger->name);
-}
-
-static struct seq_operations nflog_seq_ops = {
-	.start	= seq_start,
-	.next	= seq_next,
-	.stop	= seq_stop,
-	.show	= seq_show,
-};
-
-static int nflog_open(struct inode *inode, struct file *file)
-{
-	return seq_open(file, &nflog_seq_ops);
-}
-
-static struct file_operations nflog_file_ops = {
-	.owner	 = THIS_MODULE,
-	.open	 = nflog_open,
-	.read	 = seq_read,
-	.llseek	 = seq_lseek,
-	.release = seq_release,
-};
-
-#endif /* PROC_FS */
-
-
-/* This does not belong here, but locally generated errors need it if connection
-   tracking in use: without this, connection may not be in hash table, and hence
-   manufactured ICMP or RST packets will not be associated with it. */
-void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
-
-void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
-{
-	void (*attach)(struct sk_buff *, struct sk_buff *);
-
-	if (skb->nfct && (attach = ip_ct_attach) != NULL) {
-		mb(); /* Just to be sure: must be read before executing this */
-		attach(new, skb);
-	}
-}
-
-void __init netfilter_init(void)
-{
-	int i, h;
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *pde;
-#endif
-
-	queue_rerouter = kmalloc(NPROTO * sizeof(struct nf_queue_rerouter),
-				 GFP_KERNEL);
-	if (!queue_rerouter)
-		panic("netfilter: cannot allocate queue rerouter array\n");
-	memset(queue_rerouter, 0, NPROTO * sizeof(struct nf_queue_rerouter));
-
-	for (i = 0; i < NPROTO; i++) {
-		for (h = 0; h < NF_MAX_HOOKS; h++)
-			INIT_LIST_HEAD(&nf_hooks[i][h]);
-	}
-
-#ifdef CONFIG_PROC_FS
-	proc_net_netfilter = proc_mkdir("netfilter", proc_net);
-	if (!proc_net_netfilter)
-		panic("cannot create netfilter proc entry");
-	pde = create_proc_entry("nf_log", S_IRUGO, proc_net_netfilter);
-	if (!pde)
-		panic("cannot create /proc/net/netfilter/nf_log");
-	pde->proc_fops = &nflog_file_ops;
-#endif
-}
-
-EXPORT_SYMBOL(ip_ct_attach);
-EXPORT_SYMBOL(nf_ct_attach);
-EXPORT_SYMBOL(nf_getsockopt);
-EXPORT_SYMBOL(nf_hook_slow);
-EXPORT_SYMBOL(nf_hooks);
-EXPORT_SYMBOL(nf_register_hook);
-EXPORT_SYMBOL(nf_register_queue_handler);
-EXPORT_SYMBOL(nf_register_sockopt);
-EXPORT_SYMBOL(nf_reinject);
-EXPORT_SYMBOL(nf_setsockopt);
-EXPORT_SYMBOL(nf_unregister_hook);
-EXPORT_SYMBOL(nf_unregister_queue_handler);
-EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
-EXPORT_SYMBOL_GPL(nf_register_queue_rerouter);
-EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter);
-EXPORT_SYMBOL(nf_unregister_sockopt);
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,3 +1,7 @@
+netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
+
+obj-$(CONFIG_NETFILTER) = netfilter.o
+
 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/core.c b/net/netfilter/core.c
new file mode 100644
--- /dev/null
+++ b/net/netfilter/core.c
@@ -0,0 +1,216 @@
+/* netfilter.c: look after the filters for various protocols. 
+ * Heavily influenced by the old firewall.c by David Bonn and Alan Cox.
+ *
+ * Thanks to Rob `CmdrTaco' Malda for not influencing this code in any
+ * way.
+ *
+ * Rusty Russell (C)2000 -- This code is GPL.
+ *
+ * February 2000: Modified by James Morris to have 1 queue per protocol.
+ * 15-Mar-2000:   Added NF_REPEAT --RR.
+ * 08-May-2003:	  Internal logging interface added by Jozsef Kadlecsik.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/netfilter.h>
+#include <net/protocol.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/wait.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/if.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/proc_fs.h>
+#include <net/sock.h>
+
+#include "nf_internals.h"
+
+/* In this code, we can be waiting indefinitely for userspace to
+ * service a packet if a hook returns NF_QUEUE.  We could keep a count
+ * of skbuffs queued for userspace, and not deregister a hook unless
+ * this is zero, but that sucks.  Now, we simply check when the
+ * packets come back: if the hook is gone, the packet is discarded. */
+struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
+EXPORT_SYMBOL(nf_hooks);
+static DEFINE_SPINLOCK(nf_hook_lock);
+
+int nf_register_hook(struct nf_hook_ops *reg)
+{
+	struct list_head *i;
+
+	spin_lock_bh(&nf_hook_lock);
+	list_for_each(i, &nf_hooks[reg->pf][reg->hooknum]) {
+		if (reg->priority < ((struct nf_hook_ops *)i)->priority)
+			break;
+	}
+	list_add_rcu(&reg->list, i->prev);
+	spin_unlock_bh(&nf_hook_lock);
+
+	synchronize_net();
+	return 0;
+}
+EXPORT_SYMBOL(nf_register_hook);
+
+void nf_unregister_hook(struct nf_hook_ops *reg)
+{
+	spin_lock_bh(&nf_hook_lock);
+	list_del_rcu(&reg->list);
+	spin_unlock_bh(&nf_hook_lock);
+
+	synchronize_net();
+}
+EXPORT_SYMBOL(nf_unregister_hook);
+
+unsigned int nf_iterate(struct list_head *head,
+			struct sk_buff **skb,
+			int hook,
+			const struct net_device *indev,
+			const struct net_device *outdev,
+			struct list_head **i,
+			int (*okfn)(struct sk_buff *),
+			int hook_thresh)
+{
+	unsigned int verdict;
+
+	/*
+	 * The caller must not block between calls to this
+	 * function because of risk of continuing from deleted element.
+	 */
+	list_for_each_continue_rcu(*i, head) {
+		struct nf_hook_ops *elem = (struct nf_hook_ops *)*i;
+
+		if (hook_thresh > elem->priority)
+			continue;
+
+		/* Optimization: we don't need to hold module
+                   reference here, since function can't sleep. --RR */
+		verdict = elem->hook(hook, skb, indev, outdev, okfn);
+		if (verdict != NF_ACCEPT) {
+#ifdef CONFIG_NETFILTER_DEBUG
+			if (unlikely((verdict & NF_VERDICT_MASK)
+							> NF_MAX_VERDICT)) {
+				NFDEBUG("Evil return from %p(%u).\n",
+				        elem->hook, hook);
+				continue;
+			}
+#endif
+			if (verdict != NF_REPEAT)
+				return verdict;
+			*i = (*i)->prev;
+		}
+	}
+	return NF_ACCEPT;
+}
+
+
+/* Returns 1 if okfn() needs to be executed by the caller,
+ * -EPERM for NF_DROP, 0 otherwise. */
+int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
+		 struct net_device *indev,
+		 struct net_device *outdev,
+		 int (*okfn)(struct sk_buff *),
+		 int hook_thresh)
+{
+	struct list_head *elem;
+	unsigned int verdict;
+	int ret = 0;
+
+	/* We may already have this, but read-locks nest anyway */
+	rcu_read_lock();
+
+	elem = &nf_hooks[pf][hook];
+next_hook:
+	verdict = nf_iterate(&nf_hooks[pf][hook], pskb, hook, indev,
+			     outdev, &elem, okfn, hook_thresh);
+	if (verdict == NF_ACCEPT || verdict == NF_STOP) {
+		ret = 1;
+		goto unlock;
+	} else if (verdict == NF_DROP) {
+		kfree_skb(*pskb);
+		ret = -EPERM;
+	} else if ((verdict & NF_VERDICT_MASK)  == NF_QUEUE) {
+		NFDEBUG("nf_hook: Verdict = QUEUE.\n");
+		if (!nf_queue(pskb, elem, pf, hook, indev, outdev, okfn,
+			      verdict >> NF_VERDICT_BITS))
+			goto next_hook;
+	}
+unlock:
+	rcu_read_unlock();
+	return ret;
+}
+EXPORT_SYMBOL(nf_hook_slow);
+
+
+int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len)
+{
+	struct sk_buff *nskb;
+
+	if (writable_len > (*pskb)->len)
+		return 0;
+
+	/* Not exclusive use of packet?  Must copy. */
+	if (skb_shared(*pskb) || skb_cloned(*pskb))
+		goto copy_skb;
+
+	return pskb_may_pull(*pskb, writable_len);
+
+copy_skb:
+	nskb = skb_copy(*pskb, GFP_ATOMIC);
+	if (!nskb)
+		return 0;
+	BUG_ON(skb_is_nonlinear(nskb));
+
+	/* Rest of kernel will get very unhappy if we pass it a
+	   suddenly-orphaned skbuff */
+	if ((*pskb)->sk)
+		skb_set_owner_w(nskb, (*pskb)->sk);
+	kfree_skb(*pskb);
+	*pskb = nskb;
+	return 1;
+}
+EXPORT_SYMBOL(skb_make_writable);
+
+
+/* This does not belong here, but locally generated errors need it if connection
+   tracking in use: without this, connection may not be in hash table, and hence
+   manufactured ICMP or RST packets will not be associated with it. */
+void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
+EXPORT_SYMBOL(ip_ct_attach);
+
+void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
+{
+	void (*attach)(struct sk_buff *, struct sk_buff *);
+
+	if (skb->nfct && (attach = ip_ct_attach) != NULL) {
+		mb(); /* Just to be sure: must be read before executing this */
+		attach(new, skb);
+	}
+}
+EXPORT_SYMBOL(nf_ct_attach);
+
+#ifdef CONFIG_PROC_FS
+struct proc_dir_entry *proc_net_netfilter;
+EXPORT_SYMBOL(proc_net_netfilter);
+#endif
+
+void __init netfilter_init(void)
+{
+	int i, h;
+	for (i = 0; i < NPROTO; i++) {
+		for (h = 0; h < NF_MAX_HOOKS; h++)
+			INIT_LIST_HEAD(&nf_hooks[i][h]);
+	}
+
+#ifdef CONFIG_PROC_FS
+	proc_net_netfilter = proc_mkdir("netfilter", proc_net);
+	if (!proc_net_netfilter)
+		panic("cannot create netfilter proc entry");
+#endif
+
+	if (netfilter_queue_init() < 0)
+		panic("cannot initialize nf_queue");
+	if (netfilter_log_init() < 0)
+		panic("cannot initialize nf_log");
+}
diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h
new file mode 100644
--- /dev/null
+++ b/net/netfilter/nf_internals.h
@@ -0,0 +1,39 @@
+#ifndef _NF_INTERNALS_H
+#define _NF_INTERNALS_H
+
+#include <linux/config.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#ifdef CONFIG_NETFILTER_DEBUG
+#define NFDEBUG(format, args...)  printk(format , ## args)
+#else
+#define NFDEBUG(format, args...)
+#endif
+
+
+/* core.c */
+extern unsigned int nf_iterate(struct list_head *head,
+				struct sk_buff **skb,
+				int hook,
+				const struct net_device *indev,
+				const struct net_device *outdev,
+				struct list_head **i,
+				int (*okfn)(struct sk_buff *),
+				int hook_thresh);
+
+/* nf_queue.c */
+extern int nf_queue(struct sk_buff **skb, 
+		    struct list_head *elem, 
+		    int pf, unsigned int hook,
+		    struct net_device *indev,
+		    struct net_device *outdev,
+		    int (*okfn)(struct sk_buff *),
+		    unsigned int queuenum);
+extern int __init netfilter_queue_init(void);
+
+/* nf_log.c */
+extern int __init netfilter_log_init(void);
+
+#endif
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
new file mode 100644
--- /dev/null
+++ b/net/netfilter/nf_log.c
@@ -0,0 +1,165 @@
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter.h>
+#include <net/protocol.h>
+
+#include "nf_internals.h"
+
+/* Internal logging interface, which relies on the real 
+   LOG target modules */
+
+#define NF_LOG_PREFIXLEN		128
+
+static struct nf_logger *nf_logging[NPROTO]; /* = NULL */
+static DEFINE_SPINLOCK(nf_log_lock);
+
+int nf_log_register(int pf, struct nf_logger *logger)
+{
+	int ret = -EBUSY;
+
+	/* Any setup of logging members must be done before
+	 * substituting pointer. */
+	spin_lock(&nf_log_lock);
+	if (!nf_logging[pf]) {
+		rcu_assign_pointer(nf_logging[pf], logger);
+		ret = 0;
+	}
+	spin_unlock(&nf_log_lock);
+	return ret;
+}		
+EXPORT_SYMBOL(nf_log_register);
+
+void nf_log_unregister_pf(int pf)
+{
+	spin_lock(&nf_log_lock);
+	nf_logging[pf] = NULL;
+	spin_unlock(&nf_log_lock);
+
+	/* Give time to concurrent readers. */
+	synchronize_net();
+}
+EXPORT_SYMBOL(nf_log_unregister_pf);
+
+void nf_log_unregister_logger(struct nf_logger *logger)
+{
+	int i;
+
+	spin_lock(&nf_log_lock);
+	for (i = 0; i < NPROTO; i++) {
+		if (nf_logging[i] == logger)
+			nf_logging[i] = NULL;
+	}
+	spin_unlock(&nf_log_lock);
+
+	synchronize_net();
+}
+EXPORT_SYMBOL(nf_log_unregister_logger);
+
+void nf_log_packet(int pf,
+		   unsigned int hooknum,
+		   const struct sk_buff *skb,
+		   const struct net_device *in,
+		   const struct net_device *out,
+		   struct nf_loginfo *loginfo,
+		   const char *fmt, ...)
+{
+	va_list args;
+	char prefix[NF_LOG_PREFIXLEN];
+	struct nf_logger *logger;
+	
+	rcu_read_lock();
+	logger = rcu_dereference(nf_logging[pf]);
+	if (logger) {
+		va_start(args, fmt);
+		vsnprintf(prefix, sizeof(prefix), fmt, args);
+		va_end(args);
+		/* We must read logging before nf_logfn[pf] */
+		logger->logfn(pf, hooknum, skb, in, out, loginfo, prefix);
+	} else if (net_ratelimit()) {
+		printk(KERN_WARNING "nf_log_packet: can\'t log since "
+		       "no backend logging module loaded in! Please either "
+		       "load one, or disable logging explicitly\n");
+	}
+	rcu_read_unlock();
+}
+EXPORT_SYMBOL(nf_log_packet);
+
+#ifdef CONFIG_PROC_FS
+static void *seq_start(struct seq_file *seq, loff_t *pos)
+{
+	rcu_read_lock();
+
+	if (*pos >= NPROTO)
+		return NULL;
+
+	return pos;
+}
+
+static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	(*pos)++;
+
+	if (*pos >= NPROTO)
+		return NULL;
+
+	return pos;
+}
+
+static void seq_stop(struct seq_file *s, void *v)
+{
+	rcu_read_unlock();
+}
+
+static int seq_show(struct seq_file *s, void *v)
+{
+	loff_t *pos = v;
+	const struct nf_logger *logger;
+
+	logger = rcu_dereference(nf_logging[*pos]);
+
+	if (!logger)
+		return seq_printf(s, "%2lld NONE\n", *pos);
+	
+	return seq_printf(s, "%2lld %s\n", *pos, logger->name);
+}
+
+static struct seq_operations nflog_seq_ops = {
+	.start	= seq_start,
+	.next	= seq_next,
+	.stop	= seq_stop,
+	.show	= seq_show,
+};
+
+static int nflog_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &nflog_seq_ops);
+}
+
+static struct file_operations nflog_file_ops = {
+	.owner	 = THIS_MODULE,
+	.open	 = nflog_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = seq_release,
+};
+
+#endif /* PROC_FS */
+
+
+int __init netfilter_log_init(void)
+{
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry *pde;
+	pde = create_proc_entry("nf_log", S_IRUGO, proc_net_netfilter);
+#endif
+	if (!pde)
+		return -1;
+
+	pde->proc_fops = &nflog_file_ops;
+
+	return 0;
+}
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
new file mode 100644
--- /dev/null
+++ b/net/netfilter/nf_queue.c
@@ -0,0 +1,273 @@
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter.h>
+#include <net/protocol.h>
+
+#include "nf_internals.h"
+
+/* 
+ * A queue handler may be registered for each protocol.  Each is protected by
+ * long term mutex.  The handler must provide an an outfn() to accept packets
+ * for queueing and must reinject all packets it receives, no matter what.
+ */
+static struct nf_queue_handler_t {
+	nf_queue_outfn_t outfn;
+	void *data;
+} queue_handler[NPROTO];
+
+static struct nf_queue_rerouter *queue_rerouter;
+
+static DEFINE_RWLOCK(queue_handler_lock);
+
+
+int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
+{      
+	int ret;
+
+	if (pf >= NPROTO)
+		return -EINVAL;
+
+	write_lock_bh(&queue_handler_lock);
+	if (queue_handler[pf].outfn)
+		ret = -EBUSY;
+	else {
+		queue_handler[pf].outfn = outfn;
+		queue_handler[pf].data = data;
+		ret = 0;
+	}
+	write_unlock_bh(&queue_handler_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(nf_register_queue_handler);
+
+/* The caller must flush their queue before this */
+int nf_unregister_queue_handler(int pf)
+{
+	if (pf >= NPROTO)
+		return -EINVAL;
+
+	write_lock_bh(&queue_handler_lock);
+	queue_handler[pf].outfn = NULL;
+	queue_handler[pf].data = NULL;
+	write_unlock_bh(&queue_handler_lock);
+	
+	return 0;
+}
+EXPORT_SYMBOL(nf_unregister_queue_handler);
+
+int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer)
+{
+	if (pf >= NPROTO)
+		return -EINVAL;
+
+	write_lock_bh(&queue_handler_lock);
+	memcpy(&queue_rerouter[pf], rer, sizeof(queue_rerouter[pf]));
+	write_unlock_bh(&queue_handler_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nf_register_queue_rerouter);
+
+int nf_unregister_queue_rerouter(int pf)
+{
+	if (pf >= NPROTO)
+		return -EINVAL;
+
+	write_lock_bh(&queue_handler_lock);
+	memset(&queue_rerouter[pf], 0, sizeof(queue_rerouter[pf]));
+	write_unlock_bh(&queue_handler_lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter);
+
+void nf_unregister_queue_handlers(nf_queue_outfn_t outfn)
+{
+	int pf;
+
+	write_lock_bh(&queue_handler_lock);
+	for (pf = 0; pf < NPROTO; pf++)  {
+		if (queue_handler[pf].outfn == outfn) {
+			queue_handler[pf].outfn = NULL;
+			queue_handler[pf].data = NULL;
+		}
+	}
+	write_unlock_bh(&queue_handler_lock);
+}
+EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
+
+/* 
+ * Any packet that leaves via this function must come back 
+ * through nf_reinject().
+ */
+int nf_queue(struct sk_buff **skb, 
+	     struct list_head *elem, 
+	     int pf, unsigned int hook,
+	     struct net_device *indev,
+	     struct net_device *outdev,
+	     int (*okfn)(struct sk_buff *),
+	     unsigned int queuenum)
+{
+	int status;
+	struct nf_info *info;
+#ifdef CONFIG_BRIDGE_NETFILTER
+	struct net_device *physindev = NULL;
+	struct net_device *physoutdev = NULL;
+#endif
+
+	/* QUEUE == DROP if noone is waiting, to be safe. */
+	read_lock(&queue_handler_lock);
+	if (!queue_handler[pf].outfn) {
+		read_unlock(&queue_handler_lock);
+		kfree_skb(*skb);
+		return 1;
+	}
+
+	info = kmalloc(sizeof(*info)+queue_rerouter[pf].rer_size, GFP_ATOMIC);
+	if (!info) {
+		if (net_ratelimit())
+			printk(KERN_ERR "OOM queueing packet %p\n",
+			       *skb);
+		read_unlock(&queue_handler_lock);
+		kfree_skb(*skb);
+		return 1;
+	}
+
+	*info = (struct nf_info) { 
+		(struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn };
+
+	/* If it's going away, ignore hook. */
+	if (!try_module_get(info->elem->owner)) {
+		read_unlock(&queue_handler_lock);
+		kfree(info);
+		return 0;
+	}
+
+	/* Bump dev refs so they don't vanish while packet is out */
+	if (indev) dev_hold(indev);
+	if (outdev) dev_hold(outdev);
+
+#ifdef CONFIG_BRIDGE_NETFILTER
+	if ((*skb)->nf_bridge) {
+		physindev = (*skb)->nf_bridge->physindev;
+		if (physindev) dev_hold(physindev);
+		physoutdev = (*skb)->nf_bridge->physoutdev;
+		if (physoutdev) dev_hold(physoutdev);
+	}
+#endif
+	if (queue_rerouter[pf].save)
+		queue_rerouter[pf].save(*skb, info);
+
+	status = queue_handler[pf].outfn(*skb, info, queuenum,
+					 queue_handler[pf].data);
+
+	if (status >= 0 && queue_rerouter[pf].reroute)
+		status = queue_rerouter[pf].reroute(skb, info);
+
+	read_unlock(&queue_handler_lock);
+
+	if (status < 0) {
+		/* James M doesn't say fuck enough. */
+		if (indev) dev_put(indev);
+		if (outdev) dev_put(outdev);
+#ifdef CONFIG_BRIDGE_NETFILTER
+		if (physindev) dev_put(physindev);
+		if (physoutdev) dev_put(physoutdev);
+#endif
+		module_put(info->elem->owner);
+		kfree(info);
+		kfree_skb(*skb);
+
+		return 1;
+	}
+
+	return 1;
+}
+
+void nf_reinject(struct sk_buff *skb, struct nf_info *info,
+		 unsigned int verdict)
+{
+	struct list_head *elem = &info->elem->list;
+	struct list_head *i;
+
+	rcu_read_lock();
+
+	/* Release those devices we held, or Alexey will kill me. */
+	if (info->indev) dev_put(info->indev);
+	if (info->outdev) dev_put(info->outdev);
+#ifdef CONFIG_BRIDGE_NETFILTER
+	if (skb->nf_bridge) {
+		if (skb->nf_bridge->physindev)
+			dev_put(skb->nf_bridge->physindev);
+		if (skb->nf_bridge->physoutdev)
+			dev_put(skb->nf_bridge->physoutdev);
+	}
+#endif
+
+	/* Drop reference to owner of hook which queued us. */
+	module_put(info->elem->owner);
+
+	list_for_each_rcu(i, &nf_hooks[info->pf][info->hook]) {
+		if (i == elem) 
+  			break;
+  	}
+  
+	if (elem == &nf_hooks[info->pf][info->hook]) {
+		/* The module which sent it to userspace is gone. */
+		NFDEBUG("%s: module disappeared, dropping packet.\n",
+			__FUNCTION__);
+		verdict = NF_DROP;
+	}
+
+	/* Continue traversal iff userspace said ok... */
+	if (verdict == NF_REPEAT) {
+		elem = elem->prev;
+		verdict = NF_ACCEPT;
+	}
+
+	if (verdict == NF_ACCEPT) {
+	next_hook:
+		verdict = nf_iterate(&nf_hooks[info->pf][info->hook],
+				     &skb, info->hook, 
+				     info->indev, info->outdev, &elem,
+				     info->okfn, INT_MIN);
+	}
+
+	switch (verdict & NF_VERDICT_MASK) {
+	case NF_ACCEPT:
+		info->okfn(skb);
+		break;
+
+	case NF_QUEUE:
+		if (!nf_queue(&skb, elem, info->pf, info->hook, 
+			      info->indev, info->outdev, info->okfn,
+			      verdict >> NF_VERDICT_BITS))
+			goto next_hook;
+		break;
+	}
+	rcu_read_unlock();
+
+	if (verdict == NF_DROP)
+		kfree_skb(skb);
+
+	kfree(info);
+	return;
+}
+EXPORT_SYMBOL(nf_reinject);
+
+int __init netfilter_queue_init(void)
+{
+	queue_rerouter = kmalloc(NPROTO * sizeof(struct nf_queue_rerouter),
+				 GFP_KERNEL);
+	if (!queue_rerouter)
+		return -ENOMEM;
+
+	memset(queue_rerouter, 0, NPROTO * sizeof(struct nf_queue_rerouter));
+
+	return 0;
+}
+
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c
new file mode 100644
--- /dev/null
+++ b/net/netfilter/nf_sockopt.c
@@ -0,0 +1,132 @@
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter.h>
+#include <net/sock.h>
+
+#include "nf_internals.h"
+
+/* Sockopts only registered and called from user context, so
+   net locking would be overkill.  Also, [gs]etsockopt calls may
+   sleep. */
+static DECLARE_MUTEX(nf_sockopt_mutex);
+static LIST_HEAD(nf_sockopts);
+
+/* Do exclusive ranges overlap? */
+static inline int overlap(int min1, int max1, int min2, int max2)
+{
+	return max1 > min2 && min1 < max2;
+}
+
+/* Functions to register sockopt ranges (exclusive). */
+int nf_register_sockopt(struct nf_sockopt_ops *reg)
+{
+	struct list_head *i;
+	int ret = 0;
+
+	if (down_interruptible(&nf_sockopt_mutex) != 0)
+		return -EINTR;
+
+	list_for_each(i, &nf_sockopts) {
+		struct nf_sockopt_ops *ops = (struct nf_sockopt_ops *)i;
+		if (ops->pf == reg->pf
+		    && (overlap(ops->set_optmin, ops->set_optmax, 
+				reg->set_optmin, reg->set_optmax)
+			|| overlap(ops->get_optmin, ops->get_optmax, 
+				   reg->get_optmin, reg->get_optmax))) {
+			NFDEBUG("nf_sock overlap: %u-%u/%u-%u v %u-%u/%u-%u\n",
+				ops->set_optmin, ops->set_optmax, 
+				ops->get_optmin, ops->get_optmax, 
+				reg->set_optmin, reg->set_optmax,
+				reg->get_optmin, reg->get_optmax);
+			ret = -EBUSY;
+			goto out;
+		}
+	}
+
+	list_add(&reg->list, &nf_sockopts);
+out:
+	up(&nf_sockopt_mutex);
+	return ret;
+}
+EXPORT_SYMBOL(nf_register_sockopt);
+
+void nf_unregister_sockopt(struct nf_sockopt_ops *reg)
+{
+	/* No point being interruptible: we're probably in cleanup_module() */
+ restart:
+	down(&nf_sockopt_mutex);
+	if (reg->use != 0) {
+		/* To be woken by nf_sockopt call... */
+		/* FIXME: Stuart Young's name appears gratuitously. */
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		reg->cleanup_task = current;
+		up(&nf_sockopt_mutex);
+		schedule();
+		goto restart;
+	}
+	list_del(&reg->list);
+	up(&nf_sockopt_mutex);
+}
+EXPORT_SYMBOL(nf_unregister_sockopt);
+
+/* Call get/setsockopt() */
+static int nf_sockopt(struct sock *sk, int pf, int val, 
+		      char __user *opt, int *len, int get)
+{
+	struct list_head *i;
+	struct nf_sockopt_ops *ops;
+	int ret;
+
+	if (down_interruptible(&nf_sockopt_mutex) != 0)
+		return -EINTR;
+
+	list_for_each(i, &nf_sockopts) {
+		ops = (struct nf_sockopt_ops *)i;
+		if (ops->pf == pf) {
+			if (get) {
+				if (val >= ops->get_optmin
+				    && val < ops->get_optmax) {
+					ops->use++;
+					up(&nf_sockopt_mutex);
+					ret = ops->get(sk, val, opt, len);
+					goto out;
+				}
+			} else {
+				if (val >= ops->set_optmin
+				    && val < ops->set_optmax) {
+					ops->use++;
+					up(&nf_sockopt_mutex);
+					ret = ops->set(sk, val, opt, *len);
+					goto out;
+				}
+			}
+		}
+	}
+	up(&nf_sockopt_mutex);
+	return -ENOPROTOOPT;
+	
+ out:
+	down(&nf_sockopt_mutex);
+	ops->use--;
+	if (ops->cleanup_task)
+		wake_up_process(ops->cleanup_task);
+	up(&nf_sockopt_mutex);
+	return ret;
+}
+
+int nf_setsockopt(struct sock *sk, int pf, int val, char __user *opt,
+		  int len)
+{
+	return nf_sockopt(sk, pf, val, opt, &len, 0);
+}
+EXPORT_SYMBOL(nf_setsockopt);
+
+int nf_getsockopt(struct sock *sk, int pf, int val, char __user *opt, int *len)
+{
+	return nf_sockopt(sk, pf, val, opt, len, 1);
+}
+EXPORT_SYMBOL(nf_getsockopt);
+

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

^ permalink raw reply

* [PATCH] move conntrack helper buffers out of BSS
From: Harald Welte @ 2005-08-07 22:39 UTC (permalink / raw)
  To: David Miller; +Cc: Linux Netdev List, Netfilter Development Mailinglist


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

Hi Dave,
I guess you will enjoy the following patch ;)
Please apply to net-2.6.14, 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: 36-conntrack_helper-nobss.patch --]
[-- Type: text/plain, Size: 3917 bytes --]

[NETFILTER] move conntrack helper buffers from BSS to kmalloc()ed memory

According to DaveM, it is preferrable to have large data structures be
allocated dynamically from the module init() function rather than putting
them as static global variables into BSS.

This patch moves the conntrack helper packet buffers into dynamically
allocated memory.

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

---
commit 6a85f7cafea91c2eea692828c7c1602d2da4f4c4
tree 66716ca9e7565377dcd42552a69189c8300f8182
parent 56ca768cb5d27e3b1929656cb186976c3b9af5ec
author Harald Welte <laforge@netfilter.org> Mo, 08 Aug 2005 00:31:23 +0200
committer Harald Welte <laforge@netfilter.org> Mo, 08 Aug 2005 00:31:23 +0200

 net/ipv4/netfilter/ip_conntrack_amanda.c |   18 ++++++++++++++++--
 net/ipv4/netfilter/ip_conntrack_ftp.c    |    9 +++++++--
 net/ipv4/netfilter/ip_conntrack_irc.c    |    7 ++++++-
 3 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -40,7 +40,7 @@ MODULE_PARM_DESC(master_timeout, "timeou
 static char *conns[] = { "DATA ", "MESG ", "INDEX " };
 
 /* This is slow, but it's simple. --RR */
-static char amanda_buffer[65536];
+static char *amanda_buffer;
 static DEFINE_SPINLOCK(amanda_buffer_lock);
 
 unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb,
@@ -153,11 +153,25 @@ static struct ip_conntrack_helper amanda
 static void __exit fini(void)
 {
 	ip_conntrack_helper_unregister(&amanda_helper);
+	kfree(amanda_buffer);
 }
 
 static int __init init(void)
 {
-	return ip_conntrack_helper_register(&amanda_helper);
+	int ret;
+
+	amanda_buffer = kmalloc(65536, GFP_KERNEL);
+	if (!amanda_buffer)
+		return -ENOMEM;
+
+	ret = ip_conntrack_helper_register(&amanda_helper);
+	if (ret < 0) {
+		kfree(amanda_buffer);
+		return ret;
+	}
+	return 0;
+
+
 }
 
 module_init(init);
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -25,8 +25,7 @@ MODULE_AUTHOR("Rusty Russell <rusty@rust
 MODULE_DESCRIPTION("ftp connection tracking helper");
 
 /* This is slow, but it's simple. --RR */
-static char ftp_buffer[65536];
-
+static char *ftp_buffer;
 static DEFINE_SPINLOCK(ip_ftp_lock);
 
 #define MAX_PORTS 8
@@ -461,6 +460,8 @@ static void fini(void)
 				ports[i]);
 		ip_conntrack_helper_unregister(&ftp[i]);
 	}
+
+	kfree(ftp_buffer);
 }
 
 static int __init init(void)
@@ -468,6 +469,10 @@ static int __init init(void)
 	int i, ret;
 	char *tmpname;
 
+	ftp_buffer = kmalloc(65536, GFP_KERNEL);
+	if (!ftp_buffer)
+		return -ENOMEM;
+
 	if (ports_c == 0)
 		ports[ports_c++] = FTP_PORT;
 
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -39,7 +39,7 @@ static int ports_c;
 static int max_dcc_channels = 8;
 static unsigned int dcc_timeout = 300;
 /* This is slow, but it's simple. --RR */
-static char irc_buffer[65536];
+static char *irc_buffer;
 static DEFINE_SPINLOCK(irc_buffer_lock);
 
 unsigned int (*ip_nat_irc_hook)(struct sk_buff **pskb,
@@ -257,6 +257,10 @@ static int __init init(void)
 		printk("ip_conntrack_irc: dcc_timeout must be a positive integer\n");
 		return -EBUSY;
 	}
+
+	irc_buffer = kmalloc(65536, GFP_KERNEL);
+	if (!irc_buffer)
+		return -ENOMEM;
 	
 	/* If no port given, default to standard irc port */
 	if (ports_c == 0)
@@ -304,6 +308,7 @@ static void fini(void)
 		       ports[i]);
 		ip_conntrack_helper_unregister(&irc_helpers[i]);
 	}
+	kfree(irc_buffer);
 }
 
 module_init(init);

[-- 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