Hi Florian,

I attached two 'draft' patches in this email :)

Thanks,
Jack
From 6d811e63c9c777ed4287bc4547134c99e939b49d Mon Sep 17 00:00:00 2001
From: Jack Ma <jack...@alliedtelesis.co.nz>
Date: Mon, 12 Feb 2018 13:41:29 +1300
Subject: [PATCH] libxt_CONNMARK: Support bit-shifting for --restore,set and
 save-mark

Added bit-shifting operations for --restore & set & save-mark.

Signed-off-by: Jack Ma <jack...@alliedtelesis.co.nz>
Signed-off-by: Florian Westphal <f...@strlen.de>
---
 extensions/libxt_CONNMARK.c           | 176 ++++++++++++++++++++++++++--------
 include/linux/netfilter/xt_connmark.h |   2 +-
 2 files changed, 139 insertions(+), 39 deletions(-)

diff --git a/extensions/libxt_CONNMARK.c b/extensions/libxt_CONNMARK.c
index f60be583..dbd02351 100644
--- a/extensions/libxt_CONNMARK.c
+++ b/extensions/libxt_CONNMARK.c
@@ -28,32 +28,43 @@
 struct xt_connmark_target_info {
 	unsigned long mark;
 	unsigned long mask;
+	uint8_t shift_dir;
+	uint8_t shift_bits;
 	uint8_t mode;
 };
 
 enum {
+	D_SHIFT_LEFT = 0,
+	D_SHIFT_RIGHT,
+};
+
+enum {
 	O_SET_MARK = 0,
 	O_SAVE_MARK,
 	O_RESTORE_MARK,
 	O_AND_MARK,
 	O_OR_MARK,
 	O_XOR_MARK,
+	O_LEFT_SHIFT_MARK,
+	O_RIGHT_SHIFT_MARK,
 	O_SET_XMARK,
 	O_CTMASK,
 	O_NFMASK,
 	O_MASK,
-	F_SET_MARK     = 1 << O_SET_MARK,
-	F_SAVE_MARK    = 1 << O_SAVE_MARK,
-	F_RESTORE_MARK = 1 << O_RESTORE_MARK,
-	F_AND_MARK     = 1 << O_AND_MARK,
-	F_OR_MARK      = 1 << O_OR_MARK,
-	F_XOR_MARK     = 1 << O_XOR_MARK,
-	F_SET_XMARK    = 1 << O_SET_XMARK,
-	F_CTMASK       = 1 << O_CTMASK,
-	F_NFMASK       = 1 << O_NFMASK,
-	F_MASK         = 1 << O_MASK,
-	F_OP_ANY       = F_SET_MARK | F_SAVE_MARK | F_RESTORE_MARK |
-	                 F_AND_MARK | F_OR_MARK | F_XOR_MARK | F_SET_XMARK,
+	F_SET_MARK         = 1 << O_SET_MARK,
+	F_SAVE_MARK        = 1 << O_SAVE_MARK,
+	F_RESTORE_MARK     = 1 << O_RESTORE_MARK,
+	F_AND_MARK         = 1 << O_AND_MARK,
+	F_OR_MARK          = 1 << O_OR_MARK,
+	F_XOR_MARK         = 1 << O_XOR_MARK,
+	F_LEFT_SHIFT_MARK  = 1 << O_LEFT_SHIFT_MARK,
+	F_RIGHT_SHIFT_MARK = 1 << O_RIGHT_SHIFT_MARK,
+	F_SET_XMARK        = 1 << O_SET_XMARK,
+	F_CTMASK           = 1 << O_CTMASK,
+	F_NFMASK           = 1 << O_NFMASK,
+	F_MASK             = 1 << O_MASK,
+	F_OP_ANY           = F_SET_MARK | F_SAVE_MARK | F_RESTORE_MARK |
+	                     F_AND_MARK | F_OR_MARK | F_XOR_MARK | F_SET_XMARK,
 };
 
 static void CONNMARK_help(void)
