Skip to contentSkip to conversation

Balancing connections betewen a few internet links with HA.

PATCH In review Maciek Zobniow 4 participants 11 messages Sep 17, 2003 – Nov 21, 2003 2 messages not in the archive

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Balancing connections betewen a few internet links with HA.

The patch and explanation you can find on
http://markcb.zobniow.net
Best Regards

Signature · 4 lines
Maciej Zobniow
Open Source - Free software for free people.
http://markcb.zobniow.net
http://mysql.zobniow.net
#1 lore raw
Quoted 2 lines · Maciek Zobniow

The patch and explanation you can find on
http://markcb.zobniow.net

Hi!

May I ask, why did you invent a special Target?

You can build a solution based on the CONNMARK target/match, together with the 'nth' match, the MARK target and policyrouting.

Quoted 2 lines

Best Regards
Maciej Zobniow

Signature · 5 lines
- Harald Welte <[email protected]>             http://www.netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie
#2 lore raw
Quoted 6 lines · Harald Welte
Quoted 2 lines · Maciek Zobniow

The patch and explanation you can find on
http://markcb.zobniow.net

Quoted 12 lines

Hi!

May I ask, why did you invent a special Target?

You can build a solution based on the CONNMARK target/match, together with the 'nth' match, the MARK target and policyrouting.

Quoted 2 lines

Best Regards
Maciej Zobniow

If I am good understanding what you mean, your suggested solution will have only WRR balancing algoritm, without HA. Additonaly related connections will have possability to go by diffrent ways. In my module you can chose another algorytm and I will extend the set of possibly balance algoritms (there is a lot of possibilites). Related connetions will go always by the same way (at least I hope so - did not test this funcionality yet). I have the HA. Anyway, one from reasons why I like the *nix world is that in this world
for each problem you can find a few ways to solve it.
Best regards

Signature · 4 lines
Maciej Zobniow
Open Source - Free software for free people.
http://markcb.zobniow.net
http://mysql.zobniow.net

A message that is not in the archive (sent off-list or not yet received): [email protected]

#4 lore raw
Quoted 5 lines · Maciek Zobniow
Quoted 2 lines

You can build a solution based on the CONNMARK target/match, together with the 'nth' match, the MARK target and policyrouting.

If I am good understanding what you mean, your suggested solution will have only WRR balancing algoritm, without HA.

This is true, at least as long as you only use 'nth'. There are also the 'fuzzy' and 'random' matches, which would give slightly different behaviour.

Quoted 2 lines

Additonaly related connections will have possability to go by diffrent ways.

No, since CONNMARK givs us the inherited connection mark (and thus the needed persistency for related connections)

Quoted 2 lines

In my module you can chose another algorytm and I will extend the set of possibly balance algoritms (there is a lot of possibilites).

yes. However, you implement thos algorithms specifically for your module. If the algorithm was somehow implemented as iptables match, everybody could use it [even for a different purpose].

Quoted 2 lines

Anyway, one from reasons why I like the *nix world is that in this world
for each problem you can find a few ways to solve it.

Sure! However as of now I don't think that your proposed solution is going to be integrated as 'standard solution' for the problem of balancing connections, sorry.

Quoted 2 lines

Maciej Zobniow
Open Source - Free software for free people.

Signature · 5 lines
- Harald Welte <[email protected]>             http://www.netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie
#5 lore raw
Quoted 21 lines · Harald Welte
Quoted 4 lines · Maciek Zobniow
Quoted 2 lines

You can build a solution based on the CONNMARK target/match, together with the 'nth' match, the MARK target and policyrouting.

If I am good understanding what you mean, your suggested solution will have only WRR balancing algoritm, without HA.

This is true, at least as long as you only use 'nth'. There are also the 'fuzzy' and 'random' matches, which would give slightly different behaviour.

Quoted 2 lines

Additonaly related connections will have possability to go by diffrent ways.

No, since CONNMARK givs us the inherited connection mark (and thus the needed persistency for related connections)

Quoted 7 lines
Quoted 2 lines

In my module you can chose another algorytm and I will extend the set of possibly balance algoritms (there is a lot of possibilites).

yes. However, you implement thos algorithms specifically for your module. If the algorithm was somehow implemented as iptables match, everybody could use it [even for a different purpose].

I think that it can not working as iptables match. There is a diffrent betewen normal matchs in iptables and match algoritms in markcb module. In this module, when new connection is coming it try to chose a mark for this connection. It operate on collected data (configuration from user or lines loading) about links, not connections. I tried to abstract this module as much as possible, therefore it only marking this connections by chosen algoritm and could be use for another purpose. This is also the advantage of markcb module to your suggested solution - it can keep and process data in real time, therefore more complex balance algoritms are possible.

Best regards

Signature · 4 lines
Maciej Zobniow
Open Source - Free software for free people.
http://markcb.zobniow.net
http://mysql.zobniow.net
#6 lore raw

PATCH 1/1 RANGEMARK target

In reply to Harald Welte

I wanted to MARK packets dynamically within a certain range. Implemented a target as follows :

-j RANGEMARK --set-rangemark <base>[-<limit>[.<s>][:r|h[,S|O|A]]]

where,
<base> and <limit> define the range (inclusive) <s> is the size of the increment (default 1) r => random (default)
h => porthash (if relevant protocol)
S => set the value (default)
O => OR it to existing value
A => AND to existing value

The mark value can be set within the given range (<base> to <limit>) in steps of <s> based on a given policy e.g. random. Additionally, if <base> and <limit> are suitably chosen one could set specific bitvalues and then OR/AND them to create 'composite' MARK values between rules if needed. Needless to say that additional policies can be added (I needed random).

If none of the optional values are used then it defaults to MARK.

Please comment. I'll then update with necessary changes and also add ip6t_* target.

Thanks,
Vivek

------------------------------------------------------------------------

