Git init
[profile/ivi/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 inputname[+]         bridge port name ([+] for wildcard)\n"
20 " [!] --physdev-out outputname[+]       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                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
47                 xtables_parse_interface(optarg, 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                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
59                 xtables_parse_interface(optarg, 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                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
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                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
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                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
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         xtables_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                 xtables_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         const struct xt_physdev_info *info = (const void *)match->data;
118
119         printf("PHYSDEV match");
120         if (info->bitmask & XT_PHYSDEV_OP_ISIN)
121                 printf("%s --physdev-is-in",
122                        info->invert & XT_PHYSDEV_OP_ISIN ? " !":"");
123         if (info->bitmask & XT_PHYSDEV_OP_IN)
124                 printf("%s --physdev-in %s",
125                 (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
126
127         if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
128                 printf("%s --physdev-is-out",
129                        info->invert & XT_PHYSDEV_OP_ISOUT ? " !":"");
130         if (info->bitmask & XT_PHYSDEV_OP_OUT)
131                 printf("%s --physdev-out %s",
132                 (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
133         if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
134                 printf("%s --physdev-is-bridged",
135                        info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":"");
136         printf(" ");
137 }
138
139 static void physdev_save(const void *ip, const struct xt_entry_match *match)
140 {
141         const struct xt_physdev_info *info = (const void *)match->data;
142
143         if (info->bitmask & XT_PHYSDEV_OP_ISIN)
144                 printf("%s--physdev-is-in ",
145                        (info->invert & XT_PHYSDEV_OP_ISIN) ? "! " : "");
146         if (info->bitmask & XT_PHYSDEV_OP_IN)
147                 printf("%s--physdev-in %s ",
148                        (info->invert & XT_PHYSDEV_OP_IN) ? "! " : "",
149                        info->physindev);
150
151         if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
152                 printf("%s--physdev-is-out ",
153                        (info->invert & XT_PHYSDEV_OP_ISOUT) ? "! " : "");
154         if (info->bitmask & XT_PHYSDEV_OP_OUT)
155                 printf("%s--physdev-out %s ",
156                        (info->invert & XT_PHYSDEV_OP_OUT) ? "! " : "",
157                        info->physoutdev);
158         if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
159                 printf("%s--physdev-is-bridged ",
160                        (info->invert & XT_PHYSDEV_OP_BRIDGED) ? "! " : "");
161 }
162
163 static struct xtables_match physdev_match = {
164         .family         = NFPROTO_UNSPEC,
165         .name           = "physdev",
166         .version        = XTABLES_VERSION,
167         .size           = XT_ALIGN(sizeof(struct xt_physdev_info)),
168         .userspacesize  = XT_ALIGN(sizeof(struct xt_physdev_info)),
169         .help           = physdev_help,
170         .parse          = physdev_parse,
171         .final_check    = physdev_check,
172         .print          = physdev_print,
173         .save           = physdev_save,
174         .extra_opts     = physdev_opts,
175 };
176
177 void _init(void)
178 {
179         xtables_register_match(&physdev_match);
180 }