Netdev List
 help / color / mirror / Atom feed
* Re: [-mm PATCH][4/4] net: signed vs unsigned cleanup in net/ipv4/raw.c
From: Jesper Juhl @ 2005-06-15 21:40 UTC (permalink / raw)
  To: David S. Miller
  Cc: juhl-lkml, yoshfuji, kuznet, jmorris, ross.biro, netdev,
	linux-kernel
In-Reply-To: <20050615.142953.59469324.davem@davemloft.net>

On Wed, 15 Jun 2005, David S. Miller wrote:

> From: Jesper Juhl <juhl-lkml@dif.dk>
> Date: Wed, 15 Jun 2005 23:32:22 +0200 (CEST)
> 
> > -	if (length >= sizeof(*iph) && iph->ihl * 4 <= length) {
> > +	if (length >= sizeof(*iph) && (size_t)(iph->ihl * 4) <= length) {
> 
> Would changing the "4" into "4U" kill this warning just the same?
> 
It would.

> I think I'd prefer that.
> 
No problem. Here's a replacement patch nr. 4 : 


Signed-off-by: Jesper Juhl <juhl-lkml@dif.dk>
---

 net/ipv4/raw.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

--- linux-2.6.12-rc6-mm1/net/ipv4/raw.c.with_patch-3	2005-06-15 23:17:23.000000000 +0200
+++ linux-2.6.12-rc6-mm1/net/ipv4/raw.c	2005-06-15 23:37:11.000000000 +0200
@@ -259,7 +259,7 @@ int raw_rcv(struct sock *sk, struct sk_b
 	return 0;
 }
 
-static int raw_send_hdrinc(struct sock *sk, void *from, int length,
+static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
 			struct rtable *rt, 
 			unsigned int flags)
 {
@@ -298,7 +298,7 @@ static int raw_send_hdrinc(struct sock *
 		goto error_fault;
 
 	/* We don't modify invalid header */
-	if (length >= sizeof(*iph) && iph->ihl * 4 <= length) {
+	if (length >= sizeof(*iph) && iph->ihl * 4U <= length) {
 		if (!iph->saddr)
 			iph->saddr = rt->rt_src;
 		iph->check   = 0;

^ permalink raw reply

* Re: [-mm PATCH][4/4] net: signed vs unsigned cleanup in net/ipv4/raw.c
From: David S. Miller @ 2005-06-15 21:41 UTC (permalink / raw)
  To: juhl-lkml; +Cc: yoshfuji, kuznet, jmorris, ross.biro, netdev, linux-kernel
In-Reply-To: <Pine.LNX.4.62.0506152338450.3842@dragon.hyggekrogen.localhost>

From: Jesper Juhl <juhl-lkml@dif.dk>
Date: Wed, 15 Jun 2005 23:40:12 +0200 (CEST)

> On Wed, 15 Jun 2005, David S. Miller wrote:
> 
> > I think I'd prefer that.
> > 
> No problem. Here's a replacement patch nr. 4 : 

Thanks a lot.  All 4 patches applied to my 2.6.13-pending tree.

^ permalink raw reply

* Re: [-mm PATCH][4/4] net: signed vs unsigned cleanup in net/ipv4/raw.c
From: Jesper Juhl @ 2005-06-15 21:48 UTC (permalink / raw)
  To: David S. Miller
  Cc: yoshfuji, kuznet, jmorris, ross.biro, netdev, linux-kernel
In-Reply-To: <20050615.144116.41632938.davem@davemloft.net>

On Wed, 15 Jun 2005, David S. Miller wrote:

> From: Jesper Juhl <juhl-lkml@dif.dk>
> Date: Wed, 15 Jun 2005 23:40:12 +0200 (CEST)
> 
> > On Wed, 15 Jun 2005, David S. Miller wrote:
> > 
> > > I think I'd prefer that.
> > > 
> > No problem. Here's a replacement patch nr. 4 : 
> 
> Thanks a lot.  All 4 patches applied to my 2.6.13-pending tree.
> 
Great, thanks, 'twas a pleasure working with you :)

-- 
Jesper

^ permalink raw reply

* Re: TCP prequeue performance
From: Andi Kleen @ 2005-06-15 23:34 UTC (permalink / raw)
  To: Chase Douglas; +Cc: linux-kernel, netdev
In-Reply-To: <BED5FA3B.2A0%cndougla@purdue.edu>

Chase Douglas <cndougla@purdue.edu> writes:
>
> I then disabled the prequeue mechanism by changing net/ipv4/tcp.c:1347 of
> 2.6.11:
>
> if (tp->ucopy.task == user_recv) {
>     to
> if (0 && tp->ucopy.task == user_recv) {

You actually didn't disable it completely - it would still be filled. 
To really disable it set net.ipv4.tcp_lowlatency, that disables
even the early queueing and will process all incoming TCP in softirq context
only.

>
> The same benchmark then yielded:
>
> time ./client 10000 10000 100000 1 500000000 recv
>
> real    1m21.928s
> user    0m1.579s
> sys     0m8.330ss
>
> Note the decreases in the system and real times. These numbers are fairly
> stable through 10 consecutive benchmarks of each. If I change message sizes
> and number of connections, the difference can narrow or widen, but usually
> the non-prequeue beats the prequeue with respect to system and real time.
>
> It might be that I've just found an instance where the prequeue is slower
> than the "slow" path. I'm not quite sure why this would be. Does anyone have
> any thoughts on this?

prequeue adds latency. Its original purpose was to be able to 
do combined checksum copy to user space, but that is not very useful
anymore with modern NICs which all do hardware checksumming. 
The only purpose it has left is to batch the TCP processing
better and in particular to account it to the scheduler.

When the receiver does not process the data in time 
the delayed ack timer takes over and processes the data.

Now the way you disabled it is interesting. The data would
be still queued, but in user process would be never emptied.

This means data is always processed later in the delack
timer in your hacked kernel. 

This will lead to batching of the processing (because
after upto 200ms there will be many more packet in the queues), 
and seems to save CPU time in your case.

Basically you added something similar to the the anticipatory scheduler
which adds artifical delays into disk scheduling to your TCP receiver
to get better batching. It seems to work for you. 

I think it is unlikely adding artificial processing delays like this
will help in many cases though, normally early delivery of received
data to user space should be better.

-Andi

^ permalink raw reply

* Re: TCP prequeue performance
From: David S. Miller @ 2005-06-15 23:41 UTC (permalink / raw)
  To: ak; +Cc: cndougla, linux-kernel, netdev
In-Reply-To: <m1br679otj.fsf@muc.de>

From: Andi Kleen <ak@muc.de>
Subject: Re: TCP prequeue performance
Date: Thu, 16 Jun 2005 01:34:48 +0200

> Chase Douglas <cndougla@purdue.edu> writes:
> >
> > I then disabled the prequeue mechanism by changing net/ipv4/tcp.c:1347 of
> > 2.6.11:
> >
> > if (tp->ucopy.task == user_recv) {
> >     to
> > if (0 && tp->ucopy.task == user_recv) {
> 
> You actually didn't disable it completely - it would still be filled. 

Not true, if this check does not pass, tp->ucopy.task is
never set, therefore prequeue processing is never performed.

This test must pass the first time, when both tp->ucopy.task
and user_recv are both NULL, in order for prequeue processing
to occur at all.

So his change did totally disable prequeue.

^ permalink raw reply

* Re: TCP prequeue performance
From: Andi Kleen @ 2005-06-16  0:23 UTC (permalink / raw)
  To: David S. Miller; +Cc: cndougla, linux-kernel, netdev
In-Reply-To: <20050615.164115.74747690.davem@davemloft.net>

"David S. Miller" <davem@davemloft.net> writes:
>
> Not true, if this check does not pass, tp->ucopy.task is
> never set, therefore prequeue processing is never performed.

Oh well, here goes my nice theory :)
>
> This test must pass the first time, when both tp->ucopy.task
> and user_recv are both NULL, in order for prequeue processing
> to occur at all.
>
> So his change did totally disable prequeue.

Then probably his test was latency bound somehow, but normally
that should not affect system time, just wall time.

I would perhaps compare context switch numbers and netstat -s
output between the different runs and see if anything pops out.

-Andi

^ permalink raw reply

* Re: [PATCH]: Tigon3 new NAPI locking v2
From: Herbert Xu @ 2005-06-16 11:37 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, mchan
In-Reply-To: <20050603.122558.88474819.davem@davemloft.net>

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

On Fri, Jun 03, 2005 at 07:25:58PM +0000, David S. Miller wrote:
> 
> This version incorporates two bug fixes from Michael.
> 
> 1) Check the mailbox register for 0x1 while polling on the COMPLETE
>    state bit.
> 
> 2) Remove the BUG_ON() check in tg3_restart_ints(), it can legally and
>    harmlessly occur.
> 
> Point #2 may want some refinements, but this patch below is good
> enough for testing.

Nice work Dave.

I was thinking of how we could avoid waiting for the interrupt to
occur after setting SYNC.  Here is one way which is essentially
a hand-coded spin lock.  In fact with a bit of work we could convert
it back to a real spin lock with spin_trylock.

The advantage of this is that we won't have to rely on the interrupt
to occur after setting SYNC.  The disadvantage is that on certain
architectures (sparc64 obviously :) we're now doing the relatively
expensive bit operations on each IRQ.

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

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

--- linux-2.6/drivers/net/tg3.h.orig	2005-06-16 21:10:30.000000000 +1000
+++ linux-2.6/drivers/net/tg3.h	2005-06-16 21:12:00.000000000 +1000
@@ -2009,21 +2009,22 @@
 	/* If the IRQ handler (which runs lockless) needs to be
 	 * quiesced, the following bitmask state is used.  The
 	 * SYNC bit is set by non-IRQ context code to initiate
-	 * the quiescence.  The setter of this bit also forces
-	 * an interrupt to run via the GRC misc host control
-	 * register.
-	 *
-	 * The IRQ handler notes this, disables interrupts, and
-	 * sets the COMPLETE bit.  At this point the SYNC bit
-	 * setter can be assured that interrupts will no longer
-	 * get run.
+	 * the quiescence.
+	 *
+	 * The IRQ sets the BUSY bit whenever it runs.  When it
+	 * notices that SYNC is set, it disables interrupts,
+	 * clears the BUSY bit and returns.
+	 *
+	 * When the BUSY bit is cleared after the SYNC bit has
+	 * been set, the setter can be assured that interrupts
+	 * will no longer get run.
 	 *
 	 * In this way all SMP driver locks are never acquired
 	 * in hw IRQ context, only sw IRQ context or lower.
 	 */
 	unsigned long			irq_state;
 #define TG3_IRQSTATE_SYNC		0
-#define TG3_IRQSTATE_COMPLETE		1
+#define TG3_IRQSTATE_BUSY		1
 
 	/* SMP locking strategy:
 	 *
--- linux-2.6/drivers/net/tg3.c.orig	2005-06-16 21:10:27.000000000 +1000
+++ linux-2.6/drivers/net/tg3.c	2005-06-16 21:24:54.000000000 +1000
@@ -2931,32 +2931,26 @@
 	return (done ? 0 : 1);
 }
 
-static void tg3_irq_quiesce(struct tg3 *tp)
+static inline void tg3_irq_quiesce(struct tg3 *tp)
 {
 	BUG_ON(test_bit(TG3_IRQSTATE_SYNC, &tp->irq_state));
 
 	set_bit(TG3_IRQSTATE_SYNC, &tp->irq_state);
-	smp_mb();
-	tw32(GRC_LOCAL_CTRL,
-	     tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
-
-	while (!test_bit(TG3_IRQSTATE_COMPLETE, &tp->irq_state)) {
-		u32 val = tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
-
-		if (val == 0x00000001)
-			break;
 
+	while (test_bit(TG3_IRQSTATE_BUSY, &tp->irq_state))
 		cpu_relax();
-	}
 }
 
-static inline int tg3_irq_sync(struct tg3 *tp)
+static inline int tg3_irq_enter(struct tg3 *tp)
 {
-	if (test_bit(TG3_IRQSTATE_SYNC, &tp->irq_state)) {
-		set_bit(TG3_IRQSTATE_COMPLETE, &tp->irq_state);
-		return 1;
-	}
-	return 0;
+	set_bit(TG3_IRQSTATE_BUSY, &tp->irq_state);
+	return test_bit(TG3_IRQSTATE_SYNC, &tp->irq_state);
+}
+
+static inline void tg3_irq_exit(struct tg3 *tp)
+{
+	smp_mb__before_clear_bit();
+	clear_bit(TG3_IRQSTATE_BUSY, &tp->irq_state);
 }
 
 /* Fully shutdown all tg3 driver activity elsewhere in the system.
@@ -2997,8 +2991,10 @@
 	 */
 	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
 	tp->last_tag = sblk->status_tag;
-	if (tg3_irq_sync(tp))
+
+	if (tg3_irq_enter(tp))
 		goto out;
+
 	sblk->status &= ~SD_STATUS_UPDATED;
 	if (likely(tg3_has_work(tp)))
 		netif_rx_schedule(dev);		/* schedule NAPI poll */
@@ -3007,7 +3003,10 @@
 		tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
 			     tp->last_tag << 24);
 	}
+
 out:
+	tg3_irq_exit(tp);
+
 	return IRQ_RETVAL(1);
 }
 
@@ -3034,8 +3033,10 @@
 		 */
 		tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
 			     0x00000001);
-		if (tg3_irq_sync(tp))
+
+		if (tg3_irq_enter(tp))
 			goto out;
+
 		sblk->status &= ~SD_STATUS_UPDATED;
 		if (likely(tg3_has_work(tp)))
 			netif_rx_schedule(dev);		/* schedule NAPI poll */
@@ -3047,10 +3048,13 @@
 			     	0x00000000);
 			tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
 		}
+
+out:
+		tg3_irq_exit(tp);
 	} else {	/* shared interrupt */
 		handled = 0;
 	}
-out:
+
 	return IRQ_RETVAL(handled);
 }
 
@@ -3078,8 +3082,10 @@
 		tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
 			     0x00000001);
 		tp->last_tag = sblk->status_tag;
-		if (tg3_irq_sync(tp))
+
+		if (tg3_irq_enter(tp))
 			goto out;
+
 		sblk->status &= ~SD_STATUS_UPDATED;
 		if (likely(tg3_has_work(tp)))
 			netif_rx_schedule(dev);		/* schedule NAPI poll */
@@ -3091,10 +3097,13 @@
 				     tp->last_tag << 24);
 			tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
 		}
+
+out:
+		tg3_irq_exit(tp);
 	} else {	/* shared interrupt */
 		handled = 0;
 	}
-out:
+
 	return IRQ_RETVAL(handled);
 }
 

^ permalink raw reply

* Re: [PATCH]: Tigon3 new NAPI locking v2
From: Herbert Xu @ 2005-06-16 11:59 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, mchan
In-Reply-To: <20050616113732.GA22367@gondor.apana.org.au>

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

On Thu, Jun 16, 2005 at 09:37:32PM +1000, herbert wrote:
> 
> The advantage of this is that we won't have to rely on the interrupt
> to occur after setting SYNC.  The disadvantage is that on certain
> architectures (sparc64 obviously :) we're now doing the relatively
> expensive bit operations on each IRQ.

Actually, why don't we utilise the existing synchronize_irq mechanism?
Here is what we could do.
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

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

--- linux-2.6/drivers/net/tg3.h.orig	2005-06-16 21:52:01.000000000 +1000
+++ linux-2.6/drivers/net/tg3.h	2005-06-16 21:58:02.000000000 +1000
@@ -2008,22 +2008,20 @@
 
 	/* If the IRQ handler (which runs lockless) needs to be
 	 * quiesced, the following bitmask state is used.  The
-	 * SYNC bit is set by non-IRQ context code to initiate
-	 * the quiescence.  The setter of this bit also forces
-	 * an interrupt to run via the GRC misc host control
-	 * register.
-	 *
-	 * The IRQ handler notes this, disables interrupts, and
-	 * sets the COMPLETE bit.  At this point the SYNC bit
-	 * setter can be assured that interrupts will no longer
-	 * get run.
+	 * SYNC flag is set by non-IRQ context code to initiate
+	 * the quiescence.
+	 *
+	 * When the IRQ handler notices that SYNC is set, it
+	 * disables interrupts and returns.
+	 *
+	 * When all outstanding IRQ handlers have returned after
+	 * the SYNC flag has been set, the setter can be assured
+	 * that interrupts will no longer get run.
 	 *
 	 * In this way all SMP driver locks are never acquired
 	 * in hw IRQ context, only sw IRQ context or lower.
 	 */
-	unsigned long			irq_state;
-#define TG3_IRQSTATE_SYNC		0
-#define TG3_IRQSTATE_COMPLETE		1
+	unsigned int			irq_sync;
 
 	/* SMP locking strategy:
 	 *
--- linux-2.6/drivers/net/tg3.c.orig	2005-06-16 21:52:04.000000000 +1000
+++ linux-2.6/drivers/net/tg3.c	2005-06-16 21:58:36.000000000 +1000
@@ -435,7 +435,7 @@
 	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
 		     (tp->last_tag << 24));
 	tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
-	tp->irq_state = 0;
+	tp->irq_sync = 0;
 	tg3_cond_int(tp);
 }
 
@@ -2931,32 +2931,18 @@
 	return (done ? 0 : 1);
 }
 
-static void tg3_irq_quiesce(struct tg3 *tp)
+static inline void tg3_irq_quiesce(struct tg3 *tp)
 {
-	BUG_ON(test_bit(TG3_IRQSTATE_SYNC, &tp->irq_state));
+	BUG_ON(tp->irq_sync);
 
-	set_bit(TG3_IRQSTATE_SYNC, &tp->irq_state);
-	smp_mb();
-	tw32(GRC_LOCAL_CTRL,
-	     tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+	tp->irq_sync = 1;
 
-	while (!test_bit(TG3_IRQSTATE_COMPLETE, &tp->irq_state)) {
-		u32 val = tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
-
-		if (val == 0x00000001)
-			break;
-
-		cpu_relax();
-	}
+	synchronize_irq(tp->pdev->irq);
 }
 
 static inline int tg3_irq_sync(struct tg3 *tp)
 {
-	if (test_bit(TG3_IRQSTATE_SYNC, &tp->irq_state)) {
-		set_bit(TG3_IRQSTATE_COMPLETE, &tp->irq_state);
-		return 1;
-	}
-	return 0;
+	return tp->irq_sync;
 }
 
 /* Fully shutdown all tg3 driver activity elsewhere in the system.

^ permalink raw reply

* Re: [PATCH]: Tigon3 new NAPI locking v2
From: Herbert Xu @ 2005-06-16 13:04 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, mchan
In-Reply-To: <20050616115945.GA23064@gondor.apana.org.au>

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

On Thu, Jun 16, 2005 at 09:59:45PM +1000, herbert wrote:
> 
> Actually, why don't we utilise the existing synchronize_irq mechanism?
> Here is what we could do.

Oops, I should've left the smp_mb() in tg3_irq_quiesce since
synchronize_irq isn't a memory barrier.
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

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

--- linux-2.6/drivers/net/tg3.h.orig	2005-06-16 21:52:01.000000000 +1000
+++ linux-2.6/drivers/net/tg3.h	2005-06-16 21:58:02.000000000 +1000
@@ -2008,22 +2008,20 @@
 
 	/* If the IRQ handler (which runs lockless) needs to be
 	 * quiesced, the following bitmask state is used.  The
-	 * SYNC bit is set by non-IRQ context code to initiate
-	 * the quiescence.  The setter of this bit also forces
-	 * an interrupt to run via the GRC misc host control
-	 * register.
-	 *
-	 * The IRQ handler notes this, disables interrupts, and
-	 * sets the COMPLETE bit.  At this point the SYNC bit
-	 * setter can be assured that interrupts will no longer
-	 * get run.
+	 * SYNC flag is set by non-IRQ context code to initiate
+	 * the quiescence.
+	 *
+	 * When the IRQ handler notices that SYNC is set, it
+	 * disables interrupts and returns.
+	 *
+	 * When all outstanding IRQ handlers have returned after
+	 * the SYNC flag has been set, the setter can be assured
+	 * that interrupts will no longer get run.
 	 *
 	 * In this way all SMP driver locks are never acquired
 	 * in hw IRQ context, only sw IRQ context or lower.
 	 */
