Skip to content

Commit 01555e7

Browse files
Harout Hedeshianummakynes
authored andcommitted
netfilter: xt_socket: add XT_SOCKET_RESTORESKMARK flag
xt_socket is useful for matching sockets with IP_TRANSPARENT and taking some action on the matching packets. However, it lacks the ability to match only a small subset of transparent sockets. Suppose there are 2 applications, each with its own set of transparent sockets. The first application wants all matching packets dropped, while the second application wants them forwarded somewhere else. Add the ability to retore the skb->mark from the sk_mark. The mark is only restored if a matching socket is found and the transparent / nowildcard conditions are satisfied. Now the 2 hypothetical applications can differentiate their sockets based on a mark value set with SO_MARK. iptables -t mangle -I PREROUTING -m socket --transparent \ --restore-skmark -j action iptables -t mangle -A action -m mark --mark 10 -j action2 iptables -t mangle -A action -m mark --mark 11 -j action3 Signed-off-by: Harout Hedeshian <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent ef493bd commit 01555e7

File tree

2 files changed

+61
-6
lines changed

2 files changed

+61
-6
lines changed

include/uapi/linux/netfilter/xt_socket.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
enum {
77
XT_SOCKET_TRANSPARENT = 1 << 0,
88
XT_SOCKET_NOWILDCARD = 1 << 1,
9+
XT_SOCKET_RESTORESKMARK = 1 << 2,
910
};
1011

1112
struct xt_socket_mtinfo1 {
@@ -18,4 +19,11 @@ struct xt_socket_mtinfo2 {
1819
};
1920
#define XT_SOCKET_FLAGS_V2 (XT_SOCKET_TRANSPARENT | XT_SOCKET_NOWILDCARD)
2021

22+
struct xt_socket_mtinfo3 {
23+
__u8 flags;
24+
};
25+
#define XT_SOCKET_FLAGS_V3 (XT_SOCKET_TRANSPARENT \
26+
| XT_SOCKET_NOWILDCARD \
27+
| XT_SOCKET_RESTORESKMARK)
28+
2129
#endif /* _XT_SOCKET_H */

net/netfilter/xt_socket.c

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ static bool
205205
socket_match(const struct sk_buff *skb, struct xt_action_param *par,
206206
const struct xt_socket_mtinfo1 *info)
207207
{
208+
struct sk_buff *pskb = (struct sk_buff *)skb;
208209
struct sock *sk = skb->sk;
209210

210211
if (!sk)
@@ -226,6 +227,10 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
226227
if (info->flags & XT_SOCKET_TRANSPARENT)
227228
transparent = xt_socket_sk_is_transparent(sk);
228229

230+
if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard &&
231+
transparent)
232+
pskb->mark = sk->sk_mark;
233+
229234
if (sk != skb->sk)
230235
sock_gen_put(sk);
231236

@@ -247,7 +252,7 @@ socket_mt4_v0(const struct sk_buff *skb, struct xt_action_param *par)
247252
}
248253

249254
static bool
250-
socket_mt4_v1_v2(const struct sk_buff *skb, struct xt_action_param *par)
255+
socket_mt4_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par)
251256
{
252257
return socket_match(skb, par, par->matchinfo);
253258
}
@@ -371,9 +376,10 @@ static struct sock *xt_socket_lookup_slow_v6(const struct sk_buff *skb,
371376
}
372377

373378
static bool
374-
socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par)
379+
socket_mt6_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par)
375380
{
376381
const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo;
382+
struct sk_buff *pskb = (struct sk_buff *)skb;
377383
struct sock *sk = skb->sk;
378384

379385
if (!sk)
@@ -395,6 +401,10 @@ socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par)
395401
if (info->flags & XT_SOCKET_TRANSPARENT)
396402
transparent = xt_socket_sk_is_transparent(sk);
397403

404+
if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard &&
405+
transparent)
406+
pskb->mark = sk->sk_mark;
407+
398408
if (sk != skb->sk)
399409
sock_gen_put(sk);
400410

