mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 03:10:12 +00:00
![Patrick McHardy](/assets/img/avatar_default.png)
As reported by Damien Thebault, the double POSTROUTING hook invocation fix caused outgoing packets routed between two bridges to appear without a link-layer header. The reason for this is that we're skipping the br_nf_post_routing hook for routed packets now and don't save the original link layer header, but nevertheless tries to restore it on output, causing corruption. The root cause for this is that skb->nf_bridge has no clearly defined lifetime and is used to indicate all kind of things, but that is quite complicated to fix. For now simply don't touch these packets and handle them like packets from any other device. Tested-by: Damien Thebault <damien.thebault@gmail.com> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
92 lines
2.2 KiB
C
92 lines
2.2 KiB
C
#ifndef __LINUX_BRIDGE_NETFILTER_H
|
|
#define __LINUX_BRIDGE_NETFILTER_H
|
|
|
|
/* bridge-specific defines for netfilter.
|
|
*/
|
|
|
|
#include <linux/netfilter.h>
|
|
#include <linux/if_ether.h>
|
|
#include <linux/if_vlan.h>
|
|
#include <linux/if_pppox.h>
|
|
|
|
/* Bridge Hooks */
|
|
/* After promisc drops, checksum checks. */
|
|
#define NF_BR_PRE_ROUTING 0
|
|
/* If the packet is destined for this box. */
|
|
#define NF_BR_LOCAL_IN 1
|
|
/* If the packet is destined for another interface. */
|
|
#define NF_BR_FORWARD 2
|
|
/* Packets coming from a local process. */
|
|
#define NF_BR_LOCAL_OUT 3
|
|
/* Packets about to hit the wire. */
|
|
#define NF_BR_POST_ROUTING 4
|
|
/* Not really a hook, but used for the ebtables broute table */
|
|
#define NF_BR_BROUTING 5
|
|
#define NF_BR_NUMHOOKS 6
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
enum nf_br_hook_priorities {
|
|
NF_BR_PRI_FIRST = INT_MIN,
|
|
NF_BR_PRI_NAT_DST_BRIDGED = -300,
|
|
NF_BR_PRI_FILTER_BRIDGED = -200,
|
|
NF_BR_PRI_BRNF = 0,
|
|
NF_BR_PRI_NAT_DST_OTHER = 100,
|
|
NF_BR_PRI_FILTER_OTHER = 200,
|
|
NF_BR_PRI_NAT_SRC = 300,
|
|
NF_BR_PRI_LAST = INT_MAX,
|
|
};
|
|
|
|
#ifdef CONFIG_BRIDGE_NETFILTER
|
|
|
|
#define BRNF_PKT_TYPE 0x01
|
|
#define BRNF_BRIDGED_DNAT 0x02
|
|
#define BRNF_DONT_TAKE_PARENT 0x04
|
|
#define BRNF_BRIDGED 0x08
|
|
#define BRNF_NF_BRIDGE_PREROUTING 0x10
|
|
|
|
|
|
/* Only used in br_forward.c */
|
|
extern int nf_bridge_copy_header(struct sk_buff *skb);
|
|
static inline int nf_bridge_maybe_copy_header(struct sk_buff *skb)
|
|
{
|
|
if (skb->nf_bridge &&
|
|
skb->nf_bridge->mask & (BRNF_BRIDGED | BRNF_BRIDGED_DNAT))
|
|
return nf_bridge_copy_header(skb);
|
|
return 0;
|
|
}
|
|
|
|
static inline unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb)
|
|
{
|
|
switch (skb->protocol) {
|
|
case __constant_htons(ETH_P_8021Q):
|
|
return VLAN_HLEN;
|
|
case __constant_htons(ETH_P_PPP_SES):
|
|
return PPPOE_SES_HLEN;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* This is called by the IP fragmenting code and it ensures there is
|
|
* enough room for the encapsulating header (if there is one). */
|
|
static inline unsigned int nf_bridge_pad(const struct sk_buff *skb)
|
|
{
|
|
if (skb->nf_bridge)
|
|
return nf_bridge_encap_header_len(skb);
|
|
return 0;
|
|
}
|
|
|
|
struct bridge_skb_cb {
|
|
union {
|
|
__be32 ipv4;
|
|
} daddr;
|
|
};
|
|
|
|
#else
|
|
#define nf_bridge_maybe_copy_header(skb) (0)
|
|
#define nf_bridge_pad(skb) (0)
|
|
#endif /* CONFIG_BRIDGE_NETFILTER */
|
|
|
|
#endif /* __KERNEL__ */
|
|
#endif
|