upload tizen1.0 source
[external/iptables.git] / extensions / libipt_addrtype.c
1 /* Shared library add-on to iptables to add addrtype matching support 
2  * 
3  * This program is released under the terms of GNU GPL */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <getopt.h>
9 #include <xtables.h>
10
11 #include <linux/netfilter_ipv4/ipt_addrtype.h>
12
13 /* from linux/rtnetlink.h, must match order of enumeration */
14 static const char *const rtn_names[] = {
15         "UNSPEC",
16         "UNICAST",
17         "LOCAL",
18         "BROADCAST",
19         "ANYCAST",
20         "MULTICAST",
21         "BLACKHOLE",
22         "UNREACHABLE",
23         "PROHIBIT",
24         "THROW",
25         "NAT",
26         "XRESOLVE",
27         NULL
28 };
29
30 static void addrtype_help_types(void)
31 {
32         int i;
33
34         for (i = 0; rtn_names[i]; i++)
35                 printf("                                %s\n", rtn_names[i]);
36 }
37
38 static void addrtype_help_v0(void)
39 {
40         printf(
41 "Address type match options:\n"
42 " [!] --src-type type[,...]      Match source address type\n"
43 " [!] --dst-type type[,...]      Match destination address type\n"
44 "\n"
45 "Valid types:           \n");
46         addrtype_help_types();
47 }
48
49 static void addrtype_help_v1(void)
50 {
51         printf(
52 "Address type match options:\n"
53 " [!] --src-type type[,...]      Match source address type\n"
54 " [!] --dst-type type[,...]      Match destination address type\n"
55 "     --limit-iface-in           Match only on the packet's incoming device\n"
56 "     --limit-iface-out          Match only on the packet's incoming device\n"
57 "\n"
58 "Valid types:           \n");
59         addrtype_help_types();
60 }
61
62 static int
63 parse_type(const char *name, size_t len, u_int16_t *mask)
64 {
65         int i;
66
67         for (i = 0; rtn_names[i]; i++)
68                 if (strncasecmp(name, rtn_names[i], len) == 0) {
69                         /* build up bitmask for kernel module */
70                         *mask |= (1 << i);
71                         return 1;
72                 }
73
74         return 0;
75 }
76
77 static void parse_types(const char *arg, u_int16_t *mask)
78 {
79         const char *comma;
80
81         while ((comma = strchr(arg, ',')) != NULL) {
82                 if (comma == arg || !parse_type(arg, comma-arg, mask))
83                         xtables_error(PARAMETER_PROBLEM,
84                                    "addrtype: bad type `%s'", arg);
85                 arg = comma + 1;
86         }
87
88         if (strlen(arg) == 0 || !parse_type(arg, strlen(arg), mask))
89                 xtables_error(PARAMETER_PROBLEM, "addrtype: bad type \"%s\"", arg);
90 }
91         
92 #define IPT_ADDRTYPE_OPT_SRCTYPE        0x1
93 #define IPT_ADDRTYPE_OPT_DSTTYPE        0x2
94 #define IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN         0x4
95 #define IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT        0x8
96
97 static int
98 addrtype_parse_v0(int c, char **argv, int invert, unsigned int *flags,
99                   const void *entry, struct xt_entry_match **match)
100 {
101         struct ipt_addrtype_info *info =
102                 (struct ipt_addrtype_info *) (*match)->data;
103
104         switch (c) {
105         case '1':
106                 if (*flags&IPT_ADDRTYPE_OPT_SRCTYPE)
107                         xtables_error(PARAMETER_PROBLEM,
108                                    "addrtype: can't specify src-type twice");
109                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
110                 parse_types(optarg, &info->source);
111                 if (invert)
112                         info->invert_source = 1;
113                 *flags |= IPT_ADDRTYPE_OPT_SRCTYPE;
114                 break;
115         case '2':
116                 if (*flags&IPT_ADDRTYPE_OPT_DSTTYPE)
117                         xtables_error(PARAMETER_PROBLEM,
118                                    "addrtype: can't specify dst-type twice");
119                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
120                 parse_types(optarg, &info->dest);
121                 if (invert)
122                         info->invert_dest = 1;
123                 *flags |= IPT_ADDRTYPE_OPT_DSTTYPE;
124                 break;
125         default:
126                 return 0;
127         }
128         
129         return 1;
130 }
131
132 static int
133 addrtype_parse_v1(int c, char **argv, int invert, unsigned int *flags,
134                   const void *entry, struct xt_entry_match **match)
135 {
136         struct ipt_addrtype_info_v1 *info =
137                 (struct ipt_addrtype_info_v1 *) (*match)->data;
138
139         switch (c) {
140         case '1':
141                 if (*flags & IPT_ADDRTYPE_OPT_SRCTYPE)
142                         xtables_error(PARAMETER_PROBLEM,
143                                    "addrtype: can't specify src-type twice");
144                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
145                 parse_types(optarg, &info->source);
146                 if (invert)
147                         info->flags |= IPT_ADDRTYPE_INVERT_SOURCE;
148                 *flags |= IPT_ADDRTYPE_OPT_SRCTYPE;
149                 break;
150         case '2':
151                 if (*flags & IPT_ADDRTYPE_OPT_DSTTYPE)
152                         xtables_error(PARAMETER_PROBLEM,
153                                    "addrtype: can't specify dst-type twice");
154                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
155                 parse_types(optarg, &info->dest);
156                 if (invert)
157                         info->flags |= IPT_ADDRTYPE_INVERT_DEST;
158                 *flags |= IPT_ADDRTYPE_OPT_DSTTYPE;
159                 break;
160         case '3':
161                 if (*flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN)
162                         xtables_error(PARAMETER_PROBLEM,
163                                    "addrtype: can't specify limit-iface-in twice");
164                 info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_IN;
165                 *flags |= IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN;
166                 break;
167         case '4':
168                 if (*flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT)
169                         xtables_error(PARAMETER_PROBLEM,
170                                    "addrtype: can't specify limit-iface-out twice");
171                 info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_OUT;
172                 *flags |= IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT;
173                 break;
174         default:
175                 return 0;
176         }
177         
178         return 1;
179 }
180
181 static void addrtype_check_v0(unsigned int flags)
182 {
183         if (!(flags & (IPT_ADDRTYPE_OPT_SRCTYPE|IPT_ADDRTYPE_OPT_DSTTYPE)))
184                 xtables_error(PARAMETER_PROBLEM,
185                            "addrtype: you must specify --src-type or --dst-type");
186 }
187
188 static void addrtype_check_v1(unsigned int flags)
189 {
190         if (!(flags & (IPT_ADDRTYPE_OPT_SRCTYPE|IPT_ADDRTYPE_OPT_DSTTYPE)))
191                 xtables_error(PARAMETER_PROBLEM,
192                            "addrtype: you must specify --src-type or --dst-type");
193         if (flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN &&
194             flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT)
195                 xtables_error(PARAMETER_PROBLEM,
196                            "addrtype: you can't specify both --limit-iface-in "
197                            "and --limit-iface-out");
198 }
199
200 static void print_types(u_int16_t mask)
201 {
202         const char *sep = "";
203         int i;
204
205         for (i = 0; rtn_names[i]; i++)
206                 if (mask & (1 << i)) {
207                         printf("%s%s", sep, rtn_names[i]);
208                         sep = ",";
209                 }
210
211         printf(" ");
212 }
213
214 static void addrtype_print_v0(const void *ip, const struct xt_entry_match *match,
215                               int numeric)
216 {
217         const struct ipt_addrtype_info *info = 
218                 (struct ipt_addrtype_info *) match->data;
219
220         printf("ADDRTYPE match ");
221         if (info->source) {
222                 printf("src-type ");
223                 if (info->invert_source)
224                         printf("!");
225                 print_types(info->source);
226         }
227         if (info->dest) {
228                 printf("dst-type ");
229                 if (info->invert_dest)
230                         printf("!");
231                 print_types(info->dest);
232         }
233 }
234
235 static void addrtype_print_v1(const void *ip, const struct xt_entry_match *match,
236                               int numeric)
237 {
238         const struct ipt_addrtype_info_v1 *info = 
239                 (struct ipt_addrtype_info_v1 *) match->data;
240
241         printf("ADDRTYPE match ");
242         if (info->source) {
243                 printf("src-type ");
244                 if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE)
245                         printf("!");
246                 print_types(info->source);
247         }
248         if (info->dest) {
249                 printf("dst-type ");
250                 if (info->flags & IPT_ADDRTYPE_INVERT_DEST)
251                         printf("!");
252                 print_types(info->dest);
253         }
254         if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) {
255                 printf("limit-in ");
256         }
257         if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) {
258                 printf("limit-out ");
259         }
260 }
261
262 static void addrtype_save_v0(const void *ip, const struct xt_entry_match *match)
263 {
264         const struct ipt_addrtype_info *info =
265                 (struct ipt_addrtype_info *) match->data;
266
267         if (info->source) {
268                 if (info->invert_source)
269                         printf("! ");
270                 printf("--src-type ");
271                 print_types(info->source);
272         }
273         if (info->dest) {
274                 if (info->invert_dest)
275                         printf("! ");
276                 printf("--dst-type ");
277                 print_types(info->dest);
278         }
279 }
280
281 static void addrtype_save_v1(const void *ip, const struct xt_entry_match *match)
282 {
283         const struct ipt_addrtype_info_v1 *info =
284                 (struct ipt_addrtype_info_v1 *) match->data;
285
286         if (info->source) {
287                 if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE)
288                         printf("! ");
289                 printf("--src-type ");
290                 print_types(info->source);
291         }
292         if (info->dest) {
293                 if (info->flags & IPT_ADDRTYPE_INVERT_DEST)
294                         printf("! ");
295                 printf("--dst-type ");
296                 print_types(info->dest);
297         }
298         if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) {
299                 printf("--limit-iface-in ");
300         }
301         if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) {
302                 printf("--limit-iface-out ");
303         }
304 }
305
306 static const struct option addrtype_opts[] = {
307         { "src-type", 1, NULL, '1' },
308         { "dst-type", 1, NULL, '2' },
309         { .name = NULL }
310 };
311
312 static const struct option addrtype_opts_v0[] = {
313         { "src-type", 1, NULL, '1' },
314         { "dst-type", 1, NULL, '2' },
315         { .name = NULL }
316 };
317
318 static const struct option addrtype_opts_v1[] = {
319         { "src-type", 1, NULL, '1' },
320         { "dst-type", 1, NULL, '2' },
321         { "limit-iface-in", 0, NULL, '3' },
322         { "limit-iface-out", 0, NULL, '4' },
323         { .name = NULL }
324 };
325
326 static struct xtables_match addrtype_mt_reg[] = {
327         {
328                 .name          = "addrtype",
329                 .version       = XTABLES_VERSION,
330                 .family        = NFPROTO_IPV4,
331                 .size          = XT_ALIGN(sizeof(struct ipt_addrtype_info)),
332                 .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info)),
333                 .help          = addrtype_help_v0,
334                 .parse         = addrtype_parse_v0,
335                 .final_check   = addrtype_check_v0,
336                 .print         = addrtype_print_v0,
337                 .save          = addrtype_save_v0,
338                 .extra_opts    = addrtype_opts_v0,
339         },
340         {
341                 .name          = "addrtype",
342                 .revision      = 1,
343                 .version       = XTABLES_VERSION,
344                 .family        = NFPROTO_IPV4,
345                 .size          = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)),
346                 .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)),
347                 .help          = addrtype_help_v1,
348                 .parse         = addrtype_parse_v1,
349                 .final_check   = addrtype_check_v1,
350                 .print         = addrtype_print_v1,
351                 .save          = addrtype_save_v1,
352                 .extra_opts    = addrtype_opts_v1,
353         },
354 };
355
356
357 void _init(void) 
358 {
359         xtables_register_matches(addrtype_mt_reg, ARRAY_SIZE(addrtype_mt_reg));
360 }