--- linux-2.5.56/include/linux/netfilter_ipv4/ipt_MARK.h 2003-01-09 05:03:58.000000000 +0100 +++ linux-2.5.56-new/include/linux/netfilter_ipv4/ipt_MARK.h 2003-01-14 13:28:30.000000000 +0100 @@ -5,4 +5,17 @@ unsigned long mark; }; +#define MARK_BITOPS 1 + +enum { + IPT_MARK_SET=0, + IPT_MARK_AND, + IPT_MARK_OR +}; + +struct ipt_mark_bitops_target_info { + unsigned long mark; + u_int8_t mode; +}; + #endif /*_IPT_MARK_H_target*/ --- linux-2.5.56/net/ipv4/netfilter/ipt_MARK.c 2003-01-09 05:04:15.000000000 +0100 +++ linux-2.5.56-new/net/ipv4/netfilter/ipt_MARK.c 2003-01-14 13:29:37.000000000 +0100 @@ -1,4 +1,9 @@ -/* This is a module which is used for setting the NFMARK field of an skb. */ +/* This is a module which is used for setting the NFMARK field of an skb. * + * + * 13-1-2003: Anders Fugmann + * Added bit operations ADD and OR. + */ + #include #include #include @@ -7,6 +12,10 @@ #include #include +/* If this variable is set, NFMARK works in compability mode and + Uses the old ipt_mark_target_info. */ +static int compat_mode; + static unsigned int target(struct sk_buff **pskb, unsigned int hooknum, @@ -15,12 +24,36 @@ const void *targinfo, void *userinfo) { - const struct ipt_mark_target_info *markinfo = targinfo; - - if((*pskb)->nfmark != markinfo->mark) { - (*pskb)->nfmark = markinfo->mark; - (*pskb)->nfcache |= NFC_ALTERED; + int mark; + if (compat_mode) { + const struct ipt_mark_target_info *markinfo = targinfo; + mark = markinfo->mark; + } else { + const struct ipt_mark_bitops_target_info *markinfo = targinfo; + + switch (markinfo->mode) { + case IPT_MARK_SET: + mark = markinfo->mark; + break; + + case IPT_MARK_AND: + mark = (*pskb)->nfmark & markinfo->mark; + break; + + case IPT_MARK_OR: + mark = (*pskb)->nfmark | markinfo->mark; + break; + + default: + mark = (*pskb)->nfmark; + break; + } } + if ((*pskb)->nfmark != mark) { + (*pskb)->nfmark = mark; + (*pskb)->nfcache |= NFC_ALTERED; + } + return IPT_CONTINUE; } @@ -31,15 +64,18 @@ unsigned int targinfosize, unsigned int hook_mask) { - if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) { - printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", - targinfosize, - IPT_ALIGN(sizeof(struct ipt_mark_target_info))); + if (targinfosize == IPT_ALIGN(sizeof(struct ipt_mark_target_info))) + compat_mode = 1; + else if (targinfosize != + IPT_ALIGN(sizeof(struct ipt_mark_bitops_target_info))) { + printk(KERN_WARNING "MARK: targinfosize %u mismatch\n", + targinfosize); return 0; } if (strcmp(tablename, "mangle") != 0) { - printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename); + printk(KERN_WARNING "MARK: can only be called from " + "\"mangle\" table, not \"%s\"\n", tablename); return 0; } @@ -53,6 +89,8 @@ { if (ipt_register_target(&ipt_mark_reg)) return -EINVAL; + + compat_mode = 0; return 0; }