blob: fa93160bf52244fbf71db7812bf7dccd86cc9278 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * TUN - Universal TUN/TAP device driver.
3 * Copyright (C) 1999-2002 Maxim Krasnyansky <maxk@qualcomm.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * $Id: tun.c,v 1.15 2002/03/01 02:44:24 maxk Exp $
16 */
17
18/*
19 * Changes:
20 *
Mike Kershawff4cc3a2005-09-01 17:40:05 -070021 * Mike Kershaw <dragorn@kismetwireless.net> 2005/08/14
22 * Add TUNSETLINK ioctl to set the link encapsulation
23 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 * Mark Smith <markzzzsmith@yahoo.com.au>
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -070025 * Use random_ether_addr() for tap MAC address.
Linus Torvalds1da177e2005-04-16 15:20:36 -070026 *
27 * Harald Roelle <harald.roelle@ifi.lmu.de> 2004/04/20
28 * Fixes in packet dropping, queue length setting and queue wakeup.
29 * Increased default tx queue length.
30 * Added ethtool API.
31 * Minor cleanups
32 *
33 * Daniel Podlejski <underley@underley.eu.org>
34 * Modifications for 2.3.99-pre5 kernel.
35 */
36
37#define DRV_NAME "tun"
38#define DRV_VERSION "1.6"
39#define DRV_DESCRIPTION "Universal TUN/TAP device driver"
40#define DRV_COPYRIGHT "(C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>"
41
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/module.h>
43#include <linux/errno.h>
44#include <linux/kernel.h>
45#include <linux/major.h>
46#include <linux/slab.h>
Arnd Bergmannfd3e05b2008-05-20 19:16:24 +020047#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#include <linux/poll.h>
49#include <linux/fcntl.h>
50#include <linux/init.h>
51#include <linux/skbuff.h>
52#include <linux/netdevice.h>
53#include <linux/etherdevice.h>
54#include <linux/miscdevice.h>
55#include <linux/ethtool.h>
56#include <linux/rtnetlink.h>
57#include <linux/if.h>
58#include <linux/if_arp.h>
59#include <linux/if_ether.h>
60#include <linux/if_tun.h>
61#include <linux/crc32.h>
Pavel Emelyanovd647a592008-04-16 00:41:16 -070062#include <linux/nsproxy.h>
Rusty Russellf43798c2008-07-03 03:48:02 -070063#include <linux/virtio_net.h>
Eric W. Biederman881d9662007-09-17 11:56:21 -070064#include <net/net_namespace.h>
Pavel Emelyanov79d17602008-04-16 00:40:46 -070065#include <net/netns/generic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
67#include <asm/system.h>
68#include <asm/uaccess.h>
69
Rusty Russell14daa022008-04-12 18:48:58 -070070/* Uncomment to enable debugging */
71/* #define TUN_DEBUG 1 */
72
Linus Torvalds1da177e2005-04-16 15:20:36 -070073#ifdef TUN_DEBUG
74static int debug;
Rusty Russell14daa022008-04-12 18:48:58 -070075
76#define DBG if(tun->debug)printk
77#define DBG1 if(debug==2)printk
78#else
79#define DBG( a... )
80#define DBG1( a... )
Linus Torvalds1da177e2005-04-16 15:20:36 -070081#endif
82
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -070083#define FLT_EXACT_COUNT 8
84struct tap_filter {
85 unsigned int count; /* Number of addrs. Zero means disabled */
86 u32 mask[2]; /* Mask of the hashed addrs */
87 unsigned char addr[FLT_EXACT_COUNT][ETH_ALEN];
88};
89
Eric W. Biederman631ab462009-01-20 11:00:40 +000090struct tun_file {
91 struct tun_struct *tun;
Eric W. Biederman36b50ba2009-01-20 11:01:48 +000092 struct net *net;
Eric W. Biederman631ab462009-01-20 11:00:40 +000093};
94
Rusty Russell14daa022008-04-12 18:48:58 -070095struct tun_struct {
Eric W. Biederman631ab462009-01-20 11:00:40 +000096 struct tun_file *tfile;
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -070097 unsigned int flags;
Rusty Russell14daa022008-04-12 18:48:58 -070098 uid_t owner;
99 gid_t group;
100
101 wait_queue_head_t read_wait;
102 struct sk_buff_head readq;
103
104 struct net_device *dev;
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -0700105 struct fasync_struct *fasync;
Rusty Russell14daa022008-04-12 18:48:58 -0700106
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -0700107 struct tap_filter txflt;
Rusty Russell14daa022008-04-12 18:48:58 -0700108
109#ifdef TUN_DEBUG
110 int debug;
111#endif
112};
113
Eric W. Biedermana7385ba2009-01-20 10:57:48 +0000114static int tun_attach(struct tun_struct *tun, struct file *file)
115{
Eric W. Biederman631ab462009-01-20 11:00:40 +0000116 struct tun_file *tfile = file->private_data;
Eric W. Biedermana7385ba2009-01-20 10:57:48 +0000117 const struct cred *cred = current_cred();
Eric W. Biederman38231b72009-01-20 11:02:28 +0000118 int err;
Eric W. Biedermana7385ba2009-01-20 10:57:48 +0000119
120 ASSERT_RTNL();
121
Eric W. Biedermana7385ba2009-01-20 10:57:48 +0000122 /* Check permissions */
123 if (((tun->owner != -1 && cred->euid != tun->owner) ||
124 (tun->group != -1 && cred->egid != tun->group)) &&
125 !capable(CAP_NET_ADMIN))
126 return -EPERM;
127
Eric W. Biederman38231b72009-01-20 11:02:28 +0000128 netif_tx_lock_bh(tun->dev);
129
130 err = -EINVAL;
131 if (tfile->tun)
132 goto out;
133
134 err = -EBUSY;
135 if (tun->tfile)
136 goto out;
137
138 err = 0;
Eric W. Biederman631ab462009-01-20 11:00:40 +0000139 tfile->tun = tun;
140 tun->tfile = tfile;
Eric W. Biedermana7385ba2009-01-20 10:57:48 +0000141
Eric W. Biederman38231b72009-01-20 11:02:28 +0000142out:
143 netif_tx_unlock_bh(tun->dev);
144 return err;
Eric W. Biedermana7385ba2009-01-20 10:57:48 +0000145}
146
Eric W. Biederman631ab462009-01-20 11:00:40 +0000147static void __tun_detach(struct tun_struct *tun)
148{
149 struct tun_file *tfile = tun->tfile;
150
151 /* Detach from net device */
Eric W. Biederman38231b72009-01-20 11:02:28 +0000152 netif_tx_lock_bh(tun->dev);
Eric W. Biederman631ab462009-01-20 11:00:40 +0000153 tfile->tun = NULL;
154 tun->tfile = NULL;
Eric W. Biederman38231b72009-01-20 11:02:28 +0000155 netif_tx_unlock_bh(tun->dev);
Eric W. Biederman631ab462009-01-20 11:00:40 +0000156
157 /* Drop read queue */
158 skb_queue_purge(&tun->readq);
159}
160
161static struct tun_struct *__tun_get(struct tun_file *tfile)
162{
163 return tfile->tun;
164}
165
166static struct tun_struct *tun_get(struct file *file)
167{
168 return __tun_get(file->private_data);
169}
170
171static void tun_put(struct tun_struct *tun)
172{
173 /* Noop for now */
174}
175
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -0700176/* TAP filterting */
177static void addr_hash_set(u32 *mask, const u8 *addr)
178{
179 int n = ether_crc(ETH_ALEN, addr) >> 26;
180 mask[n >> 5] |= (1 << (n & 31));
181}
182
183static unsigned int addr_hash_test(const u32 *mask, const u8 *addr)
184{
185 int n = ether_crc(ETH_ALEN, addr) >> 26;
186 return mask[n >> 5] & (1 << (n & 31));
187}
188
189static int update_filter(struct tap_filter *filter, void __user *arg)
190{
191 struct { u8 u[ETH_ALEN]; } *addr;
192 struct tun_filter uf;
193 int err, alen, n, nexact;
194
195 if (copy_from_user(&uf, arg, sizeof(uf)))
196 return -EFAULT;
197
198 if (!uf.count) {
199 /* Disabled */
200 filter->count = 0;
201 return 0;
202 }
203
204 alen = ETH_ALEN * uf.count;
205 addr = kmalloc(alen, GFP_KERNEL);
206 if (!addr)
207 return -ENOMEM;
208
209 if (copy_from_user(addr, arg + sizeof(uf), alen)) {
210 err = -EFAULT;
211 goto done;
212 }
213
214 /* The filter is updated without holding any locks. Which is
215 * perfectly safe. We disable it first and in the worst
216 * case we'll accept a few undesired packets. */
217 filter->count = 0;
218 wmb();
219
220 /* Use first set of addresses as an exact filter */
221 for (n = 0; n < uf.count && n < FLT_EXACT_COUNT; n++)
222 memcpy(filter->addr[n], addr[n].u, ETH_ALEN);
223
224 nexact = n;
225
226 /* The rest is hashed */
227 memset(filter->mask, 0, sizeof(filter->mask));
228 for (; n < uf.count; n++)
229 addr_hash_set(filter->mask, addr[n].u);
230
231 /* For ALLMULTI just set the mask to all ones.
232 * This overrides the mask populated above. */
233 if ((uf.flags & TUN_FLT_ALLMULTI))
234 memset(filter->mask, ~0, sizeof(filter->mask));
235
236 /* Now enable the filter */
237 wmb();
238 filter->count = nexact;
239
240 /* Return the number of exact filters */
241 err = nexact;
242
243done:
244 kfree(addr);
245 return err;
246}
247
248/* Returns: 0 - drop, !=0 - accept */
249static int run_filter(struct tap_filter *filter, const struct sk_buff *skb)
250{
251 /* Cannot use eth_hdr(skb) here because skb_mac_hdr() is incorrect
252 * at this point. */
253 struct ethhdr *eh = (struct ethhdr *) skb->data;
254 int i;
255
256 /* Exact match */
257 for (i = 0; i < filter->count; i++)
258 if (!compare_ether_addr(eh->h_dest, filter->addr[i]))
259 return 1;
260
261 /* Inexact match (multicast only) */
262 if (is_multicast_ether_addr(eh->h_dest))
263 return addr_hash_test(filter->mask, eh->h_dest);
264
265 return 0;
266}
267
268/*
269 * Checks whether the packet is accepted or not.
270 * Returns: 0 - drop, !=0 - accept
271 */
272static int check_filter(struct tap_filter *filter, const struct sk_buff *skb)
273{
274 if (!filter->count)
275 return 1;
276
277 return run_filter(filter, skb);
278}
279
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280/* Network device part of the driver */
281
Jeff Garzik7282d492006-09-13 14:30:00 -0400282static const struct ethtool_ops tun_ethtool_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
284/* Net device open. */
285static int tun_net_open(struct net_device *dev)
286{
287 netif_start_queue(dev);
288 return 0;
289}
290
291/* Net device close. */
292static int tun_net_close(struct net_device *dev)
293{
294 netif_stop_queue(dev);
295 return 0;
296}
297
298/* Net device start xmit */
299static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
300{
301 struct tun_struct *tun = netdev_priv(dev);
302
303 DBG(KERN_INFO "%s: tun_net_xmit %d\n", tun->dev->name, skb->len);
304
305 /* Drop packet if interface is not attached */
Eric W. Biederman631ab462009-01-20 11:00:40 +0000306 if (!tun->tfile)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 goto drop;
308
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -0700309 /* Drop if the filter does not like it.
310 * This is a noop if the filter is disabled.
311 * Filter can be enabled only for the TAP devices. */
312 if (!check_filter(&tun->txflt, skb))
313 goto drop;
314
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 if (skb_queue_len(&tun->readq) >= dev->tx_queue_len) {
316 if (!(tun->flags & TUN_ONE_QUEUE)) {
317 /* Normal queueing mode. */
318 /* Packet scheduler handles dropping of further packets. */
319 netif_stop_queue(dev);
320
321 /* We won't see all dropped packets individually, so overrun
322 * error is more appropriate. */
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700323 dev->stats.tx_fifo_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 } else {
325 /* Single queue mode.
326 * Driver handles dropping of all packets itself. */
327 goto drop;
328 }
329 }
330
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -0700331 /* Enqueue packet */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 skb_queue_tail(&tun->readq, skb);
333 dev->trans_start = jiffies;
334
335 /* Notify and wake up reader process */
336 if (tun->flags & TUN_FASYNC)
337 kill_fasync(&tun->fasync, SIGIO, POLL_IN);
338 wake_up_interruptible(&tun->read_wait);
339 return 0;
340
341drop:
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700342 dev->stats.tx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 kfree_skb(skb);
344 return 0;
345}
346
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -0700347static void tun_net_mclist(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348{
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -0700349 /*
350 * This callback is supposed to deal with mc filter in
351 * _rx_ path and has nothing to do with the _tx_ path.
352 * In rx path we always accept everything userspace gives us.
353 */
354 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355}
356
Ed Swierk4885a502007-09-16 12:21:38 -0700357#define MIN_MTU 68
358#define MAX_MTU 65535
359
360static int
361tun_net_change_mtu(struct net_device *dev, int new_mtu)
362{
363 if (new_mtu < MIN_MTU || new_mtu + dev->hard_header_len > MAX_MTU)
364 return -EINVAL;
365 dev->mtu = new_mtu;
366 return 0;
367}
368
Stephen Hemminger758e43b2008-11-19 22:10:37 -0800369static const struct net_device_ops tun_netdev_ops = {
370 .ndo_open = tun_net_open,
371 .ndo_stop = tun_net_close,
Stephen Hemminger00829822008-11-20 20:14:53 -0800372 .ndo_start_xmit = tun_net_xmit,
Stephen Hemminger758e43b2008-11-19 22:10:37 -0800373 .ndo_change_mtu = tun_net_change_mtu,
Stephen Hemminger758e43b2008-11-19 22:10:37 -0800374};
375
376static const struct net_device_ops tap_netdev_ops = {
377 .ndo_open = tun_net_open,
378 .ndo_stop = tun_net_close,
Stephen Hemminger00829822008-11-20 20:14:53 -0800379 .ndo_start_xmit = tun_net_xmit,
Stephen Hemminger758e43b2008-11-19 22:10:37 -0800380 .ndo_change_mtu = tun_net_change_mtu,
381 .ndo_set_multicast_list = tun_net_mclist,
382 .ndo_set_mac_address = eth_mac_addr,
383 .ndo_validate_addr = eth_validate_addr,
384};
385
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386/* Initialize net device. */
387static void tun_net_init(struct net_device *dev)
388{
389 struct tun_struct *tun = netdev_priv(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400390
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 switch (tun->flags & TUN_TYPE_MASK) {
392 case TUN_TUN_DEV:
Stephen Hemminger758e43b2008-11-19 22:10:37 -0800393 dev->netdev_ops = &tun_netdev_ops;
394
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 /* Point-to-Point TUN Device */
396 dev->hard_header_len = 0;
397 dev->addr_len = 0;
398 dev->mtu = 1500;
399
400 /* Zero header length */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400401 dev->type = ARPHRD_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
403 dev->tx_queue_len = TUN_READQ_SIZE; /* We prefer our own queue length */
404 break;
405
406 case TUN_TAP_DEV:
Kusanagi Kouichi7a0a9602008-12-29 18:23:28 -0800407 dev->netdev_ops = &tap_netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 /* Ethernet TAP Device */
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -0700409 ether_setup(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -0700411 random_ether_addr(dev->dev_addr);
Brian Braunstein36226a82007-04-26 01:00:55 -0700412
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 dev->tx_queue_len = TUN_READQ_SIZE; /* We prefer our own queue length */
414 break;
415 }
416}
417
418/* Character device part */
419
420/* Poll */
421static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400422{
Eric W. Biederman631ab462009-01-20 11:00:40 +0000423 struct tun_struct *tun = tun_get(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 unsigned int mask = POLLOUT | POLLWRNORM;
425
426 if (!tun)
Eric W. Biedermaneac9e902009-01-20 10:59:05 +0000427 return POLLERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428
429 DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);
430
431 poll_wait(file, &tun->read_wait, wait);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400432
David S. Millerb03efcf2005-07-08 14:57:23 -0700433 if (!skb_queue_empty(&tun->readq))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 mask |= POLLIN | POLLRDNORM;
435
Eric W. Biederman631ab462009-01-20 11:00:40 +0000436 tun_put(tun);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 return mask;
438}
439
Rusty Russellf42157c2008-08-15 15:15:10 -0700440/* prepad is the amount to reserve at front. len is length after that.
441 * linear is a hint as to how much to copy (usually headers). */
442static struct sk_buff *tun_alloc_skb(size_t prepad, size_t len, size_t linear,
443 gfp_t gfp)
444{
445 struct sk_buff *skb;
446 unsigned int i;
447
448 skb = alloc_skb(prepad + len, gfp|__GFP_NOWARN);
449 if (skb) {
450 skb_reserve(skb, prepad);
451 skb_put(skb, len);
452 return skb;
453 }
454
455 /* Under a page? Don't bother with paged skb. */
456 if (prepad + len < PAGE_SIZE)
457 return NULL;
458
459 /* Start with a normal skb, and add pages. */
460 skb = alloc_skb(prepad + linear, gfp);
461 if (!skb)
462 return NULL;
463
464 skb_reserve(skb, prepad);
465 skb_put(skb, linear);
466
467 len -= linear;
468
469 for (i = 0; i < MAX_SKB_FRAGS; i++) {
470 skb_frag_t *f = &skb_shinfo(skb)->frags[i];
471
472 f->page = alloc_page(gfp|__GFP_ZERO);
473 if (!f->page)
474 break;
475
476 f->page_offset = 0;
477 f->size = PAGE_SIZE;
478
479 skb->data_len += PAGE_SIZE;
480 skb->len += PAGE_SIZE;
481 skb->truesize += PAGE_SIZE;
482 skb_shinfo(skb)->nr_frags++;
483
484 if (len < PAGE_SIZE) {
485 len = 0;
486 break;
487 }
488 len -= PAGE_SIZE;
489 }
490
491 /* Too large, or alloc fail? */
492 if (unlikely(len)) {
493 kfree_skb(skb);
494 skb = NULL;
495 }
496
497 return skb;
498}
499
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500/* Get packet from user space buffer */
501static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, size_t count)
502{
503 struct tun_pi pi = { 0, __constant_htons(ETH_P_IP) };
504 struct sk_buff *skb;
505 size_t len = count, align = 0;
Rusty Russellf43798c2008-07-03 03:48:02 -0700506 struct virtio_net_hdr gso = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
508 if (!(tun->flags & TUN_NO_PI)) {
509 if ((len -= sizeof(pi)) > count)
510 return -EINVAL;
511
512 if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi)))
513 return -EFAULT;
514 }
515
Rusty Russellf43798c2008-07-03 03:48:02 -0700516 if (tun->flags & TUN_VNET_HDR) {
517 if ((len -= sizeof(gso)) > count)
518 return -EINVAL;
519
520 if (memcpy_fromiovec((void *)&gso, iv, sizeof(gso)))
521 return -EFAULT;
522
523 if (gso.hdr_len > len)
524 return -EINVAL;
525 }
526
Rusty Russelle01bf1c2008-04-12 18:49:30 -0700527 if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 align = NET_IP_ALIGN;
Rusty Russelle01bf1c2008-04-12 18:49:30 -0700529 if (unlikely(len < ETH_HLEN))
530 return -EINVAL;
531 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400532
Rusty Russellf42157c2008-08-15 15:15:10 -0700533 if (!(skb = tun_alloc_skb(align, len, gso.hdr_len, GFP_KERNEL))) {
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700534 tun->dev->stats.rx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 return -ENOMEM;
536 }
537
Rusty Russellf42157c2008-08-15 15:15:10 -0700538 if (skb_copy_datagram_from_iovec(skb, 0, iv, len)) {
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700539 tun->dev->stats.rx_dropped++;
Dave Jones8f227572006-03-11 18:49:13 -0800540 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 return -EFAULT;
Dave Jones8f227572006-03-11 18:49:13 -0800542 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
Rusty Russellf43798c2008-07-03 03:48:02 -0700544 if (gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
545 if (!skb_partial_csum_set(skb, gso.csum_start,
546 gso.csum_offset)) {
547 tun->dev->stats.rx_frame_errors++;
548 kfree_skb(skb);
549 return -EINVAL;
550 }
551 } else if (tun->flags & TUN_NOCHECKSUM)
552 skb->ip_summed = CHECKSUM_UNNECESSARY;
553
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 switch (tun->flags & TUN_TYPE_MASK) {
555 case TUN_TUN_DEV:
Ang Way Chuangf09f7ee2008-06-17 21:10:33 -0700556 if (tun->flags & TUN_NO_PI) {
557 switch (skb->data[0] & 0xf0) {
558 case 0x40:
559 pi.proto = htons(ETH_P_IP);
560 break;
561 case 0x60:
562 pi.proto = htons(ETH_P_IPV6);
563 break;
564 default:
565 tun->dev->stats.rx_dropped++;
566 kfree_skb(skb);
567 return -EINVAL;
568 }
569 }
570
Arnaldo Carvalho de Melo459a98e2007-03-19 15:30:44 -0700571 skb_reset_mac_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 skb->protocol = pi.proto;
Arnaldo Carvalho de Melo4c13eb62007-04-25 17:40:23 -0700573 skb->dev = tun->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 break;
575 case TUN_TAP_DEV:
576 skb->protocol = eth_type_trans(skb, tun->dev);
577 break;
578 };
579
Rusty Russellf43798c2008-07-03 03:48:02 -0700580 if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
581 pr_debug("GSO!\n");
582 switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
583 case VIRTIO_NET_HDR_GSO_TCPV4:
584 skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
585 break;
586 case VIRTIO_NET_HDR_GSO_TCPV6:
587 skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
588 break;
589 default:
590 tun->dev->stats.rx_frame_errors++;
591 kfree_skb(skb);
592 return -EINVAL;
593 }
594
595 if (gso.gso_type & VIRTIO_NET_HDR_GSO_ECN)
596 skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
597
598 skb_shinfo(skb)->gso_size = gso.gso_size;
599 if (skb_shinfo(skb)->gso_size == 0) {
600 tun->dev->stats.rx_frame_errors++;
601 kfree_skb(skb);
602 return -EINVAL;
603 }
604
605 /* Header must be checked, and gso_segs computed. */
606 skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
607 skb_shinfo(skb)->gso_segs = 0;
608 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400609
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 netif_rx_ni(skb);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400611
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700612 tun->dev->stats.rx_packets++;
613 tun->dev->stats.rx_bytes += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
615 return count;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400616}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617
Badari Pulavartyee0b3e62006-09-30 23:28:47 -0700618static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
619 unsigned long count, loff_t pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620{
Eric W. Biederman631ab462009-01-20 11:00:40 +0000621 struct tun_struct *tun = tun_get(iocb->ki_filp);
622 ssize_t result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623
624 if (!tun)
625 return -EBADFD;
626
627 DBG(KERN_INFO "%s: tun_chr_write %ld\n", tun->dev->name, count);
628
Eric W. Biederman631ab462009-01-20 11:00:40 +0000629 result = tun_get_user(tun, (struct iovec *) iv, iov_length(iv, count));
630
631 tun_put(tun);
632 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633}
634
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635/* Put packet to the user space buffer */
636static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
637 struct sk_buff *skb,
638 struct iovec *iv, int len)
639{
640 struct tun_pi pi = { 0, skb->protocol };
641 ssize_t total = 0;
642
643 if (!(tun->flags & TUN_NO_PI)) {
644 if ((len -= sizeof(pi)) < 0)
645 return -EINVAL;
646
647 if (len < skb->len) {
648 /* Packet will be striped */
649 pi.flags |= TUN_PKT_STRIP;
650 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400651
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 if (memcpy_toiovec(iv, (void *) &pi, sizeof(pi)))
653 return -EFAULT;
654 total += sizeof(pi);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400655 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
Rusty Russellf43798c2008-07-03 03:48:02 -0700657 if (tun->flags & TUN_VNET_HDR) {
658 struct virtio_net_hdr gso = { 0 }; /* no info leak */
659 if ((len -= sizeof(gso)) < 0)
660 return -EINVAL;
661
662 if (skb_is_gso(skb)) {
663 struct skb_shared_info *sinfo = skb_shinfo(skb);
664
665 /* This is a hint as to how much should be linear. */
666 gso.hdr_len = skb_headlen(skb);
667 gso.gso_size = sinfo->gso_size;
668 if (sinfo->gso_type & SKB_GSO_TCPV4)
669 gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
670 else if (sinfo->gso_type & SKB_GSO_TCPV6)
671 gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
672 else
673 BUG();
674 if (sinfo->gso_type & SKB_GSO_TCP_ECN)
675 gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN;
676 } else
677 gso.gso_type = VIRTIO_NET_HDR_GSO_NONE;
678
679 if (skb->ip_summed == CHECKSUM_PARTIAL) {
680 gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
681 gso.csum_start = skb->csum_start - skb_headroom(skb);
682 gso.csum_offset = skb->csum_offset;
683 } /* else everything is zero */
684
685 if (unlikely(memcpy_toiovec(iv, (void *)&gso, sizeof(gso))))
686 return -EFAULT;
687 total += sizeof(gso);
688 }
689
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 len = min_t(int, skb->len, len);
691
692 skb_copy_datagram_iovec(skb, 0, iv, len);
693 total += len;
694
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700695 tun->dev->stats.tx_packets++;
696 tun->dev->stats.tx_bytes += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697
698 return total;
699}
700
Badari Pulavartyee0b3e62006-09-30 23:28:47 -0700701static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
702 unsigned long count, loff_t pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703{
Badari Pulavartyee0b3e62006-09-30 23:28:47 -0700704 struct file *file = iocb->ki_filp;
Eric W. Biederman631ab462009-01-20 11:00:40 +0000705 struct tun_struct *tun = tun_get(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 DECLARE_WAITQUEUE(wait, current);
707 struct sk_buff *skb;
708 ssize_t len, ret = 0;
709
710 if (!tun)
711 return -EBADFD;
712
713 DBG(KERN_INFO "%s: tun_chr_read\n", tun->dev->name);
714
Akinobu Mita52427c92007-11-19 22:46:51 -0800715 len = iov_length(iv, count);
Eric W. Biederman631ab462009-01-20 11:00:40 +0000716 if (len < 0) {
717 ret = -EINVAL;
718 goto out;
719 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720
721 add_wait_queue(&tun->read_wait, &wait);
722 while (len) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 current->state = TASK_INTERRUPTIBLE;
724
725 /* Read frames from the queue */
726 if (!(skb=skb_dequeue(&tun->readq))) {
727 if (file->f_flags & O_NONBLOCK) {
728 ret = -EAGAIN;
729 break;
730 }
731 if (signal_pending(current)) {
732 ret = -ERESTARTSYS;
733 break;
734 }
735
736 /* Nothing to read, let's sleep */
737 schedule();
738 continue;
739 }
740 netif_wake_queue(tun->dev);
741
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -0700742 ret = tun_put_user(tun, skb, (struct iovec *) iv, len);
743 kfree_skb(skb);
744 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 }
746
747 current->state = TASK_RUNNING;
748 remove_wait_queue(&tun->read_wait, &wait);
749
Eric W. Biederman631ab462009-01-20 11:00:40 +0000750out:
751 tun_put(tun);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 return ret;
753}
754
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755static void tun_setup(struct net_device *dev)
756{
757 struct tun_struct *tun = netdev_priv(dev);
758
759 skb_queue_head_init(&tun->readq);
760 init_waitqueue_head(&tun->read_wait);
761
762 tun->owner = -1;
Guido Guenther8c644622007-07-02 22:50:25 -0700763 tun->group = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 dev->ethtool_ops = &tun_ethtool_ops;
766 dev->destructor = free_netdev;
Pavel Emelyanovfc54c652008-04-16 00:41:53 -0700767 dev->features |= NETIF_F_NETNS_LOCAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768}
769
Pavel Emelyanovd647a592008-04-16 00:41:16 -0700770static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771{
772 struct tun_struct *tun;
773 struct net_device *dev;
774 int err;
775
Eric W. Biederman74a3e5a2009-01-20 10:56:20 +0000776 dev = __dev_get_by_name(net, ifr->ifr_name);
777 if (dev) {
778 if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops)
779 tun = netdev_priv(dev);
780 else if ((ifr->ifr_flags & IFF_TAP) && dev->netdev_ops == &tap_netdev_ops)
781 tun = netdev_priv(dev);
782 else
783 return -EINVAL;
784
Eric W. Biedermana7385ba2009-01-20 10:57:48 +0000785 err = tun_attach(tun, file);
786 if (err < 0)
787 return err;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400788 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 else {
790 char *name;
791 unsigned long flags = 0;
792
793 err = -EINVAL;
794
David Woodhouseca6bb5d2006-06-22 16:07:52 -0700795 if (!capable(CAP_NET_ADMIN))
796 return -EPERM;
797
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 /* Set dev type */
799 if (ifr->ifr_flags & IFF_TUN) {
800 /* TUN device */
801 flags |= TUN_TUN_DEV;
802 name = "tun%d";
803 } else if (ifr->ifr_flags & IFF_TAP) {
804 /* TAP device */
805 flags |= TUN_TAP_DEV;
806 name = "tap%d";
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400807 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 goto failed;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400809
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 if (*ifr->ifr_name)
811 name = ifr->ifr_name;
812
813 dev = alloc_netdev(sizeof(struct tun_struct), name,
814 tun_setup);
815 if (!dev)
816 return -ENOMEM;
817
Pavel Emelyanovfc54c652008-04-16 00:41:53 -0700818 dev_net_set(dev, net);
Stephen Hemminger758e43b2008-11-19 22:10:37 -0800819
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 tun = netdev_priv(dev);
821 tun->dev = dev;
822 tun->flags = flags;
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -0700823 tun->txflt.count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824
825 tun_net_init(dev);
826
827 if (strchr(dev->name, '%')) {
828 err = dev_alloc_name(dev, dev->name);
829 if (err < 0)
830 goto err_free_dev;
831 }
832
833 err = register_netdevice(tun->dev);
834 if (err < 0)
835 goto err_free_dev;
Eric W. Biedermana7385ba2009-01-20 10:57:48 +0000836
837 err = tun_attach(tun, file);
838 if (err < 0)
839 goto err_free_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 }
841
842 DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name);
843
844 if (ifr->ifr_flags & IFF_NO_PI)
845 tun->flags |= TUN_NO_PI;
Nathaniel Filardoa26af1e2008-02-05 03:05:07 -0800846 else
847 tun->flags &= ~TUN_NO_PI;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848
849 if (ifr->ifr_flags & IFF_ONE_QUEUE)
850 tun->flags |= TUN_ONE_QUEUE;
Nathaniel Filardoa26af1e2008-02-05 03:05:07 -0800851 else
852 tun->flags &= ~TUN_ONE_QUEUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853
Rusty Russellf43798c2008-07-03 03:48:02 -0700854 if (ifr->ifr_flags & IFF_VNET_HDR)
855 tun->flags |= TUN_VNET_HDR;
856 else
857 tun->flags &= ~TUN_VNET_HDR;
858
Max Krasnyanskye35259a2008-07-10 16:59:11 -0700859 /* Make sure persistent devices do not get stuck in
860 * xoff state.
861 */
862 if (netif_running(tun->dev))
863 netif_wake_queue(tun->dev);
864
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 strcpy(ifr->ifr_name, tun->dev->name);
866 return 0;
867
868 err_free_dev:
869 free_netdev(dev);
870 failed:
871 return err;
872}
873
Mark McLoughline3b99552008-08-15 15:09:56 -0700874static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr)
875{
Eric W. Biederman631ab462009-01-20 11:00:40 +0000876 struct tun_struct *tun = tun_get(file);
Mark McLoughline3b99552008-08-15 15:09:56 -0700877
878 if (!tun)
879 return -EBADFD;
880
881 DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name);
882
883 strcpy(ifr->ifr_name, tun->dev->name);
884
885 ifr->ifr_flags = 0;
886
887 if (ifr->ifr_flags & TUN_TUN_DEV)
888 ifr->ifr_flags |= IFF_TUN;
889 else
890 ifr->ifr_flags |= IFF_TAP;
891
892 if (tun->flags & TUN_NO_PI)
893 ifr->ifr_flags |= IFF_NO_PI;
894
895 if (tun->flags & TUN_ONE_QUEUE)
896 ifr->ifr_flags |= IFF_ONE_QUEUE;
897
898 if (tun->flags & TUN_VNET_HDR)
899 ifr->ifr_flags |= IFF_VNET_HDR;
900
Eric W. Biederman631ab462009-01-20 11:00:40 +0000901 tun_put(tun);
Mark McLoughline3b99552008-08-15 15:09:56 -0700902 return 0;
903}
904
Rusty Russell5228ddc2008-07-03 03:46:16 -0700905/* This is like a cut-down ethtool ops, except done via tun fd so no
906 * privs required. */
907static int set_offload(struct net_device *dev, unsigned long arg)
908{
909 unsigned int old_features, features;
910
911 old_features = dev->features;
912 /* Unset features, set them as we chew on the arg. */
913 features = (old_features & ~(NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST
914 |NETIF_F_TSO_ECN|NETIF_F_TSO|NETIF_F_TSO6));
915
916 if (arg & TUN_F_CSUM) {
917 features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
918 arg &= ~TUN_F_CSUM;
919
920 if (arg & (TUN_F_TSO4|TUN_F_TSO6)) {
921 if (arg & TUN_F_TSO_ECN) {
922 features |= NETIF_F_TSO_ECN;
923 arg &= ~TUN_F_TSO_ECN;
924 }
925 if (arg & TUN_F_TSO4)
926 features |= NETIF_F_TSO;
927 if (arg & TUN_F_TSO6)
928 features |= NETIF_F_TSO6;
929 arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
930 }
931 }
932
933 /* This gives the user a way to test for new features in future by
934 * trying to set them. */
935 if (arg)
936 return -EINVAL;
937
938 dev->features = features;
939 if (old_features != dev->features)
940 netdev_features_change(dev);
941
942 return 0;
943}
944
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400945static int tun_chr_ioctl(struct inode *inode, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 unsigned int cmd, unsigned long arg)
947{
Eric W. Biederman36b50ba2009-01-20 11:01:48 +0000948 struct tun_file *tfile = file->private_data;
Eric W. Biederman631ab462009-01-20 11:00:40 +0000949 struct tun_struct *tun;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 void __user* argp = (void __user*)arg;
951 struct ifreq ifr;
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -0700952 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953
954 if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89)
955 if (copy_from_user(&ifr, argp, sizeof ifr))
956 return -EFAULT;
957
Eric W. Biederman631ab462009-01-20 11:00:40 +0000958 if (cmd == TUNGETFEATURES) {
959 /* Currently this just means: "what IFF flags are valid?".
960 * This is needed because we never checked for invalid flags on
961 * TUNSETIFF. */
962 return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE |
963 IFF_VNET_HDR,
964 (unsigned int __user*)argp);
965 }
966
Eric W. Biederman36b50ba2009-01-20 11:01:48 +0000967 tun = __tun_get(tfile);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 if (cmd == TUNSETIFF && !tun) {
969 int err;
970
971 ifr.ifr_name[IFNAMSIZ-1] = '\0';
972
973 rtnl_lock();
Eric W. Biederman36b50ba2009-01-20 11:01:48 +0000974 err = tun_set_iff(tfile->net, file, &ifr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 rtnl_unlock();
976
977 if (err)
978 return err;
979
980 if (copy_to_user(argp, &ifr, sizeof(ifr)))
981 return -EFAULT;
982 return 0;
983 }
984
Rusty Russell07240fd2008-07-03 03:45:32 -0700985
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 if (!tun)
987 return -EBADFD;
988
989 DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd);
990
Eric W. Biederman631ab462009-01-20 11:00:40 +0000991 ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 switch (cmd) {
Mark McLoughline3b99552008-08-15 15:09:56 -0700993 case TUNGETIFF:
994 ret = tun_get_iff(current->nsproxy->net_ns, file, &ifr);
995 if (ret)
Eric W. Biederman631ab462009-01-20 11:00:40 +0000996 break;
Mark McLoughline3b99552008-08-15 15:09:56 -0700997
998 if (copy_to_user(argp, &ifr, sizeof(ifr)))
Eric W. Biederman631ab462009-01-20 11:00:40 +0000999 ret = -EFAULT;
Mark McLoughline3b99552008-08-15 15:09:56 -07001000 break;
1001
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 case TUNSETNOCSUM:
1003 /* Disable/Enable checksum */
1004 if (arg)
1005 tun->flags |= TUN_NOCHECKSUM;
1006 else
1007 tun->flags &= ~TUN_NOCHECKSUM;
1008
1009 DBG(KERN_INFO "%s: checksum %s\n",
1010 tun->dev->name, arg ? "disabled" : "enabled");
1011 break;
1012
1013 case TUNSETPERSIST:
1014 /* Disable/Enable persist mode */
1015 if (arg)
1016 tun->flags |= TUN_PERSIST;
1017 else
1018 tun->flags &= ~TUN_PERSIST;
1019
1020 DBG(KERN_INFO "%s: persist %s\n",
Toyo Abec6e991d2007-12-24 21:29:35 -08001021 tun->dev->name, arg ? "enabled" : "disabled");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 break;
1023
1024 case TUNSETOWNER:
1025 /* Set owner of the device */
1026 tun->owner = (uid_t) arg;
1027
1028 DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner);
1029 break;
1030
Guido Guenther8c644622007-07-02 22:50:25 -07001031 case TUNSETGROUP:
1032 /* Set group of the device */
1033 tun->group= (gid_t) arg;
1034
1035 DBG(KERN_INFO "%s: group set to %d\n", tun->dev->name, tun->group);
1036 break;
1037
Mike Kershawff4cc3a2005-09-01 17:40:05 -07001038 case TUNSETLINK:
1039 /* Only allow setting the type when the interface is down */
David S. Miller48abfe02008-04-23 19:37:58 -07001040 rtnl_lock();
Mike Kershawff4cc3a2005-09-01 17:40:05 -07001041 if (tun->dev->flags & IFF_UP) {
1042 DBG(KERN_INFO "%s: Linktype set failed because interface is up\n",
1043 tun->dev->name);
David S. Miller48abfe02008-04-23 19:37:58 -07001044 ret = -EBUSY;
Mike Kershawff4cc3a2005-09-01 17:40:05 -07001045 } else {
1046 tun->dev->type = (int) arg;
1047 DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type);
David S. Miller48abfe02008-04-23 19:37:58 -07001048 ret = 0;
Mike Kershawff4cc3a2005-09-01 17:40:05 -07001049 }
David S. Miller48abfe02008-04-23 19:37:58 -07001050 rtnl_unlock();
Eric W. Biederman631ab462009-01-20 11:00:40 +00001051 break;
Mike Kershawff4cc3a2005-09-01 17:40:05 -07001052
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053#ifdef TUN_DEBUG
1054 case TUNSETDEBUG:
1055 tun->debug = arg;
1056 break;
1057#endif
Rusty Russell5228ddc2008-07-03 03:46:16 -07001058 case TUNSETOFFLOAD:
Rusty Russell5228ddc2008-07-03 03:46:16 -07001059 rtnl_lock();
1060 ret = set_offload(tun->dev, arg);
1061 rtnl_unlock();
Eric W. Biederman631ab462009-01-20 11:00:40 +00001062 break;
Rusty Russell5228ddc2008-07-03 03:46:16 -07001063
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -07001064 case TUNSETTXFILTER:
1065 /* Can be set only for TAPs */
Eric W. Biederman631ab462009-01-20 11:00:40 +00001066 ret = -EINVAL;
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -07001067 if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
Eric W. Biederman631ab462009-01-20 11:00:40 +00001068 break;
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -07001069 rtnl_lock();
Harvey Harrisonc0e5a8c2008-07-16 12:45:34 -07001070 ret = update_filter(&tun->txflt, (void __user *)arg);
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -07001071 rtnl_unlock();
Eric W. Biederman631ab462009-01-20 11:00:40 +00001072 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
1074 case SIOCGIFHWADDR:
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -07001075 /* Get hw addres */
1076 memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN);
1077 ifr.ifr_hwaddr.sa_family = tun->dev->type;
1078 if (copy_to_user(argp, &ifr, sizeof ifr))
Eric W. Biederman631ab462009-01-20 11:00:40 +00001079 ret = -EFAULT;
1080 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
1082 case SIOCSIFHWADDR:
Max Krasnyanskyf271b2cc2008-07-14 22:18:19 -07001083 /* Set hw address */
Johannes Berge1749612008-10-27 15:59:26 -07001084 DBG(KERN_DEBUG "%s: set hw address: %pM\n",
1085 tun->dev->name, ifr.ifr_hwaddr.sa_data);
Kim B. Heino40102372008-02-29 12:26:21 -08001086
1087 rtnl_lock();
1088 ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
1089 rtnl_unlock();
Eric W. Biederman631ab462009-01-20 11:00:40 +00001090 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 default:
Eric W. Biederman631ab462009-01-20 11:00:40 +00001092 ret = -EINVAL;
1093 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 };
1095
Eric W. Biederman631ab462009-01-20 11:00:40 +00001096 tun_put(tun);
1097 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098}
1099
1100static int tun_chr_fasync(int fd, struct file *file, int on)
1101{
Eric W. Biederman631ab462009-01-20 11:00:40 +00001102 struct tun_struct *tun = tun_get(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 int ret;
1104
1105 if (!tun)
1106 return -EBADFD;
1107
1108 DBG(KERN_INFO "%s: tun_chr_fasync %d\n", tun->dev->name, on);
1109
Jonathan Corbet9d319522008-06-19 15:50:37 -06001110 lock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0)
Jonathan Corbet9d319522008-06-19 15:50:37 -06001112 goto out;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001113
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 if (on) {
Eric W. Biederman609d7fa2006-10-02 02:17:15 -07001115 ret = __f_setown(file, task_pid(current), PIDTYPE_PID, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 if (ret)
Jonathan Corbet9d319522008-06-19 15:50:37 -06001117 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 tun->flags |= TUN_FASYNC;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001119 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 tun->flags &= ~TUN_FASYNC;
Jonathan Corbet9d319522008-06-19 15:50:37 -06001121 ret = 0;
1122out:
1123 unlock_kernel();
Eric W. Biederman631ab462009-01-20 11:00:40 +00001124 tun_put(tun);
Jonathan Corbet9d319522008-06-19 15:50:37 -06001125 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126}
1127
1128static int tun_chr_open(struct inode *inode, struct file * file)
1129{
Eric W. Biederman631ab462009-01-20 11:00:40 +00001130 struct tun_file *tfile;
Arnd Bergmannfd3e05b2008-05-20 19:16:24 +02001131 cycle_kernel_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 DBG1(KERN_INFO "tunX: tun_chr_open\n");
Eric W. Biederman631ab462009-01-20 11:00:40 +00001133
1134 tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
1135 if (!tfile)
1136 return -ENOMEM;
1137 tfile->tun = NULL;
Eric W. Biederman36b50ba2009-01-20 11:01:48 +00001138 tfile->net = get_net(current->nsproxy->net_ns);
Eric W. Biederman631ab462009-01-20 11:00:40 +00001139 file->private_data = tfile;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 return 0;
1141}
1142
1143static int tun_chr_close(struct inode *inode, struct file *file)
1144{
Eric W. Biederman631ab462009-01-20 11:00:40 +00001145 struct tun_file *tfile = file->private_data;
1146 struct tun_struct *tun = __tun_get(tfile);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
Eric W. Biederman631ab462009-01-20 11:00:40 +00001149 if (tun) {
1150 DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
Eric W. Biederman631ab462009-01-20 11:00:40 +00001152 rtnl_lock();
1153 __tun_detach(tun);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
Eric W. Biederman631ab462009-01-20 11:00:40 +00001155 /* If desireable, unregister the netdevice. */
1156 if (!(tun->flags & TUN_PERSIST))
1157 unregister_netdevice(tun->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158
Eric W. Biederman631ab462009-01-20 11:00:40 +00001159 rtnl_unlock();
1160 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161
Eric W. Biederman36b50ba2009-01-20 11:01:48 +00001162 put_net(tfile->net);
Eric W. Biederman631ab462009-01-20 11:00:40 +00001163 kfree(tfile);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
1165 return 0;
1166}
1167
Arjan van de Vend54b1fd2007-02-12 00:55:34 -08001168static const struct file_operations tun_fops = {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001169 .owner = THIS_MODULE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 .llseek = no_llseek,
Badari Pulavartyee0b3e62006-09-30 23:28:47 -07001171 .read = do_sync_read,
1172 .aio_read = tun_chr_aio_read,
1173 .write = do_sync_write,
1174 .aio_write = tun_chr_aio_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 .poll = tun_chr_poll,
1176 .ioctl = tun_chr_ioctl,
1177 .open = tun_chr_open,
1178 .release = tun_chr_close,
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001179 .fasync = tun_chr_fasync
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180};
1181
1182static struct miscdevice tun_miscdev = {
1183 .minor = TUN_MINOR,
1184 .name = "tun",
1185 .fops = &tun_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186};
1187
1188/* ethtool interface */
1189
1190static int tun_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1191{
1192 cmd->supported = 0;
1193 cmd->advertising = 0;
1194 cmd->speed = SPEED_10;
1195 cmd->duplex = DUPLEX_FULL;
1196 cmd->port = PORT_TP;
1197 cmd->phy_address = 0;
1198 cmd->transceiver = XCVR_INTERNAL;
1199 cmd->autoneg = AUTONEG_DISABLE;
1200 cmd->maxtxpkt = 0;
1201 cmd->maxrxpkt = 0;
1202 return 0;
1203}
1204
1205static void tun_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
1206{
1207 struct tun_struct *tun = netdev_priv(dev);
1208
1209 strcpy(info->driver, DRV_NAME);
1210 strcpy(info->version, DRV_VERSION);
1211 strcpy(info->fw_version, "N/A");
1212
1213 switch (tun->flags & TUN_TYPE_MASK) {
1214 case TUN_TUN_DEV:
1215 strcpy(info->bus_info, "tun");
1216 break;
1217 case TUN_TAP_DEV:
1218 strcpy(info->bus_info, "tap");
1219 break;
1220 }
1221}
1222
1223static u32 tun_get_msglevel(struct net_device *dev)
1224{
1225#ifdef TUN_DEBUG
1226 struct tun_struct *tun = netdev_priv(dev);
1227 return tun->debug;
1228#else
1229 return -EOPNOTSUPP;
1230#endif
1231}
1232
1233static void tun_set_msglevel(struct net_device *dev, u32 value)
1234{
1235#ifdef TUN_DEBUG
1236 struct tun_struct *tun = netdev_priv(dev);
1237 tun->debug = value;
1238#endif
1239}
1240
1241static u32 tun_get_link(struct net_device *dev)
1242{
1243 struct tun_struct *tun = netdev_priv(dev);
Eric W. Biederman631ab462009-01-20 11:00:40 +00001244 return !!tun->tfile;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245}
1246
1247static u32 tun_get_rx_csum(struct net_device *dev)
1248{
1249 struct tun_struct *tun = netdev_priv(dev);
1250 return (tun->flags & TUN_NOCHECKSUM) == 0;
1251}
1252
1253static int tun_set_rx_csum(struct net_device *dev, u32 data)
1254{
1255 struct tun_struct *tun = netdev_priv(dev);
1256 if (data)
1257 tun->flags &= ~TUN_NOCHECKSUM;
1258 else
1259 tun->flags |= TUN_NOCHECKSUM;
1260 return 0;
1261}
1262
Jeff Garzik7282d492006-09-13 14:30:00 -04001263static const struct ethtool_ops tun_ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 .get_settings = tun_get_settings,
1265 .get_drvinfo = tun_get_drvinfo,
1266 .get_msglevel = tun_get_msglevel,
1267 .set_msglevel = tun_set_msglevel,
1268 .get_link = tun_get_link,
1269 .get_rx_csum = tun_get_rx_csum,
1270 .set_rx_csum = tun_set_rx_csum
1271};
1272
Pavel Emelyanov79d17602008-04-16 00:40:46 -07001273static int tun_init_net(struct net *net)
1274{
Pavel Emelyanov79d17602008-04-16 00:40:46 -07001275 return 0;
1276}
1277
1278static void tun_exit_net(struct net *net)
1279{
Eric W. Biederman74a3e5a2009-01-20 10:56:20 +00001280 struct net_device *dev, *next;
Pavel Emelyanovd647a592008-04-16 00:41:16 -07001281
1282 rtnl_lock();
Eric W. Biederman74a3e5a2009-01-20 10:56:20 +00001283 for_each_netdev_safe(net, dev, next) {
1284 if (dev->ethtool_ops != &tun_ethtool_ops)
1285 continue;
1286 DBG(KERN_INFO "%s cleaned up\n", dev->name);
1287 unregister_netdevice(dev);
Pavel Emelyanovd647a592008-04-16 00:41:16 -07001288 }
1289 rtnl_unlock();
Pavel Emelyanov79d17602008-04-16 00:40:46 -07001290}
1291
1292static struct pernet_operations tun_net_ops = {
1293 .init = tun_init_net,
1294 .exit = tun_exit_net,
1295};
1296
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297static int __init tun_init(void)
1298{
1299 int ret = 0;
1300
1301 printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
1302 printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
1303
Eric W. Biederman74a3e5a2009-01-20 10:56:20 +00001304 ret = register_pernet_device(&tun_net_ops);
Pavel Emelyanov79d17602008-04-16 00:40:46 -07001305 if (ret) {
1306 printk(KERN_ERR "tun: Can't register pernet ops\n");
1307 goto err_pernet;
1308 }
1309
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 ret = misc_register(&tun_miscdev);
Pavel Emelyanov79d17602008-04-16 00:40:46 -07001311 if (ret) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR);
Pavel Emelyanov79d17602008-04-16 00:40:46 -07001313 goto err_misc;
1314 }
1315 return 0;
1316
1317err_misc:
Eric W. Biederman74a3e5a2009-01-20 10:56:20 +00001318 unregister_pernet_device(&tun_net_ops);
Pavel Emelyanov79d17602008-04-16 00:40:46 -07001319err_pernet:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 return ret;
1321}
1322
1323static void tun_cleanup(void)
1324{
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001325 misc_deregister(&tun_miscdev);
Eric W. Biederman74a3e5a2009-01-20 10:56:20 +00001326 unregister_pernet_device(&tun_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327}
1328
1329module_init(tun_init);
1330module_exit(tun_cleanup);
1331MODULE_DESCRIPTION(DRV_DESCRIPTION);
1332MODULE_AUTHOR(DRV_COPYRIGHT);
1333MODULE_LICENSE("GPL");
1334MODULE_ALIAS_MISCDEV(TUN_MINOR);