extensions/libipt_RANGEMARK.c +300 -0
diff -urN iptables-1.2.9rc1.orig/extensions/libipt_RANGEMARK.c iptables-1.2.9rc1/extensions/libipt_RANGEMARK.c
@@ -0,0 +1,300 @@
+/* Shared library add-on to iptables to add RANGEMARK target support. */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ctype.h>
+
+#include <iptables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_RANGEMARK.h>
+
+struct rangemarkinfo {
+    struct ipt_entry_target t;
+    struct ipt_rangemark_target_info rangemark;
+};
+
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+    printf(
+"RANGEMARK target v%s options:\n"
+"  --set-rangemark base[-limit[.s][:r]][,S|O|A]] Set random nfmark within range"
+"\n"
+"  --set-rangemark base[-limit[.s][:h]][,S|O|A]] Set nfmark based on ports"
+"\n",
+IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+    { "set-rangemark", 1, 0, '1' },
+    { 0 }
+};
+
+static char *
+get_val(char *s, unsigned long *val)
+{
+    char *ep = s;
+    
+    if (NULL == s)
+        return NULL;
+
+    if (*s == '\0') 
+        exit_error(PARAMETER_PROBLEM, "Invalid base-limit specified");
+
+    while(isalnum(*ep++));
+
+    /*
+     * Out of range values are clipped at ULONG_MAX
+     */
+    *val  = strtoul(s,&ep,0);
+
+    return ep;
+}
+
+static char *
+get_baseval(char *s, unsigned long *val, unsigned int *flags)
+{
+    if (*flags & RANGEMARK_FLAG_BASE)
+        exit_error(PARAMETER_PROBLEM, "set-rangemark: Base specified twice");
+
+    *flags |= RANGEMARK_FLAG_BASE;
+
+    return get_val(s, val);
+}
+
+static char *
+get_limitval(char *s, unsigned long *val, unsigned int *flags)
+{
+    if (*flags & RANGEMARK_FLAG_LIMIT)
+        exit_error(PARAMETER_PROBLEM, "set-rangemark: Limit specified twice");
+
+    *flags |= RANGEMARK_FLAG_LIMIT;
+
+    return get_val(s, val);
+}
+
+static char *
+get_skipval(char *s, unsigned long *val, unsigned int *flags)
+{
+    if (*flags & RANGEMARK_FLAG_SKIPVALUE)
+        exit_error(PARAMETER_PROBLEM, "set-rangemark: Skipval specified twice");
+
+    *flags |= RANGEMARK_FLAG_SKIPVALUE;
+
+    return get_val(s, val);
+}
+
+static char *
+get_policy(char *s, unsigned int *policy, unsigned int *flags)
+{
+    if (*flags & RANGEMARK_FLAG_POLICY)
+        exit_error(PARAMETER_PROBLEM, "set-rangemark: Policy specified twice");
+
+    *flags |= RANGEMARK_FLAG_POLICY;
+
+    switch(*s) {
+        case 'r': /* random */
+            *policy = RANGEMARK_POLICY_RANDOM;
+            break;
+
+        case 'h': /* port hash */
+            *policy = RANGEMARK_POLICY_PORTHASH;
+            break;
+
+        default: /* unrecognised */
+            exit_error(PARAMETER_PROBLEM, "set-rangemark: Unrecognised policy");
+            return NULL;
+    }
+
+    return ++s;
+}
+
+    
+static char *
+get_op(char *s, unsigned int *op, unsigned *flags)
+{
+    if (*flags & RANGEMARK_FLAG_OP)
+        exit_error(PARAMETER_PROBLEM, "set-rangemark: Policy specified twice");
+
+    *flags |= RANGEMARK_FLAG_OP;
+
+    switch(*s) {
+        case 'S': /* Set the value overwriting any existing value */
+            *op = RANGEMARK_OP_SET;
+            break;
+
+        case 'O': /* OR the value with the existing value */
+            *op = RANGEMARK_OP_OR;
+            break;
+
+        case 'A': /* AND the value with the existing value */
+            *op = RANGEMARK_OP_AND;
+            break;
+
+        default: /* unrecognised */
+            exit_error(PARAMETER_PROBLEM, 
+                "set-rangemark: Unrecognised operation");
+            return NULL;
+    }
+
+    return ++s;
+}
+    
+
+static int
+parse_params(int c, struct ipt_rangemark_target_info *rinfo, char **argv, 
+            unsigned int *flags)
+{
+
+    char *ptr = NULL;
+    unsigned long mask;
+
+    switch(c) {
+        case '1': 
+            /* Calculate the base value */
+            ptr = get_baseval(optarg, &rinfo->base, flags);
+
+            /* Get the limit if present */
+            if (ptr && *ptr == '-') {
+                ptr = get_limitval(++ptr, &rinfo->limit, flags);
+            }
+
+            /* Get the skip value if present */
+            if (ptr && *ptr == '.') {
+                ptr = get_skipval(++ptr, &rinfo->skip, flags);
+            }
+
+            /* Get the policy if specified */
+            if (ptr && ( *ptr == ':')){
+                    ptr = get_policy(++ptr, &rinfo->policy, flags);
+            }
+
+            /* Get the operation if specified */
+            if (ptr && *ptr == ',') {
+                ptr = get_op(++ptr, &rinfo->op, flags);
+            }
+
+            if (ptr && *ptr) {
+                exit_error(PARAMETER_PROBLEM, 
+                    "set-rangemark: Unrecognised option");
+            }
+
+            if (!(*flags & RANGEMARK_FLAG_LIMIT))
+                rinfo->limit = rinfo->base;
+            if (!(*flags & RANGEMARK_FLAG_SKIPVALUE))
+                rinfo->skip = 1;
+            if (!(*flags & RANGEMARK_FLAG_POLICY))
+                rinfo->policy = RANGEMARK_POLICY_RANDOM;
+            if (!(*flags & RANGEMARK_FLAG_OP))
+                rinfo->op = RANGEMARK_OP_SET;
+
+            /*
+             * Set the mask 
+             */
+            mask = rinfo->limit - rinfo->base;
+            rinfo->mask = 1;
+            while(mask >>= 1)
+                rinfo->mask = (rinfo->mask << 1) | 1;
+            break;
+
+        default:
+            return 0;
+    }
+
+    return 1;
+}
+
+/* Initialize the target. */
+static void
+init(struct ipt_entry_target *t, unsigned int *nfcache)
+{
+}
+
+/* Function which parses command options; returns true if it
+   ate an option */
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ipt_entry *entry,
+      struct ipt_entry_target **target)
+{
+
+int ret = 0;
+
+struct ipt_rangemark_target_info *rangeinfo
+    = (struct ipt_rangemark_target_info *)(*target)->data;
+
+    switch (c) {
+    case '1':
+        if (invert)
+            exit_error(PARAMETER_PROBLEM, "set-rangemark: invert flag used\n");
+        ret = parse_params(c, rangeinfo, argv, flags);
+        break;
+
+    default:
+        return 0;
+    }
+
+    return ret;
+}
+
+static void
+final_check(unsigned int flags)
+{
+}
+
+
+static void
+print_rangemark(struct ipt_rangemark_target_info *r)
+{
+    printf("Base:   %lu %lx\n", r->base, r->base);
+    printf("Limit:  %lu %lx\n", r->limit, r->limit);
+    printf("rsize:  %lu %lx\n", r->rsize, r->rsize);
+    printf("skipvalue:  %lu %lx\n", r->skip, r->skip);
+    printf("mask:  %lu %lx\n", r->mask, r->mask);
+    printf("policy: %d\n", r->policy);
+    printf("op:     %d\n", r->op);
+}
+
+/* Prints out the targinfo. */
+static void
+print(const struct ipt_ip *ip,
+      const struct ipt_entry_target *target,
+      int numeric)
+{
+    struct ipt_rangemark_target_info *rinfo =
+        (struct ipt_rangemark_target_info *)target->data;
+    print_rangemark(rinfo);
+}
+
+/* Saves the union ipt_targinfo in parsable form to stdout. */
+static void
+save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+{
+    struct ipt_rangemark_target_info *rinfo =
+        (struct ipt_rangemark_target_info *)target->data;
+
+    print_rangemark(rinfo);
+}
+
+static
+struct iptables_target rangemark
+= { NULL,
+    "RANGEMARK",
+    IPTABLES_VERSION,
+    IPT_ALIGN(sizeof(struct ipt_rangemark_target_info)),
+    IPT_ALIGN(sizeof(struct ipt_rangemark_target_info)),
+    &help,
+    &init,
+    &parse,
+    &final_check,
+    &print,
+    &save,
+    opts
+};
+
+void _init(void)
+{
+    register_target(&rangemark);
+}
extensions/Makefile +1 -1
diff -urN iptables-1.2.9rc1.orig/extensions/Makefile iptables-1.2.9rc1/extensions/Makefile
@@ -5,7 +5,7 @@
 # header files are present in the include/linux directory of this iptables
 # package (HW)
 #
-PF_EXT_SLIB:=ah connlimit conntrack dscp ecn esp helper icmp iprange length limit mac mark multiport owner physdev pkttype realm rpc standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NOTRACK REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TRACE TTL ULOG 
+PF_EXT_SLIB:=ah connlimit conntrack dscp ecn esp helper icmp iprange length limit mac mark multiport owner physdev pkttype realm rpc standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NOTRACK REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TRACE TTL ULOG RANGEMARK
 
 PF6_EXT_SLIB:=eui64 hl icmpv6 length limit mac mark multiport owner standard tcp udp HL LOG MARK TRACE
 