-	unsigned long			irq_state;
-#define TG3_IRQSTATE_SYNC		0
-#define TG3_IRQSTATE_COMPLETE		1
+	unsigned int			irq_sync;
 
 	/* SMP locking strategy:
 	 *
--- linux-2.6/drivers/net/tg3.c.orig	2005-06-16 21:52:04.000000000 +1000
+++ linux-2.6/drivers/net/tg3.c	2005-06-16 23:02:22.000000000 +1000
@@ -435,7 +435,7 @@
 	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
 		     (tp->last_tag << 24));
 	tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
-	tp->irq_state = 0;
+	tp->irq_sync = 0;
 	tg3_cond_int(tp);
 }
 
@@ -2933,30 +2933,17 @@
 
 static void tg3_irq_quiesce(struct tg3 *tp)
 {
-	BUG_ON(test_bit(TG3_IRQSTATE_SYNC, &tp->irq_state));
+	BUG_ON(tp->irq_sync);
 
-	set_bit(TG3_IRQSTATE_SYNC, &tp->irq_state);
+	tp->irq_sync = 1;
 	smp_mb();
-	tw32(GRC_LOCAL_CTRL,
-	     tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
 
-	while (!test_bit(TG3_IRQSTATE_COMPLETE, &tp->irq_state)) {
-		u32 val = tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
-
-		if (val == 0x00000001)
-			break;
-
-		cpu_relax();
-	}
+	synchronize_irq(tp->pdev->irq);
 }
 
 static inline int tg3_irq_sync(struct tg3 *tp)
 {
-	if (test_bit(TG3_IRQSTATE_SYNC, &tp->irq_state)) {
-		set_bit(TG3_IRQSTATE_COMPLETE, &tp->irq_state);
-		return 1;
-	}
-	return 0;
+	return tp->irq_sync;
 }
 
 /* Fully shutdown all tg3 driver activity elsewhere in the system.

^ permalink raw reply

* [PATCH] sk98lin: fix ethtool stats
From: Stephen Hemminger @ 2005-06-16 18:01 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev

The ethtool stats code in the sk98lin driver doesn't correctly match
stats with names. Also it always reports stats for port 0, and doesn't
update stats before reporting.

This patch fixes that and adds statistics for the number
of pause frames sent/received.

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>

Index: work/drivers/net/sk98lin/skethtool.c
===================================================================
--- work.orig/drivers/net/sk98lin/skethtool.c
+++ work/drivers/net/sk98lin/skethtool.c
@@ -268,6 +268,7 @@ static const char StringsStats[][ETH_GST
 	"rx_bytes",	"tx_bytes",
 	"rx_errors",	"tx_errors",	
 	"rx_dropped",	"tx_dropped",
+	"rx_pause",	"tx_pause",
 	"multicasts",	"collisions",	
 	"rx_length_errors",		"rx_buffer_overflow_errors",
 	"rx_crc_errors",		"rx_frame_errors",
@@ -297,37 +298,49 @@ static void getStrings(struct net_device
 static void getEthtoolStats(struct net_device *dev,
 			    struct ethtool_stats *stats, u64 *data)
 {
-	const DEV_NET	*pNet = netdev_priv(dev);
-	const SK_AC *pAC = pNet->pAC;
-	const SK_PNMI_STRUCT_DATA *pPnmiStruct = &pAC->PnmiStruct;
-
-	*data++ = pPnmiStruct->Stat[0].StatRxOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxOctetsOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxOctetsOkCts;
-	*data++ = pPnmiStruct->InErrorsCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
-	*data++ = pPnmiStruct->RxNoBufCts;
-	*data++ = pPnmiStruct->TxNoBufCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxMulticastOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxRuntCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxFifoOverflowCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxFcsCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxFramingCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxShortsCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxTooLongCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxCextCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxSymbolCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxIRLengthCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxCarrierCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxJabberCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxMissedCts;
-	*data++ = pAC->stats.tx_aborted_errors;
-	*data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxFifoUnderrunCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
-	*data++ = pAC->stats.tx_window_errors;
+	DEV_NET	*pNet = netdev_priv(dev);
+	SK_AC *pAC = pNet->pAC;
+	SK_PNMI_STRUCT_DATA *pPnmiStruct = &pAC->PnmiStruct;
+	u32 size = sizeof(*pPnmiStruct);
+	int port = pNet->NetNr;
+	int i = 0;
+
+	if (netif_running(dev))
+		SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, 
+				&size, port);
+
+	i = 0;
+	data[i++] = pPnmiStruct->Stat[port].StatRxOkCts;
+	data[i++] = pPnmiStruct->Stat[port].StatTxOkCts;
+	data[i++] = pPnmiStruct->Stat[port].StatRxOctetsOkCts;
+	data[i++] = pPnmiStruct->Stat[port].StatTxOctetsOkCts;
+	data[i++] = pPnmiStruct->InErrorsCts;
+	data[i++] = pPnmiStruct->OutErrorsCts;
+	data[i++] = pPnmiStruct->RxNoBufCts;
+	data[i++] = pPnmiStruct->TxNoBufCts;
+	data[i++] = pPnmiStruct->Stat[port].StatRxPauseMacCtrlCts;
+	data[i++] = pPnmiStruct->Stat[port].StatTxPauseMacCtrlCts;
+	data[i++] = pPnmiStruct->Stat[port].StatRxMulticastOkCts;
+	data[i++] = pPnmiStruct->Stat[port].StatTxSingleCollisionCts;
+	data[i++] = pPnmiStruct->Stat[port].StatRxRuntCts;
+	data[i++] = pPnmiStruct->Stat[port].StatRxFifoOverflowCts;
+	data[i++] = pPnmiStruct->Stat[port].StatRxFcsCts;
+	data[i++] = pPnmiStruct->Stat[port].StatRxFramingCts;
+	data[i++] = pPnmiStruct->Stat[port].StatRxShortsCts;
+	data[i++] = pPnmiStruct->Stat[port].StatRxTooLongCts;
+	data[i++] = pPnmiStruct->Stat[port].StatRxCextCts;
+	data[i++] = pPnmiStruct->Stat[port].StatRxSymbolCts;
+	data[i++] = pPnmiStruct->Stat[port].StatRxIRLengthCts;
+	data[i++] = pPnmiStruct->Stat[port].StatRxCarrierCts;
+	data[i++] = pPnmiStruct->Stat[port].StatRxJabberCts;
+	data[i++] = pPnmiStruct->Stat[port].StatRxMissedCts;
+	data[i++] = pAC->stats.tx_aborted_errors;
+	data[i++] = pPnmiStruct->Stat[port].StatTxCarrierCts;
+	data[i++] = pPnmiStruct->Stat[port].StatTxFifoUnderrunCts;
+	data[i++] = pPnmiStruct->Stat[port].StatTxCarrierCts;
+	data[i++] = pAC->stats.tx_window_errors;
+	
+	BUG_ON(i != ARRAY_SIZE(StringsStats));
 }
 
 

^ permalink raw reply

* Re: [PATCH]: Tigon3 new NAPI locking v2
From: David S. Miller @ 2005-06-16 20:04 UTC (permalink / raw)
  To: herbert; +Cc: netdev, mchan
In-Reply-To: <20050616130453.GA23682@gondor.apana.org.au>

From: Herbert Xu <herbert@gondor.apana.org.au>
Subject: Re: [PATCH]: Tigon3 new NAPI locking v2
Date: Thu, 16 Jun 2005 23:04:53 +1000

> On Thu, Jun 16, 2005 at 09:59:45PM +1000, herbert wrote:
> > 
> > Actually, why don't we utilise the existing synchronize_irq mechanism?
> > Here is what we could do.
> 
> Oops, I should've left the smp_mb() in tg3_irq_quiesce since
> synchronize_irq isn't a memory barrier.

Wow, that's a very cool idea.  :-)

In fact, I think it will eliminate some (but definitely not all) of
the races that the new locking code has.

When you posted the patch with the atomic bitop added to the interrupt
handler, I was going to tell you that the whole idea was to make it
near zero cost to the interrupt fast path. :)

^ permalink raw reply

* Re: [PATCH] uninitialized variable in prism54 isl38xx_trigger_device
From: Luis R. Rodriguez @ 2005-06-16 23:52 UTC (permalink / raw)
  To: Olaf Hering; +Cc: Jeff Garzik, netdev, prism54-private
In-Reply-To: <20050525231651.GA21816@suse.de>

Sure, why not. This has been applied to prism54 svn tree.

On 5/25/05, Olaf Hering <olh@suse.de> wrote:
> 
> drivers/net/wireless/prism54/isl_38xx.c:131: warning: 'current_time.tv_sec' is used uninitialized in this function
> drivers/net/wireless/prism54/isl_38xx.c:131: warning: 'current_time.tv_usec' is used uninitialized in this function
> 
> Signed-off-by: Olaf Hering <olh@suse.de>
> Index: linux-2.6.12-rc5-olh/drivers/net/wireless/prism54/isl_38xx.c
> ===================================================================
> --- linux-2.6.12-rc5-olh.orig/drivers/net/wireless/prism54/isl_38xx.c
> +++ linux-2.6.12-rc5-olh/drivers/net/wireless/prism54/isl_38xx.c
> @@ -112,10 +112,10 @@ isl38xx_handle_wakeup(isl38xx_control_bl
>  void
>  isl38xx_trigger_device(int asleep, void __iomem *device_base)
>  {
> -       struct timeval current_time;
>         u32 reg, counter = 0;
> 
>  #if VERBOSE > SHOW_ERROR_MESSAGES
> +       struct timeval current_time;
>         DEBUG(SHOW_FUNCTION_CALLS, "isl38xx trigger device\n");
>  #endif
> 
> @@ -126,11 +126,11 @@ isl38xx_trigger_device(int asleep, void
>                 do_gettimeofday(&current_time);
>                 DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n",
>                       current_time.tv_sec, (long)current_time.tv_usec);
> -#endif
> 
>                 DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n",
>                       current_time.tv_sec, (long)current_time.tv_usec,
>                       readl(device_base + ISL38XX_CTRL_STAT_REG));
> +#endif
>                 udelay(ISL38XX_WRITEIO_DELAY);
> 
>                 reg = readl(device_base + ISL38XX_INT_IDENT_REG);
> @@ -148,10 +148,12 @@ isl38xx_trigger_device(int asleep, void
>                                 counter++;
>                         }
> 
> +#if VERBOSE > SHOW_ERROR_MESSAGES
>                         DEBUG(SHOW_TRACING,
>                               "%08li.%08li Device register read %08x\n",
>                               current_time.tv_sec, (long)current_time.tv_usec,
>                               readl(device_base + ISL38XX_CTRL_STAT_REG));
> +#endif
>                         udelay(ISL38XX_WRITEIO_DELAY);
> 
>  #if VERBOSE > SHOW_ERROR_MESSAGES
>

^ permalink raw reply

* QoS and pcmcia cards (Ver: 2.6.9-1)
From: Aidan P. Doyle @ 2005-06-16 23:56 UTC (permalink / raw)
  To: linux-net; +Cc: netdev

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

I've rebuilt my 2.6.9-1 kernel to support QoS/fair queueing, but if I leave my
pcmcia network cards in (one Demartek 802.11, one Socketcom ethernet), I get a
kernel oops listed below for both cards).  If remove them the node reboots fine
but as soon as either card is inserted the oops happens.  Is QoS broken for
pcmcia cards in 2.6.9-1 and is there a recent fix or is something else causing
the problem?  I need QoS for the 802.11 card so leaving it out is not an
option.

[My .config files is attached]

Thanks for any feedback.

Sincerely,
Aidan Doyle

uname -a:
SL-158:armbin$ uname -a
Linux SL-158 2.6.9-sln1 #4 Thu Jun 16 01:11:08 PDT 2005 armv5tel armv5tel
armv5tel GNU/Linux

* QoS zImage: if pcmcia cards unplugged no oops, with either card in oops occurs

** with 802.11 card in

Kernel 2.6.9-sln1 on a armv5tel processor
Sensoria arm-linux Platform, Release ASW-SL-FW17-269-03-15-2005 03/15/05 18:35
SL-159 login: pgd = c0004000
[00000000] *pgd=00000000
Internal error: Oops: 807 [#1]
Modules linked in: hostap_cs hostap kfusd ds pxa2xx_cs pxa2xx_core pcmcia_core
ds1307 eeprom
CPU: 0
PC is at $a+0x40/0x48
LR is at 0xc01bff3c
pc : [<c011d48c>]    lr : [<c01bff3c>]    Not tainted
sp : c01bdd6c  ip : 00000013  fp : c01bdd7c
r10: 000003cf  r9 : c01bde88  r8 : c02c7c10
r7 : c3102000  r6 : 00000054  r5 : 00000000  r4 : c3c0ae00
r3 : 00000000  r2 : c01bff3c  r1 : c3519f10  r0 : 0000002a
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  Segment kernel
Control: 397F  Table: A31E8000  DAC: 0000001D
Process swapper (pid: 0, stack limit = 0xc01bc190)
Stack: (0xc01bdd6c to 0xc01be000)
dd60:                            c019f668 c01bdefc c01bdd80 bf04f2a4 c011d458
dd80: c3102000 c31026ec c01bdde0 c01bdd98 bf04fc38 c004a990 600000d3 00000003
dda0: c01bdde4 c01bddb0 00000000 00000001 c31026ec 60000053 c3770fa0 00000000
ddc0: 00000000 0000001c c01bde80 c02029b0 c01bde80 c01bde04 c01bdde4 0000001d
dde0: 00000080 c3102000 c31026ec c3770fa0 c01bde80 c0202ef0 c01bde28 c01bde08
de00: c001c74c c001c3dc 00000001 c0202ef0 0000001d c01bde80 60000013 c01bde48
de20: c01bde2c c00240c0 c001c63c c01bdeb4 f2d00000 c01bc000 bf0506e0 c01bde7c
de40: c01bde4c c001c88c c002407c c01bde84 c01bde5c c01bdeb4 f2d00000 00000400
de60: bf0506e0 60000013 ffffffff c01bdf70 c01bdee8 c3102000 c01bded0 c01bde88
de80: bf05021c c002d854 f100002b ffff92cb c31026ec c01bf268 00000000 00000001
dea0: c31026ec c0030d94 c3770fa0 00000000 00000000 0000001c c01bdf70 c02029b0
dec0: c01bdf70 c01bdef4 c01bded4 c001c580 bf04f8bc 00000000 c0209864 c01bc000
dee0: 0000000a c0209840 c02029b0 c01bdf70 c01bdf14 c01bdf00 c002d9e4 bf04ed40
df00: 00000001 c0209890 c01bdf38 c01bdf18 c002d608 c002d970 c01bdfa4 f2d00000
df20: c01bc000 c001d178 60000013 c01bdf6c c01bdf3c c001c968 c002d5b8 c01bdf7c
df40: c01bdf4c c01bdfa4 f2d00000 00000400 c001d178 60000013 ffffffff a0017474
df60: c01bdfc4 c01bdf70 c001b720 c001c84c 00000001 00600000 00200000 60000013
df80: c001d130 c01bc000 c01bf260 c0203d64 c01bef94 69052d06 a0017474 c01bdfc4
dfa0: c01bdfc8 c01bdfb8 c001d16c c001d178 60000013 ffffffff c01bdfe0 c01bdfc8
dfc0: c001d1cc c001d13c c020c33c c02249ec c0203d68 c01bdffc c01bdfe4 c00086b4
dfe0: c001d18c c00082a0 c0203d78 c02249ec 00000000 c01be000 c0008080 c00085a0
Backtrace:
[<c011d44c>] ($a+0x0/0x48) from [<bf04f2a4>] (hostap_bap_tasklet+0x570/0xaf0
[hostap_cs])
[<bf04ed34>] (hostap_bap_tasklet+0x0/0xaf0 [hostap_cs]) from [<c002d9e4>]
($a+0x80/0xc0)
[<c002d964>] ($a+0x0/0xc0) from [<c002d608>] ($a+0x5c/0xc4)
 r5 = C0209890  r4 = 00000001
[<c002d5ac>] ($a+0x0/0xc4) from [<c001c968>] ($a+0x128/0x130)
 r8 = 60000013  r7 = C001D178  r6 = C01BC000  r5 = F2D00000
 r4 = C01BDFA4
[<c001c840>] ($a+0x0/0x130) from [<c001b720>] (__irq_svc+0x20/0x60)
[<c001d130>] ($a+0x0/0x4c) from [<c001d1cc>] ($a+0x4c/0x64)
[<c001d180>] ($a+0x0/0x64) from [<c00086b4>] ($a+0x120/0x128)
 r6 = C0203D68  r5 = C02249EC  r4 = C020C33C
[<c0008594>] ($a+0x0/0x128) from [<c0008080>] (__mmap_switched+0x0/0x2c)
Code: e59f0014 e58dc000 ebfc3119 e3a03000 (e5833000)
 <0>Kernel panic - not syncing: Aiee, killing interrupt handler!
 <6>wifi0: SW TICK stuck? bits=0x2 EvStat=8081 IntEn=e018

** ethernet card

SL-159:~$ ip link show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:05:88:00:03:dd brd ff:ff:ff:ff:ff:ff
SL-159:~$ pgd = c1438000
[00000000] *pgd=a1b3b011, *pte=00000000, *ppte=00000000
Internal error: Oops: 807 [#1]
Modules linked in: pcnet_cs 8390 kfusd ds pxa2xx_cs pxa2xx_core pcmcia_core
ds1307 eeprom
CPU: 0
PC is at $a+0x40/0x48
LR is at 0xc01bff3c
pc : [<c011d48c>]    lr : [<c01bff3c>]    Not tainted
sp : c1be1de0  ip : 00000014  fp : c1be1df0
r10: c1be1e08  r9 : c68c0300  r8 : 0000004d
r7 : c18cfc00  r6 : 00000073  r5 : c18cfe20  r4 : c3d9ac20
r3 : 00000000  r2 : c01bff3c  r1 : c3519f10  r0 : 0000002c
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  Segment user
Control: 397F  Table: A1438000  DAC: 00000015
Process default.hotplug (pid: 521, stack limit = 0xc1be0190)
Stack: (0xc1be1de0 to 0xc1be2000)
1de0: c18cfc00 c1be1e3c c1be1df4 bf030764 c011d458 c18ce140 00000021 00000034
1e00: 00000001 00004c00 00774d21 c1be1e0c c1be1e0c c18cfebc 00000000 00000001
1e20: c68c0300 c18cfc00 00000001 c18cfe20 c1be1e68 c1be1e40 bf0309ac bf03057c
1e40: c18cfebc 00000000 00000000 0000001e c1be1f1c c02029b0 c1be1f1c c1be1e7c
1e60: c1be1e6c bf034688 bf03088c c3732be0 c1be1ea0 c1be1e80 c001c580 bf034680
1e80: c0202f50 0000001e c3732be0 c1be1f1c 00000000 c1be1ec4 c1be1ea4 c001c6e4
1ea0: c001c540 00000001 c0202f50 0000001f c1be1f1c a0000013 c1be1ee4 c1be1ec8
1ec0: c00240c0 c001c63c c1be1f50 f2d00000 c1be0000 c0034df4 c1be1f18 c1be1ee8
1ee0: c001c88c c002407c c18ff3c4 c1be1f0c c1be1f50 f2d00000 00000400 c0034df4
1f00: a0000013 ffffffff 4016f648 c1be1fa4 c1be1f1c c001b720 c001c84c 00000002
1f20: c1be1f78 c1be1f64 04000000 befff304 c1be1f78 00000002 000000ae c001bbe4
1f40: c1be0000 4016f648 c1be1fa4 00000000 c1be1f64 c0035340 c0034df4 a0000013
1f60: ffffffff befff584 c1be1f80 fffffff2 00000000 c003443c 00037d60 04000000
1f80: 40064f40 00000000 00000000 befff464 befff4f0 befff464 00000000 c1be1fa8
1fa0: c001ba60 c00352bc befff464 c00221a8 00000002 befff390 befff304 00000008
1fc0: befff464 befff4f0 befff464 00000002 00000002 00000000 4016f648 000a86d4
1fe0: 00000000 befff304 400ba2d8 40063e7c a0000010 00000002 000000f0 00000000
Backtrace:
[<c011d44c>] ($a+0x0/0x48) from [<bf030764>] (ei_receive+0x1f4/0x2f4 [8390])
[<bf030570>] (ei_receive+0x0/0x2f4 [8390]) from [<bf0309ac>] ($a+0x12c/0x244
[8390])
[<bf030880>] ($a+0x0/0x244 [8390]) from [<bf034688>] (ei_irq_wrapper+0x14/0x24
[pcnet_cs])
[<bf034674>] (ei_irq_wrapper+0x0/0x24 [pcnet_cs]) from [<c001c580>]
($a+0x4c/0x88)
 r4 = C3732BE0
[<c001c534>] ($a+0x0/0x88) from [<c001c6e4>] ($a+0xb4/0x154)
 r8 = 00000000  r7 = C1BE1F1C  r6 = C3732BE0  r5 = 0000001E
 r4 = C0202F50
[<c001c630>] ($a+0x0/0x154) from [<c00240c0>] ($a+0x50/0xfc)
 r8 = A0000013  r7 = C1BE1F1C  r6 = 0000001F  r5 = C0202F50
 r4 = 00000001
[<c0024070>] ($a+0x0/0xfc) from [<c001c88c>] ($a+0x4c/0x130)
 r7 = C0034DF4  r6 = C1BE0000  r5 = F2D00000  r4 = C1BE1F50
[<c001c840>] ($a+0x0/0x130) from [<c001b720>] (__irq_svc+0x20/0x60)
[<c00352b0>] (sys_rt_sigaction+0x0/0xf8) from [<c001ba60>] ($a+0x0/0x2c)
 r6 = BEFFF464  r5 = BEFFF4F0  r4 = BEFFF464
Code: e59f0014 e58dc000 ebfc3119 e3a03000 (e5833000)
 <0>Kernel panic - not syncing: Aiee, killing interrupt handler!






----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.

[-- Attachment #2: sched.config --]
[-- Type: application/octet-stream, Size: 20254 bytes --]

#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.9
# Thu Jun 16 01:05:59 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_IOMAP=y

#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y

#
# General setup
#
CONFIG_LOCALVERSION="-sln1"
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SHMEM=y
# CONFIG_TINY_SHMEM is not set

#
# Loadable module support
#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
CONFIG_KMOD=y

#
# System Type
#
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_IXP2000 is not set
# CONFIG_ARCH_L7200 is not set
CONFIG_ARCH_PXA=y
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_S3C2410 is not set
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
# CONFIG_ARCH_VERSATILE_PB is not set
# CONFIG_ARCH_IMX is not set
# CONFIG_ARCH_H720X is not set

#
# Intel PXA2xx Implementations
#
# CONFIG_ARCH_LUBBOCK is not set
# CONFIG_MACH_MAINSTONE is not set
CONFIG_MACH_SLAUSON=y
# CONFIG_ARCH_PXA_IDP is not set
CONFIG_PXA25x=y

#
# h720x Implementations
#

#
# Processor Type
#
CONFIG_CPU_32=y
CONFIG_CPU_XSCALE=y
CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
CONFIG_CPU_TLB_V4WBI=y
CONFIG_CPU_MINICACHE=y

#
# Processor Features
#
# CONFIG_ARM_THUMB is not set
CONFIG_XSCALE_PMU=y

#
# General setup
#
CONFIG_ZBOOT_ROM=y
CONFIG_ZBOOT_ROM_TEXT=0x40000
CONFIG_ZBOOT_ROM_BSS=0xa0400000
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_TABLE=y
CONFIG_CPU_FREQ_SLAUSON=m
CONFIG_CPU_FREQ_PXA=y
CONFIG_CPU_FREQ_PROC_INTF=m
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_PERFORMANCE=m
CONFIG_CPU_FREQ_GOV_POWERSAVE=m
CONFIG_CPU_FREQ_GOV_USERSPACE=y
# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
CONFIG_CPU_FREQ_24_API=y

#
# PCMCIA/CardBus support
#
CONFIG_PCMCIA=m
# CONFIG_PCMCIA_DEBUG is not set
# CONFIG_TCIC is not set
CONFIG_PCMCIA_PXA2XX=m

#
# At least one math emulation must be selected
#
# CONFIG_FPE_NWFPE is not set
# CONFIG_FPE_FASTFPE is not set
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_AOUT is not set
# CONFIG_BINFMT_MISC is not set

#
# Generic Driver Options
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=m
CONFIG_PM=y
# CONFIG_PREEMPT is not set
# CONFIG_APM is not set
# CONFIG_ARTHUR is not set
CONFIG_CMDLINE="console=ttyS0,115200"
CONFIG_LEDS=y
CONFIG_LEDS_TIMER=y
CONFIG_LEDS_CPU=y
CONFIG_ALIGNMENT_TRAP=y

#
# Parallel port support
#
# CONFIG_PARPORT is not set

#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_REDBOOT_PARTS=y
# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set

#
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set

#
# RAM/ROM/Flash chip drivers
#
CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_NOSWAP=y
# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
CONFIG_MTD_CFI_GEOMETRY=y
# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set
CONFIG_MTD_MAP_BANK_WIDTH_4=y
# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
# CONFIG_MTD_CFI_I1 is not set
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set

#
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
CONFIG_MTD_SLAUSON=y
# CONFIG_MTD_EDB7312 is not set

#
# Self-contained MTD device drivers
#
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
# CONFIG_MTD_BLKMTD is not set

#
# Disk-On-Chip Device Drivers
#
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set

#
# NAND Flash Device Drivers
#
# CONFIG_MTD_NAND is not set

#
# Plug and Play support
#

#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
CONFIG_BLK_DEV_LOOP=m
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set

#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set

#
# Networking support
#
CONFIG_NET=y

#
# Networking options
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_NETLINK_DEV=m
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
# CONFIG_IP_MULTIPLE_TABLES is not set
# CONFIG_IP_ROUTE_MULTIPATH is not set
# CONFIG_IP_ROUTE_VERBOSE is not set
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
# CONFIG_IP_PNP_BOOTP is not set
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
CONFIG_IP_MROUTE=y
# CONFIG_IP_PIMSM_V1 is not set
# CONFIG_IP_PIMSM_V2 is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_TUNNEL is not set

#
# IP: Virtual Server Configuration
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set

#
# IP: Netfilter Configuration
#
# CONFIG_IP_NF_CONNTRACK is not set
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_LIMIT=m
CONFIG_IP_NF_MATCH_IPRANGE=m
CONFIG_IP_NF_MATCH_MAC=m
CONFIG_IP_NF_MATCH_PKTTYPE=m
CONFIG_IP_NF_MATCH_MARK=m
CONFIG_IP_NF_MATCH_MULTIPORT=m
CONFIG_IP_NF_MATCH_TOS=m
CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_ECN=m
CONFIG_IP_NF_MATCH_DSCP=m
CONFIG_IP_NF_MATCH_AH_ESP=m
CONFIG_IP_NF_MATCH_LENGTH=m
CONFIG_IP_NF_MATCH_TTL=m
CONFIG_IP_NF_MATCH_TCPMSS=m
CONFIG_IP_NF_MATCH_OWNER=m
# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
# CONFIG_IP_NF_MATCH_REALM is not set
# CONFIG_IP_NF_MATCH_SCTP is not set
# CONFIG_IP_NF_MATCH_COMMENT is not set
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_IP_NF_TARGET_TCPMSS=m
CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_DSCP=m
CONFIG_IP_NF_TARGET_MARK=m
CONFIG_IP_NF_TARGET_CLASSIFY=m
# CONFIG_IP_NF_RAW is not set
# CONFIG_IP_NF_ARPTABLES is not set
# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
# CONFIG_IP_NF_COMPAT_IPFWADM is not set

#
# SCTP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
CONFIG_LLC=m
CONFIG_LLC2=m
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_HW_FLOWCONTROL is not set

#
# QoS and/or fair queueing
#
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CLK_JIFFIES=y
# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
# CONFIG_NET_SCH_CLK_CPU is not set
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=m
CONFIG_NET_SCH_HFSC=m
CONFIG_NET_SCH_PRIO=m
CONFIG_NET_SCH_RED=m
CONFIG_NET_SCH_SFQ=m
CONFIG_NET_SCH_TEQL=m
CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=m
CONFIG_NET_SCH_NETEM=m
CONFIG_NET_SCH_INGRESS=m
CONFIG_NET_QOS=y
# CONFIG_NET_ESTIMATOR is not set
CONFIG_NET_CLS=y
CONFIG_NET_CLS_TCINDEX=m
CONFIG_NET_CLS_ROUTE4=m
CONFIG_NET_CLS_ROUTE=y
CONFIG_NET_CLS_FW=m
CONFIG_NET_CLS_U32=m
CONFIG_CLS_U32_PERF=y
# CONFIG_NET_CLS_IND is not set
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
# CONFIG_NET_CLS_ACT is not set
CONFIG_NET_CLS_POLICE=y

#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
# CONFIG_ETHERTAP is not set

#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
CONFIG_SMC91X=y

#
# Ethernet (1000 Mbit)
#

#
# Ethernet (10000 Mbit)
#

#
# Token Ring devices
#

#
# Wireless LAN (non-hamradio)
#
CONFIG_NET_RADIO=y

#
# Obsolete Wireless cards support (pre-802.11)
#
# CONFIG_STRIP is not set
# CONFIG_PCMCIA_WAVELAN is not set
# CONFIG_PCMCIA_NETWAVE is not set

#
# Wireless 802.11 Frequency Hopping cards support
#
# CONFIG_PCMCIA_RAYCS is not set

#
# Wireless 802.11b ISA/PCI cards support
#
CONFIG_HERMES=m
# CONFIG_ATMEL is not set

#
# Wireless 802.11b Pcmcia/Cardbus cards support
#
CONFIG_PCMCIA_HERMES=m
# CONFIG_AIRO_CS is not set
# CONFIG_PCMCIA_WL3501 is not set
CONFIG_NET_WIRELESS=y

#
# PCMCIA network device support
#
CONFIG_NET_PCMCIA=y
CONFIG_PCMCIA_3C589=m
# CONFIG_PCMCIA_3C574 is not set
# CONFIG_PCMCIA_FMVJ18X is not set
CONFIG_PCMCIA_PCNET=m
# CONFIG_PCMCIA_NMCLAN is not set
CONFIG_PCMCIA_SMC91C92=m
# CONFIG_PCMCIA_XIRC2PS is not set
CONFIG_PCMCIA_AXNET=m

#
# Wan interfaces
#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
CONFIG_SHAPER=m
# CONFIG_NETCONSOLE is not set

#
# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
CONFIG_BLK_DEV_IDE=m

#
# Please see Documentation/ide.txt for help/info on IDE drives
#
# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_BLK_DEV_IDEDISK=m
# CONFIG_IDEDISK_MULTI_MODE is not set
CONFIG_BLK_DEV_IDECS=m
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_IDE_TASK_IOCTL is not set
# CONFIG_IDE_TASKFILE_IO is not set

#
# IDE chipset support/bugfixes
#
CONFIG_IDE_GENERIC=m
# CONFIG_IDE_ARM is not set
# CONFIG_BLK_DEV_IDEDMA is not set
# CONFIG_IDEDMA_AUTO is not set
# CONFIG_BLK_DEV_HD is not set

#
# SCSI device support
#
# CONFIG_SCSI is not set

#
# Fusion MPT device support
#

#
# IEEE 1394 (FireWire) support
#

#
# I2O device support
#

#
# ISDN subsystem
#
# CONFIG_ISDN is not set

#
# Input device support
#
CONFIG_INPUT=y

#
# Userland interfaces
#
CONFIG_INPUT_MOUSEDEV=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set

#
# Input I/O drivers
#
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
# CONFIG_SERIO is not set

#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set

#
# Character devices
#
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_SERIAL_NONSTANDARD is not set

#
# Serial drivers
#
CONFIG_SERIAL_8250=m
# CONFIG_SERIAL_8250_CS is not set
CONFIG_SERIAL_8250_NR_UARTS=16
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
# CONFIG_SERIAL_8250_DETECT_IRQ is not set
# CONFIG_SERIAL_8250_MULTIPORT is not set
# CONFIG_SERIAL_8250_RSA is not set

#
# Non-8250 serial port support
#
CONFIG_SERIAL_PXA=y
CONFIG_SERIAL_PXA_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set

#
# IPMI
#
# CONFIG_IPMI_HANDLER is not set

#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set

#
# Ftape, the floppy tape device driver
#
# CONFIG_DRM is not set

#
# PCMCIA character devices
#
# CONFIG_SYNCLINK_CS is not set
# CONFIG_RAW_DRIVER is not set

#
# I2C support
#
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y

#
# I2C Algorithms
#
# CONFIG_I2C_ALGOBIT is not set
# CONFIG_I2C_ALGOPCF is not set
# CONFIG_I2C_ALGOPCA is not set

#
# I2C Hardware Bus support
#
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_ISA is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_PCA_ISA is not set
CONFIG_I2C_PXA=y

#
# Hardware Sensors Chip support
#
CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_ADM1021 is not set
CONFIG_SENSORS_ADS1100=m
# CONFIG_SENSORS_AD7417 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM75 is not set
# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_W83781D is not set
CONFIG_SENSORS_DS1307=m
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set

#
# Other I2C Chip support
#
CONFIG_SENSORS_EEPROM=m
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set

#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set

#
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set

#
# File systems
#
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
CONFIG_EXT3_FS=m
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
CONFIG_JBD=m
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set

#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
# CONFIG_UDF_FS is not set

#
# DOS/FAT/NT Filesystems
#
CONFIG_FAT_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set

#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
CONFIG_SYSFS=y
CONFIG_DEVFS_FS=y
CONFIG_DEVFS_MOUNT=y
# CONFIG_DEVFS_DEBUG is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y

#
# Miscellaneous filesystems
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set

#
# Network File Systems
#
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set

#
# Partition Types
#
CONFIG_PARTITION_ADVANCED=y
# CONFIG_ACORN_PARTITION is not set
# CONFIG_OSF_PARTITION is not set
# CONFIG_AMIGA_PARTITION is not set
# CONFIG_ATARI_PARTITION is not set
# CONFIG_MAC_PARTITION is not set
CONFIG_MSDOS_PARTITION=y
# CONFIG_BSD_DISKLABEL is not set
# CONFIG_MINIX_SUBPARTITION is not set
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_LDM_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_EFI_PARTITION is not set

#
# Native Language Support
#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
# CONFIG_NLS_CODEPAGE_850 is not set
# CONFIG_NLS_CODEPAGE_852 is not set
# CONFIG_NLS_CODEPAGE_855 is not set
# CONFIG_NLS_CODEPAGE_857 is not set
# CONFIG_NLS_CODEPAGE_860 is not set
# CONFIG_NLS_CODEPAGE_861 is not set
# CONFIG_NLS_CODEPAGE_862 is not set
# CONFIG_NLS_CODEPAGE_863 is not set
# CONFIG_NLS_CODEPAGE_864 is not set
# CONFIG_NLS_CODEPAGE_865 is not set
# CONFIG_NLS_CODEPAGE_866 is not set
# CONFIG_NLS_CODEPAGE_869 is not set
# CONFIG_NLS_CODEPAGE_936 is not set
# CONFIG_NLS_CODEPAGE_950 is not set
# CONFIG_NLS_CODEPAGE_932 is not set
# CONFIG_NLS_CODEPAGE_949 is not set
# CONFIG_NLS_CODEPAGE_874 is not set
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
# CONFIG_NLS_ASCII is not set
# CONFIG_NLS_ISO8859_1 is not set
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
# CONFIG_NLS_ISO8859_4 is not set
# CONFIG_NLS_ISO8859_5 is not set
# CONFIG_NLS_ISO8859_6 is not set
# CONFIG_NLS_ISO8859_7 is not set
# CONFIG_NLS_ISO8859_9 is not set
# CONFIG_NLS_ISO8859_13 is not set
# CONFIG_NLS_ISO8859_14 is not set
# CONFIG_NLS_ISO8859_15 is not set
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set

#
# Profiling support
#
# CONFIG_PROFILING is not set

#
# Graphics support
#
# CONFIG_FB is not set

#
# Console display driver support
#
# CONFIG_VGA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y

#
# Sound
#
CONFIG_SOUND=m

#
# Advanced Linux Sound Architecture
#
# CONFIG_SND is not set

#
# Open Sound System
#
CONFIG_SOUND_PRIME=m
# CONFIG_SOUND_BT878 is not set
# CONFIG_SOUND_FUSION is not set
# CONFIG_SOUND_CS4281 is not set
CONFIG_SOUND_PXA_AC97=m
# CONFIG_SOUND_SONICVIBES is not set
# CONFIG_SOUND_TRIDENT is not set
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
# CONFIG_SOUND_OSS is not set
# CONFIG_SOUND_TVMIXER is not set
# CONFIG_SOUND_AD1980 is not set
# CONFIG_SOUND_WM97XX is not set

#
# Misc devices
#

#
# USB support
#

#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set

#
# MMC/SD Card support
#
CONFIG_MMC=y
# CONFIG_MMC_DEBUG is not set
CONFIG_MMC_BLOCK=y
CONFIG_MMC_PXA=y

#
# Kernel hacking
#
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_INFO is not set
CONFIG_FRAME_POINTER=y
# CONFIG_DEBUG_USER is not set

#
# Security options
#
# CONFIG_SECURITY is not set

#
# Cryptographic options
#
CONFIG_CRYPTO=y
CONFIG_CRYPTO_HMAC=y
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
# CONFIG_CRYPTO_WP512 is not set
CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_BLOWFISH=m
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
CONFIG_CRYPTO_AES=m
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
# CONFIG_CRYPTO_TEA is not set
CONFIG_CRYPTO_ARC4=m
# CONFIG_CRYPTO_KHAZAD is not set
CONFIG_CRYPTO_DEFLATE=m
# CONFIG_CRYPTO_MICHAEL_MIC is not set
CONFIG_CRYPTO_CRC32C=m
# CONFIG_CRYPTO_TEST is not set

#
# Library routines
#
# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y

^ permalink raw reply

* Re: [ipv4, e1000] multi client throughput testing
From: Jesse Brandeburg @ 2005-06-17  0:48 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, shemminger, jheffner, netdev
In-Reply-To: <20050610.171127.59653238.davem@davemloft.net>

Ick, I get to be the bearer of my own bad news.  I seem to mostly have a 
client misconfiguration problem.

David S. Miller wrote:
 > From: Jesse Brandeburg <jesse.brandeburg@intel.com>
 > Date: Fri, 10 Jun 2005 16:56:50 -0700 (Pacific Daylight Time)
 >
 >  > What did i miss?
 >
 > Thanks for all of the data Jesse.  I'll try to sift through it this
 > weekend.

Well, as it turns out I was sort of right all along, when i was thinking 
that the client's tcp windows were not being serviced quickly enough.
First, I figured out that the windows client machines have a good "out 
of the box" behavior when receiving tcp data from linux.
Second, the clients sending data to the server were maxing out their tcp 
window at 64k and did *not* have rfc1323 enabled.  After enabling 
rfc1323 and upping the max window size to 128k, each client's throughput 
went up quite a bit (there may be more headroom i didn't test yet). 
Total throughput for us in this case is around 1560Mb/s now.  I'd like 
to see it at 1700-1800 but I don't think it will do it.  We're still 
running almost entirely in interrupt mode (with NAPI enabled) at about 
7-8000 ints/s

Now I will go back and run with the netfilter enabled kernel and take a 
look again at the faster replenish/fairness patches I've been working on.

Thanks for your attention,
  Jesse

^ permalink raw reply

* [PATCH 1/2] Update: LSM-IPSec Networking Hooks
From: jaegert @ 2005-06-17 13:11 UTC (permalink / raw)
  To: jmorris, davem, herbert, netdev, chrisw; +Cc: jaegert, sergeh, latten

Hi,

Just a followup on the patch sent on 6/14.  I checked the code paths for
checking the length of the user-provided security contexts via pfkey and
xfrm_user and find that the these interfaces ensure that the length
refers only to user data.  

I am resending the patch due to a couple of minor mods -- e.g., I need
to apply one James's suggestions in a second place.

This patch subsumes the previous.  The 2/2 patch is unchanged.

Regards,
Trent.

===================================================

This patch series implements per packet access control via the
extension of the Linux Security Modules (LSM) interface by hooks in
the XFRM and pfkey subsystems that leverage IPSec security
associations to label packets.  Extensions to the SELinux LSM are
included that leverage the patch for this purpose.

This patch implements the changes necessary to the XFRM subsystem,
pfkey interface, ipv4/ipv6, and xfrm_user interface to restrict a
socket to use only authorized security associations (or no security
association) to send/receive network packets.

Patch purpose:

The patch is designed to enable access control per packets based on
the strongly authenticated IPSec security association.  Such access
controls augment the existing ones based on network interface and IP
address.  The former are very coarse-grained, and the latter can be
spoofed.  By using IPSec, the system can control access to remote
hosts based on cryptographic keys generated using the IPSec mechanism.
This enables access control on a per-machine basis or per-application
if the remote machine is running the same mechanism and trusted to
enforce the access control policy.

Patch design approach:

The overall approach is that policy (xfrm_policy) entries set by
user-level programs (e.g., setkey for ipsec-tools) are extended with a
security context that is used at policy selection time in the XFRM
subsystem to restrict the sockets that can send/receive packets via
security associations (xfrm_states) that are built from those
policies.  

A presentation available at
www.selinux-symposium.org/2005/presentations/session2/2-3-jaeger.pdf
from the SELinux symposium describes the overall approach.

Patch implementation details: 

On output, the policy retrieved (via xfrm_policy_lookup or
xfrm_sk_policy_lookup) must be authorized for the security context of
the socket and the same security context is required for resultant
security association (retrieved or negotiated via racoon in
ipsec-tools).  This is enforced in xfrm_state_find.

On input, the policy retrieved must also be authorized for the socket
(at __xfrm_policy_check), and the security context of the policy must
also match the security association being used.

The patch has virtually no impact on packets that do not use IPSec.
The existing Netfilter (outgoing) and LSM rcv_skb hooks are used as
before.

Also, if IPSec is used without security contexts, the impact is
minimal.  The LSM must allow such policies to be selected for the
combination of socket and remote machine, but subsequent IPSec
processing proceeds as in the original case.

Testing:

The pfkey interface is tested using the ipsec-tools.  ipsec-tools have
been modified (a separate ipsec-tools patch is available for version
0.5) that supports assignment of xfrm_policy entries and security
associations with security contexts via setkey and the negotiation
using the security contexts via racoon.

The xfrm_user interface is tested via ad hoc programs that set
security contexts.  These programs are also available from me, and
contain programs for setting, getting, and deleting policy for testing
this interface.  Testing of sa functions was done by tracing kernel
behavior.

---

 include/linux/pfkeyv2.h  |   13 +++
 include/linux/security.h |  119 +++++++++++++++++++++++++++++++++++
 include/linux/xfrm.h     |   36 ++++++++++
 include/net/flow.h       |    5 -
 include/net/xfrm.h       |   21 ++++++
 net/core/flow.c          |    4 -
 net/ipv4/xfrm4_policy.c  |    2 
 net/ipv6/xfrm6_policy.c  |    2 
 net/key/af_key.c         |  150
+++++++++++++++++++++++++++++++++++++++++++-
 net/xfrm/xfrm_policy.c   |   66 ++++++++++++-------
 net/xfrm/xfrm_state.c    |   16 +++-
 net/xfrm/xfrm_user.c     |  158
+++++++++++++++++++++++++++++++++++++++++++++--
 security/Kconfig         |   13 +++
 security/dummy.c         |   37 +++++++++++
 14 files changed, 599 insertions(+), 43 deletions(-)

diff -puN include/linux/pfkeyv2.h~lsm-xfrm-nethooks
include/linux/pfkeyv2.h
---
linux-2.6.12-rc6-xfrm/include/linux/pfkeyv2.h~lsm-xfrm-nethooks	2005-06-13 13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/include/linux/pfkeyv2.h	2005-06-13
13:22:59.000000000 -0400
@@ -216,6 +216,16 @@ struct sadb_x_nat_t_port {
 } __attribute__((packed));
 /* sizeof(struct sadb_x_nat_t_port) == 8 */
 
