Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 00/10]: Netfilter IPsec support
From: David S. Miller @ 2005-11-11  5:17 UTC (permalink / raw)
  To: kaber; +Cc: netdev, netfilter-devel
In-Reply-To: <43740D9C.80003@trash.net>

From: Patrick McHardy <kaber@trash.net>
Date: Fri, 11 Nov 2005 04:18:52 +0100

> This is the latest set patches for netfilter IPsec support.
> The use of netif_rx for the innermost SA if it used transport
> mode has been replaced by explicit NF_HOOK calls in
> xfrm{4,6}_input.c.

Note that I consider this stuff 2.6.16 material.

We do have a lot of networking changes in 2.6.15
as it is, and also it would be good for these changes
to get some review and discussion time.

^ permalink raw reply

* [PATCH 10/10]: [NETFILTER]: Handle NAT in IPsec policy checks
From: Patrick McHardy @ 2005-11-11  3:19 UTC (permalink / raw)
  To: Kernel Netdev Mailing List, Netfilter Development Mailinglist

[-- Attachment #1: 10.diff --]
[-- Type: text/x-patch, Size: 8716 bytes --]

[NETFILTER]: Handle NAT in IPsec policy checks

Handle NAT by reconstructing the struct flowi for the original packet
from the conntrack information.

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

---
commit 5365555b302ffc8a31170833ca33636e9e66ff9a
tree 23c41caf62635ec31f4a6f0f12407de9fcc5d24a
parent d449eeda76508f14f27d76a84350e4069c968497
author Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 03:42:20 +0100
committer Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 03:42:20 +0100

 include/linux/netfilter.h              |   16 ++++++++++
 net/dccp/ipv4.c                        |    2 +
 net/ipv4/ip_input.c                    |   14 ++++-----
 net/ipv4/netfilter.c                   |    3 ++
 net/ipv4/netfilter/ip_nat_standalone.c |   50 +++++++++++++++++++++++++++++++-
 net/ipv4/raw.c                         |    1 +
 net/ipv4/tcp_ipv4.c                    |    3 ++
 net/ipv4/udp.c                         |    2 +
 net/sctp/input.c                       |    1 +
 net/xfrm/xfrm_policy.c                 |    2 +
 10 files changed, 84 insertions(+), 10 deletions(-)

diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 4c89c2c..8497f24 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -266,6 +266,20 @@ static inline int nf_defer_fragment(stru
 	return skb->nfct != NULL;
 }
 
+#include <net/flow.h>
+extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
+
+static inline void
+nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
+{
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+	void (*decodefn)(struct sk_buff *, struct flowi *);
+
+	if (family == AF_INET && (decodefn = ip_nat_decode_session) != NULL)
+		decodefn(skb, fl);
+#endif
+}
+
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
 extern struct proc_dir_entry *proc_net_netfilter;
@@ -275,6 +289,8 @@ extern struct proc_dir_entry *proc_net_n
 #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
 static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
 static inline int nf_defer_fragment(struct sk_buff *skb) { return 0; }
+static inline void
+nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family) {}
 #endif /*CONFIG_NETFILTER*/
 
 #endif /*__KERNEL__*/
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 6298cf5..599be6c 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -1173,6 +1173,7 @@ int dccp_v4_rcv(struct sk_buff *skb)
 		dccp_pr_debug("xfrm4_policy_check failed\n");
 		goto discard_and_relse;
 	}
+	nf_reset(skb);
 
         if (sk_filter(sk, skb, 0)) {
 		dccp_pr_debug("sk_filter failed\n");
@@ -1195,6 +1196,7 @@ int dccp_v4_rcv(struct sk_buff *skb)
 no_dccp_socket:
 	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
 		goto discard_it;
+	nf_reset(skb);
 	/*
 	 * Step 2:
 	 *		Generate Reset(No Connection) unless P.type == Reset
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 473d0f2..b6f5c85 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -203,10 +203,6 @@ static inline int ip_local_deliver_finis
 
 	__skb_pull(skb, ihl);
 
-	/* Free reference early: we don't need it any more, and it may
-           hold ip_conntrack module loaded indefinitely. */
-	nf_reset(skb);
-
         /* Point into the IP datagram, just past the header. */
         skb->h.raw = skb->data;
 
@@ -231,10 +227,12 @@ static inline int ip_local_deliver_finis
 		if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
 			int ret;
 
-			if (!ipprot->no_policy &&
-			    !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
-				kfree_skb(skb);
-				goto out;
+			if (!ipprot->no_policy) {
+				if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+					kfree_skb(skb);
+					goto out;
+				}
+				nf_reset(skb);
 			}
 			ret = ipprot->handler(skb);
 			if (ret < 0) {
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 8fda96a..b66856d 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -134,6 +134,9 @@ drop:
 }
 #endif /* CONFIG_XFRM */
 
+void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
+EXPORT_SYMBOL(ip_nat_decode_session);
+
 /*
  * Extra routing may needed on local out, as the QUEUE target never
  * returns control to the table.
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index e383b16..5217318 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -55,6 +55,44 @@
 			         : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN"  \
 				    : "*ERROR*")))
 
+#ifdef CONFIG_XFRM
+static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
+{
+	struct ip_conntrack *ct;
+	struct ip_conntrack_tuple *t;
+	enum ip_conntrack_info ctinfo;
+	enum ip_conntrack_dir dir;
+	unsigned long statusbit;
+
+	ct = ip_conntrack_get(skb, &ctinfo);
+	if (ct == NULL)
+		return;
+	dir = CTINFO2DIR(ctinfo);
+	t = &ct->tuplehash[dir].tuple;
+
+	if (dir == IP_CT_DIR_ORIGINAL)
+		statusbit = IPS_DST_NAT;
+	else
+		statusbit = IPS_SRC_NAT;
+
+	if (ct->status & statusbit) {
+		fl->fl4_dst = t->dst.ip;
+		if (t->dst.protonum == IPPROTO_TCP ||
+		    t->dst.protonum == IPPROTO_UDP)
+			fl->fl_ip_dport = t->dst.u.tcp.port;
+	}
+
+	statusbit ^= IPS_NAT_MASK;
+
+	if (ct->status & statusbit) {
+		fl->fl4_src = t->src.ip;
+		if (t->dst.protonum == IPPROTO_TCP ||
+		    t->dst.protonum == IPPROTO_UDP)
+			fl->fl_ip_sport = t->src.u.tcp.port;
+	}
+}
+#endif
+		
 static unsigned int
 ip_nat_fn(unsigned int hooknum,
 	  struct sk_buff **pskb,
@@ -332,10 +370,14 @@ static int init_or_cleanup(int init)
 
 	if (!init) goto cleanup;
 
+#ifdef CONFIG_XFRM
+	BUG_ON(ip_nat_decode_session != NULL);
+	ip_nat_decode_session = nat_decode_session;
+#endif
 	ret = ip_nat_rule_init();
 	if (ret < 0) {
 		printk("ip_nat_init: can't setup rules.\n");
-		goto cleanup_nothing;
+		goto cleanup_decode_session;
 	}
 	ret = nf_register_hook(&ip_nat_in_ops);
 	if (ret < 0) {
@@ -383,7 +425,11 @@ static int init_or_cleanup(int init)
 	nf_unregister_hook(&ip_nat_in_ops);
  cleanup_rule_init:
 	ip_nat_rule_cleanup();
- cleanup_nothing:
+ cleanup_decode_session:
+#ifdef CONFIG_XFRM
+	ip_nat_decode_session = NULL;
+	synchronize_net();
+#endif
 	return ret;
 }
 
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 421538a..8251a28 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -255,6 +255,7 @@ int raw_rcv(struct sock *sk, struct sk_b
 		kfree_skb(skb);
 		return NET_RX_DROP;
 	}
+	nf_reset(skb);
 
 	skb_push(skb, skb->data - skb->nh.raw);
 
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index c85819d..9efa1f2 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1247,6 +1247,7 @@ process:
 
 	if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
 		goto discard_and_relse;
+	nf_reset(skb);
 
 	if (sk_filter(sk, skb, 0))
 		goto discard_and_relse;
@@ -1269,6 +1270,7 @@ process:
 no_tcp_socket:
 	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
 		goto discard_it;
+	nf_reset(skb);
 
 	if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
 bad_packet:
@@ -1291,6 +1293,7 @@ do_time_wait:
 		inet_twsk_put((struct inet_timewait_sock *) sk);
 		goto discard_it;
 	}
+	nf_reset(skb);
 
 	if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
 		TCP_INC_STATS_BH(TCP_MIB_INERRS);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index e0bd101..cd58b0c 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1001,6 +1001,7 @@ static int udp_queue_rcv_skb(struct sock
 		kfree_skb(skb);
 		return -1;
 	}
+	nf_reset(skb);
 
 	if (up->encap_type) {
 		/*
@@ -1166,6 +1167,7 @@ int udp_rcv(struct sk_buff *skb)
 
 	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
 		goto drop;
+	nf_reset(skb);
 
 	/* No socket. Drop packet silently, if checksum is wrong */
 	if (udp_checksum_complete(skb))
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 28f3224..dea792e 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -243,6 +243,7 @@ int sctp_rcv(struct sk_buff *skb)
 
 	if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb, family))
 		goto discard_release;
+	nf_reset(skb);
 
 	ret = sk_filter(sk, skb, 1);
 	if (ret)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 29d1343..04465d8 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -22,6 +22,7 @@
 #include <linux/workqueue.h>
 #include <linux/notifier.h>
 #include <linux/netdevice.h>
+#include <linux/netfilter.h>
 #include <linux/module.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
