memcpy(skb->nf_bridge->data, skb->data - header_size, header_size);
}
+/* 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
+int nf_bridge_pad(struct sk_buff *skb)
+{
+ if (skb->protocol == __constant_htons(ETH_P_IP))
+ return 0;
+ if (skb->nf_bridge) {
+ if (skb->protocol == __constant_htons(ETH_P_8021Q))
+ return 4;
+ }
+ return 0;
+}
+
struct bridge_skb_cb {
union {
__u32 ipv4;
#include <net/inetpeer.h>
#include <linux/igmp.h>
#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_bridge.h>
#include <linux/mroute.h>
#include <linux/netlink.h>
int ptr;
struct net_device *dev;
struct sk_buff *skb2;
- unsigned int mtu, hlen, left, len;
+ unsigned int mtu, hlen, left, len, ll_rs;
int offset;
int not_last_frag;
struct rtable *rt = (struct rtable*)skb->dst;
left = skb->len - hlen; /* Space per frame */
ptr = raw + hlen; /* Where to start from */
+#ifdef CONFIG_BRIDGE_NETFILTER
+ /* for bridged IP traffic encapsulated inside f.e. a vlan header,
+ * we need to make room for the encapsulating header */
+ ll_rs = LL_RESERVED_SPACE(rt->u.dst.dev + nf_bridge_pad(skb));
+ mtu -= nf_bridge_pad(skb);
+#else
+ ll_rs = LL_RESERVED_SPACE(rt->u.dst.dev);
+#endif
/*
* Fragment the datagram.
*/
* Allocate buffer.
*/
- if ((skb2 = alloc_skb(len+hlen+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) {
+ if ((skb2 = alloc_skb(len+hlen+ll_rs, GFP_ATOMIC)) == NULL) {
NETDEBUG(printk(KERN_INFO "IP: frag: no memory for new fragment!\n"));
err = -ENOMEM;
goto fail;
*/
ip_copy_metadata(skb2, skb);
- skb_reserve(skb2, LL_RESERVED_SPACE(rt->u.dst.dev));
+ skb_reserve(skb2, ll_rs);
skb_put(skb2, len + hlen);
skb2->nh.raw = skb2->data;
skb2->h.raw = skb2->data + hlen;