1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* iptables module to match on related connections */ |
3 | /* |
4 | * (C) 2001 Martin Josefsson <gandalf@wlug.westbo.se> |
5 | */ |
6 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
7 | #include <linux/module.h> |
8 | #include <linux/skbuff.h> |
9 | #include <linux/netfilter.h> |
10 | #include <net/netfilter/nf_conntrack.h> |
11 | #include <net/netfilter/nf_conntrack_core.h> |
12 | #include <net/netfilter/nf_conntrack_helper.h> |
13 | #include <linux/netfilter/x_tables.h> |
14 | #include <linux/netfilter/xt_helper.h> |
15 | |
16 | MODULE_LICENSE("GPL" ); |
17 | MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>" ); |
18 | MODULE_DESCRIPTION("Xtables: Related connection matching" ); |
19 | MODULE_ALIAS("ipt_helper" ); |
20 | MODULE_ALIAS("ip6t_helper" ); |
21 | |
22 | |
23 | static bool |
24 | helper_mt(const struct sk_buff *skb, struct xt_action_param *par) |
25 | { |
26 | const struct xt_helper_info *info = par->matchinfo; |
27 | const struct nf_conn *ct; |
28 | const struct nf_conn_help *master_help; |
29 | const struct nf_conntrack_helper *helper; |
30 | enum ip_conntrack_info ctinfo; |
31 | bool ret = info->invert; |
32 | |
33 | ct = nf_ct_get(skb, ctinfo: &ctinfo); |
34 | if (!ct || !ct->master) |
35 | return ret; |
36 | |
37 | master_help = nfct_help(ct: ct->master); |
38 | if (!master_help) |
39 | return ret; |
40 | |
41 | /* rcu_read_lock()ed by nf_hook_thresh */ |
42 | helper = rcu_dereference(master_help->helper); |
43 | if (!helper) |
44 | return ret; |
45 | |
46 | if (info->name[0] == '\0') |
47 | ret = !ret; |
48 | else |
49 | ret ^= !strncmp(helper->name, info->name, |
50 | strlen(helper->name)); |
51 | return ret; |
52 | } |
53 | |
54 | static int helper_mt_check(const struct xt_mtchk_param *par) |
55 | { |
56 | struct xt_helper_info *info = par->matchinfo; |
57 | int ret; |
58 | |
59 | ret = nf_ct_netns_get(net: par->net, nfproto: par->family); |
60 | if (ret < 0) { |
61 | pr_info_ratelimited("cannot load conntrack support for proto=%u\n" , |
62 | par->family); |
63 | return ret; |
64 | } |
65 | info->name[sizeof(info->name) - 1] = '\0'; |
66 | return 0; |
67 | } |
68 | |
69 | static void helper_mt_destroy(const struct xt_mtdtor_param *par) |
70 | { |
71 | nf_ct_netns_put(net: par->net, nfproto: par->family); |
72 | } |
73 | |
74 | static struct xt_match helper_mt_reg __read_mostly = { |
75 | .name = "helper" , |
76 | .revision = 0, |
77 | .family = NFPROTO_UNSPEC, |
78 | .checkentry = helper_mt_check, |
79 | .match = helper_mt, |
80 | .destroy = helper_mt_destroy, |
81 | .matchsize = sizeof(struct xt_helper_info), |
82 | .me = THIS_MODULE, |
83 | }; |
84 | |
85 | static int __init helper_mt_init(void) |
86 | { |
87 | return xt_register_match(target: &helper_mt_reg); |
88 | } |
89 | |
90 | static void __exit helper_mt_exit(void) |
91 | { |
92 | xt_unregister_match(target: &helper_mt_reg); |
93 | } |
94 | |
95 | module_init(helper_mt_init); |
96 | module_exit(helper_mt_exit); |
97 | |