aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 4c0c5972a489..eba1271b9735 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -314,6 +314,21 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv,
314 314
315 switch (tun->flags & TUN_TYPE_MASK) { 315 switch (tun->flags & TUN_TYPE_MASK) {
316 case TUN_TUN_DEV: 316 case TUN_TUN_DEV:
317 if (tun->flags & TUN_NO_PI) {
318 switch (skb->data[0] & 0xf0) {
319 case 0x40:
320 pi.proto = htons(ETH_P_IP);
321 break;
322 case 0x60:
323 pi.proto = htons(ETH_P_IPV6);
324 break;
325 default:
326 tun->dev->stats.rx_dropped++;
327 kfree_skb(skb);
328 return -EINVAL;
329 }
330 }
331
317 skb_reset_mac_header(skb); 332 skb_reset_mac_header(skb);
318 skb->protocol = pi.proto; 333 skb->protocol = pi.proto;
319 skb->dev = tun->dev; 334 skb->dev = tun->dev;
@@ -588,6 +603,12 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
588 tun->attached = 1; 603 tun->attached = 1;
589 get_net(dev_net(tun->dev)); 604 get_net(dev_net(tun->dev));
590 605
606 /* Make sure persistent devices do not get stuck in
607 * xoff state.
608 */
609 if (netif_running(tun->dev))
610 netif_wake_queue(tun->dev);
611
591 strcpy(ifr->ifr_name, tun->dev->name); 612 strcpy(ifr->ifr_name, tun->dev->name);
592 return 0; 613 return 0;
593 614