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 {.name = "physdev-is-out", .id = O_PHYSDEV_IS_OUT,
32 .type = XTTYPE_NONE},
33 {.name = "physdev-is-bridged", .id = O_PHYSDEV_IS_BRIDGED,
34 .type = XTTYPE_NONE},
35 XTOPT_TABLEEND,
36 };
37 #undef s
38
physdev_parse(struct xt_option_call * cb)39 static void physdev_parse(struct xt_option_call *cb)
40 {
41 struct xt_physdev_info *info = cb->data;
42
43 xtables_option_parse(cb);
44 switch (cb->entry->id) {
45 case O_PHYSDEV_IN:
46 xtables_parse_interface(cb->arg, info->physindev,
47 (unsigned char *)info->in_mask);
48 if (cb->invert)
49 info->invert |= XT_PHYSDEV_OP_IN;
50 info->bitmask |= XT_PHYSDEV_OP_IN;
51 break;
52 case O_PHYSDEV_OUT:
53 xtables_parse_interface(cb->arg, info->physoutdev,
54 (unsigned char *)info->out_mask);
55 if (cb->invert)
56 info->invert |= XT_PHYSDEV_OP_OUT;
57 info->bitmask |= XT_PHYSDEV_OP_OUT;
58 break;
59 case O_PHYSDEV_IS_IN:
60 info->bitmask |= XT_PHYSDEV_OP_ISIN;
61 if (cb->invert)
62 info->invert |= XT_PHYSDEV_OP_ISIN;
63 break;
64 case O_PHYSDEV_IS_OUT:
65 info->bitmask |= XT_PHYSDEV_OP_ISOUT;
66 if (cb->invert)
67 info->invert |= XT_PHYSDEV_OP_ISOUT;
68 break;
69 case O_PHYSDEV_IS_BRIDGED:
70 if (cb->invert)
71 info->invert |= XT_PHYSDEV_OP_BRIDGED;
72 info->bitmask |= XT_PHYSDEV_OP_BRIDGED;
73 break;
74 }
75 }
76
physdev_check(struct xt_fcheck_call * cb)77 static void physdev_check(struct xt_fcheck_call *cb)
78 {
79 if (cb->xflags == 0)
80 xtables_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
81 }
82
83 static void
physdev_print(const void * ip,const struct xt_entry_match * match,int numeric)84 physdev_print(const void *ip, const struct xt_entry_match *match, int numeric)
85 {
86 const struct xt_physdev_info *info = (const void *)match->data;
87
88 printf(" PHYSDEV match");
89 if (info->bitmask & XT_PHYSDEV_OP_ISIN)
90 printf("%s --physdev-is-in",
91 info->invert & XT_PHYSDEV_OP_ISIN ? " !":"");
92 if (info->bitmask & XT_PHYSDEV_OP_IN)
93 printf("%s --physdev-in %s",
94 (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
95
96 if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
97 printf("%s --physdev-is-out",
98 info->invert & XT_PHYSDEV_OP_ISOUT ? " !":"");
99 if (info->bitmask & XT_PHYSDEV_OP_OUT)
100 printf("%s --physdev-out %s",
101 (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
102 if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
103 printf("%s --physdev-is-bridged",
104 info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":"");
105 }
106
physdev_save(const void * ip,const struct xt_entry_match * match)107 static void physdev_save(const void *ip, const struct xt_entry_match *match)
108 {
109 const struct xt_physdev_info *info = (const void *)match->data;
110
111 if (info->bitmask & XT_PHYSDEV_OP_ISIN)
112 printf("%s --physdev-is-in",
113 (info->invert & XT_PHYSDEV_OP_ISIN) ? " !" : "");
114 if (info->bitmask & XT_PHYSDEV_OP_IN)
115 printf("%s --physdev-in %s",
116 (info->invert & XT_PHYSDEV_OP_IN) ? " !" : "",
117 info->physindev);
118
119 if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
120 printf("%s --physdev-is-out",
121 (info->invert & XT_PHYSDEV_OP_ISOUT) ? " !" : "");
122 if (info->bitmask & XT_PHYSDEV_OP_OUT)
123 printf("%s --physdev-out %s",
124 (info->invert & XT_PHYSDEV_OP_OUT) ? " !" : "",
125 info->physoutdev);
126 if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
127 printf("%s --physdev-is-bridged",
128 (info->invert & XT_PHYSDEV_OP_BRIDGED) ? " !" : "");
129 }
130
131 static struct xtables_match physdev_match = {
132 .family = NFPROTO_UNSPEC,
133 .name = "physdev",
134 .version = XTABLES_VERSION,
135 .size = XT_ALIGN(sizeof(struct xt_physdev_info)),
136 .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)),
137 .help = physdev_help,
138 .print = physdev_print,
139 .save = physdev_save,
140 .x6_parse = physdev_parse,
141 .x6_fcheck = physdev_check,
142 .x6_options = physdev_opts,
143 };
144
_init(void)145 void _init(void)
146 {
147 xtables_register_match(&physdev_match);
148 }
149