Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
c539f017 FW |
2 | /* |
3 | * (C) 2013 Astaro GmbH & Co KG | |
c539f017 FW |
4 | */ |
5 | ||
6 | #include <linux/module.h> | |
7 | #include <linux/skbuff.h> | |
8 | #include <net/netfilter/nf_conntrack.h> | |
857ed310 | 9 | #include <net/netfilter/nf_conntrack_ecache.h> |
c539f017 FW |
10 | #include <net/netfilter/nf_conntrack_labels.h> |
11 | #include <linux/netfilter/x_tables.h> | |
12 | ||
13 | MODULE_LICENSE("GPL"); | |
14 | MODULE_AUTHOR("Florian Westphal <fw@strlen.de>"); | |
1de6f334 | 15 | MODULE_DESCRIPTION("Xtables: add/match connection tracking labels"); |
c539f017 FW |
16 | MODULE_ALIAS("ipt_connlabel"); |
17 | MODULE_ALIAS("ip6t_connlabel"); | |
18 | ||
19 | static bool | |
20 | connlabel_mt(const struct sk_buff *skb, struct xt_action_param *par) | |
21 | { | |
22 | const struct xt_connlabel_mtinfo *info = par->matchinfo; | |
23 | enum ip_conntrack_info ctinfo; | |
857ed310 | 24 | struct nf_conn_labels *labels; |
c539f017 FW |
25 | struct nf_conn *ct; |
26 | bool invert = info->options & XT_CONNLABEL_OP_INVERT; | |
27 | ||
28 | ct = nf_ct_get(skb, &ctinfo); | |
ab8bc7ed | 29 | if (ct == NULL) |
c539f017 FW |
30 | return invert; |
31 | ||
857ed310 FW |
32 | labels = nf_ct_labels_find(ct); |
33 | if (!labels) | |
34 | return invert; | |
35 | ||
36 | if (test_bit(info->bit, labels->bits)) | |
37 | return !invert; | |
38 | ||
39 | if (info->options & XT_CONNLABEL_OP_SET) { | |
40 | if (!test_and_set_bit(info->bit, labels->bits)) | |
41 | nf_conntrack_event_cache(IPCT_LABEL, ct); | |
42 | ||
43 | return !invert; | |
44 | } | |
c539f017 | 45 | |
857ed310 | 46 | return invert; |
c539f017 FW |
47 | } |
48 | ||
49 | static int connlabel_mt_check(const struct xt_mtchk_param *par) | |
50 | { | |
51 | const int options = XT_CONNLABEL_OP_INVERT | | |
52 | XT_CONNLABEL_OP_SET; | |
53 | struct xt_connlabel_mtinfo *info = par->matchinfo; | |
54 | int ret; | |
c539f017 FW |
55 | |
56 | if (info->options & ~options) { | |
b2606644 FW |
57 | pr_info_ratelimited("Unknown options in mask %x\n", |
58 | info->options); | |
c539f017 FW |
59 | return -EINVAL; |
60 | } | |
61 | ||
ecb2421b | 62 | ret = nf_ct_netns_get(par->net, par->family); |
c539f017 | 63 | if (ret < 0) { |
b2606644 FW |
64 | pr_info_ratelimited("cannot load conntrack support for proto=%u\n", |
65 | par->family); | |
c539f017 FW |
66 | return ret; |
67 | } | |
68 | ||
adff6c65 | 69 | ret = nf_connlabels_get(par->net, info->bit); |
86ca02e7 | 70 | if (ret < 0) |
ecb2421b | 71 | nf_ct_netns_put(par->net, par->family); |
c539f017 FW |
72 | return ret; |
73 | } | |
74 | ||
75 | static void connlabel_mt_destroy(const struct xt_mtdtor_param *par) | |
76 | { | |
86ca02e7 | 77 | nf_connlabels_put(par->net); |
ecb2421b | 78 | nf_ct_netns_put(par->net, par->family); |
c539f017 FW |
79 | } |
80 | ||
81 | static struct xt_match connlabels_mt_reg __read_mostly = { | |
82 | .name = "connlabel", | |
83 | .family = NFPROTO_UNSPEC, | |
84 | .checkentry = connlabel_mt_check, | |
85 | .match = connlabel_mt, | |
86 | .matchsize = sizeof(struct xt_connlabel_mtinfo), | |
87 | .destroy = connlabel_mt_destroy, | |
88 | .me = THIS_MODULE, | |
89 | }; | |
90 | ||
91 | static int __init connlabel_mt_init(void) | |
92 | { | |
93 | return xt_register_match(&connlabels_mt_reg); | |
94 | } | |
95 | ||
96 | static void __exit connlabel_mt_exit(void) | |
97 | { | |
98 | xt_unregister_match(&connlabels_mt_reg); | |
99 | } | |
100 | ||
101 | module_init(connlabel_mt_init); | |
102 | module_exit(connlabel_mt_exit); |