-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
netfilter: add connlabel conntrack extension
similar to connmarks, except labels are bit-based; i.e. all labels may be attached to a flow at the same time. Up to 128 labels are supported. Supporting more labels is possible, but requires increasing the ct offset delta from u8 to u16 type due to increased extension sizes. Mapping of bit-identifier to label name is done in userspace. The extension is enabled at run-time once "-m connlabel" netfilter rules are added. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
- Loading branch information
Florian Westphal
authored and
Pablo Neira Ayuso
committed
Jan 17, 2013
1 parent
7266507
commit c539f01
Showing
10 changed files
with
281 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
#include <linux/types.h> | ||
#include <net/net_namespace.h> | ||
#include <linux/netfilter/nf_conntrack_common.h> | ||
#include <linux/netfilter/nf_conntrack_tuple_common.h> | ||
#include <net/netfilter/nf_conntrack.h> | ||
#include <net/netfilter/nf_conntrack_extend.h> | ||
|
||
#include <uapi/linux/netfilter/xt_connlabel.h> | ||
|
||
struct nf_conn_labels { | ||
u8 words; | ||
unsigned long bits[]; | ||
}; | ||
|
||
static inline struct nf_conn_labels *nf_ct_labels_find(const struct nf_conn *ct) | ||
{ | ||
#ifdef CONFIG_NF_CONNTRACK_LABELS | ||
return nf_ct_ext_find(ct, NF_CT_EXT_LABELS); | ||
#else | ||
return NULL; | ||
#endif | ||
} | ||
|
||
static inline struct nf_conn_labels *nf_ct_labels_ext_add(struct nf_conn *ct) | ||
{ | ||
#ifdef CONFIG_NF_CONNTRACK_LABELS | ||
struct nf_conn_labels *cl_ext; | ||
struct net *net = nf_ct_net(ct); | ||
u8 words; | ||
|
||
words = ACCESS_ONCE(net->ct.label_words); | ||
if (words == 0 || WARN_ON_ONCE(words > 8)) | ||
return NULL; | ||
|
||
cl_ext = nf_ct_ext_add_length(ct, NF_CT_EXT_LABELS, | ||
words * sizeof(long), GFP_ATOMIC); | ||
if (cl_ext != NULL) | ||
cl_ext->words = words; | ||
|
||
return cl_ext; | ||
#else | ||
return NULL; | ||
#endif | ||
} | ||
|
||
bool nf_connlabel_match(const struct nf_conn *ct, u16 bit); | ||
int nf_connlabel_set(struct nf_conn *ct, u16 bit); | ||
|
||
#ifdef CONFIG_NF_CONNTRACK_LABELS | ||
int nf_conntrack_labels_init(struct net *net); | ||
void nf_conntrack_labels_fini(struct net *net); | ||
#else | ||
static inline int nf_conntrack_labels_init(struct net *n) { return 0; } | ||
static inline void nf_conntrack_labels_fini(struct net *net) {} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#include <linux/types.h> | ||
|
||
#define XT_CONNLABEL_MAXBIT 127 | ||
enum xt_connlabel_mtopts { | ||
XT_CONNLABEL_OP_INVERT = 1 << 0, | ||
XT_CONNLABEL_OP_SET = 1 << 1, | ||
}; | ||
|
||
struct xt_connlabel_mtinfo { | ||
__u16 bit; | ||
__u16 options; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
* test/set flag bits stored in conntrack extension area. | ||
* | ||
* (C) 2013 Astaro GmbH & Co KG | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
*/ | ||
|
||
#include <linux/ctype.h> | ||
#include <linux/export.h> | ||
#include <linux/jhash.h> | ||
#include <linux/spinlock.h> | ||
#include <linux/types.h> | ||
#include <linux/slab.h> | ||
|
||
#include <net/netfilter/nf_conntrack_ecache.h> | ||
#include <net/netfilter/nf_conntrack_labels.h> | ||
|
||
static unsigned int label_bits(const struct nf_conn_labels *l) | ||
{ | ||
unsigned int longs = l->words; | ||
return longs * BITS_PER_LONG; | ||
} | ||
|
||
bool nf_connlabel_match(const struct nf_conn *ct, u16 bit) | ||
{ | ||
struct nf_conn_labels *labels = nf_ct_labels_find(ct); | ||
|
||
if (!labels) | ||
return false; | ||
|
||
return bit < label_bits(labels) && test_bit(bit, labels->bits); | ||
} | ||
EXPORT_SYMBOL_GPL(nf_connlabel_match); | ||
|
||
int nf_connlabel_set(struct nf_conn *ct, u16 bit) | ||
{ | ||
struct nf_conn_labels *labels = nf_ct_labels_find(ct); | ||
|
||
if (!labels || bit >= label_bits(labels)) | ||
return -ENOSPC; | ||
|
||
if (test_bit(bit, labels->bits)) | ||
return 0; | ||
|
||
if (test_and_set_bit(bit, labels->bits)) | ||
return 0; | ||
|
||
return 0; | ||
} | ||
EXPORT_SYMBOL_GPL(nf_connlabel_set); | ||
|
||
static struct nf_ct_ext_type labels_extend __read_mostly = { | ||
.len = sizeof(struct nf_conn_labels), | ||
.align = __alignof__(struct nf_conn_labels), | ||
.id = NF_CT_EXT_LABELS, | ||
}; | ||
|
||
int nf_conntrack_labels_init(struct net *net) | ||
{ | ||
if (net_eq(net, &init_net)) | ||
return nf_ct_extend_register(&labels_extend); | ||
return 0; | ||
} | ||
|
||
void nf_conntrack_labels_fini(struct net *net) | ||
{ | ||
if (net_eq(net, &init_net)) | ||
nf_ct_extend_unregister(&labels_extend); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/* | ||
* (C) 2013 Astaro GmbH & Co KG | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
*/ | ||
|
||
#include <linux/module.h> | ||
#include <linux/skbuff.h> | ||
#include <net/netfilter/nf_conntrack.h> | ||
#include <net/netfilter/nf_conntrack_labels.h> | ||
#include <linux/netfilter/x_tables.h> | ||
|
||
MODULE_LICENSE("GPL"); | ||
MODULE_AUTHOR("Florian Westphal <fw@strlen.de>"); | ||
MODULE_DESCRIPTION("Xtables: add/match connection trackling labels"); | ||
MODULE_ALIAS("ipt_connlabel"); | ||
MODULE_ALIAS("ip6t_connlabel"); | ||
|
||
static bool | ||
connlabel_mt(const struct sk_buff *skb, struct xt_action_param *par) | ||
{ | ||
const struct xt_connlabel_mtinfo *info = par->matchinfo; | ||
enum ip_conntrack_info ctinfo; | ||
struct nf_conn *ct; | ||
bool invert = info->options & XT_CONNLABEL_OP_INVERT; | ||
|
||
ct = nf_ct_get(skb, &ctinfo); | ||
if (ct == NULL || nf_ct_is_untracked(ct)) | ||
return invert; | ||
|
||
if (info->options & XT_CONNLABEL_OP_SET) | ||
return (nf_connlabel_set(ct, info->bit) == 0) ^ invert; | ||
|
||
return nf_connlabel_match(ct, info->bit) ^ invert; | ||
} | ||
|
||
static int connlabel_mt_check(const struct xt_mtchk_param *par) | ||
{ | ||
const int options = XT_CONNLABEL_OP_INVERT | | ||
XT_CONNLABEL_OP_SET; | ||
struct xt_connlabel_mtinfo *info = par->matchinfo; | ||
int ret; | ||
size_t words; | ||
|
||
if (info->bit > XT_CONNLABEL_MAXBIT) | ||
return -ERANGE; | ||
|
||
if (info->options & ~options) { | ||
pr_err("Unknown options in mask %x\n", info->options); | ||
return -EINVAL; | ||
} | ||
|
||
ret = nf_ct_l3proto_try_module_get(par->family); | ||
if (ret < 0) { | ||
pr_info("cannot load conntrack support for proto=%u\n", | ||
par->family); | ||
return ret; | ||
} | ||
|
||
par->net->ct.labels_used++; | ||
words = BITS_TO_LONGS(info->bit+1); | ||
if (words > par->net->ct.label_words) | ||
par->net->ct.label_words = words; | ||
|
||
return ret; | ||
} | ||
|
||
static void connlabel_mt_destroy(const struct xt_mtdtor_param *par) | ||
{ | ||
par->net->ct.labels_used--; | ||
if (par->net->ct.labels_used == 0) | ||
par->net->ct.label_words = 0; | ||
nf_ct_l3proto_module_put(par->family); | ||
} | ||
|
||
static struct xt_match connlabels_mt_reg __read_mostly = { | ||
.name = "connlabel", | ||
.family = NFPROTO_UNSPEC, | ||
.checkentry = connlabel_mt_check, | ||
.match = connlabel_mt, | ||
.matchsize = sizeof(struct xt_connlabel_mtinfo), | ||
.destroy = connlabel_mt_destroy, | ||
.me = THIS_MODULE, | ||
}; | ||
|
||
static int __init connlabel_mt_init(void) | ||
{ | ||
return xt_register_match(&connlabels_mt_reg); | ||
} | ||
|
||
static void __exit connlabel_mt_exit(void) | ||
{ | ||
xt_unregister_match(&connlabels_mt_reg); | ||
} | ||
|
||
module_init(connlabel_mt_init); | ||
module_exit(connlabel_mt_exit); |