Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
420788a6
Commit
420788a6
authored
Oct 07, 2003
by
Bart De Schuymer
Committed by
David S. Miller
Oct 07, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[BRIDGE]: Let {ip,arp}tables see bridged VLAN packets.
parent
4044a3f8
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
158 additions
and
29 deletions
+158
-29
include/linux/netfilter_bridge.h
include/linux/netfilter_bridge.h
+34
-0
include/linux/skbuff.h
include/linux/skbuff.h
+4
-1
net/8021q/vlan_dev.c
net/8021q/vlan_dev.c
+4
-0
net/bridge/br_forward.c
net/bridge/br_forward.c
+1
-2
net/bridge/br_netfilter.c
net/bridge/br_netfilter.c
+115
-26
No files found.
include/linux/netfilter_bridge.h
View file @
420788a6
...
@@ -8,6 +8,9 @@
...
@@ -8,6 +8,9 @@
#include <linux/netfilter.h>
#include <linux/netfilter.h>
#if defined(__KERNEL__) && defined(CONFIG_BRIDGE_NETFILTER)
#if defined(__KERNEL__) && defined(CONFIG_BRIDGE_NETFILTER)
#include <asm/atomic.h>
#include <asm/atomic.h>
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#include <linux/if_ether.h>
#endif
#endif
#endif
/* Bridge Hooks */
/* Bridge Hooks */
...
@@ -44,6 +47,7 @@ enum nf_br_hook_priorities {
...
@@ -44,6 +47,7 @@ enum nf_br_hook_priorities {
#define BRNF_BRIDGED_DNAT 0x02
#define BRNF_BRIDGED_DNAT 0x02
#define BRNF_DONT_TAKE_PARENT 0x04
#define BRNF_DONT_TAKE_PARENT 0x04
#define BRNF_BRIDGED 0x08
#define BRNF_BRIDGED 0x08
#define BRNF_NF_BRIDGE_PREROUTING 0x10
static
inline
static
inline
struct
nf_bridge_info
*
nf_bridge_alloc
(
struct
sk_buff
*
skb
)
struct
nf_bridge_info
*
nf_bridge_alloc
(
struct
sk_buff
*
skb
)
...
@@ -54,11 +58,41 @@ struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
...
@@ -54,11 +58,41 @@ struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
atomic_set
(
&
(
*
nf_bridge
)
->
use
,
1
);
atomic_set
(
&
(
*
nf_bridge
)
->
use
,
1
);
(
*
nf_bridge
)
->
mask
=
0
;
(
*
nf_bridge
)
->
mask
=
0
;
(
*
nf_bridge
)
->
physindev
=
(
*
nf_bridge
)
->
physoutdev
=
NULL
;
(
*
nf_bridge
)
->
physindev
=
(
*
nf_bridge
)
->
physoutdev
=
NULL
;
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
(
*
nf_bridge
)
->
netoutdev
=
NULL
;
#endif
}
}
return
*
nf_bridge
;
return
*
nf_bridge
;
}
}
/* Only used in br_forward.c */
static
inline
void
nf_bridge_maybe_copy_header
(
struct
sk_buff
*
skb
)
{
if
(
skb
->
nf_bridge
)
{
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
if
(
skb
->
protocol
==
__constant_htons
(
ETH_P_8021Q
))
{
memcpy
(
skb
->
data
-
18
,
skb
->
nf_bridge
->
hh
,
18
);
skb_push
(
skb
,
4
);
}
else
#endif
memcpy
(
skb
->
data
-
16
,
skb
->
nf_bridge
->
hh
,
16
);
}
}
static
inline
void
nf_bridge_save_header
(
struct
sk_buff
*
skb
)
{
int
header_size
=
16
;
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
if
(
skb
->
protocol
==
__constant_htons
(
ETH_P_8021Q
))
header_size
=
18
;
#endif
memcpy
(
skb
->
nf_bridge
->
hh
,
skb
->
data
-
header_size
,
header_size
);
}
struct
bridge_skb_cb
{
struct
bridge_skb_cb
{
union
{
union
{
__u32
ipv4
;
__u32
ipv4
;
...
...
include/linux/skbuff.h
View file @
420788a6
...
@@ -103,8 +103,11 @@ struct nf_bridge_info {
...
@@ -103,8 +103,11 @@ struct nf_bridge_info {
atomic_t
use
;
atomic_t
use
;
struct
net_device
*
physindev
;
struct
net_device
*
physindev
;
struct
net_device
*
physoutdev
;
struct
net_device
*
physoutdev
;
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
struct
net_device
*
netoutdev
;
#endif
unsigned
int
mask
;
unsigned
int
mask
;
unsigned
long
hh
[
16
/
sizeof
(
unsigned
long
)];
unsigned
long
hh
[
32
/
sizeof
(
unsigned
long
)];
};
};
#endif
#endif
...
...
net/8021q/vlan_dev.c
View file @
420788a6
...
@@ -502,6 +502,10 @@ int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
...
@@ -502,6 +502,10 @@ int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
stats
->
tx_packets
++
;
/* for statics only */
stats
->
tx_packets
++
;
/* for statics only */
stats
->
tx_bytes
+=
skb
->
len
;
stats
->
tx_bytes
+=
skb
->
len
;
skb
->
protocol
=
__constant_htons
(
ETH_P_8021Q
);
skb
->
mac
.
raw
-=
VLAN_HLEN
;
skb
->
nh
.
raw
-=
VLAN_HLEN
;
dev_queue_xmit
(
skb
);
dev_queue_xmit
(
skb
);
return
0
;
return
0
;
...
...
net/bridge/br_forward.c
View file @
420788a6
...
@@ -35,8 +35,7 @@ int br_dev_queue_push_xmit(struct sk_buff *skb)
...
@@ -35,8 +35,7 @@ int br_dev_queue_push_xmit(struct sk_buff *skb)
{
{
#ifdef CONFIG_BRIDGE_NETFILTER
#ifdef CONFIG_BRIDGE_NETFILTER
/* ip_refrag calls ip_fragment, which doesn't copy the MAC header. */
/* ip_refrag calls ip_fragment, which doesn't copy the MAC header. */
if
(
skb
->
nf_bridge
)
nf_bridge_maybe_copy_header
(
skb
);
memcpy
(
skb
->
data
-
16
,
skb
->
nf_bridge
->
hh
,
16
);
#endif
#endif
skb_push
(
skb
,
ETH_HLEN
);
skb_push
(
skb
,
ETH_HLEN
);
...
...
net/bridge/br_netfilter.c
View file @
420788a6
...
@@ -4,7 +4,13 @@
...
@@ -4,7 +4,13 @@
*
*
* Authors:
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
* Lennert Buytenhek <buytenh@gnu.org>
* Bart De Schuymer <bdschuym@pandora.be>
* Bart De Schuymer (maintainer) <bdschuym@pandora.be>
*
* Changes:
* Apr 29 2003: physdev module support (bdschuym)
* Jun 19 2003: let arptables see bridged ARP traffic (bdschuym)
* Oct 06 2003: filter encapsulated IP/ARP VLAN traffic on untagged bridge
* (bdschuym)
*
*
* This program is free software; you can redistribute it and/or
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* modify it under the terms of the GNU General Public License
...
@@ -20,6 +26,7 @@
...
@@ -20,6 +26,7 @@
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/skbuff.h>
#include <linux/if_ether.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/netfilter_bridge.h>
#include <linux/netfilter_bridge.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_arp.h>
#include <linux/netfilter_arp.h>
...
@@ -40,6 +47,11 @@
...
@@ -40,6 +47,11 @@
#define has_bridge_parent(device) ((device)->br_port != NULL)
#define has_bridge_parent(device) ((device)->br_port != NULL)
#define bridge_parent(device) ((device)->br_port->br->dev)
#define bridge_parent(device) ((device)->br_port->br->dev)
#define IS_VLAN_IP (skb->protocol == __constant_htons(ETH_P_8021Q) && \
hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP))
#define IS_VLAN_ARP (skb->protocol == __constant_htons(ETH_P_8021Q) && \
hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_ARP))
/* We need these fake structures to make netfilter happy --
/* We need these fake structures to make netfilter happy --
* lots of places assume that skb->dst != NULL, which isn't
* lots of places assume that skb->dst != NULL, which isn't
* all that unreasonable.
* all that unreasonable.
...
@@ -135,8 +147,13 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
...
@@ -135,8 +147,13 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
skb
->
pkt_type
=
PACKET_HOST
;
skb
->
pkt_type
=
PACKET_HOST
;
skb
->
nf_bridge
->
mask
|=
BRNF_PKT_TYPE
;
skb
->
nf_bridge
->
mask
|=
BRNF_PKT_TYPE
;
}
}
skb
->
nf_bridge
->
mask
^=
BRNF_NF_BRIDGE_PREROUTING
;
skb
->
dev
=
bridge_parent
(
skb
->
dev
);
skb
->
dev
=
bridge_parent
(
skb
->
dev
);
if
(
skb
->
protocol
==
__constant_htons
(
ETH_P_8021Q
))
{
skb_pull
(
skb
,
VLAN_HLEN
);
skb
->
nh
.
raw
+=
VLAN_HLEN
;
}
skb
->
dst
->
output
(
skb
);
skb
->
dst
->
output
(
skb
);
return
0
;
return
0
;
}
}
...
@@ -155,6 +172,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
...
@@ -155,6 +172,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
skb
->
pkt_type
=
PACKET_OTHERHOST
;
skb
->
pkt_type
=
PACKET_OTHERHOST
;
nf_bridge
->
mask
^=
BRNF_PKT_TYPE
;
nf_bridge
->
mask
^=
BRNF_PKT_TYPE
;
}
}
nf_bridge
->
mask
^=
BRNF_NF_BRIDGE_PREROUTING
;
if
(
dnat_took_place
(
skb
))
{
if
(
dnat_took_place
(
skb
))
{
if
(
ip_route_input
(
skb
,
iph
->
daddr
,
iph
->
saddr
,
iph
->
tos
,
if
(
ip_route_input
(
skb
,
iph
->
daddr
,
iph
->
saddr
,
iph
->
tos
,
...
@@ -186,6 +204,11 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
...
@@ -186,6 +204,11 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
nf_bridge
->
mask
|=
BRNF_BRIDGED_DNAT
;
nf_bridge
->
mask
|=
BRNF_BRIDGED_DNAT
;
skb
->
dev
=
nf_bridge
->
physindev
;
skb
->
dev
=
nf_bridge
->
physindev
;
clear_cb
(
skb
);
clear_cb
(
skb
);
if
(
skb
->
protocol
==
__constant_htons
(
ETH_P_8021Q
))
{
skb_push
(
skb
,
VLAN_HLEN
);
skb
->
nh
.
raw
-=
VLAN_HLEN
;
}
NF_HOOK_THRESH
(
PF_BRIDGE
,
NF_BR_PRE_ROUTING
,
NF_HOOK_THRESH
(
PF_BRIDGE
,
NF_BR_PRE_ROUTING
,
skb
,
skb
->
dev
,
NULL
,
skb
,
skb
->
dev
,
NULL
,
br_nf_pre_routing_finish_bridge
,
br_nf_pre_routing_finish_bridge
,
...
@@ -202,6 +225,10 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
...
@@ -202,6 +225,10 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
clear_cb
(
skb
);
clear_cb
(
skb
);
skb
->
dev
=
nf_bridge
->
physindev
;
skb
->
dev
=
nf_bridge
->
physindev
;
if
(
skb
->
protocol
==
__constant_htons
(
ETH_P_8021Q
))
{
skb_push
(
skb
,
VLAN_HLEN
);
skb
->
nh
.
raw
-=
VLAN_HLEN
;
}
NF_HOOK_THRESH
(
PF_BRIDGE
,
NF_BR_PRE_ROUTING
,
skb
,
skb
->
dev
,
NULL
,
NF_HOOK_THRESH
(
PF_BRIDGE
,
NF_BR_PRE_ROUTING
,
skb
,
skb
->
dev
,
NULL
,
br_handle_frame_finish
,
1
);
br_handle_frame_finish
,
1
);
...
@@ -220,13 +247,20 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
...
@@ -220,13 +247,20 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
{
{
struct
iphdr
*
iph
;
struct
iphdr
*
iph
;
__u32
len
;
__u32
len
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
=
*
pskb
;
struct
nf_bridge_info
*
nf_bridge
;
struct
nf_bridge_info
*
nf_bridge
;
if
((
*
pskb
)
->
protocol
!=
__constant_htons
(
ETH_P_IP
))
if
(
skb
->
protocol
!=
__constant_htons
(
ETH_P_IP
))
{
return
NF_ACCEPT
;
struct
vlan_ethhdr
*
hdr
=
(
struct
vlan_ethhdr
*
)
((
*
pskb
)
->
mac
.
ethernet
);
if
((
skb
=
skb_share_check
(
*
pskb
,
GFP_ATOMIC
))
==
NULL
)
if
(
!
IS_VLAN_IP
)
return
NF_ACCEPT
;
if
((
skb
=
skb_share_check
(
*
pskb
,
GFP_ATOMIC
))
==
NULL
)
goto
out
;
skb_pull
(
*
pskb
,
VLAN_HLEN
);
(
*
pskb
)
->
nh
.
raw
+=
VLAN_HLEN
;
}
else
if
((
skb
=
skb_share_check
(
*
pskb
,
GFP_ATOMIC
))
==
NULL
)
goto
out
;
goto
out
;
if
(
!
pskb_may_pull
(
skb
,
sizeof
(
struct
iphdr
)))
if
(
!
pskb_may_pull
(
skb
,
sizeof
(
struct
iphdr
)))
...
@@ -264,6 +298,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
...
@@ -264,6 +298,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
nf_bridge
->
mask
|=
BRNF_PKT_TYPE
;
nf_bridge
->
mask
|=
BRNF_PKT_TYPE
;
}
}
nf_bridge
->
mask
|=
BRNF_NF_BRIDGE_PREROUTING
;
nf_bridge
->
physindev
=
skb
->
dev
;
nf_bridge
->
physindev
=
skb
->
dev
;
skb
->
dev
=
bridge_parent
(
skb
->
dev
);
skb
->
dev
=
bridge_parent
(
skb
->
dev
);
store_orig_dstaddr
(
skb
);
store_orig_dstaddr
(
skb
);
...
@@ -294,9 +329,6 @@ static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb,
...
@@ -294,9 +329,6 @@ static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb,
{
{
struct
sk_buff
*
skb
=
*
pskb
;
struct
sk_buff
*
skb
=
*
pskb
;
if
(
skb
->
protocol
!=
__constant_htons
(
ETH_P_IP
))
return
NF_ACCEPT
;
if
(
skb
->
dst
==
(
struct
dst_entry
*
)
&
__fake_rtable
)
{
if
(
skb
->
dst
==
(
struct
dst_entry
*
)
&
__fake_rtable
)
{
dst_release
(
skb
->
dst
);
dst_release
(
skb
->
dst
);
skb
->
dst
=
NULL
;
skb
->
dst
=
NULL
;
...
@@ -310,12 +342,13 @@ static int br_nf_forward_finish(struct sk_buff *skb)
...
@@ -310,12 +342,13 @@ static int br_nf_forward_finish(struct sk_buff *skb)
{
{
struct
nf_bridge_info
*
nf_bridge
=
skb
->
nf_bridge
;
struct
nf_bridge_info
*
nf_bridge
=
skb
->
nf_bridge
;
struct
net_device
*
in
;
struct
net_device
*
in
;
struct
vlan_ethhdr
*
hdr
=
(
struct
vlan_ethhdr
*
)(
skb
->
mac
.
ethernet
);
#ifdef CONFIG_NETFILTER_DEBUG
#ifdef CONFIG_NETFILTER_DEBUG
skb
->
nf_debug
^=
(
1
<<
NF_BR_FORWARD
);
skb
->
nf_debug
^=
(
1
<<
NF_BR_FORWARD
);
#endif
#endif
if
(
skb
->
protocol
==
__constant_htons
(
ETH_P_IP
))
{
if
(
skb
->
protocol
==
__constant_htons
(
ETH_P_IP
)
||
IS_VLAN_IP
)
{
in
=
nf_bridge
->
physindev
;
in
=
nf_bridge
->
physindev
;
if
(
nf_bridge
->
mask
&
BRNF_PKT_TYPE
)
{
if
(
nf_bridge
->
mask
&
BRNF_PKT_TYPE
)
{
skb
->
pkt_type
=
PACKET_OTHERHOST
;
skb
->
pkt_type
=
PACKET_OTHERHOST
;
...
@@ -324,7 +357,10 @@ static int br_nf_forward_finish(struct sk_buff *skb)
...
@@ -324,7 +357,10 @@ static int br_nf_forward_finish(struct sk_buff *skb)
}
else
{
}
else
{
in
=
*
((
struct
net_device
**
)(
skb
->
cb
));
in
=
*
((
struct
net_device
**
)(
skb
->
cb
));
}
}
if
(
skb
->
protocol
==
__constant_htons
(
ETH_P_8021Q
))
{
skb_push
(
skb
,
VLAN_HLEN
);
skb
->
nh
.
raw
-=
VLAN_HLEN
;
}
NF_HOOK_THRESH
(
PF_BRIDGE
,
NF_BR_FORWARD
,
skb
,
in
,
NF_HOOK_THRESH
(
PF_BRIDGE
,
NF_BR_FORWARD
,
skb
,
in
,
skb
->
dev
,
br_forward_finish
,
1
);
skb
->
dev
,
br_forward_finish
,
1
);
return
0
;
return
0
;
...
@@ -342,15 +378,20 @@ static unsigned int br_nf_forward(unsigned int hook, struct sk_buff **pskb,
...
@@ -342,15 +378,20 @@ static unsigned int br_nf_forward(unsigned int hook, struct sk_buff **pskb,
{
{
struct
sk_buff
*
skb
=
*
pskb
;
struct
sk_buff
*
skb
=
*
pskb
;
struct
nf_bridge_info
*
nf_bridge
;
struct
nf_bridge_info
*
nf_bridge
;
struct
vlan_ethhdr
*
hdr
=
(
struct
vlan_ethhdr
*
)(
skb
->
mac
.
ethernet
);
if
(
skb
->
protocol
!=
__constant_htons
(
ETH_P_IP
)
&&
if
(
skb
->
protocol
!=
__constant_htons
(
ETH_P_IP
)
&&
skb
->
protocol
!=
__constant_htons
(
ETH_P_ARP
))
skb
->
protocol
!=
__constant_htons
(
ETH_P_ARP
))
{
return
NF_ACCEPT
;
if
(
!
IS_VLAN_IP
&&
!
IS_VLAN_ARP
)
return
NF_ACCEPT
;
skb_pull
(
*
pskb
,
VLAN_HLEN
);
(
*
pskb
)
->
nh
.
raw
+=
VLAN_HLEN
;
}
#ifdef CONFIG_NETFILTER_DEBUG
#ifdef CONFIG_NETFILTER_DEBUG
skb
->
nf_debug
^=
(
1
<<
NF_BR_FORWARD
);
skb
->
nf_debug
^=
(
1
<<
NF_BR_FORWARD
);
#endif
#endif
if
(
skb
->
protocol
==
__constant_htons
(
ETH_P_IP
))
{
if
(
skb
->
protocol
==
__constant_htons
(
ETH_P_IP
)
||
IS_VLAN_IP
)
{
nf_bridge
=
skb
->
nf_bridge
;
nf_bridge
=
skb
->
nf_bridge
;
if
(
skb
->
pkt_type
==
PACKET_OTHERHOST
)
{
if
(
skb
->
pkt_type
==
PACKET_OTHERHOST
)
{
skb
->
pkt_type
=
PACKET_HOST
;
skb
->
pkt_type
=
PACKET_HOST
;
...
@@ -365,7 +406,15 @@ static unsigned int br_nf_forward(unsigned int hook, struct sk_buff **pskb,
...
@@ -365,7 +406,15 @@ static unsigned int br_nf_forward(unsigned int hook, struct sk_buff **pskb,
bridge_parent
(
out
),
br_nf_forward_finish
);
bridge_parent
(
out
),
br_nf_forward_finish
);
}
else
{
}
else
{
struct
net_device
**
d
=
(
struct
net_device
**
)(
skb
->
cb
);
struct
net_device
**
d
=
(
struct
net_device
**
)(
skb
->
cb
);
struct
arphdr
*
arp
=
skb
->
nh
.
arph
;
if
(
arp
->
ar_pln
!=
4
)
{
if
(
IS_VLAN_ARP
)
{
skb_push
(
*
pskb
,
VLAN_HLEN
);
(
*
pskb
)
->
nh
.
raw
-=
VLAN_HLEN
;
}
return
NF_ACCEPT
;
}
*
d
=
(
struct
net_device
*
)
in
;
*
d
=
(
struct
net_device
*
)
in
;
NF_HOOK
(
NF_ARP
,
NF_ARP_FORWARD
,
skb
,
(
struct
net_device
*
)
in
,
NF_HOOK
(
NF_ARP
,
NF_ARP_FORWARD
,
skb
,
(
struct
net_device
*
)
in
,
(
struct
net_device
*
)
out
,
br_nf_forward_finish
);
(
struct
net_device
*
)
out
,
br_nf_forward_finish
);
...
@@ -381,6 +430,10 @@ static int br_nf_local_out_finish(struct sk_buff *skb)
...
@@ -381,6 +430,10 @@ static int br_nf_local_out_finish(struct sk_buff *skb)
#ifdef CONFIG_NETFILTER_DEBUG
#ifdef CONFIG_NETFILTER_DEBUG
skb
->
nf_debug
&=
~
(
1
<<
NF_BR_LOCAL_OUT
);
skb
->
nf_debug
&=
~
(
1
<<
NF_BR_LOCAL_OUT
);
#endif
#endif
if
(
skb
->
protocol
==
__constant_htons
(
ETH_P_8021Q
))
{
skb_push
(
skb
,
VLAN_HLEN
);
skb
->
nh
.
raw
-=
VLAN_HLEN
;
}
NF_HOOK_THRESH
(
PF_BRIDGE
,
NF_BR_LOCAL_OUT
,
skb
,
NULL
,
skb
->
dev
,
NF_HOOK_THRESH
(
PF_BRIDGE
,
NF_BR_LOCAL_OUT
,
skb
,
NULL
,
skb
->
dev
,
br_forward_finish
,
NF_BR_PRI_FIRST
+
1
);
br_forward_finish
,
NF_BR_PRI_FIRST
+
1
);
...
@@ -419,8 +472,9 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
...
@@ -419,8 +472,9 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
struct
net_device
*
realindev
;
struct
net_device
*
realindev
;
struct
sk_buff
*
skb
=
*
pskb
;
struct
sk_buff
*
skb
=
*
pskb
;
struct
nf_bridge_info
*
nf_bridge
;
struct
nf_bridge_info
*
nf_bridge
;
struct
vlan_ethhdr
*
hdr
=
(
struct
vlan_ethhdr
*
)(
skb
->
mac
.
ethernet
);
if
(
skb
->
protocol
!=
__constant_htons
(
ETH_P_IP
))
if
(
skb
->
protocol
!=
__constant_htons
(
ETH_P_IP
)
&&
!
IS_VLAN_IP
)
return
NF_ACCEPT
;
return
NF_ACCEPT
;
/* Sometimes we get packets with NULL ->dst here (for example,
/* Sometimes we get packets with NULL ->dst here (for example,
...
@@ -444,11 +498,26 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
...
@@ -444,11 +498,26 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
skb
->
pkt_type
=
PACKET_OTHERHOST
;
skb
->
pkt_type
=
PACKET_OTHERHOST
;
nf_bridge
->
mask
^=
BRNF_PKT_TYPE
;
nf_bridge
->
mask
^=
BRNF_PKT_TYPE
;
}
}
if
(
skb
->
protocol
==
__constant_htons
(
ETH_P_8021Q
))
{
skb_push
(
skb
,
VLAN_HLEN
);
skb
->
nh
.
raw
-=
VLAN_HLEN
;
}
NF_HOOK
(
PF_BRIDGE
,
NF_BR_FORWARD
,
skb
,
realindev
,
NF_HOOK
(
PF_BRIDGE
,
NF_BR_FORWARD
,
skb
,
realindev
,
skb
->
dev
,
okfn
);
skb
->
dev
,
okfn
);
}
else
{
}
else
{
struct
net_device
*
realoutdev
=
bridge_parent
(
skb
->
dev
);
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
/* iptables should match -o br0.x */
if
(
nf_bridge
->
netoutdev
)
realoutdev
=
nf_bridge
->
netoutdev
;
#endif
okfn
=
br_nf_local_out_finish
;
okfn
=
br_nf_local_out_finish
;
if
(
skb
->
protocol
==
__constant_htons
(
ETH_P_8021Q
))
{
skb_pull
(
skb
,
VLAN_HLEN
);
(
*
pskb
)
->
nh
.
raw
+=
VLAN_HLEN
;
}
/* IP forwarded traffic has a physindev, locally
/* IP forwarded traffic has a physindev, locally
* generated traffic hasn't.
* generated traffic hasn't.
*/
*/
...
@@ -456,9 +525,8 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
...
@@ -456,9 +525,8 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
if
(((
nf_bridge
->
mask
&
BRNF_DONT_TAKE_PARENT
)
==
0
)
&&
if
(((
nf_bridge
->
mask
&
BRNF_DONT_TAKE_PARENT
)
==
0
)
&&
has_bridge_parent
(
realindev
))
has_bridge_parent
(
realindev
))
realindev
=
bridge_parent
(
realindev
);
realindev
=
bridge_parent
(
realindev
);
NF_HOOK_THRESH
(
PF_INET
,
NF_IP_FORWARD
,
skb
,
realindev
,
NF_HOOK_THRESH
(
PF_INET
,
NF_IP_FORWARD
,
skb
,
realindev
,
bridge_parent
(
skb
->
dev
)
,
okfn
,
realoutdev
,
okfn
,
NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD
+
1
);
NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD
+
1
);
}
else
{
}
else
{
#ifdef CONFIG_NETFILTER_DEBUG
#ifdef CONFIG_NETFILTER_DEBUG
...
@@ -466,7 +534,7 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
...
@@ -466,7 +534,7 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
#endif
#endif
NF_HOOK_THRESH
(
PF_INET
,
NF_IP_LOCAL_OUT
,
skb
,
realindev
,
NF_HOOK_THRESH
(
PF_INET
,
NF_IP_LOCAL_OUT
,
skb
,
realindev
,
bridge_parent
(
skb
->
dev
)
,
okfn
,
realoutdev
,
okfn
,
NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT
+
1
);
NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT
+
1
);
}
}
}
}
...
@@ -482,6 +550,8 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
...
@@ -482,6 +550,8 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
{
{
struct
sk_buff
*
skb
=
*
pskb
;
struct
sk_buff
*
skb
=
*
pskb
;
struct
nf_bridge_info
*
nf_bridge
=
(
*
pskb
)
->
nf_bridge
;
struct
nf_bridge_info
*
nf_bridge
=
(
*
pskb
)
->
nf_bridge
;
struct
vlan_ethhdr
*
hdr
=
(
struct
vlan_ethhdr
*
)(
skb
->
mac
.
ethernet
);
struct
net_device
*
realoutdev
=
bridge_parent
(
skb
->
dev
);
/* Be very paranoid. Must be a device driver bug. */
/* Be very paranoid. Must be a device driver bug. */
if
(
skb
->
mac
.
raw
<
skb
->
head
||
skb
->
mac
.
raw
+
ETH_HLEN
>
skb
->
data
)
{
if
(
skb
->
mac
.
raw
<
skb
->
head
||
skb
->
mac
.
raw
+
ETH_HLEN
>
skb
->
data
)
{
...
@@ -492,11 +562,11 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
...
@@ -492,11 +562,11 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
if
(
has_bridge_parent
(
skb
->
dev
))
if
(
has_bridge_parent
(
skb
->
dev
))
printk
(
"[%s]"
,
bridge_parent
(
skb
->
dev
)
->
name
);
printk
(
"[%s]"
,
bridge_parent
(
skb
->
dev
)
->
name
);
}
}
printk
(
"
\n
"
);
printk
(
"
head:%p, raw:%p
\n
"
,
skb
->
head
,
skb
->
mac
.
raw
);
return
NF_ACCEPT
;
return
NF_ACCEPT
;
}
}
if
(
skb
->
protocol
!=
__constant_htons
(
ETH_P_IP
))
if
(
skb
->
protocol
!=
__constant_htons
(
ETH_P_IP
)
&&
!
IS_VLAN_IP
)
return
NF_ACCEPT
;
return
NF_ACCEPT
;
/* Sometimes we get packets with NULL ->dst here (for example,
/* Sometimes we get packets with NULL ->dst here (for example,
...
@@ -517,10 +587,19 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
...
@@ -517,10 +587,19 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
nf_bridge
->
mask
|=
BRNF_PKT_TYPE
;
nf_bridge
->
mask
|=
BRNF_PKT_TYPE
;
}
}
memcpy
(
nf_bridge
->
hh
,
skb
->
data
-
16
,
16
);
if
(
skb
->
protocol
==
__constant_htons
(
ETH_P_8021Q
))
{
skb_pull
(
skb
,
VLAN_HLEN
);
skb
->
nh
.
raw
+=
VLAN_HLEN
;
}
nf_bridge_save_header
(
skb
);
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
if
(
nf_bridge
->
netoutdev
)
realoutdev
=
nf_bridge
->
netoutdev
;
#endif
NF_HOOK
(
PF_INET
,
NF_IP_POST_ROUTING
,
skb
,
NULL
,
NF_HOOK
(
PF_INET
,
NF_IP_POST_ROUTING
,
skb
,
NULL
,
bridge_parent
(
skb
->
dev
)
,
br_dev_queue_push_xmit
);
realoutdev
,
br_dev_queue_push_xmit
);
return
NF_STOLEN
;
return
NF_STOLEN
;
}
}
...
@@ -535,8 +614,8 @@ static unsigned int ipv4_sabotage_in(unsigned int hook, struct sk_buff **pskb,
...
@@ -535,8 +614,8 @@ static unsigned int ipv4_sabotage_in(unsigned int hook, struct sk_buff **pskb,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
int
(
*
okfn
)(
struct
sk_buff
*
))
int
(
*
okfn
)(
struct
sk_buff
*
))
{
{
if
(
in
->
hard_start_xmit
==
br_dev_xmit
&&
if
(
(
*
pskb
)
->
nf_bridge
&&
okfn
!=
br_nf_pre_routing_finish
)
{
!
((
*
pskb
)
->
nf_bridge
->
mask
&
BRNF_NF_BRIDGE_PREROUTING
)
)
{
okfn
(
*
pskb
);
okfn
(
*
pskb
);
return
NF_STOLEN
;
return
NF_STOLEN
;
}
}
...
@@ -552,10 +631,15 @@ static unsigned int ipv4_sabotage_out(unsigned int hook, struct sk_buff **pskb,
...
@@ -552,10 +631,15 @@ static unsigned int ipv4_sabotage_out(unsigned int hook, struct sk_buff **pskb,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
const
struct
net_device
*
in
,
const
struct
net_device
*
out
,
int
(
*
okfn
)(
struct
sk_buff
*
))
int
(
*
okfn
)(
struct
sk_buff
*
))
{
{
if
(
out
->
hard_start_xmit
==
br_dev_xmit
&&
if
(
(
out
->
hard_start_xmit
==
br_dev_xmit
&&
okfn
!=
br_nf_forward_finish
&&
okfn
!=
br_nf_forward_finish
&&
okfn
!=
br_nf_local_out_finish
&&
okfn
!=
br_nf_local_out_finish
&&
okfn
!=
br_dev_queue_push_xmit
)
{
okfn
!=
br_dev_queue_push_xmit
)
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
||
((
out
->
priv_flags
&
IFF_802_1Q_VLAN
)
&&
VLAN_DEV_INFO
(
out
)
->
real_dev
->
hard_start_xmit
==
br_dev_xmit
)
#endif
)
{
struct
sk_buff
*
skb
=
*
pskb
;
struct
sk_buff
*
skb
=
*
pskb
;
struct
nf_bridge_info
*
nf_bridge
;
struct
nf_bridge_info
*
nf_bridge
;
...
@@ -574,6 +658,11 @@ static unsigned int ipv4_sabotage_out(unsigned int hook, struct sk_buff **pskb,
...
@@ -574,6 +658,11 @@ static unsigned int ipv4_sabotage_out(unsigned int hook, struct sk_buff **pskb,
nf_bridge
->
mask
&=
BRNF_DONT_TAKE_PARENT
;
nf_bridge
->
mask
&=
BRNF_DONT_TAKE_PARENT
;
nf_bridge
->
physindev
=
(
struct
net_device
*
)
in
;
nf_bridge
->
physindev
=
(
struct
net_device
*
)
in
;
}
}
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
/* the iptables outdev is br0.x, not br0 */
if
(
out
->
priv_flags
&
IFF_802_1Q_VLAN
)
nf_bridge
->
netoutdev
=
(
struct
net_device
*
)
out
;
#endif
okfn
(
skb
);
okfn
(
skb
);
return
NF_STOLEN
;
return
NF_STOLEN
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment