From 0ed2f1d1392322d0b4b84c2d219e3af064441017 Mon Sep 17 00:00:00 2001
From: Andy Bavier <acb@cs.princeton.edu>
Date: Tue, 23 Jun 2009 20:58:48 +0000
Subject: [PATCH] Sync from trunk

---
 ...-2.6-522-iptables-connection-tagging.patch | 517 +++++++-----------
 1 file changed, 189 insertions(+), 328 deletions(-)

diff --git a/linux-2.6-522-iptables-connection-tagging.patch b/linux-2.6-522-iptables-connection-tagging.patch
index 83e2cc0c6..79891d6d2 100644
--- a/linux-2.6-522-iptables-connection-tagging.patch
+++ b/linux-2.6-522-iptables-connection-tagging.patch
@@ -1,7 +1,7 @@
-diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/include/linux/netfilter/xt_MARK.h linux-2.6.27.10-vs2.3.x-P522/include/linux/netfilter/xt_MARK.h
---- linux-2.6.27.10-vs2.3.x-P/include/linux/netfilter/xt_MARK.h	2008-07-13 23:51:29.000000000 +0200
-+++ linux-2.6.27.10-vs2.3.x-P522/include/linux/netfilter/xt_MARK.h	2009-01-12 01:18:23.000000000 +0100
-@@ -11,6 +11,7 @@ enum {
+diff -Nurb linux-2.6.27-521/include/linux/netfilter/xt_MARK.h linux-2.6.27-522-ol/include/linux/netfilter/xt_MARK.h
+--- linux-2.6.27-521/include/linux/netfilter/xt_MARK.h	2008-10-09 18:13:53.000000000 -0400
++++ linux-2.6.27-522-ol/include/linux/netfilter/xt_MARK.h	2009-06-02 10:02:16.000000000 -0400
+@@ -11,6 +11,7 @@
  	XT_MARK_SET=0,
  	XT_MARK_AND,
  	XT_MARK_OR,
@@ -9,9 +9,9 @@ diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/inclu
  };
  
  struct xt_mark_target_info_v1 {
-diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/include/linux/netfilter/xt_SETXID.h linux-2.6.27.10-vs2.3.x-P522/include/linux/netfilter/xt_SETXID.h
---- linux-2.6.27.10-vs2.3.x-P/include/linux/netfilter/xt_SETXID.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.27.10-vs2.3.x-P522/include/linux/netfilter/xt_SETXID.h	2009-01-12 01:18:23.000000000 +0100
+diff -Nurb linux-2.6.27-521/include/linux/netfilter/xt_SETXID.h linux-2.6.27-522-ol/include/linux/netfilter/xt_SETXID.h
+--- linux-2.6.27-521/include/linux/netfilter/xt_SETXID.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.27-522-ol/include/linux/netfilter/xt_SETXID.h	2009-06-02 10:02:16.000000000 -0400
 @@ -0,0 +1,14 @@
 +#ifndef _XT_SETXID_H_target
 +#define _XT_SETXID_H_target
@@ -27,9 +27,9 @@ diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/inclu
 +};
 +
 +#endif /*_XT_SETXID_H_target*/
-diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/include/linux/netfilter_ipv4/ipt_MARK.h linux-2.6.27.10-vs2.3.x-P522/include/linux/netfilter_ipv4/ipt_MARK.h
---- linux-2.6.27.10-vs2.3.x-P/include/linux/netfilter_ipv4/ipt_MARK.h	2008-07-13 23:51:29.000000000 +0200
-+++ linux-2.6.27.10-vs2.3.x-P522/include/linux/netfilter_ipv4/ipt_MARK.h	2009-01-12 01:18:23.000000000 +0100
+diff -Nurb linux-2.6.27-521/include/linux/netfilter_ipv4/ipt_MARK.h linux-2.6.27-522-ol/include/linux/netfilter_ipv4/ipt_MARK.h
+--- linux-2.6.27-521/include/linux/netfilter_ipv4/ipt_MARK.h	2008-10-09 18:13:53.000000000 -0400
++++ linux-2.6.27-522-ol/include/linux/netfilter_ipv4/ipt_MARK.h	2009-06-02 10:02:16.000000000 -0400
 @@ -12,6 +12,7 @@
  #define IPT_MARK_SET	XT_MARK_SET
  #define IPT_MARK_AND	XT_MARK_AND
@@ -38,9 +38,9 @@ diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/inclu
  
  #define ipt_mark_target_info_v1 xt_mark_target_info_v1
  
-diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/include/linux/netfilter_ipv4/ipt_SETXID.h linux-2.6.27.10-vs2.3.x-P522/include/linux/netfilter_ipv4/ipt_SETXID.h
---- linux-2.6.27.10-vs2.3.x-P/include/linux/netfilter_ipv4/ipt_SETXID.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.27.10-vs2.3.x-P522/include/linux/netfilter_ipv4/ipt_SETXID.h	2009-01-12 01:18:23.000000000 +0100
+diff -Nurb linux-2.6.27-521/include/linux/netfilter_ipv4/ipt_SETXID.h linux-2.6.27-522-ol/include/linux/netfilter_ipv4/ipt_SETXID.h
+--- linux-2.6.27-521/include/linux/netfilter_ipv4/ipt_SETXID.h	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.27-522-ol/include/linux/netfilter_ipv4/ipt_SETXID.h	2009-06-02 10:02:16.000000000 -0400
 @@ -0,0 +1,13 @@
 +#ifndef _IPT_SETXID_H_target
 +#define _IPT_SETXID_H_target
@@ -55,10 +55,10 @@ diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/inclu
 +#define ipt_setxid_target_info_v1 xt_setxid_target_info_v1
 +
 +#endif /*_IPT_SETXID_H_target*/
-diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/include/net/netfilter/nf_conntrack.h linux-2.6.27.10-vs2.3.x-P522/include/net/netfilter/nf_conntrack.h
---- linux-2.6.27.10-vs2.3.x-P/include/net/netfilter/nf_conntrack.h	2008-10-13 14:52:09.000000000 +0200
-+++ linux-2.6.27.10-vs2.3.x-P522/include/net/netfilter/nf_conntrack.h	2009-01-12 01:59:20.000000000 +0100
-@@ -121,6 +121,9 @@ struct nf_conn
+diff -Nurb linux-2.6.27-521/include/net/netfilter/nf_conntrack.h linux-2.6.27-522-ol/include/net/netfilter/nf_conntrack.h
+--- linux-2.6.27-521/include/net/netfilter/nf_conntrack.h	2008-10-09 18:13:53.000000000 -0400
++++ linux-2.6.27-522-ol/include/net/netfilter/nf_conntrack.h	2009-06-02 10:02:16.000000000 -0400
+@@ -121,6 +121,9 @@
  	/* Storage reserved for other modules: */
  	union nf_conntrack_proto proto;
  
@@ -68,10 +68,10 @@ diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/inclu
  	/* Extensions */
  	struct nf_ct_ext *ext;
  
-diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/net/netfilter/Kconfig linux-2.6.27.10-vs2.3.x-P522/net/netfilter/Kconfig
---- linux-2.6.27.10-vs2.3.x-P/net/netfilter/Kconfig	2008-10-13 14:52:09.000000000 +0200
-+++ linux-2.6.27.10-vs2.3.x-P522/net/netfilter/Kconfig	2009-01-12 01:18:23.000000000 +0100
-@@ -477,6 +477,13 @@ config NETFILTER_XT_TARGET_TCPOPTSTRIP
+diff -Nurb linux-2.6.27-521/net/netfilter/Kconfig linux-2.6.27-522-ol/net/netfilter/Kconfig
+--- linux-2.6.27-521/net/netfilter/Kconfig	2008-10-09 18:13:53.000000000 -0400
++++ linux-2.6.27-522-ol/net/netfilter/Kconfig	2009-06-02 10:02:16.000000000 -0400
+@@ -477,6 +477,13 @@
  	  This option adds a "TCPOPTSTRIP" target, which allows you to strip
  	  TCP options from TCP packets.
  
@@ -85,10 +85,10 @@ diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/net/n
  config NETFILTER_XT_MATCH_COMMENT
  	tristate  '"comment" match support'
  	depends on NETFILTER_XTABLES
-diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/net/netfilter/Makefile linux-2.6.27.10-vs2.3.x-P522/net/netfilter/Makefile
---- linux-2.6.27.10-vs2.3.x-P/net/netfilter/Makefile	2008-10-13 14:52:09.000000000 +0200
-+++ linux-2.6.27.10-vs2.3.x-P522/net/netfilter/Makefile	2009-01-12 01:18:23.000000000 +0100
-@@ -38,6 +38,7 @@ obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_co
+diff -Nurb linux-2.6.27-521/net/netfilter/Makefile linux-2.6.27-522-ol/net/netfilter/Makefile
+--- linux-2.6.27-521/net/netfilter/Makefile	2008-10-09 18:13:53.000000000 -0400
++++ linux-2.6.27-522-ol/net/netfilter/Makefile	2009-06-02 10:02:16.000000000 -0400
+@@ -38,6 +38,7 @@
  obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
  
  # targets
@@ -96,59 +96,59 @@ diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/net/n
  obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
  obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
  obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
-diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/net/netfilter/nf_conntrack_core.c linux-2.6.27.10-vs2.3.x-P522/net/netfilter/nf_conntrack_core.c
---- linux-2.6.27.10-vs2.3.x-P/net/netfilter/nf_conntrack_core.c	2008-10-13 14:52:09.000000000 +0200
-+++ linux-2.6.27.10-vs2.3.x-P522/net/netfilter/nf_conntrack_core.c	2009-01-12 02:01:55.000000000 +0100
-@@ -595,6 +595,9 @@ init_conntrack(const struct nf_conntrack
+diff -Nurb linux-2.6.27-521/net/netfilter/nf_conntrack_core.c linux-2.6.27-522-ol/net/netfilter/nf_conntrack_core.c
+--- linux-2.6.27-521/net/netfilter/nf_conntrack_core.c	2008-10-09 18:13:53.000000000 -0400
++++ linux-2.6.27-522-ol/net/netfilter/nf_conntrack_core.c	2009-06-02 10:02:16.000000000 -0400
+@@ -595,6 +595,9 @@
  	/* Overload tuple linked list to put us in unconfirmed list. */
  	hlist_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode, &unconfirmed);
  