+/* Generic LSM security context */
+struct sadb_x_sec_ctx {
+	uint16_t	sadb_x_sec_len;
+	uint16_t	sadb_x_sec_exttype;
+	uint8_t		sadb_x_ctx_alg;  /* LSMs: e.g., selinux == 1 */
+	uint8_t		sadb_x_ctx_doi;
+	uint16_t	sadb_x_ctx_len;
+} __attribute__((packed));
+/* sizeof(struct sadb_sec_ctx) = 8 */
+
 /* Message types */
 #define SADB_RESERVED		0
 #define SADB_GETSPI		1
@@ -324,7 +334,8 @@ struct sadb_x_nat_t_port {
 #define SADB_X_EXT_NAT_T_SPORT		21
 #define SADB_X_EXT_NAT_T_DPORT		22
 #define SADB_X_EXT_NAT_T_OA		23
-#define SADB_EXT_MAX			23
+#define SADB_X_EXT_SEC_CTX		24
+#define SADB_EXT_MAX			24
 
 /* Identity Extension values */
 #define SADB_IDENTTYPE_RESERVED	0
diff -puN include/linux/security.h~lsm-xfrm-nethooks
include/linux/security.h
---
linux-2.6.12-rc6-xfrm/include/linux/security.h~lsm-xfrm-nethooks	2005-06-13 13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/include/linux/security.h	2005-06-13
13:22:59.000000000 -0400
@@ -58,6 +58,12 @@ struct sk_buff;
 struct sock;
 struct sockaddr;
 struct socket;
+struct flowi;
+struct dst_entry;
+struct xfrm_selector;
+struct xfrm_policy;
+struct xfrm_state;
+struct xfrm_user_sec_ctx;
 
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb);
@@ -802,6 +808,50 @@ struct swap_info_struct;
  * @sk_free_security:
  *	Deallocate security structure.
  *
+ * Security hooks for XFRM operations.
+ *
+ * @xfrm_policy_alloc_security:
+ *	@xp contains the xfrm_policy being added to Security Policy Database
+ *      used by the XFRM system.
+ *      @sec_ctx contains the security context information being
provided by
+ *      the user-level policy update program (e.g., setkey).
+ *      Allocate a security structure to the xp->selector.security
field.
+ *      The security field is initialized to NULL when the xfrm_policy
is
+ *      allocated.
+ *	Return 0 if operation was successful (memory to allocate, legal
context)
+ * @xfrm_policy_clone_security:
+ *      @old contains an existing xfrm_policy in the SPD.
+ *      @new contains a new xfrm_policy being cloned from old.
+ *      Allocate a security structure to the new->selector.security
field
+ *      that contains the information from the old->selector.security
field.
+ *	Return 0 if operation was successful (memory to allocate).
+ * @xfrm_policy_free_security:
+ *      @xp contains the xfrm_policy
+ *      Deallocate xp->selector.security.
+ * @xfrm_state_alloc_security:
+ *      @x contains the xfrm_state being added to the Security
Association
+ *      Database by the XFRM system.
+ *      @sec_ctx contains the security context information being
provided by
+ *      the user-level SA generation program (e.g., setkey or racoon).
+ *      Allocate a security structure to the x->sel.security field. 
The
+ *      security field is initialized to NULL when the xfrm_state is
+ *      allocated.
+ *	Return 0 if operation was successful (memory to allocate, legal
context).
+ * @xfrm_state_free_security:
+ *      @x contains the xfrm_state.
+ *      Deallocate x>sel.security.
+ * @xfrm_policy_lookup:
+ *      @sk contains the sock that is requesting to either send or
receive a
+ *      network communication.
+ *      @sel contains the selector that matches the communication end
points of
+ *      the network communication (source, destination, and ports).
+ *      @fl contains the flowi that indicates the communication
protocol.
+ *      @dir contains the direction of the flow (input or output).
+ *	Check permission when a sock selects a xfrm_policy for processing
+ *      XFRMs on a packet.  The hook is called when selecting either a
+ *      per-socket policy or a generic xfrm policy.
+ *	Return 0 if permission is granted.
+ *
  * Security hooks affecting all System V IPC operations.
  *
  * @ipc_permission:
@@ -1243,6 +1293,15 @@ struct security_operations {
 	int (*sk_alloc_security) (struct sock *sk, int family, int priority);
 	void (*sk_free_security) (struct sock *sk);
 #endif	/* CONFIG_SECURITY_NETWORK */
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+	int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp, struct
xfrm_user_sec_ctx *sec_ctx);
+	int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct
xfrm_policy *new);
+	void (*xfrm_policy_free_security) (struct xfrm_policy *xp);
+	int (*xfrm_state_alloc_security) (struct xfrm_state *x, struct
xfrm_user_sec_ctx *sec_ctx);
+	void (*xfrm_state_free_security) (struct xfrm_state *x);
+	int (*xfrm_policy_lookup)(struct sock *sk, struct xfrm_selector *sel,
struct flowi *fl, u8 dir);
+#endif	/* CONFIG_SECURITY_NETWORK_XFRM */
 };
 
 /* global variables */
@@ -2854,5 +2913,65 @@ static inline void security_sk_free(stru
 }
 #endif	/* CONFIG_SECURITY_NETWORK */
 
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp,
struct xfrm_user_sec_ctx *sec_ctx)
+{
+        return security_ops->xfrm_policy_alloc_security(xp, sec_ctx);
+}
+
+static inline int security_xfrm_policy_clone(struct xfrm_policy *old,
struct xfrm_policy *new)
+{
+        return security_ops->xfrm_policy_clone_security(old, new);
+}
+
+static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
+{
+        security_ops->xfrm_policy_free_security(xp);
+}
+
+static inline int security_xfrm_state_alloc(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx)
+{
+        return security_ops->xfrm_state_alloc_security(x, sec_ctx);
+}
+
+static inline void security_xfrm_state_free(struct xfrm_state *x)
+{
+        security_ops->xfrm_state_free_security(x);
+}
+
+static inline int security_xfrm_policy_lookup(struct sock *sk, struct
xfrm_selector *sel, struct flowi *fl, u8 dir)
+{
+        return security_ops->xfrm_policy_lookup(sk, sel, fl, dir);
+}
+#else	/* CONFIG_SECURITY_NETWORK_XFRM */
+static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp,
struct xfrm_user_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static inline int security_xfrm_policy_clone(struct xfrm_policy *old,
struct xfrm_policy *new)
+{
+        return 0;
+}
+
+static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
+{
+}
+
+static inline int security_xfrm_state_alloc(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static inline void security_xfrm_state_free(struct xfrm_state *x)
+{
+}
+
+static inline int security_xfrm_policy_lookup(struct sock *sk, struct
xfrm_selector *sel, struct flowi *fl, u8 dir)
+{
+        return 0;
+}
+#endif	/* CONFIG_SECURITY_NETWORK_XFRM */
+
 #endif /* ! __LINUX_SECURITY_H */
 
diff -puN include/linux/xfrm.h~lsm-xfrm-nethooks include/linux/xfrm.h
---
linux-2.6.12-rc6-xfrm/include/linux/xfrm.h~lsm-xfrm-nethooks	2005-06-13
13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/include/linux/xfrm.h	2005-06-13
13:22:59.000000000 -0400
@@ -27,6 +27,22 @@ struct xfrm_id
 	__u8		proto;
 };
 
+struct xfrm_sec_ctx {
+	__u8	ctx_doi;
+	__u8	ctx_alg;
+	__u16	ctx_len;
+	__u32	ctx_sid;
+	char	ctx_str[0];
+};
+
+/* Security Context Domains of Interpretation */
+#define XFRM_SC_DOI_RESERVED 0
+#define XFRM_SC_DOI_LSM 1
+
+/* Security Context Algorithms */
+#define XFRM_SC_ALG_RESERVED 0
+#define XFRM_SC_ALG_SELINUX 1
+
 /* Selector, used as selector both on policy rules (SPD) and SAs. */
 
 struct xfrm_selector
@@ -43,8 +59,15 @@ struct xfrm_selector
 	__u8	proto;
 	int	ifindex;
 	uid_t	user;
+	struct xfrm_sec_ctx *security;
 };
 
+/* All but the security field */
+static inline int xfrm_selector_base_size(void)
+{
+	return sizeof(struct xfrm_selector) - sizeof(struct xfrm_sec_ctx *);
+}
+
 #define XFRM_INF (~(__u64)0)
 
 struct xfrm_lifetime_cfg
@@ -146,6 +169,18 @@ enum {
 
 #define XFRM_NR_MSGTYPES (XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)
 
+/*
+ * Generic LSM security context for comunicating to user space
+ * NOTE: Same format as sadb_x_sec_ctx
+ */
+struct xfrm_user_sec_ctx {
+	__u16			len;
+	__u16			exttype;
+	__u8			ctx_alg;  /* LSMs: e.g., selinux == 1 */
+	__u8			ctx_doi;
+	__u16			ctx_len;
+};
+
 struct xfrm_user_tmpl {
 	struct xfrm_id		id;
 	__u16			family;
@@ -173,6 +208,7 @@ enum xfrm_attr_type_t {
 	XFRMA_ALG_CRYPT,	/* struct xfrm_algo */
 	XFRMA_ALG_COMP,		/* struct xfrm_algo */
 	XFRMA_ENCAP,		/* struct xfrm_algo + struct xfrm_encap_tmpl */
+	XFRMA_SEC_CTX,          /* struct xfrm_sec_ctx */
 	XFRMA_TMPL,		/* 1 or more struct xfrm_user_tmpl */
 	__XFRMA_MAX
 
diff -puN include/net/flow.h~lsm-xfrm-nethooks include/net/flow.h
---
linux-2.6.12-rc6-xfrm/include/net/flow.h~lsm-xfrm-nethooks	2005-06-13
13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/include/net/flow.h	2005-06-13
13:22:59.000000000 -0400
@@ -84,10 +84,11 @@ struct flowi {
 #define FLOW_DIR_OUT	1
 #define FLOW_DIR_FWD	2
 
-typedef void (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir,
+struct sock;
+typedef void (*flow_resolve_t)(struct flowi *key, struct sock *sk, u16
family, u8 dir,
 			       void **objp, atomic_t **obj_refp);
 
-extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
+extern void *flow_cache_lookup(struct flowi *key, struct sock *sk, u16
family, u8 dir,
 			       flow_resolve_t resolver);
 extern void flow_cache_flush(void);
 extern atomic_t flow_cache_genid;
diff -puN include/net/xfrm.h~lsm-xfrm-nethooks include/net/xfrm.h
---
linux-2.6.12-rc6-xfrm/include/net/xfrm.h~lsm-xfrm-nethooks	2005-06-13
13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/include/net/xfrm.h	2005-06-13
13:22:59.000000000 -0400
@@ -493,6 +493,27 @@ xfrm_selector_match(struct xfrm_selector
 	return 0;
 }
 
+/* If neither has a context --> match
+   Otherwise, both must have a context and the sids, doi, alg must
match */
+static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct
xfrm_sec_ctx *s2)
+{
+	return ((!s1 && !s2) ||
+		(s1 && s2 &&
+		 (s1->ctx_sid == s2->ctx_sid) &&
+		 (s1->ctx_doi == s2->ctx_doi) &&
+		 (s1->ctx_alg == s2->ctx_alg)));
+}
+
+static inline struct xfrm_sec_ctx *xfrm_policy_security(struct
xfrm_policy *xp)
+{
+	return (xp ? xp->selector.security : NULL);
+}
+
+static inline struct xfrm_sec_ctx *xfrm_state_security(struct
xfrm_state *x)
+{
+	return (x ? x->sel.security : NULL);
+}
+
 /* A struct encoding bundle of transformations to apply to some set of
flow.
  *
  * dst->child points to the next element of bundle.
diff -puN net/core/flow.c~lsm-xfrm-nethooks net/core/flow.c
--- linux-2.6.12-rc6-xfrm/net/core/flow.c~lsm-xfrm-nethooks	2005-06-13
13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/net/core/flow.c	2005-06-13
13:22:59.000000000 -0400
@@ -162,7 +162,7 @@ static int flow_key_compare(struct flowi
 	return 0;
 }
 
-void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
+void *flow_cache_lookup(struct flowi *key, struct sock *sk, u16 family,
u8 dir,
 			flow_resolve_t resolver)
 {
 	struct flow_cache_entry *fle, **head;
@@ -221,7 +221,7 @@ nocache:
 		void *obj;
 		atomic_t *obj_ref;
 
-		resolver(key, family, dir, &obj, &obj_ref);
+		resolver(key, sk, family, dir, &obj, &obj_ref);
 
 		if (fle) {
 			fle->genid = atomic_read(&flow_cache_genid);
diff -puN net/ipv4/xfrm4_policy.c~lsm-xfrm-nethooks
net/ipv4/xfrm4_policy.c
---
linux-2.6.12-rc6-xfrm/net/ipv4/xfrm4_policy.c~lsm-xfrm-nethooks	2005-06-13 13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/net/ipv4/xfrm4_policy.c	2005-06-13
13:22:59.000000000 -0400
@@ -36,6 +36,8 @@ __xfrm4_find_bundle(struct flowi *fl, st
 		if (xdst->u.rt.fl.oif == fl->oif &&	/*XXX*/
 		    xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
 	    	    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
+ 		    xfrm_sec_ctx_match(xfrm_policy_security(policy),
+				       xfrm_state_security(dst->xfrm)) &&
 		    xfrm_bundle_ok(xdst, fl, AF_INET)) {
 			dst_clone(dst);
 			break;
diff -puN net/ipv6/xfrm6_policy.c~lsm-xfrm-nethooks
net/ipv6/xfrm6_policy.c
---
linux-2.6.12-rc6-xfrm/net/ipv6/xfrm6_policy.c~lsm-xfrm-nethooks	2005-06-13 13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/net/ipv6/xfrm6_policy.c	2005-06-13
13:22:59.000000000 -0400
@@ -54,6 +54,8 @@ __xfrm6_find_bundle(struct flowi *fl, st
 				 xdst->u.rt6.rt6i_src.plen);
 		if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) &&
 		    ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) &&
+ 		    xfrm_sec_ctx_match(xfrm_policy_security(policy),
+ 				       xfrm_state_security(dst->xfrm)) &&
 		    xfrm_bundle_ok(xdst, fl, AF_INET6)) {
 			dst_clone(dst);
 			break;
diff -puN net/key/af_key.c~lsm-xfrm-nethooks net/key/af_key.c
--- linux-2.6.12-rc6-xfrm/net/key/af_key.c~lsm-xfrm-nethooks	2005-06-13
13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/net/key/af_key.c	2005-06-16
14:48:27.000000000 -0400
@@ -336,6 +336,7 @@ static u8 sadb_ext_min_len[] = {
 	[SADB_X_EXT_NAT_T_SPORT]	= (u8) sizeof(struct sadb_x_nat_t_port),
 	[SADB_X_EXT_NAT_T_DPORT]	= (u8) sizeof(struct sadb_x_nat_t_port),
 	[SADB_X_EXT_NAT_T_OA]		= (u8) sizeof(struct sadb_address),
+	[SADB_X_EXT_SEC_CTX]            = (u8) sizeof(struct sadb_x_sec_ctx),
 };
 
 /* Verify sadb_address_{len,prefixlen} against sa_family.  */
@@ -383,6 +384,40 @@ static int verify_address_len(void *p)
 	return 0;
 }
 
+static inline int verify_sec_ctx_len(void *p)
+{
+	struct sadb_x_sec_ctx *sec_ctx = (struct sadb_x_sec_ctx *)p;
+	int len = 0;
+
+	len += sizeof(struct sadb_x_sec_ctx);
+	len += sec_ctx->sadb_x_ctx_len;
+	len += sizeof(uint64_t) - 1;
+	len /= sizeof(uint64_t);
+
+	if (sec_ctx->sadb_x_sec_len != len)
+		return -EINVAL;
+
+	return 0;
+}
+
+static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_ctx(struct
sadb_x_sec_ctx *sec_ctx)
+{
+	struct xfrm_user_sec_ctx *uctx = NULL;
+
+	if (sec_ctx) {
+		int ctx_size = sec_ctx->sadb_x_ctx_len;
+		uctx = kmalloc((sizeof(*uctx)+ctx_size), GFP_KERNEL);
+		uctx->len = sec_ctx->sadb_x_sec_len;
+		uctx->exttype = sec_ctx->sadb_x_sec_exttype;
+		uctx->ctx_doi = sec_ctx->sadb_x_ctx_doi;
+		uctx->ctx_alg = sec_ctx->sadb_x_ctx_alg;
+		uctx->ctx_len = sec_ctx->sadb_x_ctx_len;
+		memcpy(uctx + 1, sec_ctx + 1,
+		       uctx->ctx_len);
+	}
+	return uctx;
+}
+
 static int present_and_same_family(struct sadb_address *src,
 				   struct sadb_address *dst)
 {
@@ -438,6 +473,10 @@ static int parse_exthdrs(struct sk_buff 
 				if (verify_address_len(p))
 					return -EINVAL;
 			}				
+			if (ext_type == SADB_X_EXT_SEC_CTX) {
+				if (verify_sec_ctx_len(p))
+					return -EINVAL;
+			}
 			ext_hdrs[ext_type-1] = p;
 		}
 		p   += ext_len;
@@ -586,6 +625,9 @@ static struct sk_buff * pfkey_xfrm_state
 	struct sadb_key *key;
 	struct sadb_x_sa2 *sa2;
 	struct sockaddr_in *sin;
+	struct sadb_x_sec_ctx *sec_ctx;
+	struct xfrm_sec_ctx *xfrm_ctx;
+	int ctx_size = 0;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	struct sockaddr_in6 *sin6;
 #endif
@@ -609,6 +651,12 @@ static struct sk_buff * pfkey_xfrm_state
 			sizeof(struct sadb_address)*2 + 
 				sockaddr_size*2 +
 					sizeof(struct sadb_x_sa2);
+
+	if ((xfrm_ctx = xfrm_state_security(x))) {
+		ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len);
+		size += sizeof(struct sadb_x_sec_ctx) + ctx_size;
+        }
+
 	/* identity & sensitivity */
 
 	if ((x->props.family == AF_INET &&
@@ -892,6 +940,20 @@ static struct sk_buff * pfkey_xfrm_state
 		n_port->sadb_x_nat_t_port_reserved = 0;
 	}
 
+	/* security context */
+        if (xfrm_ctx) {
+		sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb,
+				sizeof(struct sadb_x_sec_ctx) + ctx_size);
+		sec_ctx->sadb_x_sec_len =
+		  (sizeof(struct sadb_x_sec_ctx) + ctx_size) / sizeof(uint64_t);
+		sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+		sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;
+		sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;
+		sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;
+		memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,
+		       xfrm_ctx->ctx_len);
+	}
+
 	return skb;
 }
 
@@ -902,6 +964,7 @@ static struct xfrm_state * pfkey_msg2xfr
 	struct sadb_lifetime *lifetime;
 	struct sadb_sa *sa;
 	struct sadb_key *key;
+	struct sadb_x_sec_ctx *sec_ctx;
 	uint16_t proto;
 	int err;
 	
@@ -984,6 +1047,17 @@ static struct xfrm_state * pfkey_msg2xfr
 		x->lft.soft_add_expires_seconds = lifetime->sadb_lifetime_addtime;
 		x->lft.soft_use_expires_seconds = lifetime->sadb_lifetime_usetime;
 	}
+
+	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+	if (sec_ctx != NULL) {
+		struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_ctx(sec_ctx);
+
+		err = security_xfrm_state_alloc(x, uctx);
+		kfree(uctx);
+		if (err)
+			goto out;
+	}
+
 	key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
 	if (sa->sadb_sa_auth) {
 		int keysize = 0;
@@ -1634,6 +1708,18 @@ parse_ipsecrequests(struct xfrm_policy *
 	return 0;
 }
 
+static inline int pfkey_xfrm_policy2sec_ctx_size(struct xfrm_policy
*xp)
+{
+	struct xfrm_sec_ctx *xfrm_ctx = xfrm_policy_security(xp);
+
+	if (xfrm_ctx) {
+		int len = sizeof(struct sadb_x_sec_ctx);
+		len += xfrm_ctx->ctx_len;
+		return PFKEY_ALIGN8(len);
+	}
+	return 0;
+}
+
 static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp)
 {
 	int sockaddr_size = pfkey_sockaddr_size(xp->family);
@@ -1647,7 +1733,8 @@ static int pfkey_xfrm_policy2msg_size(st
 		(sockaddr_size * 2) +
 		sizeof(struct sadb_x_policy) +
 		(xp->xfrm_nr * (sizeof(struct sadb_x_ipsecrequest) +
-				(socklen * 2)));
+				(socklen * 2))) +
+		pfkey_xfrm_policy2sec_ctx_size(xp);
 }
 
 static struct sk_buff * pfkey_xfrm_policy2msg_prep(struct xfrm_policy
*xp)
@@ -1671,6 +1758,8 @@ static void pfkey_xfrm_policy2msg(struct
 	struct sadb_lifetime *lifetime;
 	struct sadb_x_policy *pol;
 	struct sockaddr_in   *sin;
+	struct sadb_x_sec_ctx *sec_ctx;
+	struct xfrm_sec_ctx *xfrm_ctx;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	struct sockaddr_in6  *sin6;
 #endif
@@ -1855,19 +1944,35 @@ static void pfkey_xfrm_policy2msg(struct
 			}
 		}
 	}
+
+	/* security context */
+        if ((xfrm_ctx = xfrm_policy_security(xp))) {
+		int ctx_size = pfkey_xfrm_policy2sec_ctx_size(xp);
+
+		sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb, ctx_size);
+		sec_ctx->sadb_x_sec_len = ctx_size / sizeof(uint64_t);
+		sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+		sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;
+		sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;
+		sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;
+		memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,
+		       xfrm_ctx->ctx_len);
+	}
+
 	hdr->sadb_msg_len = size / sizeof(uint64_t);
 	hdr->sadb_msg_reserved = atomic_read(&xp->refcnt);
 }
 
 static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct
