]> err.no Git - linux-2.6/blob - net/ipv4/netfilter/ipt_MARK.c
[NETFILTER]: convert nfmark and conntrack mark to 32bit
[linux-2.6] / net / ipv4 / netfilter / ipt_MARK.c
1 /* This is a module which is used for setting the NFMARK field of an skb. */
2
3 /* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  */
9
10 #include <linux/module.h>
11 #include <linux/skbuff.h>
12 #include <linux/ip.h>
13 #include <net/checksum.h>
14
15 #include <linux/netfilter_ipv4/ip_tables.h>
16 #include <linux/netfilter_ipv4/ipt_MARK.h>
17
18 MODULE_LICENSE("GPL");
19 MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
20 MODULE_DESCRIPTION("iptables MARK modification module");
21
22 static unsigned int
23 target_v0(struct sk_buff **pskb,
24           const struct net_device *in,
25           const struct net_device *out,
26           unsigned int hooknum,
27           const void *targinfo,
28           void *userinfo)
29 {
30         const struct ipt_mark_target_info *markinfo = targinfo;
31
32         if((*pskb)->nfmark != markinfo->mark) {
33                 (*pskb)->nfmark = markinfo->mark;
34                 (*pskb)->nfcache |= NFC_ALTERED;
35         }
36         return IPT_CONTINUE;
37 }
38
39 static unsigned int
40 target_v1(struct sk_buff **pskb,
41           const struct net_device *in,
42           const struct net_device *out,
43           unsigned int hooknum,
44           const void *targinfo,
45           void *userinfo)
46 {
47         const struct ipt_mark_target_info_v1 *markinfo = targinfo;
48         int mark = 0;
49
50         switch (markinfo->mode) {
51         case IPT_MARK_SET:
52                 mark = markinfo->mark;
53                 break;
54                 
55         case IPT_MARK_AND:
56                 mark = (*pskb)->nfmark & markinfo->mark;
57                 break;
58                 
59         case IPT_MARK_OR:
60                 mark = (*pskb)->nfmark | markinfo->mark;
61                 break;
62         }
63
64         if((*pskb)->nfmark != mark) {
65                 (*pskb)->nfmark = mark;
66                 (*pskb)->nfcache |= NFC_ALTERED;
67         }
68         return IPT_CONTINUE;
69 }
70
71
72 static int
73 checkentry_v0(const char *tablename,
74               const struct ipt_entry *e,
75               void *targinfo,
76               unsigned int targinfosize,
77               unsigned int hook_mask)
78 {
79         struct ipt_mark_target_info *markinfo = targinfo;
80
81         if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) {
82                 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
83                        targinfosize,
84                        IPT_ALIGN(sizeof(struct ipt_mark_target_info)));
85                 return 0;
86         }
87
88         if (strcmp(tablename, "mangle") != 0) {
89                 printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
90                 return 0;
91         }
92
93         if (markinfo->mark > 0xffffffff) {
94                 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
95                 return 0;
96         }
97
98         return 1;
99 }
100
101 static int
102 checkentry_v1(const char *tablename,
103               const struct ipt_entry *e,
104               void *targinfo,
105               unsigned int targinfosize,
106               unsigned int hook_mask)
107 {
108         struct ipt_mark_target_info_v1 *markinfo = targinfo;
109
110         if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))){
111                 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
112                        targinfosize,
113                        IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1)));
114                 return 0;
115         }
116
117         if (strcmp(tablename, "mangle") != 0) {
118                 printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
119                 return 0;
120         }
121
122         if (markinfo->mode != IPT_MARK_SET
123             && markinfo->mode != IPT_MARK_AND
124             && markinfo->mode != IPT_MARK_OR) {
125                 printk(KERN_WARNING "MARK: unknown mode %u\n",
126                        markinfo->mode);
127                 return 0;
128         }
129
130         if (markinfo->mark > 0xffffffff) {
131                 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
132                 return 0;
133         }
134
135         return 1;
136 }
137
138 static struct ipt_target ipt_mark_reg_v0 = {
139         .name           = "MARK",
140         .target         = target_v0,
141         .checkentry     = checkentry_v0,
142         .me             = THIS_MODULE,
143         .revision       = 0,
144 };
145
146 static struct ipt_target ipt_mark_reg_v1 = {
147         .name           = "MARK",
148         .target         = target_v1,
149         .checkentry     = checkentry_v1,
150         .me             = THIS_MODULE,
151         .revision       = 1,
152 };
153
154 static int __init init(void)
155 {
156         int err;
157
158         err = ipt_register_target(&ipt_mark_reg_v0);
159         if (!err) {
160                 err = ipt_register_target(&ipt_mark_reg_v1);
161                 if (err)
162                         ipt_unregister_target(&ipt_mark_reg_v0);
163         }
164         return err;
165 }
166
167 static void __exit fini(void)
168 {
169         ipt_unregister_target(&ipt_mark_reg_v0);
170         ipt_unregister_target(&ipt_mark_reg_v1);
171 }
172
173 module_init(init);
174 module_exit(fini);