Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * (C) 2013 Astaro GmbH & Co KG
0004  */
0005 
0006 #include <linux/module.h>
0007 #include <linux/skbuff.h>
0008 #include <net/netfilter/nf_conntrack.h>
0009 #include <net/netfilter/nf_conntrack_ecache.h>
0010 #include <net/netfilter/nf_conntrack_labels.h>
0011 #include <linux/netfilter/x_tables.h>
0012 
0013 MODULE_LICENSE("GPL");
0014 MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
0015 MODULE_DESCRIPTION("Xtables: add/match connection tracking labels");
0016 MODULE_ALIAS("ipt_connlabel");
0017 MODULE_ALIAS("ip6t_connlabel");
0018 
0019 static bool
0020 connlabel_mt(const struct sk_buff *skb, struct xt_action_param *par)
0021 {
0022     const struct xt_connlabel_mtinfo *info = par->matchinfo;
0023     enum ip_conntrack_info ctinfo;
0024     struct nf_conn_labels *labels;
0025     struct nf_conn *ct;
0026     bool invert = info->options & XT_CONNLABEL_OP_INVERT;
0027 
0028     ct = nf_ct_get(skb, &ctinfo);
0029     if (ct == NULL)
0030         return invert;
0031 
0032     labels = nf_ct_labels_find(ct);
0033     if (!labels)
0034         return invert;
0035 
0036     if (test_bit(info->bit, labels->bits))
0037         return !invert;
0038 
0039     if (info->options & XT_CONNLABEL_OP_SET) {
0040         if (!test_and_set_bit(info->bit, labels->bits))
0041             nf_conntrack_event_cache(IPCT_LABEL, ct);
0042 
0043         return !invert;
0044     }
0045 
0046     return invert;
0047 }
0048 
0049 static int connlabel_mt_check(const struct xt_mtchk_param *par)
0050 {
0051     const int options = XT_CONNLABEL_OP_INVERT |
0052                 XT_CONNLABEL_OP_SET;
0053     struct xt_connlabel_mtinfo *info = par->matchinfo;
0054     int ret;
0055 
0056     if (info->options & ~options) {
0057         pr_info_ratelimited("Unknown options in mask %x\n",
0058                     info->options);
0059         return -EINVAL;
0060     }
0061 
0062     ret = nf_ct_netns_get(par->net, par->family);
0063     if (ret < 0) {
0064         pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
0065                     par->family);
0066         return ret;
0067     }
0068 
0069     ret = nf_connlabels_get(par->net, info->bit);
0070     if (ret < 0)
0071         nf_ct_netns_put(par->net, par->family);
0072     return ret;
0073 }
0074 
0075 static void connlabel_mt_destroy(const struct xt_mtdtor_param *par)
0076 {
0077     nf_connlabels_put(par->net);
0078     nf_ct_netns_put(par->net, par->family);
0079 }
0080 
0081 static struct xt_match connlabels_mt_reg __read_mostly = {
0082     .name           = "connlabel",
0083     .family         = NFPROTO_UNSPEC,
0084     .checkentry     = connlabel_mt_check,
0085     .match          = connlabel_mt,
0086     .matchsize      = sizeof(struct xt_connlabel_mtinfo),
0087     .destroy        = connlabel_mt_destroy,
0088     .me             = THIS_MODULE,
0089 };
0090 
0091 static int __init connlabel_mt_init(void)
0092 {
0093     return xt_register_match(&connlabels_mt_reg);
0094 }
0095 
0096 static void __exit connlabel_mt_exit(void)
0097 {
0098     xt_unregister_match(&connlabels_mt_reg);
0099 }
0100 
0101 module_init(connlabel_mt_init);
0102 module_exit(connlabel_mt_exit);