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