xt_mark.c revision 17b0d7ef658583842da75eebf8001dc617f0b52e
1/*
2 *	xt_mark - Netfilter module to match NFMARK value
3 *
4 *	(C) 1999-2001 Marc Boucher <marc@mbsi.ca>
5 *	Copyright © CC Computer Consultants GmbH, 2007 - 2008
6 *	Jan Engelhardt <jengelh@computergmbh.de>
7 *
8 *	This program is free software; you can redistribute it and/or modify
9 *	it under the terms of the GNU General Public License version 2 as
10 *	published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/skbuff.h>
15
16#include <linux/netfilter/xt_mark.h>
17#include <linux/netfilter/x_tables.h>
18
19MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
21MODULE_DESCRIPTION("iptables mark matching module");
22MODULE_ALIAS("ipt_mark");
23MODULE_ALIAS("ip6t_mark");
24
25static bool
26mark_mt_v0(const struct sk_buff *skb, const struct net_device *in,
27           const struct net_device *out, const struct xt_match *match,
28           const void *matchinfo, int offset, unsigned int protoff,
29           bool *hotdrop)
30{
31	const struct xt_mark_info *info = matchinfo;
32
33	return ((skb->mark & info->mask) == info->mark) ^ info->invert;
34}
35
36static bool
37mark_mt(const struct sk_buff *skb, const struct net_device *in,
38        const struct net_device *out, const struct xt_match *match,
39        const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
40{
41	const struct xt_mark_mtinfo1 *info = matchinfo;
42
43	return ((skb->mark & info->mask) == info->mark) ^ info->invert;
44}
45
46static bool
47mark_mt_check_v0(const char *tablename, const void *entry,
48                 const struct xt_match *match, void *matchinfo,
49                 unsigned int hook_mask)
50{
51	const struct xt_mark_info *minfo = matchinfo;
52
53	if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) {
54		printk(KERN_WARNING "mark: only supports 32bit mark\n");
55		return false;
56	}
57	return true;
58}
59
60#ifdef CONFIG_COMPAT
61struct compat_xt_mark_info {
62	compat_ulong_t	mark, mask;
63	u_int8_t	invert;
64	u_int8_t	__pad1;
65	u_int16_t	__pad2;
66};
67
68static void mark_mt_compat_from_user_v0(void *dst, void *src)
69{
70	const struct compat_xt_mark_info *cm = src;
71	struct xt_mark_info m = {
72		.mark	= cm->mark,
73		.mask	= cm->mask,
74		.invert	= cm->invert,
75	};
76	memcpy(dst, &m, sizeof(m));
77}
78
79static int mark_mt_compat_to_user_v0(void __user *dst, void *src)
80{
81	const struct xt_mark_info *m = src;
82	struct compat_xt_mark_info cm = {
83		.mark	= m->mark,
84		.mask	= m->mask,
85		.invert	= m->invert,
86	};
87	return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
88}
89#endif /* CONFIG_COMPAT */
90
91static struct xt_match mark_mt_reg[] __read_mostly = {
92	{
93		.name		= "mark",
94		.revision	= 0,
95		.family		= AF_INET,
96		.checkentry	= mark_mt_check_v0,
97		.match		= mark_mt_v0,
98		.matchsize	= sizeof(struct xt_mark_info),
99#ifdef CONFIG_COMPAT
100		.compatsize	= sizeof(struct compat_xt_mark_info),
101		.compat_from_user = mark_mt_compat_from_user_v0,
102		.compat_to_user	= mark_mt_compat_to_user_v0,
103#endif
104		.me		= THIS_MODULE,
105	},
106	{
107		.name		= "mark",
108		.revision	= 0,
109		.family		= AF_INET6,
110		.checkentry	= mark_mt_check_v0,
111		.match		= mark_mt_v0,
112		.matchsize	= sizeof(struct xt_mark_info),
113#ifdef CONFIG_COMPAT
114		.compatsize	= sizeof(struct compat_xt_mark_info),
115		.compat_from_user = mark_mt_compat_from_user_v0,
116		.compat_to_user	= mark_mt_compat_to_user_v0,
117#endif
118		.me		= THIS_MODULE,
119	},
120	{
121		.name           = "mark",
122		.revision       = 1,
123		.family         = AF_INET,
124		.match          = mark_mt,
125		.matchsize      = sizeof(struct xt_mark_mtinfo1),
126		.me             = THIS_MODULE,
127	},
128	{
129		.name           = "mark",
130		.revision       = 1,
131		.family         = AF_INET6,
132		.match          = mark_mt,
133		.matchsize      = sizeof(struct xt_mark_mtinfo1),
134		.me             = THIS_MODULE,
135	},
136};
137
138static int __init mark_mt_init(void)
139{
140	return xt_register_matches(mark_mt_reg, ARRAY_SIZE(mark_mt_reg));
141}
142
143static void __exit mark_mt_exit(void)
144{
145	xt_unregister_matches(mark_mt_reg, ARRAY_SIZE(mark_mt_reg));
146}
147
148module_init(mark_mt_init);
149module_exit(mark_mt_exit);
150