xt_connlabel.c (2515B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * (C) 2013 Astaro GmbH & Co KG 4 */ 5 6#include <linux/module.h> 7#include <linux/skbuff.h> 8#include <net/netfilter/nf_conntrack.h> 9#include <net/netfilter/nf_conntrack_ecache.h> 10#include <net/netfilter/nf_conntrack_labels.h> 11#include <linux/netfilter/x_tables.h> 12 13MODULE_LICENSE("GPL"); 14MODULE_AUTHOR("Florian Westphal <fw@strlen.de>"); 15MODULE_DESCRIPTION("Xtables: add/match connection tracking labels"); 16MODULE_ALIAS("ipt_connlabel"); 17MODULE_ALIAS("ip6t_connlabel"); 18 19static bool 20connlabel_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; 24 struct nf_conn_labels *labels; 25 struct nf_conn *ct; 26 bool invert = info->options & XT_CONNLABEL_OP_INVERT; 27 28 ct = nf_ct_get(skb, &ctinfo); 29 if (ct == NULL) 30 return invert; 31 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 } 45 46 return invert; 47} 48 49static 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; 55 56 if (info->options & ~options) { 57 pr_info_ratelimited("Unknown options in mask %x\n", 58 info->options); 59 return -EINVAL; 60 } 61 62 ret = nf_ct_netns_get(par->net, par->family); 63 if (ret < 0) { 64 pr_info_ratelimited("cannot load conntrack support for proto=%u\n", 65 par->family); 66 return ret; 67 } 68 69 ret = nf_connlabels_get(par->net, info->bit); 70 if (ret < 0) 71 nf_ct_netns_put(par->net, par->family); 72 return ret; 73} 74 75static void connlabel_mt_destroy(const struct xt_mtdtor_param *par) 76{ 77 nf_connlabels_put(par->net); 78 nf_ct_netns_put(par->net, par->family); 79} 80 81static 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 91static int __init connlabel_mt_init(void) 92{ 93 return xt_register_match(&connlabels_mt_reg); 94} 95 96static void __exit connlabel_mt_exit(void) 97{ 98 xt_unregister_match(&connlabels_mt_reg); 99} 100 101module_init(connlabel_mt_init); 102module_exit(connlabel_mt_exit);