include/linux/netfilter_ipv4/ipt_RANGEMARK.h +35 -0
diff -urN iptables-1.2.9rc1.orig/include/linux/netfilter_ipv4/ipt_RANGEMARK.h iptables-1.2.9rc1/include/linux/netfilter_ipv4/ipt_RANGEMARK.h
@@ -0,0 +1,35 @@
+#ifndef _IPT_RANGEMARK_H_target
+#define _IPT_RANGEMARK_H_target
+
+#include <linux/spinlock.h>
+
+enum rangemark_policy {
+	RANGEMARK_POLICY_RANDOM = 1,
+	RANGEMARK_POLICY_PORTHASH,
+};
+
+enum rangemark_op {
+	RANGEMARK_OP_SET = 1,
+	RANGEMARK_OP_OR,
+	RANGEMARK_OP_AND,
+};
+
+enum rangemark_flags {
+	RANGEMARK_FLAG_BASE = 1,
+	RANGEMARK_FLAG_LIMIT = 2,
+	RANGEMARK_FLAG_POLICY = 4,
+	RANGEMARK_FLAG_OP = 8,
+	RANGEMARK_FLAG_SKIPVALUE = 16,
+};
+
+struct ipt_rangemark_target_info {
+	unsigned long 			base;
+	unsigned long 			limit;
+	unsigned long			rsize;
+	unsigned long			skip;
+	signed   long           mask;
+	enum rangemark_policy 	policy;
+	enum rangemark_op 		op;
+};
+
+#endif /*_IPT_RANGEMARK_H_target*/
net/ipv4/netfilter/Config.in +1 -0
diff -urN linux-2.4.22.orig/net/ipv4/netfilter/Config.in linux-2.4.22/net/ipv4/netfilter/Config.in
@@ -104,6 +104,7 @@
     dep_tristate '    DSCP target support' CONFIG_IP_NF_TARGET_DSCP $CONFIG_IP_NF_MANGLE
  
     dep_tristate '    MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
+    dep_tristate '    RANGEMARK target support' CONFIG_IP_NF_TARGET_RANGEMARK $CONFIG_IP_NF_MANGLE
   fi
   dep_tristate '  LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES
   dep_tristate '  ULOG target support' CONFIG_IP_NF_TARGET_ULOG $CONFIG_IP_NF_IPTABLES
net/ipv4/netfilter/ipt_RANGEMARK.c +212 -0

212 lines not on this page · raw message

net/ipv4/netfilter/Makefile +1 -0
diff -urN linux-2.4.22.orig/net/ipv4/netfilter/Makefile linux-2.4.22/net/ipv4/netfilter/Makefile
@@ -94,6 +94,7 @@
 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
+obj-$(CONFIG_IP_NF_TARGET_RANGEMARK) += ipt_RANGEMARK.o
 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
include/linux/netfilter_ipv4/ipt_RANGEMARK.h +35 -0
diff -urN linux-2.4.22.orig/include/linux/netfilter_ipv4/ipt_RANGEMARK.h linux-2.4.22/include/linux/netfilter_ipv4/ipt_RANGEMARK.h
@@ -0,0 +1,35 @@
+#ifndef _IPT_RANGEMARK_H_target
+#define _IPT_RANGEMARK_H_target
+
+#include <linux/spinlock.h>
+
+enum rangemark_policy {
+	RANGEMARK_POLICY_RANDOM = 1,
+	RANGEMARK_POLICY_PORTHASH,
+};
+
+enum rangemark_op {
+	RANGEMARK_OP_SET = 1,
+	RANGEMARK_OP_OR,
+	RANGEMARK_OP_AND,
+};
+
+enum rangemark_flags {
+	RANGEMARK_FLAG_BASE = 1,
+	RANGEMARK_FLAG_LIMIT = 2,
+	RANGEMARK_FLAG_POLICY = 4,
+	RANGEMARK_FLAG_OP = 8,
+	RANGEMARK_FLAG_SKIPVALUE = 16,
+};
+
+struct ipt_rangemark_target_info {
+	unsigned long 			base;
+	unsigned long 			limit;
+	unsigned long			rsize;
+	unsigned long			skip;
+	signed   long           mask;
+	enum rangemark_policy 	policy;
+	enum rangemark_op 		op;
+};
+
+#endif /*_IPT_RANGEMARK_H_target*/
#7 lore raw

Re: [PATCH] RANGEMARK target

Quoted 1 line · Vivek Kashyap

I wanted to MARK packets dynamically within a certain range.

Ok, thanks for this contribution.

Quoted 2 lines

Please comment. I'll then update with necessary changes and also add ip6t_* target.

I'm going to comment inline.

extensions/libipt_RANGEMARK.c line 14