@@ -937,6 +938,7 @@ int __xfrm_policy_check(struct sock *sk,
 
 	if (xfrm_decode_session(skb, &fl, family) < 0)
 		return 0;
+	nf_nat_decode_session(skb, &fl, family);
 
 	/* First, check used SA against their selectors. */
 	if (skb->sp) {

^ permalink raw reply related

* [PATCH 09/10]: [NETFILTER]: Redo policy lookups after NAT when neccessary
From: Patrick McHardy @ 2005-11-11  3:19 UTC (permalink / raw)
  To: Kernel Netdev Mailing List, Netfilter Development Mailinglist

[-- Attachment #1: 09.diff --]
[-- Type: text/x-patch, Size: 5200 bytes --]

[NETFILTER]: Redo policy lookups after NAT when neccessary

When NAT changes the key used for the xfrm lookup on the output
path the lookup needs to be redone.

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

---
commit d449eeda76508f14f27d76a84350e4069c968497
tree fa245e3599e04432ee1ef1e046eeef9c800553e3
parent 351bc1c8a9c5c5e4aa48c153f0050f0a8b979201
author Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 03:21:13 +0100
committer Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 03:21:13 +0100

 include/net/dst.h                      |    1 +
 include/net/ip.h                       |    1 +
 net/ipv4/ip_output.c                   |    6 ++++++
 net/ipv4/netfilter.c                   |    6 ++++--
 net/ipv4/netfilter/ip_nat_standalone.c |   27 +++++++++++++++++++++++++--
 net/ipv4/xfrm4_output.c                |    1 +
 6 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/include/net/dst.h b/include/net/dst.h
index 7eadd0c..4630e17 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -237,6 +237,7 @@ static inline int dst_output(struct sk_b
 }
 
 #if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
+extern int __ip_dst_output(struct sk_buff *skb);
 extern int ip_dst_output(struct sk_buff *skb);
 extern int ip6_dst_output(struct sk_buff *skb);
 #else
diff --git a/include/net/ip.h b/include/net/ip.h
index 9f09882..377036b 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -45,6 +45,7 @@ struct inet_skb_parm
 #define IPSKB_TRANSLATED	2
 #define IPSKB_FORWARDED		4
 #define IPSKB_XFRM_TUNNEL_SIZE	8
+#define IPSKB_XFRM_TRANSFORMED	16
 };
 
 struct ipcm_cookie
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index eb6906d..579877f 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -167,6 +167,12 @@ static inline int ip_finish_output3(stru
 	struct net_device *dev = dst->dev;
 	int hh_len = LL_RESERVED_SPACE(dev);
 
+#if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
+	/* Policy lookup after SNAT yielded a new policy */
+	if (dst->xfrm != NULL)
+		return __ip_dst_output(skb);
+#endif
+
 	/* Be paranoid, rather than too clever. */
 	if (unlikely(skb_headroom(skb) < hh_len && dev->hard_header)) {
 		struct sk_buff *skb2;
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 0f6616f..8fda96a 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -13,6 +13,7 @@
 #include <linux/ip.h>
 #include <net/route.h>
 #include <net/xfrm.h>
+#include <net/ip.h>
 
 /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
 int ip_route_me_harder(struct sk_buff **pskb)
@@ -61,7 +62,8 @@ int ip_route_me_harder(struct sk_buff **
 		return -1;
 
 #ifdef CONFIG_XFRM
-	if (xfrm_decode_session(*pskb, &fl, AF_INET) == 0)
+	if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) &&
+	    xfrm_decode_session(*pskb, &fl, AF_INET) == 0)
 		if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0))
 			return -1;
 #endif
@@ -85,7 +87,7 @@ int ip_route_me_harder(struct sk_buff **
 EXPORT_SYMBOL(ip_route_me_harder);
 
 #ifdef CONFIG_XFRM
-static inline int __ip_dst_output(struct sk_buff *skb)
+inline int __ip_dst_output(struct sk_buff *skb)
 {
 	int err;
 
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index ff24bac..e383b16 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -187,6 +187,10 @@ ip_nat_out(unsigned int hooknum,
 	   const struct net_device *out,
 	   int (*okfn)(struct sk_buff *))
 {
+	struct ip_conntrack *ct;
+	enum ip_conntrack_info ctinfo;
+	unsigned int ret;
+
 	/* root is playing with raw sockets. */
 	if ((*pskb)->len < sizeof(struct iphdr)
 	    || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
@@ -194,7 +198,21 @@ ip_nat_out(unsigned int hooknum,
 
 	WARN_ON((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET));
 
-	return ip_nat_fn(hooknum, pskb, in, out, okfn);
+	ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
+	if (ret != NF_DROP && ret != NF_STOLEN
+	    && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) {
+		enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+
+		if (ct->tuplehash[dir].tuple.src.ip !=
+		    ct->tuplehash[!dir].tuple.dst.ip
+#ifdef CONFIG_XFRM
+		    || ct->tuplehash[dir].tuple.src.u.all !=
+		       ct->tuplehash[!dir].tuple.dst.u.all
+#endif
+		    )
+			return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
+	}
+	return ret;
 }
 
 static unsigned int
@@ -219,7 +237,12 @@ ip_nat_local_fn(unsigned int hooknum,
 		enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 
 		if (ct->tuplehash[dir].tuple.dst.ip !=
-		    ct->tuplehash[!dir].tuple.src.ip)
+		    ct->tuplehash[!dir].tuple.src.ip
+#ifdef CONFIG_XFRM
+		    || ct->tuplehash[dir].tuple.dst.u.all !=
+		       ct->tuplehash[dir].tuple.src.u.all
+#endif
+		    )
 			return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
 	}
 	return ret;
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index c135746..9e49eeb 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -133,6 +133,7 @@ int xfrm4_output(struct sk_buff *skb)
 		err = -EHOSTUNREACH;
 		goto error_nolock;
 	}
+	IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
 	nf_reset(skb);
 	err = NET_XMIT_BYPASS;
 

^ permalink raw reply related

* [PATCH 08/10]: [NETFILTER]: Use conntrack information to determine if packet was NATed
From: Patrick McHardy @ 2005-11-11  3:19 UTC (permalink / raw)
  To: Kernel Netdev Mailing List, Netfilter Development Mailinglist

[-- Attachment #1: 08.diff --]
[-- Type: text/x-patch, Size: 2819 bytes --]

[NETFILTER]: Use conntrack information to determine if packet was NATed

Preparation for full IPsec support for NAT:

Use conntrack information instead of saving the saving and comparing
the addresses to determine if a packet was NATed and needs to be
rerouted to make it easier to extend the key.

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

---
commit 351bc1c8a9c5c5e4aa48c153f0050f0a8b979201
tree 9f8a0f9472ed609beba69bf653fa7833d61db339
parent 909b664477ab16fc04f2bf24ef92676117ccbc26
author Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 03:04:28 +0100
committer Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 03:04:28 +0100

 net/ipv4/netfilter/ip_nat_standalone.c |   34 ++++++++++++++++++--------------
 1 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index f0fff02..ff24bac 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -162,18 +162,20 @@ ip_nat_in(unsigned int hooknum,
           const struct net_device *out,
           int (*okfn)(struct sk_buff *))
 {
-	u_int32_t saddr, daddr;
+	struct ip_conntrack *ct;
+	enum ip_conntrack_info ctinfo;
 	unsigned int ret;
 
-	saddr = (*pskb)->nh.iph->saddr;
-	daddr = (*pskb)->nh.iph->daddr;
-
 	ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
 	if (ret != NF_DROP && ret != NF_STOLEN
-	    && ((*pskb)->nh.iph->saddr != saddr
-	        || (*pskb)->nh.iph->daddr != daddr)) {
-		dst_release((*pskb)->dst);
-		(*pskb)->dst = NULL;
+	    && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) {
+		enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+
+		if (ct->tuplehash[dir].tuple.src.ip !=
+		    ct->tuplehash[!dir].tuple.dst.ip) {
+			dst_release((*pskb)->dst);
+			(*pskb)->dst = NULL;
+		}
 	}
 	return ret;
 }
@@ -202,7 +204,8 @@ ip_nat_local_fn(unsigned int hooknum,
 		const struct net_device *out,
 		int (*okfn)(struct sk_buff *))
 {
-	u_int32_t saddr, daddr;
+	struct ip_conntrack *ct;
+	enum ip_conntrack_info ctinfo;
 	unsigned int ret;
 
 	/* root is playing with raw sockets. */
@@ -210,14 +213,15 @@ ip_nat_local_fn(unsigned int hooknum,
 	    || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
 		return NF_ACCEPT;
 
-	saddr = (*pskb)->nh.iph->saddr;
-	daddr = (*pskb)->nh.iph->daddr;
-
 	ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
 	if (ret != NF_DROP && ret != NF_STOLEN
-	    && ((*pskb)->nh.iph->saddr != saddr
-		|| (*pskb)->nh.iph->daddr != daddr))
-		return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
+	    && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) {
+		enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+
+		if (ct->tuplehash[dir].tuple.dst.ip !=
+		    ct->tuplehash[!dir].tuple.src.ip)
+			return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
+	}
 	return ret;
 }
 

^ permalink raw reply related

* [PATCH 07/10]: [NETFILTER]: Fix xfrm lookup in ip_route_me_harder
From: Patrick McHardy @ 2005-11-11  3:19 UTC (permalink / raw)
  To: Kernel Netdev Mailing List, Netfilter Development Mailinglist

[-- Attachment #1: 07.diff --]
[-- Type: text/x-patch, Size: 3082 bytes --]

[NETFILTER]: Fix xfrm lookup in ip_route_me_harder

ip_route_me_harder uses ip_route_input for non-local addresses, which
doesn't do a xfrm lookup, and doesn't use the port numbers for the
lookup for local addresses. Use xfrm_decode_session and do the lookup
manually.

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

---
commit 909b664477ab16fc04f2bf24ef92676117ccbc26
tree 7085763e2f28f37ffc7f5ce4af044e92f835d03e
parent d14a36982a14bb6695a6ce44fd4f3f4c9aaa6a0c
author Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 03:02:17 +0100
committer Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 03:02:17 +0100

 include/net/xfrm.h     |    2 +-
 net/ipv4/netfilter.c   |    7 ++++++-
 net/xfrm/xfrm_policy.c |    8 ++++----
 3 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 5beae1c..19d6aa0 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -644,7 +644,7 @@ static inline int xfrm6_policy_check(str
 	return xfrm_policy_check(sk, dir, skb, AF_INET6);
 }
 
-
+extern int xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family);
 extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
 
 static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 3c39296..0f6616f 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -34,7 +34,6 @@ int ip_route_me_harder(struct sk_buff **
 #ifdef CONFIG_IP_ROUTE_FWMARK
 		fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
 #endif
-		fl.proto = iph->protocol;
 		if (ip_route_output_key(&rt, &fl) != 0)
 			return -1;
 
@@ -61,6 +60,12 @@ int ip_route_me_harder(struct sk_buff **
 	if ((*pskb)->dst->error)
 		return -1;
 
+#ifdef CONFIG_XFRM
+	if (xfrm_decode_session(*pskb, &fl, AF_INET) == 0)
+		if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0))
+			return -1;
+#endif
+
 	/* Change in oif may mean change in hh_len. */
 	hh_len = (*pskb)->dst->dev->hard_header_len;
 	if (skb_headroom(*pskb) < hh_len) {
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 0db9e57..29d1343 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -906,8 +906,8 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, s
 	return start;
 }
 
-static int
-_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family)
+int xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
+                        unsigned short family)
 {
 	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
 
@@ -935,7 +935,7 @@ int __xfrm_policy_check(struct sock *sk,
 	struct xfrm_policy *pol;
 	struct flowi fl;
 
-	if (_decode_session(skb, &fl, family) < 0)
+	if (xfrm_decode_session(skb, &fl, family) < 0)
 		return 0;
 
 	/* First, check used SA against their selectors. */
@@ -1007,7 +1007,7 @@ int __xfrm_route_forward(struct sk_buff 
 {
 	struct flowi fl;
 
-	if (_decode_session(skb, &fl, family) < 0)
+	if (xfrm_decode_session(skb, &fl, family) < 0)
 		return 0;
 
 	return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0;

^ permalink raw reply related

* [PATCH 06/10]: [IPV4/6]: Make input netfilter IPsec processing symetrical to output
From: Patrick McHardy @ 2005-11-11  3:19 UTC (permalink / raw)
  To: Kernel Netdev Mailing List, Netfilter Development Mailinglist

[-- Attachment #1: 06.diff --]
[-- Type: text/x-patch, Size: 4872 bytes --]

[IPV4/6]: Make input netfilter IPsec processing symetrical to output

When the innermost transform uses transport mode the decapsulated
packet is not visible to netfilter. Pass the packet through
PRE_ROUTING->LOCAL_IN again before handing it to upper layer
protocols.

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

---
commit d14a36982a14bb6695a6ce44fd4f3f4c9aaa6a0c
tree f8d97c21b7d005bd23b37556691bc2026bd2f5cb
parent 193f15d5698b56a568f284a460ce38734ed84e24
author Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 02:32:53 +0100
committer Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 02:32:53 +0100

 include/linux/netfilter_ipv4.h |    2 +-
 include/net/ipv6.h             |    2 ++
 net/ipv4/netfilter.c           |   20 ++++++++++++++++++++
 net/ipv4/xfrm4_input.c         |   14 ++++++++++++++
 net/ipv6/ip6_input.c           |    2 +-
 net/ipv6/xfrm6_input.c         |   13 +++++++++++++
 6 files changed, 51 insertions(+), 2 deletions(-)

diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index fdc4a95..e9103fe 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -79,7 +79,7 @@ enum nf_ip_hook_priorities {
 
 #ifdef __KERNEL__
 extern int ip_route_me_harder(struct sk_buff **pskb);
-
+extern int ip_xfrm_transport_hook(struct sk_buff *skb);
 #endif /*__KERNEL__*/
 
 #endif /*__LINUX_IP_NETFILTER_H*/
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 65ec866..0a2abe0 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -353,6 +353,8 @@ extern int			ipv6_rcv(struct sk_buff *sk
 					 struct packet_type *pt,
 					 struct net_device *orig_dev);
 
+extern int			ip6_rcv_finish(struct sk_buff *skb);
+
 /*
  *	upper-layer output functions
  */
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index b93e7cd..3c39296 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -105,6 +105,26 @@ int ip_dst_output(struct sk_buff *skb)
 	return dst_output(skb);
 }
 EXPORT_SYMBOL(ip_dst_output);
+
+/*
+ * okfn for transport mode xfrm_input.c hook. Basically a copy of
+ * ip_rcv_finish without statistics and option parsing.
+ */
+int ip_xfrm_transport_hook(struct sk_buff *skb)
+{
+	struct iphdr *iph = skb->nh.iph;
+
+	if (likely(skb->dst == NULL)) {
+		int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
+		                         skb->dev);
+		if (unlikely(err))
+			goto drop;
+	}
+	return dst_input(skb);
+drop:
+	kfree_skb(skb);
+	return NET_RX_DROP;
+}
 #endif /* CONFIG_XFRM */
 
 /*
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 2d3849c..d90cd93 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -11,6 +11,8 @@
 
 #include <linux/module.h>
 #include <linux/string.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
 #include <net/inet_ecn.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
@@ -137,6 +139,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb,
 	memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state));
 	skb->sp->len += xfrm_nr;
 
+	nf_reset(skb);
+
 	if (decaps) {
 		if (!(skb->dev->flags&IFF_LOOPBACK)) {
 			dst_release(skb->dst);
@@ -145,7 +149,17 @@ int xfrm4_rcv_encap(struct sk_buff *skb,
 		netif_rx(skb);
 		return 0;
 	} else {
+#ifdef CONFIG_NETFILTER
+		__skb_push(skb, skb->data - skb->nh.raw);
+		skb->nh.iph->tot_len = htons(skb->len);
+		ip_send_check(skb->nh.iph);
+
+		NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
+		        ip_xfrm_transport_hook);
+		return 0;
+#else
 		return -skb->nh.iph->protocol;
+#endif
 	}
 
 drop_unlock:
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index c3d32a2..4656edf 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -48,7 +48,7 @@
 
 
 
-static inline int ip6_rcv_finish( struct sk_buff *skb) 
+inline int ip6_rcv_finish(struct sk_buff *skb) 
 {
 	if (skb->dst == NULL)
 		ip6_route_input(skb);
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 28c29d7..9987416 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -11,6 +11,8 @@
 
 #include <linux/module.h>
 #include <linux/string.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv6.h>
 #include <net/dsfield.h>
 #include <net/inet_ecn.h>
 #include <net/ip.h>
@@ -121,6 +123,8 @@ int xfrm6_rcv_spi(struct sk_buff **pskb,
 	skb->sp->len += xfrm_nr;
 	skb->ip_summed = CHECKSUM_NONE;
 
+	nf_reset(skb);
+
 	if (decaps) {
 		if (!(skb->dev->flags&IFF_LOOPBACK)) {
 			dst_release(skb->dst);
@@ -129,7 +133,16 @@ int xfrm6_rcv_spi(struct sk_buff **pskb,
 		netif_rx(skb);
 		return -1;
 	} else {
+#ifdef CONFIG_NETFILTER
+		skb->nh.ipv6h->payload_len = htons(skb->len);
+		__skb_push(skb, skb->data - skb->nh.raw);
+
+		NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
+		        ip6_rcv_finish);
+		return -1;
+#else
 		return 1;
+#endif
 	}
 
 drop_unlock:

^ permalink raw reply related

* [PATCH 05/10]: [IPV4/6]: Netfilter IPsec output hooks
From: Patrick McHardy @ 2005-11-11  3:19 UTC (permalink / raw)
  To: Kernel Netdev Mailing List, Netfilter Development Mailinglist

[-- Attachment #1: 05.diff --]
[-- Type: text/x-patch, Size: 4598 bytes --]

[IPV4/6]: Netfilter IPsec output hooks

Add alternative ip_dst_output/ip6_dst_output functions to call
netfilter hooks between xfrm transforms. Packets visit
FORWARD/LOCAL_OUT->POST_ROUTING before encapsulation and
LOCAL_OUT->POST_ROUTING after each tunnel mode transform.

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

---
commit 193f15d5698b56a568f284a460ce38734ed84e24
tree f6032d5c28c630af1fc8a55f0e77eca749b4e87f
parent acfa963b047cbda6a8350f122da90f1e84bf4938
author Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 02:15:08 +0100
committer Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 02:15:08 +0100

 include/net/dst.h       |    5 +++++
 net/ipv4/netfilter.c    |   31 ++++++++++++++++++++++++++++++-
 net/ipv4/xfrm4_output.c |    1 +
 net/ipv6/netfilter.c    |   29 +++++++++++++++++++++++++++++
 net/ipv6/xfrm6_output.c |    1 +
 5 files changed, 66 insertions(+), 1 deletions(-)

diff --git a/include/net/dst.h b/include/net/dst.h
index 4886f25..7eadd0c 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -236,8 +236,13 @@ static inline int dst_output(struct sk_b
 	}
 }
 
+#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
+extern int ip_dst_output(struct sk_buff *skb);
+extern int ip6_dst_output(struct sk_buff *skb);
+#else
 #define ip_dst_output	dst_output
 #define ip6_dst_output	dst_output
+#endif
 
 /* Input packet from network to transport.  */
 static inline int dst_input(struct sk_buff *skb)
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index ae0779d..b93e7cd 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -10,8 +10,9 @@
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/icmp.h>
-#include <net/route.h>
 #include <linux/ip.h>
+#include <net/route.h>
+#include <net/xfrm.h>
 
 /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
 int ip_route_me_harder(struct sk_buff **pskb)
@@ -78,6 +79,34 @@ int ip_route_me_harder(struct sk_buff **
 }
 EXPORT_SYMBOL(ip_route_me_harder);
 
+#ifdef CONFIG_XFRM
+static inline int __ip_dst_output(struct sk_buff *skb)
+{
+	int err;
+
+	do {
+		err = skb->dst->output(skb);
+
+		if (likely(err == 0))
+			return err;
+		if (unlikely(err != NET_XMIT_BYPASS))
+			return err;
+	} while (skb->dst->xfrm && !skb->dst->xfrm->props.mode);
+
+	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dst->dev,
+	               ip_dst_output);
+}
+
+int ip_dst_output(struct sk_buff *skb)
+{
+	if (skb->dst->xfrm != NULL)
+		return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
+		               skb->dst->dev, __ip_dst_output);
+	return dst_output(skb);
+}
+EXPORT_SYMBOL(ip_dst_output);
+#endif /* CONFIG_XFRM */
+
 /*
  * Extra routing may needed on local out, as the QUEUE target never
  * returns control to the table.
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 66620a9..c135746 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -133,6 +133,7 @@ int xfrm4_output(struct sk_buff *skb)
 		err = -EHOSTUNREACH;
 		goto error_nolock;
 	}
+	nf_reset(skb);
 	err = NET_XMIT_BYPASS;
 
 out_exit:
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index f8626eb..06b275e 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -10,6 +10,7 @@
 #include <net/dst.h>
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
+#include <net/xfrm.h>
 
 int ip6_route_me_harder(struct sk_buff *skb)
 {
@@ -41,6 +42,34 @@ int ip6_route_me_harder(struct sk_buff *
 }
 EXPORT_SYMBOL(ip6_route_me_harder);
 
+#ifdef CONFIG_XFRM
+static inline int __ip6_dst_output(struct sk_buff *skb)
+{
+	int err;
+	
+	do {
+		err = skb->dst->output(skb);
+
+		if (likely(err == 0))
+			return err;
+		if (unlikely(err != NET_XMIT_BYPASS))
+			return err;
+	} while (skb->dst->xfrm && !skb->dst->xfrm->props.mode);
+
+	return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev,
+	               ip6_dst_output);
+}
+
+int ip6_dst_output(struct sk_buff *skb)
+{
+	if (skb->dst->xfrm != NULL)
+		return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL,
+		               skb->dst->dev, __ip6_dst_output);
+	return dst_output(skb);
+}
+EXPORT_SYMBOL(ip6_dst_output);
+#endif /* CONFIG_XFRM */
+
 /*
  * Extra routing may needed on local out, as the QUEUE target never
  * returns control to the table.
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 6b98677..a566d25 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -132,6 +132,7 @@ int xfrm6_output(struct sk_buff *skb)
 		err = -EHOSTUNREACH;
 		goto error_nolock;
 	}
+	nf_reset(skb);
 	err = NET_XMIT_BYPASS;
 
 out_exit:

^ permalink raw reply related

* [PATCH 04/10]: [IPV6]: Replace dst_output by ip6_dst_output
From: Patrick McHardy @ 2005-11-11  3:19 UTC (permalink / raw)
  To: Kernel Netdev Mailing List, Netfilter Development Mailinglist

[-- Attachment #1: 04.diff --]
[-- Type: text/x-patch, Size: 5771 bytes --]

[IPV6]: Replace dst_output by ip6_dst_output

Preparation for netfilter IPsec support.

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

---
commit acfa963b047cbda6a8350f122da90f1e84bf4938
tree b545b44a3074377283a2b491a5f7ae60b19ed914
parent 9271210c937a55a2e5dcba05df078e1c43b81d6c
author Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 02:11:14 +0100
committer Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 02:11:14 +0100

 include/net/dst.h                |    1 +
 net/ipv6/ip6_input.c             |    4 ++--
 net/ipv6/ip6_output.c            |    7 ++++---
 net/ipv6/ip6_tunnel.c            |    2 +-
 net/ipv6/ndisc.c                 |    8 ++++----
 net/ipv6/netfilter/ip6t_REJECT.c |    2 +-
 net/ipv6/raw.c                   |    2 +-
 7 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/include/net/dst.h b/include/net/dst.h
index 07f552b..4886f25 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -237,6 +237,7 @@ static inline int dst_output(struct sk_b
 }
 
 #define ip_dst_output	dst_output
+#define ip6_dst_output	dst_output
 
 /* Input packet from network to transport.  */
 static inline int dst_input(struct sk_buff *skb)
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 6e34804..c3d32a2 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -250,9 +250,9 @@ int ip6_mc_input(struct sk_buff *skb)
 			
 			if (deliver) {
 				skb2 = skb_clone(skb, GFP_ATOMIC);
-				dst_output(skb2);
+				ip6_dst_output(skb2);
 			} else {
-				dst_output(skb);
+				ip6_dst_output(skb);
 				return 0;
 			}
 		}
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 614296a..14e00f4 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -230,7 +230,7 @@ int ip6_xmit(struct sock *sk, struct sk_
 	if ((skb->len <= mtu) || ipfragok) {
 		IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
 		return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev,
-				dst_output);
+				ip6_dst_output);
 	}
 
 	if (net_ratelimit())
@@ -308,7 +308,7 @@ static int ip6_call_ra_chain(struct sk_b
 
 static inline int ip6_forward_finish(struct sk_buff *skb)
 {
-	return dst_output(skb);
+	return ip6_dst_output(skb);
 }
 
 int ip6_forward(struct sk_buff *skb)
@@ -1176,7 +1176,8 @@ int ip6_push_pending_frames(struct sock 
 
 	skb->dst = dst_clone(&rt->u.dst);
 	IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);	
-	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output);
+	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev,
+	              ip6_dst_output);
 	if (err) {
 		if (err > 0)
 			err = np->recverr ? net_xmit_errno(err) : 0;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index cf94372..0642cf1 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -745,7 +745,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str
 	nf_reset(skb);
 	pkt_len = skb->len;
 	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, 
-		      skb->dst->dev, dst_output);
+		      skb->dst->dev, ip6_dst_output);
 
 	if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) {
 		stats->tx_bytes += pkt_len;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 305d9ee..287170f 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -499,7 +499,7 @@ static void ndisc_send_na(struct net_dev
 	skb->dst = dst;
 	idev = in6_dev_get(dst->dev);
 	IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
-	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
+	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_dst_output);
 	if (!err) {
 		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS);
 		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
@@ -582,7 +582,7 @@ void ndisc_send_ns(struct net_device *de
 	skb->dst = dst;
 	idev = in6_dev_get(dst->dev);
 	IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
-	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
+	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_dst_output);
 	if (!err) {
 		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORSOLICITS);
 		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
@@ -654,7 +654,7 @@ void ndisc_send_rs(struct net_device *de
 	skb->dst = dst;
 	idev = in6_dev_get(dst->dev);
 	IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);	
-	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
+	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_dst_output);
 	if (!err) {
 		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTROUTERSOLICITS);
 		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
