fix for f12, gcc4.4
[iptables.git] / extensions / libipt_MARK.c
1 /* Shared library add-on to iptables to add MARK target support. */
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <getopt.h>
6
7 #include <iptables.h>
8 #include <linux/netfilter_ipv4/ip_tables.h>
9 /* For 64bit kernel / 32bit userspace */
10 #include "../include/linux/netfilter_ipv4/ipt_MARK.h"
11
12 /* Function which prints out usage message. */
13 static void
14 help(void)
15 {
16         printf(
17 "MARK target v%s options:\n"
18 "  --set-mark value                   Set nfmark value\n"
19 "  --and-mark value                   Binary AND the nfmark with value\n"
20 "  --or-mark  value                   Binary OR  the nfmark with value\n"
21 "  --copy-xid                         Set nfmark to be the connection xid (PlanetLab specific)\n"
22 "\n",
23 IPTABLES_VERSION);
24 }
25
26 static struct option opts[] = {
27         { "set-mark", 1, 0, '1' },
28         { "and-mark", 1, 0, '2' },
29         { "or-mark", 1, 0, '3' },
30         { "copy-xid", 1, 0, '4' },
31         { 0 }
32 };
33
34 /* Initialize the target. */
35 static void
36 init(struct ipt_entry_target *t, unsigned int *nfcache)
37 {
38 }
39
40 /* Function which parses command options; returns true if it
41    ate an option */
42 static int
43 parse_v0(int c, char **argv, int invert, unsigned int *flags,
44          const struct ipt_entry *entry,
45          struct ipt_entry_target **target)
46 {
47         struct ipt_mark_target_info *markinfo
48                 = (struct ipt_mark_target_info *)(*target)->data;
49
50         switch (c) {
51         case '1':
52 #ifdef KERNEL_64_USERSPACE_32
53                 if (string_to_number_ll(optarg, 0, 0, 
54                                      &markinfo->mark))
55 #else
56                 if (string_to_number_l(optarg, 0, 0, 
57                                      &markinfo->mark))
58 #endif
59                         exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
60                 if (*flags)
61                         exit_error(PARAMETER_PROBLEM,
62                                    "MARK target: Can't specify --set-mark twice");
63                 *flags = 1;
64                 break;
65         case '2':
66                 exit_error(PARAMETER_PROBLEM,
67                            "MARK target: kernel too old for --and-mark");
68         case '3':
69                 exit_error(PARAMETER_PROBLEM,
70                            "MARK target: kernel too old for --or-mark");
71         default:
72                 return 0;
73         }
74
75         return 1;
76 }
77
78 static void
79 final_check(unsigned int flags)
80 {
81         if (!flags)
82                 exit_error(PARAMETER_PROBLEM,
83                            "MARK target: Parameter --set/and/or-mark"
84                            " is required");
85 }
86
87 /* Function which parses command options; returns true if it
88    ate an option */
89 static int
90 parse_v1(int c, char **argv, int invert, unsigned int *flags,
91          const struct ipt_entry *entry,
92          struct ipt_entry_target **target)
93 {
94         struct ipt_mark_target_info_v1 *markinfo
95                 = (struct ipt_mark_target_info_v1 *)(*target)->data;
96
97         switch (c) {
98         case '1':
99                 markinfo->mode = IPT_MARK_SET;
100                 break;
101         case '2':
102                 markinfo->mode = IPT_MARK_AND;
103                 break;
104         case '3':
105                 markinfo->mode = IPT_MARK_OR;
106                 break;
107         case '4':
108                 markinfo->mode = IPT_MARK_COPYXID;
109                 break;
110         default:
111                 return 0;
112         }
113
114 #ifdef KERNEL_64_USERSPACE_32
115         if (string_to_number_ll(optarg, 0, 0,  &markinfo->mark))
116 #else
117         if (string_to_number_l(optarg, 0, 0, &markinfo->mark))
118 #endif
119                 exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
120
121         if (*flags)
122                 exit_error(PARAMETER_PROBLEM,
123                            "MARK target: Can't specify --set-mark twice");
124
125         *flags = 1;
126         return 1;
127 }
128
129 #ifdef KERNEL_64_USERSPACE_32
130 static void
131 print_mark(unsigned long long mark)
132 {
133         printf("0x%llx ", mark);
134 }
135 #else
136 static void
137 print_mark(unsigned long mark)
138 {
139         printf("0x%lx ", mark);
140 }
141 #endif
142
143 /* Prints out the targinfo. */
144 static void
145 print_v0(const struct ipt_ip *ip,
146          const struct ipt_entry_target *target,
147          int numeric)
148 {
149         const struct ipt_mark_target_info *markinfo =
150                 (const struct ipt_mark_target_info *)target->data;
151         printf("MARK set ");
152         print_mark(markinfo->mark);
153 }
154
155 /* Saves the union ipt_targinfo in parsable form to stdout. */
156 static void
157 save_v0(const struct ipt_ip *ip, const struct ipt_entry_target *target)
158 {
159         const struct ipt_mark_target_info *markinfo =
160                 (const struct ipt_mark_target_info *)target->data;
161
162         printf("--set-mark ");
163         print_mark(markinfo->mark);
164 }
165
166 /* Prints out the targinfo. */
167 static void
168 print_v1(const struct ipt_ip *ip,
169          const struct ipt_entry_target *target,
170          int numeric)
171 {
172         const struct ipt_mark_target_info_v1 *markinfo =
173                 (const struct ipt_mark_target_info_v1 *)target->data;
174
175         switch (markinfo->mode) {
176         case IPT_MARK_SET:
177                 printf("MARK set ");
178                 break;
179         case IPT_MARK_AND:
180                 printf("MARK and ");
181                 break;
182         case IPT_MARK_OR: 
183                 printf("MARK or ");
184                 break;
185         case IPT_MARK_COPYXID: 
186                 printf("MARK copyxid ");
187                 break;
188         }
189         print_mark(markinfo->mark);
190 }
191
192 /* Saves the union ipt_targinfo in parsable form to stdout. */
193 static void
194 save_v1(const struct ipt_ip *ip, const struct ipt_entry_target *target)
195 {
196         const struct ipt_mark_target_info_v1 *markinfo =
197                 (const struct ipt_mark_target_info_v1 *)target->data;
198
199         switch (markinfo->mode) {
200         case IPT_MARK_SET:
201                 printf("--set-mark ");
202                 break;
203         case IPT_MARK_AND:
204                 printf("--and-mark ");
205                 break;
206         case IPT_MARK_OR: 
207                 printf("--or-mark ");
208                 break;
209         case IPT_MARK_COPYXID: 
210                 printf("--copy-xid ");
211                 break;
212         }
213         print_mark(markinfo->mark);
214 }
215
216 static
217 struct iptables_target mark_v0 = {
218         .next           = NULL,
219         .name           = "MARK",
220         .version        = IPTABLES_VERSION,
221         .revision       = 0,
222         .size           = IPT_ALIGN(sizeof(struct ipt_mark_target_info)),
223         .userspacesize  = IPT_ALIGN(sizeof(struct ipt_mark_target_info)),
224         .help           = &help,
225         .init           = &init,
226         .parse          = &parse_v0,
227         .final_check    = &final_check,
228         .print          = &print_v0,
229         .save           = &save_v0,
230         .extra_opts     = opts
231 };
232
233 static
234 struct iptables_target mark_v1 = {
235         .next           = NULL,
236         .name           = "MARK",
237         .version        = IPTABLES_VERSION,
238         .revision       = 1,
239         .size           = IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1)),
240         .userspacesize  = IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1)),
241         .help           = &help,
242         .init           = &init,
243         .parse          = &parse_v1,
244         .final_check    = &final_check,
245         .print          = &print_v1,
246         .save           = &save_v1,
247         .extra_opts     = opts
248 };
249
250 void _init(void)
251 {
252         register_target(&mark_v0);
253         register_target(&mark_v1);
254 }