blob: ad3e6f73c0591feb7e2bcbc43c04bdb17b3aa637 [file] [log] [blame]
Bart De Schuymer1abc55d2002-06-01 19:23:47 +00001/*
2 * Summary: ebt_vlan userspace module
3 *
4 * Description: 802.1Q Virtual LAN match support module for ebtables project.
5 * Enable to match 802.1Q VLAN tagged frames by VLAN numeric
6 * identifier (12-bites field) and frame priority (3-bites field)
7 *
8 * Authors:
9 * Bart De Schuymer <bart.de.schuymer@pandora.be>
10 * Nick Fedchik <nick@fedchik.org.ua>
11 *
12 * May, 2002
13 */
14
15#include <stdio.h>
16#include <string.h>
17#include <stdlib.h>
18#include <sys/socket.h>
19#include <netinet/in.h>
20#include <linux/netfilter_bridge/ebtables.h>
21#include <getopt.h>
22#include "../include/ebtables_u.h"
23#include <linux/netfilter_bridge/ebt_vlan.h>
24
25#define VLAN_ID '1'
26#define VLAN_PRIO '2'
27
28static struct option opts[] = {
29 {"vlan-id", required_argument, 0, VLAN_ID},
30 {"vlan-prio", required_argument, 0, VLAN_PRIO},
31 {0}
32};
33
34/*
35 * Print out help for ebtables -h vlan
36 */
37static void print_help ()
38{
39 printf ("802.1Q VLAN options:\n"
40 "--vlan-id [!] id : VLAN ID 1-4095 (integer)\n"
41 "--vlan-prio [!] prio : VLAN Priority 0-7 (integer)\n");
42}
43
44/*
45 * Initialization function
46 */
47static void init (struct ebt_entry_match *match)
48{
49 struct ebt_vlan_info *vlaninfo =
50 (struct ebt_vlan_info *) match->data;
51 /*
52 * Just clean initial values
53 */
54 vlaninfo->id = 0;
55 vlaninfo->prio = 0;
56 vlaninfo->invflags = 0;
57 vlaninfo->bitmask = 0;
58}
59
60#define OPT_VLAN_ID 0x01
61#define OPT_VLAN_PRIO 0x02
62static int
63parse (int c, char **argv, int argc,
64 const struct ebt_u_entry *entry, unsigned int *flags,
65 struct ebt_entry_match **match)
66{
67 struct ebt_vlan_info *vlaninfo =
68 (struct ebt_vlan_info *) (*match)->data;
69 unsigned short i;
70 char *end;
71
72 switch (c) {
73 case VLAN_ID:
74 check_option (flags, OPT_VLAN_ID);
75 /*
76 * Check If we got inversed arg for VID,
77 * otherwise unset inversion flag
78 */
79 if (check_inverse (optarg))
80 vlaninfo->invflags |= EBT_VLAN_ID;
81 /*
82 * Check arg value presense
83 */
84 if (optind > argc)
85 print_error ("Missing VLAN ID argument\n");
86 /*
87 * Convert argv to long int,
88 * set *end to end of argv string,
89 * base set 10 for decimal only
90 */
91 (unsigned short) i = strtol (argv[optind - 1], &end, 10);
92 /*
93 * Check arg val range
94 */
95 if (i < 1 || i >= 4096 || *end != '\0') {
96 i = 0;
97 print_error
98 ("Problem with specified VLAN ID range\n");
99 }
100 vlaninfo->id = i;
101 vlaninfo->bitmask|=EBT_VLAN_ID;
102 break;
103
104 case VLAN_PRIO:
105 check_option (flags, OPT_VLAN_PRIO);
106 if (check_inverse (optarg))
107 vlaninfo->invflags |= EBT_VLAN_PRIO;
108 if (optind > argc)
109 print_error
110 ("Missing VLAN Priority level argument\n");
111 /*
112 * Convert argv to long int,
113 * set *end to end of argv string,
114 * base set 10 for decimal only
115 */
116 (unsigned short) i = strtol (argv[optind - 1], &end, 10);
117 /*
118 * Check arg val range
119 */
120 if (i >= 8 || *end != '\0') {
121 i = 0;
122 print_error
123 ("Problem with specified VLAN Priority range\n");
124 }
125 vlaninfo->prio = i;
126 vlaninfo->bitmask|=EBT_VLAN_PRIO;
127 break;
128
129 default:
130 return 0;
131 }
132 return 1;
133}
134
135/*
136 * Final check
137 */
138static void
139final_check (const struct ebt_u_entry *entry,
140 const struct ebt_entry_match *match,
141 const char *name, unsigned int hook)
142{
143 /*
144 * Is any proto supplied there? Or specified proto isn't 802.1Q?
145 */
146 if (entry->bitmask & EBT_NOPROTO || entry->ethproto != ETH_P_8021Q)
147 print_error
148 ("For matching 802.1Q VLAN the protocol must be specified as 802_1Q\n");
149}
150
151/*
152 * Print line when listing rules by ebtables -L
153 */
154static void
155print (const struct ebt_u_entry *entry,
156 const struct ebt_entry_match *match)
157{
158 struct ebt_vlan_info *vlaninfo =
159 (struct ebt_vlan_info *) match->data;
160
161 /*
162 * Print VLAN ID if they are specified
163 */
164 if (vlaninfo->bitmask & EBT_VLAN_ID) {
165 printf ("vlan id: %s%d, ",
166 vlaninfo->invflags & EBT_VLAN_ID ? "!" : "",
167 vlaninfo->id);
168 }
169 /*
170 * Print VLAN priority if they are specified
171 */
172 if (vlaninfo->bitmask & EBT_VLAN_PRIO) {
173 printf ("vlan prio: %s%d, ",
174 vlaninfo->invflags & EBT_VLAN_PRIO ? "!" : "",
175 vlaninfo->prio);
176 }
177}
178
179
180static int
181compare (const struct ebt_entry_match *vlan1,
182 const struct ebt_entry_match *vlan2)
183{
184 struct ebt_vlan_info *vlaninfo1 =
185 (struct ebt_vlan_info *) vlan1->data;
186 struct ebt_vlan_info *vlaninfo2 =
187 (struct ebt_vlan_info *) vlan2->data;
188 /*
189 * Compare argc
190 */
191 if (vlaninfo1->bitmask != vlaninfo2->bitmask)
192 return 0;
193 /*
194 * Compare inv flags
195 */
196 if (vlaninfo1->invflags != vlaninfo2->invflags)
197 return 0;
198 /*
199 * Compare VLAN ID if they are present
200 */
201 if (vlaninfo1->bitmask & EBT_VLAN_ID) {
202 if (vlaninfo1->id != vlaninfo2->id)
203 return 0;
204 };
205 /*
206 * Compare VLAN Prio if they are present
207 */
208 if (vlaninfo1->bitmask & EBT_VLAN_PRIO) {
209 if (vlaninfo1->prio != vlaninfo2->prio)
210 return 0;
211 };
212 return 1;
213}
214
215static struct ebt_u_match vlan_match = {
216 EBT_VLAN_MATCH,
217 sizeof (struct ebt_vlan_info),
218 print_help,
219 init,
220 parse,
221 final_check,
222 print,
223 compare,
224 opts,
225};
226
227static void _init (void) __attribute__ ((constructor));
228static void _init (void)
229{
230 register_match (&vlan_match);
231}