blob: 67574bcfb8ac8016e65d211ce6126806a157f229 [file] [log] [blame]
Jan Engelhardte0a812a2008-01-14 23:38:52 -08001/*
2 * xt_MARK - Netfilter module to modify the NFMARK field of an skb
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
Jan Engelhardte0a812a2008-01-14 23:38:52 -08004 * (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.
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 */
12
13#include <linux/module.h>
14#include <linux/skbuff.h>
15#include <linux/ip.h>
16#include <net/checksum.h>
17
Harald Welte2e4e6a12006-01-12 13:30:04 -080018#include <linux/netfilter/x_tables.h>
19#include <linux/netfilter/xt_MARK.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
21MODULE_LICENSE("GPL");
22MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
Jan Engelhardt2ae15b62008-01-14 23:42:28 -080023MODULE_DESCRIPTION("Xtables: packet mark modification");
Harald Welte2e4e6a12006-01-12 13:30:04 -080024MODULE_ALIAS("ipt_MARK");
25MODULE_ALIAS("ip6t_MARK");
Linus Torvalds1da177e2005-04-16 15:20:36 -070026
27static unsigned int
Jan Engelhardt7eb35582008-10-08 11:35:19 +020028mark_tg_v0(struct sk_buff *skb, const struct xt_target_param *par)
Linus Torvalds1da177e2005-04-16 15:20:36 -070029{
Jan Engelhardt7eb35582008-10-08 11:35:19 +020030 const struct xt_mark_target_info *markinfo = par->targinfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
Herbert Xu3db05fe2007-10-15 00:53:15 -070032 skb->mark = markinfo->mark;
Harald Welte2e4e6a12006-01-12 13:30:04 -080033 return XT_CONTINUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070034}
35
36static unsigned int
Jan Engelhardt7eb35582008-10-08 11:35:19 +020037mark_tg_v1(struct sk_buff *skb, const struct xt_target_param *par)
Linus Torvalds1da177e2005-04-16 15:20:36 -070038{
Jan Engelhardt7eb35582008-10-08 11:35:19 +020039 const struct xt_mark_target_info_v1 *markinfo = par->targinfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 int mark = 0;
41
42 switch (markinfo->mode) {
Harald Welte2e4e6a12006-01-12 13:30:04 -080043 case XT_MARK_SET:
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 mark = markinfo->mark;
45 break;
YOSHIFUJI Hideaki601e68e2007-02-12 11:15:49 -080046
Harald Welte2e4e6a12006-01-12 13:30:04 -080047 case XT_MARK_AND:
Herbert Xu3db05fe2007-10-15 00:53:15 -070048 mark = skb->mark & markinfo->mark;
Linus Torvalds1da177e2005-04-16 15:20:36 -070049 break;
YOSHIFUJI Hideaki601e68e2007-02-12 11:15:49 -080050
Harald Welte2e4e6a12006-01-12 13:30:04 -080051 case XT_MARK_OR:
Herbert Xu3db05fe2007-10-15 00:53:15 -070052 mark = skb->mark | markinfo->mark;
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 break;
54 }
55
Herbert Xu3db05fe2007-10-15 00:53:15 -070056 skb->mark = mark;
Harald Welte2e4e6a12006-01-12 13:30:04 -080057 return XT_CONTINUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070058}
59
Jan Engelhardte0a812a2008-01-14 23:38:52 -080060static unsigned int
Jan Engelhardt7eb35582008-10-08 11:35:19 +020061mark_tg(struct sk_buff *skb, const struct xt_target_param *par)
Jan Engelhardte0a812a2008-01-14 23:38:52 -080062{
Jan Engelhardt7eb35582008-10-08 11:35:19 +020063 const struct xt_mark_tginfo2 *info = par->targinfo;
Jan Engelhardte0a812a2008-01-14 23:38:52 -080064
65 skb->mark = (skb->mark & ~info->mask) ^ info->mark;
66 return XT_CONTINUE;
67}
68
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +020069static bool mark_tg_check_v0(const struct xt_tgchk_param *par)
Linus Torvalds1da177e2005-04-16 15:20:36 -070070{
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +020071 const struct xt_mark_target_info *markinfo = par->targinfo;
Harald Weltebf3a46a2005-08-09 19:22:01 -070072
Harald Weltebf3a46a2005-08-09 19:22:01 -070073 if (markinfo->mark > 0xffffffff) {
74 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
Jan Engelhardte1931b72007-07-07 22:16:26 -070075 return false;
Harald Weltebf3a46a2005-08-09 19:22:01 -070076 }
Jan Engelhardte1931b72007-07-07 22:16:26 -070077 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070078}
79
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +020080static bool mark_tg_check_v1(const struct xt_tgchk_param *par)
Linus Torvalds1da177e2005-04-16 15:20:36 -070081{
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +020082 const struct xt_mark_target_info_v1 *markinfo = par->targinfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
Harald Welte2e4e6a12006-01-12 13:30:04 -080084 if (markinfo->mode != XT_MARK_SET
85 && markinfo->mode != XT_MARK_AND
86 && markinfo->mode != XT_MARK_OR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 printk(KERN_WARNING "MARK: unknown mode %u\n",
88 markinfo->mode);
Jan Engelhardte1931b72007-07-07 22:16:26 -070089 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 }
Harald Weltebf3a46a2005-08-09 19:22:01 -070091 if (markinfo->mark > 0xffffffff) {
92 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
Jan Engelhardte1931b72007-07-07 22:16:26 -070093 return false;
Harald Weltebf3a46a2005-08-09 19:22:01 -070094 }
Jan Engelhardte1931b72007-07-07 22:16:26 -070095 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070096}
97
Patrick McHardybe7263b72006-09-20 12:06:10 -070098#ifdef CONFIG_COMPAT
Patrick McHardy1fe57232007-12-17 21:51:33 -080099struct compat_xt_mark_target_info {
100 compat_ulong_t mark;
101};
102
Jan Engelhardte0a812a2008-01-14 23:38:52 -0800103static void mark_tg_compat_from_user_v0(void *dst, void *src)
Patrick McHardy1fe57232007-12-17 21:51:33 -0800104{
105 const struct compat_xt_mark_target_info *cm = src;
106 struct xt_mark_target_info m = {
107 .mark = cm->mark,
108 };
109 memcpy(dst, &m, sizeof(m));
110}
111
Jan Engelhardte0a812a2008-01-14 23:38:52 -0800112static int mark_tg_compat_to_user_v0(void __user *dst, void *src)
Patrick McHardy1fe57232007-12-17 21:51:33 -0800113{
114 const struct xt_mark_target_info *m = src;
115 struct compat_xt_mark_target_info cm = {
116 .mark = m->mark,
117 };
118 return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
119}
120
Patrick McHardybe7263b72006-09-20 12:06:10 -0700121struct compat_xt_mark_target_info_v1 {
122 compat_ulong_t mark;
123 u_int8_t mode;
124 u_int8_t __pad1;
125 u_int16_t __pad2;
126};
127
Patrick McHardy1fe57232007-12-17 21:51:33 -0800128static void mark_tg_compat_from_user_v1(void *dst, void *src)
Patrick McHardybe7263b72006-09-20 12:06:10 -0700129{
Jan Engelhardta47362a2007-07-07 22:16:55 -0700130 const struct compat_xt_mark_target_info_v1 *cm = src;
Patrick McHardybe7263b72006-09-20 12:06:10 -0700131 struct xt_mark_target_info_v1 m = {
132 .mark = cm->mark,
133 .mode = cm->mode,
134 };
135 memcpy(dst, &m, sizeof(m));
136}
137
Patrick McHardy1fe57232007-12-17 21:51:33 -0800138static int mark_tg_compat_to_user_v1(void __user *dst, void *src)
Patrick McHardybe7263b72006-09-20 12:06:10 -0700139{
Jan Engelhardta47362a2007-07-07 22:16:55 -0700140 const struct xt_mark_target_info_v1 *m = src;
Patrick McHardybe7263b72006-09-20 12:06:10 -0700141 struct compat_xt_mark_target_info_v1 cm = {
142 .mark = m->mark,
143 .mode = m->mode,
144 };
145 return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
146}
147#endif /* CONFIG_COMPAT */
148
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800149static struct xt_target mark_tg_reg[] __read_mostly = {
Patrick McHardy4470bbc2006-08-22 00:34:04 -0700150 {
151 .name = "MARK",
Jan Engelhardtab4f21e2008-10-08 11:35:20 +0200152 .family = NFPROTO_UNSPEC,
Patrick McHardy4470bbc2006-08-22 00:34:04 -0700153 .revision = 0,
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800154 .checkentry = mark_tg_check_v0,
155 .target = mark_tg_v0,
Patrick McHardy4470bbc2006-08-22 00:34:04 -0700156 .targetsize = sizeof(struct xt_mark_target_info),
Patrick McHardy1fe57232007-12-17 21:51:33 -0800157#ifdef CONFIG_COMPAT
158 .compatsize = sizeof(struct compat_xt_mark_target_info),
Jan Engelhardte0a812a2008-01-14 23:38:52 -0800159 .compat_from_user = mark_tg_compat_from_user_v0,
160 .compat_to_user = mark_tg_compat_to_user_v0,
Patrick McHardy1fe57232007-12-17 21:51:33 -0800161#endif
Patrick McHardy4470bbc2006-08-22 00:34:04 -0700162 .table = "mangle",
163 .me = THIS_MODULE,
164 },
165 {
166 .name = "MARK",
Jan Engelhardtab4f21e2008-10-08 11:35:20 +0200167 .family = NFPROTO_UNSPEC,
Patrick McHardy311af5c2007-12-17 21:51:14 -0800168 .revision = 1,
Jan Engelhardte0a812a2008-01-14 23:38:52 -0800169 .checkentry = mark_tg_check_v1,
170 .target = mark_tg_v1,
Patrick McHardy311af5c2007-12-17 21:51:14 -0800171 .targetsize = sizeof(struct xt_mark_target_info_v1),
172#ifdef CONFIG_COMPAT
173 .compatsize = sizeof(struct compat_xt_mark_target_info_v1),
Patrick McHardy1fe57232007-12-17 21:51:33 -0800174 .compat_from_user = mark_tg_compat_from_user_v1,
175 .compat_to_user = mark_tg_compat_to_user_v1,
Patrick McHardy311af5c2007-12-17 21:51:14 -0800176#endif
177 .table = "mangle",
178 .me = THIS_MODULE,
179 },
Jan Engelhardte0a812a2008-01-14 23:38:52 -0800180 {
181 .name = "MARK",
182 .revision = 2,
Jan Engelhardt55b69e92008-10-08 11:35:01 +0200183 .family = NFPROTO_UNSPEC,
Jan Engelhardte0a812a2008-01-14 23:38:52 -0800184 .target = mark_tg,
185 .targetsize = sizeof(struct xt_mark_tginfo2),
186 .me = THIS_MODULE,
187 },
Harald Welte2e4e6a12006-01-12 13:30:04 -0800188};
189
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800190static int __init mark_tg_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191{
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800192 return xt_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193}
194
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800195static void __exit mark_tg_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196{
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800197 xt_unregister_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198}
199
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800200module_init(mark_tg_init);
201module_exit(mark_tg_exit);