@@ -74,6 +85,8 @@ static const struct xt_option_entry CONNMARK_opts[] = {
 	{.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
 	 .excl = F_OP_ANY},
 	{.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32},
+	{.name = "left-shift-mark", .id = O_LEFT_SHIFT_MARK, .type = XTTYPE_UINT8},
+	{.name = "right-shift-mark", .id = O_RIGHT_SHIFT_MARK, .type = XTTYPE_UINT8},
 	XTOPT_TABLEEND,
 };
 #undef s
@@ -94,6 +107,8 @@ static const struct xt_option_entry connmark_tg_opts[] = {
 	 .excl = F_OP_ANY},
 	{.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
 	 .excl = F_OP_ANY},
+	{.name = "left-shift-mark", .id = O_LEFT_SHIFT_MARK, .type = XTTYPE_UINT8},
+	{.name = "right-shift-mark", .id = O_RIGHT_SHIFT_MARK, .type = XTTYPE_UINT8},
 	{.name = "ctmask", .id = O_CTMASK, .type = XTTYPE_UINT32,
 	 .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, ctmask)},
 	{.name = "nfmask", .id = O_NFMASK, .type = XTTYPE_UINT32,
@@ -119,6 +134,8 @@ static void connmark_tg_help(void)
 "  --and-mark value              Binary AND the ctmark with bits\n"
 "  --or-mark value               Binary OR  the ctmark with bits\n"
 "  --xor-mark value              Binary XOR the ctmark with bits\n"
+"  --left-shift-mark value       Left shift the ctmark with bits\n"
+"  --right-shift-mark value      Right shift the ctmark with bits\n"
 );
 }
 
@@ -154,6 +171,16 @@ static void CONNMARK_parse(struct xt_option_call *cb)
 	case O_MASK:
 		markinfo->mask = cb->val.u32;
 		break;
+	case O_LEFT_SHIFT_MARK:
+		markinfo->mode = XT_CONNMARK_RESTORE;
+		markinfo->shift_dir = D_SHIFT_LEFT;
+		markinfo->shift_bits = cb->val.u8;
+		break;
+	case O_RIGHT_SHIFT_MARK:
+		markinfo->mode = XT_CONNMARK_RESTORE;
+		markinfo->shift_dir = D_SHIFT_RIGHT;
+		markinfo->shift_bits = cb->val.u8;
+  break;
 	}
 }
 
@@ -197,6 +224,14 @@ static void connmark_tg_parse(struct xt_option_call *cb)
 	case O_MASK:
 		info->nfmask = info->ctmask = cb->val.u32;
 		break;
+	case O_LEFT_SHIFT_MARK:
+		info->shift_dir = D_SHIFT_LEFT;
+		info->shift_bits = cb->val.u8;
+		break;
+	case O_RIGHT_SHIFT_MARK:
+		info->shift_dir = D_SHIFT_RIGHT;
+		info->shift_bits = cb->val.u8;
+  break;
 	}
 }
 
