Hello again,

On Monday 25 February 2002 16:50, Harald Welte wrote:
> sorry, one remaining issue:
> for performance reasons, we should create the copy of 'userspace' only
> if there is a $patch.userspace file present in the patch-o-matic
> repository. This saves time since we don't need to copy the whole userspace
> tree around.

Fixed.

> Maybe also print a big WARNING message, that the user _needs_ to rebuild
> and recompile the iptables command (only in case he has used one or more
> .userspace patches).

Fixed, it will warn the user everytime he applies a patch that contains a .userspace

> Not applied to CVS until this is resolved.

This should work as you exepect now.
You'll find attach a set of patches for the latest CVS tree,
with the same names as contained in the previous mail I sent. Just overwrite
all the files, as the patches have changed slightely to include
the warnings you advised.

Have a nice day,

Fabrice.
--
Fabrice MARIE
Senior R&D Engineer
Celestix Networks
http://www.celestix.com/

"Silly hacker, root is for administrators" 
       -Unknown
diff -uNr cvs/nefilter/userspace/patch-o-matic/runme netfilter/userspace/patch-o-matic/runme
--- cvs/nefilter/userspace/patch-o-matic/runme	Mon Feb 25 18:32:27 2002
+++ netfilter/userspace/patch-o-matic/runme	Mon Feb 25 19:12:50 2002
@@ -4,6 +4,8 @@
 #		- added support for other protocols than ipv4
 # Tue 12 Feb 2002 Bob Hockney <[EMAIL PROTECTED]>
 #		- added support for reverting patches out
+# Fri 22 Feb 2002 Fabrice MARIE <[EMAIL PROTECTED]>
+#               - added support for userspace/ patches
 #
 
 # set -x