@@ -1438,7 +1438,7 @@ void ndisc_send_redirect(struct sk_buff 
 	buff->dst = dst;
 	idev = in6_dev_get(dst->dev);
 	IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
-	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output);
+	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, ip6_dst_output);
 	if (!err) {
 		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTREDIRECTS);
 		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index b03e87a..8579eaa 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -161,7 +161,7 @@ static void send_reset(struct sk_buff *o
 						   sizeof(struct tcphdr), 0));
 
 	NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
-		dst_output);
+		ip6_dst_output);
 }
 
 static inline void
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index a1265a3..130684c 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -579,7 +579,7 @@ static int rawv6_send_hdrinc(struct sock
 
 	IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);		
 	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-		      dst_output);
+		      ip6_dst_output);
 	if (err > 0)
 		err = np->recverr ? net_xmit_errno(err) : 0;
 	if (err)

^ permalink raw reply related

* [PATCH 03/10]: [IPV4]: Replace dst_output by ip_dst_output
From: Patrick McHardy @ 2005-11-11  3:19 UTC (permalink / raw)
  To: Kernel Netdev Mailing List, Netfilter Development Mailinglist

[-- Attachment #1: 03.diff --]
[-- Type: text/x-patch, Size: 5325 bytes --]

[IPV4]: Replace dst_output by ip_dst_output

Preparation for netfilter IPsec support.

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

---
commit 9271210c937a55a2e5dcba05df078e1c43b81d6c
tree 7f510d89a5245630e33e429c9d690de0aa2b05c9
parent dc924f62fd0611bb349e398c80ce3ffa5c3a9025
author Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 02:10:58 +0100
committer Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 02:10:58 +0100

 include/net/dst.h               |    2 ++
 include/net/ipip.h              |    2 +-
 net/ipv4/igmp.c                 |    4 ++--
 net/ipv4/ip_forward.c           |    2 +-
 net/ipv4/ip_output.c            |    6 +++---
 net/ipv4/ipmr.c                 |    2 +-
 net/ipv4/ipvs/ip_vs_xmit.c      |    2 +-
 net/ipv4/netfilter/ipt_REJECT.c |    2 +-
 net/ipv4/raw.c                  |    2 +-
 9 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/include/net/dst.h b/include/net/dst.h
index 6c196a5..07f552b 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -236,6 +236,8 @@ static inline int dst_output(struct sk_b
 	}
 }
 
+#define ip_dst_output	dst_output
+
 /* Input packet from network to transport.  */
 static inline int dst_input(struct sk_buff *skb)
 {
diff --git a/include/net/ipip.h b/include/net/ipip.h
index f490c3c..b267496 100644
--- a/include/net/ipip.h
+++ b/include/net/ipip.h
@@ -34,7 +34,7 @@ struct ip_tunnel
 	ip_select_ident(iph, &rt->u.dst, NULL);				\
 	ip_send_check(iph);						\
 									\
-	err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output);\
+	err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, ip_dst_output);\
 	if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) {		\
 		stats->tx_bytes += pkt_len;				\
 		stats->tx_packets++;					\
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index c6247fc..7c6bf44 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -343,7 +343,7 @@ static int igmpv3_sendpack(struct sk_buf
 	pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
 
 	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
-		       dst_output);
+		       ip_dst_output);
 }
 
 static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
@@ -674,7 +674,7 @@ static int igmp_send_report(struct in_de
 	ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
 
 	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-		       dst_output);
+		       ip_dst_output);
 }
 
 static void igmp_gq_timer_expire(unsigned long data)
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index 0923add..486355d 100644
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@ -51,7 +51,7 @@ static inline int ip_forward_finish(stru
 	if (unlikely(opt->optlen))
 		ip_forward_options(skb);
 
-	return dst_output(skb);
+	return ip_dst_output(skb);
 }
 
 int ip_forward(struct sk_buff *skb)
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index b0487a2..eb6906d 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -155,7 +155,7 @@ int ip_build_and_send_pkt(struct sk_buff
 
 	/* Send it out. */
 	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-		       dst_output);
+		       ip_dst_output);
 }
 
 EXPORT_SYMBOL_GPL(ip_build_and_send_pkt);
@@ -373,7 +373,7 @@ packet_routed:
 	skb->priority = sk->sk_priority;
 
 	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-		       dst_output);