@@ -253,36 +288,101 @@ connmark_tg_print(const void *ip, const struct xt_entry_target *target,
 
 	switch (info->mode) {
 	case XT_CONNMARK_SET:
-		if (info->ctmark == 0)
-			printf(" CONNMARK and 0x%x",
-			       (unsigned int)(uint32_t)~info->ctmask);
-		else if (info->ctmark == info->ctmask)
-			printf(" CONNMARK or 0x%x", info->ctmark);
-		else if (info->ctmask == 0)
-			printf(" CONNMARK xor 0x%x", info->ctmark);
-		else if (info->ctmask == 0xFFFFFFFFU)
-			printf(" CONNMARK set 0x%x", info->ctmark);
-		else
-			printf(" CONNMARK xset 0x%x/0x%x",
-			       info->ctmark, info->ctmask);
+		if (info->ctmark == 0) {
+			if (info->shift_bits)
+				printf(" CONNMARK and 0x%x %s %d",
+					(unsigned int)(uint32_t)~info->ctmask,
+					info->shift_dir == D_SHIFT_LEFT ? "<<" : ">>",
+					info->shift_bits);
+			else
+				printf(" CONNMARK and 0x%x",
+					(unsigned int)(uint32_t)~info->ctmask);
+		}
+		else if (info->ctmark == info->ctmask) {
+			if (info->shift_bits)
+				printf(" CONNMARK or 0x%x %s %d", info->ctmark,
+					info->shift_dir == D_SHIFT_LEFT ? "<<" : ">>",
+					info->shift_bits);
+			else
+				printf(" CONNMARK or 0x%x", info->ctmark);
+		}
+		else if (info->ctmask == 0) {
+			if (info->shift_bits)
+				printf(" CONNMARK xor 0x%x %s %d", info->ctmark,
+					info->shift_dir == D_SHIFT_LEFT ? "<<" : ">>",
+					info->shift_bits);
+			else
+				printf(" CONNMARK xor 0x%x", info->ctmark);
+		}
+		else if (info->ctmask == 0xFFFFFFFFU) {
+			if (info->shift_bits)
+				printf(" CONNMARK set 0x%x %s %d", info->ctmark,
+					info->shift_dir == D_SHIFT_LEFT ? "<<" : ">>",
+					info->shift_bits);
+			else
+				printf(" CONNMARK set 0x%x", info->ctmark);
+		}
+		else {
+			if (info->shift_bits)
+				printf(" CONNMARK xset 0x%x/0x%x %s %d",
+					info->ctmark, info->ctmask, info->shift_dir ==
+					D_SHIFT_LEFT ? "<<" : ">>", info->shift_bits);
+			else
+				printf(" CONNMARK xset 0x%x/0x%x",
+						info->ctmark, info->ctmask);
+		}
 		break;
 	case XT_CONNMARK_SAVE:
-		if (info->nfmask == UINT32_MAX && info->ctmask == UINT32_MAX)
-			printf(" CONNMARK save");
-		else if (info->nfmask == info->ctmask)
-			printf(" CONNMARK save mask 0x%x", info->nfmask);
-		else
-			printf(" CONNMARK save nfmask 0x%x ctmask ~0x%x",
-			       info->nfmask, info->ctmask);
+		if (info->nfmask == UINT32_MAX && info->ctmask == UINT32_MAX) {
+			if (info->shift_bits)
+				printf(" CONNMARK save %s %d", info->shift_dir ==
+					D_SHIFT_LEFT ? "<<" : ">>", info->shift_bits);
+			else
+				printf(" CONNMARK save");
+		}
+		else if (info->nfmask == info->ctmask) {
+			if (info->shift_bits)
+				printf(" CONNMARK save mask 0x%x %s %d", info->nfmask,
+					info->shift_dir == D_SHIFT_LEFT ? "<<" : ">>",
+					info->shift_bits);
+			else
+				printf(" CONNMARK save mask 0x%x", info->nfmask);
+		}
+		else {
+			if (info->shift_bits)
+				printf(" CONNMARK save nfmask 0x%x ctmask ~0x%x %s %d",
+					info->nfmask, info->ctmask, info->shift_dir ==
+					D_SHIFT_LEFT ? "<<" : ">>", info->shift_bits);
+			else
+				printf(" CONNMARK save nfmask 0x%x ctmask ~0x%x",
+					info->nfmask, info->ctmask);
+		}
 		break;
 	case XT_CONNMARK_RESTORE:
-		if (info->ctmask == UINT32_MAX && info->nfmask == UINT32_MAX)
-			printf(" CONNMARK restore");
-		else if (info->ctmask == info->nfmask)
-			printf(" CONNMARK restore mask 0x%x", info->ctmask);
-		else
-			printf(" CONNMARK restore ctmask 0x%x nfmask ~0x%x",
-			       info->ctmask, info->nfmask);
+		if (info->ctmask == UINT32_MAX && info->nfmask == UINT32_MAX) {
+			if (info->shift_bits)
+				printf(" CONNMARK restore %s %d", info->shift_dir ==
+					D_SHIFT_LEFT ? "<<" : ">>", info->shift_bits);
+			else
+				printf(" CONNMARK restore");
+		}
+		else if (info->ctmask == info->nfmask) {
+			if (info->shift_bits)
+				printf(" CONNMARK restore mask 0x%x %s %d", info->ctmask,
+					info->shift_dir == D_SHIFT_LEFT ? "<<" : ">>",
+					info->shift_bits);
+			else
+				printf(" CONNMARK restore mask 0x%x", info->ctmask);
+		}
+		else {
+			if (info->shift_bits)
+				printf(" CONNMARK restore ctmask 0x%x nfmask ~0x%x %s %d",
+					info->ctmask, info->nfmask, info->shift_dir ==
+					D_SHIFT_LEFT ? "<<" : ">>", info->shift_bits);
+			else
+				printf(" CONNMARK restore ctmask 0x%x nfmask ~0x%x",
+					info->ctmask, info->nfmask);
+		}
 		break;
 
 	default:
diff --git a/include/linux/netfilter/xt_connmark.h b/include/linux/netfilter/xt_connmark.h
index efc17a83..2010a40c 100644
--- a/include/linux/netfilter/xt_connmark.h
+++ b/include/linux/netfilter/xt_connmark.h
@@ -20,7 +20,7 @@ enum {
 
 struct xt_connmark_tginfo1 {
 	__u32 ctmark, ctmask, nfmask;
-	__u8 mode;
+	__u8 shift_dir, shift_bits, mode;
 };
 
 struct xt_connmark_mtinfo1 {
-- 
2.13.0

From b6ff58635bb42cd4c14e03ebfccb9236fd0d5001 Mon Sep 17 00:00:00 2001
From: Jack Ma <jack...@alliedtelesis.co.nz>
Date: Mon, 12 Feb 2018 11:13:08 +1300
Subject: [PATCH] xt_conntrack: Support bit-shifting for CONNMARK & MARK.

Bit-shifting operations are added to accompany with --restore,set,
save-mark + --mask.

Signed-off-by: Jack Ma <jack...@alliedtelesis.co.nz>
Signed-off-by: Florian Westphal <f...@strlen.de>
---
 include/uapi/linux/netfilter/xt_connmark.h |  7 ++++++-
 net/netfilter/xt_connmark.c                | 16 ++++++++++++----
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/include/uapi/linux/netfilter/xt_connmark.h b/include/uapi/linux/netfilter/xt_connmark.h
index 408a9654f05c..28834812124f 100644
--- a/include/uapi/linux/netfilter/xt_connmark.h
+++ b/include/uapi/linux/netfilter/xt_connmark.h
@@ -19,9 +19,14 @@ enum {
 	XT_CONNMARK_RESTORE
 };
 
+enum {
+	D_SHIFT_LEFT = 0,
+	D_SHIFT_RIGHT,
+};
+
 struct xt_connmark_tginfo1 {
 	__u32 ctmark, ctmask, nfmask;
-	__u8 mode;
+	__u8 shift_dir, shift_bits, mode;
 };
 
 struct xt_connmark_mtinfo1 {
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index ec377cc6a369..31cb0acb6208 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -51,7 +51,10 @@ connmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
 	case XT_CONNMARK_SET:
 		newmark = (ct->mark & ~info->ctmask) ^ info->ctmark;
 		if (ct->mark != newmark) {
-			ct->mark = newmark;
+			if (info->shift_dir == D_SHIFT_RIGHT)
+				ct->mark = newmark >> info->shift_bits;
+			else
+				ct->mark = newmark << info->shift_bits;
 			nf_conntrack_event_cache(IPCT_MARK, ct);
 		}
 		break;
@@ -59,17 +62,22 @@ connmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
 		newmark = (ct->mark & ~info->ctmask) ^
 		          (skb->mark & info->nfmask);
 		if (ct->mark != newmark) {
-			ct->mark = newmark;
+			if (info->shift_dir == D_SHIFT_RIGHT)
+				ct->mark = newmark >> info->shift_bits;
+			else
+				ct->mark = newmark << info->shift_bits;
 			nf_conntrack_event_cache(IPCT_MARK, ct);
 		}
 		break;
 	case XT_CONNMARK_RESTORE:
 		newmark = (skb->mark & ~info->nfmask) ^
 		          (ct->mark & info->ctmask);
-		skb->mark = newmark;
+		if (info->shift_dir == D_SHIFT_RIGHT)
+			skb->mark = newmark >> info->shift_bits;
+		else
+			skb->mark = newmark << info->shift_bits;
 		break;
 	}
-
 	return XT_CONTINUE;
 }
 
-- 
2.13.0

Reply via email to