diff options
Diffstat (limited to 'drivers/net/tun.c')
| -rw-r--r-- | drivers/net/tun.c | 25 | 
1 files changed, 16 insertions, 9 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 186ce541c657..7302398f0b1f 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -65,6 +65,7 @@  #include <linux/nsproxy.h>  #include <linux/virtio_net.h>  #include <linux/rcupdate.h> +#include <net/ipv6.h>  #include <net/net_namespace.h>  #include <net/netns/generic.h>  #include <net/rtnetlink.h> @@ -174,7 +175,7 @@ struct tun_struct {  	struct net_device	*dev;  	netdev_features_t	set_features;  #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ -			  NETIF_F_TSO6|NETIF_F_UFO) +			  NETIF_F_TSO6)  	int			vnet_hdr_sz;  	int			sndbuf; @@ -1139,6 +1140,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,  		break;  	} +	skb_reset_network_header(skb); +  	if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) {  		pr_debug("GSO!\n");  		switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { @@ -1149,8 +1152,20 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,  			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;  			break;  		case VIRTIO_NET_HDR_GSO_UDP: +		{ +			static bool warned; + +			if (!warned) { +				warned = true; +				netdev_warn(tun->dev, +					    "%s: using disabled UFO feature; please fix this program\n", +					    current->comm); +			}  			skb_shinfo(skb)->gso_type = SKB_GSO_UDP; +			if (skb->protocol == htons(ETH_P_IPV6)) +				ipv6_proxy_select_ident(skb);  			break; +		}  		default:  			tun->dev->stats.rx_frame_errors++;  			kfree_skb(skb); @@ -1179,7 +1194,6 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,  		skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;  	} -	skb_reset_network_header(skb);  	skb_probe_transport_header(skb, 0);  	rxhash = skb_get_hash(skb); @@ -1251,8 +1265,6 @@ static ssize_t tun_put_user(struct tun_struct *tun,  				gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;  			else if (sinfo->gso_type & SKB_GSO_TCPV6)  				gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; -			else if (sinfo->gso_type & SKB_GSO_UDP) -				gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;  			else {  				pr_err("unexpected GSO type: "  				       "0x%x, gso_size %d, hdr_len %d\n", @@ -1762,11 +1774,6 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)  				features |= NETIF_F_TSO6;  			arg &= ~(TUN_F_TSO4|TUN_F_TSO6);  		} - -		if (arg & TUN_F_UFO) { -			features |= NETIF_F_UFO; -			arg &= ~TUN_F_UFO; -		}  	}  	/* This gives the user a way to test for new features in future by  |