Commit 420788a6 authored by Bart De Schuymer's avatar Bart De Schuymer Committed by David S. Miller

[BRIDGE]: Let {ip,arp}tables see bridged VLAN packets.

parent 4044a3f8
...@@ -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;
......
...@@ -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
......
...@@ -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;
......
...@@ -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);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment