1 #include <stdio.h>
2 #include <xtables.h>
3 #include <linux/netfilter/xt_physdev.h>
4
5 enum {
6 O_PHYSDEV_IN = 0,
7 O_PHYSDEV_OUT,
8 O_PHYSDEV_IS_IN,
9 O_PHYSDEV_IS_OUT,
10 O_PHYSDEV_IS_BRIDGED,
11 };
12
physdev_help(void)13 static void physdev_help(void)
14 {
15 printf(
16 "physdev match options:\n"
17 " [!] --physdev-in inputname[+] bridge port name ([+] for wildcard)\n"
18 " [!] --physdev-out outputname[+] bridge port name ([+] for wildcard)\n"
19 " [!] --physdev-is-in arrived on a bridge device\n"
20 " [!] --physdev-is-out will leave on a bridge device\n"
21 " [!] --physdev-is-bridged it's a bridged packet\n");
22 }
23
24 #define s struct xt_physdev_info
25 static const struct xt_option_entry physdev_opts[] = {
26 {.name = "physdev-in", .id = O_PHYSDEV_IN, .type = XTTYPE_STRING,
27 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, physindev)},
28 {.name = "physdev-out", .id = O_PHYSDEV_OUT, .type = XTTYPE_STRING,
29 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, physoutdev)},
30 {.name = "physdev-is-in", .id = O_PHYSDEV_IS_IN, .type = XTTYPE_NONE,
31 .flags = XTOPT_INVERT},
32 {.name = "physdev-is-out", .id = O_PHYSDEV_IS_OUT,
33 .type = XTTYPE_NONE, .flags = XTOPT_INVERT},
34 {.name = "physdev-is-bridged", .id = O_PHYSDEV_IS_BRIDGED,
35 .type = XTTYPE_NONE, .flags = XTOPT_INVERT},
36 XTOPT_TABLEEND,
37 };
38 #undef s
39
physdev_parse(struct xt_option_call * cb)40 static void physdev_parse(struct xt_option_call *cb)
41 {
42 struct xt_physdev_info *info = cb->data;
43
44 xtables_option_parse(cb);
45 switch (cb->entry->id) {
46 case O_PHYSDEV_IN:
47 xtables_parse_interface(cb->arg, info->physindev,
48 (unsigned char *)info->in_mask);
49 if (cb->invert)
50 info->invert |= XT_PHYSDEV_OP_IN;
51 info->bitmask |= XT_PHYSDEV_OP_IN;
52 break;
53 case O_PHYSDEV_OUT:
54 xtables_parse_interface(cb->arg, info->physoutdev,
55 (unsigned char *)info->out_mask);
56 if (cb->invert)
57 info->invert |= XT_PHYSDEV_OP_OUT;
58 info->bitmask |= XT_PHYSDEV_OP_OUT;
59 break;
60 case O_PHYSDEV_IS_IN:
61 info->bitmask |= XT_PHYSDEV_OP_ISIN;
62 if (cb->invert)
63 info->invert |= XT_PHYSDEV_OP_ISIN;
64 break;
65 case O_PHYSDEV_IS_OUT:
66 info->bitmask |= XT_PHYSDEV_OP_ISOUT;
67 if (cb->invert)
68 info->invert |= XT_PHYSDEV_OP_ISOUT;
69 break;
70 case O_PHYSDEV_IS_BRIDGED:
71 if (cb->invert)
72 info->invert |= XT_PHYSDEV_OP_BRIDGED;
73 info->bitmask |= XT_PHYSDEV_OP_BRIDGED;
74 break;
75 }
76 }
77
physdev_check(struct xt_fcheck_call * cb)78 static void physdev_check(struct xt_fcheck_call *cb)
79 {
80 if (cb->xflags == 0)
81 xtables_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
82 }
83
84 static void
physdev_print(const void * ip,const struct xt_entry_match * match,int numeric)85 physdev_print(const void *ip, const struct xt_entry_match *match, int numeric)
86 {
87 const struct xt_physdev_info *info = (const void *)match->data;
88
89 printf(" PHYSDEV match");
90 if (info->bitmask & XT_PHYSDEV_OP_ISIN)
91 printf("%s --physdev-is-in",
92 info->invert & XT_PHYSDEV_OP_ISIN ? " !":"");
93 if (info->bitmask & XT_PHYSDEV_OP_IN)
94 printf("%s --physdev-in %s",
95 (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
96
97 if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
98 printf("%s --physdev-is-out",
99 info->invert & XT_PHYSDEV_OP_ISOUT ? " !":"");
100 if (info->bitmask & XT_PHYSDEV_OP_OUT)
101 printf("%s --physdev-out %s",
102 (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
103 if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
104 printf("%s --physdev-is-bridged",
105 info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":"");
106 }
107
physdev_save(const void * ip,const struct xt_entry_match * match)108 static void physdev_save(const void *ip, const struct xt_entry_match *match)
109 {
110 const struct xt_physdev_info *info = (const void *)match->data;
111
112 if (info->bitmask & XT_PHYSDEV_OP_ISIN)
113 printf("%s --physdev-is-in",
114 (info->invert & XT_PHYSDEV_OP_ISIN) ? " !" : "");
115 if (info->bitmask & XT_PHYSDEV_OP_IN)
116 printf("%s --physdev-in %s",
117 (info->invert & XT_PHYSDEV_OP_IN) ? " !" : "",
118 info->physindev);
119
120 if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
121 printf("%s --physdev-is-out",
122 (info->invert & XT_PHYSDEV_OP_ISOUT) ? " !" : "");
123 if (info->bitmask & XT_PHYSDEV_OP_OUT)
124 printf("%s --physdev-out %s",
125 (info->invert & XT_PHYSDEV_OP_OUT) ? " !" : "",
126 info->physoutdev);
127 if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
128 printf("%s --physdev-is-bridged",
129 (info->invert & XT_PHYSDEV_OP_BRIDGED) ? " !" : "");
130 }
131
132 static struct xtables_match physdev_match = {
133 .family = NFPROTO_UNSPEC,
134 .name = "physdev",
135 .version = XTABLES_VERSION,
136 .size = XT_ALIGN(sizeof(struct xt_physdev_info)),
137 .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)),
138 .help = physdev_help,
139 .print = physdev_print,
140 .save = physdev_save,
141 .x6_parse = physdev_parse,
142 .x6_fcheck = physdev_check,
143 .x6_options = physdev_opts,
144 };
145
_init(void)146 void _init(void)
147 {
148 xtables_register_match(&physdev_match);
149 }
150