struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, int gso_type_mask);
 
+static inline int iptunnel_pull_offloads(struct sk_buff *skb)
+{
+       if (skb_is_gso(skb)) {
+               int err;
+
+               err = skb_unclone(skb, GFP_ATOMIC);
+               if (unlikely(err))
+                       return err;
+               skb_shinfo(skb)->gso_type &= ~(NETIF_F_GSO_ENCAP_ALL >>
+                                              NETIF_F_GSO_SHIFT);
+       }
+
+       skb->encapsulation = 0;
+       return 0;
+}
+
 static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len)
 {
        if (pkt_len > 0) {
 
        return sk->sk_user_data;
 }
 
-static void fou_recv_pull(struct sk_buff *skb, size_t len)
+static int fou_recv_pull(struct sk_buff *skb, size_t len)
 {
        struct iphdr *iph = ip_hdr(skb);
 
        __skb_pull(skb, len);
        skb_postpull_rcsum(skb, udp_hdr(skb), len);
        skb_reset_transport_header(skb);
+       return iptunnel_pull_offloads(skb);
 }
 
 static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
        if (!fou)
                return 1;
 
-       fou_recv_pull(skb, sizeof(struct udphdr));
+       if (fou_recv_pull(skb, sizeof(struct udphdr)))
+               goto drop;
 
        return -fou->protocol;
+
+drop:
+       kfree_skb(skb);
+       return 0;
 }
 
 static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr,
        __skb_pull(skb, sizeof(struct udphdr) + hdrlen);
        skb_reset_transport_header(skb);
 
+       if (iptunnel_pull_offloads(skb))
+               goto drop;
+
        return -guehdr->proto_ctype;
 
 drop:
 
        skb->vlan_tci = 0;
        skb_set_queue_mapping(skb, 0);
        skb_scrub_packet(skb, xnet);
-       return 0;
+
+       return iptunnel_pull_offloads(skb);
 }
 EXPORT_SYMBOL_GPL(iptunnel_pull_header);
 
 
                skb->mac_header = skb->network_header;
                skb_reset_network_header(skb);
                IPCB(skb)->flags = 0;
-               skb->protocol = htons(ETH_P_IPV6);
+               skb->dev = tunnel->dev;
 
                if (packet_is_spoofed(skb, iph, tunnel)) {
                        tunnel->dev->stats.rx_errors++;
                        goto out;
                }
 
-               __skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
+               if (iptunnel_pull_header(skb, 0, htons(ETH_P_IPV6),
+                   !net_eq(tunnel->net, dev_net(tunnel->dev))))
+                       goto out;
 
                err = IP_ECN_decapsulate(iph, skb);
                if (unlikely(err)) {