sadb_msg *hdr, void **ext_hdrs)
 {
-	int err;
+	int err = 0;
 	struct sadb_lifetime *lifetime;
 	struct sadb_address *sa;
 	struct sadb_x_policy *pol;
 	struct xfrm_policy *xp;
 	struct sk_buff *out_skb;
 	struct sadb_msg *out_hdr;
+	struct sadb_x_sec_ctx *sec_ctx;
 
 	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -1914,6 +2019,18 @@ static int pfkey_spdadd(struct sock *sk,
 	if (xp->selector.dport)
 		xp->selector.dport_mask = ~0;
 
+	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+	if (sec_ctx != NULL) {
+		struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_ctx(sec_ctx);
+
+		err = security_xfrm_policy_alloc(xp, uctx);
+		kfree(uctx);
+		if (err) {
+			err = -EINVAL;
+			goto out;
+		}
+	}
+
 	xp->lft.soft_byte_limit = XFRM_INF;
 	xp->lft.hard_byte_limit = XFRM_INF;
 	xp->lft.soft_packet_limit = XFRM_INF;
@@ -1963,6 +2080,7 @@ static int pfkey_spdadd(struct sock *sk,
 	return 0;
 
 out:
+	security_xfrm_policy_free(xp);
 	kfree(xp);
 	return err;
 }
@@ -1972,10 +2090,11 @@ static int pfkey_spddelete(struct sock *
 	int err;
 	struct sadb_address *sa;
 	struct sadb_x_policy *pol;
-	struct xfrm_policy *xp;
+	struct xfrm_policy *xp, tmp;
 	struct sk_buff *out_skb;
 	struct sadb_msg *out_hdr;
 	struct xfrm_selector sel;
+	struct sadb_x_sec_ctx *sec_ctx;
 
 	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -2004,7 +2123,17 @@ static int pfkey_spddelete(struct sock *
 	if (sel.dport)
 		sel.dport_mask = ~0;
 
-	xp = xfrm_policy_bysel(pol->sadb_x_policy_dir-1, &sel, 1);
+	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+	memcpy(&tmp.selector, &sel, sizeof(struct xfrm_selector));
+	if (sec_ctx != NULL) {
+		err = security_xfrm_policy_alloc(
+			&tmp, (struct xfrm_user_sec_ctx *)sec_ctx);
+		if (err)
+			return err;
+	}
+
+	xp = xfrm_policy_bysel(pol->sadb_x_policy_dir-1, &tmp.selector, 1);
+	security_xfrm_policy_free(&tmp);
 	if (xp == NULL)
 		return -ENOENT;
 
@@ -2482,6 +2611,7 @@ static struct xfrm_policy *pfkey_compile
 {
 	struct xfrm_policy *xp;
 	struct sadb_x_policy *pol = (struct sadb_x_policy*)data;
+	struct sadb_x_sec_ctx *sec_ctx;
 
 	switch (family) {
 	case AF_INET:
@@ -2531,10 +2661,22 @@ static struct xfrm_policy *pfkey_compile
 	    (*dir = parse_ipsecrequests(xp, pol)) < 0)
 		goto out;
 
+	/* security context too */
+	if (len >= (pol->sadb_x_policy_len*8 +
+		    sizeof(struct sadb_x_sec_ctx))) {
+		char *p = (char *) pol;
+		p += pol->sadb_x_policy_len*8;
+		sec_ctx = (struct sadb_x_sec_ctx *) p;
+		if (security_xfrm_policy_alloc(
+			    xp, (struct xfrm_user_sec_ctx *)sec_ctx))
+			goto out;
+	}
+
 	*dir = pol->sadb_x_policy_dir-1;
 	return xp;
 
 out:
+	security_xfrm_policy_free(xp);
 	kfree(xp);
 	return NULL;
 }
diff -puN net/xfrm/xfrm_policy.c~lsm-xfrm-nethooks
net/xfrm/xfrm_policy.c
---
linux-2.6.12-rc6-xfrm/net/xfrm/xfrm_policy.c~lsm-xfrm-nethooks	2005-06-13 13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/net/xfrm/xfrm_policy.c	2005-06-13
13:22:59.000000000 -0400
@@ -10,7 +10,7 @@
  * 	YOSHIFUJI Hideaki
  * 		Split up af-specific portion
  *	Derek Atkins <derek@ihtfp.com>		Add the post_input processor
- * 	
+ *
  */
 
 #include <asm/bug.h>
@@ -257,6 +257,7 @@ void __xfrm_policy_destroy(struct xfrm_p
 	if (del_timer(&policy->timer))
 		BUG();
 
+	security_xfrm_policy_free(policy);
 	kfree(policy);
 }
 EXPORT_SYMBOL(__xfrm_policy_destroy);
@@ -396,7 +397,8 @@ struct xfrm_policy *xfrm_policy_bysel(in
 
 	write_lock_bh(&xfrm_policy_lock);
 	for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) {
-		if (memcmp(sel, &pol->selector, sizeof(*sel)) == 0) {
+		if ((memcmp(sel, &pol->selector, xfrm_selector_base_size()) == 0) &&
+		    (xfrm_sec_ctx_match(sel->security, xfrm_policy_security(pol)))) {
 			xfrm_pol_hold(pol);
 			if (delete)
 				*p = pol->next;
@@ -492,7 +494,7 @@ EXPORT_SYMBOL(xfrm_policy_walk);
 
 /* Find policy to apply to this flow. */
 
-static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
+static void xfrm_policy_lookup(struct flowi *fl, struct sock *sk, u16
family, u8 dir,
 			       void **objp, atomic_t **obj_refp)
 {
 	struct xfrm_policy *pol;
@@ -506,9 +508,12 @@ static void xfrm_policy_lookup(struct fl
 			continue;
 
 		match = xfrm_selector_match(sel, fl, family);
+
 		if (match) {
-			xfrm_pol_hold(pol);
-			break;
+ 			if (!security_xfrm_policy_lookup(sk, sel, fl, dir)) {
+				xfrm_pol_hold(pol);
+				break;
+			}
 		}
 	}
 	read_unlock_bh(&xfrm_policy_lock);
@@ -516,15 +521,38 @@ static void xfrm_policy_lookup(struct fl
 		*obj_refp = &pol->refcnt;
 }
 
+static inline int policy_to_flow_dir(int dir)
+{
+	if (XFRM_POLICY_IN == FLOW_DIR_IN &&
+ 	    XFRM_POLICY_OUT == FLOW_DIR_OUT &&
+ 	    XFRM_POLICY_FWD == FLOW_DIR_FWD)
+ 		return dir;
+ 	switch (dir) {
+ 	default:
+ 	case XFRM_POLICY_IN:
+ 		return FLOW_DIR_IN;
+ 	case XFRM_POLICY_OUT:
+ 		return FLOW_DIR_OUT;
+ 	case XFRM_POLICY_FWD:
+ 		return FLOW_DIR_FWD;
+	};
+}
+
 static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int
dir, struct flowi *fl)
 {
 	struct xfrm_policy *pol;
 
 	read_lock_bh(&xfrm_policy_lock);
 	if ((pol = sk->sk_policy[dir]) != NULL) {
-		int match = xfrm_selector_match(&pol->selector, fl,
+ 		struct xfrm_selector *sel = &pol->selector;
+ 		int match = xfrm_selector_match(sel, fl,
 						sk->sk_family);
+ 		int err = 0;
+
 		if (match)
+ 			err = security_xfrm_policy_lookup(sk, sel, fl,
policy_to_flow_dir(dir));
+
+ 		if (match && !err)
 			xfrm_pol_hold(pol);
 		else
 			pol = NULL;
@@ -595,6 +623,10 @@ static struct xfrm_policy *clone_policy(
 
 	if (newp) {
 		newp->selector = old->selector;
+		if (security_xfrm_policy_clone(old, newp)) {
+			kfree(newp);
+			return NULL;  /* ENOMEM */
+		}
 		newp->lft = old->lft;
 		newp->curlft = old->curlft;
 		newp->action = old->action;
@@ -706,22 +738,6 @@ xfrm_bundle_create(struct xfrm_policy *p
 	return err;
 }
 
-static inline int policy_to_flow_dir(int dir)
-{
-	if (XFRM_POLICY_IN == FLOW_DIR_IN &&
-	    XFRM_POLICY_OUT == FLOW_DIR_OUT &&
-	    XFRM_POLICY_FWD == FLOW_DIR_FWD)
-		return dir;
-	switch (dir) {
-	default:
-	case XFRM_POLICY_IN:
-		return FLOW_DIR_IN;
-	case XFRM_POLICY_OUT:
-		return FLOW_DIR_OUT;
-	case XFRM_POLICY_FWD:
-		return FLOW_DIR_FWD;
-	};
-}
 
 static int stale_bundle(struct dst_entry *dst);
 
@@ -751,7 +767,7 @@ restart:
 		if ((dst_orig->flags & DST_NOXFRM) ||
!xfrm_policy_list[XFRM_POLICY_OUT])
 			return 0;
 
-		policy = flow_cache_lookup(fl, family,
+		policy = flow_cache_lookup(fl, sk, family,
 					   policy_to_flow_dir(XFRM_POLICY_OUT),
 					   xfrm_policy_lookup);
 	}
@@ -942,7 +958,7 @@ int __xfrm_policy_check(struct sock *sk,
 		int i;
 
 		for (i=skb->sp->len-1; i>=0; i--) {
-		  struct sec_decap_state *xvec = &(skb->sp->x[i]);
+			struct sec_decap_state *xvec = &(skb->sp->x[i]);
 			if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family))
 				return 0;
 
@@ -960,7 +976,7 @@ int __xfrm_policy_check(struct sock *sk,
 		pol = xfrm_sk_policy_lookup(sk, dir, &fl);
 
 	if (!pol)
-		pol = flow_cache_lookup(&fl, family,
+		pol = flow_cache_lookup(&fl, sk, family,
 					policy_to_flow_dir(dir),
 					xfrm_policy_lookup);
 
diff -puN net/xfrm/xfrm_state.c~lsm-xfrm-nethooks net/xfrm/xfrm_state.c
---
linux-2.6.12-rc6-xfrm/net/xfrm/xfrm_state.c~lsm-xfrm-nethooks	2005-06-13
13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/net/xfrm/xfrm_state.c	2005-06-13
13:22:59.000000000 -0400
@@ -10,7 +10,7 @@
  * 		Split up af-specific functions
  *	Derek Atkins <derek@ihtfp.com>
  *		Add UDP Encapsulation
- * 	
+ *
  */
 
 #include <linux/workqueue.h>
@@ -74,6 +74,7 @@ static void xfrm_state_gc_destroy(struct
 		x->type->destructor(x);
 		xfrm_put_type(x->type);
 	}
+	security_xfrm_state_free(x);
 	kfree(x);
 }
 
@@ -338,7 +339,8 @@ xfrm_state_find(xfrm_address_t *daddr, x
 			      selector.
 			 */
 			if (x->km.state == XFRM_STATE_VALID) {
-				if (!xfrm_selector_match(&x->sel, fl, family))
+				if (!xfrm_selector_match(&x->sel, fl, family) ||
+				    !xfrm_sec_ctx_match(xfrm_policy_security(pol),
xfrm_state_security(x)))
 					continue;
 				if (!best ||
 				    best->km.dying > x->km.dying ||
@@ -349,7 +351,8 @@ xfrm_state_find(xfrm_address_t *daddr, x
 				acquire_in_progress = 1;
 			} else if (x->km.state == XFRM_STATE_ERROR ||
 				   x->km.state == XFRM_STATE_EXPIRED) {
-				if (xfrm_selector_match(&x->sel, fl, family))
+ 				if (xfrm_selector_match(&x->sel, fl, family) &&
+				    xfrm_sec_ctx_match(xfrm_policy_security(pol),
xfrm_state_security(x)))
 					error = -ESRCH;
 			}
 		}
@@ -374,6 +377,13 @@ xfrm_state_find(xfrm_address_t *daddr, x
 		xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
 
 		if (km_query(x, tmpl, pol) == 0) {
+			if (!xfrm_sec_ctx_match(xfrm_policy_security(pol),
xfrm_state_security(x))) {
+				x->km.state = XFRM_STATE_DEAD;
+				xfrm_state_put(x);
+				x = NULL;
+				error = -EPERM;
+				goto out;
+			}
 			x->km.state = XFRM_STATE_ACQ;
 			list_add_tail(&x->bydst, xfrm_state_bydst+h);
 			xfrm_state_hold(x);
diff -puN net/xfrm/xfrm_user.c~lsm-xfrm-nethooks net/xfrm/xfrm_user.c
---
linux-2.6.12-rc6-xfrm/net/xfrm/xfrm_user.c~lsm-xfrm-nethooks	2005-06-13
13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/net/xfrm/xfrm_user.c	2005-06-16
14:39:56.000000000 -0400
@@ -7,7 +7,7 @@
  * 	Kazunori MIYAZAWA @USAGI
  * 	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
  * 		IPv6 support
- * 	
+ *
  */
 
 #include <linux/module.h>
@@ -209,6 +209,30 @@ static int attach_encap_tmpl(struct xfrm
 	return 0;
 }
 
+
+static inline int xfrm_user_sec_ctx_size(struct xfrm_policy *xp)
+{
+	struct xfrm_sec_ctx *xfrm_ctx = xfrm_policy_security(xp);
+	int len = 0;
+
+	if (xfrm_ctx) {
+		len += sizeof(struct xfrm_user_sec_ctx);
+		len += xfrm_ctx->ctx_len;
+	}
+	return len;
+}
+
+static int attach_sec_ctx(struct xfrm_state *x, struct rtattr *u_arg)
+{
+	struct xfrm_user_sec_ctx *uxsc = RTA_DATA(u_arg);
+
+	if (uxsc) {
+		return security_xfrm_state_alloc(x, uxsc);
+	}
+
+	return 0;
+}
+
 static void copy_from_user_state(struct xfrm_state *x, struct
xfrm_usersa_info *p)
 {
 	memcpy(&x->id, &p->id, sizeof(x->id));
@@ -258,6 +282,9 @@ static struct xfrm_state *xfrm_state_con
 	if (err)
 		goto error;
 
+	if ((err = attach_sec_ctx(x, xfrma[XFRMA_SEC_CTX-1])))
+		goto error;
+
 	x->curlft.add_time = (unsigned long) xtime.tv_sec;
 	x->km.state = XFRM_STATE_VALID;
 	x->km.seq = p->seq;
@@ -344,6 +371,27 @@ struct xfrm_dump_info {
 	int this_idx;
 };
 
+static int dump_one_sec_ctx(struct xfrm_sec_ctx *ctx, struct
xfrm_user_sec_ctx *uctx, struct sk_buff *skb, int ctx_size)
+{
+	if (!ctx)
+		return -1;
+
+	uctx->exttype = XFRMA_SEC_CTX;
+	uctx->len = ctx_size;
+	uctx->ctx_doi = ctx->ctx_doi;
+	uctx->ctx_alg = ctx->ctx_alg;
+	uctx->ctx_len = ctx->ctx_len;
+
+	memcpy(uctx + 1, ctx->ctx_str, ctx->ctx_len);
+
+	RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size, uctx);
+
+	return 0;
+
+rtattr_failure:
+	return -1;
+}
+
 static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
 {
 	struct xfrm_dump_info *sp = ptr;
@@ -352,6 +400,7 @@ static int dump_one_state(struct xfrm_st
 	struct xfrm_usersa_info *p;
 	struct nlmsghdr *nlh;
 	unsigned char *b = skb->tail;
+	struct xfrm_sec_ctx *xfrm_ctx;
 
 	if (sp->this_idx < sp->start_idx)
 		goto out;
@@ -376,6 +425,18 @@ static int dump_one_state(struct xfrm_st
 	if (x->encap)
 		RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
 
+	if ((xfrm_ctx = xfrm_state_security(x))) {
+		int ctx_size = sizeof(struct xfrm_user_sec_ctx) +
+			xfrm_ctx->ctx_len + 1;
+		struct xfrm_user_sec_ctx *uctx = kmalloc(ctx_size, GFP_KERNEL);
+		int err;
+
+	        err = dump_one_sec_ctx(xfrm_ctx, uctx, skb, ctx_size);
+		kfree(uctx);
+
+		if (err < 0)
+			goto rtattr_failure;
+	}
 	nlh->nlmsg_len = skb->tail - b;
 out:
 	sp->this_idx++;
@@ -589,6 +650,25 @@ static int verify_newpolicy_info(struct 
 	return verify_policy_dir(p->dir);
 }
 
+static int copy_sec_ctx(struct xfrm_policy *pol, struct
xfrm_user_sec_ctx *uctx)
+{
+	int err = 0;
+
+	if (uctx) {
+		err = security_xfrm_policy_alloc(pol, uctx);
+	}
+
+	return err;
+}
+
+static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct
rtattr **xfrma)
+{
+	struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1];
+	struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt);
+
+	return copy_sec_ctx(pol, uctx);
+}
+
 static void copy_templates(struct xfrm_policy *xp, struct
xfrm_user_tmpl *ut,
 			   int nr)
 {
@@ -667,7 +747,10 @@ static struct xfrm_policy *xfrm_policy_c
 	}
 
 	copy_from_user_policy(xp, p);
-	err = copy_from_user_tmpl(xp, xfrma);
+
+	if (!(err = copy_from_user_tmpl(xp, xfrma)))
+		err = copy_from_user_sec_ctx(xp, xfrma);
+
 	if (err) {
 		*errp = err;
 		kfree(xp);
@@ -737,6 +820,27 @@ rtattr_failure:
 	return -1;
 }
 
+static int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff
*skb, int src)
+{
+	int err = 0;
+	struct xfrm_sec_ctx *xfrm_ctx = xfrm_policy_security(xp);
+
+	if (xfrm_ctx) {
+		int ctx_size = sizeof(struct xfrm_user_sec_ctx) +
+			xfrm_ctx->ctx_len;
+		struct xfrm_user_sec_ctx *uctx = kmalloc(ctx_size, GFP_KERNEL);
+
+		if (!uctx)
+			return -ENOMEM;
+
+	        err = dump_one_sec_ctx(xfrm_ctx, uctx, skb,
+				       ctx_size);
+		kfree(uctx);
+	}
+
+	return err;
+}
+
 static int dump_one_policy(struct xfrm_policy *xp, int dir, int count,
void *ptr)
 {
 	struct xfrm_dump_info *sp = ptr;
@@ -758,6 +862,8 @@ static int dump_one_policy(struct xfrm_p
 	copy_to_user_policy(xp, p, dir);
 	if (copy_to_user_tmpl(xp, skb) < 0)
 		goto nlmsg_failure;
+	if (copy_to_user_sec_ctx(xp, skb, 0) < 0)
+		goto nlmsg_failure;
 
 	nlh->nlmsg_len = skb->tail - b;
 out:
@@ -813,7 +919,7 @@ static struct sk_buff *xfrm_policy_netli
 
 static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
void **xfrma)
 {
-	struct xfrm_policy *xp;
+	struct xfrm_policy *xp, tmp;
 	struct xfrm_userpolicy_id *p;
 	int err;
 	int delete;
@@ -827,8 +933,20 @@ static int xfrm_get_policy(struct sk_buf
 
 	if (p->index)
 		xp = xfrm_policy_byid(p->dir, p->index, delete);
-	else
-		xp = xfrm_policy_bysel(p->dir, &p->sel, delete);
+	else {
+		struct rtattr **rtattrs = (struct rtattr **) xfrma;
+		struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1];
+
+		memcpy(&tmp.selector, &p->sel, sizeof(struct xfrm_selector));
+		if (rt) {
+			struct xfrm_user_sec_ctx *uxsc = RTA_DATA(rt);
+
+			if ((err = security_xfrm_policy_alloc(&tmp, uxsc)))
+				return err;
+		}
+		xp = xfrm_policy_bysel(p->dir, &tmp.selector, delete);
+		security_xfrm_policy_free(&tmp);
+	}
 	if (xp == NULL)
 		return -ENOENT;
 
@@ -1110,6 +1228,8 @@ static int build_acquire(struct sk_buff 
 
 	if (copy_to_user_tmpl(xp, skb) < 0)
 		goto nlmsg_failure;
+	if (copy_to_user_sec_ctx(xp, skb, 1) < 0)
+		goto nlmsg_failure;
 
 	nlh->nlmsg_len = skb->tail - b;
 	return skb->len;
@@ -1127,6 +1247,7 @@ static int xfrm_send_acquire(struct xfrm
 
 	len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
 	len += NLMSG_SPACE(sizeof(struct xfrm_user_acquire));
+	len += RTA_SPACE(xfrm_user_sec_ctx_size(xp));
 	skb = alloc_skb(len, GFP_ATOMIC);
 	if (skb == NULL)
 		return -ENOMEM;
@@ -1147,8 +1268,9 @@ static struct xfrm_policy *xfrm_compile_
 {
 	struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data;
 	struct xfrm_user_tmpl *ut = (struct xfrm_user_tmpl *) (p + 1);
+	struct xfrm_user_sec_ctx *uctx;
 	struct xfrm_policy *xp;
-	int nr;
+	int nr = 0;
 
 	switch (family) {
 	case AF_INET:
@@ -1176,9 +1298,26 @@ static struct xfrm_policy *xfrm_compile_
 	    verify_newpolicy_info(p))
 		return NULL;
 
+ 	if (len > (sizeof(*p) + (XFRM_MAX_DEPTH *
+				 sizeof(struct xfrm_user_tmpl)))) {
+ 		struct xfrm_user_tmpl *tmpl;
+ 		uctx = (struct xfrm_user_sec_ctx *) (ut + XFRM_MAX_DEPTH);
+
+ 		if (len != sizeof(*p) +
+		    (XFRM_MAX_DEPTH * sizeof(struct xfrm_user_tmpl)) +
+		    uctx->len)
+ 			return NULL;
+
+		/* spi must be zero'd unless real tmpl */
+		for (tmpl = ut; tmpl->id.spi != 0; tmpl = tmpl + 1)
+ 			nr++;
+ 	}
+	else {
+		uctx = NULL;
 	nr = ((len - sizeof(*p)) / sizeof(*ut));
 	if (nr > XFRM_MAX_DEPTH)
 		return NULL;
+	}
 
 	xp = xfrm_policy_alloc(GFP_KERNEL);
 	if (xp == NULL) {
@@ -1188,6 +1327,10 @@ static struct xfrm_policy *xfrm_compile_
 
 	copy_from_user_policy(xp, p);
 	copy_templates(xp, ut, nr);
+	if (copy_sec_ctx(xp, uctx)) {
+		*dir = -EPERM;
+		return NULL;
+	}
 
 	*dir = p->dir;
 
@@ -1208,6 +1351,8 @@ static int build_polexpire(struct sk_buf
 	copy_to_user_policy(xp, &upe->pol, dir);
 	if (copy_to_user_tmpl(xp, skb) < 0)
 		goto nlmsg_failure;
+	if (copy_to_user_sec_ctx(xp, skb, 2) < 0)
+		goto nlmsg_failure;
 	upe->hard = !!hard;
 
 	nlh->nlmsg_len = skb->tail - b;
@@ -1225,6 +1370,7 @@ static int xfrm_send_policy_notify(struc
 
 	len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
 	len += NLMSG_SPACE(sizeof(struct xfrm_user_polexpire));
+	len += xfrm_user_sec_ctx_size(xp);
 	skb = alloc_skb(len, GFP_ATOMIC);
 	if (skb == NULL)
 		return -ENOMEM;
diff -puN security/dummy.c~lsm-xfrm-nethooks security/dummy.c
--- linux-2.6.12-rc6-xfrm/security/dummy.c~lsm-xfrm-nethooks	2005-06-13
13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/security/dummy.c	2005-06-13
13:22:59.000000000 -0400
@@ -811,6 +811,35 @@ static inline void dummy_sk_free_securit
 }
 #endif	/* CONFIG_SECURITY_NETWORK */
 
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp,
struct xfrm_user_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static inline int dummy_xfrm_policy_clone_security(struct xfrm_policy
*old, struct xfrm_policy *new)
+{
+        return 0;
+}
+
+static void dummy_xfrm_policy_free_security(struct xfrm_policy *xp)
+{
+}
+
+static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, struct
xfrm_user_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static void dummy_xfrm_state_free_security(struct xfrm_state *x)
+{
+}
+
+static int dummy_xfrm_policy_lookup(struct sock *sk, struct
xfrm_selector *sel, struct flowi *fl, u8 dir)
+{
+        return 0;
+}
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
 static int dummy_register_security (const char *name, struct
security_operations *ops)
 {
 	return -EINVAL;
@@ -992,5 +1021,13 @@ void security_fixup_ops (struct security
 	set_to_dummy_if_null(ops, sk_alloc_security);
 	set_to_dummy_if_null(ops, sk_free_security);
 #endif	/* CONFIG_SECURITY_NETWORK */
+#ifdef  CONFIG_SECURITY_NETWORK_XFRM
+	set_to_dummy_if_null(ops, xfrm_policy_alloc_security);
+	set_to_dummy_if_null(ops, xfrm_policy_clone_security);
+	set_to_dummy_if_null(ops, xfrm_policy_free_security);
+	set_to_dummy_if_null(ops, xfrm_state_alloc_security);
+	set_to_dummy_if_null(ops, xfrm_state_free_security);
+	set_to_dummy_if_null(ops, xfrm_policy_lookup);
+#endif	/* CONFIG_SECURITY_NETWORK_XFRM */
 }
 
diff -puN security/Kconfig~lsm-xfrm-nethooks security/Kconfig
--- linux-2.6.12-rc6-xfrm/security/Kconfig~lsm-xfrm-nethooks	2005-06-13
13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/security/Kconfig	2005-06-13
13:22:59.000000000 -0400
@@ -53,6 +53,19 @@ config SECURITY_NETWORK
 	  implement socket and networking access controls.
 	  If you are unsure how to answer this question, answer N.
 
+config SECURITY_NETWORK_XFRM
+	bool "XFRM (IPSec) Networking Security Hooks"
+	depends on XFRM && SECURITY_NETWORK
+	help
+	  This enables the XFRM (IPSec) networking security hooks.
+	  If enabled, a security module can use these hooks to
+	  implement per-packet access controls based on labels
+	  derived from IPSec policy.  Non-IPSec communications are
+	  designated as unlabelled, and only sockets authorized
+	  to communicate unlabelled data can send without using
+	  IPSec.
+	  If you are unsure how to answer this question, answer N.
+
 config SECURITY_CAPABILITIES
 	tristate "Default Linux Capabilities"
 	depends on SECURITY
_

^ permalink raw reply

* receive only one record from the routing table
From: Tomáš Macek @ 2005-06-17 13:51 UTC (permalink / raw)
  To: netdev

Hi, I have this program (see below), and I want him to find a certain route record in the kernel routing table. I copied this somewhere from the internet and add the NetlinkAddAttr() function, that should add an request on the destination address. But the program prints always the WHOLE routing table.

But I would like to have a program, that would RECEIVE only one route from the kernel routing table for certain destination address only. Is it possible to do in rtnetlink?
I wasn't able to find the answer on google and my tries all failed.

Any help will be very appreciated!

Tomas


==================================================================================

#include <asm/types.h>
#include <netinet/ether.h>
#include <netinet/in.h>
#include <net/if.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/types.h>

#define BUFSIZE 8192

struct route_info {
     u_int dstAddr;
     u_int dstMask;
     u_int srcAddr;
     u_int gateWay;
     char ifName[IF_NAMESIZE];
};

int NetlinkAddAttr(struct nlmsghdr *n, int maxlen, int type, void *data, int alen) {
         int len = RTA_LENGTH(alen);
         struct rtattr *rta;

         if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
                 return -1;
         rta = (struct rtattr *)(((char *)n) + NLMSG_ALIGN(n->nlmsg_len));
         rta->rta_type = type;
         rta->rta_len = len;
         memcpy(RTA_DATA(rta), data, alen);
         n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
         return 0;
}

int readNlSock(int sockFd, char *bufPtr, int seqNum, int pId) {
     struct nlmsghdr *nlHdr;
     int readLen = 0, msgLen = 0;

     do {
         /* Recieve response from the kernel */
         if((readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0){
             perror("SOCK READ: ");
             return -1;
         }
         nlHdr = (struct nlmsghdr *)bufPtr;

         /* Check if the header is valid */
         if((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR)) {
             perror("Error in recieved packet");
             return -1;
         }

         /* Check if the its the last message */
         if(nlHdr->nlmsg_type == NLMSG_DONE){
             break;
         } else{
             /* Else move the pointer to buffer appropriately */
             bufPtr += readLen;
             msgLen += readLen;
         }

         /* Check if its a multi part message */
         if((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0){
             /* return if its not */
             break;
         }
     } while((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId));

     return msgLen;
}

unsigned long netmask_from_bitcount(unsigned int bits) {
     return 0xffffffff << (32 - bits);
}

/* For printing the routes. */
void printRoute(struct route_info *rtInfo) {
     char tempBuf[512];

     /* Print Destination address */
     if(rtInfo->dstAddr != 0)
         strcpy(tempBuf, (char *)inet_ntoa(rtInfo->dstAddr));
     else
         sprintf(tempBuf,"*.*.*.*\t\t");
     fprintf(stdout,"%s\t\t", tempBuf);

     /* Print Gateway address */
     if(rtInfo->gateWay != 0)
         strcpy(tempBuf, (char *)inet_ntoa(rtInfo->gateWay));
     else
         sprintf(tempBuf,"*.*.*.*\t\t");
     fprintf(stdout,"%s\t\t", tempBuf);

     /* Print Interface Name*/
     fprintf(stdout,"%s\t\t", rtInfo->ifName);

     /* Print Source address */
     if (rtInfo->srcAddr != 0)
         strcpy(tempBuf, (char *)inet_ntoa(rtInfo->srcAddr));
     else
         sprintf(tempBuf,"*.*.*.*\t\t");

     if (rtInfo->dstMask != 0) {
         struct in_addr ia;
         ia.s_addr = htonl(netmask_from_bitcount(rtInfo->dstMask));
         sprintf(tempBuf, "%s\t", inet_ntoa(ia));
     } else {
         sprintf(tempBuf, "0.0.0.0\t");
     }

     fprintf(stdout,"%s\n", tempBuf);
}

void parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo, char *find) {
     struct rtmsg *rtMsg;
     struct rtattr *rtAttr;
     int rtLen;
     char *tempBuf = NULL;
     struct in_addr ai;

     if (!inet_aton(find, &ai)) {
         return;
     }

     tempBuf = (char *)malloc(100);
     rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr);

     /* If the route is not for AF_INET or does not belong to main routing table
     then return. */
     if((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN))
         return;

     /* get the rtattr field */
     rtAttr = (struct rtattr *)RTM_RTA(rtMsg);
     rtLen = RTM_PAYLOAD(nlHdr);

     rtInfo->dstMask = rtMsg->rtm_dst_len; /* Netmask */

     for( ; RTA_OK(rtAttr,rtLen);rtAttr = RTA_NEXT(rtAttr,rtLen)) {
         switch(rtAttr->rta_type){
             case RTA_OIF:
                 if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName);
                 break;
             case RTA_GATEWAY:
                 rtInfo->gateWay = *(u_int *)RTA_DATA(rtAttr);
                 break;
             case RTA_PREFSRC:
                 rtInfo->srcAddr = *(u_int *)RTA_DATA(rtAttr);
                 break;
             case RTA_DST:
                 rtInfo->dstAddr = *(u_int *)RTA_DATA(rtAttr);
                 break;
         }
     }

/*
     if (rtInfo->dstAddr == ai.s_addr) {
         printf("match %s\n", inet_ntoa(rtInfo->dstAddr));
         return;
     }
*/
     printRoute(rtInfo);

     free(tempBuf);
     return;
}

int main(int argc, char *argv[]) {
     struct nlmsghdr *nlMsg;
     struct rtmsg *rtMsg;
     struct route_info *rtInfo;
     char msgBuf[BUFSIZE];

     int sock, len, msgSeq = 0;
     char buff[1024];

     /* Create Socket */
     if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0)
         perror("Socket Creation: ");

     /* Initialize the buffer */
     memset(msgBuf, 0, BUFSIZE);

     /* point the header and the msg structure pointers into the buffer */
     nlMsg = (struct nlmsghdr *)msgBuf;
     rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg);

     /* Fill in the nlmsg header*/
     nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
     nlMsg->nlmsg_type = RTM_GETROUTE;   // Get the routes from kernel routing table .

     nlMsg->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;   // The message is a request for dump.
     nlMsg->nlmsg_seq = msgSeq++;   // Sequence of the message packet.
     nlMsg->nlmsg_pid = getpid();   // PID of process sending the request.

     char *cp;
     unsigned int xx[4]; int i = 0;
     unsigned char *ap = (unsigned char *)xx;
     for (cp = argv[1], i = 0; *cp; cp++) {
         if (*cp <= '9' && *cp >= '0') {
             ap[i] = 10*ap[i] + (*cp-'0');
             continue;
         }
         if (*cp == '.' && ++i <= 3)
             continue;
         return -1;
     }

     NetlinkAddAttr(nlMsg, sizeof(nlMsg), RTA_DST, &xx, 4);

     /* Send the request */
     if(send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0){
         printf("Write To Socket Failed...\n");
         return -1;
     }

     /* Read the response */
     if((len = readNlSock(sock, msgBuf, msgSeq, getpid())) < 0) {
         printf("Read From Socket Failed...\n");
         return -1;
     }

/* Parse and print the response */
     rtInfo = (struct route_info *)malloc(sizeof(struct route_info));
     fprintf(stdout, "Destination\t\tGateway\t\tInterface\t\tSource\t\tNetmask\n");

     for( ; NLMSG_OK(nlMsg,len); nlMsg = NLMSG_NEXT(nlMsg,len)) {
         memset(rtInfo, 0, sizeof(struct route_info));
         parseRoutes(nlMsg, rtInfo, argv[1]);
     }

     free(rtInfo);
     close(sock);
     return 0;
}

^ permalink raw reply

* [PATCH 1/2] Resend (Update): LSM-IPSec Networking Hooks
From: jaegert @ 2005-06-17 14:13 UTC (permalink / raw)
  To: netdev, chrisw

Resend of patch update of this morning.  The formatting of the email
was incorrect for a patch.  I apologize for the oversight.

Regards,
Trent.

=============================================================
This patch series implements per packet access control via the
extension of the Linux Security Modules (LSM) interface by hooks in
the XFRM and pfkey subsystems that leverage IPSec security
associations to label packets.  Extensions to the SELinux LSM are
included that leverage the patch for this purpose.

This patch implements the changes necessary to the XFRM subsystem,
pfkey interface, ipv4/ipv6, and xfrm_user interface to restrict a
socket to use only authorized security associations (or no security
association) to send/receive network packets.

Patch purpose:

The patch is designed to enable access control per packets based on
the strongly authenticated IPSec security association.  Such access
controls augment the existing ones based on network interface and IP
address.  The former are very coarse-grained, and the latter can be
spoofed.  By using IPSec, the system can control access to remote
hosts based on cryptographic keys generated using the IPSec mechanism.
This enables access control on a per-machine basis or per-application
if the remote machine is running the same mechanism and trusted to
enforce the access control policy.

Patch design approach:

The overall approach is that policy (xfrm_policy) entries set by
user-level programs (e.g., setkey for ipsec-tools) are extended with a
security context that is used at policy selection time in the XFRM
subsystem to restrict the sockets that can send/receive packets via
security associations (xfrm_states) that are built from those
policies.  

A presentation available at
www.selinux-symposium.org/2005/presentations/session2/2-3-jaeger.pdf
from the SELinux symposium describes the overall approach.

Patch implementation details: 

On output, the policy retrieved (via xfrm_policy_lookup or
xfrm_sk_policy_lookup) must be authorized for the security context of
the socket and the same security context is required for resultant
security association (retrieved or negotiated via racoon in
ipsec-tools).  This is enforced in xfrm_state_find.

On input, the policy retrieved must also be authorized for the socket
(at __xfrm_policy_check), and the security context of the policy must
also match the security association being used.

The patch has virtually no impact on packets that do not use IPSec.
The existing Netfilter (outgoing) and LSM rcv_skb hooks are used as
before.

Also, if IPSec is used without security contexts, the impact is
minimal.  The LSM must allow such policies to be selected for the
combination of socket and remote machine, but subsequent IPSec
processing proceeds as in the original case.

Testing:

The pfkey interface is tested using the ipsec-tools.  ipsec-tools have
been modified (a separate ipsec-tools patch is available for version
0.5) that supports assignment of xfrm_policy entries and security
associations with security contexts via setkey and the negotiation
using the security contexts via racoon.

The xfrm_user interface is tested via ad hoc programs that set
security contexts.  These programs are also available from me, and
contain programs for setting, getting, and deleting policy for testing
this interface.  Testing of sa functions was done by tracing kernel
behavior.

---

 include/linux/pfkeyv2.h  |   13 +++
 include/linux/security.h |  119 +++++++++++++++++++++++++++++++++++
 include/linux/xfrm.h     |   36 ++++++++++
 include/net/flow.h       |    5 -
 include/net/xfrm.h       |   21 ++++++
 net/core/flow.c          |    4 -
 net/ipv4/xfrm4_policy.c  |    2 
 net/ipv6/xfrm6_policy.c  |    2 
 net/key/af_key.c         |  150
+++++++++++++++++++++++++++++++++++++++++++-
 net/xfrm/xfrm_policy.c   |   66 ++++++++++++-------
 net/xfrm/xfrm_state.c    |   16 +++-
 net/xfrm/xfrm_user.c     |  158
+++++++++++++++++++++++++++++++++++++++++++++--
 security/Kconfig         |   13 +++
 security/dummy.c         |   37 +++++++++++
 14 files changed, 599 insertions(+), 43 deletions(-)

diff -puN include/linux/pfkeyv2.h~lsm-xfrm-nethooks
include/linux/pfkeyv2.h
---
linux-2.6.12-rc6-xfrm/include/linux/pfkeyv2.h~lsm-xfrm-nethooks     2005-06-13 13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/include/linux/pfkeyv2.h  2005-06-13
13:22:59.000000000 -0400
@@ -216,6 +216,16 @@ struct sadb_x_nat_t_port {
 } __attribute__((packed));
 /* sizeof(struct sadb_x_nat_t_port) == 8 */
 
+/* Generic LSM security context */
+struct sadb_x_sec_ctx {
+       uint16_t        sadb_x_sec_len;
+       uint16_t        sadb_x_sec_exttype;
+       uint8_t         sadb_x_ctx_alg;  /* LSMs: e.g., selinux == 1 */
+       uint8_t         sadb_x_ctx_doi;
+       uint16_t        sadb_x_ctx_len;
+} __attribute__((packed));
+/* sizeof(struct sadb_sec_ctx) = 8 */
+
 /* Message types */
 #define SADB_RESERVED          0
 #define SADB_GETSPI            1
@@ -324,7 +334,8 @@ struct sadb_x_nat_t_port {
 #define SADB_X_EXT_NAT_T_SPORT         21
 #define SADB_X_EXT_NAT_T_DPORT         22
 #define SADB_X_EXT_NAT_T_OA            23
-#define SADB_EXT_MAX                   23
+#define SADB_X_EXT_SEC_CTX             24
+#define SADB_EXT_MAX                   24
 
 /* Identity Extension values */
 #define SADB_IDENTTYPE_RESERVED        0
diff -puN include/linux/security.h~lsm-xfrm-nethooks
include/linux/security.h
---
linux-2.6.12-rc6-xfrm/include/linux/security.h~lsm-xfrm-nethooks    2005-06-13 13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/include/linux/security.h 2005-06-13
13:22:59.000000000 -0400
@@ -58,6 +58,12 @@ struct sk_buff;
 struct sock;
 struct sockaddr;
 struct socket;
+struct flowi;
+struct dst_entry;
+struct xfrm_selector;
+struct xfrm_policy;
+struct xfrm_state;
+struct xfrm_user_sec_ctx;
 
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb);
@@ -802,6 +808,50 @@ struct swap_info_struct;
  * @sk_free_security:
  *     Deallocate security structure.
  *
+ * Security hooks for XFRM operations.
+ *
+ * @xfrm_policy_alloc_security:
+ *     @xp contains the xfrm_policy being added to Security Policy
Database
+ *      used by the XFRM system.
+ *      @sec_ctx contains the security context information being
provided by
+ *      the user-level policy update program (e.g., setkey).
+ *      Allocate a security structure to the xp->selector.security
field.
+ *      The security field is initialized to NULL when the xfrm_policy
is
+ *      allocated.
+ *     Return 0 if operation was successful (memory to allocate, legal
context)
+ * @xfrm_policy_clone_security:
+ *      @old contains an existing xfrm_policy in the SPD.
+ *      @new contains a new xfrm_policy being cloned from old.
+ *      Allocate a security structure to the new->selector.security
field
+ *      that contains the information from the old->selector.security
field.
+ *     Return 0 if operation was successful (memory to allocate).
+ * @xfrm_policy_free_security:
+ *      @xp contains the xfrm_policy
+ *      Deallocate xp->selector.security.
+ * @xfrm_state_alloc_security:
+ *      @x contains the xfrm_state being added to the Security
Association
+ *      Database by the XFRM system.
+ *      @sec_ctx contains the security context information being
provided by
+ *      the user-level SA generation program (e.g., setkey or racoon).
+ *      Allocate a security structure to the x->sel.security field. 
The
+ *      security field is initialized to NULL when the xfrm_state is
+ *      allocated.
+ *     Return 0 if operation was successful (memory to allocate, legal
context).
+ * @xfrm_state_free_security:
+ *      @x contains the xfrm_state.
+ *      Deallocate x>sel.security.
+ * @xfrm_policy_lookup:
+ *      @sk contains the sock that is requesting to either send or
receive a
+ *      network communication.
+ *      @sel contains the selector that matches the communication end
points of
+ *      the network communication (source, destination, and ports).
+ *      @fl contains the flowi that indicates the communication
protocol.
+ *      @dir contains the direction of the flow (input or output).
+ *     Check permission when a sock selects a xfrm_policy for
processing
+ *      XFRMs on a packet.  The hook is called when selecting either a
+ *      per-socket policy or a generic xfrm policy.
+ *     Return 0 if permission is granted.
+ *
  * Security hooks affecting all System V IPC operations.
  *
  * @ipc_permission:
@@ -1243,6 +1293,15 @@ struct security_operations {
        int (*sk_alloc_security) (struct sock *sk, int family, int
priority);
        void (*sk_free_security) (struct sock *sk);
 #endif /* CONFIG_SECURITY_NETWORK */
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+       int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp,
struct xfrm_user_sec_ctx *sec_ctx);
+       int (*xfrm_policy_clone_security) (struct xfrm_policy *old,
struct xfrm_policy *new);
+       void (*xfrm_policy_free_security) (struct xfrm_policy *xp);
+       int (*xfrm_state_alloc_security) (struct xfrm_state *x, struct
xfrm_user_sec_ctx *sec_ctx);
+       void (*xfrm_state_free_security) (struct xfrm_state *x);
+       int (*xfrm_policy_lookup)(struct sock *sk, struct xfrm_selector
*sel, struct flowi *fl, u8 dir);
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
 };
 
 /* global variables */
@@ -2854,5 +2913,65 @@ static inline void security_sk_free(stru
 }
 #endif /* CONFIG_SECURITY_NETWORK */
 
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp,
struct xfrm_user_sec_ctx *sec_ctx)
+{
+        return security_ops->xfrm_policy_alloc_security(xp, sec_ctx);
+}
+
+static inline int security_xfrm_policy_clone(struct xfrm_policy *old,
struct xfrm_policy *new)
+{
+        return security_ops->xfrm_policy_clone_security(old, new);
+}
+
+static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
+{
+        security_ops->xfrm_policy_free_security(xp);
+}
+
+static inline int security_xfrm_state_alloc(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx)
+{
+        return security_ops->xfrm_state_alloc_security(x, sec_ctx);
+}
+
+static inline void security_xfrm_state_free(struct xfrm_state *x)
+{
+        security_ops->xfrm_state_free_security(x);
+}
+
+static inline int security_xfrm_policy_lookup(struct sock *sk, struct
xfrm_selector *sel, struct flowi *fl, u8 dir)
+{
+        return security_ops->xfrm_policy_lookup(sk, sel, fl, dir);
+}
+#else  /* CONFIG_SECURITY_NETWORK_XFRM */
+static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp,
struct xfrm_user_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static inline int security_xfrm_policy_clone(struct xfrm_policy *old,
struct xfrm_policy *new)
+{
+        return 0;
+}
+
+static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
+{
+}
+
+static inline int security_xfrm_state_alloc(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static inline void security_xfrm_state_free(struct xfrm_state *x)
+{
+}
+
+static inline int security_xfrm_policy_lookup(struct sock *sk, struct
xfrm_selector *sel, struct flowi *fl, u8 dir)
+{
+        return 0;
+}
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
+
 #endif /* ! __LINUX_SECURITY_H */
 
diff -puN include/linux/xfrm.h~lsm-xfrm-nethooks include/linux/xfrm.h
---
linux-2.6.12-rc6-xfrm/include/linux/xfrm.h~lsm-xfrm-nethooks        2005-06-13 13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/include/linux/xfrm.h     2005-06-13
13:22:59.000000000 -0400
@@ -27,6 +27,22 @@ struct xfrm_id
        __u8            proto;
 };
 
+struct xfrm_sec_ctx {
+       __u8    ctx_doi;
+       __u8    ctx_alg;
+       __u16   ctx_len;
+       __u32   ctx_sid;
+       char    ctx_str[0];
+};
+
+/* Security Context Domains of Interpretation */
+#define XFRM_SC_DOI_RESERVED 0
+#define XFRM_SC_DOI_LSM 1
+
+/* Security Context Algorithms */
+#define XFRM_SC_ALG_RESERVED 0
+#define XFRM_SC_ALG_SELINUX 1
+
 /* Selector, used as selector both on policy rules (SPD) and SAs. */
 
 struct xfrm_selector
@@ -43,8 +59,15 @@ struct xfrm_selector
        __u8    proto;
        int     ifindex;
        uid_t   user;
+       struct xfrm_sec_ctx *security;
 };
 
+/* All but the security field */
+static inline int xfrm_selector_base_size(void)
+{
+       return sizeof(struct xfrm_selector) - sizeof(struct xfrm_sec_ctx
*);
+}
+
 #define XFRM_INF (~(__u64)0)
 
 struct xfrm_lifetime_cfg
@@ -146,6 +169,18 @@ enum {
 
 #define XFRM_NR_MSGTYPES (XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)
 
+/*
+ * Generic LSM security context for comunicating to user space
+ * NOTE: Same format as sadb_x_sec_ctx
+ */
+struct xfrm_user_sec_ctx {
+       __u16                   len;
+       __u16                   exttype;
+       __u8                    ctx_alg;  /* LSMs: e.g., selinux == 1 */
+       __u8                    ctx_doi;
+       __u16                   ctx_len;
+};
+
 struct xfrm_user_tmpl {
        struct xfrm_id          id;
        __u16                   family;
@@ -173,6 +208,7 @@ enum xfrm_attr_type_t {
        XFRMA_ALG_CRYPT,        /* struct xfrm_algo */
        XFRMA_ALG_COMP,         /* struct xfrm_algo */
        XFRMA_ENCAP,            /* struct xfrm_algo + struct
xfrm_encap_tmpl */
+       XFRMA_SEC_CTX,          /* struct xfrm_sec_ctx */
        XFRMA_TMPL,             /* 1 or more struct xfrm_user_tmpl */
        __XFRMA_MAX
 
diff -puN include/net/flow.h~lsm-xfrm-nethooks include/net/flow.h
---
linux-2.6.12-rc6-xfrm/include/net/flow.h~lsm-xfrm-nethooks  2005-06-13
13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/include/net/flow.h       2005-06-13
13:22:59.000000000 -0400
@@ -84,10 +84,11 @@ struct flowi {
 #define FLOW_DIR_OUT   1
 #define FLOW_DIR_FWD   2
 
-typedef void (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir,
+struct sock;
+typedef void (*flow_resolve_t)(struct flowi *key, struct sock *sk, u16
family, u8 dir,
                               void **objp, atomic_t **obj_refp);
 
-extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
+extern void *flow_cache_lookup(struct flowi *key, struct sock *sk, u16
family, u8 dir,
                               flow_resolve_t resolver);
 extern void flow_cache_flush(void);
 extern atomic_t flow_cache_genid;
diff -puN include/net/xfrm.h~lsm-xfrm-nethooks include/net/xfrm.h
---
linux-2.6.12-rc6-xfrm/include/net/xfrm.h~lsm-xfrm-nethooks  2005-06-13
13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/include/net/xfrm.h       2005-06-13
13:22:59.000000000 -0400
@@ -493,6 +493,27 @@ xfrm_selector_match(struct xfrm_selector
        return 0;
 }
 
+/* If neither has a context --> match
+   Otherwise, both must have a context and the sids, doi, alg must
match */
+static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct
xfrm_sec_ctx *s2)
+{
+       return ((!s1 && !s2) ||
+               (s1 && s2 &&
+                (s1->ctx_sid == s2->ctx_sid) &&
+                (s1->ctx_doi == s2->ctx_doi) &&
+                (s1->ctx_alg == s2->ctx_alg)));
+}
+
+static inline struct xfrm_sec_ctx *xfrm_policy_security(struct
xfrm_policy *xp)
+{
+       return (xp ? xp->selector.security : NULL);
+}
+
+static inline struct xfrm_sec_ctx *xfrm_state_security(struct
xfrm_state *x)
+{
+       return (x ? x->sel.security : NULL);
+}
+
 /* A struct encoding bundle of transformations to apply to some set of
flow.
  *
  * dst->child points to the next element of bundle.
diff -puN net/core/flow.c~lsm-xfrm-nethooks net/core/flow.c
---
linux-2.6.12-rc6-xfrm/net/core/flow.c~lsm-xfrm-nethooks     2005-06-13
13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/net/core/flow.c  2005-06-13
13:22:59.000000000 -0400
@@ -162,7 +162,7 @@ static int flow_key_compare(struct flowi
        return 0;
 }
 
-void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
+void *flow_cache_lookup(struct flowi *key, struct sock *sk, u16 family,
u8 dir,
                        flow_resolve_t resolver)
 {
        struct flow_cache_entry *fle, **head;
@@ -221,7 +221,7 @@ nocache:
                void *obj;
                atomic_t *obj_ref;
 
-               resolver(key, family, dir, &obj, &obj_ref);
+               resolver(key, sk, family, dir, &obj, &obj_ref);
 
                if (fle) {
                        fle->genid = atomic_read(&flow_cache_genid);
diff -puN net/ipv4/xfrm4_policy.c~lsm-xfrm-nethooks
net/ipv4/xfrm4_policy.c
---
linux-2.6.12-rc6-xfrm/net/ipv4/xfrm4_policy.c~lsm-xfrm-nethooks     2005-06-13 13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/net/ipv4/xfrm4_policy.c  2005-06-13
13:22:59.000000000 -0400
@@ -36,6 +36,8 @@ __xfrm4_find_bundle(struct flowi *fl, st
                if (xdst->u.rt.fl.oif == fl->oif &&     /*XXX*/
                    xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
                    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
+                   xfrm_sec_ctx_match(xfrm_policy_security(policy),
+                                      xfrm_state_security(dst->xfrm))
&&
                    xfrm_bundle_ok(xdst, fl, AF_INET)) {
                        dst_clone(dst);
                        break;
diff -puN net/ipv6/xfrm6_policy.c~lsm-xfrm-nethooks
net/ipv6/xfrm6_policy.c
---
linux-2.6.12-rc6-xfrm/net/ipv6/xfrm6_policy.c~lsm-xfrm-nethooks     2005-06-13 13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/net/ipv6/xfrm6_policy.c  2005-06-13
13:22:59.000000000 -0400
@@ -54,6 +54,8 @@ __xfrm6_find_bundle(struct flowi *fl, st
                                 xdst->u.rt6.rt6i_src.plen);
                if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr,
&fl_dst_prefix) &&
                    ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr,
&fl_src_prefix) &&
+                   xfrm_sec_ctx_match(xfrm_policy_security(policy),
+                                      xfrm_state_security(dst->xfrm))
&&
                    xfrm_bundle_ok(xdst, fl, AF_INET6)) {
                        dst_clone(dst);
                        break;
diff -puN net/key/af_key.c~lsm-xfrm-nethooks net/key/af_key.c
---
linux-2.6.12-rc6-xfrm/net/key/af_key.c~lsm-xfrm-nethooks    2005-06-13
13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/net/key/af_key.c 2005-06-16
14:48:27.000000000 -0400
@@ -336,6 +336,7 @@ static u8 sadb_ext_min_len[] = {
        [SADB_X_EXT_NAT_T_SPORT]        = (u8) sizeof(struct
sadb_x_nat_t_port),
        [SADB_X_EXT_NAT_T_DPORT]        = (u8) sizeof(struct
sadb_x_nat_t_port),
        [SADB_X_EXT_NAT_T_OA]           = (u8) sizeof(struct
sadb_address),
+       [SADB_X_EXT_SEC_CTX]            = (u8) sizeof(struct
sadb_x_sec_ctx),
 };
 
 /* Verify sadb_address_{len,prefixlen} against sa_family.  */
@@ -383,6 +384,40 @@ static int verify_address_len(void *p)
        return 0;
 }
 
+static inline int verify_sec_ctx_len(void *p)
+{
+       struct sadb_x_sec_ctx *sec_ctx = (struct sadb_x_sec_ctx *)p;
+       int len = 0;
+
+       len += sizeof(struct sadb_x_sec_ctx);
+       len += sec_ctx->sadb_x_ctx_len;
+       len += sizeof(uint64_t) - 1;
+       len /= sizeof(uint64_t);
+
+       if (sec_ctx->sadb_x_sec_len != len)
+               return -EINVAL;
+
+       return 0;
+}
+
+static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_ctx(struct
sadb_x_sec_ctx *sec_ctx)
+{
+       struct xfrm_user_sec_ctx *uctx = NULL;
+
+       if (sec_ctx) {
+               int ctx_size = sec_ctx->sadb_x_ctx_len;
+               uctx = kmalloc((sizeof(*uctx)+ctx_size), GFP_KERNEL);
+               uctx->len = sec_ctx->sadb_x_sec_len;
+               uctx->exttype = sec_ctx->sadb_x_sec_exttype;
+               uctx->ctx_doi = sec_ctx->sadb_x_ctx_doi;
+               uctx->ctx_alg = sec_ctx->sadb_x_ctx_alg;
+               uctx->ctx_len = sec_ctx->sadb_x_ctx_len;
+               memcpy(uctx + 1, sec_ctx + 1,
+                      uctx->ctx_len);
+       }
+       return uctx;
+}
+
 static int present_and_same_family(struct sadb_address *src,
                                   struct sadb_address *dst)
 {
@@ -438,6 +473,10 @@ static int parse_exthdrs(struct sk_buff 
                                if (verify_address_len(p))
                                        return -EINVAL;
                        }                               
+                       if (ext_type == SADB_X_EXT_SEC_CTX) {
+                               if (verify_sec_ctx_len(p))
+                                       return -EINVAL;
+                       }
                        ext_hdrs[ext_type-1] = p;
                }
                p   += ext_len;
@@ -586,6 +625,9 @@ static struct sk_buff * pfkey_xfrm_state
        struct sadb_key *key;
        struct sadb_x_sa2 *sa2;
        struct sockaddr_in *sin;
+       struct sadb_x_sec_ctx *sec_ctx;
+       struct xfrm_sec_ctx *xfrm_ctx;
+       int ctx_size = 0;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        struct sockaddr_in6 *sin6;
 #endif
@@ -609,6 +651,12 @@ static struct sk_buff * pfkey_xfrm_state
                        sizeof(struct sadb_address)*2 + 
                                sockaddr_size*2 +
                                        sizeof(struct sadb_x_sa2);
+
+       if ((xfrm_ctx = xfrm_state_security(x))) {
+               ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len);
+               size += sizeof(struct sadb_x_sec_ctx) + ctx_size;
+        }
+
        /* identity & sensitivity */
 
        if ((x->props.family == AF_INET &&
@@ -892,6 +940,20 @@ static struct sk_buff * pfkey_xfrm_state
                n_port->sadb_x_nat_t_port_reserved = 0;
        }
 
+       /* security context */
+        if (xfrm_ctx) {
+               sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb,
+                               sizeof(struct sadb_x_sec_ctx) +
ctx_size);
+               sec_ctx->sadb_x_sec_len =
+                 (sizeof(struct sadb_x_sec_ctx) + ctx_size) /
sizeof(uint64_t);
+               sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+               sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;
+               sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;
+               sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;
+               memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,
+                      xfrm_ctx->ctx_len);
+       }
+
        return skb;
 }
 
@@ -902,6 +964,7 @@ static struct xfrm_state * pfkey_msg2xfr
        struct sadb_lifetime *lifetime;
        struct sadb_sa *sa;
        struct sadb_key *key;
+       struct sadb_x_sec_ctx *sec_ctx;
        uint16_t proto;
        int err;
        
@@ -984,6 +1047,17 @@ static struct xfrm_state * pfkey_msg2xfr
                x->lft.soft_add_expires_seconds =
lifetime->sadb_lifetime_addtime;
                x->lft.soft_use_expires_seconds =
lifetime->sadb_lifetime_usetime;
        }
+
+       sec_ctx = (struct sadb_x_sec_ctx *)
ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+       if (sec_ctx != NULL) {
+               struct xfrm_user_sec_ctx *uctx =
pfkey_sadb2xfrm_user_ctx(sec_ctx);
+
+               err = security_xfrm_state_alloc(x, uctx);
+               kfree(uctx);
+               if (err)
+                       goto out;
+       }
+
        key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
        if (sa->sadb_sa_auth) {
                int keysize = 0;
@@ -1634,6 +1708,18 @@ parse_ipsecrequests(struct xfrm_policy *
        return 0;
 }
 
+static inline int pfkey_xfrm_policy2sec_ctx_size(struct xfrm_policy
*xp)
+{
+       struct xfrm_sec_ctx *xfrm_ctx = xfrm_policy_security(xp);
+
+       if (xfrm_ctx) {
+               int len = sizeof(struct sadb_x_sec_ctx);
+               len += xfrm_ctx->ctx_len;
+               return PFKEY_ALIGN8(len);
+       }
+       return 0;
+}
+
 static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp)
 {
        int sockaddr_size = pfkey_sockaddr_size(xp->family);
@@ -1647,7 +1733,8 @@ static int pfkey_xfrm_policy2msg_size(st
                (sockaddr_size * 2) +
                sizeof(struct sadb_x_policy) +
                (xp->xfrm_nr * (sizeof(struct sadb_x_ipsecrequest) +
-                               (socklen * 2)));
+                               (socklen * 2))) +
+               pfkey_xfrm_policy2sec_ctx_size(xp);
 }
 
 static struct sk_buff * pfkey_xfrm_policy2msg_prep(struct xfrm_policy
*xp)
@@ -1671,6 +1758,8 @@ static void pfkey_xfrm_policy2msg(struct
        struct sadb_lifetime *lifetime;
        struct sadb_x_policy *pol;
        struct sockaddr_in   *sin;
+       struct sadb_x_sec_ctx *sec_ctx;
+       struct xfrm_sec_ctx *xfrm_ctx;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        struct sockaddr_in6  *sin6;
 #endif
@@ -1855,19 +1944,35 @@ static void pfkey_xfrm_policy2msg(struct
                        }
                }
        }
+
+       /* security context */
+        if ((xfrm_ctx = xfrm_policy_security(xp))) {
+               int ctx_size = pfkey_xfrm_policy2sec_ctx_size(xp);
+
+               sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb,
ctx_size);
+               sec_ctx->sadb_x_sec_len = ctx_size / sizeof(uint64_t);
+               sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+               sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;
+               sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;
+               sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;
+               memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,
+                      xfrm_ctx->ctx_len);
+       }
+
        hdr->sadb_msg_len = size / sizeof(uint64_t);
        hdr->sadb_msg_reserved = atomic_read(&xp->refcnt);
 }
 
 static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct
sadb_msg *hdr, void **ext_hdrs)
 {
-       int err;
+       int err = 0;
        struct sadb_lifetime *lifetime;
        struct sadb_address *sa;
        struct sadb_x_policy *pol;
        struct xfrm_policy *xp;
        struct sk_buff *out_skb;
        struct sadb_msg *out_hdr;
+       struct sadb_x_sec_ctx *sec_ctx;
 
        if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
                                     ext_hdrs[SADB_EXT_ADDRESS_DST-1])
||
@@ -1914,6 +2019,18 @@ static int pfkey_spdadd(struct sock *sk,
        if (xp->selector.dport)
                xp->selector.dport_mask = ~0;
 
+       sec_ctx = (struct sadb_x_sec_ctx *)
ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+       if (sec_ctx != NULL) {
+               struct xfrm_user_sec_ctx *uctx =
pfkey_sadb2xfrm_user_ctx(sec_ctx);
+
+               err = security_xfrm_policy_alloc(xp, uctx);
+               kfree(uctx);
+               if (err) {
+                       err = -EINVAL;
+                       goto out;
+               }
+       }
+
        xp->lft.soft_byte_limit = XFRM_INF;
        xp->lft.hard_byte_limit = XFRM_INF;
        xp->lft.soft_packet_limit = XFRM_INF;
@@ -1963,6 +2080,7 @@ static int pfkey_spdadd(struct sock *sk,
        return 0;
 
 out:
+       security_xfrm_policy_free(xp);
        kfree(xp);
        return err;
 }
@@ -1972,10 +2090,11 @@ static int pfkey_spddelete(struct sock *
        int err;
        struct sadb_address *sa;
        struct sadb_x_policy *pol;
-       struct xfrm_policy *xp;
+       struct xfrm_policy *xp, tmp;
        struct sk_buff *out_skb;
        struct sadb_msg *out_hdr;
        struct xfrm_selector sel;
+       struct sadb_x_sec_ctx *sec_ctx;
 
        if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
                                     ext_hdrs[SADB_EXT_ADDRESS_DST-1])
||
@@ -2004,7 +2123,17 @@ static int pfkey_spddelete(struct sock *
        if (sel.dport)
                sel.dport_mask = ~0;
 
-       xp = xfrm_policy_bysel(pol->sadb_x_policy_dir-1, &sel, 1);
+       sec_ctx = (struct sadb_x_sec_ctx *)
ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+       memcpy(&tmp.selector, &sel, sizeof(struct xfrm_selector));
+       if (sec_ctx != NULL) {
+               err = security_xfrm_policy_alloc(
+                       &tmp, (struct xfrm_user_sec_ctx *)sec_ctx);
+               if (err)
+                       return err;
+       }
+
+       xp = xfrm_policy_bysel(pol->sadb_x_policy_dir-1, &tmp.selector,
1);
+       security_xfrm_policy_free(&tmp);
        if (xp == NULL)
                return -ENOENT;
 
@@ -2482,6 +2611,7 @@ static struct xfrm_policy *pfkey_compile
 {
        struct xfrm_policy *xp;
        struct sadb_x_policy *pol = (struct sadb_x_policy*)data;
+       struct sadb_x_sec_ctx *sec_ctx;
 
        switch (family) {
        case AF_INET:
@@ -2531,10 +2661,22 @@ static struct xfrm_policy *pfkey_compile
            (*dir = parse_ipsecrequests(xp, pol)) < 0)
                goto out;
 
+       /* security context too */
+       if (len >= (pol->sadb_x_policy_len*8 +
+                   sizeof(struct sadb_x_sec_ctx))) {
+               char *p = (char *) pol;
+               p += pol->sadb_x_policy_len*8;
+               sec_ctx = (struct sadb_x_sec_ctx *) p;
+               if (security_xfrm_policy_alloc(
+                           xp, (struct xfrm_user_sec_ctx *)sec_ctx))
+                       goto out;
+       }
+
        *dir = pol->sadb_x_policy_dir-1;
        return xp;
 
 out:
+       security_xfrm_policy_free(xp);
        kfree(xp);
        return NULL;
 }
diff -puN net/xfrm/xfrm_policy.c~lsm-xfrm-nethooks
net/xfrm/xfrm_policy.c
---
linux-2.6.12-rc6-xfrm/net/xfrm/xfrm_policy.c~lsm-xfrm-nethooks      2005-06-13 13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/net/xfrm/xfrm_policy.c   2005-06-13
13:22:59.000000000 -0400
@@ -10,7 +10,7 @@
  *     YOSHIFUJI Hideaki
  *             Split up af-specific portion
  *     Derek Atkins <derek@ihtfp.com>          Add the post_input
processor
- *     
+ *
  */
 
 #include <asm/bug.h>
@@ -257,6 +257,7 @@ void __xfrm_policy_destroy(struct xfrm_p
        if (del_timer(&policy->timer))
                BUG();
 
+       security_xfrm_policy_free(policy);
        kfree(policy);
 }
 EXPORT_SYMBOL(__xfrm_policy_destroy);
@@ -396,7 +397,8 @@ struct xfrm_policy *xfrm_policy_bysel(in
 
        write_lock_bh(&xfrm_policy_lock);
        for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next)
{
-               if (memcmp(sel, &pol->selector, sizeof(*sel)) == 0) {
+               if ((memcmp(sel, &pol->selector,
xfrm_selector_base_size()) == 0) &&
+                   (xfrm_sec_ctx_match(sel->security,
xfrm_policy_security(pol)))) {
                        xfrm_pol_hold(pol);
                        if (delete)
                                *p = pol->next;
@@ -492,7 +494,7 @@ EXPORT_SYMBOL(xfrm_policy_walk);
 
 /* Find policy to apply to this flow. */
 
-static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
+static void xfrm_policy_lookup(struct flowi *fl, struct sock *sk, u16
family, u8 dir,
                               void **objp, atomic_t **obj_refp)
 {
        struct xfrm_policy *pol;
@@ -506,9 +508,12 @@ static void xfrm_policy_lookup(struct fl
                        continue;
 
                match = xfrm_selector_match(sel, fl, family);
+
                if (match) {
-                       xfrm_pol_hold(pol);
-                       break;
+                       if (!security_xfrm_policy_lookup(sk, sel, fl,
dir)) {
+                               xfrm_pol_hold(pol);
+                               break;
+                       }
                }
        }
        read_unlock_bh(&xfrm_policy_lock);
@@ -516,15 +521,38 @@ static void xfrm_policy_lookup(struct fl
                *obj_refp = &pol->refcnt;
 }
 
+static inline int policy_to_flow_dir(int dir)
+{
+       if (XFRM_POLICY_IN == FLOW_DIR_IN &&
+           XFRM_POLICY_OUT == FLOW_DIR_OUT &&
+           XFRM_POLICY_FWD == FLOW_DIR_FWD)
+               return dir;
+       switch (dir) {
+       default:
+       case XFRM_POLICY_IN:
+               return FLOW_DIR_IN;
+       case XFRM_POLICY_OUT:
+               return FLOW_DIR_OUT;
+       case XFRM_POLICY_FWD:
+               return FLOW_DIR_FWD;
+       };
+}
+
 static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int
dir, struct flowi *fl)
 {
        struct xfrm_policy *pol;
 
        read_lock_bh(&xfrm_policy_lock);
        if ((pol = sk->sk_policy[dir]) != NULL) {
-               int match = xfrm_selector_match(&pol->selector, fl,
+               struct xfrm_selector *sel = &pol->selector;
+               int match = xfrm_selector_match(sel, fl,
                                                sk->sk_family);
+               int err = 0;
+
                if (match)
+                       err = security_xfrm_policy_lookup(sk, sel, fl,
policy_to_flow_dir(dir));
+
+               if (match && !err)
                        xfrm_pol_hold(pol);
                else
                        pol = NULL;
@@ -595,6 +623,10 @@ static struct xfrm_policy *clone_policy(
 
        if (newp) {
                newp->selector = old->selector;
+               if (security_xfrm_policy_clone(old, newp)) {
+                       kfree(newp);
+                       return NULL;  /* ENOMEM */
+               }
                newp->lft = old->lft;
                newp->curlft = old->curlft;
                newp->action = old->action;
@@ -706,22 +738,6 @@ xfrm_bundle_create(struct xfrm_policy *p
        return err;
 }
 
-static inline int policy_to_flow_dir(int dir)
-{
-       if (XFRM_POLICY_IN == FLOW_DIR_IN &&
-           XFRM_POLICY_OUT == FLOW_DIR_OUT &&
-           XFRM_POLICY_FWD == FLOW_DIR_FWD)
-               return dir;
-       switch (dir) {
-       default:
-       case XFRM_POLICY_IN:
-               return FLOW_DIR_IN;
-       case XFRM_POLICY_OUT:
-               return FLOW_DIR_OUT;
-       case XFRM_POLICY_FWD:
-               return FLOW_DIR_FWD;
-       };
-}
 
 static int stale_bundle(struct dst_entry *dst);
 
@@ -751,7 +767,7 @@ restart:
                if ((dst_orig->flags & DST_NOXFRM) ||
!xfrm_policy_list[XFRM_POLICY_OUT])
                        return 0;
 
-               policy = flow_cache_lookup(fl, family,
+               policy = flow_cache_lookup(fl, sk, family,
                                          
policy_to_flow_dir(XFRM_POLICY_OUT),
                                           xfrm_policy_lookup);
        }
@@ -942,7 +958,7 @@ int __xfrm_policy_check(struct sock *sk,
                int i;
 
                for (i=skb->sp->len-1; i>=0; i--) {
-                 struct sec_decap_state *xvec = &(skb->sp->x[i]);
+                       struct sec_decap_state *xvec = &(skb->sp->x[i]);
                        if (!xfrm_selector_match(&xvec->xvec->sel, &fl,
family))
                                return 0;
 
@@ -960,7 +976,7 @@ int __xfrm_policy_check(struct sock *sk,
                pol = xfrm_sk_policy_lookup(sk, dir, &fl);
 
        if (!pol)
-               pol = flow_cache_lookup(&fl, family,
+               pol = flow_cache_lookup(&fl, sk, family,
                                        policy_to_flow_dir(dir),
                                        xfrm_policy_lookup);
 
diff -puN net/xfrm/xfrm_state.c~lsm-xfrm-nethooks net/xfrm/xfrm_state.c
---
linux-2.6.12-rc6-xfrm/net/xfrm/xfrm_state.c~lsm-xfrm-nethooks       2005-06-13 13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/net/xfrm/xfrm_state.c    2005-06-13
13:22:59.000000000 -0400
@@ -10,7 +10,7 @@
  *             Split up af-specific functions
  *     Derek Atkins <derek@ihtfp.com>
  *             Add UDP Encapsulation
- *     
+ *
  */
 
 #include <linux/workqueue.h>
@@ -74,6 +74,7 @@ static void xfrm_state_gc_destroy(struct
                x->type->destructor(x);
                xfrm_put_type(x->type);
        }
+       security_xfrm_state_free(x);
        kfree(x);
 }
 
@@ -338,7 +339,8 @@ xfrm_state_find(xfrm_address_t *daddr, x
                              selector.
                         */
                        if (x->km.state == XFRM_STATE_VALID) {
-                               if (!xfrm_selector_match(&x->sel, fl,
family))
+                               if (!xfrm_selector_match(&x->sel, fl,
family) ||
+                                  
!xfrm_sec_ctx_match(xfrm_policy_security(pol), xfrm_state_security(x)))
                                        continue;
                                if (!best ||
                                    best->km.dying > x->km.dying ||
@@ -349,7 +351,8 @@ xfrm_state_find(xfrm_address_t *daddr, x
                                acquire_in_progress = 1;
                        } else if (x->km.state == XFRM_STATE_ERROR ||
                                   x->km.state == XFRM_STATE_EXPIRED) {
-                               if (xfrm_selector_match(&x->sel, fl,
family))
+                               if (xfrm_selector_match(&x->sel, fl,
family) &&
+                                  
xfrm_sec_ctx_match(xfrm_policy_security(pol), xfrm_state_security(x)))
                                        error = -ESRCH;
                        }
                }
@@ -374,6 +377,13 @@ xfrm_state_find(xfrm_address_t *daddr, x
                xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
 
                if (km_query(x, tmpl, pol) == 0) {
+                       if
(!xfrm_sec_ctx_match(xfrm_policy_security(pol), xfrm_state_security(x)))
{
+                               x->km.state = XFRM_STATE_DEAD;
+                               xfrm_state_put(x);
+                               x = NULL;
+                               error = -EPERM;
+                               goto out;
+                       }
                        x->km.state = XFRM_STATE_ACQ;
                        list_add_tail(&x->bydst, xfrm_state_bydst+h);
                        xfrm_state_hold(x);
diff -puN net/xfrm/xfrm_user.c~lsm-xfrm-nethooks net/xfrm/xfrm_user.c
---
linux-2.6.12-rc6-xfrm/net/xfrm/xfrm_user.c~lsm-xfrm-nethooks        2005-06-13 13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/net/xfrm/xfrm_user.c     2005-06-16
14:39:56.000000000 -0400
@@ -7,7 +7,7 @@
  *     Kazunori MIYAZAWA @USAGI
  *     Kunihiro Ishiguro <kunihiro@ipinfusion.com>
  *             IPv6 support
- *     
+ *
  */
 
 #include <linux/module.h>
@@ -209,6 +209,30 @@ static int attach_encap_tmpl(struct xfrm
        return 0;
 }
 
+
+static inline int xfrm_user_sec_ctx_size(struct xfrm_policy *xp)
+{
+       struct xfrm_sec_ctx *xfrm_ctx = xfrm_policy_security(xp);
+       int len = 0;
+
+       if (xfrm_ctx) {
+               len += sizeof(struct xfrm_user_sec_ctx);
+               len += xfrm_ctx->ctx_len;
+       }
+       return len;
+}
+
+static int attach_sec_ctx(struct xfrm_state *x, struct rtattr *u_arg)
+{
+       struct xfrm_user_sec_ctx *uxsc = RTA_DATA(u_arg);
+
+       if (uxsc) {
+               return security_xfrm_state_alloc(x, uxsc);
+       }
+
+       return 0;
+}
+
 static void copy_from_user_state(struct xfrm_state *x, struct
xfrm_usersa_info *p)
 {
        memcpy(&x->id, &p->id, sizeof(x->id));
@@ -258,6 +282,9 @@ static struct xfrm_state *xfrm_state_con
        if (err)
                goto error;
 
+       if ((err = attach_sec_ctx(x, xfrma[XFRMA_SEC_CTX-1])))
+               goto error;
+
        x->curlft.add_time = (unsigned long) xtime.tv_sec;
        x->km.state = XFRM_STATE_VALID;
        x->km.seq = p->seq;
@@ -344,6 +371,27 @@ struct xfrm_dump_info {
        int this_idx;
 };
 
+static int dump_one_sec_ctx(struct xfrm_sec_ctx *ctx, struct
xfrm_user_sec_ctx *uctx, struct sk_buff *skb, int ctx_size)
+{
+       if (!ctx)
+               return -1;
+
+       uctx->exttype = XFRMA_SEC_CTX;
+       uctx->len = ctx_size;
+       uctx->ctx_doi = ctx->ctx_doi;
+       uctx->ctx_alg = ctx->ctx_alg;
+       uctx->ctx_len = ctx->ctx_len;
+
+       memcpy(uctx + 1, ctx->ctx_str, ctx->ctx_len);
+
+       RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size, uctx);
+
+       return 0;
+
+rtattr_failure:
+       return -1;
+}
+
 static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
 {
        struct xfrm_dump_info *sp = ptr;
@@ -352,6 +400,7 @@ static int dump_one_state(struct xfrm_st
        struct xfrm_usersa_info *p;
        struct nlmsghdr *nlh;
        unsigned char *b = skb->tail;
+       struct xfrm_sec_ctx *xfrm_ctx;
 
        if (sp->this_idx < sp->start_idx)
                goto out;
@@ -376,6 +425,18 @@ static int dump_one_state(struct xfrm_st
        if (x->encap)
                RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
 
+       if ((xfrm_ctx = xfrm_state_security(x))) {
+               int ctx_size = sizeof(struct xfrm_user_sec_ctx) +
+                       xfrm_ctx->ctx_len + 1;
+               struct xfrm_user_sec_ctx *uctx = kmalloc(ctx_size,
GFP_KERNEL);
+               int err;
+
+               err = dump_one_sec_ctx(xfrm_ctx, uctx, skb, ctx_size);
+               kfree(uctx);
+
+               if (err < 0)
+                       goto rtattr_failure;
+       }
        nlh->nlmsg_len = skb->tail - b;
 out:
        sp->this_idx++;
@@ -589,6 +650,25 @@ static int verify_newpolicy_info(struct 
        return verify_policy_dir(p->dir);
 }
 
+static int copy_sec_ctx(struct xfrm_policy *pol, struct
xfrm_user_sec_ctx *uctx)
+{
+       int err = 0;
+
+       if (uctx) {
+               err = security_xfrm_policy_alloc(pol, uctx);
+       }
+
+       return err;
+}
+
+static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct
rtattr **xfrma)
+{
+       struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1];
+       struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt);
+
+       return copy_sec_ctx(pol, uctx);
+}
+
 static void copy_templates(struct xfrm_policy *xp, struct
xfrm_user_tmpl *ut,
                           int nr)
 {
@@ -667,7 +747,10 @@ static struct xfrm_policy *xfrm_policy_c
        }
 
        copy_from_user_policy(xp, p);
-       err = copy_from_user_tmpl(xp, xfrma);
+
+       if (!(err = copy_from_user_tmpl(xp, xfrma)))
+               err = copy_from_user_sec_ctx(xp, xfrma);
+
        if (err) {
                *errp = err;
                kfree(xp);
@@ -737,6 +820,27 @@ rtattr_failure:
        return -1;
 }
 
+static int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff
*skb, int src)
+{
+       int err = 0;
+       struct xfrm_sec_ctx *xfrm_ctx = xfrm_policy_security(xp);
+
+       if (xfrm_ctx) {
+               int ctx_size = sizeof(struct xfrm_user_sec_ctx) +
+                       xfrm_ctx->ctx_len;
+               struct xfrm_user_sec_ctx *uctx = kmalloc(ctx_size,
GFP_KERNEL);
+
+               if (!uctx)
+                       return -ENOMEM;
+
+               err = dump_one_sec_ctx(xfrm_ctx, uctx, skb,
+                                      ctx_size);
+               kfree(uctx);
+       }
+
+       return err;
+}
+
 static int dump_one_policy(struct xfrm_policy *xp, int dir, int count,
void *ptr)
 {
        struct xfrm_dump_info *sp = ptr;
@@ -758,6 +862,8 @@ static int dump_one_policy(struct xfrm_p
        copy_to_user_policy(xp, p, dir);
        if (copy_to_user_tmpl(xp, skb) < 0)
                goto nlmsg_failure;
+       if (copy_to_user_sec_ctx(xp, skb, 0) < 0)
+               goto nlmsg_failure;
 
        nlh->nlmsg_len = skb->tail - b;
 out:
@@ -813,7 +919,7 @@ static struct sk_buff *xfrm_policy_netli
 
 static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
void **xfrma)
 {
-       struct xfrm_policy *xp;
+       struct xfrm_policy *xp, tmp;
        struct xfrm_userpolicy_id *p;
        int err;
        int delete;
@@ -827,8 +933,20 @@ static int xfrm_get_policy(struct sk_buf
 
        if (p->index)
                xp = xfrm_policy_byid(p->dir, p->index, delete);
-       else
-               xp = xfrm_policy_bysel(p->dir, &p->sel, delete);
+       else {
+               struct rtattr **rtattrs = (struct rtattr **) xfrma;
+               struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1];
+
+               memcpy(&tmp.selector, &p->sel, sizeof(struct
xfrm_selector));
+               if (rt) {
+                       struct xfrm_user_sec_ctx *uxsc = RTA_DATA(rt);
+
+                       if ((err = security_xfrm_policy_alloc(&tmp,
uxsc)))
+                               return err;
+               }
+               xp = xfrm_policy_bysel(p->dir, &tmp.selector, delete);
+               security_xfrm_policy_free(&tmp);
+       }
        if (xp == NULL)
                return -ENOENT;
 
@@ -1110,6 +1228,8 @@ static int build_acquire(struct sk_buff 
 
        if (copy_to_user_tmpl(xp, skb) < 0)
                goto nlmsg_failure;
+       if (copy_to_user_sec_ctx(xp, skb, 1) < 0)
+               goto nlmsg_failure;
 
        nlh->nlmsg_len = skb->tail - b;
        return skb->len;
@@ -1127,6 +1247,7 @@ static int xfrm_send_acquire(struct xfrm
 
        len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
        len += NLMSG_SPACE(sizeof(struct xfrm_user_acquire));
+       len += RTA_SPACE(xfrm_user_sec_ctx_size(xp));
        skb = alloc_skb(len, GFP_ATOMIC);
        if (skb == NULL)
                return -ENOMEM;
@@ -1147,8 +1268,9 @@ static struct xfrm_policy *xfrm_compile_
 {
        struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info
*)data;
        struct xfrm_user_tmpl *ut = (struct xfrm_user_tmpl *) (p + 1);
+       struct xfrm_user_sec_ctx *uctx;
        struct xfrm_policy *xp;
-       int nr;
+       int nr = 0;
 
        switch (family) {
        case AF_INET:
@@ -1176,9 +1298,26 @@ static struct xfrm_policy *xfrm_compile_
            verify_newpolicy_info(p))
                return NULL;
 
+       if (len > (sizeof(*p) + (XFRM_MAX_DEPTH *
+                                sizeof(struct xfrm_user_tmpl)))) {
+               struct xfrm_user_tmpl *tmpl;
+               uctx = (struct xfrm_user_sec_ctx *) (ut +
XFRM_MAX_DEPTH);
+
+               if (len != sizeof(*p) +
+                   (XFRM_MAX_DEPTH * sizeof(struct xfrm_user_tmpl)) +
+                   uctx->len)
+                       return NULL;
+
+               /* spi must be zero'd unless real tmpl */
+               for (tmpl = ut; tmpl->id.spi != 0; tmpl = tmpl + 1)
+                       nr++;
+       }
+       else {
+               uctx = NULL;
        nr = ((len - sizeof(*p)) / sizeof(*ut));
        if (nr > XFRM_MAX_DEPTH)
                return NULL;
+       }
 
        xp = xfrm_policy_alloc(GFP_KERNEL);
        if (xp == NULL) {
@@ -1188,6 +1327,10 @@ static struct xfrm_policy *xfrm_compile_
 
        copy_from_user_policy(xp, p);
        copy_templates(xp, ut, nr);
+       if (copy_sec_ctx(xp, uctx)) {
+               *dir = -EPERM;
+               return NULL;
+       }
 
        *dir = p->dir;
 
@@ -1208,6 +1351,8 @@ static int build_polexpire(struct sk_buf
        copy_to_user_policy(xp, &upe->pol, dir);
        if (copy_to_user_tmpl(xp, skb) < 0)
                goto nlmsg_failure;
+       if (copy_to_user_sec_ctx(xp, skb, 2) < 0)
+               goto nlmsg_failure;
        upe->hard = !!hard;
 
        nlh->nlmsg_len = skb->tail - b;
@@ -1225,6 +1370,7 @@ static int xfrm_send_policy_notify(struc
 
        len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
        len += NLMSG_SPACE(sizeof(struct xfrm_user_polexpire));
+       len += xfrm_user_sec_ctx_size(xp);
        skb = alloc_skb(len, GFP_ATOMIC);
        if (skb == NULL)
                return -ENOMEM;
diff -puN security/dummy.c~lsm-xfrm-nethooks security/dummy.c
---
linux-2.6.12-rc6-xfrm/security/dummy.c~lsm-xfrm-nethooks    2005-06-13
13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/security/dummy.c 2005-06-13
13:22:59.000000000 -0400
@@ -811,6 +811,35 @@ static inline void dummy_sk_free_securit
 }
 #endif /* CONFIG_SECURITY_NETWORK */
 
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp,
struct xfrm_user_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static inline int dummy_xfrm_policy_clone_security(struct xfrm_policy
*old, struct xfrm_policy *new)
+{
+        return 0;
+}
+
+static void dummy_xfrm_policy_free_security(struct xfrm_policy *xp)
+{
+}
+
+static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, struct
xfrm_user_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static void dummy_xfrm_state_free_security(struct xfrm_state *x)
+{
+}
+
+static int dummy_xfrm_policy_lookup(struct sock *sk, struct
xfrm_selector *sel, struct flowi *fl, u8 dir)
+{
+        return 0;
+}
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
 static int dummy_register_security (const char *name, struct
security_operations *ops)
 {
        return -EINVAL;
@@ -992,5 +1021,13 @@ void security_fixup_ops (struct security
        set_to_dummy_if_null(ops, sk_alloc_security);
        set_to_dummy_if_null(ops, sk_free_security);
 #endif /* CONFIG_SECURITY_NETWORK */
+#ifdef  CONFIG_SECURITY_NETWORK_XFRM
+       set_to_dummy_if_null(ops, xfrm_policy_alloc_security);
+       set_to_dummy_if_null(ops, xfrm_policy_clone_security);
+       set_to_dummy_if_null(ops, xfrm_policy_free_security);
+       set_to_dummy_if_null(ops, xfrm_state_alloc_security);
+       set_to_dummy_if_null(ops, xfrm_state_free_security);
+       set_to_dummy_if_null(ops, xfrm_policy_lookup);
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
 }
 
diff -puN security/Kconfig~lsm-xfrm-nethooks security/Kconfig
---
linux-2.6.12-rc6-xfrm/security/Kconfig~lsm-xfrm-nethooks    2005-06-13
13:22:59.000000000 -0400
+++ linux-2.6.12-rc6-xfrm-root/security/Kconfig 2005-06-13
13:22:59.000000000 -0400
@@ -53,6 +53,19 @@ config SECURITY_NETWORK
          implement socket and networking access controls.
          If you are unsure how to answer this question, answer N.
 
+config SECURITY_NETWORK_XFRM
+       bool "XFRM (IPSec) Networking Security Hooks"
+       depends on XFRM && SECURITY_NETWORK
+       help
+         This enables the XFRM (IPSec) networking security hooks.
+         If enabled, a security module can use these hooks to
+         implement per-packet access controls based on labels
+         derived from IPSec policy.  Non-IPSec communications are
+         designated as unlabelled, and only sockets authorized
+         to communicate unlabelled data can send without using
+         IPSec.
+         If you are unsure how to answer this question, answer N.
+
 config SECURITY_CAPABILITIES
        tristate "Default Linux Capabilities"
        depends on SECURITY
_

^ permalink raw reply

* Re: receive only one record from the routing table
From: Thomas Graf @ 2005-06-17 14:15 UTC (permalink / raw)
  To: Tomá? Macek; +Cc: netdev
In-Reply-To: <Pine.LNX.4.61.0506171359490.31631@localhost.localdomain>

* Tom?? Macek <Pine.LNX.4.61.0506171359490.31631@localhost.localdomain> 2005-06-17 14:51
>      nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
>      nlMsg->nlmsg_type = RTM_GETROUTE;   // Get the routes from kernel routing table .
> 
>      nlMsg->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;   // The message is a request for dump.

Omit NLM_F_DUMP and you'll be fine, see rfc3549.

^ permalink raw reply

* Re: receive only one record from the routing table
From: Tomáš Macek @ 2005-06-17 18:57 UTC (permalink / raw)
  To: netdev
In-Reply-To: <20050617141527.GN22463@postel.suug.ch>

Part of my routing table is here:

3.3.0.0         *               255.255.0.0     U     0      0        0 eth1
default         meric           0.0.0.0         UG    0      0        0 eth0

Ommiting NLM_F_DUMP and typing './a.out 3.3.0.0' gives

Error in recieved packet: Success
Read From Socket Failed...

and I don't see the reason why... I think, it should write something with the 3.3.0.0 destination, but writes the error above instead


On Fri, 17 Jun 2005, Thomas Graf wrote:

> * Tom?? Macek <Pine.LNX.4.61.0506171359490.31631@localhost.localdomain> 2005-06-17 14:51
>>      nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
>>      nlMsg->nlmsg_type = RTM_GETROUTE;   // Get the routes from kernel routing table .
>>
>>      nlMsg->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;   // The message is a request for dump.
>
> Omit NLM_F_DUMP and you'll be fine, see rfc3549.
>
>
>
>
>

^ permalink raw reply

* Re: receive only one record from the routing table
From: Thomas Graf @ 2005-06-17 19:13 UTC (permalink / raw)
  To: Tomá? Macek; +Cc: netdev
In-Reply-To: <Pine.LNX.4.61.0506172057240.26739@localhost.localdomain>

* Tom?? Macek <Pine.LNX.4.61.0506172057240.26739@localhost.localdomain> 2005-06-17 20:57
> Part of my routing table is here:
> 
> 3.3.0.0         *               255.255.0.0     U     0      0        0 eth1
> default         meric           0.0.0.0         UG    0      0        0 eth0
> 
> Ommiting NLM_F_DUMP and typing './a.out 3.3.0.0' gives
> 
> Error in recieved packet: Success
> Read From Socket Failed...

Bcause you don't set rtm_dst_len to the prefix length or 32,
and rtm_family (AF_INET). You could also use libnl, probably
easier to use.

^ permalink raw reply

* netpoll and the bonding driver
From: Jeff Moyer @ 2005-06-17 19:56 UTC (permalink / raw)
  To: mpm; +Cc: netdev, linux-kernel

Hi,

I'm trying to implement a netpoll hook for the bonding driver.  In doing
so, I ran into the following problem:

netpoll_send_skb calls the device's hard_start_xmit routine.  In this case,
it will be one of the bonding driver's xmit routines.  Each of these ends
up calling bond_dev_queue_xmit, which in turn calls dev_queue_xmit.

Now, for netconsole, the code disables interrupts before calling
netpoll_send_udp:

        local_irq_save(flags);

        for(left = len; left; ) {
                frag = min(left, MAX_PRINT_CHUNK);
                netpoll_send_udp(&np, msg, frag);
                msg += frag;
                left -= frag;
        }

        local_irq_restore(flags);

Note that if you did an alt-sysrq-t, then you would enter this code path in
interrupt context as well, and herein lies the problem.  It seems that
dev_queue_xmit is not supposed to be called with interrupts disabled.  The
immediate affect of this is that the WARN_ON in local_bh_enable triggers
(called at the end of dev_queue_xmit), causing us to loop infinitely
printing out stack traces.

So, my question is this: how in the world do we fit the bonding driver into
the generic netpoll infrastructure?  In the case of every other driver,
netpoll simply calls the hard_start_xmit routine[1], and this approach
simply doesn't work for the bonding driver, for the reasons I described
above.  So, one way to make the bonding driver fit into this model is to
modify it to not call dev_queue_xmit when called from netpoll.  This can be
done, I suppose, by adding another start_xmit routine that is specific to
netpoll.  This doesn't feel good to me, but I'm not sure how else you would
solve the problem (and netpoll already gets its own poll interface, so is
one more all that bad?).  The other approach to take is to put bonding
specific logic into netpoll.  I think we can all agree that is a bad idea.

-Jeff

[1] Note that netpoll does not perform any of the checks that dev_queue_xmit
    does.  This either means that a) in the netpoll case, this is an okay
    thing to do (since it's been working for this long), or b) netpoll has a 
    bug.

^ permalink raw reply

* [PATCH net-drivers-2.6 0/9] ixgb: driver update
From: Malli Chilakala @ 2005-06-17 23:54 UTC (permalink / raw)
  To: jgarzik@pobox.com; +Cc: netdev

ixgb: driver update

Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
Signed-off-by: John Ronciak <john.ronciak@intel.com>
 
1. Set RXDCTL:PTHRESH/HTHRESH to zero 
2. Fix unnecessary link state messages
3. Use netdev_priv() instead of netdev->priv
4. Fix Broadcast/Multicast packets received statistics
5. Fix data output by ethtool -d 
6. Ethtool cleanup patch from Stephen Hemminger
7. Remove unused functions, render some variable static instead of global 
8. Redefined buffer_info-dma to be dma_addr_t instead of uint64
9. Driver version & white space fixes

^ permalink raw reply

* [PATCH net-drivers-2.6 1/9] ixgb: Set RXDCTL:PTHRESH/HTHRESH to zero
From: Malli Chilakala @ 2005-06-17 23:55 UTC (permalink / raw)
  To: jgarzik@pobox.com; +Cc: netdev

Set RXDCTL:PTHRESH/HTHRESH to zero 

Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
Signed-off-by: John Ronciak <john.ronciak@intel.com>
 
diff -up netdev-2.6/drivers/net/ixgb/ixgb_main.c netdev-2.6/drivers/net/ixgb.new/ixgb_main.c
--- netdev-2.6/drivers/net/ixgb/ixgb_main.c	2005-05-25 12:26:48.000000000 -0700
+++ netdev-2.6/drivers/net/ixgb.new/ixgb_main.c	2005-05-25 12:27:01.000000000 -0700
@@ -142,10 +142,12 @@ static void ixgb_netpoll(struct net_devi
 MODULE_LICENSE("GPL");
 
 /* some defines for controlling descriptor fetches in h/w */
-#define RXDCTL_PTHRESH_DEFAULT 128	/* chip considers prefech below this */
-#define RXDCTL_HTHRESH_DEFAULT 16	/* chip will only prefetch if tail is 
-					   pushed this many descriptors from head */
 #define RXDCTL_WTHRESH_DEFAULT 16	/* chip writes back at this many or RXT0 */
+#define RXDCTL_PTHRESH_DEFAULT 0		/* chip considers prefech below
+						 * this */
+#define RXDCTL_HTHRESH_DEFAULT 0		/* chip will only prefetch if tail
+						 * is pushed this many descriptors
+						 * from head */
 
 /**
  * ixgb_init_module - Driver Registration Routine

^ permalink raw reply

* [PATCH net-drivers-2.6 2/9] ixgb: Fix unnecessary link state messages
From: Malli Chilakala @ 2005-06-17 23:57 UTC (permalink / raw)
  To: jgarzik@pobox.com; +Cc: netdev

Fix unnecessary link state messages

Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
Signed-off-by: John Ronciak <john.ronciak@intel.com>
 
diff -up netdev-2.6/drivers/net/ixgb/ixgb_ethtool.c netdev-2.6/drivers/net/ixgb.new/ixgb_ethtool.c
--- netdev-2.6/drivers/net/ixgb/ixgb_ethtool.c	2005-05-25 12:26:48.000000000 -0700
+++ netdev-2.6/drivers/net/ixgb.new/ixgb_ethtool.c	2005-05-25 12:26:56.000000000 -0700
@@ -130,6 +130,12 @@ ixgb_get_settings(struct net_device *net
 		ixgb_down(adapter, TRUE);
 		ixgb_reset(adapter);
 		ixgb_up(adapter);
+		/* be optimistic about our link, since we were up before */
+		adapter->link_speed = 10000;
+		adapter->link_duplex = FULL_DUPLEX;
+		netif_carrier_on(netdev);
+		netif_wake_queue(netdev);
+		
 	} else
 		ixgb_reset(adapter);
 
@@ -177,6 +181,11 @@ ixgb_set_pauseparam(struct net_device *n
 	if(netif_running(adapter->netdev)) {
 		ixgb_down(adapter, TRUE);
 		ixgb_up(adapter);
+		/* be optimistic about our link, since we were up before */
+		adapter->link_speed = 10000;
+		adapter->link_duplex = FULL_DUPLEX;
+		netif_carrier_on(netdev);
+		netif_wake_queue(netdev);
 	} else
 		ixgb_reset(adapter);
 		
@@ -199,6 +181,11 @@ 
 	if(netif_running(netdev)) {
 		ixgb_down(adapter,TRUE);
 		ixgb_up(adapter);
+		/* be optimistic about our link, since we were up before */
+		adapter->link_speed = 10000;
+		adapter->link_duplex = FULL_DUPLEX;
+		netif_carrier_on(netdev);
+		netif_wake_queue(netdev);
 	} else
 		ixgb_reset(adapter);
 	return 0;
@@ -573,6 +573,11 @@ ixgb_set_ringparam(struct net_device *ne
 		adapter->tx_ring = tx_new;
 		if((err = ixgb_up(adapter)))
 			return err;
+		/* be optimistic about our link, since we were up before */
+		adapter->link_speed = 10000;
+		adapter->link_duplex = FULL_DUPLEX;
+		netif_carrier_on(netdev);
+		netif_wake_queue(netdev);
 	}
 
 	return 0;

^ permalink raw reply

* Re: [PATCH net-drivers-2.6 2/9] ixgb: Fix unnecessary link state messages
From: Francois Romieu @ 2005-06-18 10:28 UTC (permalink / raw)
  To: Malli Chilakala; +Cc: jgarzik@pobox.com, netdev
In-Reply-To: <Pine.LNX.4.61.0506131234090.24260@anoushka.jf.intel.com>

Malli Chilakala <mallikarjuna.chilakala@intel.com> :
> Fix unnecessary link state messages
> 
> Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
> Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
> Signed-off-by: John Ronciak <john.ronciak@intel.com>

The patch duplicates a lot of code. Do you really want these parts to be
modified independantly ?

--
Ueimor

^ 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