Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2e2f7aef authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller
Browse files

[NETFILTER]: Fix fragmentation issues with bridge netfilter



The conntrack code doesn't do re-fragmentation of defragmented packets
anymore but relies on fragmentation in the IP layer. Purely bridged
packets don't pass through the IP layer, so the bridge netfilter code
needs to take care of fragmentation itself.

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 550e29bc
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -95,6 +95,7 @@ extern int ip_local_deliver(struct sk_buff *skb);
extern int		ip_mr_input(struct sk_buff *skb);
extern int		ip_mr_input(struct sk_buff *skb);
extern int		ip_output(struct sk_buff *skb);
extern int		ip_output(struct sk_buff *skb);
extern int		ip_mc_output(struct sk_buff *skb);
extern int		ip_mc_output(struct sk_buff *skb);
extern int		ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
extern int		ip_do_nat(struct sk_buff *skb);
extern int		ip_do_nat(struct sk_buff *skb);
extern void		ip_send_check(struct iphdr *ip);
extern void		ip_send_check(struct iphdr *ip);
extern int		ip_queue_xmit(struct sk_buff *skb, int ipfragok);
extern int		ip_queue_xmit(struct sk_buff *skb, int ipfragok);
+11 −2
Original line number Original line Diff line number Diff line
@@ -765,6 +765,15 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
	return NF_STOLEN;
	return NF_STOLEN;
}
}


static int br_nf_dev_queue_xmit(struct sk_buff *skb)
{
	if (skb->protocol == htons(ETH_P_IP) &&
	    skb->len > skb->dev->mtu &&
	    !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
		return ip_fragment(skb, br_dev_queue_push_xmit);
	else
		return br_dev_queue_push_xmit(skb);
}


/* PF_BRIDGE/POST_ROUTING ********************************************/
/* PF_BRIDGE/POST_ROUTING ********************************************/
static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
@@ -824,7 +833,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
		realoutdev = nf_bridge->netoutdev;
		realoutdev = nf_bridge->netoutdev;
#endif
#endif
	NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
	NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
		br_dev_queue_push_xmit);
		br_nf_dev_queue_xmit);


	return NF_STOLEN;
	return NF_STOLEN;


@@ -869,7 +878,7 @@ static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,


	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_dev_queue_push_xmit)
	     okfn != br_nf_local_out_finish && okfn != br_nf_dev_queue_xmit)
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
	    || ((out->priv_flags & IFF_802_1Q_VLAN) &&
	    || ((out->priv_flags & IFF_802_1Q_VLAN) &&
		VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
		VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
+3 −3
Original line number Original line Diff line number Diff line
@@ -86,8 +86,6 @@


int sysctl_ip_default_ttl = IPDEFTTL;
int sysctl_ip_default_ttl = IPDEFTTL;


static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*));

/* Generate a checksum for an outgoing IP datagram. */
/* Generate a checksum for an outgoing IP datagram. */
__inline__ void ip_send_check(struct iphdr *iph)
__inline__ void ip_send_check(struct iphdr *iph)
{
{
@@ -421,7 +419,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
 *	single device frame, and queue such a frame for sending.
 *	single device frame, and queue such a frame for sending.
 */
 */


static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
{
{
	struct iphdr *iph;
	struct iphdr *iph;
	int raw = 0;
	int raw = 0;
@@ -673,6 +671,8 @@ static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
	return err;
	return err;
}
}


EXPORT_SYMBOL(ip_fragment);

int
int
ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
{
{