@@ -280,21 +282,56 @@
 test_patch()
 {
     KTMPDIR=`tmpdirname`
+    if [ -e $1.userspace ];
+    then
+        UTMPDIR=`tmpdirname`
+    fi
     # I'm really paranoid.  What if there's no /dev/urandom?
-    if test -z "$KTMPDIR"; then
-        echo Failed to generate tmpdirname: perhaps your /dev/urandom is broken >&2
+    if [ -z "$KTMPDIR" ]; then
+        echo Failed to generate kernel tmpdirname: perhaps your /dev/urandom is broken >&2
 	exit 1
     fi
+    if [ -e $1.userspace ];
+    then
+        if [ -z "$UTMPDIR" ]; then
+            echo Failed to generate userspace tmpdirname: perhaps your /dev/urandom is broken >&2
+	    exit 1
+	fi
+    fi
     KTMPDIR=$KERNEL_DIR/../$KTMPDIR
+    if [ -e $1.userspace ];
+    then
+        UTMPDIR=/tmp/$UTMPDIR
+    fi
+         
     # On exit, clean up
-    trap "rm -rf $KTMPDIR" 0
+    if [ -e $1.userspace ];
+    then
+    	trap "rm -rf $KTMPDIR $UTMPDIR" 0
+    else
+    	trap "rm -rf $KTMPDIR" 0
+    fi
     if cp -al $KERNEL_DIR/. $KTMPDIR
     then :
     else
 	echo Failed to make copy of $KERNEL_DIR >&2
 	rm -rf $KTMPDIR
+	if [ -e $1.userspace ];
+	then
+	    rm -rf $UTMPDIR
+	fi
 	exit 1
     fi
+    if [ -e $1.userspace ];
+    then
+        if cp -al $NETFILTERDIR/. $UTMPDIR
+        then :
+    	else
+            echo Failed to make copy of $NETFILTERDIR >&2
+            rm -rf $KTMPDIR $UTMPDIR
+            exit 1
+        fi
+    fi
 
     echo Testing patch $1...
 
@@ -305,26 +342,66 @@
     then :
     else
 	rm -rf $KTMPDIR
+	if [ -e $1.userspace ];
+	then
+	    rm -rf $UTMPDIR
+	fi
 	return 1
     fi
 
     REJECTSBEFORE="`find $KTMPDIR/. -name '*.rej' -exec cat {} \; | grep -c '^\*\*\* '`"
+    if [ -e $1.userspace ];
+    then
+        REJECTSBEFOREU="`find $UTMPDIR/. -name '*.rej' -exec cat {} \; | grep -c '^\*\*\* '`"
+    fi
     if (cd $KTMPDIR && if [ $MODE ]; then patch -R -p1; else patch -p1; fi >/dev/null) < $1
     then :
     else
 	echo Failed to patch copy of $KERNEL_DIR >&2
 	rm -rf $KTMPDIR
+	if [ -e $1.userspace ];
+	then
+	    rm -rf $UTMPDIR
+	fi
 	return 1
     fi
+    if [ -e $1.userspace ];
+    then
+        if (cd $UTMPDIR && if [ $MODE ]; then patch -R -p0; else patch -p0; fi >/dev/null) < $1.userspace
+        then :
+        else
+            echo Failed to patch copy of $NETFILTERDIR >&2
+            rm -rf $KTMPDIR $UTMPDIR
+	    return 1
+        fi
+    fi
     REJECTSAFTER="`find $KTMPDIR/. -name '*.rej' -exec cat {} \; | grep -c '^\*\*\* '`"
-	
-    if [ "$REJECTSBEFORE" -ne "$REJECTSAFTER" ]
+    if [ -e $1.userspace ];
     then
-	echo Patch $1 seems to have had rejects \(`expr $REJECTSAFTER - $REJECTSBEFORE` new rejections\) >&2
-	rm -rf $KTMPDIR
-	return 1
+        REJECTSAFTERU="`find $UTMPDIR/. -name '*.rej' -exec cat {} \; | grep -c '^\*\*\* '`"
+    fi
+
+    if [ -e $1.userspace ];
+    then
+        if [ "$REJECTSBEFORE" -ne "$REJECTSAFTER" ] || [ "$REJECTSBEFOREU" -ne "$REJECTSAFTERU" ];
+        then
+            echo Patch $1 seems to have had rejects \(`expr $REJECTSAFTER + $REJECTSAFTERU - $REJECTSBEFORE - $REJECTSBEFOREU` new rejections\) >&2
+            rm -rf $KTMPDIR $UTMPDIR
+            return 1
+        fi
+    else
+        if [ "$REJECTSBEFORE" -ne "$REJECTSAFTER" ];
+        then
+            echo Patch $1 seems to have had rejects \(`expr $REJECTSAFTER - $REJECTSBEFORE` new rejections\) >&2
+	    rm -rf $KTMPDIR
+	    return 1
+        fi
     fi
     rm -rf $KTMPDIR
+    if [ -e $1.userspace ];
+    then
+        rm -rf $UTMPDIR
+    fi
 
     echo "   Patch $1 `modesense 2` cleanly."
     return 0
@@ -335,20 +412,53 @@
 {
     echo `modesense 3` patch $1...
     REJECTSBEFORE="`find $KERNEL_DIR/. -name '*.rej' -exec cat {} \; | grep -c '^\*\*\* '`"
+    if [ -e $1.userspace ];
+    then
+        REJECTSBEFOREU="`find $NETFILTERDIR/. -name '*.rej' -exec cat {} \; | grep -c '^\*\*\* '`"
+    fi
     if (cd $KERNEL_DIR && if [ $MODE ]; then patch -R -p1; else patch -p1; fi > /dev/null) < $1
     then :
     else
 	echo Failed to patch $KERNEL_DIR >&2
 	return 1
     fi
+    if [ -e $1.userspace ];
+    then
+        if (cd $NETFILTERDIR && if [ $MODE ]; then patch -R -p0; else patch -p0; fi > /dev/null) < $1.userspace
+        then :
+        else
+            echo Failed to patch $NETFILTERDIR >&2
+            return 1
+        fi
+    fi
     REJECTSAFTER="`find $KERNEL_DIR/. -name '*.rej' -exec cat {} \; | grep -c '^\*\*\* '`"
+    if [ -e $1.userspace ];
+    then
+        REJECTSAFTERU="`find $NETFILTERDIR/. -name '*.rej' -exec cat {} \; | grep -c '^\*\*\* '`"
+    fi
 
-    if [ $REJECTSBEFORE -ne $REJECTSAFTER ]
+    if [ -e $1.userspace ];
     then
-	echo WARNING: patch $1 seems to have had rejects \(`expr $REJECTSAFTER - $REJECTSBEFORE` new rejections\):
-	find $KERNEL_DIR/. -name '*rej'
+        if [ "$REJECTSBEFORE" -ne "$REJECTSAFTER" ] || [ "$REJECTSBEFOREU" -ne "$REJECTSAFTERU" ];
+        then
+            echo WARNING: patch $1 seems to have had rejects \(`expr $REJECTSAFTER + $REJECTSAFTERU - $REJECTSBEFORE - $REJECTSBEFOREU` new rejections\):
+	    find $KERNEL_DIR/. -name '*rej'
+	    find $NETFILTERDIR/. -name '*rej'
+        else
+	    echo "   Patch $1 `modesense 2` cleanly."
+	    echo "   *******************"
+	    echo "   ***** WARNING ***** You have applied a userspace patch, so do not forget to recompile"
+	    echo "   ******************* and re-install iptables."
+	    echo "   *******************"
+        fi
     else
-	echo "   Patch $1 `modesense 2` cleanly."
+        if [ "$REJECTSBEFORE" -ne "$REJECTSAFTER" ];
+        then
+            echo WARNING: patch $1 seems to have had rejects \(`expr $REJECTSAFTER - $REJECTSBEFORE` new rejections\):
+	    find $KERNEL_DIR/. -name '*rej'
+        else
+	    echo "   Patch $1 `modesense 2` cleanly."
+        fi
     fi
     apply_config_in_changes $1 $KERNEL_DIR/net/$2/netfilter/
     apply_config_help_changes $1 $KERNEL_DIR/Documentation/
@@ -589,6 +699,8 @@
     exit 1
 fi 
 
+export NETFILTERDIR=`cd ..; pwd`
+
 # Check to see if we are applying or reversing patches
 MODE=
 if [ $1 = reverse ]; then
diff -uNr cvs/nefilter/userspace/patch-o-matic/base/ipt_REJECT-fake-source.patch netfilter/userspace/patch-o-matic/base/ipt_REJECT-fake-source.patch
--- cvs/nefilter/userspace/patch-o-matic/base/ipt_REJECT-fake-source.patch	Thu Jan  1 07:30:00 1970
+++ netfilter/userspace/patch-o-matic/base/ipt_REJECT-fake-source.patch	Mon Feb 25 18:43:06 2002
@@ -0,0 +1,85 @@
+--- original/linux/include/linux/netfilter_ipv4/ipt_REJECT.h	Sat Jul 15 03:20:23 2000
++++ linux/include/linux/netfilter_ipv4/ipt_REJECT.h	Thu Nov 15 16:56:23 2001
+@@ -14,6 +14,7 @@
+ 
+ struct ipt_reject_info {
+ 	enum ipt_reject_with with;      /* reject type */
++	u_int32_t fake_source_address;  /* fake source address, 0 if no fake */
+ };
+ 
+-#endif /*_IPT_REJECT_H*/
++#endif /* _IPT_REJECT_H */
+--- original/linux/net/ipv4/netfilter/ipt_REJECT.c	Sat Oct  6 23:50:28 2001
++++ linux/net/ipv4/netfilter/ipt_REJECT.c	Thu Nov 15 16:57:52 2001
+@@ -1,6 +1,7 @@
+ /*
+  * This is a module which is used for rejecting packets.
+  * Added support for customized reject packets (Jozsef Kadlecsik).
++ * Added support for fake source IP in icmp-unreach (Fabrice MARIE).
+  */
+ #include <linux/config.h>
+ #include <linux/module.h>
+@@ -150,7 +151,7 @@
+ 	kfree_skb(nskb);
+ }
+ 
+-static void send_unreach(struct sk_buff *skb_in, int code)
++static void send_unreach(struct sk_buff *skb_in, int code, u_int32_t fake_source_address)
+ {
+ 	struct iphdr *iph;
+ 	struct icmphdr *icmph;
+@@ -243,7 +244,12 @@
+ 	iph->ttl = MAXTTL;
+ 	ip_select_ident(iph, &rt->u.dst, NULL);
+ 	iph->protocol=IPPROTO_ICMP;
+-	iph->saddr=rt->rt_src;
++
++        /* fake source IP if we have to */
++        if (fake_source_address != 0)
++		iph->saddr=fake_source_address;
++	else
++		iph->saddr=rt->rt_src;
+ 	iph->daddr=rt->rt_dst;
+ 	iph->check=0;
+ 	iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+@@ -290,22 +296,22 @@
+ 	   must return an absolute verdict. --RR */
+     	switch (reject->with) {
+     	case IPT_ICMP_NET_UNREACHABLE:
+-    		send_unreach(*pskb, ICMP_NET_UNREACH);
++    		send_unreach(*pskb, ICMP_NET_UNREACH, reject->fake_source_address);
+     		break;
+     	case IPT_ICMP_HOST_UNREACHABLE:
+-    		send_unreach(*pskb, ICMP_HOST_UNREACH);
++    		send_unreach(*pskb, ICMP_HOST_UNREACH, reject->fake_source_address);
+     		break;
+     	case IPT_ICMP_PROT_UNREACHABLE:
+-    		send_unreach(*pskb, ICMP_PROT_UNREACH);
++    		send_unreach(*pskb, ICMP_PROT_UNREACH, reject->fake_source_address);
+     		break;
+     	case IPT_ICMP_PORT_UNREACHABLE:
+-    		send_unreach(*pskb, ICMP_PORT_UNREACH);
++    		send_unreach(*pskb, ICMP_PORT_UNREACH, reject->fake_source_address);
+     		break;
+     	case IPT_ICMP_NET_PROHIBITED:
+-    		send_unreach(*pskb, ICMP_NET_ANO);
++    		send_unreach(*pskb, ICMP_NET_ANO, reject->fake_source_address);
+     		break;
+ 	case IPT_ICMP_HOST_PROHIBITED:
+-    		send_unreach(*pskb, ICMP_HOST_ANO);
++    		send_unreach(*pskb, ICMP_HOST_ANO, reject->fake_source_address);
+     		break;
+ 	case IPT_TCP_RESET:
+ 		send_reset(*pskb, hooknum == NF_IP_LOCAL_IN);
+@@ -350,6 +356,11 @@
+ 		if (e->ip.proto != IPPROTO_TCP
+ 		    || (e->ip.invflags & IPT_INV_PROTO)) {
+ 			DEBUGP("REJECT: TCP_RESET illegal for non-tcp\n");
++			return 0;
++		}
++		/* cannot fake source address */
++		if (rejinfo->fake_source_address != 0) {
++			DEBUGP("REJECT: fake-source-address illegal for TCP-RESET\n");
+ 			return 0;
+ 		}
+ 	}
diff -uNr cvs/nefilter/userspace/patch-o-matic/base/ipt_REJECT-fake-source.patch.help netfilter/userspace/patch-o-matic/base/ipt_REJECT-fake-source.patch.help
--- cvs/nefilter/userspace/patch-o-matic/base/ipt_REJECT-fake-source.patch.help	Thu Jan  1 07:30:00 1970
+++ netfilter/userspace/patch-o-matic/base/ipt_REJECT-fake-source.patch.help	Mon Feb 25 19:20:02 2002
@@ -0,0 +1,15 @@
+Author: Fabrice MARIE <[EMAIL PROTECTED]>
+Status: It Works For Me.
+
+Adds the possibility to send icmp-unreachable messages
+from a fake source IP address.
+
+Example :
+# iptables -A INPUT -p tcp -d 202.156.58.79 --dport http -j REJECT --fake-source 10.1.1.1
+# iptables --list -n
+Chain INPUT (policy ACCEPT)
+target prot opt source      destination         
+REJECT tcp  --  0.0.0.0/0   202.156.58.79   tcp dpt:80 reject-with icmp-port-unreachable faked from 10.1.1.1
+
+***** WARNING ***** This patch also patch the userspace directory which means that you
+                    you have to recompile and reinstall the iptables package after that.
diff -uNr cvs/nefilter/userspace/patch-o-matic/base/ipt_REJECT-fake-source.patch.userspace netfilter/userspace/patch-o-matic/base/ipt_REJECT-fake-source.patch.userspace
--- cvs/nefilter/userspace/patch-o-matic/base/ipt_REJECT-fake-source.patch.userspace	Thu Jan  1 07:30:00 1970
+++ netfilter/userspace/patch-o-matic/base/ipt_REJECT-fake-source.patch.userspace	Mon Feb 25 18:43:06 2002
@@ -0,0 +1,105 @@
+--- extensions/libipt_REJECT.c	Thu Nov 15 18:08:42 2001
++++ extensions/libipt_REJECT.c	Thu Nov 15 17:28:03 2001
+@@ -6,10 +6,17 @@
+ #include <string.h>
+ #include <stdlib.h>
+ #include <getopt.h>
++#include <netdb.h>
+ #include <iptables.h>
+ #include <linux/netfilter_ipv4/ip_tables.h>
+ #include <linux/netfilter_ipv4/ipt_REJECT.h>
+ 
++#define NIPQUAD(addr) \
++        ((unsigned char *)&addr)[0], \
++        ((unsigned char *)&addr)[1], \
++        ((unsigned char *)&addr)[2], \
++        ((unsigned char *)&addr)[3]
++
+ struct reject_names {
+ 	const char *name;
+ 	const char *alias;
+@@ -52,7 +59,7 @@
+ 	printf("\n");
+ }
+ 
+-/* Saves the union ipt_targinfo in parsable form to stdout. */
++/* Saves the struct ipt_targinfo in parsable form to stdout. */
+ 
+ /* Function which prints out usage message. */
+ static void
+@@ -62,12 +69,15 @@
+ "REJECT options:\n"
+ "--reject-with type              drop input packet and send back\n"
+ "                                a reply packet according to type:\n");
+-
+ 	print_reject_types();
++	printf(
++"--fake-source ip_address        fake the source address of the packet to\n"
++"                                be ip_address (do not use with tcp-reset!)\n");
+ }
+ 
+ static struct option opts[] = {
+ 	{ "reject-with", 1, 0, '1' },
++	{ "fake-source", 1, 0, '2' },
+ 	{ 0 }
+ };
+ 
+@@ -79,6 +89,7 @@
+ 
+ 	/* default */
+ 	reject->with = IPT_ICMP_PORT_UNREACHABLE;
++	reject->fake_source_address = 0;  /* by default we don't fake */
+ 
+ 	/* Can't cache this */
+ 	*nfcache |= NFC_UNKNOWN;
+@@ -94,6 +105,7 @@
+ 	struct ipt_reject_info *reject = (struct ipt_reject_info *)(*target)->data;
+ 	unsigned int limit = sizeof(reject_table)/sizeof(struct reject_names);
+ 	unsigned int i;
++	struct in_addr *ip;
+ 
+ 	switch(c) {
+ 	case '1':
+@@ -113,6 +125,24 @@
+ 			fprintf(stderr, "--reject-with echo-reply no longer"
+ 				" supported\n");
+ 		exit_error(PARAMETER_PROBLEM, "unknown reject type `%s'",optarg);
++		if ((reject->fake_source_address != 0) && (reject->with == IPT_TCP_RESET))
++			exit_error(PARAMETER_PROBLEM,
++				"Cannot use fake source address with TCP_RESET for REJECT");
++
++		break;
++	case '2':
++		if (invert)
++			exit_error(PARAMETER_PROBLEM,
++				"unexpected '!' with --fake-source");
++		if (reject->with == IPT_TCP_RESET)
++                        exit_error(PARAMETER_PROBLEM,
++                                "Cannot use fake source address with TCP_RESET for REJECT");
++		ip = dotted_to_addr(optarg);
++		if (!ip)
++			exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n", optarg);
++		reject->fake_source_address = ip->s_addr;
++		return 1;
++		break;
+ 	default:
+ 		/* Fall through */
+ 	}
+@@ -139,6 +169,8 @@
+ 			break;
+ 	}
+ 	printf("reject-with %s ", reject_table[i].name);
++	if (reject->fake_source_address != 0)
++		printf("faked from %u.%u.%u.%u ", NIPQUAD(reject->fake_source_address));
+ }
+
+ /* Saves ipt_reject in parsable form to stdout. */
+@@ -153,6 +185,8 @@
+ 			break;
+ 
+ 	printf("--reject-with %s ", reject_table[i].name);
++	if (reject->fake_source_address != 0)
++		printf("--fake-source %u.%u.%u.%u ", NIPQUAD(reject->fake_source_address));
+ }
+ 
+ static
diff -uNr cvs/nefilter/userspace/patch-o-matic/base/MARK_operations.patch netfilter/userspace/patch-o-matic/base/MARK_operations.patch
--- cvs/nefilter/userspace/patch-o-matic/base/MARK_operations.patch	Thu Jan  1 07:30:00 1970
+++ netfilter/userspace/patch-o-matic/base/MARK_operations.patch	Mon Feb 25 18:43:18 2002
@@ -0,0 +1,45 @@
+--- original/linux/net/ipv4/netfilter/ipt_MARK.c	Mon Oct  1 03:26:08 2001
++++ linux/net/ipv4/netfilter/ipt_MARK.c	Wed Feb 20 22:45:12 2002
+@@ -17,10 +17,22 @@
+ {
+ 	const struct ipt_mark_target_info *markinfo = targinfo;
+ 
+-	if((*pskb)->nfmark != markinfo->mark) {
++	switch (markinfo->mode) {
++	case IPT_MARK_SET:
+ 		(*pskb)->nfmark = markinfo->mark;
+-		(*pskb)->nfcache |= NFC_ALTERED;
++		break;
++		
++	case IPT_MARK_AND:
++		(*pskb)->nfmark = (*pskb)->nfmark & markinfo->mark;
++		break;
++		
++	case IPT_MARK_OR:
++		(*pskb)->nfmark = (*pskb)->nfmark | markinfo->mark;
++		break;
++	default:
++		break;
+ 	}
++        (*pskb)->nfcache |= NFC_ALTERED;
+ 	return IPT_CONTINUE;
+ }
+ 
+--- original/linux/include/linux/netfilter_ipv4/ipt_MARK.h	Sat Mar 18 02:56:20 2000
++++ linux/include/linux/netfilter_ipv4/ipt_MARK.h	Wed Feb 20 22:24:16 2002
+@@ -1,8 +1,15 @@
+ #ifndef _IPT_MARK_H_target
+ #define _IPT_MARK_H_target
+ 
++enum {
++        IPT_MARK_SET,
++        IPT_MARK_AND,
++        IPT_MARK_OR
++};
++
+ struct ipt_mark_target_info {
+ 	unsigned long mark;
++	u_int8_t mode;
+ };
+ 
+ #endif /*_IPT_MARK_H_target*/
diff -uNr cvs/nefilter/userspace/patch-o-matic/base/MARK_operations.patch.help netfilter/userspace/patch-o-matic/base/MARK_operations.patch.help
--- cvs/nefilter/userspace/patch-o-matic/base/MARK_operations.patch.help	Thu Jan  1 07:30:00 1970
+++ netfilter/userspace/patch-o-matic/base/MARK_operations.patch.help	Mon Feb 25 19:19:53 2002
@@ -0,0 +1,10 @@
+Author: Fabrice MARIE <[EMAIL PROTECTED]>
+Status: Works For Me.
+
+This patch adds support for setting the nfmark bitwise (and & or).
+
+# iptables -t mangle -A PREROUTING -p icmp -j MARK --or-mark 0x15
+# iptables -t mangle -A PREROUTING -p icmp -j MARK --and-mark 0x15
+
+***** WARNING ***** This patch also patch the userspace directory which means that you
+                    you have to recompile and reinstall the iptables package after that.
diff -uNr cvs/nefilter/userspace/patch-o-matic/base/MARK_operations.patch.userspace netfilter/userspace/patch-o-matic/base/MARK_operations.patch.userspace
--- cvs/nefilter/userspace/patch-o-matic/base/MARK_operations.patch.userspace	Thu Jan  1 07:30:00 1970
+++ netfilter/userspace/patch-o-matic/base/MARK_operations.patch.userspace	Mon Feb 25 18:43:18 2002
@@ -0,0 +1,121 @@
+--- extensions/libipt_MARK.c	Tue Aug  7 02:50:22 2001
++++ extensions/libipt_MARK.c	Thu Feb 21 00:27:05 2002
+@@ -20,12 +20,16 @@
+ 	printf(
+ "MARK target v%s options:\n"
+ "  --set-mark value                   Set nfmark value\n"
++"  --and-mark value                   Binary AND the nfmark with value\n"
++"  --or-mark  value                   Binary OR  the nfmark with value\n"
+ "\n",
+ NETFILTER_VERSION);
+ }
+ 
+ static struct option opts[] = {
+ 	{ "set-mark", 1, 0, '1' },
++	{ "and-mark", 1, 0, '2' },
++	{ "or-mark", 1, 0, '3' },
+ 	{ 0 }
+ };
+ 
+@@ -45,16 +49,38 @@
+ 	struct ipt_mark_target_info *markinfo
+ 		= (struct ipt_mark_target_info *)(*target)->data;
+ 
+-	switch (c) {
++	if ((c=='1') || (c=='2') || (c=='3'))
++	{
+ 		char *end;
+-	case '1':
++		
++		if (*flags)
++			exit_error(PARAMETER_PROBLEM, "MARK target: can specify only one action");
+ 		markinfo->mark = strtoul(optarg, &end, 0);
+ 		if (*end != '\0' || end == optarg)
+ 			exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
+-		if (*flags)
+-			exit_error(PARAMETER_PROBLEM,
+-			           "MARK target: Can't specify --set-mark twice");
+ 		*flags = 1;
++	}
++
++	switch (c) {
++	case '1':
++		if (invert)
++			exit_error(PARAMETER_PROBLEM, "unexpected '!' with --set-mark");
++
++		markinfo->mode = IPT_MARK_SET;
++		break;
++
++	case '2':
++		if (invert)
++			exit_error(PARAMETER_PROBLEM, "unexpected '!' with --and-mark");
++
++		markinfo->mode = IPT_MARK_AND;
++		break;
++
++	case '3':
++		if (invert)
++			exit_error(PARAMETER_PROBLEM, "unexpected '!' with --or-mark");
++
++		markinfo->mode = IPT_MARK_OR;
+ 		break;
+ 
+ 	default:
+@@ -72,12 +98,6 @@
+ 		           "MARK target: Parameter --set-mark is required");
+ }
+ 
+-static void
+-print_mark(unsigned long mark, int numeric)
+-{
+-	printf("0x%lx ", mark);
+-}
+-
+ /* Prints out the targinfo. */
+ static void
+ print(const struct ipt_ip *ip,
+@@ -86,8 +106,20 @@
+ {
+ 	const struct ipt_mark_target_info *markinfo =
+ 		(const struct ipt_mark_target_info *)target->data;
+-	printf("MARK set ");
+-	print_mark(markinfo->mark, numeric);
++	switch (markinfo->mode) {
++		case IPT_MARK_SET:
++			printf("MARK set ");
++			break;
++		case IPT_MARK_AND:
++			printf("MARK and ");
++			break;
++		case IPT_MARK_OR:
++			printf("MARK or ");
++			break;
++		default:
++			printf("MARK set "); /* This shouldn't happen.. */
++	}
++	printf("0x%lx ", markinfo->mark);
+ }
+ 
+ /* Saves the union ipt_targinfo in parsable form to stdout. */
+@@ -97,7 +129,20 @@
+ 	const struct ipt_mark_target_info *markinfo =
+ 		(const struct ipt_mark_target_info *)target->data;
+ 
+-	printf("--set-mark 0x%lx ", markinfo->mark);
++	switch (markinfo->mode) {
++		case IPT_MARK_SET:
++			printf("--set-mark ");
++			break;
++		case IPT_MARK_AND:
++			printf("--and-mark ");
++			break;
++		case IPT_MARK_OR:
++			printf("--or-mark ");
++			break;
++		default:
++			printf("--set-mark ");
++	}
++	printf("0x%lx ", markinfo->mark);
+ }
+ 
+ static
--- cvs/nefilter/TODO	Mon Feb 25 19:25:43 2002
+++ netfilter/TODO	Mon Feb 25 19:27:33 2002
@@ -35,7 +35,7 @@
 - sysctl support for ftp-multi, irc-conntrack/nat, ftp-fxp
 - integrate HOPLIMIT for ipv6 in patch-o-matic [HW]
 - u32 classifier (port from tc -> iptables) [YU]
-- MARK match / target with boolean OR / AND (to use nfmark bitwise)
+- MARK match with boolean OR / AND (to use nfmark bitwise)
 - documentation for libiptc
 - port conntrack to IPv6 (code reuse?) [BC]
 x make patch-o-matic reversible
@@ -44,7 +44,7 @@
 - ip_nat_ident module [FM]
 x provide daily CVS snapshots via ftp [HW]
 - make iptables / ip6tables use the same codebase (as libiptc) [KA]
-- REJECT optionally generates port unreachable with faked SOURCE
+x REJECT optionally generates port unreachable with faked SOURCE
 - libipq reentrancy [JM]
 - compiling without O2 issue
 x add more information like original addresses to the state match

Reply via email to