@@ -428,6 +438,19 @@ static int socket_mt_v2_check(const struct xt_mtchk_param *par)
428438
return 0;
429439
}
430440

441+
static int socket_mt_v3_check(const struct xt_mtchk_param *par)
442+
{
443+
const struct xt_socket_mtinfo3 *info =
444+
(struct xt_socket_mtinfo3 *)par->matchinfo;
445+
446+
if (info->flags & ~XT_SOCKET_FLAGS_V3) {
447+
pr_info("unknown flags 0x%x\n",
448+
info->flags & ~XT_SOCKET_FLAGS_V3);
449+
return -EINVAL;
450+
}
451+
return 0;
452+
}
453+
431454
static struct xt_match socket_mt_reg[] __read_mostly = {
432455
{
433456
.name = "socket",
@@ -442,7 +465,7 @@ static struct xt_match socket_mt_reg[] __read_mostly = {
442465
.name = "socket",
443466
.revision = 1,
444467
.family = NFPROTO_IPV4,
445-
.match = socket_mt4_v1_v2,
468+
.match = socket_mt4_v1_v2_v3,
446469
.checkentry = socket_mt_v1_check,
447470
.matchsize = sizeof(struct xt_socket_mtinfo1),
448471
.hooks = (1 << NF_INET_PRE_ROUTING) |
@@ -454,7 +477,7 @@ static struct xt_match socket_mt_reg[] __read_mostly = {
454477
.name = "socket",
455478
.revision = 1,
456479
.family = NFPROTO_IPV6,
457-
.match = socket_mt6_v1_v2,
480+
.match = socket_mt6_v1_v2_v3,
458481
.checkentry = socket_mt_v1_check,
459482
.matchsize = sizeof(struct xt_socket_mtinfo1),
460483
.hooks = (1 << NF_INET_PRE_ROUTING) |
@@ -466,7 +489,7 @@ static struct xt_match socket_mt_reg[] __read_mostly = {
466489
.name = "socket",
467490
.revision = 2,
468491
.family = NFPROTO_IPV4,
469-
.match = socket_mt4_v1_v2,
492+
.match = socket_mt4_v1_v2_v3,
470493
.checkentry = socket_mt_v2_check,
471494
.matchsize = sizeof(struct xt_socket_mtinfo1),
472495
.hooks = (1 << NF_INET_PRE_ROUTING) |
@@ -478,13 +501,37 @@ static struct xt_match socket_mt_reg[] __read_mostly = {
478501
.name = "socket",
479502
.revision = 2,
480503
.family = NFPROTO_IPV6,
481-
.match = socket_mt6_v1_v2,
504+
.match = socket_mt6_v1_v2_v3,
482505
.checkentry = socket_mt_v2_check,
483506
.matchsize = sizeof(struct xt_socket_mtinfo1),
484507
.hooks = (1 << NF_INET_PRE_ROUTING) |
485508
(1 << NF_INET_LOCAL_IN),
486509
.me = THIS_MODULE,
487510
},
511+
#endif
512+
{
513+
.name = "socket",
514+
.revision = 3,
515+
.family = NFPROTO_IPV4,
516+
.match = socket_mt4_v1_v2_v3,
517+
.checkentry = socket_mt_v3_check,
518+
.matchsize = sizeof(struct xt_socket_mtinfo1),
519+
.hooks = (1 << NF_INET_PRE_ROUTING) |
520+
(1 << NF_INET_LOCAL_IN),
521+
.me = THIS_MODULE,
522+
},
523+
#ifdef XT_SOCKET_HAVE_IPV6
524+
{
525+
.name = "socket",
526+
.revision = 3,
527+
.family = NFPROTO_IPV6,
528+
.match = socket_mt6_v1_v2_v3,
529+
.checkentry = socket_mt_v3_check,
530+
.matchsize = sizeof(struct xt_socket_mtinfo1),
531+
.hooks = (1 << NF_INET_PRE_ROUTING) |
532+
(1 << NF_INET_LOCAL_IN),
533+
.me = THIS_MODULE,
534+
},
488535
#endif
489536
};
490537

0 commit comments

Comments
 (0)