vserver 1.9.5.x5
[linux-2.6.git] / 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         if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) {
80                 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
81                        targinfosize,
82                        IPT_ALIGN(sizeof(struct ipt_mark_target_info)));
83                 return 0;
84         }
85
86         if (strcmp(tablename, "mangle") != 0) {
87                 printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
88                 return 0;
89         }
90
91         return 1;
92 }
93
94 static int
95 checkentry_v1(const char *tablename,
96               const struct ipt_entry *e,
97               void *targinfo,
98               unsigned int targinfosize,
99               unsigned int hook_mask)
100 {
101         struct ipt_mark_target_info_v1 *markinfo = targinfo;
102
103         if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))){
104                 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
105                        targinfosize,
106                        IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1)));
107                 return 0;
108         }
109
110         if (strcmp(tablename, "mangle") != 0) {
111                 printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
112                 return 0;
113         }
114
115         if (markinfo->mode != IPT_MARK_SET
116             && markinfo->mode != IPT_MARK_AND
117             && markinfo->mode != IPT_MARK_OR) {
118                 printk(KERN_WARNING "MARK: unknown mode %u\n",
119                        markinfo->mode);
120                 return 0;
121         }
122
123         return 1;
124 }
125
126 static struct ipt_target ipt_mark_reg_v0 = {
127         .name           = "MARK",
128         .target         = target_v0,
129         .checkentry     = checkentry_v0,
130         .me             = THIS_MODULE,
131         .revision       = 0,
132 };
133
134 static struct ipt_target ipt_mark_reg_v1 = {
135         .name           = "MARK",
136         .target         = target_v1,
137         .checkentry     = checkentry_v1,
138         .me             = THIS_MODULE,
139         .revision       = 1,
140 };
141
142 static int __init init(void)
143 {
144         int err;
145
146         err = ipt_register_target(&ipt_mark_reg_v0);
147         if (!err) {
148                 err = ipt_register_target(&ipt_mark_reg_v1);
149                 if (err)
150                         ipt_unregister_target(&ipt_mark_reg_v0);
151         }
152         return err;
153 }
154
155 static void __exit fini(void)
156 {
157         ipt_unregister_target(&ipt_mark_reg_v0);
158         ipt_unregister_target(&ipt_mark_reg_v1);
159 }
160
161 module_init(init);
162 module_exit(fini);