4 * Bart De Schuymer <bdschuym@pandora.be>
5 * Nick Fedchik <nick@fedchik.org.ua>
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"
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
},
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()
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
;
67 struct ebt_vlan_info local
;
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
;
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
;
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);
96 ethent
= getethertypebyname(optarg
);
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
;
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
);
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
)
158 if (vlaninfo1
->invflags
!= vlaninfo2
->invflags
)
160 if (vlaninfo1
->bitmask
& EBT_VLAN_ID
&&
161 vlaninfo1
->id
!= vlaninfo2
->id
)
163 if (vlaninfo1
->bitmask
& EBT_VLAN_PRIO
&&
164 vlaninfo1
->prio
!= vlaninfo2
->prio
)
166 if (vlaninfo1
->bitmask
& EBT_VLAN_ENCAP
&&
167 vlaninfo1
->encap
!= vlaninfo2
->encap
)
172 static struct ebt_u_match vlan_match
= {
174 .size
= sizeof(struct ebt_vlan_info
),
178 .final_check
= final_check
,
186 ebt_register_match(&vlan_match
);