diff options
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r-- | drivers/net/tun.c | 371 |
1 files changed, 228 insertions, 143 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index d7b81e4fdd56..e9bcbdfe015a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -63,6 +63,7 @@ | |||
63 | #include <linux/virtio_net.h> | 63 | #include <linux/virtio_net.h> |
64 | #include <net/net_namespace.h> | 64 | #include <net/net_namespace.h> |
65 | #include <net/netns/generic.h> | 65 | #include <net/netns/generic.h> |
66 | #include <net/rtnetlink.h> | ||
66 | 67 | ||
67 | #include <asm/system.h> | 68 | #include <asm/system.h> |
68 | #include <asm/uaccess.h> | 69 | #include <asm/uaccess.h> |
@@ -87,14 +88,19 @@ struct tap_filter { | |||
87 | unsigned char addr[FLT_EXACT_COUNT][ETH_ALEN]; | 88 | unsigned char addr[FLT_EXACT_COUNT][ETH_ALEN]; |
88 | }; | 89 | }; |
89 | 90 | ||
91 | struct tun_file { | ||
92 | atomic_t count; | ||
93 | struct tun_struct *tun; | ||
94 | struct net *net; | ||
95 | wait_queue_head_t read_wait; | ||
96 | }; | ||
97 | |||
90 | struct tun_struct { | 98 | struct tun_struct { |
91 | struct list_head list; | 99 | struct tun_file *tfile; |
92 | unsigned int flags; | 100 | unsigned int flags; |
93 | int attached; | ||
94 | uid_t owner; | 101 | uid_t owner; |
95 | gid_t group; | 102 | gid_t group; |
96 | 103 | ||
97 | wait_queue_head_t read_wait; | ||
98 | struct sk_buff_head readq; | 104 | struct sk_buff_head readq; |
99 | 105 | ||
100 | struct net_device *dev; | 106 | struct net_device *dev; |
@@ -107,6 +113,88 @@ struct tun_struct { | |||
107 | #endif | 113 | #endif |
108 | }; | 114 | }; |
109 | 115 | ||
116 | static int tun_attach(struct tun_struct *tun, struct file *file) | ||
117 | { | ||
118 | struct tun_file *tfile = file->private_data; | ||
119 | const struct cred *cred = current_cred(); | ||
120 | int err; | ||
121 | |||
122 | ASSERT_RTNL(); | ||
123 | |||
124 | /* Check permissions */ | ||
125 | if (((tun->owner != -1 && cred->euid != tun->owner) || | ||
126 | (tun->group != -1 && cred->egid != tun->group)) && | ||
127 | !capable(CAP_NET_ADMIN)) | ||
128 | return -EPERM; | ||
129 | |||
130 | netif_tx_lock_bh(tun->dev); | ||
131 | |||
132 | err = -EINVAL; | ||
133 | if (tfile->tun) | ||
134 | goto out; | ||
135 | |||
136 | err = -EBUSY; | ||
137 | if (tun->tfile) | ||
138 | goto out; | ||
139 | |||
140 | err = 0; | ||
141 | tfile->tun = tun; | ||
142 | tun->tfile = tfile; | ||
143 | dev_hold(tun->dev); | ||
144 | atomic_inc(&tfile->count); | ||
145 | |||
146 | out: | ||
147 | netif_tx_unlock_bh(tun->dev); | ||
148 | return err; | ||
149 | } | ||
150 | |||
151 | static void __tun_detach(struct tun_struct *tun) | ||
152 | { | ||
153 | struct tun_file *tfile = tun->tfile; | ||
154 | |||
155 | /* Detach from net device */ | ||
156 | netif_tx_lock_bh(tun->dev); | ||
157 | tfile->tun = NULL; | ||
158 | tun->tfile = NULL; | ||
159 | netif_tx_unlock_bh(tun->dev); | ||
160 | |||
161 | /* Drop read queue */ | ||
162 | skb_queue_purge(&tun->readq); | ||
163 | |||
164 | /* Drop the extra count on the net device */ | ||
165 | dev_put(tun->dev); | ||
166 | } | ||
167 | |||
168 | static void tun_detach(struct tun_struct *tun) | ||
169 | { | ||
170 | rtnl_lock(); | ||
171 | __tun_detach(tun); | ||
172 | rtnl_unlock(); | ||
173 | } | ||
174 | |||
175 | static struct tun_struct *__tun_get(struct tun_file *tfile) | ||
176 | { | ||
177 | struct tun_struct *tun = NULL; | ||
178 | |||
179 | if (atomic_inc_not_zero(&tfile->count)) | ||
180 | tun = tfile->tun; | ||
181 | |||
182 | return tun; | ||
183 | } | ||
184 | |||
185 | static struct tun_struct *tun_get(struct file *file) | ||
186 | { | ||
187 | return __tun_get(file->private_data); | ||
188 | } | ||
189 | |||
190 | static void tun_put(struct tun_struct *tun) | ||
191 | { | ||
192 | struct tun_file *tfile = tun->tfile; | ||
193 | |||
194 | if (atomic_dec_and_test(&tfile->count)) | ||
195 | tun_detach(tfile->tun); | ||
196 | } | ||
197 | |||
110 | /* TAP filterting */ | 198 | /* TAP filterting */ |
111 | static void addr_hash_set(u32 *mask, const u8 *addr) | 199 | static void addr_hash_set(u32 *mask, const u8 *addr) |
112 | { | 200 | { |
@@ -213,13 +301,23 @@ static int check_filter(struct tap_filter *filter, const struct sk_buff *skb) | |||
213 | 301 | ||
214 | /* Network device part of the driver */ | 302 | /* Network device part of the driver */ |
215 | 303 | ||
216 | static int tun_net_id; | ||
217 | struct tun_net { | ||
218 | struct list_head dev_list; | ||
219 | }; | ||
220 | |||
221 | static const struct ethtool_ops tun_ethtool_ops; | 304 | static const struct ethtool_ops tun_ethtool_ops; |
222 | 305 | ||
306 | /* Net device detach from fd. */ | ||
307 | static void tun_net_uninit(struct net_device *dev) | ||
308 | { | ||
309 | struct tun_struct *tun = netdev_priv(dev); | ||
310 | struct tun_file *tfile = tun->tfile; | ||
311 | |||
312 | /* Inform the methods they need to stop using the dev. | ||
313 | */ | ||
314 | if (tfile) { | ||
315 | wake_up_all(&tfile->read_wait); | ||
316 | if (atomic_dec_and_test(&tfile->count)) | ||
317 | __tun_detach(tun); | ||
318 | } | ||
319 | } | ||
320 | |||
223 | /* Net device open. */ | 321 | /* Net device open. */ |
224 | static int tun_net_open(struct net_device *dev) | 322 | static int tun_net_open(struct net_device *dev) |
225 | { | 323 | { |
@@ -242,7 +340,7 @@ static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev) | |||
242 | DBG(KERN_INFO "%s: tun_net_xmit %d\n", tun->dev->name, skb->len); | 340 | DBG(KERN_INFO "%s: tun_net_xmit %d\n", tun->dev->name, skb->len); |
243 | 341 | ||
244 | /* Drop packet if interface is not attached */ | 342 | /* Drop packet if interface is not attached */ |
245 | if (!tun->attached) | 343 | if (!tun->tfile) |
246 | goto drop; | 344 | goto drop; |
247 | 345 | ||
248 | /* Drop if the filter does not like it. | 346 | /* Drop if the filter does not like it. |
@@ -274,7 +372,7 @@ static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev) | |||
274 | /* Notify and wake up reader process */ | 372 | /* Notify and wake up reader process */ |
275 | if (tun->flags & TUN_FASYNC) | 373 | if (tun->flags & TUN_FASYNC) |
276 | kill_fasync(&tun->fasync, SIGIO, POLL_IN); | 374 | kill_fasync(&tun->fasync, SIGIO, POLL_IN); |
277 | wake_up_interruptible(&tun->read_wait); | 375 | wake_up_interruptible(&tun->tfile->read_wait); |
278 | return 0; | 376 | return 0; |
279 | 377 | ||
280 | drop: | 378 | drop: |
@@ -306,6 +404,7 @@ tun_net_change_mtu(struct net_device *dev, int new_mtu) | |||
306 | } | 404 | } |
307 | 405 | ||
308 | static const struct net_device_ops tun_netdev_ops = { | 406 | static const struct net_device_ops tun_netdev_ops = { |
407 | .ndo_uninit = tun_net_uninit, | ||
309 | .ndo_open = tun_net_open, | 408 | .ndo_open = tun_net_open, |
310 | .ndo_stop = tun_net_close, | 409 | .ndo_stop = tun_net_close, |
311 | .ndo_start_xmit = tun_net_xmit, | 410 | .ndo_start_xmit = tun_net_xmit, |
@@ -313,6 +412,7 @@ static const struct net_device_ops tun_netdev_ops = { | |||
313 | }; | 412 | }; |
314 | 413 | ||
315 | static const struct net_device_ops tap_netdev_ops = { | 414 | static const struct net_device_ops tap_netdev_ops = { |
415 | .ndo_uninit = tun_net_uninit, | ||
316 | .ndo_open = tun_net_open, | 416 | .ndo_open = tun_net_open, |
317 | .ndo_stop = tun_net_close, | 417 | .ndo_stop = tun_net_close, |
318 | .ndo_start_xmit = tun_net_xmit, | 418 | .ndo_start_xmit = tun_net_xmit, |
@@ -359,19 +459,24 @@ static void tun_net_init(struct net_device *dev) | |||
359 | /* Poll */ | 459 | /* Poll */ |
360 | static unsigned int tun_chr_poll(struct file *file, poll_table * wait) | 460 | static unsigned int tun_chr_poll(struct file *file, poll_table * wait) |
361 | { | 461 | { |
362 | struct tun_struct *tun = file->private_data; | 462 | struct tun_file *tfile = file->private_data; |
463 | struct tun_struct *tun = __tun_get(tfile); | ||
363 | unsigned int mask = POLLOUT | POLLWRNORM; | 464 | unsigned int mask = POLLOUT | POLLWRNORM; |
364 | 465 | ||
365 | if (!tun) | 466 | if (!tun) |
366 | return -EBADFD; | 467 | return POLLERR; |
367 | 468 | ||
368 | DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name); | 469 | DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name); |
369 | 470 | ||
370 | poll_wait(file, &tun->read_wait, wait); | 471 | poll_wait(file, &tfile->read_wait, wait); |
371 | 472 | ||
372 | if (!skb_queue_empty(&tun->readq)) | 473 | if (!skb_queue_empty(&tun->readq)) |
373 | mask |= POLLIN | POLLRDNORM; | 474 | mask |= POLLIN | POLLRDNORM; |
374 | 475 | ||
476 | if (tun->dev->reg_state != NETREG_REGISTERED) | ||
477 | mask = POLLERR; | ||
478 | |||
479 | tun_put(tun); | ||
375 | return mask; | 480 | return mask; |
376 | } | 481 | } |
377 | 482 | ||
@@ -556,14 +661,18 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, | |||
556 | static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, | 661 | static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, |
557 | unsigned long count, loff_t pos) | 662 | unsigned long count, loff_t pos) |
558 | { | 663 | { |
559 | struct tun_struct *tun = iocb->ki_filp->private_data; | 664 | struct tun_struct *tun = tun_get(iocb->ki_filp); |
665 | ssize_t result; | ||
560 | 666 | ||
561 | if (!tun) | 667 | if (!tun) |
562 | return -EBADFD; | 668 | return -EBADFD; |
563 | 669 | ||
564 | DBG(KERN_INFO "%s: tun_chr_write %ld\n", tun->dev->name, count); | 670 | DBG(KERN_INFO "%s: tun_chr_write %ld\n", tun->dev->name, count); |
565 | 671 | ||
566 | return tun_get_user(tun, (struct iovec *) iv, iov_length(iv, count)); | 672 | result = tun_get_user(tun, (struct iovec *) iv, iov_length(iv, count)); |
673 | |||
674 | tun_put(tun); | ||
675 | return result; | ||
567 | } | 676 | } |
568 | 677 | ||
569 | /* Put packet to the user space buffer */ | 678 | /* Put packet to the user space buffer */ |
@@ -636,7 +745,8 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, | |||
636 | unsigned long count, loff_t pos) | 745 | unsigned long count, loff_t pos) |
637 | { | 746 | { |
638 | struct file *file = iocb->ki_filp; | 747 | struct file *file = iocb->ki_filp; |
639 | struct tun_struct *tun = file->private_data; | 748 | struct tun_file *tfile = file->private_data; |
749 | struct tun_struct *tun = __tun_get(tfile); | ||
640 | DECLARE_WAITQUEUE(wait, current); | 750 | DECLARE_WAITQUEUE(wait, current); |
641 | struct sk_buff *skb; | 751 | struct sk_buff *skb; |
642 | ssize_t len, ret = 0; | 752 | ssize_t len, ret = 0; |
@@ -647,10 +757,12 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, | |||
647 | DBG(KERN_INFO "%s: tun_chr_read\n", tun->dev->name); | 757 | DBG(KERN_INFO "%s: tun_chr_read\n", tun->dev->name); |
648 | 758 | ||
649 | len = iov_length(iv, count); | 759 | len = iov_length(iv, count); |
650 | if (len < 0) | 760 | if (len < 0) { |
651 | return -EINVAL; | 761 | ret = -EINVAL; |
762 | goto out; | ||
763 | } | ||
652 | 764 | ||
653 | add_wait_queue(&tun->read_wait, &wait); | 765 | add_wait_queue(&tfile->read_wait, &wait); |
654 | while (len) { | 766 | while (len) { |
655 | current->state = TASK_INTERRUPTIBLE; | 767 | current->state = TASK_INTERRUPTIBLE; |
656 | 768 | ||
@@ -664,6 +776,10 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, | |||
664 | ret = -ERESTARTSYS; | 776 | ret = -ERESTARTSYS; |
665 | break; | 777 | break; |
666 | } | 778 | } |
779 | if (tun->dev->reg_state != NETREG_REGISTERED) { | ||
780 | ret = -EIO; | ||
781 | break; | ||
782 | } | ||
667 | 783 | ||
668 | /* Nothing to read, let's sleep */ | 784 | /* Nothing to read, let's sleep */ |
669 | schedule(); | 785 | schedule(); |
@@ -677,8 +793,10 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, | |||
677 | } | 793 | } |
678 | 794 | ||
679 | current->state = TASK_RUNNING; | 795 | current->state = TASK_RUNNING; |
680 | remove_wait_queue(&tun->read_wait, &wait); | 796 | remove_wait_queue(&tfile->read_wait, &wait); |
681 | 797 | ||
798 | out: | ||
799 | tun_put(tun); | ||
682 | return ret; | 800 | return ret; |
683 | } | 801 | } |
684 | 802 | ||
@@ -687,54 +805,49 @@ static void tun_setup(struct net_device *dev) | |||
687 | struct tun_struct *tun = netdev_priv(dev); | 805 | struct tun_struct *tun = netdev_priv(dev); |
688 | 806 | ||
689 | skb_queue_head_init(&tun->readq); | 807 | skb_queue_head_init(&tun->readq); |
690 | init_waitqueue_head(&tun->read_wait); | ||
691 | 808 | ||
692 | tun->owner = -1; | 809 | tun->owner = -1; |
693 | tun->group = -1; | 810 | tun->group = -1; |
694 | 811 | ||
695 | dev->ethtool_ops = &tun_ethtool_ops; | 812 | dev->ethtool_ops = &tun_ethtool_ops; |
696 | dev->destructor = free_netdev; | 813 | dev->destructor = free_netdev; |
697 | dev->features |= NETIF_F_NETNS_LOCAL; | ||
698 | } | 814 | } |
699 | 815 | ||
700 | static struct tun_struct *tun_get_by_name(struct tun_net *tn, const char *name) | 816 | /* Trivial set of netlink ops to allow deleting tun or tap |
817 | * device with netlink. | ||
818 | */ | ||
819 | static int tun_validate(struct nlattr *tb[], struct nlattr *data[]) | ||
701 | { | 820 | { |
702 | struct tun_struct *tun; | 821 | return -EINVAL; |
822 | } | ||
703 | 823 | ||
704 | ASSERT_RTNL(); | 824 | static struct rtnl_link_ops tun_link_ops __read_mostly = { |
705 | list_for_each_entry(tun, &tn->dev_list, list) { | 825 | .kind = DRV_NAME, |
706 | if (!strncmp(tun->dev->name, name, IFNAMSIZ)) | 826 | .priv_size = sizeof(struct tun_struct), |
707 | return tun; | 827 | .setup = tun_setup, |
708 | } | 828 | .validate = tun_validate, |
829 | }; | ||
709 | 830 | ||
710 | return NULL; | ||
711 | } | ||
712 | 831 | ||
713 | static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | 832 | static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) |
714 | { | 833 | { |
715 | struct tun_net *tn; | ||
716 | struct tun_struct *tun; | 834 | struct tun_struct *tun; |
717 | struct net_device *dev; | 835 | struct net_device *dev; |
718 | const struct cred *cred = current_cred(); | ||
719 | int err; | 836 | int err; |
720 | 837 | ||
721 | tn = net_generic(net, tun_net_id); | 838 | dev = __dev_get_by_name(net, ifr->ifr_name); |
722 | tun = tun_get_by_name(tn, ifr->ifr_name); | 839 | if (dev) { |
723 | if (tun) { | 840 | if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops) |
724 | if (tun->attached) | 841 | tun = netdev_priv(dev); |
725 | return -EBUSY; | 842 | else if ((ifr->ifr_flags & IFF_TAP) && dev->netdev_ops == &tap_netdev_ops) |
726 | 843 | tun = netdev_priv(dev); | |
727 | /* Check permissions */ | 844 | else |
728 | if (((tun->owner != -1 && | 845 | return -EINVAL; |
729 | cred->euid != tun->owner) || | 846 | |
730 | (tun->group != -1 && | 847 | err = tun_attach(tun, file); |
731 | cred->egid != tun->group)) && | 848 | if (err < 0) |
732 | !capable(CAP_NET_ADMIN)) { | 849 | return err; |
733 | return -EPERM; | ||
734 | } | ||
735 | } | 850 | } |
736 | else if (__dev_get_by_name(net, ifr->ifr_name)) | ||
737 | return -EINVAL; | ||
738 | else { | 851 | else { |
739 | char *name; | 852 | char *name; |
740 | unsigned long flags = 0; | 853 | unsigned long flags = 0; |
@@ -765,6 +878,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
765 | return -ENOMEM; | 878 | return -ENOMEM; |
766 | 879 | ||
767 | dev_net_set(dev, net); | 880 | dev_net_set(dev, net); |
881 | dev->rtnl_link_ops = &tun_link_ops; | ||
768 | 882 | ||
769 | tun = netdev_priv(dev); | 883 | tun = netdev_priv(dev); |
770 | tun->dev = dev; | 884 | tun->dev = dev; |
@@ -783,7 +897,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
783 | if (err < 0) | 897 | if (err < 0) |
784 | goto err_free_dev; | 898 | goto err_free_dev; |
785 | 899 | ||
786 | list_add(&tun->list, &tn->dev_list); | 900 | err = tun_attach(tun, file); |
901 | if (err < 0) | ||
902 | goto err_free_dev; | ||
787 | } | 903 | } |
788 | 904 | ||
789 | DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name); | 905 | DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name); |
@@ -803,10 +919,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
803 | else | 919 | else |
804 | tun->flags &= ~TUN_VNET_HDR; | 920 | tun->flags &= ~TUN_VNET_HDR; |
805 | 921 | ||
806 | file->private_data = tun; | ||
807 | tun->attached = 1; | ||
808 | get_net(dev_net(tun->dev)); | ||
809 | |||
810 | /* Make sure persistent devices do not get stuck in | 922 | /* Make sure persistent devices do not get stuck in |
811 | * xoff state. | 923 | * xoff state. |
812 | */ | 924 | */ |
@@ -824,7 +936,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
824 | 936 | ||
825 | static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr) | 937 | static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr) |
826 | { | 938 | { |
827 | struct tun_struct *tun = file->private_data; | 939 | struct tun_struct *tun = tun_get(file); |
828 | 940 | ||
829 | if (!tun) | 941 | if (!tun) |
830 | return -EBADFD; | 942 | return -EBADFD; |
@@ -849,6 +961,7 @@ static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
849 | if (tun->flags & TUN_VNET_HDR) | 961 | if (tun->flags & TUN_VNET_HDR) |
850 | ifr->ifr_flags |= IFF_VNET_HDR; | 962 | ifr->ifr_flags |= IFF_VNET_HDR; |
851 | 963 | ||
964 | tun_put(tun); | ||
852 | return 0; | 965 | return 0; |
853 | } | 966 | } |
854 | 967 | ||
@@ -895,7 +1008,8 @@ static int set_offload(struct net_device *dev, unsigned long arg) | |||
895 | static int tun_chr_ioctl(struct inode *inode, struct file *file, | 1008 | static int tun_chr_ioctl(struct inode *inode, struct file *file, |
896 | unsigned int cmd, unsigned long arg) | 1009 | unsigned int cmd, unsigned long arg) |
897 | { | 1010 | { |
898 | struct tun_struct *tun = file->private_data; | 1011 | struct tun_file *tfile = file->private_data; |
1012 | struct tun_struct *tun; | ||
899 | void __user* argp = (void __user*)arg; | 1013 | void __user* argp = (void __user*)arg; |
900 | struct ifreq ifr; | 1014 | struct ifreq ifr; |
901 | int ret; | 1015 | int ret; |
@@ -904,13 +1018,23 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, | |||
904 | if (copy_from_user(&ifr, argp, sizeof ifr)) | 1018 | if (copy_from_user(&ifr, argp, sizeof ifr)) |
905 | return -EFAULT; | 1019 | return -EFAULT; |
906 | 1020 | ||
1021 | if (cmd == TUNGETFEATURES) { | ||
1022 | /* Currently this just means: "what IFF flags are valid?". | ||
1023 | * This is needed because we never checked for invalid flags on | ||
1024 | * TUNSETIFF. */ | ||
1025 | return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE | | ||
1026 | IFF_VNET_HDR, | ||
1027 | (unsigned int __user*)argp); | ||
1028 | } | ||
1029 | |||
1030 | tun = __tun_get(tfile); | ||
907 | if (cmd == TUNSETIFF && !tun) { | 1031 | if (cmd == TUNSETIFF && !tun) { |
908 | int err; | 1032 | int err; |
909 | 1033 | ||
910 | ifr.ifr_name[IFNAMSIZ-1] = '\0'; | 1034 | ifr.ifr_name[IFNAMSIZ-1] = '\0'; |
911 | 1035 | ||
912 | rtnl_lock(); | 1036 | rtnl_lock(); |
913 | err = tun_set_iff(current->nsproxy->net_ns, file, &ifr); | 1037 | err = tun_set_iff(tfile->net, file, &ifr); |
914 | rtnl_unlock(); | 1038 | rtnl_unlock(); |
915 | 1039 | ||
916 | if (err) | 1040 | if (err) |
@@ -921,28 +1045,21 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, | |||
921 | return 0; | 1045 | return 0; |
922 | } | 1046 | } |
923 | 1047 | ||
924 | if (cmd == TUNGETFEATURES) { | ||
925 | /* Currently this just means: "what IFF flags are valid?". | ||
926 | * This is needed because we never checked for invalid flags on | ||
927 | * TUNSETIFF. */ | ||
928 | return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE | | ||
929 | IFF_VNET_HDR, | ||
930 | (unsigned int __user*)argp); | ||
931 | } | ||
932 | 1048 | ||
933 | if (!tun) | 1049 | if (!tun) |
934 | return -EBADFD; | 1050 | return -EBADFD; |
935 | 1051 | ||
936 | DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd); | 1052 | DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd); |
937 | 1053 | ||
1054 | ret = 0; | ||
938 | switch (cmd) { | 1055 | switch (cmd) { |
939 | case TUNGETIFF: | 1056 | case TUNGETIFF: |
940 | ret = tun_get_iff(current->nsproxy->net_ns, file, &ifr); | 1057 | ret = tun_get_iff(current->nsproxy->net_ns, file, &ifr); |
941 | if (ret) | 1058 | if (ret) |
942 | return ret; | 1059 | break; |
943 | 1060 | ||
944 | if (copy_to_user(argp, &ifr, sizeof(ifr))) | 1061 | if (copy_to_user(argp, &ifr, sizeof(ifr))) |
945 | return -EFAULT; | 1062 | ret = -EFAULT; |
946 | break; | 1063 | break; |
947 | 1064 | ||
948 | case TUNSETNOCSUM: | 1065 | case TUNSETNOCSUM: |
@@ -994,7 +1111,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, | |||
994 | ret = 0; | 1111 | ret = 0; |
995 | } | 1112 | } |
996 | rtnl_unlock(); | 1113 | rtnl_unlock(); |
997 | return ret; | 1114 | break; |
998 | 1115 | ||
999 | #ifdef TUN_DEBUG | 1116 | #ifdef TUN_DEBUG |
1000 | case TUNSETDEBUG: | 1117 | case TUNSETDEBUG: |
@@ -1005,24 +1122,25 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, | |||
1005 | rtnl_lock(); | 1122 | rtnl_lock(); |
1006 | ret = set_offload(tun->dev, arg); | 1123 | ret = set_offload(tun->dev, arg); |
1007 | rtnl_unlock(); | 1124 | rtnl_unlock(); |
1008 | return ret; | 1125 | break; |
1009 | 1126 | ||
1010 | case TUNSETTXFILTER: | 1127 | case TUNSETTXFILTER: |
1011 | /* Can be set only for TAPs */ | 1128 | /* Can be set only for TAPs */ |
1129 | ret = -EINVAL; | ||
1012 | if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) | 1130 | if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) |
1013 | return -EINVAL; | 1131 | break; |
1014 | rtnl_lock(); | 1132 | rtnl_lock(); |
1015 | ret = update_filter(&tun->txflt, (void __user *)arg); | 1133 | ret = update_filter(&tun->txflt, (void __user *)arg); |
1016 | rtnl_unlock(); | 1134 | rtnl_unlock(); |
1017 | return ret; | 1135 | break; |
1018 | 1136 | ||
1019 | case SIOCGIFHWADDR: | 1137 | case SIOCGIFHWADDR: |
1020 | /* Get hw addres */ | 1138 | /* Get hw addres */ |
1021 | memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN); | 1139 | memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN); |
1022 | ifr.ifr_hwaddr.sa_family = tun->dev->type; | 1140 | ifr.ifr_hwaddr.sa_family = tun->dev->type; |
1023 | if (copy_to_user(argp, &ifr, sizeof ifr)) | 1141 | if (copy_to_user(argp, &ifr, sizeof ifr)) |
1024 | return -EFAULT; | 1142 | ret = -EFAULT; |
1025 | return 0; | 1143 | break; |
1026 | 1144 | ||
1027 | case SIOCSIFHWADDR: | 1145 | case SIOCSIFHWADDR: |
1028 | /* Set hw address */ | 1146 | /* Set hw address */ |
@@ -1032,18 +1150,19 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, | |||
1032 | rtnl_lock(); | 1150 | rtnl_lock(); |
1033 | ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr); | 1151 | ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr); |
1034 | rtnl_unlock(); | 1152 | rtnl_unlock(); |
1035 | return ret; | 1153 | break; |
1036 | |||
1037 | default: | 1154 | default: |
1038 | return -EINVAL; | 1155 | ret = -EINVAL; |
1156 | break; | ||
1039 | }; | 1157 | }; |
1040 | 1158 | ||
1041 | return 0; | 1159 | tun_put(tun); |
1160 | return ret; | ||
1042 | } | 1161 | } |
1043 | 1162 | ||
1044 | static int tun_chr_fasync(int fd, struct file *file, int on) | 1163 | static int tun_chr_fasync(int fd, struct file *file, int on) |
1045 | { | 1164 | { |
1046 | struct tun_struct *tun = file->private_data; | 1165 | struct tun_struct *tun = tun_get(file); |
1047 | int ret; | 1166 | int ret; |
1048 | 1167 | ||
1049 | if (!tun) | 1168 | if (!tun) |
@@ -1065,42 +1184,48 @@ static int tun_chr_fasync(int fd, struct file *file, int on) | |||
1065 | ret = 0; | 1184 | ret = 0; |
1066 | out: | 1185 | out: |
1067 | unlock_kernel(); | 1186 | unlock_kernel(); |
1187 | tun_put(tun); | ||
1068 | return ret; | 1188 | return ret; |
1069 | } | 1189 | } |
1070 | 1190 | ||
1071 | static int tun_chr_open(struct inode *inode, struct file * file) | 1191 | static int tun_chr_open(struct inode *inode, struct file * file) |
1072 | { | 1192 | { |
1193 | struct tun_file *tfile; | ||
1073 | cycle_kernel_lock(); | 1194 | cycle_kernel_lock(); |
1074 | DBG1(KERN_INFO "tunX: tun_chr_open\n"); | 1195 | DBG1(KERN_INFO "tunX: tun_chr_open\n"); |
1075 | file->private_data = NULL; | 1196 | |
1197 | tfile = kmalloc(sizeof(*tfile), GFP_KERNEL); | ||
1198 | if (!tfile) | ||
1199 | return -ENOMEM; | ||
1200 | atomic_set(&tfile->count, 0); | ||
1201 | tfile->tun = NULL; | ||
1202 | tfile->net = get_net(current->nsproxy->net_ns); | ||
1203 | init_waitqueue_head(&tfile->read_wait); | ||
1204 | file->private_data = tfile; | ||
1076 | return 0; | 1205 | return 0; |
1077 | } | 1206 | } |
1078 | 1207 | ||
1079 | static int tun_chr_close(struct inode *inode, struct file *file) | 1208 | static int tun_chr_close(struct inode *inode, struct file *file) |
1080 | { | 1209 | { |
1081 | struct tun_struct *tun = file->private_data; | 1210 | struct tun_file *tfile = file->private_data; |
1211 | struct tun_struct *tun = __tun_get(tfile); | ||
1082 | 1212 | ||
1083 | if (!tun) | ||
1084 | return 0; | ||
1085 | |||
1086 | DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name); | ||
1087 | 1213 | ||
1088 | rtnl_lock(); | 1214 | if (tun) { |
1215 | DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name); | ||
1089 | 1216 | ||
1090 | /* Detach from net device */ | 1217 | rtnl_lock(); |
1091 | file->private_data = NULL; | 1218 | __tun_detach(tun); |
1092 | tun->attached = 0; | ||
1093 | put_net(dev_net(tun->dev)); | ||
1094 | 1219 | ||
1095 | /* Drop read queue */ | 1220 | /* If desireable, unregister the netdevice. */ |
1096 | skb_queue_purge(&tun->readq); | 1221 | if (!(tun->flags & TUN_PERSIST)) |
1222 | unregister_netdevice(tun->dev); | ||
1097 | 1223 | ||
1098 | if (!(tun->flags & TUN_PERSIST)) { | 1224 | rtnl_unlock(); |
1099 | list_del(&tun->list); | ||
1100 | unregister_netdevice(tun->dev); | ||
1101 | } | 1225 | } |
1102 | 1226 | ||
1103 | rtnl_unlock(); | 1227 | put_net(tfile->net); |
1228 | kfree(tfile); | ||
1104 | 1229 | ||
1105 | return 0; | 1230 | return 0; |
1106 | } | 1231 | } |
@@ -1181,7 +1306,7 @@ static void tun_set_msglevel(struct net_device *dev, u32 value) | |||
1181 | static u32 tun_get_link(struct net_device *dev) | 1306 | static u32 tun_get_link(struct net_device *dev) |
1182 | { | 1307 | { |
1183 | struct tun_struct *tun = netdev_priv(dev); | 1308 | struct tun_struct *tun = netdev_priv(dev); |
1184 | return tun->attached; | 1309 | return !!tun->tfile; |
1185 | } | 1310 | } |
1186 | 1311 | ||
1187 | static u32 tun_get_rx_csum(struct net_device *dev) | 1312 | static u32 tun_get_rx_csum(struct net_device *dev) |
@@ -1210,45 +1335,6 @@ static const struct ethtool_ops tun_ethtool_ops = { | |||
1210 | .set_rx_csum = tun_set_rx_csum | 1335 | .set_rx_csum = tun_set_rx_csum |
1211 | }; | 1336 | }; |
1212 | 1337 | ||
1213 | static int tun_init_net(struct net *net) | ||
1214 | { | ||
1215 | struct tun_net *tn; | ||
1216 | |||
1217 | tn = kmalloc(sizeof(*tn), GFP_KERNEL); | ||
1218 | if (tn == NULL) | ||
1219 | return -ENOMEM; | ||
1220 | |||
1221 | INIT_LIST_HEAD(&tn->dev_list); | ||
1222 | |||
1223 | if (net_assign_generic(net, tun_net_id, tn)) { | ||
1224 | kfree(tn); | ||
1225 | return -ENOMEM; | ||
1226 | } | ||
1227 | |||
1228 | return 0; | ||
1229 | } | ||
1230 | |||
1231 | static void tun_exit_net(struct net *net) | ||
1232 | { | ||
1233 | struct tun_net *tn; | ||
1234 | struct tun_struct *tun, *nxt; | ||
1235 | |||
1236 | tn = net_generic(net, tun_net_id); | ||
1237 | |||
1238 | rtnl_lock(); | ||
1239 | list_for_each_entry_safe(tun, nxt, &tn->dev_list, list) { | ||
1240 | DBG(KERN_INFO "%s cleaned up\n", tun->dev->name); | ||
1241 | unregister_netdevice(tun->dev); | ||
1242 | } | ||
1243 | rtnl_unlock(); | ||
1244 | |||
1245 | kfree(tn); | ||
1246 | } | ||
1247 | |||
1248 | static struct pernet_operations tun_net_ops = { | ||
1249 | .init = tun_init_net, | ||
1250 | .exit = tun_exit_net, | ||
1251 | }; | ||
1252 | 1338 | ||
1253 | static int __init tun_init(void) | 1339 | static int __init tun_init(void) |
1254 | { | 1340 | { |
@@ -1257,10 +1343,10 @@ static int __init tun_init(void) | |||
1257 | printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION); | 1343 | printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION); |
1258 | printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT); | 1344 | printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT); |
1259 | 1345 | ||
1260 | ret = register_pernet_gen_device(&tun_net_id, &tun_net_ops); | 1346 | ret = rtnl_link_register(&tun_link_ops); |
1261 | if (ret) { | 1347 | if (ret) { |
1262 | printk(KERN_ERR "tun: Can't register pernet ops\n"); | 1348 | printk(KERN_ERR "tun: Can't register link_ops\n"); |
1263 | goto err_pernet; | 1349 | goto err_linkops; |
1264 | } | 1350 | } |
1265 | 1351 | ||
1266 | ret = misc_register(&tun_miscdev); | 1352 | ret = misc_register(&tun_miscdev); |
@@ -1268,18 +1354,17 @@ static int __init tun_init(void) | |||
1268 | printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR); | 1354 | printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR); |
1269 | goto err_misc; | 1355 | goto err_misc; |
1270 | } | 1356 | } |
1271 | return 0; | 1357 | return 0; |
1272 | |||
1273 | err_misc: | 1358 | err_misc: |
1274 | unregister_pernet_gen_device(tun_net_id, &tun_net_ops); | 1359 | rtnl_link_unregister(&tun_link_ops); |
1275 | err_pernet: | 1360 | err_linkops: |
1276 | return ret; | 1361 | return ret; |
1277 | } | 1362 | } |
1278 | 1363 | ||
1279 | static void tun_cleanup(void) | 1364 | static void tun_cleanup(void) |
1280 | { | 1365 | { |
1281 | misc_deregister(&tun_miscdev); | 1366 | misc_deregister(&tun_miscdev); |
1282 | unregister_pernet_gen_device(tun_net_id, &tun_net_ops); | 1367 | rtnl_link_unregister(&tun_link_ops); |
1283 | } | 1368 | } |
1284 | 1369 | ||
1285 | module_init(tun_init); | 1370 | module_init(tun_init); |