Setting tag linux-2.6-27-38
[linux-2.6.git] / linux-2.6-522-iptables-connection-tagging.patch
index 4fb0b36..24939be 100644 (file)
@@ -1,6 +1,117 @@
+diff -Nurb linux-2.6.27-521/include/linux/netfilter/xt_MARK.h linux-2.6.27-522/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/include/linux/netfilter/xt_MARK.h 2009-12-10 12:09:35.000000000 -0500
+@@ -11,6 +11,7 @@
+       XT_MARK_SET=0,
+       XT_MARK_AND,
+       XT_MARK_OR,
++      XT_MARK_COPYXID,
+ };
+ struct xt_mark_target_info_v1 {
+diff -Nurb linux-2.6.27-521/include/linux/netfilter/xt_SETXID.h linux-2.6.27-522/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/include/linux/netfilter/xt_SETXID.h       2009-12-10 12:09:35.000000000 -0500
+@@ -0,0 +1,14 @@
++#ifndef _XT_SETXID_H_target
++#define _XT_SETXID_H_target
++
++/* Version 1 */
++enum {
++      XT_SET_PACKET_XID=0
++};
++
++struct xt_setxid_target_info_v1 {
++      unsigned long mark;
++      u_int8_t mode;
++};
++
++#endif /*_XT_SETXID_H_target*/
+diff -Nurb linux-2.6.27-521/include/linux/netfilter_ipv4/ipt_MARK.h linux-2.6.27-522/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/include/linux/netfilter_ipv4/ipt_MARK.h   2009-12-10 12:09:35.000000000 -0500
+@@ -12,6 +12,7 @@
+ #define IPT_MARK_SET  XT_MARK_SET
+ #define IPT_MARK_AND  XT_MARK_AND
+ #define       IPT_MARK_OR     XT_MARK_OR
++#define IPT_MARK_COPYXID      XT_MARK_COPYXID
+ #define ipt_mark_target_info_v1 xt_mark_target_info_v1
+diff -Nurb linux-2.6.27-521/include/linux/netfilter_ipv4/ipt_SETXID.h linux-2.6.27-522/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/include/linux/netfilter_ipv4/ipt_SETXID.h 2009-12-10 12:09:35.000000000 -0500
+@@ -0,0 +1,13 @@
++#ifndef _IPT_SETXID_H_target
++#define _IPT_SETXID_H_target
++
++/* Backwards compatibility for old userspace */
++
++#include <linux/netfilter/xt_SETXID.h>
++
++/* Version 1 */
++#define IPT_SET_PACKET_XID    XT_SET_PACKET_XID
++
++#define ipt_setxid_target_info_v1 xt_setxid_target_info_v1
++
++#endif /*_IPT_SETXID_H_target*/
+diff -Nurb linux-2.6.27-521/include/net/netfilter/nf_conntrack.h linux-2.6.27-522/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/include/net/netfilter/nf_conntrack.h      2009-12-10 12:09:35.000000000 -0500
+@@ -121,6 +121,9 @@
+       /* Storage reserved for other modules: */
+       union nf_conntrack_proto proto;
++      /* PLANETLAB. VNET-specific */
++      int xid[IP_CT_DIR_MAX];
++
+       /* Extensions */
+       struct nf_ct_ext *ext;
+diff -Nurb linux-2.6.27-521/net/netfilter/Kconfig linux-2.6.27-522/net/netfilter/Kconfig
+--- linux-2.6.27-521/net/netfilter/Kconfig     2008-10-09 18:13:53.000000000 -0400
++++ linux-2.6.27-522/net/netfilter/Kconfig     2009-12-10 12:09:35.000000000 -0500
+@@ -477,6 +477,13 @@
+         This option adds a "TCPOPTSTRIP" target, which allows you to strip
+         TCP options from TCP packets.
++config NETFILTER_XT_TARGET_SETXID
++      tristate '"SETXID" target support'
++      depends on NETFILTER_XTABLES
++      help
++        This option adds a `SETXID' target, which allows you to alter the
++        xid of a socket.
++
+ config NETFILTER_XT_MATCH_COMMENT
+       tristate  '"comment" match support'
+       depends on NETFILTER_XTABLES
+diff -Nurb linux-2.6.27-521/net/netfilter/Makefile linux-2.6.27-522/net/netfilter/Makefile
+--- linux-2.6.27-521/net/netfilter/Makefile    2008-10-09 18:13:53.000000000 -0400
++++ linux-2.6.27-522/net/netfilter/Makefile    2009-12-10 12:09:35.000000000 -0500
+@@ -38,6 +38,7 @@
+ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
+ # targets
++obj-$(CONFIG_NETFILTER_XT_TARGET_SETXID) += xt_SETXID.o
+ 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 -Nurb linux-2.6.27-521/net/netfilter/nf_conntrack_core.c linux-2.6.27-522/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/net/netfilter/nf_conntrack_core.c 2009-12-10 12:09:35.000000000 -0500
+@@ -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);
++      ct->xid[IP_CT_DIR_ORIGINAL] = -1;
++      ct->xid[IP_CT_DIR_REPLY] = -1;
++
+       spin_unlock_bh(&nf_conntrack_lock);
+       if (exp) {
 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
++++ linux-2.6.27-522/net/netfilter/xt_MARK.c   2009-12-16 01:39:55.000000000 -0500
 @@ -13,7 +13,13 @@
  #include <linux/module.h>
  #include <linux/skbuff.h>
@@ -24,7 +135,7 @@ diff -Nurb linux-2.6.27-521/net/netfilter/xt_MARK.c linux-2.6.27-522/net/netfilt
  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 @@
+@@ -61,14 +69,256 @@
        return XT_CONTINUE;
  }
  
@@ -69,63 +180,66 @@ diff -Nurb linux-2.6.27-521/net/netfilter/xt_MARK.c linux-2.6.27-522/net/netfilt
 +      }
 +}
 +
-+static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
-+                      __be32 daddr, __be16 dport,
-+                      int dif, struct hlist_head udptable[])
++static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
++              __be16 sport, __be32 daddr, __be16 dport,
++              int dif, struct hlist_head udptable[])
 +{
-+    struct sock *sk, *result = NULL;
-+    struct hlist_node *node;
-+    unsigned short hnum = ntohs(dport);
-+    int badness = -1;
-+
-+    read_lock(&udp_hash_lock);
-+
-+    sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
-+        struct inet_sock *inet = inet_sk(sk);
-+
-+        if (sk->sk_hash == hnum && !ipv6_only_sock(sk)) {
-+            int score = (sk->sk_family == PF_INET ? 1 : 0);
-+
-+            if (inet->rcv_saddr) {
-+                if (inet->rcv_saddr != daddr)
-+                    continue;
-+                score+=2;
-+            } else {
-+                /* block non nx_info ips */
-+                if (!v4_addr_in_nx_info(sk->sk_nx_info,
-+                    daddr, NXA_MASK_BIND))
-+                    continue;
-+            }
-+            if (inet->daddr) {
-+                if (inet->daddr != saddr)
-+                    continue;
-+                score+=2;
-+            }
-+            if (inet->dport) {
-+                if (inet->dport != sport)
-+                    continue;
-+                score+=2;
-+            }
-+            if (sk->sk_bound_dev_if) {
-+                if (sk->sk_bound_dev_if != dif)
-+                    continue;
-+                score+=2;
-+            }
-+            if (score == 9) {
-+                result = sk;
-+                break;
-+            } else if (score > badness) {
-+                result = sk;
-+                badness = score;
-+            }
-+        }
-+    }
++      struct sock *sk, *result = NULL;
++      struct hlist_node *node;
++      unsigned short hnum = ntohs(dport);
++      int badness = -1;
++
++      read_lock(&udp_hash_lock);
++      sk_for_each(sk, node, &udptable[udp_hashfn(net, hnum)]) {
++              struct inet_sock *inet = inet_sk(sk);
++
++              if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum &&
++                              !ipv6_only_sock(sk)) {
++                      int score = (sk->sk_family == PF_INET ? 1 : 0);
++
++                      if (inet->rcv_saddr) {
++                              if (inet->rcv_saddr != daddr)
++                                      continue;
++                              score+=2;
++                      } else {
++                              /* block non nx_info ips */
++                              if (!v4_addr_in_nx_info(sk->sk_nx_info,
++                                      daddr, NXA_MASK_BIND))
++                                      continue;
++                      }
++                      if (inet->daddr) {
++                              if (inet->daddr != saddr)
++                                      continue;
++                              score+=2;
++                      }
++                      if (inet->dport) {
++                              if (inet->dport != sport)
++                                      continue;
++                              score+=2;
++                      }
++                      if (sk->sk_bound_dev_if) {
++                              if (sk->sk_bound_dev_if != dif)
++                                      continue;
++                              score+=2;
++                      }
++                      if (score == 9) {
++                              result = sk;
++                              break;
++                      } else if (score > badness) {
++                              result = sk;
++                              badness = score;
++                      }
++              }
++      }
 +
-+    if (result)
-+        sock_hold(result);
-+    read_unlock(&udp_hash_lock);
-+    return result;
++      if (result)
++              sock_hold(result);
++      read_unlock(&udp_hash_lock);
++      return result;
 +}
++
++int onceonly = 1;
++
  static unsigned int
  mark_tg(struct sk_buff *skb, const struct net_device *in,
          const struct net_device *out, unsigned int hooknum,
@@ -146,7 +260,18 @@ diff -Nurb linux-2.6.27-521/net/netfilter/xt_MARK.c linux-2.6.27-522/net/netfilt
 +    u_int32_t ip;
 +    u_int16_t port;
 +
++    
 +    if (info->mark == ~0U) {
++        // As of 2.6.27.39, Dec 8 2009, 
++        // NetNS + VNET = Trouble
++        // Let's handle this as a special case
++        struct net *net = dev_net(skb->dev);
++        if (!net_eq(net, &init_net)) {
++            WARN_ON(onceonly);
++            onceonly = 0;
++            return XT_CONTINUE;
++        }
++
 +        /* copy-xid */
 +        dif = ((struct rtable *)(skb->dst))->rt_iif;
 +
@@ -174,7 +299,7 @@ diff -Nurb linux-2.6.27-521/net/netfilter/xt_MARK.c linux-2.6.27-522/net/netfilt
 +        else if (proto == 17) {
 +            struct sock *sk;
 +            if (!skb->mark) {
-+                sk = __udp4_lib_lookup(src_ip, src_port,
++                sk = __udp4_lib_lookup(net,src_ip, src_port,
 +                        ip, port, dif, udp_hash);
 +
 +                if (sk && hooknum == NF_INET_LOCAL_IN)
@@ -189,7 +314,6 @@ diff -Nurb linux-2.6.27-521/net/netfilter/xt_MARK.c linux-2.6.27-522/net/netfilt
 +        }
 +        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.
@@ -206,6 +330,11 @@ diff -Nurb linux-2.6.27-521/net/netfilter/xt_MARK.c linux-2.6.27-522/net/netfilt
 +            }
 +
 +            if (connection_sk) {
++                if (connection_sk->sk_state == TCP_TIME_WAIT) {
++                    inet_twsk_put(inet_twsk(connection_sk));
++                    goto out_mark_finish;
++                }
++
 +                /* 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)) {
@@ -229,11 +358,7 @@ diff -Nurb linux-2.6.27-521/net/netfilter/xt_MARK.c linux-2.6.27-522/net/netfilt
 +                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);
++                sock_put(connection_sk);
 +            }
 +
 +            /* All else failed. Is this a connection over raw sockets?
@@ -268,542 +393,86 @@ diff -Nurb linux-2.6.27-521/net/netfilter/xt_MARK.c linux-2.6.27-522/net/netfilt
        return XT_CONTINUE;
  }
  
-diff -Nurb linux-2.6.27-521/net/netfilter/xt_MARK.c.orig linux-2.6.27-522/net/netfilter/xt_MARK.c.orig
---- linux-2.6.27-521/net/netfilter/xt_MARK.c.orig      1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.27-522/net/netfilter/xt_MARK.c.orig      2009-06-02 10:14:55.000000000 -0400
-@@ -0,0 +1,381 @@
-+/*
-+ *    xt_MARK - Netfilter module to modify the NFMARK field of an skb
-+ *
-+ *    (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
-+ *    Copyright © CC Computer Consultants GmbH, 2007 - 2008
-+ *    Jan Engelhardt <jengelh@computergmbh.de>
-+ *
-+ *    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_SETXID.c linux-2.6.27-522/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/net/netfilter/xt_SETXID.c 2009-12-10 12:09:35.000000000 -0500
+@@ -0,0 +1,79 @@
 +#include <linux/module.h>
 +#include <linux/skbuff.h>
 +#include <linux/ip.h>
 +#include <net/checksum.h>
++#include <linux/vs_network.h>
 +
 +#include <linux/netfilter/x_tables.h>
-+#include <linux/netfilter/xt_MARK.h>
++#include <linux/netfilter/xt_SETXID.h>
 +
 +MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
-+MODULE_DESCRIPTION("Xtables: packet mark modification");
-+MODULE_ALIAS("ipt_MARK");
-+MODULE_ALIAS("ip6t_MARK");
-+
-+static unsigned int
-+mark_tg_v0(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 *markinfo = targinfo;
-+
-+      skb->mark = markinfo->mark;
-+      return XT_CONTINUE;
-+}
++MODULE_AUTHOR("");
++MODULE_DESCRIPTION("");
++MODULE_ALIAS("ipt_SETXID");
 +
 +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)
++target_v1(struct sk_buff **pskb,
++        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;
-+
-+      switch (markinfo->mode) {
-+      case XT_MARK_SET:
-+              mark = markinfo->mark;
-+              break;
-+
-+      case XT_MARK_AND:
-+              mark = skb->mark & markinfo->mark;
-+              break;
++      const struct xt_setxid_target_info_v1 *setxidinfo = targinfo;
 +
-+      case XT_MARK_OR:
-+              mark = skb->mark | markinfo->mark;
++      switch (setxidinfo->mode) {
++      case XT_SET_PACKET_XID:
++               (*pskb)->skb_tag = setxidinfo->mark;
 +              break;
 +      }
-+
-+      skb->mark = mark;
 +      return XT_CONTINUE;
 +}
 +
-+static unsigned int
-+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_tginfo2 *info = targinfo;
-+    long mark = -1;
-+
-+    if (info->mark == ~0U) {
-+        /* copy-xid */
-+        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;
-+
-+        dif = ((struct rtable *)(skb->dst))->rt_iif;
-+
-+        ct = nf_ct_get(skb, &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 (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));
-+                    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 (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];
-+            break;
-+        }
-+    }
-+    else
-+          mark = (skb->mark & ~info->mask) ^ info->mark;
-+
-+    if (mark != -1)
-+              skb->mark = mark;
-+
-+      curtag = &__get_cpu_var(sknid_elevator);
-+      if (mark > 0 && *curtag == -2 && hooknum == NF_INET_LOCAL_IN) 
-+              *curtag = mark;
-+
-+      return XT_CONTINUE;
-+}
-+
-+static bool
-+mark_tg_check_v0(const char *tablename, const void *entry,
-+                 const struct xt_target *target, void *targinfo,
-+                 unsigned int hook_mask)
++static int
++checkentry_v1(const char *tablename,
++            const void *entry,
++            const struct xt_target *target,
++            void *targinfo,
++            unsigned int hook_mask)
 +{
-+      const struct xt_mark_target_info *markinfo = targinfo;
-+
-+      if (markinfo->mark > 0xffffffff) {
-+              printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
-+              return false;
-+      }
-+      return true;
-+}
++      struct xt_setxid_target_info_v1 *setxidinfo = targinfo;
 +
-+static bool
-+mark_tg_check_v1(const char *tablename, const void *entry,
-+                 const struct xt_target *target, void *targinfo,
-+                 unsigned int hook_mask)
-+{
-+      const struct xt_mark_target_info_v1 *markinfo = targinfo;
-+
-+      if (markinfo->mode != XT_MARK_SET
-+          && markinfo->mode != XT_MARK_AND
-+          && markinfo->mode != XT_MARK_OR) {
-+              printk(KERN_WARNING "MARK: unknown mode %u\n",
-+                     markinfo->mode);
-+              return false;
-+      }
-+      if (markinfo->mark > 0xffffffff) {
-+              printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
-+              return false;
++      if (setxidinfo->mode != XT_SET_PACKET_XID) {
++              printk(KERN_WARNING "SETXID: unknown mode %u\n",
++                     setxidinfo->mode);
++              return 0;
 +      }
-+      return true;
-+}
-+
-+#ifdef CONFIG_COMPAT
-+struct compat_xt_mark_target_info {
-+      compat_ulong_t  mark;
-+};
 +
-+static void mark_tg_compat_from_user_v0(void *dst, void *src)
-+{
-+      const struct compat_xt_mark_target_info *cm = src;
-+      struct xt_mark_target_info m = {
-+              .mark   = cm->mark,
-+      };
-+      memcpy(dst, &m, sizeof(m));
++      return 1;
 +}
 +
-+static int mark_tg_compat_to_user_v0(void __user *dst, void *src)
-+{
-+      const struct xt_mark_target_info *m = src;
-+      struct compat_xt_mark_target_info cm = {
-+              .mark   = m->mark,
-+      };
-+      return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
-+}
-+
-+struct compat_xt_mark_target_info_v1 {
-+      compat_ulong_t  mark;
-+      u_int8_t        mode;
-+      u_int8_t        __pad1;
-+      u_int16_t       __pad2;
-+};
-+
-+static void mark_tg_compat_from_user_v1(void *dst, void *src)
-+{
-+      const struct compat_xt_mark_target_info_v1 *cm = src;
-+      struct xt_mark_target_info_v1 m = {
-+              .mark   = cm->mark,
-+              .mode   = cm->mode,
-+      };
-+      memcpy(dst, &m, sizeof(m));
-+}
-+
-+static int mark_tg_compat_to_user_v1(void __user *dst, void *src)
-+{
-+      const struct xt_mark_target_info_v1 *m = src;
-+      struct compat_xt_mark_target_info_v1 cm = {
-+              .mark   = m->mark,
-+              .mode   = m->mode,
-+      };
-+      return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
-+}
-+#endif /* CONFIG_COMPAT */
-+
-+static struct xt_target mark_tg_reg[] __read_mostly = {
-+      {
-+              .name           = "MARK",
-+              .family         = AF_INET,
-+              .revision       = 0,
-+              .checkentry     = mark_tg_check_v0,
-+              .target         = mark_tg_v0,
-+              .targetsize     = sizeof(struct xt_mark_target_info),
-+#ifdef CONFIG_COMPAT
-+              .compatsize     = sizeof(struct compat_xt_mark_target_info),
-+              .compat_from_user = mark_tg_compat_from_user_v0,
-+              .compat_to_user = mark_tg_compat_to_user_v0,
-+#endif
-+              .table          = "mangle",
-+              .me             = THIS_MODULE,
-+      },
++static struct xt_target xt_setxid_target[] = {
 +      {
-+              .name           = "MARK",
++              .name           = "SETXID",
 +              .family         = AF_INET,
 +              .revision       = 1,
-+              .checkentry     = mark_tg_check_v1,
-+              .target         = mark_tg_v1,
-+              .targetsize     = sizeof(struct xt_mark_target_info_v1),
-+#ifdef CONFIG_COMPAT
-+              .compatsize     = sizeof(struct compat_xt_mark_target_info_v1),
-+              .compat_from_user = mark_tg_compat_from_user_v1,
-+              .compat_to_user = mark_tg_compat_to_user_v1,
-+#endif
-+              .table          = "mangle",
-+              .me             = THIS_MODULE,
-+      },
-+      {
-+              .name           = "MARK",
-+              .family         = AF_INET6,
-+              .revision       = 0,
-+              .checkentry     = mark_tg_check_v0,
-+              .target         = mark_tg_v0,
-+              .targetsize     = sizeof(struct xt_mark_target_info),
-+#ifdef CONFIG_COMPAT
-+              .compatsize     = sizeof(struct compat_xt_mark_target_info),
-+              .compat_from_user = mark_tg_compat_from_user_v0,
-+              .compat_to_user = mark_tg_compat_to_user_v0,
-+#endif
-+              .table          = "mangle",
-+              .me             = THIS_MODULE,
-+      },
-+      {
-+              .name           = "MARK",
-+              .family         = AF_INET6,
-+              .revision       = 1,
-+              .checkentry     = mark_tg_check_v1,
-+              .target         = mark_tg_v1,
-+              .targetsize     = sizeof(struct xt_mark_target_info_v1),
-+#ifdef CONFIG_COMPAT
-+              .compatsize     = sizeof(struct compat_xt_mark_target_info_v1),
-+              .compat_from_user = mark_tg_compat_from_user_v1,
-+              .compat_to_user = mark_tg_compat_to_user_v1,
-+#endif
++              .checkentry     = checkentry_v1,
++              .target         = target_v1,
++              .targetsize     = sizeof(struct xt_setxid_target_info_v1),
 +              .table          = "mangle",
 +              .me             = THIS_MODULE,
-+      },
-+      {
-+              .name           = "MARK",
-+              .revision       = 2,
-+              .family         = AF_INET,
-+              .target         = mark_tg,
-+              .targetsize     = sizeof(struct xt_mark_tginfo2),
-+              .me             = THIS_MODULE,
-+      },
-+      {
-+              .name           = "MARK",
-+              .revision       = 2,
-+              .family         = AF_INET6,
-+              .target         = mark_tg,
-+              .targetsize     = sizeof(struct xt_mark_tginfo2),
-+              .me             = THIS_MODULE,
-+      },
++      }
 +};
 +
-+static int __init mark_tg_init(void)
++static int __init init(void)
 +{
-+      return xt_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
++      int err;
++
++      err = xt_register_targets(xt_setxid_target, ARRAY_SIZE(xt_setxid_target));
++      return err;
 +}
 +
-+static void __exit mark_tg_exit(void)
++static void __exit fini(void)
 +{
-+      xt_unregister_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
++      xt_unregister_targets(xt_setxid_target, ARRAY_SIZE(xt_setxid_target));
 +}
 +
-+module_init(mark_tg_init);
-+module_exit(mark_tg_exit);
-diff -Nurb linux-2.6.27-521/scripts/basic/.docproc.cmd linux-2.6.27-522/scripts/basic/.docproc.cmd
---- linux-2.6.27-521/scripts/basic/.docproc.cmd        1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.27-522/scripts/basic/.docproc.cmd        2009-06-02 10:59:54.000000000 -0400
-@@ -0,0 +1,68 @@
-+cmd_scripts/basic/docproc := gcc -Wp,-MD,scripts/basic/.docproc.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer     -o scripts/basic/docproc scripts/basic/docproc.c  
-+
-+deps_scripts/basic/docproc := \
-+  scripts/basic/docproc.c \
-+  /usr/include/stdio.h \
-+  /usr/include/features.h \
-+  /usr/include/sys/cdefs.h \
-+  /usr/include/bits/wordsize.h \
-+  /usr/include/gnu/stubs.h \
-+  /usr/include/gnu/stubs-32.h \
-+  /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/include/stddef.h \
-+  /usr/include/bits/types.h \
-+  /usr/include/bits/typesizes.h \
-+  /usr/include/libio.h \
-+  /usr/include/_G_config.h \
-+  /usr/include/wchar.h \
-+  /usr/include/bits/wchar.h \
-+  /usr/include/gconv.h \
-+  /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/include/stdarg.h \
-+  /usr/include/bits/stdio_lim.h \
-+  /usr/include/bits/sys_errlist.h \
-+  /usr/include/bits/stdio.h \
-+  /usr/include/stdlib.h \
-+  /usr/include/sys/types.h \
-+  /usr/include/time.h \
-+  /usr/include/endian.h \
-+  /usr/include/bits/endian.h \
-+  /usr/include/sys/select.h \
-+  /usr/include/bits/select.h \
-+  /usr/include/bits/sigset.h \
-+  /usr/include/bits/time.h \
-+  /usr/include/sys/sysmacros.h \
-+  /usr/include/bits/pthreadtypes.h \
-+  /usr/include/alloca.h \
-+  /usr/include/string.h \
-+  /usr/include/bits/string.h \
-+  /usr/include/bits/string2.h \
-+  /usr/include/ctype.h \
-+  /usr/include/unistd.h \
-+  /usr/include/bits/posix_opt.h \
-+  /usr/include/bits/confname.h \
-+  /usr/include/getopt.h \
-+  /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/include/limits.h \
-+  /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/include/syslimits.h \
-+  /usr/include/limits.h \
-+  /usr/include/bits/posix1_lim.h \
-+  /usr/include/bits/local_lim.h \
-+  /usr/include/linux/limits.h \
-+  /usr/include/bits/posix2_lim.h \
-+  /usr/include/sys/wait.h \
-+  /usr/include/signal.h \
-+  /usr/include/bits/signum.h \
-+  /usr/include/bits/siginfo.h \
-+  /usr/include/bits/sigaction.h \
-+  /usr/include/bits/sigcontext.h \
-+  /usr/include/asm/sigcontext.h \
-+  /usr/include/asm/types.h \
-+  /usr/include/asm-generic/int-ll64.h \
-+  /usr/include/bits/sigstack.h \
-+  /usr/include/bits/sigthread.h \
-+  /usr/include/sys/resource.h \
-+  /usr/include/bits/resource.h \
-+  /usr/include/bits/waitflags.h \
-+  /usr/include/bits/waitstatus.h \
-+
-+scripts/basic/docproc: $(deps_scripts/basic/docproc)
-+
-+$(deps_scripts/basic/docproc):
-diff -Nurb linux-2.6.27-521/scripts/basic/.fixdep.cmd linux-2.6.27-522/scripts/basic/.fixdep.cmd
---- linux-2.6.27-521/scripts/basic/.fixdep.cmd 1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.27-522/scripts/basic/.fixdep.cmd 2009-06-02 10:59:54.000000000 -0400
-@@ -0,0 +1,76 @@
-+cmd_scripts/basic/fixdep := gcc -Wp,-MD,scripts/basic/.fixdep.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer     -o scripts/basic/fixdep scripts/basic/fixdep.c  
-+
-+deps_scripts/basic/fixdep := \
-+  scripts/basic/fixdep.c \
-+    $(wildcard include/config/his/driver.h) \
-+    $(wildcard include/config/my/option.h) \
-+    $(wildcard include/config/.h) \
-+    $(wildcard include/config/foo.h) \
-+    $(wildcard include/config/boom.h) \
-+  /usr/include/sys/types.h \
-+  /usr/include/features.h \
-+  /usr/include/sys/cdefs.h \
-+  /usr/include/bits/wordsize.h \
-+  /usr/include/gnu/stubs.h \
-+  /usr/include/gnu/stubs-32.h \
-+  /usr/include/bits/types.h \
-+  /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/include/stddef.h \
-+  /usr/include/bits/typesizes.h \
-+  /usr/include/time.h \
-+  /usr/include/endian.h \
-+  /usr/include/bits/endian.h \
-+  /usr/include/sys/select.h \
-+  /usr/include/bits/select.h \
-+  /usr/include/bits/sigset.h \
-+  /usr/include/bits/time.h \
-+  /usr/include/sys/sysmacros.h \
-+  /usr/include/bits/pthreadtypes.h \
-+  /usr/include/sys/stat.h \
-+  /usr/include/bits/stat.h \
-+  /usr/include/sys/mman.h \
-+  /usr/include/bits/mman.h \
-+  /usr/include/unistd.h \
-+  /usr/include/bits/posix_opt.h \
-+  /usr/include/bits/confname.h \
-+  /usr/include/getopt.h \
-+  /usr/include/fcntl.h \
-+  /usr/include/bits/fcntl.h \
-+  /usr/include/string.h \
-+  /usr/include/bits/string.h \
-+  /usr/include/bits/string2.h \
-+  /usr/include/stdlib.h \
-+  /usr/include/alloca.h \
-+  /usr/include/stdio.h \
-+  /usr/include/libio.h \
-+  /usr/include/_G_config.h \
-+  /usr/include/wchar.h \
-+  /usr/include/bits/wchar.h \
-+  /usr/include/gconv.h \
-+  /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/include/stdarg.h \
-+  /usr/include/bits/stdio_lim.h \
-+  /usr/include/bits/sys_errlist.h \
-+  /usr/include/bits/stdio.h \
-+  /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/include/limits.h \
-+  /usr/lib/gcc/i686-pc-linux-gnu/4.1.1/include/syslimits.h \
-+  /usr/include/limits.h \
-+  /usr/include/bits/posix1_lim.h \
-+  /usr/include/bits/local_lim.h \
-+  /usr/include/linux/limits.h \
-+  /usr/include/bits/posix2_lim.h \
-+  /usr/include/ctype.h \
-+  /usr/include/arpa/inet.h \
-+  /usr/include/netinet/in.h \
-+  /usr/include/stdint.h \
-+  /usr/include/sys/socket.h \
-+  /usr/include/sys/uio.h \
-+  /usr/include/bits/uio.h \
-+  /usr/include/bits/socket.h \
-+  /usr/include/bits/sockaddr.h \
-+  /usr/include/asm/socket.h \
-+  /usr/include/asm/sockios.h \
-+  /usr/include/bits/in.h \
-+  /usr/include/bits/byteswap.h \
-+
-+scripts/basic/fixdep: $(deps_scripts/basic/fixdep)
-+
-+$(deps_scripts/basic/fixdep):
-Files linux-2.6.27-521/scripts/basic/docproc and linux-2.6.27-522/scripts/basic/docproc differ
-Files linux-2.6.27-521/scripts/basic/fixdep and linux-2.6.27-522/scripts/basic/fixdep differ
++module_init(init);
++module_exit(fini);