Quoted 3 lines
extensions/libipt_RANGEMARK.c +3 -0
+struct rangemarkinfo {
+    struct ipt_entry_target t;
+    struct ipt_rangemark_target_info rangemark;

please adhere to the kernel CodingStyle (tabulator indent, 8char).

extensions/libipt_RANGEMARK.c line 258

Quoted 11 lines
extensions/libipt_RANGEMARK.c +11 -0
+static void
+print_rangemark(struct ipt_rangemark_target_info *r)
+{
+    printf("Base:   %lu %lx\n", r->base, r->base);
+    printf("Limit:  %lu %lx\n", r->limit, r->limit);
+    printf("rsize:  %lu %lx\n", r->rsize, r->rsize);
+    printf("skipvalue:  %lu %lx\n", r->skip, r->skip);
+    printf("mask:  %lu %lx\n", r->mask, r->mask);
+    printf("policy: %d\n", r->policy);
+    printf("op:     %d\n", r->op);
+}

you'd have to try to be less verbose and not use newlines in the printout. the print() function will be called for every rule when you do a 'iptables -L'.

extensions/libipt_RANGEMARK.c line 279

Quoted 9 lines
extensions/libipt_RANGEMARK.c +9 -0
+/* Saves the union ipt_targinfo in parsable form to stdout. */
+static void
+save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+{
+    struct ipt_rangemark_target_info *rinfo =
+        (struct ipt_rangemark_target_info *)target->data;
+
+    print_rangemark(rinfo);
+}

this is not correc.t save() has to save it in exactly the same format (i.e. gnu-longoppts like --base) so that a later call to parse() can parse it again.

extensions/Makefile line 9

Quoted 7 lines
extensions/Makefile +1 -1
@@ -5,7 +5,7 @@
 # header files are present in the include/linux directory of this iptables
 # package (HW)
 #
-PF_EXT_SLIB:=ah connlimit conntrack dscp ecn esp helper icmp iprange length limit mac mark multiport owner physdev pkttype realm rpc standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NOTRACK REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TRACE TTL ULOG 
+PF_EXT_SLIB:=ah connlimit conntrack dscp ecn esp helper icmp iprange length limit mac mark multiport owner physdev pkttype realm rpc standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NOTRACK REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TRACE TTL ULOG RANGEMARK
 

instead of adding it to the makefile, we use a conditional compile mechanism. Please look at the '.*-test' files in the extensions subdirectory as an example.

include/linux/netfilter_ipv4/ipt_RANGEMARK.h line 9

Quoted 4 lines
include/linux/netfilter_ipv4/ipt_RANGEMARK.h +4 -0
+enum rangemark_policy {
+	RANGEMARK_POLICY_RANDOM = 1,
+	RANGEMARK_POLICY_PORTHASH,
+};

in the kernel, you really should follow linux/Documentation/CodingStyle

net/ipv4/netfilter/ipt_RANGEMARK.c line 15

Quoted 2 lines
net/ipv4/netfilter/ipt_RANGEMARK.c +2 -0
+unsigned short
+rangemark_hash(unsigned short s, unsigned short d)

please try to use architecture independent fixed-size data types. The kernel is compiled on various architectures, ... so if you want an unsigned 16bit number, please use 'u_int16_t' or __u16.

net/ipv4/netfilter/ipt_RANGEMARK.c line 76

Quoted 8 lines
net/ipv4/netfilter/ipt_RANGEMARK.c +8 -0
+        case RANGEMARK_POLICY_PORTHASH:
+            /*
+             * Skip non IP packets 
+             */
+            iptr = (void *)(*pskb)->nh.iph;
+            if ((((struct iphdr *)iptr)->version != 6) && 
+                    (((struct iphdr *)iptr)->version != 4)){
+                return IPT_CONTINUE;

an iptables target can only be called from ip_tables. And ip_tables is ipv4 specific, so it's guaranteed that you only receive IPv4 packets.

Quoted 1 line

+#endif /*_IPT_RANGEMARK_H_target*/

Signature · 5 lines
- Harald Welte <[email protected]>             http://www.netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie
#8 lore raw

Re: [PATCH] RANGEMARK target

OK Thanks. Will resubmit after correcting.

Vivek

Quoted 84 lines · Harald Welte
Quoted 1 line · Vivek Kashyap

I wanted to MARK packets dynamically within a certain range.

Ok, thanks for this contribution.

Quoted 2 lines

Please comment. I'll then update with necessary changes and also add ip6t_* target.

I'm going to comment inline.

extensions/libipt_RANGEMARK.c line 14

Quoted 3 lines
extensions/libipt_RANGEMARK.c +3 -0
+struct rangemarkinfo {
+    struct ipt_entry_target t;
+    struct ipt_rangemark_target_info rangemark;

please adhere to the kernel CodingStyle (tabulator indent, 8char).

extensions/libipt_RANGEMARK.c line 258

Quoted 11 lines
extensions/libipt_RANGEMARK.c +11 -0
+static void
+print_rangemark(struct ipt_rangemark_target_info *r)
+{
+    printf("Base:   %lu %lx\n", r->base, r->base);
+    printf("Limit:  %lu %lx\n", r->limit, r->limit);
+    printf("rsize:  %lu %lx\n", r->rsize, r->rsize);
+    printf("skipvalue:  %lu %lx\n", r->skip, r->skip);
+    printf("mask:  %lu %lx\n", r->mask, r->mask);
+    printf("policy: %d\n", r->policy);
+    printf("op:     %d\n", r->op);
+}

you'd have to try to be less verbose and not use newlines in the printout. the print() function will be called for every rule when you do a 'iptables -L'.

extensions/libipt_RANGEMARK.c line 279

Quoted 9 lines
extensions/libipt_RANGEMARK.c +9 -0
+/* Saves the union ipt_targinfo in parsable form to stdout. */
+static void
+save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+{
+    struct ipt_rangemark_target_info *rinfo =
+        (struct ipt_rangemark_target_info *)target->data;
+
+    print_rangemark(rinfo);
+}

this is not correc.t save() has to save it in exactly the same format (i.e. gnu-longoppts like --base) so that a later call to parse() can parse it again.

extensions/Makefile line 9

Quoted 7 lines
extensions/Makefile +1 -1
@@ -5,7 +5,7 @@
 # header files are present in the include/linux directory of this iptables
 # package (HW)
 #
-PF_EXT_SLIB:=ah connlimit conntrack dscp ecn esp helper icmp iprange length limit mac mark multiport owner physdev pkttype realm rpc standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NOTRACK REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TRACE TTL ULOG
+PF_EXT_SLIB:=ah connlimit conntrack dscp ecn esp helper icmp iprange length limit mac mark multiport owner physdev pkttype realm rpc standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NOTRACK REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TRACE TTL ULOG RANGEMARK
 

instead of adding it to the makefile, we use a conditional compile mechanism. Please look at the '.*-test' files in the extensions subdirectory as an example.

include/linux/netfilter_ipv4/ipt_RANGEMARK.h line 9

Quoted 4 lines
include/linux/netfilter_ipv4/ipt_RANGEMARK.h +4 -0
+enum rangemark_policy {
+	RANGEMARK_POLICY_RANDOM = 1,
+	RANGEMARK_POLICY_PORTHASH,
+};

in the kernel, you really should follow linux/Documentation/CodingStyle

net/ipv4/netfilter/ipt_RANGEMARK.c line 15

Quoted 2 lines
net/ipv4/netfilter/ipt_RANGEMARK.c +2 -0
+unsigned short
+rangemark_hash(unsigned short s, unsigned short d)

please try to use architecture independent fixed-size data types. The kernel is compiled on various architectures, ... so if you want an unsigned 16bit number, please use 'u_int16_t' or __u16.

net/ipv4/netfilter/ipt_RANGEMARK.c line 76

Quoted 8 lines
net/ipv4/netfilter/ipt_RANGEMARK.c +8 -0
+        case RANGEMARK_POLICY_PORTHASH:
+            /*
+             * Skip non IP packets
+             */
+            iptr = (void *)(*pskb)->nh.iph;
+            if ((((struct iphdr *)iptr)->version != 6) &&
+                    (((struct iphdr *)iptr)->version != 4)){
+                return IPT_CONTINUE;

an iptables target can only be called from ip_tables. And ip_tables is ipv4 specific, so it's guaranteed that you only receive IPv4 packets.

Quoted 9 lines
Quoted 1 line

+#endif /*_IPT_RANGEMARK_H_target*/

--
- Harald Welte <[email protected]> http://www.netfilter.org/
============================================================================
"Fragmentation is like classful addressing -- an interesting early
architectural error that shows how much experimentation was going
on while IP was being designed." -- Paul Vixie

__

Vivek Kashyap
Linux Technology Center, IBM

#9 lore raw

Re: [PATCH] RANGEMARK target

In reply to Harald Welte
Quoted 10 lines · Harald Welte
Quoted 1 line · Vivek Kashyap

I wanted to MARK packets dynamically within a certain range.

Ok, thanks for this contribution.

Quoted 2 lines

Please comment. I'll then update with necessary changes and also add ip6t_* target.

I'm going to comment inline.

I've updated the patch as per the comments.

Vivek

-------------------------------------------------------------------

extensions/libip6t_RANGEMARK.c +293 -0
diff -urN iptables-1.2.9.orig/extensions/libip6t_RANGEMARK.c iptables-1.2.9rc1/extensions/libip6t_RANGEMARK.c
@@ -0,0 +1,293 @@
+/* Shared library add-on to iptables to add RANGEMARK target support. */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ctype.h>
+
+#include <ip6tables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6t_RANGEMARK.h>
+
+struct rangemarkinfo {
+	struct ip6t_entry_target t;
+	struct ip6t_rangemark_target_info rangemark;
+};
+
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+	printf(
+"RANGEMARK target v%s options:\n"
+"  --set-rangemark base[-limit[.k][:r]][,S|O|A]] Set random nfmark within range"
+"\n"
+"  --set-rangemark base[-limit[.k][:h]][,S|O|A]] Set nfmark based on ports"
+"\n",
+IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+	{ "set-rangemark", 1, 0, '1' },
+	{ 0 }
+};
+
+static char *
+get_val(char *s, unsigned long *val)
+{
+	char *ep = s;
+	
+	if (NULL == s)
+		return NULL;
+
+	if (*s == '\0') 
+		exit_error(PARAMETER_PROBLEM, "Invalid base-limit specified");
+
+	while(isalnum(*ep++));
+
+	/*
+	 * Out of range values are clipped at ULONG_MAX
+	 */
+	*val  = strtoul(s,&ep,0);
+
+	return ep;
+}
+
+static char *
+get_baseval(char *s, unsigned long *val, unsigned int *flags)
+{
+	if (*flags & RANGEMARK_FLAG_BASE)
+		exit_error(PARAMETER_PROBLEM, 
+			"set-rangemark: Base specified twice");
+
+	*flags |= RANGEMARK_FLAG_BASE;
+
+	return get_val(s, val);
+}
+
+static char *
+get_limitval(char *s, unsigned long *val, unsigned int *flags)
+{
+	if (*flags & RANGEMARK_FLAG_LIMIT)
+		exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: Limit specified twice");
+
+	*flags |= RANGEMARK_FLAG_LIMIT;
+
+	return get_val(s, val);
+}
+
+static char *
+get_incrval(char *s, unsigned long *val, unsigned int *flags)
+{
+	if (*flags & RANGEMARK_FLAG_INCRVALUE)
+		exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: Increment specified twice");
+
+	*flags |= RANGEMARK_FLAG_INCRVALUE;
+
+	return get_val(s, val);
+}
+
+static char *
+get_policy(char *s, char *policy, unsigned int *flags)
+{
+	if (*flags & RANGEMARK_FLAG_POLICY)
+		exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: Policy specified twice");
+
+	*flags |= RANGEMARK_FLAG_POLICY;
+
+	switch(*s) {
+	case 'r': /* random */
+	case 'h': /* port hash */
+		*policy = *s;
+		break;
+
+	default: /* unrecognised */
+		exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: Unrecognised policy");
+		return NULL;
+	}
+
+	return ++s;
+}
+
+	
+static char *
+get_op(char *s, char *op, unsigned *flags)
+{
+	if (*flags & RANGEMARK_FLAG_OP)
+		exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: Policy specified twice");
+
+	*flags |= RANGEMARK_FLAG_OP;
+
+	switch(*s) {
+	case 'S': /* Set the value overwriting any existing value */
+	case 'O': /* OR the value with the existing value */
+	case 'A': /* AND the value with the existing value */
+		*op = *s;
+		break;
+
+	default: /* unrecognised */
+		exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: Unrecognised operation");
+		return NULL;
+	}
+	return ++s;
+}
+	
+
+static int
+parse_params(int c, struct ip6t_rangemark_target_info *rinfo, char **argv, 
+			unsigned int *flags)
+{
+
+	char *ptr = NULL;
+	unsigned long mask;
+
+	switch(c) {
+	case '1': 
+		/* Calculate the base value */
+		ptr = get_baseval(optarg, &rinfo->base, flags);
+
+		/* Get the limit if present */
+		if (ptr && *ptr == '-') {
+			ptr = get_limitval(++ptr, &rinfo->limit, flags);
+		}
+
+		/* Get the incr value if present */
+		if (ptr && *ptr == '.') {
+			ptr = get_incrval(++ptr, &rinfo->incr, flags);
+		}
+
+		/* Get the policy if specified */
+		if (ptr && ( *ptr == ':')){
+				ptr = get_policy(++ptr, &rinfo->policy, flags);
+		}
+
+		/* Get the operation if specified */
+		if (ptr && *ptr == ',') {
+			ptr = get_op(++ptr, &rinfo->op, flags);
+		}
+
+		if (ptr && *ptr) {
+			exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: Unrecognised option");
+		}
+
+		if (!(*flags & RANGEMARK_FLAG_LIMIT))
+			rinfo->limit = rinfo->base;
+		if (!(*flags & RANGEMARK_FLAG_INCRVALUE))
+			rinfo->incr = 1;
+		if (!(*flags & RANGEMARK_FLAG_POLICY))
+			rinfo->policy = RANGEMARK_POLICY_RANDOM;
+		if (!(*flags & RANGEMARK_FLAG_OP))
+			rinfo->op = RANGEMARK_OP_SET;
+
+		/*
+		 * Set the mask 
+		 */
+		mask = rinfo->limit - rinfo->base;
+		rinfo->mask = 1;
+		while(mask >>= 1)
+			rinfo->mask = (rinfo->mask << 1) | 1;
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 1;
+}
+
+/* Initialize the target. */
+static void
+init(struct ip6t_entry_target *t, unsigned int *nfcache)
+{
+}
+
+/* Function which parses command options; returns true if it
+   ate an option */
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+	  const struct ip6t_entry *entry,
+	  struct ip6t_entry_target **target)
+{
+
+	int ret = 0;
+	struct ip6t_rangemark_target_info *rangeinfo = 
+			(struct ip6t_rangemark_target_info *)(*target)->data;
+
+	switch (c) {
+	case '1':
+		if (invert)
+			exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: invert flag used\n");
+		ret = parse_params(c, rangeinfo, argv, flags);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return ret;
+}
+
+static void
+final_check(unsigned int flags)
+{
+}
+
+static void
+print_rangemark(struct ip6t_rangemark_target_info *r)
+{
+	printf("RANGEMARK Policy: %s Range: 0x%lx-0x%lx Incr: 0x%lx : %s  ", 
+		r->policy == 'h' ? "Hash" : "Random",
+		r->base, r->limit, r->incr,
+		r->op == 'S' ? "Set" : (r->op == 'O' ? "OR" : "AND")); 
+}
+
+/* Prints out the targinfo. */
+static void
+print(const struct ip6t_ip6 *ip,
+	  const struct ip6t_entry_target *target,
+	  int numeric)
+{
+	struct ip6t_rangemark_target_info *rinfo =
+		(struct ip6t_rangemark_target_info *)target->data;
+	print_rangemark(rinfo);
+}
+
+/* Saves the union ip6t_targinfo in parsable form to stdout. */
+static void
+save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
+{
+	struct ip6t_rangemark_target_info *r =
+		(struct ip6t_rangemark_target_info *)target->data;
+
+	printf("--set-rangemark %lu-%lu.%lu:%c,%c",r->base, r->limit,
+			r->incr, r->policy, r->op);
+}
+
+static
+struct ip6tables_target rangemark
+= {	NULL,
+	"RANGEMARK",
+	IPTABLES_VERSION,
+	IP6T_ALIGN(sizeof(struct ip6t_rangemark_target_info)),
+	IP6T_ALIGN(sizeof(struct ip6t_rangemark_target_info)),
+	&help,
+	&init,
+	&parse,
+	&final_check,
+	&print,
+	&save,
+	opts
+};
+
+void _init(void)
+{
+	register_target6(&rangemark);
+}
extensions/libipt_RANGEMARK.c +294 -0

294 lines not on this page · raw message

extensions/.RANGEMARK-test +2 -0
diff -urN iptables-1.2.9.orig/extensions/.RANGEMARK-test iptables-1.2.9rc1/extensions/.RANGEMARK-test
@@ -0,0 +1,2 @@
+#! /bin/sh
+[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_RANGEMARK.c ] && echo RANGEMARK
extensions/.RANGEMARK-test6 +2 -0
diff -urN iptables-1.2.9.orig/extensions/.RANGEMARK-test6 iptables-1.2.9rc1/extensions/.RANGEMARK-test6
@@ -0,0 +1,2 @@
+#! /bin/sh
+[ -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_RANGEMARK.c ] && echo RANGEMARK
include/linux/netfilter_ipv4/ipt_RANGEMARK.h +40 -0
diff -urN iptables-1.2.9.orig/include/linux/netfilter_ipv4/ipt_RANGEMARK.h iptables-1.2.9rc1/include/linux/netfilter_ipv4/ipt_RANGEMARK.h
@@ -0,0 +1,40 @@
+#ifndef _IPT_RANGEMARK_H_target
+#define _IPT_RANGEMARK_H_target
+
+#include <linux/spinlock.h>
+
+/*
+ * Policy
+ */
+#define RANGEMARK_POLICY_RANDOM	'r'
+#define RANGEMARK_POLICY_PORTHASH 	'h'
+
+/*
+ * Operations
+ */
+#define RANGEMARK_OP_SET 	'S'
+#define RANGEMARK_OP_OR 	'O'
+#define RANGEMARK_OP_AND 	'A'
+
+/*
+ * Flags
+ */
+enum rangemark_flags {
+	RANGEMARK_FLAG_BASE = 1,
+	RANGEMARK_FLAG_LIMIT = 2,
+	RANGEMARK_FLAG_POLICY = 4,
+	RANGEMARK_FLAG_OP = 8,
+	RANGEMARK_FLAG_INCRVALUE = 16,
+};
+
+struct ipt_rangemark_target_info {
+	unsigned long	base;
+	unsigned long 	limit;
+	unsigned long	rsize;
+	unsigned long	incr;
+	signed   long   mask;
+	char		policy;
+	char 		op;
+};
+
+#endif /*_IPT_RANGEMARK_H_target*/
include/linux/netfilter_ipv6/ip6t_RANGEMARK.h +40 -0
diff -urN iptables-1.2.9.orig/include/linux/netfilter_ipv6/ip6t_RANGEMARK.h iptables-1.2.9rc1/include/linux/netfilter_ipv6/ip6t_RANGEMARK.h
@@ -0,0 +1,40 @@
+#ifndef _IP6T_RANGEMARK_H_target
+#define _IP6T_RANGEMARK_H_target
+
+#include <linux/spinlock.h>
+
+/*
+ * Policy
+ */
+#define RANGEMARK_POLICY_RANDOM	'r'
+#define RANGEMARK_POLICY_PORTHASH 	'h'
+
+/*
+ * Operations
+ */
+#define RANGEMARK_OP_SET 	'S'
+#define RANGEMARK_OP_OR 	'O'
+#define RANGEMARK_OP_AND 	'A'
+
+/*
+ * Flags
+ */
+enum rangemark_flags {
+	RANGEMARK_FLAG_BASE = 1,
+	RANGEMARK_FLAG_LIMIT = 2,
+	RANGEMARK_FLAG_POLICY = 4,
+	RANGEMARK_FLAG_OP = 8,
+	RANGEMARK_FLAG_INCRVALUE = 16,
+};
+
+struct ip6t_rangemark_target_info {
+	unsigned long	base;
+	unsigned long 	limit;
+	unsigned long	rsize;
+	unsigned long	incr;
+	signed   long   mask;
+	char		policy;
+	char 		op;
+};
+
+#endif /*_IP6T_RANGEMARK_H_target*/
include/linux/netfilter_ipv4/ipt_RANGEMARK.h +40 -0
diff -urN linux-2.4.22.orig/include/linux/netfilter_ipv4/ipt_RANGEMARK.h linux-2.4.22/include/linux/netfilter_ipv4/ipt_RANGEMARK.h
@@ -0,0 +1,40 @@
+#ifndef _IPT_RANGEMARK_H_target
+#define _IPT_RANGEMARK_H_target
+
+#include <linux/spinlock.h>
+
+/*
+ * Policy
+ */
+#define RANGEMARK_POLICY_RANDOM	'r'
+#define RANGEMARK_POLICY_PORTHASH 	'h'
+
+/*
+ * Operations
+ */
+#define RANGEMARK_OP_SET 	'S'
+#define RANGEMARK_OP_OR 	'O'
+#define RANGEMARK_OP_AND 	'A'
+
+/*
+ * Flags
+ */
+enum rangemark_flags {
+	RANGEMARK_FLAG_BASE = 1,
+	RANGEMARK_FLAG_LIMIT = 2,
+	RANGEMARK_FLAG_POLICY = 4,
+	RANGEMARK_FLAG_OP = 8,
+	RANGEMARK_FLAG_INCRVALUE = 16,
+};
+
+struct ipt_rangemark_target_info {
+	unsigned long	base;
+	unsigned long 	limit;
+	unsigned long	rsize;
+	unsigned long	incr;
+	signed   long   mask;
+	char		policy;
+	char 		op;
+};
+
+#endif /*_IPT_RANGEMARK_H_target*/
include/linux/netfilter_ipv6/ip6t_RANGEMARK.h +40 -0
diff -urN linux-2.4.22.orig/include/linux/netfilter_ipv6/ip6t_RANGEMARK.h linux-2.4.22/include/linux/netfilter_ipv6/ip6t_RANGEMARK.h
@@ -0,0 +1,40 @@
+#ifndef _IP6T_RANGEMARK_H_target
+#define _IP6T_RANGEMARK_H_target
+
+#include <linux/spinlock.h>
+
+/*
+ * Policy
+ */
+#define RANGEMARK_POLICY_RANDOM	'r'
+#define RANGEMARK_POLICY_PORTHASH 	'h'
+
+/*
+ * Operations
+ */
+#define RANGEMARK_OP_SET 	'S'
+#define RANGEMARK_OP_OR 	'O'
+#define RANGEMARK_OP_AND 	'A'
+
+/*
+ * Flags
+ */
+enum rangemark_flags {
+	RANGEMARK_FLAG_BASE = 1,
+	RANGEMARK_FLAG_LIMIT = 2,
+	RANGEMARK_FLAG_POLICY = 4,
+	RANGEMARK_FLAG_OP = 8,
+	RANGEMARK_FLAG_INCRVALUE = 16,
+};
+
+struct ip6t_rangemark_target_info {
+	unsigned long	base;
+	unsigned long 	limit;
+	unsigned long	rsize;
+	unsigned long	incr;
+	signed   long   mask;
+	char		policy;
+	char 		op;
+};
+
+#endif /*_IP6T_RANGEMARK_H_target*/
net/ipv4/netfilter/Config.in +1 -0
diff -urN linux-2.4.22.orig/net/ipv4/netfilter/Config.in linux-2.4.22/net/ipv4/netfilter/Config.in
@@ -104,6 +104,7 @@
     dep_tristate '    DSCP target support' CONFIG_IP_NF_TARGET_DSCP $CONFIG_IP_NF_MANGLE
  
     dep_tristate '    MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
+    dep_tristate '    RANGEMARK target support' CONFIG_IP_NF_TARGET_RANGEMARK $CONFIG_IP_NF_MANGLE
   fi
   dep_tristate '  LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES
   dep_tristate '  ULOG target support' CONFIG_IP_NF_TARGET_ULOG $CONFIG_IP_NF_IPTABLES
net/ipv4/netfilter/ipt_RANGEMARK.c +188 -0

188 lines not on this page · raw message

net/ipv4/netfilter/Makefile +1 -0
diff -urN linux-2.4.22.orig/net/ipv4/netfilter/Makefile linux-2.4.22/net/ipv4/netfilter/Makefile
@@ -94,6 +94,7 @@
 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
+obj-$(CONFIG_IP_NF_TARGET_RANGEMARK) += ipt_RANGEMARK.o
 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
net/ipv6/netfilter/Config.in +1 -0
diff -urN linux-2.4.22.orig/net/ipv6/netfilter/Config.in linux-2.4.22/net/ipv6/netfilter/Config.in
@@ -34,6 +34,7 @@
   fi
 #  dep_tristate '  MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES
   dep_tristate '  netfilter MARK match support' CONFIG_IP6_NF_MATCH_MARK $CONFIG_IP6_NF_IPTABLES
+  dep_tristate '  netfilter RANGEMARK match support' CONFIG_IP6_NF_MATCH_RANGEMARK $CONFIG_IP6_NF_IPTABLES
   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
     dep_tristate '  IPv6 Extension Headers Match (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_IPV6HEADER $CONFIG_IP6_NF_IPTABLES
   fi
net/ipv6/netfilter/ip6t_RANGEMARK.c +188 -0

188 lines not on this page · raw message

net/ipv6/netfilter/Makefile +1 -0
diff -urN linux-2.4.22.orig/net/ipv6/netfilter/Makefile linux-2.4.22/net/ipv6/netfilter/Makefile
@@ -28,6 +28,7 @@
 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
+obj-$(CONFIG_IP6_NF_TARGET_RANGEMARK) += ip6t_RANGEMARK.o
 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
#10 lore raw

Re: [PATCH] RANGEMARK target

In reply to Harald Welte
Quoted 9 lines · Harald Welte
Quoted 1 line · Vivek Kashyap

I wanted to MARK packets dynamically within a certain range.

Ok, thanks for this contribution.

Quoted 2 lines

Please comment. I'll then update with necessary changes and also add ip6t_* target.

I'm going to comment inline.

I've updated the patch as per the comments. Attached below.

Vivek

--------------------------------------------------------------

extensions/libip6t_RANGEMARK.c +293 -0
diff -urN iptables-1.2.9.orig/extensions/libip6t_RANGEMARK.c iptables-1.2.9rc1/extensions/libip6t_RANGEMARK.c
@@ -0,0 +1,293 @@
+/* Shared library add-on to iptables to add RANGEMARK target support. */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ctype.h>
+
+#include <ip6tables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6t_RANGEMARK.h>
+
+struct rangemarkinfo {
+	struct ip6t_entry_target t;
+	struct ip6t_rangemark_target_info rangemark;
+};
+
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+	printf(
+"RANGEMARK target v%s options:\n"
+"  --set-rangemark base[-limit[.k][:r]][,S|O|A]] Set random nfmark within range"
+"\n"
+"  --set-rangemark base[-limit[.k][:h]][,S|O|A]] Set nfmark based on ports"
+"\n",
+IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+	{ "set-rangemark", 1, 0, '1' },
+	{ 0 }
+};
+
+static char *
+get_val(char *s, unsigned long *val)
+{
+	char *ep = s;
+	
+	if (NULL == s)
+		return NULL;
+
+	if (*s == '\0') 
+		exit_error(PARAMETER_PROBLEM, "Invalid base-limit specified");
+
+	while(isalnum(*ep++));
+
+	/*
+	 * Out of range values are clipped at ULONG_MAX
+	 */
+	*val  = strtoul(s,&ep,0);
+
+	return ep;
+}
+
+static char *
+get_baseval(char *s, unsigned long *val, unsigned int *flags)
+{
+	if (*flags & RANGEMARK_FLAG_BASE)
+		exit_error(PARAMETER_PROBLEM, 
+			"set-rangemark: Base specified twice");
+
+	*flags |= RANGEMARK_FLAG_BASE;
+
+	return get_val(s, val);
+}
+
+static char *
+get_limitval(char *s, unsigned long *val, unsigned int *flags)
+{
+	if (*flags & RANGEMARK_FLAG_LIMIT)
+		exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: Limit specified twice");
+
+	*flags |= RANGEMARK_FLAG_LIMIT;
+
+	return get_val(s, val);
+}
+
+static char *
+get_incrval(char *s, unsigned long *val, unsigned int *flags)
+{
+	if (*flags & RANGEMARK_FLAG_INCRVALUE)
+		exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: Increment specified twice");
+
+	*flags |= RANGEMARK_FLAG_INCRVALUE;
+
+	return get_val(s, val);
+}
+
+static char *
+get_policy(char *s, char *policy, unsigned int *flags)
+{
+	if (*flags & RANGEMARK_FLAG_POLICY)
+		exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: Policy specified twice");
+
+	*flags |= RANGEMARK_FLAG_POLICY;
+
+	switch(*s) {
+	case 'r': /* random */
+	case 'h': /* port hash */
+		*policy = *s;
+		break;
+
+	default: /* unrecognised */
+		exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: Unrecognised policy");
+		return NULL;
+	}
+
+	return ++s;
+}
+
+	
+static char *
+get_op(char *s, char *op, unsigned *flags)
+{
+	if (*flags & RANGEMARK_FLAG_OP)
+		exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: Policy specified twice");
+
+	*flags |= RANGEMARK_FLAG_OP;
+
+	switch(*s) {
+	case 'S': /* Set the value overwriting any existing value */
+	case 'O': /* OR the value with the existing value */
+	case 'A': /* AND the value with the existing value */
+		*op = *s;
+		break;
+
+	default: /* unrecognised */
+		exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: Unrecognised operation");
+		return NULL;
+	}
+	return ++s;
+}
+	
+
+static int
+parse_params(int c, struct ip6t_rangemark_target_info *rinfo, char **argv, 
+			unsigned int *flags)
+{
+
+	char *ptr = NULL;
+	unsigned long mask;
+
+	switch(c) {
+	case '1': 
+		/* Calculate the base value */
+		ptr = get_baseval(optarg, &rinfo->base, flags);
+
+		/* Get the limit if present */
+		if (ptr && *ptr == '-') {
+			ptr = get_limitval(++ptr, &rinfo->limit, flags);
+		}
+
+		/* Get the incr value if present */
+		if (ptr && *ptr == '.') {
+			ptr = get_incrval(++ptr, &rinfo->incr, flags);
+		}
+
+		/* Get the policy if specified */
+		if (ptr && ( *ptr == ':')){
+				ptr = get_policy(++ptr, &rinfo->policy, flags);
+		}
+
+		/* Get the operation if specified */
+		if (ptr && *ptr == ',') {
+			ptr = get_op(++ptr, &rinfo->op, flags);
+		}
+
+		if (ptr && *ptr) {
+			exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: Unrecognised option");
+		}
+
+		if (!(*flags & RANGEMARK_FLAG_LIMIT))
+			rinfo->limit = rinfo->base;
+		if (!(*flags & RANGEMARK_FLAG_INCRVALUE))
+			rinfo->incr = 1;
+		if (!(*flags & RANGEMARK_FLAG_POLICY))
+			rinfo->policy = RANGEMARK_POLICY_RANDOM;
+		if (!(*flags & RANGEMARK_FLAG_OP))
+			rinfo->op = RANGEMARK_OP_SET;
+
+		/*
+		 * Set the mask 
+		 */
+		mask = rinfo->limit - rinfo->base;
+		rinfo->mask = 1;
+		while(mask >>= 1)
+			rinfo->mask = (rinfo->mask << 1) | 1;
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 1;
+}
+
+/* Initialize the target. */
+static void
+init(struct ip6t_entry_target *t, unsigned int *nfcache)
+{
+}
+
+/* Function which parses command options; returns true if it
+   ate an option */
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+	  const struct ip6t_entry *entry,
+	  struct ip6t_entry_target **target)
+{
+
+	int ret = 0;
+	struct ip6t_rangemark_target_info *rangeinfo = 
+			(struct ip6t_rangemark_target_info *)(*target)->data;
+
+	switch (c) {
+	case '1':
+		if (invert)
+			exit_error(PARAMETER_PROBLEM, 
+				"set-rangemark: invert flag used\n");
+		ret = parse_params(c, rangeinfo, argv, flags);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return ret;
+}
+
+static void
+final_check(unsigned int flags)
+{
+}
+
+static void
+print_rangemark(struct ip6t_rangemark_target_info *r)
+{
+	printf("RANGEMARK Policy: %s Range: 0x%lx-0x%lx Incr: 0x%lx : %s  ", 
+		r->policy == 'h' ? "Hash" : "Random",
+		r->base, r->limit, r->incr,
+		r->op == 'S' ? "Set" : (r->op == 'O' ? "OR" : "AND")); 
+}
+
+/* Prints out the targinfo. */
+static void
+print(const struct ip6t_ip6 *ip,
+	  const struct ip6t_entry_target *target,
+	  int numeric)
+{
+	struct ip6t_rangemark_target_info *rinfo =
+		(struct ip6t_rangemark_target_info *)target->data;
+	print_rangemark(rinfo);
+}
+
+/* Saves the union ip6t_targinfo in parsable form to stdout. */
+static void
+save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
+{
+	struct ip6t_rangemark_target_info *r =
+		(struct ip6t_rangemark_target_info *)target->data;
+
+	printf("--set-rangemark %lu-%lu.%lu:%c,%c",r->base, r->limit,
+			r->incr, r->policy, r->op);
+}
+
+static
+struct ip6tables_target rangemark
+= {	NULL,
+	"RANGEMARK",
+	IPTABLES_VERSION,
+	IP6T_ALIGN(sizeof(struct ip6t_rangemark_target_info)),
+	IP6T_ALIGN(sizeof(struct ip6t_rangemark_target_info)),
+	&help,
+	&init,
+	&parse,
+	&final_check,
+	&print,
+	&save,
+	opts
+};
+
+void _init(void)
+{
+	register_target6(&rangemark);
+}
extensions/libipt_RANGEMARK.c +294 -0

294 lines not on this page · raw message

extensions/.RANGEMARK-test +2 -0
diff -urN iptables-1.2.9.orig/extensions/.RANGEMARK-test iptables-1.2.9rc1/extensions/.RANGEMARK-test
@@ -0,0 +1,2 @@
+#! /bin/sh
+[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_RANGEMARK.c ] && echo RANGEMARK
extensions/.RANGEMARK-test6 +2 -0
diff -urN iptables-1.2.9.orig/extensions/.RANGEMARK-test6 iptables-1.2.9rc1/extensions/.RANGEMARK-test6
@@ -0,0 +1,2 @@
+#! /bin/sh
+[ -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_RANGEMARK.c ] && echo RANGEMARK
include/linux/netfilter_ipv4/ipt_RANGEMARK.h +40 -0
diff -urN iptables-1.2.9.orig/include/linux/netfilter_ipv4/ipt_RANGEMARK.h iptables-1.2.9rc1/include/linux/netfilter_ipv4/ipt_RANGEMARK.h
@@ -0,0 +1,40 @@
+#ifndef _IPT_RANGEMARK_H_target
+#define _IPT_RANGEMARK_H_target
+
+#include <linux/spinlock.h>
+
+/*
+ * Policy
+ */
+#define RANGEMARK_POLICY_RANDOM	'r'
+#define RANGEMARK_POLICY_PORTHASH 	'h'
+
+/*
+ * Operations
+ */
+#define RANGEMARK_OP_SET 	'S'
+#define RANGEMARK_OP_OR 	'O'
+#define RANGEMARK_OP_AND 	'A'
+
+/*
+ * Flags
+ */
+enum rangemark_flags {
+	RANGEMARK_FLAG_BASE = 1,
+	RANGEMARK_FLAG_LIMIT = 2,
+	RANGEMARK_FLAG_POLICY = 4,
+	RANGEMARK_FLAG_OP = 8,
+	RANGEMARK_FLAG_INCRVALUE = 16,
+};
+
+struct ipt_rangemark_target_info {
+	unsigned long	base;
+	unsigned long 	limit;
+	unsigned long	rsize;
+	unsigned long	incr;
+	signed   long   mask;
+	char		policy;
+	char 		op;
+};
+
+#endif /*_IPT_RANGEMARK_H_target*/
include/linux/netfilter_ipv6/ip6t_RANGEMARK.h +40 -0
diff -urN iptables-1.2.9.orig/include/linux/netfilter_ipv6/ip6t_RANGEMARK.h iptables-1.2.9rc1/include/linux/netfilter_ipv6/ip6t_RANGEMARK.h
@@ -0,0 +1,40 @@
+#ifndef _IP6T_RANGEMARK_H_target
+#define _IP6T_RANGEMARK_H_target
+
+#include <linux/spinlock.h>
+
+/*
+ * Policy
+ */
+#define RANGEMARK_POLICY_RANDOM	'r'
+#define RANGEMARK_POLICY_PORTHASH 	'h'
+
+/*
+ * Operations
+ */
+#define RANGEMARK_OP_SET 	'S'
+#define RANGEMARK_OP_OR 	'O'
+#define RANGEMARK_OP_AND 	'A'
+
+/*
+ * Flags
+ */
+enum rangemark_flags {
+	RANGEMARK_FLAG_BASE = 1,
+	RANGEMARK_FLAG_LIMIT = 2,
+	RANGEMARK_FLAG_POLICY = 4,
+	RANGEMARK_FLAG_OP = 8,
+	RANGEMARK_FLAG_INCRVALUE = 16,
+};
+
+struct ip6t_rangemark_target_info {
+	unsigned long	base;
+	unsigned long 	limit;
+	unsigned long	rsize;
+	unsigned long	incr;
+	signed   long   mask;
+	char		policy;
+	char 		op;
+};
+
+#endif /*_IP6T_RANGEMARK_H_target*/
include/linux/netfilter_ipv4/ipt_RANGEMARK.h +40 -0
diff -urN linux-2.4.22.orig/include/linux/netfilter_ipv4/ipt_RANGEMARK.h linux-2.4.22/include/linux/netfilter_ipv4/ipt_RANGEMARK.h
@@ -0,0 +1,40 @@
+#ifndef _IPT_RANGEMARK_H_target
+#define _IPT_RANGEMARK_H_target
+
+#include <linux/spinlock.h>
+
+/*
+ * Policy
+ */
+#define RANGEMARK_POLICY_RANDOM	'r'
+#define RANGEMARK_POLICY_PORTHASH 	'h'
+
+/*
+ * Operations
+ */
+#define RANGEMARK_OP_SET 	'S'
+#define RANGEMARK_OP_OR 	'O'
+#define RANGEMARK_OP_AND 	'A'
+
+/*
+ * Flags
+ */
+enum rangemark_flags {
+	RANGEMARK_FLAG_BASE = 1,
+	RANGEMARK_FLAG_LIMIT = 2,
+	RANGEMARK_FLAG_POLICY = 4,
+	RANGEMARK_FLAG_OP = 8,
+	RANGEMARK_FLAG_INCRVALUE = 16,
+};
+
+struct ipt_rangemark_target_info {
+	unsigned long	base;
+	unsigned long 	limit;
+	unsigned long	rsize;
+	unsigned long	incr;
+	signed   long   mask;
+	char		policy;
+	char 		op;
+};
+
+#endif /*_IPT_RANGEMARK_H_target*/
include/linux/netfilter_ipv6/ip6t_RANGEMARK.h +40 -0
diff -urN linux-2.4.22.orig/include/linux/netfilter_ipv6/ip6t_RANGEMARK.h linux-2.4.22/include/linux/netfilter_ipv6/ip6t_RANGEMARK.h
@@ -0,0 +1,40 @@
+#ifndef _IP6T_RANGEMARK_H_target
+#define _IP6T_RANGEMARK_H_target
+
+#include <linux/spinlock.h>
+
+/*
+ * Policy
+ */
+#define RANGEMARK_POLICY_RANDOM	'r'
+#define RANGEMARK_POLICY_PORTHASH 	'h'
+
+/*
+ * Operations
+ */
+#define RANGEMARK_OP_SET 	'S'
+#define RANGEMARK_OP_OR 	'O'
+#define RANGEMARK_OP_AND 	'A'
+
+/*
+ * Flags
+ */
+enum rangemark_flags {
+	RANGEMARK_FLAG_BASE = 1,
+	RANGEMARK_FLAG_LIMIT = 2,
+	RANGEMARK_FLAG_POLICY = 4,
+	RANGEMARK_FLAG_OP = 8,
+	RANGEMARK_FLAG_INCRVALUE = 16,
+};
+
+struct ip6t_rangemark_target_info {
+	unsigned long	base;
+	unsigned long 	limit;
+	unsigned long	rsize;
+	unsigned long	incr;
+	signed   long   mask;
+	char		policy;
+	char 		op;
+};
+
+#endif /*_IP6T_RANGEMARK_H_target*/
net/ipv4/netfilter/Config.in +1 -0
diff -urN linux-2.4.22.orig/net/ipv4/netfilter/Config.in linux-2.4.22/net/ipv4/netfilter/Config.in
@@ -104,6 +104,7 @@
     dep_tristate '    DSCP target support' CONFIG_IP_NF_TARGET_DSCP $CONFIG_IP_NF_MANGLE
  
     dep_tristate '    MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
+    dep_tristate '    RANGEMARK target support' CONFIG_IP_NF_TARGET_RANGEMARK $CONFIG_IP_NF_MANGLE
   fi
   dep_tristate '  LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES
   dep_tristate '  ULOG target support' CONFIG_IP_NF_TARGET_ULOG $CONFIG_IP_NF_IPTABLES
net/ipv4/netfilter/ipt_RANGEMARK.c +188 -0

188 lines not on this page · raw message

net/ipv4/netfilter/Makefile +1 -0
diff -urN linux-2.4.22.orig/net/ipv4/netfilter/Makefile linux-2.4.22/net/ipv4/netfilter/Makefile
@@ -94,6 +94,7 @@
 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
+obj-$(CONFIG_IP_NF_TARGET_RANGEMARK) += ipt_RANGEMARK.o
 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
net/ipv6/netfilter/Config.in +1 -0
diff -urN linux-2.4.22.orig/net/ipv6/netfilter/Config.in linux-2.4.22/net/ipv6/netfilter/Config.in
@@ -34,6 +34,7 @@
   fi
 #  dep_tristate '  MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES
   dep_tristate '  netfilter MARK match support' CONFIG_IP6_NF_MATCH_MARK $CONFIG_IP6_NF_IPTABLES
+  dep_tristate '  netfilter RANGEMARK match support' CONFIG_IP6_NF_MATCH_RANGEMARK $CONFIG_IP6_NF_IPTABLES
   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
     dep_tristate '  IPv6 Extension Headers Match (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_IPV6HEADER $CONFIG_IP6_NF_IPTABLES
   fi
net/ipv6/netfilter/ip6t_RANGEMARK.c +188 -0

188 lines not on this page · raw message

net/ipv6/netfilter/Makefile +1 -0
diff -urN linux-2.4.22.orig/net/ipv6/netfilter/Makefile linux-2.4.22/net/ipv6/netfilter/Makefile
@@ -28,6 +28,7 @@
 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
+obj-$(CONFIG_IP6_NF_TARGET_RANGEMARK) += ip6t_RANGEMARK.o
 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o

A message that is not in the archive (sent off-list or not yet received): Pine.LNX.4.44.0311210839010.1186-100000@loopback.beaverton.ibm.com

#12 lore raw

Re: [PATCH] RANGEMARK target

Quoted 3 lines · Vivek Kashyap

Harald,

What is the status of this patch?

Sorry, I haven't yet put in in patch-o-matic. If you want to speed it up, please submit in patch-o-matic format (i.e. move the Makefile and config.in changes to seperate files, etc.).

Quoted 3 lines

In general is there a way to determine the
status without querying? for e.g. I downloaded the 1119 snapshot from ftp.netfilter.org to verify.

We have anonymous CVS access, please refer to
http://www.netfilter.org/downloads.html#cvs

Quoted 1 line

Vivek

Signature · 5 lines
- Harald Welte <[email protected]>             http://www.netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie