Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / ebtables / extensions / ebt_vlan.c
blob6714c82d4d1acf056d7cc7a7b2143779fc134fcd
1 /* ebt_vlan
2 *
3 * Authors:
4 * Bart De Schuymer <bdschuym@pandora.be>
5 * Nick Fedchik <nick@fedchik.org.ua>
7 * June, 2002
8 */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <getopt.h>
14 #include <ctype.h>
15 #include "../include/ebtables_u.h"
16 #include "../include/ethernetdb.h"
17 #include <linux/netfilter_bridge/ebt_vlan.h>
18 #include <linux/if_ether.h>
20 #define NAME_VLAN_ID "id"
21 #define NAME_VLAN_PRIO "prio"
22 #define NAME_VLAN_ENCAP "encap"
24 #define VLAN_ID '1'
25 #define VLAN_PRIO '2'
26 #define VLAN_ENCAP '3'
28 static struct option opts[] = {
29 {"vlan-id" , required_argument, NULL, VLAN_ID},
30 {"vlan-prio" , required_argument, NULL, VLAN_PRIO},
31 {"vlan-encap", required_argument, NULL, VLAN_ENCAP},
32 { 0 }
36 * option inverse flags definition
38 #define OPT_VLAN_ID 0x01
39 #define OPT_VLAN_PRIO 0x02
40 #define OPT_VLAN_ENCAP 0x04
41 #define OPT_VLAN_FLAGS (OPT_VLAN_ID | OPT_VLAN_PRIO | OPT_VLAN_ENCAP)
43 struct ethertypeent *ethent;
45 static void print_help()
47 printf(
48 "vlan options:\n"
49 "--vlan-id [!] id : vlan-tagged frame identifier, 0,1-4096 (integer)\n"
50 "--vlan-prio [!] prio : Priority-tagged frame's user priority, 0-7 (integer)\n"
51 "--vlan-encap [!] encap : Encapsulated frame protocol (hexadecimal or name)\n");
54 static void init(struct ebt_entry_match *match)
56 struct ebt_vlan_info *vlaninfo = (struct ebt_vlan_info *) match->data;
57 vlaninfo->invflags = 0;
58 vlaninfo->bitmask = 0;
62 static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
63 unsigned int *flags, struct ebt_entry_match **match)
65 struct ebt_vlan_info *vlaninfo = (struct ebt_vlan_info *) (*match)->data;
66 char *end;
67 struct ebt_vlan_info local;
69 switch (c) {
70 case VLAN_ID:
71 ebt_check_option2(flags, OPT_VLAN_ID);
72 if (ebt_check_inverse2(optarg))
73 vlaninfo->invflags |= EBT_VLAN_ID;
74 local.id = strtoul(optarg, &end, 10);
75 if (local.id > 4094 || *end != '\0')
76 ebt_print_error2("Invalid --vlan-id range ('%s')", optarg);
77 vlaninfo->id = local.id;
78 vlaninfo->bitmask |= EBT_VLAN_ID;
79 break;
80 case VLAN_PRIO:
81 ebt_check_option2(flags, OPT_VLAN_PRIO);
82 if (ebt_check_inverse2(optarg))
83 vlaninfo->invflags |= EBT_VLAN_PRIO;
84 local.prio = strtoul(optarg, &end, 10);
85 if (local.prio >= 8 || *end != '\0')
86 ebt_print_error2("Invalid --vlan-prio range ('%s')", optarg);
87 vlaninfo->prio = local.prio;
88 vlaninfo->bitmask |= EBT_VLAN_PRIO;
89 break;
90 case VLAN_ENCAP:
91 ebt_check_option2(flags, OPT_VLAN_ENCAP);
92 if (ebt_check_inverse2(optarg))
93 vlaninfo->invflags |= EBT_VLAN_ENCAP;
94 local.encap = strtoul(optarg, &end, 16);
95 if (*end != '\0') {
96 ethent = getethertypebyname(optarg);
97 if (ethent == NULL)
98 ebt_print_error("Unknown --vlan-encap value ('%s')", optarg);
99 local.encap = ethent->e_ethertype;
101 if (local.encap < ETH_ZLEN)
102 ebt_print_error2("Invalid --vlan-encap range ('%s')", optarg);
103 vlaninfo->encap = htons(local.encap);
104 vlaninfo->bitmask |= EBT_VLAN_ENCAP;
105 break;
106 default:
107 return 0;
110 return 1;
113 static void final_check(const struct ebt_u_entry *entry,
114 const struct ebt_entry_match *match,
115 const char *name, unsigned int hookmask, unsigned int time)
117 if (entry->ethproto != ETH_P_8021Q || entry->invflags & EBT_IPROTO)
118 ebt_print_error("For vlan filtering the protocol must be specified as 802_1Q");
120 /* Check if specified vlan-id=0 (priority-tagged frame condition)
121 * when vlan-prio was specified. */
122 /* I see no reason why a user should be prohibited to match on a perhaps impossible situation <BDS>
123 if (vlaninfo->bitmask & EBT_VLAN_PRIO &&
124 vlaninfo->id && vlaninfo->bitmask & EBT_VLAN_ID)
125 ebt_print_error("When setting --vlan-prio the specified --vlan-id must be 0");*/
128 static void print(const struct ebt_u_entry *entry,
129 const struct ebt_entry_match *match)
131 struct ebt_vlan_info *vlaninfo = (struct ebt_vlan_info *) match->data;
133 if (vlaninfo->bitmask & EBT_VLAN_ID) {
134 printf("--vlan-id %s%d ", (vlaninfo->invflags & EBT_VLAN_ID) ? "! " : "", vlaninfo->id);
136 if (vlaninfo->bitmask & EBT_VLAN_PRIO) {
137 printf("--vlan-prio %s%d ", (vlaninfo->invflags & EBT_VLAN_PRIO) ? "! " : "", vlaninfo->prio);
139 if (vlaninfo->bitmask & EBT_VLAN_ENCAP) {
140 printf("--vlan-encap %s", (vlaninfo->invflags & EBT_VLAN_ENCAP) ? "! " : "");
141 ethent = getethertypebynumber(ntohs(vlaninfo->encap));
142 if (ethent != NULL) {
143 printf("%s ", ethent->e_name);
144 } else {
145 printf("%4.4X ", ntohs(vlaninfo->encap));
150 static int compare(const struct ebt_entry_match *vlan1,
151 const struct ebt_entry_match *vlan2)
153 struct ebt_vlan_info *vlaninfo1 = (struct ebt_vlan_info *) vlan1->data;
154 struct ebt_vlan_info *vlaninfo2 = (struct ebt_vlan_info *) vlan2->data;
156 if (vlaninfo1->bitmask != vlaninfo2->bitmask)
157 return 0;
158 if (vlaninfo1->invflags != vlaninfo2->invflags)
159 return 0;
160 if (vlaninfo1->bitmask & EBT_VLAN_ID &&
161 vlaninfo1->id != vlaninfo2->id)
162 return 0;
163 if (vlaninfo1->bitmask & EBT_VLAN_PRIO &&
164 vlaninfo1->prio != vlaninfo2->prio)
165 return 0;
166 if (vlaninfo1->bitmask & EBT_VLAN_ENCAP &&
167 vlaninfo1->encap != vlaninfo2->encap)
168 return 0;
169 return 1;
172 static struct ebt_u_match vlan_match = {
173 .name = "vlan",
174 .size = sizeof(struct ebt_vlan_info),
175 .help = print_help,
176 .init = init,
177 .parse = parse,
178 .final_check = final_check,
179 .print = print,
180 .compare = compare,
181 .extra_ops = opts,
184 void _init(void)
186 ebt_register_match(&vlan_match);