Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
0004  */
0005 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0006 #include <linux/module.h>
0007 #include <linux/gfp.h>
0008 #include <linux/skbuff.h>
0009 #include <linux/netfilter_ipv4/ip_tables.h>
0010 #include <linux/netfilter_ipv6/ip6_tables.h>
0011 #include <linux/netfilter/x_tables.h>
0012 #include <linux/netfilter/xt_CT.h>
0013 #include <net/netfilter/nf_conntrack.h>
0014 #include <net/netfilter/nf_conntrack_l4proto.h>
0015 #include <net/netfilter/nf_conntrack_helper.h>
0016 #include <net/netfilter/nf_conntrack_ecache.h>
0017 #include <net/netfilter/nf_conntrack_timeout.h>
0018 #include <net/netfilter/nf_conntrack_zones.h>
0019 
0020 static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct)
0021 {
0022     /* Previously seen (loopback)? Ignore. */
0023     if (skb->_nfct != 0)
0024         return XT_CONTINUE;
0025 
0026     if (ct) {
0027         refcount_inc(&ct->ct_general.use);
0028         nf_ct_set(skb, ct, IP_CT_NEW);
0029     } else {
0030         nf_ct_set(skb, ct, IP_CT_UNTRACKED);
0031     }
0032 
0033     return XT_CONTINUE;
0034 }
0035 
0036 static unsigned int xt_ct_target_v0(struct sk_buff *skb,
0037                     const struct xt_action_param *par)
0038 {
0039     const struct xt_ct_target_info *info = par->targinfo;
0040     struct nf_conn *ct = info->ct;
0041 
0042     return xt_ct_target(skb, ct);
0043 }
0044 
0045 static unsigned int xt_ct_target_v1(struct sk_buff *skb,
0046                     const struct xt_action_param *par)
0047 {
0048     const struct xt_ct_target_info_v1 *info = par->targinfo;
0049     struct nf_conn *ct = info->ct;
0050 
0051     return xt_ct_target(skb, ct);
0052 }
0053 
0054 static u8 xt_ct_find_proto(const struct xt_tgchk_param *par)
0055 {
0056     if (par->family == NFPROTO_IPV4) {
0057         const struct ipt_entry *e = par->entryinfo;
0058 
0059         if (e->ip.invflags & IPT_INV_PROTO)
0060             return 0;
0061         return e->ip.proto;
0062     } else if (par->family == NFPROTO_IPV6) {
0063         const struct ip6t_entry *e = par->entryinfo;
0064 
0065         if (e->ipv6.invflags & IP6T_INV_PROTO)
0066             return 0;
0067         return e->ipv6.proto;
0068     } else
0069         return 0;
0070 }
0071 
0072 static int
0073 xt_ct_set_helper(struct nf_conn *ct, const char *helper_name,
0074          const struct xt_tgchk_param *par)
0075 {
0076     struct nf_conntrack_helper *helper;
0077     struct nf_conn_help *help;
0078     u8 proto;
0079 
0080     proto = xt_ct_find_proto(par);
0081     if (!proto) {
0082         pr_info_ratelimited("You must specify a L4 protocol and not use inversions on it\n");
0083         return -ENOENT;
0084     }
0085 
0086     helper = nf_conntrack_helper_try_module_get(helper_name, par->family,
0087                             proto);
0088     if (helper == NULL) {
0089         pr_info_ratelimited("No such helper \"%s\"\n", helper_name);
0090         return -ENOENT;
0091     }
0092 
0093     help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
0094     if (help == NULL) {
0095         nf_conntrack_helper_put(helper);
0096         return -ENOMEM;
0097     }
0098 
0099     rcu_assign_pointer(help->helper, helper);
0100     return 0;
0101 }
0102 
0103 static int
0104 xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
0105           const char *timeout_name)
0106 {
0107 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
0108     const struct nf_conntrack_l4proto *l4proto;
0109     u8 proto;
0110 
0111     proto = xt_ct_find_proto(par);
0112     if (!proto) {
0113         pr_info_ratelimited("You must specify a L4 protocol and not "
0114                     "use inversions on it");
0115         return -EINVAL;
0116     }
0117     l4proto = nf_ct_l4proto_find(proto);
0118     return nf_ct_set_timeout(par->net, ct, par->family, l4proto->l4proto,
0119                  timeout_name);
0120 
0121 #else
0122     return -EOPNOTSUPP;
0123 #endif
0124 }
0125 
0126 static u16 xt_ct_flags_to_dir(const struct xt_ct_target_info_v1 *info)
0127 {
0128     switch (info->flags & (XT_CT_ZONE_DIR_ORIG |
0129                    XT_CT_ZONE_DIR_REPL)) {
0130     case XT_CT_ZONE_DIR_ORIG:
0131         return NF_CT_ZONE_DIR_ORIG;
0132     case XT_CT_ZONE_DIR_REPL:
0133         return NF_CT_ZONE_DIR_REPL;
0134     default:
0135         return NF_CT_DEFAULT_ZONE_DIR;
0136     }
0137 }
0138 
0139 static void xt_ct_put_helper(struct nf_conn_help *help)
0140 {
0141     struct nf_conntrack_helper *helper;
0142 
0143     if (!help)
0144         return;
0145 
0146     /* not yet exposed to other cpus, or ruleset
0147      * already detached (post-replacement).
0148      */
0149     helper = rcu_dereference_raw(help->helper);
0150     if (helper)
0151         nf_conntrack_helper_put(helper);
0152 }
0153 
0154 static int xt_ct_tg_check(const struct xt_tgchk_param *par,
0155               struct xt_ct_target_info_v1 *info)
0156 {
0157     struct nf_conntrack_zone zone;
0158     struct nf_conn_help *help;
0159     struct nf_conn *ct;
0160     int ret = -EOPNOTSUPP;
0161 
0162     if (info->flags & XT_CT_NOTRACK) {
0163         ct = NULL;
0164         goto out;
0165     }
0166 
0167 #ifndef CONFIG_NF_CONNTRACK_ZONES
0168     if (info->zone || info->flags & (XT_CT_ZONE_DIR_ORIG |
0169                      XT_CT_ZONE_DIR_REPL |
0170                      XT_CT_ZONE_MARK))
0171         goto err1;
0172 #endif
0173 
0174     ret = nf_ct_netns_get(par->net, par->family);
0175     if (ret < 0)
0176         goto err1;
0177 
0178     memset(&zone, 0, sizeof(zone));
0179     zone.id = info->zone;
0180     zone.dir = xt_ct_flags_to_dir(info);
0181     if (info->flags & XT_CT_ZONE_MARK)
0182         zone.flags |= NF_CT_FLAG_MARK;
0183 
0184     ct = nf_ct_tmpl_alloc(par->net, &zone, GFP_KERNEL);
0185     if (!ct) {
0186         ret = -ENOMEM;
0187         goto err2;
0188     }
0189 
0190     if ((info->ct_events || info->exp_events) &&
0191         !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
0192                   GFP_KERNEL)) {
0193         ret = -EINVAL;
0194         goto err3;
0195     }
0196 
0197     if (info->helper[0]) {
0198         if (strnlen(info->helper, sizeof(info->helper)) == sizeof(info->helper)) {
0199             ret = -ENAMETOOLONG;
0200             goto err3;
0201         }
0202 
0203         ret = xt_ct_set_helper(ct, info->helper, par);
0204         if (ret < 0)
0205             goto err3;
0206     }
0207 
0208     if (info->timeout[0]) {
0209         if (strnlen(info->timeout, sizeof(info->timeout)) == sizeof(info->timeout)) {
0210             ret = -ENAMETOOLONG;
0211             goto err4;
0212         }
0213 
0214         ret = xt_ct_set_timeout(ct, par, info->timeout);
0215         if (ret < 0)
0216             goto err4;
0217     }
0218     __set_bit(IPS_CONFIRMED_BIT, &ct->status);
0219 out:
0220     info->ct = ct;
0221     return 0;
0222 
0223 err4:
0224     help = nfct_help(ct);
0225     xt_ct_put_helper(help);
0226 err3:
0227     nf_ct_tmpl_free(ct);
0228 err2:
0229     nf_ct_netns_put(par->net, par->family);
0230 err1:
0231     return ret;
0232 }
0233 
0234 static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
0235 {
0236     struct xt_ct_target_info *info = par->targinfo;
0237     struct xt_ct_target_info_v1 info_v1 = {
0238         .flags      = info->flags,
0239         .zone       = info->zone,
0240         .ct_events  = info->ct_events,
0241         .exp_events = info->exp_events,
0242     };
0243     int ret;
0244 
0245     if (info->flags & ~XT_CT_NOTRACK)
0246         return -EINVAL;
0247 
0248     memcpy(info_v1.helper, info->helper, sizeof(info->helper));
0249 
0250     ret = xt_ct_tg_check(par, &info_v1);
0251     if (ret < 0)
0252         return ret;
0253 
0254     info->ct = info_v1.ct;
0255 
0256     return ret;
0257 }
0258 
0259 static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
0260 {
0261     struct xt_ct_target_info_v1 *info = par->targinfo;
0262 
0263     if (info->flags & ~XT_CT_NOTRACK)
0264         return -EINVAL;
0265 
0266     return xt_ct_tg_check(par, par->targinfo);
0267 }
0268 
0269 static int xt_ct_tg_check_v2(const struct xt_tgchk_param *par)
0270 {
0271     struct xt_ct_target_info_v1 *info = par->targinfo;
0272 
0273     if (info->flags & ~XT_CT_MASK)
0274         return -EINVAL;
0275 
0276     return xt_ct_tg_check(par, par->targinfo);
0277 }
0278 
0279 static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par,
0280                  struct xt_ct_target_info_v1 *info)
0281 {
0282     struct nf_conn *ct = info->ct;
0283     struct nf_conn_help *help;
0284 
0285     if (ct) {
0286         help = nfct_help(ct);
0287         xt_ct_put_helper(help);
0288 
0289         nf_ct_netns_put(par->net, par->family);
0290 
0291         nf_ct_destroy_timeout(ct);
0292         nf_ct_put(info->ct);
0293     }
0294 }
0295 
0296 static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par)
0297 {
0298     struct xt_ct_target_info *info = par->targinfo;
0299     struct xt_ct_target_info_v1 info_v1 = {
0300         .flags      = info->flags,
0301         .zone       = info->zone,
0302         .ct_events  = info->ct_events,
0303         .exp_events = info->exp_events,
0304         .ct     = info->ct,
0305     };
0306     memcpy(info_v1.helper, info->helper, sizeof(info->helper));
0307 
0308     xt_ct_tg_destroy(par, &info_v1);
0309 }
0310 
0311 static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par)
0312 {
0313     xt_ct_tg_destroy(par, par->targinfo);
0314 }
0315 
0316 static struct xt_target xt_ct_tg_reg[] __read_mostly = {
0317     {
0318         .name       = "CT",
0319         .family     = NFPROTO_UNSPEC,
0320         .targetsize = sizeof(struct xt_ct_target_info),
0321         .usersize   = offsetof(struct xt_ct_target_info, ct),
0322         .checkentry = xt_ct_tg_check_v0,
0323         .destroy    = xt_ct_tg_destroy_v0,
0324         .target     = xt_ct_target_v0,
0325         .table      = "raw",
0326         .me     = THIS_MODULE,
0327     },
0328     {
0329         .name       = "CT",
0330         .family     = NFPROTO_UNSPEC,
0331         .revision   = 1,
0332         .targetsize = sizeof(struct xt_ct_target_info_v1),
0333         .usersize   = offsetof(struct xt_ct_target_info, ct),
0334         .checkentry = xt_ct_tg_check_v1,
0335         .destroy    = xt_ct_tg_destroy_v1,
0336         .target     = xt_ct_target_v1,
0337         .table      = "raw",
0338         .me     = THIS_MODULE,
0339     },
0340     {
0341         .name       = "CT",
0342         .family     = NFPROTO_UNSPEC,
0343         .revision   = 2,
0344         .targetsize = sizeof(struct xt_ct_target_info_v1),
0345         .usersize   = offsetof(struct xt_ct_target_info, ct),
0346         .checkentry = xt_ct_tg_check_v2,
0347         .destroy    = xt_ct_tg_destroy_v1,
0348         .target     = xt_ct_target_v1,
0349         .table      = "raw",
0350         .me     = THIS_MODULE,
0351     },
0352 };
0353 
0354 static unsigned int
0355 notrack_tg(struct sk_buff *skb, const struct xt_action_param *par)
0356 {
0357     /* Previously seen (loopback)? Ignore. */
0358     if (skb->_nfct != 0)
0359         return XT_CONTINUE;
0360 
0361     nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
0362 
0363     return XT_CONTINUE;
0364 }
0365 
0366 static struct xt_target notrack_tg_reg __read_mostly = {
0367     .name       = "NOTRACK",
0368     .revision   = 0,
0369     .family     = NFPROTO_UNSPEC,
0370     .target     = notrack_tg,
0371     .table      = "raw",
0372     .me     = THIS_MODULE,
0373 };
0374 
0375 static int __init xt_ct_tg_init(void)
0376 {
0377     int ret;
0378 
0379     ret = xt_register_target(&notrack_tg_reg);
0380     if (ret < 0)
0381         return ret;
0382 
0383     ret = xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
0384     if (ret < 0) {
0385         xt_unregister_target(&notrack_tg_reg);
0386         return ret;
0387     }
0388     return 0;
0389 }
0390 
0391 static void __exit xt_ct_tg_exit(void)
0392 {
0393     xt_unregister_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
0394     xt_unregister_target(&notrack_tg_reg);
0395 }
0396 
0397 module_init(xt_ct_tg_init);
0398 module_exit(xt_ct_tg_exit);
0399 
0400 MODULE_LICENSE("GPL");
0401 MODULE_DESCRIPTION("Xtables: connection tracking target");
0402 MODULE_ALIAS("ipt_CT");
0403 MODULE_ALIAS("ip6t_CT");
0404 MODULE_ALIAS("ipt_NOTRACK");
0405 MODULE_ALIAS("ip6t_NOTRACK");