• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <ip6tables.h>
8 #include <linux/netfilter_ipv6/ip6t_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
help(void)16 help(void)
17 {
18 	printf(
19 "physdev v%s options:\n"
20 " --physdev-in [!] input name[+]		bridge port name ([+] for wildcard)\n"
21 " --physdev-out [!] output name[+]	bridge port name ([+] for wildcard)\n"
22 " [!] --physdev-is-in			arrived on a bridge device\n"
23 " [!] --physdev-is-out			will leave on a bridge device\n"
24 " [!] --physdev-is-bridged		it's a bridged packet\n"
25 "\n", IPTABLES_VERSION);
26 }
27 
28 static struct option opts[] = {
29 	{ "physdev-in", 1, 0, '1' },
30 	{ "physdev-out", 1, 0, '2' },
31 	{ "physdev-is-in", 0, 0, '3' },
32 	{ "physdev-is-out", 0, 0, '4' },
33 	{ "physdev-is-bridged", 0, 0, '5' },
34 	{0}
35 };
36 
37 static void
init(struct ip6t_entry_match * m,unsigned int * nfcache)38 init(struct ip6t_entry_match *m, unsigned int *nfcache)
39 {
40 }
41 
42 static int
parse(int c,char ** argv,int invert,unsigned int * flags,const struct ip6t_entry * entry,unsigned int * nfcache,struct ip6t_entry_match ** match)43 parse(int c, char **argv, int invert, unsigned int *flags,
44       const struct ip6t_entry *entry,
45       unsigned int *nfcache,
46       struct ip6t_entry_match **match)
47 {
48 	struct ip6t_physdev_info *info =
49 		(struct ip6t_physdev_info*)(*match)->data;
50 
51 	switch (c) {
52 	case '1':
53 		if (*flags & IP6T_PHYSDEV_OP_IN)
54 			goto multiple_use;
55 		check_inverse(optarg, &invert, &optind, 0);
56 		parse_interface(argv[optind-1], info->physindev,
57 				(unsigned char *)info->in_mask);
58 		if (invert)
59 			info->invert |= IP6T_PHYSDEV_OP_IN;
60 		info->bitmask |= IP6T_PHYSDEV_OP_IN;
61 		*flags |= IP6T_PHYSDEV_OP_IN;
62 		break;
63 
64 	case '2':
65 		if (*flags & IP6T_PHYSDEV_OP_OUT)
66 			goto multiple_use;
67 		check_inverse(optarg, &invert, &optind, 0);
68 		parse_interface(argv[optind-1], info->physoutdev,
69 				(unsigned char *)info->out_mask);
70 		if (invert)
71 			info->invert |= IP6T_PHYSDEV_OP_OUT;
72 		info->bitmask |= IP6T_PHYSDEV_OP_OUT;
73 		*flags |= IP6T_PHYSDEV_OP_OUT;
74 		break;
75 
76 	case '3':
77 		if (*flags & IP6T_PHYSDEV_OP_ISIN)
78 			goto multiple_use;
79 		check_inverse(optarg, &invert, &optind, 0);
80 		info->bitmask |= IP6T_PHYSDEV_OP_ISIN;
81 		if (invert)
82 			info->invert |= IP6T_PHYSDEV_OP_ISIN;
83 		*flags |= IP6T_PHYSDEV_OP_ISIN;
84 		break;
85 
86 	case '4':
87 		if (*flags & IP6T_PHYSDEV_OP_ISOUT)
88 			goto multiple_use;
89 		check_inverse(optarg, &invert, &optind, 0);
90 		info->bitmask |= IP6T_PHYSDEV_OP_ISOUT;
91 		if (invert)
92 			info->invert |= IP6T_PHYSDEV_OP_ISOUT;
93 		*flags |= IP6T_PHYSDEV_OP_ISOUT;
94 		break;
95 
96 	case '5':
97 		if (*flags & IP6T_PHYSDEV_OP_BRIDGED)
98 			goto multiple_use;
99 		check_inverse(optarg, &invert, &optind, 0);
100 		if (invert)
101 			info->invert |= IP6T_PHYSDEV_OP_BRIDGED;
102 		*flags |= IP6T_PHYSDEV_OP_BRIDGED;
103 		info->bitmask |= IP6T_PHYSDEV_OP_BRIDGED;
104 		break;
105 
106 	default:
107 		return 0;
108 	}
109 
110 	return 1;
111 multiple_use:
112 	exit_error(PARAMETER_PROBLEM,
113 	   "multiple use of the same physdev option is not allowed");
114 
115 }
116 
final_check(unsigned int flags)117 static void final_check(unsigned int flags)
118 {
119 	if (flags == 0)
120 		exit_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
121 }
122 
123 static void
print(const struct ip6t_ip6 * ip,const struct ip6t_entry_match * match,int numeric)124 print(const struct ip6t_ip6 *ip,
125       const struct ip6t_entry_match *match,
126       int numeric)
127 {
128 	struct ip6t_physdev_info *info =
129 		(struct ip6t_physdev_info*)match->data;
130 
131 	printf("PHYSDEV match");
132 	if (info->bitmask & IP6T_PHYSDEV_OP_ISIN)
133 		printf("%s --physdev-is-in",
134 		       info->invert & IP6T_PHYSDEV_OP_ISIN ? " !":"");
135 	if (info->bitmask & IP6T_PHYSDEV_OP_IN)
136 		printf("%s --physdev-in %s",
137 		(info->invert & IP6T_PHYSDEV_OP_IN) ? " !":"", info->physindev);
138 
139 	if (info->bitmask & IP6T_PHYSDEV_OP_ISOUT)
140 		printf("%s --physdev-is-out",
141 		       info->invert & IP6T_PHYSDEV_OP_ISOUT ? " !":"");
142 	if (info->bitmask & IP6T_PHYSDEV_OP_OUT)
143 		printf("%s --physdev-out %s",
144 		(info->invert & IP6T_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
145 	if (info->bitmask & IP6T_PHYSDEV_OP_BRIDGED)
146 		printf("%s --physdev-is-bridged",
147 		       info->invert & IP6T_PHYSDEV_OP_BRIDGED ? " !":"");
148 	printf(" ");
149 }
150 
save(const struct ip6t_ip6 * ip,const struct ip6t_entry_match * match)151 static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
152 {
153 	struct ip6t_physdev_info *info =
154 		(struct ip6t_physdev_info*)match->data;
155 
156 	if (info->bitmask & IP6T_PHYSDEV_OP_ISIN)
157 		printf("%s --physdev-is-in",
158 		       info->invert & IP6T_PHYSDEV_OP_ISIN ? " !":"");
159 	if (info->bitmask & IP6T_PHYSDEV_OP_IN)
160 		printf("%s --physdev-in %s",
161 		(info->invert & IP6T_PHYSDEV_OP_IN) ? " !":"", info->physindev);
162 
163 	if (info->bitmask & IP6T_PHYSDEV_OP_ISOUT)
164 		printf("%s --physdev-is-out",
165 		       info->invert & IP6T_PHYSDEV_OP_ISOUT ? " !":"");
166 	if (info->bitmask & IP6T_PHYSDEV_OP_OUT)
167 		printf("%s --physdev-out %s",
168 		(info->invert & IP6T_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
169 	if (info->bitmask & IP6T_PHYSDEV_OP_BRIDGED)
170 		printf("%s --physdev-is-bridged",
171 		       info->invert & IP6T_PHYSDEV_OP_BRIDGED ? " !":"");
172 	printf(" ");
173 }
174 
175 static struct ip6tables_match physdev = {
176 	.name		= "physdev",
177 	.version	= IPTABLES_VERSION,
178 	.size		= IP6T_ALIGN(sizeof(struct ip6t_physdev_info)),
179 	.userspacesize	= IP6T_ALIGN(sizeof(struct ip6t_physdev_info)),
180 	.help		= &help,
181 	.init		= &init,
182 	.parse		= &parse,
183 	.final_check	= &final_check,
184 	.print		= &print,
185 	.save		= &save,
186 	.extra_opts	= opts,
187 };
188 
_init(void)189 void _init(void)
190 {
191 	register_match6(&physdev);
192 }
193