+		       ip_dst_output);
 
 no_route:
 	IP_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
@@ -1264,7 +1264,7 @@ int ip_push_pending_frames(struct sock *
 
 	/* Netfilter gets whole the not fragmented skb. */
 	err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, 
-		      skb->dst->dev, dst_output);
+		      skb->dst->dev, ip_dst_output);
 	if (err) {
 		if (err > 0)
 			err = inet->recverr ? net_xmit_errno(err) : 0;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 302b7eb..40af27f 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1125,7 +1125,7 @@ static inline int ipmr_forward_finish(st
 	if (unlikely(opt->optlen))
 		ip_forward_options(skb);
 
-	return dst_output(skb);
+	return ip_dst_output(skb);
 }
 
 /*
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
index 3b87482..b66c3da 100644
--- a/net/ipv4/ipvs/ip_vs_xmit.c
+++ b/net/ipv4/ipvs/ip_vs_xmit.c
@@ -130,7 +130,7 @@ do {							\
 	(skb)->ipvs_property = 1;			\
 	(skb)->ip_summed = CHECKSUM_NONE;		\
 	NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, (skb), NULL,	\
-		(rt)->u.dst.dev, dst_output);		\
+		(rt)->u.dst.dev, ip_dst_output);	\
 } while (0)
 
 
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index f057025..55b601b 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -220,7 +220,7 @@ static void send_reset(struct sk_buff *o
 	nf_ct_attach(nskb, oldskb);
 
 	NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
-		dst_output);
+		ip_dst_output);
 	return;
 
  free_nskb:
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 4b0d7e4..421538a 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -313,7 +313,7 @@ static int raw_send_hdrinc(struct sock *
 	}
 
 	err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-		      dst_output);
+		      ip_dst_output);
 	if (err > 0)
 		err = inet->recverr ? net_xmit_errno(err) : 0;
 	if (err)

^ permalink raw reply related

* [PATCH 02/10]: [NETFILTER]: Defer fragmentation in ip_output when connection tracking is used
From: Patrick McHardy @ 2005-11-11  3:19 UTC (permalink / raw)
  To: Kernel Netdev Mailing List, Netfilter Development Mailinglist

[-- Attachment #1: 02.diff --]
[-- Type: text/x-patch, Size: 6732 bytes --]

[NETFILTER]: Defer fragmentation in ip_output when connection tracking is used

This allows to get rid of the okfn use in ip_refrag and save the useless
fragmentation/defragmentation step when NAT is used.

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

---
commit dc924f62fd0611bb349e398c80ce3ffa5c3a9025
tree 7eb988fef33fa008d1a64fceaee0b310bba30162
parent e718fcad3d24ada7b56fdca8dd234c9ba7459219
author Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 02:10:19 +0100
committer Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 02:10:19 +0100

 include/linux/netfilter.h                    |    6 ++++++
 include/net/ip.h                             |    1 -
 net/ipv4/ip_output.c                         |   18 ++++++++++++++---
 net/ipv4/netfilter/ip_conntrack_standalone.c |   27 +-------------------------
 net/ipv4/netfilter/ip_nat_standalone.c       |   19 ++----------------
 5 files changed, 24 insertions(+), 47 deletions(-)

diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index be365e7..4c89c2c 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -261,6 +261,11 @@ struct nf_queue_rerouter {
 extern int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer);
 extern int nf_unregister_queue_rerouter(int pf);
 
+static inline int nf_defer_fragment(struct sk_buff *skb)
+{
+	return skb->nfct != NULL;
+}
+
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
 extern struct proc_dir_entry *proc_net_netfilter;
@@ -269,6 +274,7 @@ extern struct proc_dir_entry *proc_net_n
 #else /* !CONFIG_NETFILTER */
 #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
 static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
+static inline int nf_defer_fragment(struct sk_buff *skb) { return 0; }
 #endif /*CONFIG_NETFILTER*/
 
 #endif /*__KERNEL__*/
diff --git a/include/net/ip.h b/include/net/ip.h
index e4563bb..9f09882 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -310,7 +310,6 @@ enum ip_defrag_users
 	IP_DEFRAG_CALL_RA_CHAIN,
 	IP_DEFRAG_CONNTRACK_IN,
 	IP_DEFRAG_CONNTRACK_OUT,
-	IP_DEFRAG_NAT_OUT,
 	IP_DEFRAG_VS_IN,
 	IP_DEFRAG_VS_OUT,
 	IP_DEFRAG_VS_FWD
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 1775823..b0487a2 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -160,7 +160,7 @@ int ip_build_and_send_pkt(struct sk_buff
 
 EXPORT_SYMBOL_GPL(ip_build_and_send_pkt);
 
-static inline int ip_finish_output2(struct sk_buff *skb)
+static inline int ip_finish_output3(struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb->dst;
 	struct hh_cache *hh = dst->hh;
@@ -200,6 +200,17 @@ static inline int ip_finish_output2(stru
 	return -EINVAL;
 }
 
+static inline int ip_finish_output2(struct sk_buff *skb)
+{
+#ifdef CONFIG_NETFILTER
+	/* defered fragmentation when connection tracking is used */
+	if (skb->len > dst_mtu(skb->dst) &&
+	    !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
+		return ip_fragment(skb, ip_finish_output3);
+#endif
+	return ip_finish_output3(skb);
+}
+
 static inline int ip_finish_output(struct sk_buff *skb)
 {
 	struct net_device *dev = skb->dst->dev;
@@ -265,7 +276,7 @@ int ip_mc_output(struct sk_buff *skb)
 				newskb->dev, ip_dev_loopback_xmit);
 	}
 
-	if (skb->len > dst_mtu(&rt->u.dst))
+	if (skb->len > dst_mtu(&rt->u.dst) && !nf_defer_fragment(skb))
 		return ip_fragment(skb, ip_finish_output);
 	else
 		return ip_finish_output(skb);
@@ -276,7 +287,8 @@ int ip_output(struct sk_buff *skb)
 	IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
 
 	if (skb->len > dst_mtu(skb->dst) &&
-		!(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
+	    !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size) &&
+	    !nf_defer_fragment(skb))
 		return ip_fragment(skb, ip_finish_output);
 	else
 		return ip_finish_output(skb);
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index dd476b1..381650d 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -450,30 +450,6 @@ static unsigned int ip_conntrack_defrag(
 	return NF_ACCEPT;
 }
 
-static unsigned int ip_refrag(unsigned int hooknum,
-			      struct sk_buff **pskb,
-			      const struct net_device *in,
-			      const struct net_device *out,
-			      int (*okfn)(struct sk_buff *))
-{
-	struct rtable *rt = (struct rtable *)(*pskb)->dst;
-
-	/* We've seen it coming out the other side: confirm */
-	if (ip_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)
-		return NF_DROP;
-
-	/* Local packets are never produced too large for their
-	   interface.  We degfragment them at LOCAL_OUT, however,
-	   so we have to refragment them here. */
-	if ((*pskb)->len > dst_mtu(&rt->u.dst) &&
-	    !skb_shinfo(*pskb)->tso_size) {
-		/* No hook can be after us, so this should be OK. */
-		ip_fragment(*pskb, okfn);
-		return NF_STOLEN;
-	}
-	return NF_ACCEPT;
-}
-
 static unsigned int ip_conntrack_local(unsigned int hooknum,
 				       struct sk_buff **pskb,
 				       const struct net_device *in,
@@ -541,9 +517,8 @@ static struct nf_hook_ops ip_conntrack_h
 	.priority	= NF_IP_PRI_CONNTRACK_HELPER,
 };
 
-/* Refragmenter; last chance. */
 static struct nf_hook_ops ip_conntrack_out_ops = {
-	.hook		= ip_refrag,
+	.hook		= ip_confirm,
 	.owner		= THIS_MODULE,
 	.pf		= PF_INET,
 	.hooknum	= NF_IP_POST_ROUTING,
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 30cd4e1..f0fff02 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -69,7 +69,7 @@ ip_nat_fn(unsigned int hooknum,
 	enum ip_nat_manip_type maniptype = HOOK2MANIP(hooknum);
 
 	/* We never see fragments: conntrack defrags on pre-routing
-	   and local-out, and ip_nat_out protects post-routing. */
+	   and local-out. */
 	IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off
 		       & htons(IP_MF|IP_OFFSET)));
 
@@ -190,22 +190,7 @@ ip_nat_out(unsigned int hooknum,
 	    || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
 		return NF_ACCEPT;
 
-	/* We can hit fragment here; forwarded packets get
-	   defragmented by connection tracking coming in, then
-	   fragmented (grr) by the forward code.
-
-	   In future: If we have nfct != NULL, AND we have NAT
-	   initialized, AND there is no helper, then we can do full
-	   NAPT on the head, and IP-address-only NAT on the rest.
-
-	   I'm starting to have nightmares about fragments.  */
-
-	if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
-		*pskb = ip_ct_gather_frags(*pskb, IP_DEFRAG_NAT_OUT);
-
-		if (!*pskb)
-			return NF_STOLEN;
-	}
+	WARN_ON((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET));
 
 	return ip_nat_fn(hooknum, pskb, in, out, okfn);
 }

^ permalink raw reply related

* [PATCH 01/10]: [NETFILTER]: Remove okfn usage in ip_vs_core.c
From: Patrick McHardy @ 2005-11-11  3:19 UTC (permalink / raw)
  To: Kernel Netdev Mailing List, Netfilter Development Mailinglist

[-- Attachment #1: 01.diff --]
[-- Type: text/x-patch, Size: 1086 bytes --]

[NETFILTER]: Remove okfn usage in ip_vs_core.c

okfn should only be used from different contexts to avoid deep
call stacks, i.e. by nf_queue.

Acked-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit e718fcad3d24ada7b56fdca8dd234c9ba7459219
tree 0f067bbacbeb03439707940a1ad7b504c8251187
parent 0bbacc402e67abca8794a8401c1621dc0c0202e9
author Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 02:09:52 +0100
committer Patrick McHardy <kaber@trash.net> Fri, 11 Nov 2005 02:09:52 +0100

 net/ipv4/ipvs/ip_vs_core.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 981cc32..7b13722 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -532,11 +532,8 @@ static unsigned int ip_vs_post_routing(u
 {
 	if (!((*pskb)->ipvs_property))
 		return NF_ACCEPT;
-
 	/* The packet was sent from IPVS, exit this chain */
-	(*okfn)(*pskb);
-
-	return NF_STOLEN;
+	return NF_STOP;
 }
 
 u16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)

^ permalink raw reply related

* [PATCH 00/10]: Netfilter IPsec support
From: Patrick McHardy @ 2005-11-11  3:18 UTC (permalink / raw)
  To: Kernel Netdev Mailing List, Netfilter Development Mailinglist

This is the latest set patches for netfilter IPsec support.
The use of netif_rx for the innermost SA if it used transport
mode has been replaced by explicit NF_HOOK calls in
xfrm{4,6}_input.c.

[NETFILTER]: Remove okfn usage in ip_vs_core.c
[NETFILTER]: Defer fragmentation in ip_output when connection tracking 
is used
[IPV4]: Replace dst_output by ip_dst_output
[IPV6]: Replace dst_output by ip6_dst_output
[IPV4/6]: Netfilter IPsec output hooks
[IPV4/6]: Make input netfilter IPsec processing symetrical to output
[NETFILTER]: Fix xfrm lookup in ip_route_me_harder
[NETFILTER]: Use conntrack information to determine if packet was NATed
[NETFILTER]: Redo policy lookups after NAT when neccessary
[NETFILTER]: Handle NAT in IPsec policy checks

^ permalink raw reply

* [patch 7/7] s390: mail address changed
From: Frank Pavlic @ 2005-11-10 12:51 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linux-kernel

[patch 7/7] s390: mail address changed 

From: Frank Pavlic <fpavlic@de.ibm.com>
	- mail address changed to fpavlic@de.ibm.com
	
Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com>

diffstat:
 lcs.c       |    4 ++--
 qeth_main.c |    4 ++--
 qeth_mpc.c  |    2 +-
 qeth_mpc.h  |    2 +-
 qeth_sys.c  |    2 +-
 qeth_tso.h  |    2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)

diff -Naupr orig/drivers/s390/net/lcs.c linux-patched/drivers/s390/net/lcs.c
--- orig/drivers/s390/net/lcs.c	2005-11-10 13:11:18.000000000 +0100
+++ linux-patched/drivers/s390/net/lcs.c	2005-11-10 13:07:11.000000000 +0100
@@ -8,7 +8,7 @@
  *    Author(s): Original Code written by
  *			  DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  *		 Rewritten by
- *			  Frank Pavlic (pavlic@de.ibm.com) and
+ *			  Frank Pavlic (fpavlic@de.ibm.com) and
  *		 	  Martin Schwidefsky <schwidefsky@de.ibm.com>
  *
  *    $Revision: 1.99 $	 $Date: 2005/05/11 08:10:17 $
@@ -2342,6 +2342,6 @@ __exit lcs_cleanup_module(void)
 module_init(lcs_init_module);
 module_exit(lcs_cleanup_module);
 
-MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>");
+MODULE_AUTHOR("Frank Pavlic <fpavlic@de.ibm.com>");
 MODULE_LICENSE("GPL");
 
diff -Naupr orig/drivers/s390/net/qeth_main.c linux-patched/drivers/s390/net/qeth_main.c
--- orig/drivers/s390/net/qeth_main.c	2005-11-10 13:13:21.000000000 +0100
+++ linux-patched/drivers/s390/net/qeth_main.c	2005-11-10 13:07:56.000000000 +0100
@@ -9,7 +9,7 @@
  *    Author(s): Original Code written by
  *			  Utz Bacher (utz.bacher@de.ibm.com)
  *		 Rewritten by
- *			  Frank Pavlic (pavlic@de.ibm.com) and
+ *			  Frank Pavlic (fpavlic@de.ibm.com) and
  *		 	  Thomas Spatzier <tspat@de.ibm.com>
  *
  *    $Revision: 1.242 $	 $Date: 2005/05/04 20:19:18 $
@@ -8715,7 +8715,7 @@ EXPORT_SYMBOL(qeth_osn_deregister);
 EXPORT_SYMBOL(qeth_osn_assist);
 module_init(qeth_init);
 module_exit(qeth_exit);
-MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>");
+MODULE_AUTHOR("Frank Pavlic <fpavlic@de.ibm.com>");
 MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \
 		                      "Copyright 2000,2003 IBM Corporation\n");
 
diff -Naupr orig/drivers/s390/net/qeth_mpc.c linux-patched/drivers/s390/net/qeth_mpc.c
--- orig/drivers/s390/net/qeth_mpc.c	2005-11-10 13:11:18.000000000 +0100
+++ linux-patched/drivers/s390/net/qeth_mpc.c	2005-11-10 13:08:05.000000000 +0100
@@ -4,7 +4,7 @@
  * Linux on zSeries OSA Express and HiperSockets support
  *
  * Copyright 2000,2003 IBM Corporation
- * Author(s): Frank Pavlic <pavlic@de.ibm.com>
+ * Author(s): Frank Pavlic <fpavlic@de.ibm.com>
  * 	      Thomas Spatzier <tspat@de.ibm.com>
  *
  */
diff -Naupr orig/drivers/s390/net/qeth_mpc.h linux-patched/drivers/s390/net/qeth_mpc.h
--- orig/drivers/s390/net/qeth_mpc.h	2005-11-10 13:13:21.000000000 +0100
+++ linux-patched/drivers/s390/net/qeth_mpc.h	2005-11-10 13:08:19.000000000 +0100
@@ -6,7 +6,7 @@
  * Copyright 2000,2003 IBM Corporation
  * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
  *            Thomas Spatzier <tspat@de.ibm.com>
- *            Frank Pavlic <pavlic@de.ibm.com>
+ *            Frank Pavlic <fpavlic@de.ibm.com>
  *
  */
 #ifndef __QETH_MPC_H__
diff -Naupr orig/drivers/s390/net/qeth_sys.c linux-patched/drivers/s390/net/qeth_sys.c
--- orig/drivers/s390/net/qeth_sys.c	2005-11-10 13:12:52.000000000 +0100
+++ linux-patched/drivers/s390/net/qeth_sys.c	2005-11-10 13:08:30.000000000 +0100
@@ -8,7 +8,7 @@
  * Copyright 2000,2003 IBM Corporation
  *
  * Author(s): Thomas Spatzier <tspat@de.ibm.com>
- * 	      Frank Pavlic <pavlic@de.ibm.com>
+ * 	      Frank Pavlic <fpavlic@de.ibm.com>
  *
  */
 #include <linux/list.h>
diff -Naupr orig/drivers/s390/net/qeth_tso.h linux-patched/drivers/s390/net/qeth_tso.h
--- orig/drivers/s390/net/qeth_tso.h	2005-11-10 13:11:18.000000000 +0100
+++ linux-patched/drivers/s390/net/qeth_tso.h	2005-11-10 13:08:43.000000000 +0100
@@ -5,7 +5,7 @@
  *
  * Copyright 2004 IBM Corporation
  *
- *    Author(s): Frank Pavlic <pavlic@de.ibm.com>
+ *    Author(s): Frank Pavlic <fpavlic@de.ibm.com>
  *
  *    $Revision: 1.7 $	 $Date: 2005/05/04 20:19:18 $
  *

^ permalink raw reply

* [patch 6/7] s390: introduce guestLan sniffer support in qeth
From: Frank Pavlic @ 2005-11-10 12:51 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linux-kernel

[patch 6/7] s390: introduce guestLan sniffer support in qeth

From: Peter Tiedemann  <ptiedem@de.ibm.com>
	- introduce guestLan sniffer support in qeth	
	  feature allows a linux in a virtual machine 
	  guest to become a network LAN sniffer, 
	  monitoring and recording the networking traffic 
	  within an entire guestLan.

Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com>

diffstat:
 qeth.h      |    2 +
 qeth_main.c |   93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qeth_mpc.h  |   11 ++++---
 3 files changed, 102 insertions(+), 4 deletions(-)

diff -Naupr orig/drivers/s390/net/qeth.h patched-linux/drivers/s390/net/qeth.h
--- orig/drivers/s390/net/qeth.h	2005-11-09 20:49:36.000000000 +0100
+++ patched-linux/drivers/s390/net/qeth.h	2005-11-09 20:52:27.000000000 +0100
@@ -750,6 +750,7 @@ struct qeth_card_info {
 	int unique_id;
 	struct qeth_card_blkt blkt;
 	__u32 csum_mask;
+	enum qeth_ipa_promisc_modes promisc_mode;
 };
 
 struct qeth_card_options {
@@ -776,6 +777,7 @@ struct qeth_card_options {
 enum qeth_threads {
 	QETH_SET_IP_THREAD  = 1,
 	QETH_RECOVER_THREAD = 2,
+	QETH_SET_PROMISC_MODE_THREAD = 4,
 };
 
 struct qeth_osn_info {
diff -Naupr orig/drivers/s390/net/qeth_main.c patched-linux/drivers/s390/net/qeth_main.c
--- orig/drivers/s390/net/qeth_main.c	2005-11-09 20:49:36.000000000 +0100
+++ patched-linux/drivers/s390/net/qeth_main.c	2005-11-09 20:50:03.000000000 +0100
@@ -160,6 +160,9 @@ static void
 qeth_set_multicast_list(struct net_device *);
 
 static void
+qeth_setadp_promisc_mode(struct qeth_card *);
+
+static void
 qeth_notify_processes(void)
 {
 	/*notify all  registered processes */
@@ -965,6 +968,24 @@ qeth_register_ip_addresses(void *ptr)
 	return 0;
 }
 
+/*
+ * Drive the SET_PROMISC_MODE thread
+ */
+static int
+qeth_set_promisc_mode(void *ptr)
+{
+	struct qeth_card *card = (struct qeth_card *) ptr;
+
+	daemonize("qeth_setprm");
+	QETH_DBF_TEXT(trace,4,"setprm1");
+	if (!qeth_do_run_thread(card, QETH_SET_PROMISC_MODE_THREAD))
+		return 0;
+	QETH_DBF_TEXT(trace,4,"setprm2");
+	qeth_setadp_promisc_mode(card);
+	qeth_clear_thread_running_bit(card, QETH_SET_PROMISC_MODE_THREAD);
+	return 0;
+}
+
 static int
 qeth_recover(void *ptr)
 {
@@ -1031,6 +1052,8 @@ qeth_start_kernel_thread(struct qeth_car
 
 	if (qeth_do_start_thread(card, QETH_SET_IP_THREAD))
 		kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD);
+	if (qeth_do_start_thread(card, QETH_SET_PROMISC_MODE_THREAD))
+		kernel_thread(qeth_set_promisc_mode, (void *)card, SIGCHLD);
 	if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
 		kernel_thread(qeth_recover, (void *) card, SIGCHLD);
 }
@@ -5003,6 +5026,10 @@ qeth_default_setassparms_cb(struct qeth_
 			    unsigned long);
 
 static int
+qeth_default_setadapterparms_cb(struct qeth_card *card,
+                                struct qeth_reply *reply,
+                                unsigned long data);
+static int
 qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *,
 		      __u16, long,
 		      int (*reply_cb)
@@ -5476,6 +5503,59 @@ qeth_vlan_rx_kill_vid(struct net_device 
 	qeth_set_multicast_list(card->dev);
 }
 #endif
+/**
+ * Examine hardware response to SET_PROMISC_MODE
+ */
+static int
+qeth_setadp_promisc_mode_cb(struct qeth_card *card, 
+			    struct qeth_reply *reply,
+			    unsigned long data)
+{
+	struct qeth_ipa_cmd *cmd;
+	struct qeth_ipacmd_setadpparms *setparms;
+
+	QETH_DBF_TEXT(trace,4,"prmadpcb");
+
+	cmd = (struct qeth_ipa_cmd *) data;
+	setparms = &(cmd->data.setadapterparms);
+	
+        qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
+	if (cmd->hdr.return_code) { 
+		QETH_DBF_TEXT_(trace,4,"prmrc%2.2x",cmd->hdr.return_code);	
+		setparms->data.mode = SET_PROMISC_MODE_OFF;
+	}
+	card->info.promisc_mode = setparms->data.mode;
+	return 0;
+}
+/*
+ * Set promiscuous mode (on or off) (SET_PROMISC_MODE command)
+ */
+static void
+qeth_setadp_promisc_mode(struct qeth_card *card)
+{
+	enum qeth_ipa_promisc_modes mode;
+	struct net_device *dev = card->dev;
+	struct qeth_cmd_buffer *iob;
+	struct qeth_ipa_cmd *cmd;
+
+	QETH_DBF_TEXT(trace, 4, "setprom");
+
+	if (((dev->flags & IFF_PROMISC) &&
+	     (card->info.promisc_mode == SET_PROMISC_MODE_ON)) ||
+	    (!(dev->flags & IFF_PROMISC) &&
+	     (card->info.promisc_mode == SET_PROMISC_MODE_OFF)))
+		return;
+	mode = SET_PROMISC_MODE_OFF;
+	if (dev->flags & IFF_PROMISC)
+		mode = SET_PROMISC_MODE_ON;
+	QETH_DBF_TEXT_(trace, 4, "mode:%x", mode);
+
+	iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_PROMISC_MODE,
+			sizeof(struct qeth_ipacmd_setadpparms));
+	cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
+	cmd->data.setadapterparms.data.mode = mode;
+	qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL);
+}
 
 /**
  * set multicast address on card
@@ -5501,6 +5581,11 @@ qeth_set_multicast_list(struct net_devic
 out:
  	if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
 		schedule_work(&card->kernel_thread_starter);
+	if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
+		return;
+	if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0)
+		schedule_work(&card->kernel_thread_starter);
+
 }
 
 static int
@@ -6510,6 +6595,8 @@ qeth_default_setadapterparms_cb(struct q
 	return 0;
 }
 
+
+
 static int
 qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply,
 			      unsigned long data)
@@ -6676,6 +6763,12 @@ qeth_layer2_initialize(struct qeth_card 
         QETH_DBF_TEXT(setup, 2, "doL2init");
         QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card));
 
+	rc = qeth_query_setadapterparms(card);
+	if (rc) {
+		PRINT_WARN("could not query adapter parameters on device %s: "
+			   "x%x\n", CARD_BUS_ID(card), rc);
+	}
+
 	rc = qeth_setadpparms_change_macaddr(card);
 	if (rc) {
 		PRINT_WARN("couldn't get MAC address on "
diff -Naupr orig/drivers/s390/net/qeth_mpc.h patched-linux/drivers/s390/net/qeth_mpc.h
--- orig/drivers/s390/net/qeth_mpc.h	2005-11-09 20:06:57.000000000 +0100
+++ patched-linux/drivers/s390/net/qeth_mpc.h	2005-11-09 20:50:03.000000000 +0100
@@ -14,7 +14,7 @@
 
 #include <asm/qeth.h>
 
-#define VERSION_QETH_MPC_H "$Revision: 1.43 $"
+#define VERSION_QETH_MPC_H "$Revision: 1.44 $"
 
 extern const char *VERSION_QETH_MPC_C;
 
@@ -217,7 +217,7 @@ enum qeth_ipa_setadp_cmd {
 	IPA_SETADP_SEND_OSA_MESSAGE 		= 0x0100,
 	IPA_SETADP_SET_SNMP_CONTROL 		= 0x0200,
 	IPA_SETADP_READ_SNMP_PARMS 		= 0x0400,
-	IPA_SETADP_WRITE_SNMP_PARMS 		= 0x0800,
+	IPA_SETADP_SET_PROMISC_MODE		= 0x0800,
 	IPA_SETADP_QUERY_CARD_INFO 		= 0x1000,
 };
 enum qeth_ipa_mac_ops {
@@ -232,9 +232,12 @@ enum qeth_ipa_addr_ops {
 	CHANGE_ADDR_ADD_ADDR 		= 1,
 	CHANGE_ADDR_DEL_ADDR 		= 2,
 	CHANGE_ADDR_FLUSH_ADDR_TABLE 	= 4,
-
-
 };
+enum qeth_ipa_promisc_modes {
+	SET_PROMISC_MODE_OFF		= 0,
+	SET_PROMISC_MODE_ON		= 1,
+};
+
 /* (SET)DELIP(M) IPA stuff ***************************************************/
 struct qeth_ipacmd_setdelip4 {
 	__u8   ip_addr[4];

^ permalink raw reply

* [patch 5/7] s390: fix recovery failure of non-guestLAN devices
From: Frank Pavlic @ 2005-11-10 12:51 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linux-kernel

[patch 5/7] s390: fix recovery failure of non-guestLAN devices 

From: Frank Pavlic <fpavlic@de.ibm.com>
	- Recovery of non-guestLAN Layer 2 device failed due to
	  trying to register the real MAC address we got from
	  the READ_MAC adapter parameters command.
	  We have to keep the "old" MAC address when we process
	  the reply of a READ_MAC.
	
Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com>

diffstat:
 qeth.h      |   12 ++++++------
 qeth_main.c |   27 ++++++++++++++++-----------
 2 files changed, 22 insertions(+), 17 deletions(-)

diff -Naupr orig/drivers/s390/net/qeth.h patched-linux/drivers/s390/net/qeth.h
--- orig/drivers/s390/net/qeth.h	2005-11-09 20:16:39.000000000 +0100
+++ patched-linux/drivers/s390/net/qeth.h	2005-11-09 20:43:33.000000000 +0100
@@ -25,7 +25,7 @@
 
 #include "qeth_mpc.h"
 
-#define VERSION_QETH_H 		"$Revision: 1.151 $"
+#define VERSION_QETH_H 		"$Revision: 1.152 $"
 
 #ifdef CONFIG_QETH_IPV6
 #define QETH_VERSION_IPV6 	":IPv6"
@@ -719,8 +719,6 @@ struct qeth_reply {
 	atomic_t refcnt;
 };
 
-#define QETH_BROADCAST_WITH_ECHO    1
-#define QETH_BROADCAST_WITHOUT_ECHO 2
 
 struct qeth_card_blkt {
 	int time_total;
@@ -728,8 +726,10 @@ struct qeth_card_blkt {
 	int inter_packet_jumbo;
 };
 
-
-
+#define QETH_BROADCAST_WITH_ECHO    0x01
+#define QETH_BROADCAST_WITHOUT_ECHO 0x02
+#define QETH_LAYER2_MAC_READ	    0x01
+#define QETH_LAYER2_MAC_REGISTERED  0x02
 struct qeth_card_info {
 	unsigned short unit_addr2;
 	unsigned short cula;
@@ -737,7 +737,7 @@ struct qeth_card_info {
 	__u16 func_level;
 	char mcl_level[QETH_MCL_LENGTH + 1];
 	int guestlan;
-	int layer2_mac_registered;
+	int mac_bits;
 	int portname_required;
 	int portno;
 	char portname[9];
diff -Naupr orig/drivers/s390/net/qeth_main.c patched-linux/drivers/s390/net/qeth_main.c
--- orig/drivers/s390/net/qeth_main.c	2005-11-09 20:42:41.000000000 +0100
+++ patched-linux/drivers/s390/net/qeth_main.c	2005-11-09 20:45:34.000000000 +0100
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.238 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.242 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -12,7 +12,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.238 $	 $Date: 2005/05/04 20:19:18 $
+ *    $Revision: 1.242 $	 $Date: 2005/05/04 20:19:18 $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -72,7 +72,7 @@
 #include "qeth_eddp.h"
 #include "qeth_tso.h"
 
-#define VERSION_QETH_C "$Revision: 1.238 $"
+#define VERSION_QETH_C "$Revision: 1.242 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -3775,7 +3775,7 @@ qeth_open(struct net_device *dev)
 
 	if ( (card->info.type != QETH_CARD_TYPE_OSN) &&
 	     (card->options.layer2) &&
-	     (!card->info.layer2_mac_registered)) {
+	     (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
 		QETH_DBF_TEXT(trace,4,"nomacadr");
 		return -EPERM;
 	}
@@ -5894,10 +5894,10 @@ qeth_layer2_send_setmac_cb(struct qeth_c
 		PRINT_WARN("Error in registering MAC address on " \
 			   "device %s: x%x\n", CARD_BUS_ID(card),
 			   cmd->hdr.return_code);
-		card->info.layer2_mac_registered = 0;
+		card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
 		cmd->hdr.return_code = -EIO;
 	} else {
-		card->info.layer2_mac_registered = 1;
+		card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
 		memcpy(card->dev->dev_addr,cmd->data.setdelmac.mac,
 		       OSA_ADDR_LEN);
 		PRINT_INFO("MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
@@ -5935,7 +5935,7 @@ qeth_layer2_send_delmac_cb(struct qeth_c
 		cmd->hdr.return_code = -EIO;
 		return 0;
 	}
-	card->info.layer2_mac_registered = 0;
+	card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
 
 	return 0;
 }
@@ -5943,7 +5943,7 @@ static int
 qeth_layer2_send_delmac(struct qeth_card *card, __u8 *mac)
 {
 	QETH_DBF_TEXT(trace, 2, "L2Delmac");
-	if (!card->info.layer2_mac_registered)
+	if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
 		return 0;
 	return qeth_layer2_send_setdelmac(card, mac, IPA_CMD_DELVMAC,
 					  qeth_layer2_send_delmac_cb);
@@ -5965,7 +5965,7 @@ qeth_layer2_set_mac_address(struct net_d
 	card = (struct qeth_card *) dev->priv;
 
 	if (!card->options.layer2) {
-		PRINT_WARN("Setting MAC address on %s is not supported"
+		PRINT_WARN("Setting MAC address on %s is not supported "
 			   "in Layer 3 mode.\n", dev->name);
 		QETH_DBF_TEXT(trace, 3, "setmcLY3");
 		return -EOPNOTSUPP;
@@ -6550,8 +6550,13 @@ qeth_setadpparms_change_macaddr_cb(struc
 	QETH_DBF_TEXT(trace,4,"chgmaccb");
 
 	cmd = (struct qeth_ipa_cmd *) data;
-	memcpy(card->dev->dev_addr,
-	       &cmd->data.setadapterparms.data.change_addr.addr,OSA_ADDR_LEN);
+	if (!card->options.layer2 || card->info.guestlan ||
+	    !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {	
+		memcpy(card->dev->dev_addr,
+		       &cmd->data.setadapterparms.data.change_addr.addr,
+		       OSA_ADDR_LEN);
+		card->info.mac_bits |= QETH_LAYER2_MAC_READ;
+	}
 	qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
 	return 0;
 }

^ permalink raw reply

* [patch 4/7] s390: some more qeth fixes
From: Frank Pavlic @ 2005-11-10 12:50 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linux-kernel

[patch 4/7] s390: some more qeth fixes  

From: Frank Pavlic <fpavlic@de.ibm.com>
From: Peter Tiedemann <ptiedem@de.ibm.com>
	- possible race on list fixed by reset 
	  list processing after every operation
	- traffic hang fixed 

Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com>

diffstat:
 qeth_main.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

diff -Naupr orig/drivers/s390/net/qeth_main.c patched-linux/drivers/s390/net/qeth_main.c
--- orig/drivers/s390/net/qeth_main.c	2005-11-09 20:37:03.000000000 +0100
+++ patched-linux/drivers/s390/net/qeth_main.c	2005-11-09 20:38:23.000000000 +0100
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.236 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.238 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -12,7 +12,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.236 $	 $Date: 2005/05/04 20:19:18 $
+ *    $Revision: 1.238 $	 $Date: 2005/05/04 20:19:18 $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -72,7 +72,7 @@
 #include "qeth_eddp.h"
 #include "qeth_tso.h"
 
-#define VERSION_QETH_C "$Revision: 1.236 $"
+#define VERSION_QETH_C "$Revision: 1.238 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -799,7 +799,7 @@ __qeth_delete_all_mc(struct qeth_card *c
 {
 	struct qeth_ipaddr *addr, *tmp;
 	int rc;
-
+again:
 	list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) {
 		if (addr->is_multicast) {
 			spin_unlock_irqrestore(&card->ip_lock, *flags);
@@ -808,6 +808,7 @@ __qeth_delete_all_mc(struct qeth_card *c
 			if (!rc) {
 				list_del(&addr->entry);
 				kfree(addr);
+				goto again;
 			}
 		}
 	}
@@ -4336,6 +4337,8 @@ qeth_do_send_packet(struct qeth_card *ca
 out:
 	if (flush_count)
 		qeth_flush_buffers(queue, 0, start_index, flush_count);
+	else if (!atomic_read(&queue->set_pci_flags_count))
+		atomic_swap(&queue->state, QETH_OUT_Q_LOCKED_FLUSH);
 	/*
 	 * queue->state will go from LOCKED -> UNLOCKED or from
 	 * LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us

^ permalink raw reply

* [patch 3/7] s390: qeth multicast address registration fixed
From: Frank Pavlic @ 2005-11-10 12:49 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linux-kernel

[patch 3/7] s390: qeth multicast address registration fixed  

From: Klaus Dieter Wacker <kdwacker@de.ibm.com>
	- when running in Layer2 mode we don't have to register
	  the multicast IP address but only group mac address.
	  Therefore for Layer 2 devices it is enough to go
	  through dev->mc_list list and register these entries.
	
Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com>

diffstat:
 qeth_main.c |  106 +++++++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 80 insertions(+), 26 deletions(-)

diff -Naupr orig/drivers/s390/net/qeth_main.c patched-linux/drivers/s390/net/qeth_main.c
--- orig/drivers/s390/net/qeth_main.c	2005-11-09 20:27:37.000000000 +0100
+++ patched-linux/drivers/s390/net/qeth_main.c	2005-11-09 20:30:44.000000000 +0100
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.235 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.236 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -12,7 +12,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.235 $	 $Date: 2005/05/04 20:19:18 $
+ *    $Revision: 1.236 $	 $Date: 2005/05/04 20:19:18 $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -72,7 +72,7 @@
 #include "qeth_eddp.h"
 #include "qeth_tso.h"
 
-#define VERSION_QETH_C "$Revision: 1.235 $"
+#define VERSION_QETH_C "$Revision: 1.236 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -602,11 +602,20 @@ __qeth_ref_ip_on_card(struct qeth_card *
 	int found = 0;
 
 	list_for_each_entry(addr, &card->ip_list, entry) {
+		if (card->options.layer2) {
+			if ((addr->type == todo->type) &&
+			    (memcmp(&addr->mac, &todo->mac, 
+				    OSA_ADDR_LEN) == 0)) {
+				found = 1;
+				break;
+			}
+			continue;
+		} 
 		if ((addr->proto     == QETH_PROT_IPV4)  &&
 		    (todo->proto     == QETH_PROT_IPV4)  &&
 		    (addr->type      == todo->type)      &&
 		    (addr->u.a4.addr == todo->u.a4.addr) &&
-		    (addr->u.a4.mask == todo->u.a4.mask)   ){
+		    (addr->u.a4.mask == todo->u.a4.mask)) {
 			found = 1;
 			break;
 		}
@@ -615,12 +624,12 @@ __qeth_ref_ip_on_card(struct qeth_card *
 		    (addr->type        == todo->type)         &&
 		    (addr->u.a6.pfxlen == todo->u.a6.pfxlen)  &&
 		    (memcmp(&addr->u.a6.addr, &todo->u.a6.addr,
-			    sizeof(struct in6_addr)) == 0))     {
+			    sizeof(struct in6_addr)) == 0)) {
 			found = 1;
 			break;
 		}
 	}
-	if (found){
+	if (found) {
 		addr->users += todo->users;
 		if (addr->users <= 0){
 			*__addr = addr;
@@ -632,7 +641,7 @@ __qeth_ref_ip_on_card(struct qeth_card *
 			return 0;
 		}
 	}
-	if (todo->users > 0){
+	if (todo->users > 0) {
 		/* for VIPA and RXIP limit refcount to 1 */
 		if (todo->type != QETH_IP_TYPE_NORMAL)
 			todo->users = 1;
@@ -682,12 +691,22 @@ __qeth_insert_ip_todo(struct qeth_card *
 		if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) &&
 		    (tmp->type == QETH_IP_TYPE_DEL_ALL_MC))
 			return 0;
+		if (card->options.layer2) {
+			if ((tmp->type	== addr->type)	&&
+			    (tmp->is_multicast == addr->is_multicast) &&
+			    (memcmp(&tmp->mac, &addr->mac, 
+				    OSA_ADDR_LEN) == 0)) {
+				found = 1;
+				break;
+			}
+			continue;
+		} 	 
 		if ((tmp->proto        == QETH_PROT_IPV4)     &&
 		    (addr->proto       == QETH_PROT_IPV4)     &&
 		    (tmp->type         == addr->type)         &&
 		    (tmp->is_multicast == addr->is_multicast) &&
 		    (tmp->u.a4.addr    == addr->u.a4.addr)    &&
-		    (tmp->u.a4.mask    == addr->u.a4.mask)      ){
+		    (tmp->u.a4.mask    == addr->u.a4.mask)) {
 			found = 1;
 			break;
 		}
@@ -697,7 +716,7 @@ __qeth_insert_ip_todo(struct qeth_card *
 		    (tmp->is_multicast == addr->is_multicast)  &&
 		    (tmp->u.a6.pfxlen  == addr->u.a6.pfxlen)   &&
 		    (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
-			    sizeof(struct in6_addr)) == 0)        ){
+			    sizeof(struct in6_addr)) == 0)) {
 			found = 1;
 			break;
 		}
@@ -707,7 +726,7 @@ __qeth_insert_ip_todo(struct qeth_card *
 			tmp->users += addr->users;
 		else
 			tmp->users += add? 1:-1;
-		if (tmp->users == 0){
+		if (tmp->users == 0) {
 			list_del(&tmp->entry);
 			kfree(tmp);
 		}
@@ -738,12 +757,15 @@ qeth_delete_ip(struct qeth_card *card, s
 	unsigned long flags;
 	int rc = 0;
 
-	QETH_DBF_TEXT(trace,4,"delip");
-	if (addr->proto == QETH_PROT_IPV4)
-		QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4);
+	QETH_DBF_TEXT(trace, 4, "delip");
+
+	if (card->options.layer2)
+		QETH_DBF_HEX(trace, 4, &addr->mac, 6);
+	else if (addr->proto == QETH_PROT_IPV4)
+		QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
 	else {
-		QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8);
-		QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8);
+		QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
+		QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
 	}
 	spin_lock_irqsave(&card->ip_lock, flags);
 	rc = __qeth_insert_ip_todo(card, addr, 0);
@@ -757,12 +779,14 @@ qeth_add_ip(struct qeth_card *card, stru
 	unsigned long flags;
 	int rc = 0;
 
-	QETH_DBF_TEXT(trace,4,"addip");
-	if (addr->proto == QETH_PROT_IPV4)
-		QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4);
+	QETH_DBF_TEXT(trace, 4, "addip");
+	if (card->options.layer2)
+		QETH_DBF_HEX(trace, 4, &addr->mac, 6);
+	else if (addr->proto == QETH_PROT_IPV4)
+		QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
 	else {
-		QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8);
-		QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8);
+		QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
+		QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
 	}
 	spin_lock_irqsave(&card->ip_lock, flags);
 	rc = __qeth_insert_ip_todo(card, addr, 1);
@@ -851,6 +875,7 @@ qeth_set_ip_addr_list(struct qeth_card *
 
 static void qeth_delete_mc_addresses(struct qeth_card *);
 static void qeth_add_multicast_ipv4(struct qeth_card *);
+static void qeth_layer2_add_multicast(struct qeth_card *);
 #ifdef CONFIG_QETH_IPV6
 static void qeth_add_multicast_ipv6(struct qeth_card *);
 #endif
@@ -5301,8 +5326,7 @@ qeth_free_vlan_addresses4(struct qeth_ca
 	struct qeth_ipaddr *addr;
 
 	QETH_DBF_TEXT(trace, 4, "frvaddr4");
-	if (!card->vlangrp)
-		return;
+
 	rcu_read_lock();
 	in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]);
 	if (!in_dev)
@@ -5330,8 +5354,7 @@ qeth_free_vlan_addresses6(struct qeth_ca
 	struct qeth_ipaddr *addr;
 
 	QETH_DBF_TEXT(trace, 4, "frvaddr6");
-	if (!card->vlangrp)
-		return;
+
 	in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]);
 	if (!in6_dev)
 		return;
@@ -5350,6 +5373,15 @@ qeth_free_vlan_addresses6(struct qeth_ca
 #endif /* CONFIG_QETH_IPV6 */
 }
 
+static void
+qeth_free_vlan_addresses(struct qeth_card *card, unsigned short vid)
+{
+	if (card->options.layer2 || !card->vlangrp)
+		return;
+	qeth_free_vlan_addresses4(card, vid);
+	qeth_free_vlan_addresses6(card, vid);
+}
+
 static int
 qeth_layer2_send_setdelvlan_cb(struct qeth_card *card,
                                struct qeth_reply *reply,
@@ -5432,8 +5464,7 @@ qeth_vlan_rx_kill_vid(struct net_device 
 	qeth_free_vlan_skbs(card, vid);
 	spin_lock_irqsave(&card->vlanlock, flags);
 	/* unregister IP addresses of vlan device */
-	qeth_free_vlan_addresses4(card, vid);
-	qeth_free_vlan_addresses6(card, vid);
+	qeth_free_vlan_addresses(card, vid);
 	if (card->vlangrp)
 		card->vlangrp->vlan_devices[vid] = NULL;
 	spin_unlock_irqrestore(&card->vlanlock, flags);
@@ -5456,10 +5487,15 @@ qeth_set_multicast_list(struct net_devic
 	 
 	QETH_DBF_TEXT(trace,3,"setmulti");
 	qeth_delete_mc_addresses(card);
+	if (card->options.layer2) {
+		qeth_layer2_add_multicast(card);
+		goto out;
+	}
 	qeth_add_multicast_ipv4(card);
 #ifdef CONFIG_QETH_IPV6
 	qeth_add_multicast_ipv6(card);
 #endif
+out:
  	if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
 		schedule_work(&card->kernel_thread_starter);
 }
@@ -5669,6 +5705,24 @@ qeth_add_multicast_ipv4(struct qeth_card
 	in_dev_put(in4_dev);
 }
 
+static void
+qeth_layer2_add_multicast(struct qeth_card *card)
+{
+	struct qeth_ipaddr *ipm;
+	struct dev_mc_list *dm;
+
+	QETH_DBF_TEXT(trace,4,"L2addmc");
+	for (dm = card->dev->mc_list; dm; dm = dm->next) {
+		ipm = qeth_get_addr_buffer(QETH_PROT_IPV4);
+		if (!ipm)
+			continue;
+		memcpy(ipm->mac,dm->dmi_addr,MAX_ADDR_LEN);
+		ipm->is_multicast = 1;
+		if (!qeth_add_ip(card, ipm))
+			kfree(ipm);
+	}
+}
+
 #ifdef CONFIG_QETH_IPV6
 static inline void
 qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)

^ permalink raw reply

* [patch 2/7] s390: minor modification in qeth layer2 code
From: Frank Pavlic @ 2005-11-10 12:49 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linux-kernel

[patch 2/7] s390: minor modification in qeth layer2 code

From: Frank Pavlic <fpavlic@de.ibm.com>
	- use qeth_layer2_send_setdelvlan_cb to check
	  return code of a SET/DELVLAN IP Assist command.
	  It fits better in qeth's design and mechanism of IP Assist
	  command handling.
	  
Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com>

diffstat:
 qeth_main.c |   40 ++++++++++++++++++++++++++--------------
 1 files changed, 26 insertions(+), 14 deletions(-)

diff -Naupr orig/drivers/s390/net/qeth_main.c patched-linux/drivers/s390/net/qeth_main.c
--- orig/drivers/s390/net/qeth_main.c	2005-11-09 20:06:57.000000000 +0100
+++ patched-linux/drivers/s390/net/qeth_main.c	2005-11-09 20:20:06.000000000 +0100
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.235 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -12,7 +12,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.224 $	 $Date: 2005/05/04 20:19:18 $
+ *    $Revision: 1.235 $	 $Date: 2005/05/04 20:19:18 $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -72,7 +72,7 @@
 #include "qeth_eddp.h"
 #include "qeth_tso.h"
 
-#define VERSION_QETH_C "$Revision: 1.224 $"
+#define VERSION_QETH_C "$Revision: 1.235 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -5350,11 +5350,30 @@ qeth_free_vlan_addresses6(struct qeth_ca
 #endif /* CONFIG_QETH_IPV6 */
 }
 
-static void
+static int
+qeth_layer2_send_setdelvlan_cb(struct qeth_card *card,
+                               struct qeth_reply *reply,
+                               unsigned long data)
+{
+        struct qeth_ipa_cmd *cmd;
+
+        QETH_DBF_TEXT(trace, 2, "L2sdvcb");
+        cmd = (struct qeth_ipa_cmd *) data;
+        if (cmd->hdr.return_code) {
+		PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
+			  "Continuing\n",cmd->data.setdelvlan.vlan_id, 
+			  QETH_CARD_IFNAME(card), cmd->hdr.return_code);
+		QETH_DBF_TEXT_(trace, 2, "L2VL%4x", cmd->hdr.command);
+		QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
+		QETH_DBF_TEXT_(trace, 2, "err%d", cmd->hdr.return_code);
+	}
+        return 0;
+}
+
+static int
 qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i,
 			    enum qeth_ipa_cmds ipacmd)
 {
- 	int rc;
 	struct qeth_ipa_cmd *cmd;
 	struct qeth_cmd_buffer *iob;
 
@@ -5362,15 +5381,8 @@ qeth_layer2_send_setdelvlan(struct qeth_
 	iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
 	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
         cmd->data.setdelvlan.vlan_id = i;
-
-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-        if (rc) {
-                PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
-			  "Continuing\n",i, QETH_CARD_IFNAME(card), rc);
-		QETH_DBF_TEXT_(trace, 2, "L2VL%4x", ipacmd);
-		QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
-		QETH_DBF_TEXT_(trace, 2, "err%d", rc);
-        }
+	return qeth_send_ipa_cmd(card, iob, 
+				 qeth_layer2_send_setdelvlan_cb, NULL);
 }
 
 static void

^ permalink raw reply

* [patch 1/7] s390: synthax checking for VIPA addresses fixed
From: Frank Pavlic @ 2005-11-10 12:49 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linux-kernel

[patch 1/7] s390: synthax checking for VIPA addresses fixed

From: Peter Tiedemann <ptiedem@de.ibm.com>
	- synthax checking for VIPA addresses fixed

Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com>

diffstat:
 qeth.h     |   65 ++++++++++++++++++++++++++++++++++++++++++++++++-------------
 qeth_sys.c |    6 ++---
 2 files changed, 55 insertions(+), 16 deletions(-)


diff -Naupr orig/drivers/s390/net/qeth.h patched-linux/drivers/s390/net/qeth.h
--- orig/drivers/s390/net/qeth.h	2005-11-09 20:06:57.000000000 +0100
+++ patched-linux/drivers/s390/net/qeth.h	2005-11-09 20:11:20.000000000 +0100
@@ -8,6 +8,7 @@
 #include <linux/trdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
+#include <linux/ctype.h>
 
 #include <net/ipv6.h>
 #include <linux/in6.h>
@@ -24,7 +25,7 @@
 
 #include "qeth_mpc.h"
 
-#define VERSION_QETH_H 		"$Revision: 1.142 $"
+#define VERSION_QETH_H 		"$Revision: 1.151 $"
 
 #ifdef CONFIG_QETH_IPV6
 #define QETH_VERSION_IPV6 	":IPv6"
@@ -1074,6 +1075,26 @@ qeth_get_qdio_q_format(struct qeth_card 
 	}
 }
 
+static inline int
+qeth_isdigit(char * buf)
+{
+	while (*buf) {
+		if (!isdigit(*buf++))
+			return 0;
+	}
+	return 1;
+}
+
+static inline int
+qeth_isxdigit(char * buf)
+{
+	while (*buf) {
+		if (!isxdigit(*buf++))
+			return 0;
+	}
+	return 1;
+}
+
 static inline void
 qeth_ipaddr4_to_string(const __u8 *addr, char *buf)
 {
@@ -1090,18 +1111,27 @@ qeth_string_to_ipaddr4(const char *buf, 
 	int i;
 
 	start = buf;
-	for (i = 0; i < 3; i++) {
-		if (!(end = strchr(start, '.')))
+	for (i = 0; i < 4; i++) {
+		if (i == 3) {
+			end = strchr(start,0xa);
+			if (end)
+				len = end - start;
+			else		
+				len = strlen(start);
+		}
+		else {
+			end = strchr(start, '.');
+			len = end - start;
+		}
+		if ((len <= 0) || (len > 3))
 			return -EINVAL;
-		len = end - start;
 		memset(abuf, 0, 4);
 		strncpy(abuf, start, len);
+		if (!qeth_isdigit(abuf))
+			return -EINVAL;
 		addr[i] = simple_strtoul(abuf, &tmp, 10);
 		start = end + 1;
 	}
-	memset(abuf, 0, 4);
-	strcpy(abuf, start);
-	addr[3] = simple_strtoul(abuf, &tmp, 10);
 	return 0;
 }
 
@@ -1128,18 +1158,27 @@ qeth_string_to_ipaddr6(const char *buf, 
 
 	tmp_addr = (u16 *)addr;
 	start = buf;
-	for (i = 0; i < 7; i++) {
-		if (!(end = strchr(start, ':')))
+	for (i = 0; i < 8; i++) {
+		if (i == 7) {
+			end = strchr(start,0xa);
+			if (end)
+				len = end - start;
+			else
+				len = strlen(start);
+		}
+		else {
+			end = strchr(start, ':');
+			len = end - start;
+		}
+		if ((len <= 0) || (len > 4))
 			return -EINVAL;
-		len = end - start;
 		memset(abuf, 0, 5);
 		strncpy(abuf, start, len);
+		if (!qeth_isxdigit(abuf))
+			return -EINVAL;
 		tmp_addr[i] = simple_strtoul(abuf, &tmp, 16);
 		start = end + 1;
 	}
-	memset(abuf, 0, 5);
-	strcpy(abuf, start);
-	tmp_addr[7] = simple_strtoul(abuf, &tmp, 16);
 	return 0;
 }
 
diff -Naupr orig/drivers/s390/net/qeth_sys.c patched-linux/drivers/s390/net/qeth_sys.c
--- orig/drivers/s390/net/qeth_sys.c	2005-11-09 20:06:57.000000000 +0100
+++ patched-linux/drivers/s390/net/qeth_sys.c	2005-11-09 20:11:59.000000000 +0100
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.55 $)
+ * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.58 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  * This file contains code related to sysfs.
@@ -20,7 +20,7 @@
 #include "qeth_mpc.h"
 #include "qeth_fs.h"
 
-const char *VERSION_QETH_SYS_C = "$Revision: 1.55 $";
+const char *VERSION_QETH_SYS_C = "$Revision: 1.58 $";
 
 /*****************************************************************************/
 /*                                                                           */
@@ -1117,7 +1117,7 @@ qeth_parse_ipatoe(const char* buf, enum 
 	start = buf;
 	/* get address string */
 	end = strchr(start, '/');
-	if (!end){
+	if (!end || (end-start >= 49)){
 		PRINT_WARN("Invalid format for ipato_addx/delx. "
 			   "Use <ip addr>/<mask bits>\n");
 		return -EINVAL;

^ permalink raw reply

* does routing performance degrade from 2.4.20 to 2.4.31 ?
From: Mayuresh Chitale @ 2005-11-10 10:12 UTC (permalink / raw)
  To: netdev, netfilter

Hi All,

We are working on kernel version 2.4.20 and are trying to migrate to
version 2.4.31. We are doing some performance related tests to see the
impact of migration. The routing throughput seems to degrade from
2.4.20 to 2.4.31.
We have a Malta board with mips 4kc processor and are using iperf tool
to do the testing. Two test PCs are connected to the malta and iperf
server is run on PC and the client on another PC. With netfilter
compiled into the kernel, version 2.4.20 shows better result than
2.4.31. No rules except the default (all accept) have been applied.
Without netfilter, both perform almost identical. Is this expected ??
The dump below shows the measurements. If anyone has done similar
tests before, please share with me their results.

Have a nice day.
Mayuresh.

2.4.31
=====
[mayuresh@localhost ~]$ ./iperf -c 100.0.0.1 -P 2
------------------------------------------------------------
Client connecting to 100.0.0.1, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[  4] local 10.1.1.99 port 33702 connected with 100.0.0.1 port 5001
[  3] local 10.1.1.99 port 33701 connected with 100.0.0.1 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec  16.9 MBytes  14.2 Mbits/sec
[  4]  0.0-10.0 sec  17.0 MBytes  14.2 Mbits/sec
[SUM]  0.0-10.0 sec  33.9 MBytes  28.3 Mbits/sec

2.4.20
=====
[mayuresh@localhost ~]$ ./iperf -c 100.0.0.1 -P 2
------------------------------------------------------------
Client connecting to 100.0.0.1, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[  4] local 10.1.1.99 port 33705 connected with 100.0.0.1 port 5001
[  3] local 10.1.1.99 port 33704 connected with 100.0.0.1 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec  20.2 MBytes  16.9 Mbits/sec
[  4]  0.0-10.0 sec  20.2 MBytes  16.9 Mbits/sec
[SUM]  0.0-10.0 sec  40.4 MBytes  33.8 Mbits/sec

^ permalink raw reply

* Re: [PATCH 2/2][MCAST] Fix for add_grec(...)
From: Yan Zheng @ 2005-11-10  1:20 UTC (permalink / raw)
  To: David Stevens; +Cc: linux-kernel, netdev
In-Reply-To: <OFD5769042.0E81A890-ON882570B4.0075A92B-882570B4.00796FDC@us.ibm.com>

David Stevens wrote:
> Yan,
>         I think your patch has some problems.
> 
> Yan Zheng <yanzheng@21cn.com> wrote on 11/09/2005 03:58:20 AM:
> 
> 
>>+#if 0
>>    if (!*psf_list) {
>>       if (type == MLD2_ALLOW_NEW_SOURCES ||
>>           type == MLD2_BLOCK_OLD_SOURCES)
>>@@ -1474,12 +1477,15 @@ static struct sk_buff *add_grec(struct s
>>       }
>>       return skb;
>>    }
>>+#endif
> 
> 
> 
>         This code is the only place in the current code where you
> can generate a group header with an empty source list (what it is
> checking for). Your patch has added an add_grhead() for change
> and EXCLUDE records, but it isn't checking mca_crcount or isquery.
> I need to check, but I'm concerned this will create a group header
> in a report for cases where it should not.
> 
ischange implicits mca_crcount has already been ckecked in mld_send_cr(...)
Actually, check mca_crcount directly will get mode change report sent one times less 
than you intend, because mca_crcount has decreased by one before call add_grec(...).


Now We only have MLD2_MODE_IS_INCLUDE left. but "mode is include and source list is empty"
is an impossible event.
> 
> 
>>    pmr = skb ? (struct mld2_report *)skb->h.raw : NULL;
>>
>>    /* EX and TO_EX get a fresh packet, if needed */
>>-   if (truncate) {
>>-      if (pmr && pmr->ngrec &&
>>-          AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) {
>>+   if (truncate || ischange) {
>>+      int min_len;
>>+      min_len   = truncate ? grec_size(pmc, type, gdeleted, sdeleted) : 
> 
> 
>>+           (sizeof(struct mld2_grec) + sizeof(struct in6_addr));
>>+      if (pmr && pmr->ngrec && AVAILABLE(skb) < min_len) {
>>          if (skb)
>>             mld_sendpack(skb);
>>          skb = mld_newpack(dev, dev->mtu);
> 
> 
>         This "truncate" code is to handle exclude records that may be
> truncated. It gets a new packet when adding this record and the whole
> thing won't fit in a single packet. This is not appropriate for anything
> but IS_EX and TO_EX, but "ischange" in your patch will be true for
> TO_IN. So, I think this will waste space in a report that could hold
> some of these TO_IN sources.

When type is MLD2_MODE_IS_INCLUDE, min_len is equal to "sizeof(struct mld2_grec) + 
sizeof(struct in6_addr)". it satisfies the comment above. (make sure we have room 
for group header and at least one source.)

^ permalink raw reply

* Re: RED qdisc not working...
From: Jamal Hadi Salim @ 2005-11-10  0:03 UTC (permalink / raw)
  To: Daniel J Blueman
  Cc: netdev, netfilter-devel, netfilter, kaber, davem, laforge,
	coreteam
In-Reply-To: <6278d2220511091532k7b732b9bv2957763ba6f4c10f@mail.gmail.com>

howdy,
When you say it is "broken" - what is this relative to?
Did you have another kernel where you precise config worked?

The only changes that have made it in for RED are in post 2.6.14; other
than that all should work great as ever before.

suggestions:

could you try the latest iproute2 posted last few days by Stephen and
see if your problem persists?

Also try using something simpler than HTB like prio qdisc to help in
debugging things for you?
Can you look at examples directory and use some of the tricks used
there?

cheers,
jamal

On Wed, 2005-09-11 at 23:32 +0000, Daniel J Blueman wrote:
> Has anyone been able to get the RED (random early detection) qdisc
> working lately?
> 
> I can't get anything going through it to be dropped or marked; the
> 'marked', 'early', 'pdrop' and 'other' fields remain at 0 [1]. In my
> example script [2], I get the 3072Kbits/s transfer into eth0, which
> you'd only expect if the RED qdisc wasn't there.
> 
> I have tried with a recent 2.6.12 debian kernel and stock 2.6.14 on
> x86_64 debian. I rebuilt new iproute and iptables packages from latest
> clean upstream sources, but to no avail.
> 
> Any ideas? Please CC me on replies, as I am not subscribed.
> 
> Thanks,
>   Dan
> 
> --- [1]
> 
> # tc -s qdisc show dev eth0
> qdisc htb 1: r2q 10 default 10 direct_packets_stat 0
>  Sent 53985530 bytes 36757 pkts (dropped 0, overlimits 45125)
> qdisc red 10: parent 1:10 limit 512Kb min 64Kb max 128Kb
>  Sent 53985530 bytes 36757 pkts (dropped 0, overlimits 0)
>   marked 0 early 0 pdrop 0 other 0
> 
> --- [2]
> 
> tc qdisc del dev eth0 root
> 
> tc qdisc add dev eth0 root handle 1: htb default 10
> tc class add dev eth0 parent 1: classid 1:1 htb rate 4096kbit ceil 4096kbit
> tc class add dev eth0 parent 1:1 classid 1:10 htb rate 3072kbit ceil 3072kbit
> tc qdisc add dev eth0 parent 1:10 handle 10: red \
>   limit 4096kbit min 512kbit max 1024kbit avpkt 1000 \
>   burst 100 probability 0.02 bandwidth 1024kbit
> ___
> Daniel J Blueman
> 
> 
> 

^ permalink raw reply

* RED qdisc not working...
From: Daniel J Blueman @ 2005-11-09 23:32 UTC (permalink / raw)
  To: netdev, netfilter-devel, netfilter, kaber; +Cc: davem, laforge, coreteam
In-Reply-To: <6278d2220511071626j3646afa7n5ac33228e8b3fc82@mail.gmail.com>

Has anyone been able to get the RED (random early detection) qdisc
working lately?

I can't get anything going through it to be dropped or marked; the
'marked', 'early', 'pdrop' and 'other' fields remain at 0 [1]. In my
example script [2], I get the 3072Kbits/s transfer into eth0, which
you'd only expect if the RED qdisc wasn't there.

I have tried with a recent 2.6.12 debian kernel and stock 2.6.14 on
x86_64 debian. I rebuilt new iproute and iptables packages from latest
clean upstream sources, but to no avail.

Any ideas? Please CC me on replies, as I am not subscribed.

Thanks,
  Dan

--- [1]

# tc -s qdisc show dev eth0
qdisc htb 1: r2q 10 default 10 direct_packets_stat 0
 Sent 53985530 bytes 36757 pkts (dropped 0, overlimits 45125)
qdisc red 10: parent 1:10 limit 512Kb min 64Kb max 128Kb
 Sent 53985530 bytes 36757 pkts (dropped 0, overlimits 0)
  marked 0 early 0 pdrop 0 other 0

--- [2]

tc qdisc del dev eth0 root

tc qdisc add dev eth0 root handle 1: htb default 10
tc class add dev eth0 parent 1: classid 1:1 htb rate 4096kbit ceil 4096kbit
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 3072kbit ceil 3072kbit
tc qdisc add dev eth0 parent 1:10 handle 10: red \
  limit 4096kbit min 512kbit max 1024kbit avpkt 1000 \
  burst 100 probability 0.02 bandwidth 1024kbit
___
Daniel J Blueman

^ permalink raw reply

* Re: [PATCH 2/2][MCAST] Fix for add_grec(...)
From: David Stevens @ 2005-11-09 22:06 UTC (permalink / raw)
  To: Yan Zheng; +Cc: linux-kernel, netdev
In-Reply-To: <4371E45C.3020500@21cn.com>

Yan,
        I think your patch has some problems.

Yan Zheng <yanzheng@21cn.com> wrote on 11/09/2005 03:58:20 AM:

> +#if 0
>     if (!*psf_list) {
>        if (type == MLD2_ALLOW_NEW_SOURCES ||
>            type == MLD2_BLOCK_OLD_SOURCES)
> @@ -1474,12 +1477,15 @@ static struct sk_buff *add_grec(struct s
>        }
>        return skb;
>     }
> +#endif


        This code is the only place in the current code where you
can generate a group header with an empty source list (what it is
checking for). Your patch has added an add_grhead() for change
and EXCLUDE records, but it isn't checking mca_crcount or isquery.
I need to check, but I'm concerned this will create a group header
in a report for cases where it should not.


>     pmr = skb ? (struct mld2_report *)skb->h.raw : NULL;
> 
>     /* EX and TO_EX get a fresh packet, if needed */
> -   if (truncate) {
> -      if (pmr && pmr->ngrec &&
> -          AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) {
> +   if (truncate || ischange) {
> +      int min_len;
> +      min_len   = truncate ? grec_size(pmc, type, gdeleted, sdeleted) : 

> +           (sizeof(struct mld2_grec) + sizeof(struct in6_addr));
> +      if (pmr && pmr->ngrec && AVAILABLE(skb) < min_len) {
>           if (skb)
>              mld_sendpack(skb);
>           skb = mld_newpack(dev, dev->mtu);

        This "truncate" code is to handle exclude records that may be
truncated. It gets a new packet when adding this record and the whole
thing won't fit in a single packet. This is not appropriate for anything
but IS_EX and TO_EX, but "ischange" in your patch will be true for
TO_IN. So, I think this will waste space in a report that could hold
some of these TO_IN sources.

        I haven't run your test code, or tested with your patch yet,
just observing the differences from the original code path and your
patch (and they appear to be more than you intended).

                                                        +-DLS

^ permalink raw reply

* Re: [patch 2.6.14 (take #2)] fec_8xx: make CONFIG_FEC_8XX depend on CONFIG_8xx
From: John W. Linville @ 2005-11-09 21:52 UTC (permalink / raw)
  To: Pantelis Antoniou, linuxppc-embedded, netdev, linux-kernel
In-Reply-To: <20051107182459.GD13797@tuxdriver.com>

On Mon, Nov 07, 2005 at 01:24:59PM -0500, John W. Linville wrote:
> Change CONFIG_FEC_8XX to depend on CONFIG_8xx instead of CONFIG_FEC.
> CONFIG_FEC depends on ColdFire CPUs, which does not apply for the
> PPC 8xx processors.

FWIW, I have this patch available on the linville-fec_8xx branch of
netdev-jwl as described below.

Thanks,

John

---

The following changes since commit 330d57fb98a916fa8e1363846540dd420e99499a:
  Al Viro:
        Fix sysctl unregistration oops (CVE-2005-2709)

are found in the git repository at:

  git://git.tuxdriver.com/git/netdev-jwl.git linville-fec_8xx

John W. Linville:
      fec_8xx: make CONFIG_FEC_8XX depend on CONFIG_8xx

 drivers/net/fec_8xx/Kconfig |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/fec_8xx/Kconfig b/drivers/net/fec_8xx/Kconfig
index 94e7a9a..a84c232 100644
--- a/drivers/net/fec_8xx/Kconfig
+++ b/drivers/net/fec_8xx/Kconfig
@@ -1,6 +1,6 @@
 config FEC_8XX
 	tristate "Motorola 8xx FEC driver"
-	depends on NET_ETHERNET && FEC
+	depends on NET_ETHERNET && 8xx
 	select MII
 
 config FEC_8XX_GENERIC_PHY
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply related


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