git.openpandora.org
/
pandora-kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[pandora-kernel.git]
/
drivers
/
net
/
tun.c
diff --git
a/drivers/net/tun.c
b/drivers/net/tun.c
index
11a0ba4
..
2533f5c
100644
(file)
--- a/
drivers/net/tun.c
+++ b/
drivers/net/tun.c
@@
-398,12
+398,12
@@
static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
if (tun->flags & TUN_FASYNC)
kill_fasync(&tun->fasync, SIGIO, POLL_IN);
wake_up_interruptible(&tun->socket.wait);
if (tun->flags & TUN_FASYNC)
kill_fasync(&tun->fasync, SIGIO, POLL_IN);
wake_up_interruptible(&tun->socket.wait);
- return
0
;
+ return
NETDEV_TX_OK
;
drop:
dev->stats.tx_dropped++;
kfree_skb(skb);
drop:
dev->stats.tx_dropped++;
kfree_skb(skb);
- return
0
;
+ return
NETDEV_TX_OK
;
}
static void tun_net_mclist(struct net_device *dev)
}
static void tun_net_mclist(struct net_device *dev)
@@
-486,12
+486,14
@@
static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
{
struct tun_file *tfile = file->private_data;
struct tun_struct *tun = __tun_get(tfile);
{
struct tun_file *tfile = file->private_data;
struct tun_struct *tun = __tun_get(tfile);
- struct sock *sk
= tun->sk
;
+ struct sock *sk;
unsigned int mask = 0;
if (!tun)
return POLLERR;
unsigned int mask = 0;
if (!tun)
return POLLERR;
+ sk = tun->sk;
+
DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);
poll_wait(file, &tun->socket.wait, wait);
DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);
poll_wait(file, &tun->socket.wait, wait);
@@
-639,6
+641,9
@@
static __inline__ ssize_t tun_get_user(struct tun_struct *tun,
case VIRTIO_NET_HDR_GSO_TCPV6:
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
break;
case VIRTIO_NET_HDR_GSO_TCPV6:
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
break;
+ case VIRTIO_NET_HDR_GSO_UDP:
+ skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+ break;
default:
tun->dev->stats.rx_frame_errors++;
kfree_skb(skb);
default:
tun->dev->stats.rx_frame_errors++;
kfree_skb(skb);
@@
-724,6
+729,8
@@
static __inline__ 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;
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
BUG();
if (sinfo->gso_type & SKB_GSO_TCP_ECN)
else
BUG();
if (sinfo->gso_type & SKB_GSO_TCP_ECN)
@@
-995,7
+1002,6
@@
static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
goto err_free_sk;
}
goto err_free_sk;
}
- err = -EINVAL;
err = register_netdevice(tun->dev);
if (err < 0)
goto err_free_sk;
err = register_netdevice(tun->dev);
if (err < 0)
goto err_free_sk;
@@
-1046,20
+1052,15
@@
static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
return err;
}
return err;
}
-static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr)
+static int tun_get_iff(struct net *net, struct tun_struct *tun,
+ struct ifreq *ifr)
{
{
- struct tun_struct *tun = tun_get(file);
-
- if (!tun)
- return -EBADFD;
-
DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name);
strcpy(ifr->ifr_name, tun->dev->name);
ifr->ifr_flags = tun_flags(tun);
DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name);
strcpy(ifr->ifr_name, tun->dev->name);
ifr->ifr_flags = tun_flags(tun);
- tun_put(tun);
return 0;
}
return 0;
}
@@
-1072,7
+1073,8
@@
static int set_offload(struct net_device *dev, unsigned long arg)
old_features = dev->features;
/* Unset features, set them as we chew on the arg. */
features = (old_features & ~(NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST
old_features = dev->features;
/* Unset features, set them as we chew on the arg. */
features = (old_features & ~(NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST
- |NETIF_F_TSO_ECN|NETIF_F_TSO|NETIF_F_TSO6));
+ |NETIF_F_TSO_ECN|NETIF_F_TSO|NETIF_F_TSO6
+ |NETIF_F_UFO));
if (arg & TUN_F_CSUM) {
features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
if (arg & TUN_F_CSUM) {
features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
@@
-1089,6
+1091,11
@@
static int set_offload(struct net_device *dev, unsigned long arg)
features |= NETIF_F_TSO6;
arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
}
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
}
/* This gives the user a way to test for new features in future by
@@
-1103,8
+1110,8
@@
static int set_offload(struct net_device *dev, unsigned long arg)
return 0;
}
return 0;
}
-static
int tun_chr_ioctl(struct inode *inode, struct file *file
,
-
unsigned int cmd,
unsigned long arg)
+static
long tun_chr_ioctl(struct file *file, unsigned int cmd
,
+ unsigned long arg)
{
struct tun_file *tfile = file->private_data;
struct tun_struct *tun;
{
struct tun_file *tfile = file->private_data;
struct tun_struct *tun;
@@
-1126,34
+1133,32
@@
static int tun_chr_ioctl(struct inode *inode, struct file *file,
(unsigned int __user*)argp);
}
(unsigned int __user*)argp);
}
+ rtnl_lock();
+
tun = __tun_get(tfile);
if (cmd == TUNSETIFF && !tun) {
tun = __tun_get(tfile);
if (cmd == TUNSETIFF && !tun) {
- int err;
-
ifr.ifr_name[IFNAMSIZ-1] = '\0';
ifr.ifr_name[IFNAMSIZ-1] = '\0';
- rtnl_lock();
- err = tun_set_iff(tfile->net, file, &ifr);
- rtnl_unlock();
+ ret = tun_set_iff(tfile->net, file, &ifr);
- if (
err
)
-
return err
;
+ if (
ret
)
+
goto unlock
;
if (copy_to_user(argp, &ifr, sizeof(ifr)))
if (copy_to_user(argp, &ifr, sizeof(ifr)))
- ret
urn
-EFAULT;
-
return 0
;
+ ret
=
-EFAULT;
+
goto unlock
;
}
}
-
+ ret = -EBADFD;
if (!tun)
if (!tun)
-
return -EBADFD
;
+
goto unlock
;
DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd);
ret = 0;
switch (cmd) {
case TUNGETIFF:
DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd);
ret = 0;
switch (cmd) {
case TUNGETIFF:
- ret = tun_get_iff(current->nsproxy->net_ns,
file
, &ifr);
+ ret = tun_get_iff(current->nsproxy->net_ns,
tun
, &ifr);
if (ret)
break;
if (ret)
break;
@@
-1199,7
+1204,6
@@
static int tun_chr_ioctl(struct inode *inode, struct file *file,
case TUNSETLINK:
/* Only allow setting the type when the interface is down */
case TUNSETLINK:
/* Only allow setting the type when the interface is down */
- rtnl_lock();
if (tun->dev->flags & IFF_UP) {
DBG(KERN_INFO "%s: Linktype set failed because interface is up\n",
tun->dev->name);
if (tun->dev->flags & IFF_UP) {
DBG(KERN_INFO "%s: Linktype set failed because interface is up\n",
tun->dev->name);
@@
-1209,7
+1213,6
@@
static int tun_chr_ioctl(struct inode *inode, struct file *file,
DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type);
ret = 0;
}
DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type);
ret = 0;
}
- rtnl_unlock();
break;
#ifdef TUN_DEBUG
break;
#ifdef TUN_DEBUG
@@
-1218,9
+1221,7
@@
static int tun_chr_ioctl(struct inode *inode, struct file *file,
break;
#endif
case TUNSETOFFLOAD:
break;
#endif
case TUNSETOFFLOAD:
- rtnl_lock();
ret = set_offload(tun->dev, arg);
ret = set_offload(tun->dev, arg);
- rtnl_unlock();
break;
case TUNSETTXFILTER:
break;
case TUNSETTXFILTER:
@@
-1228,9
+1229,7
@@
static int tun_chr_ioctl(struct inode *inode, struct file *file,
ret = -EINVAL;
if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
break;
ret = -EINVAL;
if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
break;
- rtnl_lock();
ret = update_filter(&tun->txflt, (void __user *)arg);
ret = update_filter(&tun->txflt, (void __user *)arg);
- rtnl_unlock();
break;
case SIOCGIFHWADDR:
break;
case SIOCGIFHWADDR:
@@
-1246,9
+1245,7
@@
static int tun_chr_ioctl(struct inode *inode, struct file *file,
DBG(KERN_DEBUG "%s: set hw address: %pM\n",
tun->dev->name, ifr.ifr_hwaddr.sa_data);
DBG(KERN_DEBUG "%s: set hw address: %pM\n",
tun->dev->name, ifr.ifr_hwaddr.sa_data);
- rtnl_lock();
ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
- rtnl_unlock();
break;
case TUNGETSNDBUF:
break;
case TUNGETSNDBUF:
@@
-1271,7
+1268,10
@@
static int tun_chr_ioctl(struct inode *inode, struct file *file,
break;
};
break;
};
- tun_put(tun);
+unlock:
+ rtnl_unlock();
+ if (tun)
+ tun_put(tun);
return ret;
}
return ret;
}
@@
-1324,20
+1324,22
@@
static int tun_chr_close(struct inode *inode, struct file *file)
struct tun_file *tfile = file->private_data;
struct tun_struct *tun;
struct tun_file *tfile = file->private_data;
struct tun_struct *tun;
-
- rtnl_lock();
tun = __tun_get(tfile);
if (tun) {
tun = __tun_get(tfile);
if (tun) {
- DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name);
+ struct net_device *dev = tun->dev;
+
+ DBG(KERN_INFO "%s: tun_chr_close\n", dev->name);
__tun_detach(tun);
/* If desireable, unregister the netdevice. */
__tun_detach(tun);
/* If desireable, unregister the netdevice. */
- if (!(tun->flags & TUN_PERSIST))
- unregister_netdevice(tun->dev);
-
+ if (!(tun->flags & TUN_PERSIST)) {
+ rtnl_lock();
+ if (dev->reg_state == NETREG_REGISTERED)
+ unregister_netdevice(dev);
+ rtnl_unlock();
+ }
}
}
- rtnl_unlock();
tun = tfile->tun;
if (tun)
tun = tfile->tun;
if (tun)
@@
-1357,7
+1359,7
@@
static const struct file_operations tun_fops = {
.write = do_sync_write,
.aio_write = tun_chr_aio_write,
.poll = tun_chr_poll,
.write = do_sync_write,
.aio_write = tun_chr_aio_write,
.poll = tun_chr_poll,
- .
ioctl
= tun_chr_ioctl,
+ .
unlocked_ioctl
= tun_chr_ioctl,
.open = tun_chr_open,
.release = tun_chr_close,
.fasync = tun_chr_fasync
.open = tun_chr_open,
.release = tun_chr_close,
.fasync = tun_chr_fasync