changing trunk/trunk to trunk
[iptables.git] / extensions / libxt_physdev.c
1 /* Shared library add-on to iptables to add bridge port matching support. */
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <getopt.h>
6 #include <ctype.h>
7 #include <xtables.h>
8 #include <linux/netfilter/xt_physdev.h>
9 #if defined(__GLIBC__) && __GLIBC__ == 2
10 #include <net/ethernet.h>
11 #else
12 #include <linux/if_ether.h>
13 #endif
14
15 static void physdev_help(void)
16 {
17         printf(
18 "physdev match options:\n"
19 " --physdev-in [!] input name[+]                bridge port name ([+] for wildcard)\n"
20 " --physdev-out [!] output name[+]      bridge port name ([+] for wildcard)\n"
21 " [!] --physdev-is-in                   arrived on a bridge device\n"
22 " [!] --physdev-is-out                  will leave on a bridge device\n"
23 " [!] --physdev-is-bridged              it's a bridged packet\n");
24 }
25
26 static const struct option physdev_opts[] = {
27         { "physdev-in", 1, NULL, '1' },
28         { "physdev-out", 1, NULL, '2' },
29         { "physdev-is-in", 0, NULL, '3' },
30         { "physdev-is-out", 0, NULL, '4' },
31         { "physdev-is-bridged", 0, NULL, '5' },
32         { .name = NULL }
33 };
34
35 static int
36 physdev_parse(int c, char **argv, int invert, unsigned int *flags,
37               const void *entry, struct xt_entry_match **match)
38 {
39         struct xt_physdev_info *info =
40                 (struct xt_physdev_info*)(*match)->data;
41
42         switch (c) {
43         case '1':
44                 if (*flags & XT_PHYSDEV_OP_IN)
45                         goto multiple_use;
46                 check_inverse(optarg, &invert, &optind, 0);
47                 parse_interface(argv[optind-1], info->physindev,
48                                 (unsigned char *)info->in_mask);
49                 if (invert)
50                         info->invert |= XT_PHYSDEV_OP_IN;
51                 info->bitmask |= XT_PHYSDEV_OP_IN;
52                 *flags |= XT_PHYSDEV_OP_IN;
53                 break;
54
55         case '2':
56                 if (*flags & XT_PHYSDEV_OP_OUT)
57                         goto multiple_use;
58                 check_inverse(optarg, &invert, &optind, 0);
59                 parse_interface(argv[optind-1], info->physoutdev,
60                                 (unsigned char *)info->out_mask);
61                 if (invert)
62                         info->invert |= XT_PHYSDEV_OP_OUT;
63                 info->bitmask |= XT_PHYSDEV_OP_OUT;
64                 *flags |= XT_PHYSDEV_OP_OUT;
65                 break;
66
67         case '3':
68                 if (*flags & XT_PHYSDEV_OP_ISIN)
69                         goto multiple_use;
70                 check_inverse(optarg, &invert, &optind, 0);
71                 info->bitmask |= XT_PHYSDEV_OP_ISIN;
72                 if (invert)
73                         info->invert |= XT_PHYSDEV_OP_ISIN;
74                 *flags |= XT_PHYSDEV_OP_ISIN;
75                 break;
76
77         case '4':
78                 if (*flags & XT_PHYSDEV_OP_ISOUT)
79                         goto multiple_use;
80                 check_inverse(optarg, &invert, &optind, 0);
81                 info->bitmask |= XT_PHYSDEV_OP_ISOUT;
82                 if (invert)
83                         info->invert |= XT_PHYSDEV_OP_ISOUT;
84                 *flags |= XT_PHYSDEV_OP_ISOUT;
85                 break;
86
87         case '5':
88                 if (*flags & XT_PHYSDEV_OP_BRIDGED)
89                         goto multiple_use;
90                 check_inverse(optarg, &invert, &optind, 0);
91                 if (invert)
92                         info->invert |= XT_PHYSDEV_OP_BRIDGED;
93                 *flags |= XT_PHYSDEV_OP_BRIDGED;
94                 info->bitmask |= XT_PHYSDEV_OP_BRIDGED;
95                 break;
96
97         default:
98                 return 0;
99         }
100
101         return 1;
102 multiple_use:
103         exit_error(PARAMETER_PROBLEM,
104            "multiple use of the same physdev option is not allowed");
105
106 }
107
108 static void physdev_check(unsigned int flags)
109 {
110         if (flags == 0)
111                 exit_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
112 }
113
114 static void
115 physdev_print(const void *ip, const struct xt_entry_match *match, int numeric)
116 {
117         struct xt_physdev_info *info =
118                 (struct xt_physdev_info*)match->data;
119
120         printf("PHYSDEV match");
121         if (info->bitmask & XT_PHYSDEV_OP_ISIN)
122                 printf("%s --physdev-is-in",
123                        info->invert & XT_PHYSDEV_OP_ISIN ? " !":"");
124         if (info->bitmask & XT_PHYSDEV_OP_IN)
125                 printf("%s --physdev-in %s",
126                 (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
127
128         if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
129                 printf("%s --physdev-is-out",
130                        info->invert & XT_PHYSDEV_OP_ISOUT ? " !":"");
131         if (info->bitmask & XT_PHYSDEV_OP_OUT)
132                 printf("%s --physdev-out %s",
133                 (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
134         if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
135                 printf("%s --physdev-is-bridged",
136                        info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":"");
137         printf(" ");
138 }
139
140 static void physdev_save(const void *ip, const struct xt_entry_match *match)
141 {
142         struct xt_physdev_info *info =
143                 (struct xt_physdev_info*)match->data;
144
145         if (info->bitmask & XT_PHYSDEV_OP_ISIN)
146                 printf("%s --physdev-is-in",
147                        info->invert & XT_PHYSDEV_OP_ISIN ? " !":"");
148         if (info->bitmask & XT_PHYSDEV_OP_IN)
149                 printf("%s --physdev-in %s",
150                 (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
151
152         if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
153                 printf("%s --physdev-is-out",
154                        info->invert & XT_PHYSDEV_OP_ISOUT ? " !":"");
155         if (info->bitmask & XT_PHYSDEV_OP_OUT)
156                 printf("%s --physdev-out %s",
157                 (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
158         if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
159                 printf("%s --physdev-is-bridged",
160                        info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":"");
161         printf(" ");
162 }
163
164 static struct xtables_match physdev_match = {
165         .family         = AF_INET,
166         .name           = "physdev",
167         .version        = XTABLES_VERSION,
168         .size           = XT_ALIGN(sizeof(struct xt_physdev_info)),
169         .userspacesize  = XT_ALIGN(sizeof(struct xt_physdev_info)),
170         .help           = physdev_help,
171         .parse          = physdev_parse,
172         .final_check    = physdev_check,
173         .print          = physdev_print,
174         .save           = physdev_save,
175         .extra_opts     = physdev_opts,
176 };
177
178 static struct xtables_match physdev_match6 = {
179         .family         = AF_INET6,
180         .name           = "physdev",
181         .version        = XTABLES_VERSION,
182         .size           = XT_ALIGN(sizeof(struct xt_physdev_info)),
183         .userspacesize  = XT_ALIGN(sizeof(struct xt_physdev_info)),
184         .help           = physdev_help,
185         .parse          = physdev_parse,
186         .final_check    = physdev_check,
187         .print          = physdev_print,
188         .save           = physdev_save,
189         .extra_opts     = physdev_opts,
190 };
191
192 void _init(void)
193 {
194         xtables_register_match(&physdev_match);
195         xtables_register_match(&physdev_match6);
196 }