Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
net
bridge
netfilter
ebt_vlan.c
Go to the documentation of this file.
1
/*
2
* Description: EBTables 802.1Q match extension kernelspace module.
3
* Authors: Nick Fedchik <
[email protected]
>
4
* Bart De Schuymer <
[email protected]
>
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
*/
20
21
#include <linux/if_ether.h>
22
#include <linux/if_vlan.h>
23
#include <linux/module.h>
24
#include <
linux/moduleparam.h
>
25
#include <linux/netfilter/x_tables.h>
26
#include <linux/netfilter_bridge/ebtables.h>
27
#include <
linux/netfilter_bridge/ebt_vlan.h
>
28
29
#define MODULE_VERS "0.6"
30
31
MODULE_AUTHOR
(
"Nick Fedchik <
[email protected]
>"
);
32
MODULE_DESCRIPTION
(
"Ebtables: 802.1Q VLAN tag match"
);
33
MODULE_LICENSE
(
"GPL"
);
34
35
#define GET_BITMASK(_BIT_MASK_) info->bitmask & _BIT_MASK_
36
#define EXIT_ON_MISMATCH(_MATCH_,_MASK_) {if (!((info->_MATCH_ == _MATCH_)^!!(info->invflags & _MASK_))) return false; }
37
38
static
bool
39
ebt_vlan_mt(
const
struct
sk_buff
*
skb
,
struct
xt_action_param
*par)
40
{
41
const
struct
ebt_vlan_info
*
info
= par->
matchinfo
;
42
43
unsigned
short
TCI;
/* Whole TCI, given from parsed frame */
44
unsigned
short
id
;
/* VLAN ID, given from frame TCI */
45
unsigned
char
prio
;
/* user_priority, given from frame TCI */
46
/* VLAN encapsulated Type/Length field, given from orig frame */
47
__be16
encap
;
48
49
if
(
vlan_tx_tag_present
(skb)) {
50
TCI =
vlan_tx_tag_get
(skb);
51
encap = skb->
protocol
;
52
}
else
{
53
const
struct
vlan_hdr
*
fp
;
54
struct
vlan_hdr
_frame;
55
56
fp = skb_header_pointer(skb, 0,
sizeof
(_frame), &_frame);
57
if
(fp ==
NULL
)
58
return
false
;
59
60
TCI =
ntohs
(fp->h_vlan_TCI);
61
encap = fp->h_vlan_encapsulated_proto;
62
}
63
64
/* Tag Control Information (TCI) consists of the following elements:
65
* - User_priority. The user_priority field is three bits in length,
66
* interpreted as a binary number.
67
* - Canonical Format Indicator (CFI). The Canonical Format Indicator
68
* (CFI) is a single bit flag value. Currently ignored.
69
* - VLAN Identifier (VID). The VID is encoded as
70
* an unsigned binary number. */
71
id
= TCI &
VLAN_VID_MASK
;
72
prio = (TCI >> 13) & 0x7;
73
74
/* Checking VLAN Identifier (VID) */
75
if
(
GET_BITMASK
(
EBT_VLAN_ID
))
76
EXIT_ON_MISMATCH
(
id
,
EBT_VLAN_ID
);
77
78
/* Checking user_priority */
79
if
(
GET_BITMASK
(
EBT_VLAN_PRIO
))
80
EXIT_ON_MISMATCH
(prio,
EBT_VLAN_PRIO
);
81
82
/* Checking Encapsulated Proto (Length/Type) field */
83
if
(
GET_BITMASK
(
EBT_VLAN_ENCAP
))
84
EXIT_ON_MISMATCH
(encap,
EBT_VLAN_ENCAP
);
85
86
return
true
;
87
}
88
89
static
int
ebt_vlan_mt_check(
const
struct
xt_mtchk_param
*par)
90
{
91
struct
ebt_vlan_info
*
info
= par->
matchinfo
;
92
const
struct
ebt_entry
*
e
= par->
entryinfo
;
93
94
/* Is it 802.1Q frame checked? */
95
if
(e->
ethproto
!=
htons
(
ETH_P_8021Q
)) {
96
pr_debug
(
"passed entry proto %2.4X is not 802.1Q (8100)\n"
,
97
ntohs
(e->
ethproto
));
98
return
-
EINVAL
;
99
}
100
101
/* Check for bitmask range
102
* True if even one bit is out of mask */
103
if
(info->
bitmask
& ~
EBT_VLAN_MASK
) {
104
pr_debug
(
"bitmask %2X is out of mask (%2X)\n"
,
105
info->
bitmask
,
EBT_VLAN_MASK
);
106
return
-
EINVAL
;
107
}
108
109
/* Check for inversion flags range */
110
if
(info->
invflags
& ~
EBT_VLAN_MASK
) {
111
pr_debug
(
"inversion flags %2X is out of mask (%2X)\n"
,
112
info->
invflags
,
EBT_VLAN_MASK
);
113
return
-
EINVAL
;
114
}
115
116
/* Reserved VLAN ID (VID) values
117
* -----------------------------
118
* 0 - The null VLAN ID.
119
* 1 - The default Port VID (PVID)
120
* 0x0FFF - Reserved for implementation use.
121
* if_vlan.h: VLAN_N_VID 4096. */
122
if
(
GET_BITMASK
(
EBT_VLAN_ID
)) {
123
if
(!!info->
id
) {
/* if id!=0 => check vid range */
124
if
(info->
id
>
VLAN_N_VID
) {
125
pr_debug
(
"id %d is out of range (1-4096)\n"
,
126
info->
id
);
127
return
-
EINVAL
;
128
}
129
/* Note: This is valid VLAN-tagged frame point.
130
* Any value of user_priority are acceptable,
131
* but should be ignored according to 802.1Q Std.
132
* So we just drop the prio flag. */
133
info->
bitmask
&= ~
EBT_VLAN_PRIO
;
134
}
135
/* Else, id=0 (null VLAN ID) => user_priority range (any?) */
136
}
137
138
if
(
GET_BITMASK
(
EBT_VLAN_PRIO
)) {
139
if
((
unsigned
char
) info->
prio
> 7) {
140
pr_debug
(
"prio %d is out of range (0-7)\n"
,
141
info->
prio
);
142
return
-
EINVAL
;
143
}
144
}
145
/* Check for encapsulated proto range - it is possible to be
146
* any value for u_short range.
147
* if_ether.h: ETH_ZLEN 60 - Min. octets in frame sans FCS */
148
if
(
GET_BITMASK
(
EBT_VLAN_ENCAP
)) {
149
if
((
unsigned
short
)
ntohs
(info->
encap
) <
ETH_ZLEN
) {
150
pr_debug
(
"encap frame length %d is less than "
151
"minimal\n"
,
ntohs
(info->
encap
));
152
return
-
EINVAL
;
153
}
154
}
155
156
return
0;
157
}
158
159
static
struct
xt_match
ebt_vlan_mt_reg
__read_mostly
= {
160
.name =
"vlan"
,
161
.revision = 0,
162
.family =
NFPROTO_BRIDGE
,
163
.match = ebt_vlan_mt,
164
.checkentry = ebt_vlan_mt_check,
165
.matchsize =
sizeof
(
struct
ebt_vlan_info
),
166
.me =
THIS_MODULE
,
167
};
168
169
static
int
__init
ebt_vlan_init(
void
)
170
{
171
pr_debug
(
"ebtables 802.1Q extension module v"
MODULE_VERS
"\n"
);
172
return
xt_register_match
(&ebt_vlan_mt_reg);
173
}
174
175
static
void
__exit
ebt_vlan_fini(
void
)
176
{
177
xt_unregister_match
(&ebt_vlan_mt_reg);
178
}
179
180
module_init
(ebt_vlan_init);
181
module_exit
(ebt_vlan_fini);
Generated on Thu Jan 10 2013 14:57:13 for Linux Kernel by
1.8.2