Skip to content

Commit 472a73e

Browse files
Jack Maummakynes
authored andcommitted
netfilter: xt_conntrack: Support bit-shifting for CONNMARK & MARK targets.
This patch introduces a new feature that allows bitshifting (left and right) operations to co-operate with existing iptables options. Reviewed-by: Florian Westphal <fw@strlen.de> Signed-off-by: Jack Ma <jack.ma@alliedtelesis.co.nz> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent d72133e commit 472a73e

File tree

2 files changed

+70
-17
lines changed

2 files changed

+70
-17
lines changed

include/uapi/linux/netfilter/xt_connmark.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,21 @@ enum {
1919
XT_CONNMARK_RESTORE
2020
};
2121

22+
enum {
23+
D_SHIFT_LEFT = 0,
24+
D_SHIFT_RIGHT,
25+
};
26+
2227
struct xt_connmark_tginfo1 {
2328
__u32 ctmark, ctmask, nfmask;
2429
__u8 mode;
2530
};
2631

32+
struct xt_connmark_tginfo2 {
33+
__u32 ctmark, ctmask, nfmask;
34+
__u8 shift_dir, shift_bits, mode;
35+
};
36+
2737
struct xt_connmark_mtinfo1 {
2838
__u32 mark, mask;
2939
__u8 invert;

net/netfilter/xt_connmark.c

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,10 @@ MODULE_ALIAS("ipt_connmark");
3636
MODULE_ALIAS("ip6t_connmark");
3737

3838
static unsigned int
39-
connmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
39+
connmark_tg_shift(struct sk_buff *skb,
40+
const struct xt_connmark_tginfo1 *info,
41+
u8 shift_bits, u8 shift_dir)
4042
{
41-
const struct xt_connmark_tginfo1 *info = par->targinfo;
4243
enum ip_conntrack_info ctinfo;
4344
struct nf_conn *ct;
4445
u_int32_t newmark;
@@ -50,29 +51,57 @@ connmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
5051
switch (info->mode) {
5152
case XT_CONNMARK_SET:
5253
newmark = (ct->mark & ~info->ctmask) ^ info->ctmark;
54+
if (shift_dir == D_SHIFT_RIGHT)
55+
newmark >>= shift_bits;
56+
else
57+
newmark <<= shift_bits;
5358
if (ct->mark != newmark) {
5459
ct->mark = newmark;
5560
nf_conntrack_event_cache(IPCT_MARK, ct);
5661
}
5762
break;
5863
case XT_CONNMARK_SAVE:
5964
newmark = (ct->mark & ~info->ctmask) ^
60-
(skb->mark & info->nfmask);
65+
(skb->mark & info->nfmask);
66+
if (shift_dir == D_SHIFT_RIGHT)
67+
newmark >>= shift_bits;
68+
else
69+
newmark <<= shift_bits;
6170
if (ct->mark != newmark) {
6271
ct->mark = newmark;
6372
nf_conntrack_event_cache(IPCT_MARK, ct);
6473
}
6574
break;
6675
case XT_CONNMARK_RESTORE:
6776
newmark = (skb->mark & ~info->nfmask) ^
68-
(ct->mark & info->ctmask);
77+
(ct->mark & info->ctmask);
78+
if (shift_dir == D_SHIFT_RIGHT)
79+
newmark >>= shift_bits;
80+
else
81+
newmark <<= shift_bits;
6982
skb->mark = newmark;
7083
break;
7184
}
72-
7385
return XT_CONTINUE;
7486
}
7587

88+
static unsigned int
89+
connmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
90+
{
91+
const struct xt_connmark_tginfo1 *info = par->targinfo;
92+
93+
return connmark_tg_shift(skb, info, 0, 0);
94+
}
95+
96+
static unsigned int
97+
connmark_tg_v2(struct sk_buff *skb, const struct xt_action_param *par)
98+
{
99+
const struct xt_connmark_tginfo2 *info = par->targinfo;
100+
101+
return connmark_tg_shift(skb, (const struct xt_connmark_tginfo1 *)info,
102+
info->shift_bits, info->shift_dir);
103+
}
104+
76105
static int connmark_tg_check(const struct xt_tgchk_param *par)
77106
{
78107
int ret;
@@ -119,15 +148,27 @@ static void connmark_mt_destroy(const struct xt_mtdtor_param *par)
119148
nf_ct_netns_put(par->net, par->family);
120149
}
121150

122-
static struct xt_target connmark_tg_reg __read_mostly = {
123-
.name = "CONNMARK",
124-
.revision = 1,
125-
.family = NFPROTO_UNSPEC,
126-
.checkentry = connmark_tg_check,
127-
.target = connmark_tg,
128-
.targetsize = sizeof(struct xt_connmark_tginfo1),
129-
.destroy = connmark_tg_destroy,
130-
.me = THIS_MODULE,
151+
static struct xt_target connmark_tg_reg[] __read_mostly = {
152+
{
153+
.name = "CONNMARK",
154+
.revision = 1,
155+
.family = NFPROTO_UNSPEC,
156+
.checkentry = connmark_tg_check,
157+
.target = connmark_tg,
158+
.targetsize = sizeof(struct xt_connmark_tginfo1),
159+
.destroy = connmark_tg_destroy,
160+
.me = THIS_MODULE,
161+
},
162+
{
163+
.name = "CONNMARK",
164+
.revision = 2,
165+
.family = NFPROTO_UNSPEC,
166+
.checkentry = connmark_tg_check,
167+
.target = connmark_tg_v2,
168+
.targetsize = sizeof(struct xt_connmark_tginfo2),
169+
.destroy = connmark_tg_destroy,
170+
.me = THIS_MODULE,
171+
}
131172
};
132173

133174
static struct xt_match connmark_mt_reg __read_mostly = {
@@ -145,12 +186,14 @@ static int __init connmark_mt_init(void)
145186
{
146187
int ret;
147188

148-
ret = xt_register_target(&connmark_tg_reg);
189+
ret = xt_register_targets(connmark_tg_reg,
190+
ARRAY_SIZE(connmark_tg_reg));
149191
if (ret < 0)
150192
return ret;
151193
ret = xt_register_match(&connmark_mt_reg);
152194
if (ret < 0) {
153-
xt_unregister_target(&connmark_tg_reg);
195+
xt_unregister_targets(connmark_tg_reg,
196+
ARRAY_SIZE(connmark_tg_reg));
154197
return ret;
155198
}
156199
return 0;
@@ -159,7 +202,7 @@ static int __init connmark_mt_init(void)
159202
static void __exit connmark_mt_exit(void)
160203
{
161204
xt_unregister_match(&connmark_mt_reg);
162-
xt_unregister_target(&connmark_tg_reg);
205+
xt_unregister_target(connmark_tg_reg);
163206
}
164207

165208
module_init(connmark_mt_init);

0 commit comments

Comments
 (0)