-+	conntrack->xid[IP_CT_DIR_ORIGINAL] = -1;
-+	conntrack->xid[IP_CT_DIR_REPLY] = -1;
++	ct->xid[IP_CT_DIR_ORIGINAL] = -1;
++	ct->xid[IP_CT_DIR_REPLY] = -1;
 +
  	spin_unlock_bh(&nf_conntrack_lock);
  
  	if (exp) {
-diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/net/netfilter/xt_MARK.c linux-2.6.27.10-vs2.3.x-P522/net/netfilter/xt_MARK.c
---- linux-2.6.27.10-vs2.3.x-P/net/netfilter/xt_MARK.c	2008-07-13 23:51:29.000000000 +0200
-+++ linux-2.6.27.10-vs2.3.x-P522/net/netfilter/xt_MARK.c	2009-01-12 02:20:38.000000000 +0100
-@@ -8,13 +8,19 @@
-  *	This program is free software; you can redistribute it and/or modify
-  *	it under the terms of the GNU General Public License version 2 as
-  *	published by the Free Software Foundation.
-+ *
-  */
- 
+diff -Nurb linux-2.6.27-521/net/netfilter/xt_MARK.c linux-2.6.27-522/net/netfilter/xt_MARK.c
+--- linux-2.6.27-521/net/netfilter/xt_MARK.c	2008-10-09 18:13:53.000000000 -0400
++++ linux-2.6.27-522/net/netfilter/xt_MARK.c	2009-06-02 11:12:59.000000000 -0400
+@@ -13,7 +13,13 @@
  #include <linux/module.h>
-+#include <linux/version.h>
  #include <linux/skbuff.h>
  #include <linux/ip.h>
 +#include <net/udp.h>
  #include <net/checksum.h>
 +#include <net/route.h>
 +#include <net/inet_hashtables.h>
- 
++#include <net/net_namespace.h>
++
 +#include <net/netfilter/nf_conntrack.h>
+ 
  #include <linux/netfilter/x_tables.h>
  #include <linux/netfilter/xt_MARK.h>
- 
-@@ -24,6 +30,50 @@ MODULE_DESCRIPTION("Xtables: packet mark
+@@ -24,6 +30,8 @@
  MODULE_ALIAS("ipt_MARK");
  MODULE_ALIAS("ip6t_MARK");
  
++extern DEFINE_PER_CPU(int, sknid_elevator);
++
+ static unsigned int
+ mark_tg_v0(struct sk_buff *skb, const struct net_device *in,
+            const struct net_device *out, unsigned int hooknum,
+@@ -61,14 +69,242 @@
+ 	return XT_CONTINUE;
+ }
+ 
 +#define PEERCRED_SET(x) ((x!=0) && (x!=(unsigned int)-1)) 
 +
++
 +static inline u_int16_t
 +get_dst_port(struct nf_conntrack_tuple *tuple)
 +{
 +	switch (tuple->dst.protonum) {
 +	case IPPROTO_GRE:
 +		/* XXX Truncate 32-bit GRE key to 16 bits */
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
 +		return tuple->dst.u.gre.key;
-+#else
-+		return htons(ntohl(tuple->dst.u.gre.key));
-+#endif  
 +	case IPPROTO_ICMP:
 +		/* Bind on ICMP echo ID */
 +		return tuple->src.u.icmp.id;
@@ -179,15 +179,6 @@ diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/net/n
 +		return tuple->src.u.all;
 +	}
 +}
-+
- static unsigned int
- mark_tg_v0(struct sk_buff *skb, const struct net_device *in,
-            const struct net_device *out, unsigned int hooknum,
-@@ -35,13 +85,88 @@ mark_tg_v0(struct sk_buff *skb, const st
- 	return XT_CONTINUE;
- }
- 
-+extern DEFINE_PER_CPU(int, sknid_elevator);
 +
 +static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
 +                      __be32 daddr, __be16 dport,
@@ -246,167 +237,151 @@ diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/net/n
 +    read_unlock(&udp_hash_lock);
 +    return result;
 +}
-+
-+#define related(ct) (ct==(IP_CT_IS_REPLY + IP_CT_RELATED))
-+
  static unsigned int
- mark_tg_v1(struct sk_buff *skb, const struct net_device *in,
-            const struct net_device *out, unsigned int hooknum,
-            const struct xt_target *target, const void *targinfo)
+ mark_tg(struct sk_buff *skb, const struct net_device *in,
+         const struct net_device *out, unsigned int hooknum,
+         const struct xt_target *target, const void *targinfo)
  {
- 	const struct xt_mark_target_info_v1 *markinfo = targinfo;
--	int mark = 0;
-+		enum ip_conntrack_info ctinfo;
-+		struct sock *connection_sk;
-+		int dif;
-+		struct nf_conn *ct;
-+		extern struct inet_hashinfo tcp_hashinfo;
-+		enum ip_conntrack_dir dir;
-+		int *curtag;
-+		u_int32_t src_ip;
-+		u_int32_t dst_ip;
-+		u_int16_t proto, src_port;
-+		u_int32_t ip;
-+		u_int16_t port;
-+
-+		int mark = -1;
- 
- 	switch (markinfo->mode) {
- 	case XT_MARK_SET:
-@@ -55,9 +180,119 @@ mark_tg_v1(struct sk_buff *skb, const st
- 	case XT_MARK_OR:
- 		mark = skb->mark | markinfo->mark;
- 		break;
-+
-+	case XT_MARK_COPYXID: 
-+		dif = ((struct rtable *)(*pskb)->dst)->rt_iif;
-+
-+		ct = nf_ct_get((*pskb), &ctinfo);
-+		if (!ct) 
-+			break;
-+
-+		dir = CTINFO2DIR(ctinfo);
-+		src_ip = ct->tuplehash[dir].tuple.src.u3.ip;
-+		dst_ip = ct->tuplehash[dir].tuple.dst.u3.ip;
-+		src_port = get_src_port(&ct->tuplehash[dir].tuple);
-+		proto = ct->tuplehash[dir].tuple.dst.protonum;
-+
-+		ip = ct->tuplehash[dir].tuple.dst.u3.ip;
-+		port = get_dst_port(&ct->tuplehash[dir].tuple);
-+
-+		if (proto == 1) {
-+			if ((*pskb)->mark > 0)
-+				/* The packet is marked, it's going out */
-+				ct->xid[0] = (*pskb)->mark;
-+
-+			if (ct->xid[0] > 0)
-+				mark = ct->xid[0];
-+		}
-+		else if (proto == 17) {
-+			struct sock *sk;
-+			if (!(*pskb)->mark) {
-+				sk = __udp4_lib_lookup(src_ip, src_port,
-+					ip, port, dif, udp_hash);
-+
-+				if (sk && hooknum == NF_IP_LOCAL_IN)
-+					mark = sk->sk_nid;
-+
-+				if (sk)
-+					sock_put(sk);
-+			}
-+			else if ((*pskb)->mark > 0)
-+				/* The packet is marked, it's going out */
-+				ct->xid[0] = (*pskb)->mark;
-+		}
-+		else if (proto == 6) /* TCP */{
-+			int sockettype = 0; /* Established socket */
-+
-+			/* Looks for an established socket or a listening 
-+			   socket corresponding to the 4-tuple, in that order.
-+			   The order is important for Codemux connections
-+			   to be handled properly */
-+
-+			connection_sk = inet_lookup_established(&tcp_hashinfo,
-+				src_ip, src_port, ip, port, dif);
-+
-+			if (!connection_sk) {
-+				connection_sk = inet_lookup_listener(&tcp_hashinfo,
-+					ip, port, dif);
-+				sockettype = 1; /* Listening socket */
-+			}
-+
-+			if (connection_sk) {
-+				/* The peercred is not set. We set it if the other side has an xid. */
-+				if (!PEERCRED_SET(connection_sk->sk_peercred.uid)
-+					&& ct->xid[!dir] > 0 && (sockettype == 0)) {
-+					connection_sk->sk_peercred.gid = 
-+						connection_sk->sk_peercred.uid = ct->xid[!dir];
-+				}
-+
-+				/* The peercred is set, and is not equal to the XID of 'the other side' */
-+				else if (PEERCRED_SET(connection_sk->sk_peercred.uid) &&
-+					(connection_sk->sk_peercred.uid != ct->xid[!dir]) &&
-+					(sockettype == 0)) {
-+					mark = connection_sk->sk_peercred.uid;
-+				}
-+
-+				/* Has this connection already been tagged? */
-+				if (ct->xid[dir] < 1) {
-+					/* No - let's tag it */ 
-+					ct->xid[dir]=connection_sk->sk_nid;
-+				}
-+
-+				if (mark == -1 && (ct->xid[dir] != 0))
-+					mark = ct->xid[dir];
-+
-+				if (connection_sk->sk_state == TCP_TIME_WAIT) {
-+					inet_twsk_put(inet_twsk(connection_sk));
-+					break;
-+				} else
-+					sock_put(connection_sk);
-+			}
-+ 
-+			/* All else failed. Is this a connection over raw sockets?
-+			   That explains why we couldn't get anything out of skb->sk,
-+			   or look up a "real" connection. */
-+			if (ct->xid[dir] < 1) {
-+				if ((*pskb)->skb_tag)
-+					ct->xid[dir] = (*pskb)->skb_tag;
-+			}
-+
-+			/* Covers CoDemux case */
-+			if (mark < 1 && (ct->xid[dir] > 0))
-+				mark = ct->xid[dir];
-+
-+			if (mark < 1 && (ct->xid[!dir] > 0))
-+				mark = ct->xid[!dir];
-+			break;
-+		}
- 	}
-+	if (mark != -1)
-+		skb->mark = mark;
-+
-+	curtag = &__get_cpu_var(sknid_elevator);
-+	if (mark > 0 && *curtag == -2 && hooknum == NF_IP_LOCAL_IN) 
-+		*curtag = mark;
+ 	const struct xt_mark_tginfo2 *info = targinfo;
++    long mark = -1;
++    enum ip_conntrack_info ctinfo;
++    struct sock *connection_sk;
++    int dif;
++    struct nf_conn *ct;
++    extern struct inet_hashinfo tcp_hashinfo;
++    enum ip_conntrack_dir dir;
++    int *curtag;
++    u_int32_t src_ip;
++    u_int32_t dst_ip;
++    u_int16_t proto, src_port;
++    u_int32_t ip;
++    u_int16_t port;
++
++    if (info->mark == ~0U) {
++        /* copy-xid */
++        dif = ((struct rtable *)(skb->dst))->rt_iif;
++
++        ct = nf_ct_get(skb, &ctinfo);
++        if (!ct) 
++            goto out_mark_finish;
++
++        dir = CTINFO2DIR(ctinfo);
++        src_ip = ct->tuplehash[dir].tuple.src.u3.ip;
++        dst_ip = ct->tuplehash[dir].tuple.dst.u3.ip;
++        src_port = get_src_port(&ct->tuplehash[dir].tuple);
++        proto = ct->tuplehash[dir].tuple.dst.protonum;
++
++        ip = ct->tuplehash[dir].tuple.dst.u3.ip;
++        port = get_dst_port(&ct->tuplehash[dir].tuple);
++
++        if (proto == 1) {
++            if (skb->mark > 0)
++                /* The packet is marked, it's going out */
++                ct->xid[0] = skb->mark;
++
++            if (ct->xid[0] > 0)
++                mark = ct->xid[0];
++        }
++        else if (proto == 17) {
++            struct sock *sk;
++            if (!skb->mark) {
++                sk = __udp4_lib_lookup(src_ip, src_port,
++                        ip, port, dif, udp_hash);
++
++                if (sk && hooknum == NF_INET_LOCAL_IN)
++                    mark = sk->sk_nid;
++
++                if (sk)
++                    sock_put(sk);
++            }
++            else if (skb->mark > 0)
++                /* The packet is marked, it's going out */
++                ct->xid[0] = skb->mark;
++        }
++        else if (proto == 6) /* TCP */{
++            int sockettype = 0; /* Established socket */
++            struct net *net = &init_net;
++
++            /* Looks for an established socket or a listening 
++               socket corresponding to the 4-tuple, in that order.
++               The order is important for Codemux connections
++               to be handled properly */
++
++            connection_sk = inet_lookup_established(net,
++                    &tcp_hashinfo, src_ip, src_port, ip, port, dif);
++
++            if (!connection_sk) {
++                connection_sk = inet_lookup_listener(net,
++                        &tcp_hashinfo, ip, port, dif);
++                sockettype = 1; /* Listening socket */
++            }
++
++            if (connection_sk) {
++                /* The peercred is not set. We set it if the other side has an xid. */
++                if (!PEERCRED_SET(connection_sk->sk_peercred.uid)
++                        && ct->xid[!dir] > 0 && (sockettype == 0)) {
++                    connection_sk->sk_peercred.gid = 
++                        connection_sk->sk_peercred.uid = ct->xid[!dir];
++                }
++
++                /* The peercred is set, and is not equal to the XID of 'the other side' */
++                else if (PEERCRED_SET(connection_sk->sk_peercred.uid) &&
++                        (connection_sk->sk_peercred.uid != ct->xid[!dir]) &&
++                        (sockettype == 0)) {
++                    mark = connection_sk->sk_peercred.uid;
++                }
++
++                /* Has this connection already been tagged? */
++                if (ct->xid[dir] < 1) {
++                    /* No - let's tag it */ 
++                    ct->xid[dir]=connection_sk->sk_nid;
++                }
++
++                if (mark == -1 && (ct->xid[dir] != 0))
++                    mark = ct->xid[dir];
++
++                if (connection_sk->sk_state == TCP_TIME_WAIT) {
++                    inet_twsk_put(inet_twsk(connection_sk));
++                    goto out_mark_finish;
++                } else
++                    sock_put(connection_sk);
++            }
++
++            /* All else failed. Is this a connection over raw sockets?
++               That explains why we couldn't get anything out of skb->sk,
++               or look up a "real" connection. */
++            if (ct->xid[dir] < 1) {
++                if (skb->skb_tag)
++                    ct->xid[dir] = skb->skb_tag;
++            }
++
++            /* Covers CoDemux case */
++            if (mark < 1 && (ct->xid[dir] > 0))
++                mark = ct->xid[dir];
++
++            if (mark < 1 && (ct->xid[!dir] > 0))
++                mark = ct->xid[!dir];
++            goto out_mark_finish;
++        }
++    }
++    else
++        mark = (skb->mark & ~info->mask) ^ info->mark;
++
++out_mark_finish:
++    if (mark != -1)
++        skb->mark = mark;
++
++    curtag = &__get_cpu_var(sknid_elevator);
++    if (mark > 0 && *curtag == -2 && hooknum == NF_INET_LOCAL_IN) 
++        *curtag = mark;
  
--	skb->mark = mark;
+-	skb->mark = (skb->mark & ~info->mask) ^ info->mark;
  	return XT_CONTINUE;
  }
- 
-@@ -95,7 +330,8 @@ mark_tg_check_v1(const char *tablename, 
- 
- 	if (markinfo->mode != XT_MARK_SET
- 	    && markinfo->mode != XT_MARK_AND
--	    && markinfo->mode != XT_MARK_OR) {
-+	    && markinfo->mode != XT_MARK_OR
-+	    && markinfo->mode != XT_MARK_COPYXID) {
- 		printk(KERN_WARNING "MARK: unknown mode %u\n",
- 		       markinfo->mode);
- 		return false;
-diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/net/netfilter/xt_SETXID.c linux-2.6.27.10-vs2.3.x-P522/net/netfilter/xt_SETXID.c
---- linux-2.6.27.10-vs2.3.x-P/net/netfilter/xt_SETXID.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.27.10-vs2.3.x-P522/net/netfilter/xt_SETXID.c	2009-01-12 01:18:23.000000000 +0100
+
+diff -Nurb linux-2.6.27-521/net/netfilter/xt_SETXID.c linux-2.6.27-522-ol/net/netfilter/xt_SETXID.c
+--- linux-2.6.27-521/net/netfilter/xt_SETXID.c	1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.27-522-ol/net/netfilter/xt_SETXID.c	2009-06-02 10:02:16.000000000 -0400
 @@ -0,0 +1,79 @@
 +#include <linux/module.h>
 +#include <linux/skbuff.h>
@@ -487,117 +462,3 @@ diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-P/net/n
 +
 +module_init(init);
 +module_exit(fini);
-
-; fixup
-diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-PS-02.0/net/netfilter/nf_conntrack_core.c linux-2.6.27.10-vs2.3.x-PS-02.1/net/netfilter/nf_conntrack_core.c
---- linux-2.6.27.10-vs2.3.x-PS-02.0/net/netfilter/nf_conntrack_core.c	2009-01-25 02:29:31.000000000 +0100
-+++ linux-2.6.27.10-vs2.3.x-PS-02.1/net/netfilter/nf_conntrack_core.c	2009-01-24 23:22:04.000000000 +0100
-@@ -595,8 +595,8 @@ init_conntrack(const struct nf_conntrack
- 	/* Overload tuple linked list to put us in unconfirmed list. */
- 	hlist_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode, &unconfirmed);
- 
--	conntrack->xid[IP_CT_DIR_ORIGINAL] = -1;
--	conntrack->xid[IP_CT_DIR_REPLY] = -1;
-+	ct->xid[IP_CT_DIR_ORIGINAL] = -1;
-+	ct->xid[IP_CT_DIR_REPLY] = -1;
- 
- 	spin_unlock_bh(&nf_conntrack_lock);
- 
-diff -NurpP --exclude '*.orig' --exclude '*.rej' linux-2.6.27.10-vs2.3.x-PS-02.0/net/netfilter/xt_MARK.c linux-2.6.27.10-vs2.3.x-PS-02.1/net/netfilter/xt_MARK.c
---- linux-2.6.27.10-vs2.3.x-PS-02.0/net/netfilter/xt_MARK.c	2009-01-25 02:29:31.000000000 +0100
-+++ linux-2.6.27.10-vs2.3.x-PS-02.1/net/netfilter/xt_MARK.c	2009-01-25 00:06:34.000000000 +0100
-@@ -19,6 +19,7 @@
- #include <net/checksum.h>
- #include <net/route.h>
- #include <net/inet_hashtables.h>
-+#include <net/net_namespace.h>
- 
- #include <net/netfilter/nf_conntrack.h>
- #include <linux/netfilter/x_tables.h>
-@@ -182,9 +183,9 @@ mark_tg_v1(struct sk_buff *skb, const st
- 		break;
- 
- 	case XT_MARK_COPYXID: 
--		dif = ((struct rtable *)(*pskb)->dst)->rt_iif;
-+		dif = ((struct rtable *)(skb->dst))->rt_iif;
- 
--		ct = nf_ct_get((*pskb), &ctinfo);
-+		ct = nf_ct_get(skb, &ctinfo);
- 		if (!ct) 
- 			break;
- 
-@@ -198,43 +199,44 @@ mark_tg_v1(struct sk_buff *skb, const st
- 		port = get_dst_port(&ct->tuplehash[dir].tuple);
- 
- 		if (proto == 1) {
--			if ((*pskb)->mark > 0)
-+			if (skb->mark > 0)
- 				/* The packet is marked, it's going out */
--				ct->xid[0] = (*pskb)->mark;
-+				ct->xid[0] = skb->mark;
- 
- 			if (ct->xid[0] > 0)
- 				mark = ct->xid[0];
- 		}
- 		else if (proto == 17) {
- 			struct sock *sk;
--			if (!(*pskb)->mark) {
-+			if (!skb->mark) {
- 				sk = __udp4_lib_lookup(src_ip, src_port,
- 					ip, port, dif, udp_hash);
- 
--				if (sk && hooknum == NF_IP_LOCAL_IN)
-+				if (sk && hooknum == NF_INET_LOCAL_IN)
- 					mark = sk->sk_nid;
- 
- 				if (sk)
- 					sock_put(sk);
- 			}
--			else if ((*pskb)->mark > 0)
-+			else if (skb->mark > 0)
- 				/* The packet is marked, it's going out */
--				ct->xid[0] = (*pskb)->mark;
-+				ct->xid[0] = skb->mark;
- 		}
- 		else if (proto == 6) /* TCP */{
- 			int sockettype = 0; /* Established socket */
-+			struct net *net = &init_net;
- 
- 			/* Looks for an established socket or a listening 
- 			   socket corresponding to the 4-tuple, in that order.
- 			   The order is important for Codemux connections
- 			   to be handled properly */
- 
--			connection_sk = inet_lookup_established(&tcp_hashinfo,
--				src_ip, src_port, ip, port, dif);
-+			connection_sk = inet_lookup_established(net,
-+				&tcp_hashinfo, src_ip, src_port, ip, port, dif);
- 
- 			if (!connection_sk) {
--				connection_sk = inet_lookup_listener(&tcp_hashinfo,
--					ip, port, dif);
-+				connection_sk = inet_lookup_listener(net,
-+					&tcp_hashinfo, ip, port, dif);
- 				sockettype = 1; /* Listening socket */
- 			}
- 
-@@ -273,8 +275,8 @@ mark_tg_v1(struct sk_buff *skb, const st
- 			   That explains why we couldn't get anything out of skb->sk,
- 			   or look up a "real" connection. */
- 			if (ct->xid[dir] < 1) {
--				if ((*pskb)->skb_tag)
--					ct->xid[dir] = (*pskb)->skb_tag;
-+				if (skb->skb_tag)
-+					ct->xid[dir] = skb->skb_tag;
- 			}
- 
- 			/* Covers CoDemux case */
-@@ -290,7 +292,7 @@ mark_tg_v1(struct sk_buff *skb, const st
- 		skb->mark = mark;
- 
- 	curtag = &__get_cpu_var(sknid_elevator);
--	if (mark > 0 && *curtag == -2 && hooknum == NF_IP_LOCAL_IN) 
-+	if (mark > 0 && *curtag == -2 && hooknum == NF_INET_LOCAL_IN) 
- 		*curtag = mark;
- 
- 	return XT_CONTINUE;
-- 
2.47.0