Blame view

drivers/net/tun.c 38.1 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  /*
   *  TUN - Universal TUN/TAP device driver.
   *  Copyright (C) 1999-2002 Maxim Krasnyansky <maxk@qualcomm.com>
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2 of the License, or
   *  (at your option) any later version.
   *
   *  This program is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   *  GNU General Public License for more details.
   *
   *  $Id: tun.c,v 1.15 2002/03/01 02:44:24 maxk Exp $
   */
  
  /*
   *  Changes:
   *
ff4cc3ac9   Mike Kershaw   [TUNTAP]: Allow s...
21
22
23
   *  Mike Kershaw <dragorn@kismetwireless.net> 2005/08/14
   *    Add TUNSETLINK ioctl to set the link encapsulation
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
   *  Mark Smith <markzzzsmith@yahoo.com.au>
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
25
   *    Use random_ether_addr() for tap MAC address.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
30
31
32
33
34
35
   *
   *  Harald Roelle <harald.roelle@ifi.lmu.de>  2004/04/20
   *    Fixes in packet dropping, queue length setting and queue wakeup.
   *    Increased default tx queue length.
   *    Added ethtool API.
   *    Minor cleanups
   *
   *  Daniel Podlejski <underley@underley.eu.org>
   *    Modifications for 2.3.99-pre5 kernel.
   */
6b8a66ee9   Joe Perches   tun: Convert logg...
36
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
  #define DRV_NAME	"tun"
  #define DRV_VERSION	"1.6"
  #define DRV_DESCRIPTION	"Universal TUN/TAP device driver"
  #define DRV_COPYRIGHT	"(C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  #include <linux/module.h>
  #include <linux/errno.h>
  #include <linux/kernel.h>
  #include <linux/major.h>
  #include <linux/slab.h>
  #include <linux/poll.h>
  #include <linux/fcntl.h>
  #include <linux/init.h>
  #include <linux/skbuff.h>
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/miscdevice.h>
  #include <linux/ethtool.h>
  #include <linux/rtnetlink.h>
50857e2a5   Arnd Bergmann   net/tun: handle c...
55
  #include <linux/compat.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
59
60
  #include <linux/if.h>
  #include <linux/if_arp.h>
  #include <linux/if_ether.h>
  #include <linux/if_tun.h>
  #include <linux/crc32.h>
d647a591d   Pavel Emelyanov   [TUN]: Make the t...
61
  #include <linux/nsproxy.h>
f43798c27   Rusty Russell   tun: Allow GSO us...
62
  #include <linux/virtio_net.h>
994051625   Michael S. Tsirkin   tun: socket filte...
63
  #include <linux/rcupdate.h>
881d966b4   Eric W. Biederman   [NET]: Make the d...
64
  #include <net/net_namespace.h>
79d176049   Pavel Emelyanov   [TUN]: Introduce ...
65
  #include <net/netns/generic.h>
f019a7a59   Eric W. Biederman   tun: Implement ip...
66
  #include <net/rtnetlink.h>
33dccbb05   Herbert Xu   tun: Limit amount...
67
  #include <net/sock.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
  
  #include <asm/system.h>
  #include <asm/uaccess.h>
14daa0213   Rusty Russell   net: make struct ...
71
72
  /* Uncomment to enable debugging */
  /* #define TUN_DEBUG 1 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
  #ifdef TUN_DEBUG
  static int debug;
14daa0213   Rusty Russell   net: make struct ...
75

6b8a66ee9   Joe Perches   tun: Convert logg...
76
77
78
79
80
81
82
83
84
85
  #define tun_debug(level, tun, fmt, args...)			\
  do {								\
  	if (tun->debug)						\
  		netdev_printk(level, tun->dev, fmt, ##args);	\
  } while (0)
  #define DBG1(level, fmt, args...)				\
  do {								\
  	if (debug == 2)						\
  		printk(level fmt, ##args);			\
  } while (0)
14daa0213   Rusty Russell   net: make struct ...
86
  #else
6b8a66ee9   Joe Perches   tun: Convert logg...
87
88
89
90
91
92
93
94
95
96
  #define tun_debug(level, tun, fmt, args...)			\
  do {								\
  	if (0)							\
  		netdev_printk(level, tun->dev, fmt, ##args);	\
  } while (0)
  #define DBG1(level, fmt, args...)				\
  do {								\
  	if (0)							\
  		printk(level fmt, ##args);			\
  } while (0)
14daa0213   Rusty Russell   net: make struct ...
97
  #endif
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
98
99
100
101
102
103
  #define FLT_EXACT_COUNT 8
  struct tap_filter {
  	unsigned int    count;    /* Number of addrs. Zero means disabled */
  	u32             mask[2];  /* Mask of the hashed addrs */
  	unsigned char	addr[FLT_EXACT_COUNT][ETH_ALEN];
  };
631ab46b7   Eric W. Biederman   tun: Introduce tu...
104
  struct tun_file {
c70f18294   Eric W. Biederman   tun: Fix races be...
105
  	atomic_t count;
631ab46b7   Eric W. Biederman   tun: Introduce tu...
106
  	struct tun_struct *tun;
36b50bab5   Eric W. Biederman   tun: Grab the net...
107
  	struct net *net;
631ab46b7   Eric W. Biederman   tun: Introduce tu...
108
  };
33dccbb05   Herbert Xu   tun: Limit amount...
109
  struct tun_sock;
14daa0213   Rusty Russell   net: make struct ...
110
  struct tun_struct {
631ab46b7   Eric W. Biederman   tun: Introduce tu...
111
  	struct tun_file		*tfile;
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
112
  	unsigned int 		flags;
14daa0213   Rusty Russell   net: make struct ...
113
114
  	uid_t			owner;
  	gid_t			group;
14daa0213   Rusty Russell   net: make struct ...
115
  	struct net_device	*dev;
882553752   Michał Mirosław   net: tun: convert...
116
117
118
  	u32			set_features;
  #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \
  			  NETIF_F_TSO6|NETIF_F_UFO)
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
119
  	struct fasync_struct	*fasync;
14daa0213   Rusty Russell   net: make struct ...
120

f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
121
  	struct tap_filter       txflt;
33dccbb05   Herbert Xu   tun: Limit amount...
122
  	struct socket		socket;
438154823   Eric Dumazet   net: sock_def_rea...
123
  	struct socket_wq	wq;
d9d52b517   Michael S. Tsirkin   tun: add ioctl to...
124
125
  
  	int			vnet_hdr_sz;
14daa0213   Rusty Russell   net: make struct ...
126
127
  #ifdef TUN_DEBUG
  	int debug;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  #endif
14daa0213   Rusty Russell   net: make struct ...
129
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130

33dccbb05   Herbert Xu   tun: Limit amount...
131
132
133
134
135
136
137
138
139
  struct tun_sock {
  	struct sock		sk;
  	struct tun_struct	*tun;
  };
  
  static inline struct tun_sock *tun_sk(struct sock *sk)
  {
  	return container_of(sk, struct tun_sock, sk);
  }
a7385ba21   Eric W. Biederman   tun: Fix races in...
140
141
  static int tun_attach(struct tun_struct *tun, struct file *file)
  {
631ab46b7   Eric W. Biederman   tun: Introduce tu...
142
  	struct tun_file *tfile = file->private_data;
38231b7a8   Eric W. Biederman   tun: Make tun_net...
143
  	int err;
a7385ba21   Eric W. Biederman   tun: Fix races in...
144
145
  
  	ASSERT_RTNL();
38231b7a8   Eric W. Biederman   tun: Make tun_net...
146
147
148
149
150
151
152
153
154
155
156
  	netif_tx_lock_bh(tun->dev);
  
  	err = -EINVAL;
  	if (tfile->tun)
  		goto out;
  
  	err = -EBUSY;
  	if (tun->tfile)
  		goto out;
  
  	err = 0;
631ab46b7   Eric W. Biederman   tun: Introduce tu...
157
158
  	tfile->tun = tun;
  	tun->tfile = tfile;
05c2828c7   Michael S. Tsirkin   tun: export under...
159
  	tun->socket.file = file;
bee31369c   Nolan Leake   tun: keep link (c...
160
  	netif_carrier_on(tun->dev);
c70f18294   Eric W. Biederman   tun: Fix races be...
161
  	dev_hold(tun->dev);
89f56d1e9   Michael S. Tsirkin   tun: reuse struct...
162
  	sock_hold(tun->socket.sk);
c70f18294   Eric W. Biederman   tun: Fix races be...
163
  	atomic_inc(&tfile->count);
a7385ba21   Eric W. Biederman   tun: Fix races in...
164

38231b7a8   Eric W. Biederman   tun: Make tun_net...
165
166
167
  out:
  	netif_tx_unlock_bh(tun->dev);
  	return err;
a7385ba21   Eric W. Biederman   tun: Fix races in...
168
  }
631ab46b7   Eric W. Biederman   tun: Introduce tu...
169
170
  static void __tun_detach(struct tun_struct *tun)
  {
631ab46b7   Eric W. Biederman   tun: Introduce tu...
171
  	/* Detach from net device */
38231b7a8   Eric W. Biederman   tun: Make tun_net...
172
  	netif_tx_lock_bh(tun->dev);
bee31369c   Nolan Leake   tun: keep link (c...
173
  	netif_carrier_off(tun->dev);
631ab46b7   Eric W. Biederman   tun: Introduce tu...
174
  	tun->tfile = NULL;
05c2828c7   Michael S. Tsirkin   tun: export under...
175
  	tun->socket.file = NULL;
38231b7a8   Eric W. Biederman   tun: Make tun_net...
176
  	netif_tx_unlock_bh(tun->dev);
631ab46b7   Eric W. Biederman   tun: Introduce tu...
177
178
  
  	/* Drop read queue */
89f56d1e9   Michael S. Tsirkin   tun: reuse struct...
179
  	skb_queue_purge(&tun->socket.sk->sk_receive_queue);
c70f18294   Eric W. Biederman   tun: Fix races be...
180
181
182
183
184
185
186
187
188
189
  
  	/* Drop the extra count on the net device */
  	dev_put(tun->dev);
  }
  
  static void tun_detach(struct tun_struct *tun)
  {
  	rtnl_lock();
  	__tun_detach(tun);
  	rtnl_unlock();
631ab46b7   Eric W. Biederman   tun: Introduce tu...
190
191
192
193
  }
  
  static struct tun_struct *__tun_get(struct tun_file *tfile)
  {
c70f18294   Eric W. Biederman   tun: Fix races be...
194
195
196
197
198
199
  	struct tun_struct *tun = NULL;
  
  	if (atomic_inc_not_zero(&tfile->count))
  		tun = tfile->tun;
  
  	return tun;
631ab46b7   Eric W. Biederman   tun: Introduce tu...
200
201
202
203
204
205
206
207
208
  }
  
  static struct tun_struct *tun_get(struct file *file)
  {
  	return __tun_get(file->private_data);
  }
  
  static void tun_put(struct tun_struct *tun)
  {
c70f18294   Eric W. Biederman   tun: Fix races be...
209
210
211
212
  	struct tun_file *tfile = tun->tfile;
  
  	if (atomic_dec_and_test(&tfile->count))
  		tun_detach(tfile->tun);
631ab46b7   Eric W. Biederman   tun: Introduce tu...
213
  }
6b8a66ee9   Joe Perches   tun: Convert logg...
214
  /* TAP filtering */
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
  static void addr_hash_set(u32 *mask, const u8 *addr)
  {
  	int n = ether_crc(ETH_ALEN, addr) >> 26;
  	mask[n >> 5] |= (1 << (n & 31));
  }
  
  static unsigned int addr_hash_test(const u32 *mask, const u8 *addr)
  {
  	int n = ether_crc(ETH_ALEN, addr) >> 26;
  	return mask[n >> 5] & (1 << (n & 31));
  }
  
  static int update_filter(struct tap_filter *filter, void __user *arg)
  {
  	struct { u8 u[ETH_ALEN]; } *addr;
  	struct tun_filter uf;
  	int err, alen, n, nexact;
  
  	if (copy_from_user(&uf, arg, sizeof(uf)))
  		return -EFAULT;
  
  	if (!uf.count) {
  		/* Disabled */
  		filter->count = 0;
  		return 0;
  	}
  
  	alen = ETH_ALEN * uf.count;
  	addr = kmalloc(alen, GFP_KERNEL);
  	if (!addr)
  		return -ENOMEM;
  
  	if (copy_from_user(addr, arg + sizeof(uf), alen)) {
  		err = -EFAULT;
  		goto done;
  	}
  
  	/* The filter is updated without holding any locks. Which is
  	 * perfectly safe. We disable it first and in the worst
  	 * case we'll accept a few undesired packets. */
  	filter->count = 0;
  	wmb();
  
  	/* Use first set of addresses as an exact filter */
  	for (n = 0; n < uf.count && n < FLT_EXACT_COUNT; n++)
  		memcpy(filter->addr[n], addr[n].u, ETH_ALEN);
  
  	nexact = n;
cfbf84fcb   Alex Williamson   tun: Fix unicast ...
263
264
  	/* Remaining multicast addresses are hashed,
  	 * unicast will leave the filter disabled. */
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
265
  	memset(filter->mask, 0, sizeof(filter->mask));
cfbf84fcb   Alex Williamson   tun: Fix unicast ...
266
267
268
269
270
  	for (; n < uf.count; n++) {
  		if (!is_multicast_ether_addr(addr[n].u)) {
  			err = 0; /* no filter */
  			goto done;
  		}
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
271
  		addr_hash_set(filter->mask, addr[n].u);
cfbf84fcb   Alex Williamson   tun: Fix unicast ...
272
  	}
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
  
  	/* For ALLMULTI just set the mask to all ones.
  	 * This overrides the mask populated above. */
  	if ((uf.flags & TUN_FLT_ALLMULTI))
  		memset(filter->mask, ~0, sizeof(filter->mask));
  
  	/* Now enable the filter */
  	wmb();
  	filter->count = nexact;
  
  	/* Return the number of exact filters */
  	err = nexact;
  
  done:
  	kfree(addr);
  	return err;
  }
  
  /* Returns: 0 - drop, !=0 - accept */
  static int run_filter(struct tap_filter *filter, const struct sk_buff *skb)
  {
  	/* Cannot use eth_hdr(skb) here because skb_mac_hdr() is incorrect
  	 * at this point. */
  	struct ethhdr *eh = (struct ethhdr *) skb->data;
  	int i;
  
  	/* Exact match */
  	for (i = 0; i < filter->count; i++)
  		if (!compare_ether_addr(eh->h_dest, filter->addr[i]))
  			return 1;
  
  	/* Inexact match (multicast only) */
  	if (is_multicast_ether_addr(eh->h_dest))
  		return addr_hash_test(filter->mask, eh->h_dest);
  
  	return 0;
  }
  
  /*
   * Checks whether the packet is accepted or not.
   * Returns: 0 - drop, !=0 - accept
   */
  static int check_filter(struct tap_filter *filter, const struct sk_buff *skb)
  {
  	if (!filter->count)
  		return 1;
  
  	return run_filter(filter, skb);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
  /* Network device part of the driver */
7282d491e   Jeff Garzik   drivers/net: cons...
323
  static const struct ethtool_ops tun_ethtool_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324

c70f18294   Eric W. Biederman   tun: Fix races be...
325
326
327
328
329
330
331
332
333
  /* Net device detach from fd. */
  static void tun_net_uninit(struct net_device *dev)
  {
  	struct tun_struct *tun = netdev_priv(dev);
  	struct tun_file *tfile = tun->tfile;
  
  	/* Inform the methods they need to stop using the dev.
  	 */
  	if (tfile) {
438154823   Eric Dumazet   net: sock_def_rea...
334
  		wake_up_all(&tun->wq.wait);
c70f18294   Eric W. Biederman   tun: Fix races be...
335
336
337
338
  		if (atomic_dec_and_test(&tfile->count))
  			__tun_detach(tun);
  	}
  }
9c3fea6ab   Herbert Xu   tun: Only free a ...
339
340
341
  static void tun_free_netdev(struct net_device *dev)
  {
  	struct tun_struct *tun = netdev_priv(dev);
89f56d1e9   Michael S. Tsirkin   tun: reuse struct...
342
  	sock_put(tun->socket.sk);
9c3fea6ab   Herbert Xu   tun: Only free a ...
343
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
  /* Net device open. */
  static int tun_net_open(struct net_device *dev)
  {
  	netif_start_queue(dev);
  	return 0;
  }
  
  /* Net device close. */
  static int tun_net_close(struct net_device *dev)
  {
  	netif_stop_queue(dev);
  	return 0;
  }
  
  /* Net device start xmit */
424efe9ca   Stephen Hemminger   netdev: convert p...
359
  static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
361
  {
  	struct tun_struct *tun = netdev_priv(dev);
6b8a66ee9   Joe Perches   tun: Convert logg...
362
363
  	tun_debug(KERN_INFO, tun, "tun_net_xmit %d
  ", skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
365
  
  	/* Drop packet if interface is not attached */
631ab46b7   Eric W. Biederman   tun: Introduce tu...
366
  	if (!tun->tfile)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
  		goto drop;
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
368
369
370
371
372
  	/* Drop if the filter does not like it.
  	 * This is a noop if the filter is disabled.
  	 * Filter can be enabled only for the TAP devices. */
  	if (!check_filter(&tun->txflt, skb))
  		goto drop;
994051625   Michael S. Tsirkin   tun: socket filte...
373
374
375
  	if (tun->socket.sk->sk_filter &&
  	    sk_filter(tun->socket.sk, skb))
  		goto drop;
89f56d1e9   Michael S. Tsirkin   tun: reuse struct...
376
  	if (skb_queue_len(&tun->socket.sk->sk_receive_queue) >= dev->tx_queue_len) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
378
379
380
381
382
383
  		if (!(tun->flags & TUN_ONE_QUEUE)) {
  			/* Normal queueing mode. */
  			/* Packet scheduler handles dropping of further packets. */
  			netif_stop_queue(dev);
  
  			/* We won't see all dropped packets individually, so overrun
  			 * error is more appropriate. */
09f75cd7b   Jeff Garzik   [NET] drivers/net...
384
  			dev->stats.tx_fifo_errors++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
386
387
388
389
390
  		} else {
  			/* Single queue mode.
  			 * Driver handles dropping of all packets itself. */
  			goto drop;
  		}
  	}
0110d6f22   Michael S. Tsirkin   tun: orphan an sk...
391
392
393
  	/* Orphan the skb - required as we might hang on to it
  	 * for indefinite time. */
  	skb_orphan(skb);
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
394
  	/* Enqueue packet */
89f56d1e9   Michael S. Tsirkin   tun: reuse struct...
395
  	skb_queue_tail(&tun->socket.sk->sk_receive_queue, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
398
399
  
  	/* Notify and wake up reader process */
  	if (tun->flags & TUN_FASYNC)
  		kill_fasync(&tun->fasync, SIGIO, POLL_IN);
438154823   Eric Dumazet   net: sock_def_rea...
400
  	wake_up_interruptible_poll(&tun->wq.wait, POLLIN |
05c2828c7   Michael S. Tsirkin   tun: export under...
401
  				   POLLRDNORM | POLLRDBAND);
6ed106549   Patrick McHardy   net: use NETDEV_T...
402
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
  
  drop:
09f75cd7b   Jeff Garzik   [NET] drivers/net...
405
  	dev->stats.tx_dropped++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
  	kfree_skb(skb);
6ed106549   Patrick McHardy   net: use NETDEV_T...
407
  	return NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
  }
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
409
  static void tun_net_mclist(struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
  {
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
411
412
413
414
415
  	/*
  	 * This callback is supposed to deal with mc filter in
  	 * _rx_ path and has nothing to do with the _tx_ path.
  	 * In rx path we always accept everything userspace gives us.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
  }
4885a5047   Ed Swierk   [TAP]: Configurab...
417
418
419
420
421
422
423
424
425
426
427
  #define MIN_MTU 68
  #define MAX_MTU 65535
  
  static int
  tun_net_change_mtu(struct net_device *dev, int new_mtu)
  {
  	if (new_mtu < MIN_MTU || new_mtu + dev->hard_header_len > MAX_MTU)
  		return -EINVAL;
  	dev->mtu = new_mtu;
  	return 0;
  }
882553752   Michał Mirosław   net: tun: convert...
428
429
430
431
432
433
  static u32 tun_net_fix_features(struct net_device *dev, u32 features)
  {
  	struct tun_struct *tun = netdev_priv(dev);
  
  	return (features & tun->set_features) | (features & ~TUN_USER_FEATURES);
  }
bebd097a0   Neil Horman   tun: teach the tu...
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
  #ifdef CONFIG_NET_POLL_CONTROLLER
  static void tun_poll_controller(struct net_device *dev)
  {
  	/*
  	 * Tun only receives frames when:
  	 * 1) the char device endpoint gets data from user space
  	 * 2) the tun socket gets a sendmsg call from user space
  	 * Since both of those are syncronous operations, we are guaranteed
  	 * never to have pending data when we poll for it
  	 * so theres nothing to do here but return.
  	 * We need this though so netpoll recognizes us as an interface that
  	 * supports polling, which enables bridge devices in virt setups to
  	 * still use netconsole
  	 */
  	return;
  }
  #endif
758e43b74   Stephen Hemminger   tun: convert to n...
451
  static const struct net_device_ops tun_netdev_ops = {
c70f18294   Eric W. Biederman   tun: Fix races be...
452
  	.ndo_uninit		= tun_net_uninit,
758e43b74   Stephen Hemminger   tun: convert to n...
453
454
  	.ndo_open		= tun_net_open,
  	.ndo_stop		= tun_net_close,
008298231   Stephen Hemminger   netdev: add more ...
455
  	.ndo_start_xmit		= tun_net_xmit,
758e43b74   Stephen Hemminger   tun: convert to n...
456
  	.ndo_change_mtu		= tun_net_change_mtu,
882553752   Michał Mirosław   net: tun: convert...
457
  	.ndo_fix_features	= tun_net_fix_features,
bebd097a0   Neil Horman   tun: teach the tu...
458
459
460
  #ifdef CONFIG_NET_POLL_CONTROLLER
  	.ndo_poll_controller	= tun_poll_controller,
  #endif
758e43b74   Stephen Hemminger   tun: convert to n...
461
462
463
  };
  
  static const struct net_device_ops tap_netdev_ops = {
c70f18294   Eric W. Biederman   tun: Fix races be...
464
  	.ndo_uninit		= tun_net_uninit,
758e43b74   Stephen Hemminger   tun: convert to n...
465
466
  	.ndo_open		= tun_net_open,
  	.ndo_stop		= tun_net_close,
008298231   Stephen Hemminger   netdev: add more ...
467
  	.ndo_start_xmit		= tun_net_xmit,
758e43b74   Stephen Hemminger   tun: convert to n...
468
  	.ndo_change_mtu		= tun_net_change_mtu,
882553752   Michał Mirosław   net: tun: convert...
469
  	.ndo_fix_features	= tun_net_fix_features,
758e43b74   Stephen Hemminger   tun: convert to n...
470
471
472
  	.ndo_set_multicast_list	= tun_net_mclist,
  	.ndo_set_mac_address	= eth_mac_addr,
  	.ndo_validate_addr	= eth_validate_addr,
bebd097a0   Neil Horman   tun: teach the tu...
473
474
475
  #ifdef CONFIG_NET_POLL_CONTROLLER
  	.ndo_poll_controller	= tun_poll_controller,
  #endif
758e43b74   Stephen Hemminger   tun: convert to n...
476
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
478
479
480
  /* Initialize net device. */
  static void tun_net_init(struct net_device *dev)
  {
  	struct tun_struct *tun = netdev_priv(dev);
6aa20a223   Jeff Garzik   drivers/net: Trim...
481

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
  	switch (tun->flags & TUN_TYPE_MASK) {
  	case TUN_TUN_DEV:
758e43b74   Stephen Hemminger   tun: convert to n...
484
  		dev->netdev_ops = &tun_netdev_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
486
487
488
489
490
  		/* Point-to-Point TUN Device */
  		dev->hard_header_len = 0;
  		dev->addr_len = 0;
  		dev->mtu = 1500;
  
  		/* Zero header length */
6aa20a223   Jeff Garzik   drivers/net: Trim...
491
  		dev->type = ARPHRD_NONE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
493
494
495
496
  		dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
  		dev->tx_queue_len = TUN_READQ_SIZE;  /* We prefer our own queue length */
  		break;
  
  	case TUN_TAP_DEV:
7a0a9608e   Kusanagi Kouichi   tun: Fix SIOCSIFH...
497
  		dev->netdev_ops = &tap_netdev_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
  		/* Ethernet TAP Device */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
  		ether_setup(dev);
550fd08c2   Neil Horman   net: Audit driver...
500
  		dev->priv_flags &= ~IFF_TX_SKB_SHARING;
36226a8de   Brian Braunstein   [NET] tun/tap: fi...
501

f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
502
  		random_ether_addr(dev->dev_addr);
36226a8de   Brian Braunstein   [NET] tun/tap: fi...
503

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
505
506
507
508
509
510
511
512
  		dev->tx_queue_len = TUN_READQ_SIZE;  /* We prefer our own queue length */
  		break;
  	}
  }
  
  /* Character device part */
  
  /* Poll */
  static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
6aa20a223   Jeff Garzik   drivers/net: Trim...
513
  {
b2430de37   Eric W. Biederman   tun: Move read_wa...
514
515
  	struct tun_file *tfile = file->private_data;
  	struct tun_struct *tun = __tun_get(tfile);
3c8a9c63d   Mariusz Kozlowski   tun/tap: Fix cras...
516
  	struct sock *sk;
33dccbb05   Herbert Xu   tun: Limit amount...
517
  	unsigned int mask = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
519
  
  	if (!tun)
eac9e9026   Eric W. Biederman   tun: Use POLLERR ...
520
  		return POLLERR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521

89f56d1e9   Michael S. Tsirkin   tun: reuse struct...
522
  	sk = tun->socket.sk;
3c8a9c63d   Mariusz Kozlowski   tun/tap: Fix cras...
523

6b8a66ee9   Joe Perches   tun: Convert logg...
524
525
  	tun_debug(KERN_INFO, tun, "tun_chr_poll
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526

438154823   Eric Dumazet   net: sock_def_rea...
527
  	poll_wait(file, &tun->wq.wait, wait);
6aa20a223   Jeff Garzik   drivers/net: Trim...
528

89f56d1e9   Michael S. Tsirkin   tun: reuse struct...
529
  	if (!skb_queue_empty(&sk->sk_receive_queue))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
  		mask |= POLLIN | POLLRDNORM;
33dccbb05   Herbert Xu   tun: Limit amount...
531
532
533
534
  	if (sock_writeable(sk) ||
  	    (!test_and_set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags) &&
  	     sock_writeable(sk)))
  		mask |= POLLOUT | POLLWRNORM;
c70f18294   Eric W. Biederman   tun: Fix races be...
535
536
  	if (tun->dev->reg_state != NETREG_REGISTERED)
  		mask = POLLERR;
631ab46b7   Eric W. Biederman   tun: Introduce tu...
537
  	tun_put(tun);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
539
  	return mask;
  }
f42157cb5   Rusty Russell   tun: fallback if ...
540
541
  /* prepad is the amount to reserve at front.  len is length after that.
   * linear is a hint as to how much to copy (usually headers). */
6f7c156c0   stephen hemminger   tun: dont force i...
542
543
544
  static struct sk_buff *tun_alloc_skb(struct tun_struct *tun,
  				     size_t prepad, size_t len,
  				     size_t linear, int noblock)
f42157cb5   Rusty Russell   tun: fallback if ...
545
  {
89f56d1e9   Michael S. Tsirkin   tun: reuse struct...
546
  	struct sock *sk = tun->socket.sk;
f42157cb5   Rusty Russell   tun: fallback if ...
547
  	struct sk_buff *skb;
33dccbb05   Herbert Xu   tun: Limit amount...
548
  	int err;
f42157cb5   Rusty Russell   tun: fallback if ...
549

828627428   Herbert Xu   tun: Update class...
550
  	sock_update_classid(sk);
f42157cb5   Rusty Russell   tun: fallback if ...
551
  	/* Under a page?  Don't bother with paged skb. */
0eca93bcf   Herbert Xu   tun: Fix crash wi...
552
  	if (prepad + len < PAGE_SIZE || !linear)
33dccbb05   Herbert Xu   tun: Limit amount...
553
  		linear = len;
f42157cb5   Rusty Russell   tun: fallback if ...
554

33dccbb05   Herbert Xu   tun: Limit amount...
555
556
  	skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock,
  				   &err);
f42157cb5   Rusty Russell   tun: fallback if ...
557
  	if (!skb)
33dccbb05   Herbert Xu   tun: Limit amount...
558
  		return ERR_PTR(err);
f42157cb5   Rusty Russell   tun: fallback if ...
559
560
561
  
  	skb_reserve(skb, prepad);
  	skb_put(skb, linear);
33dccbb05   Herbert Xu   tun: Limit amount...
562
563
  	skb->data_len = len - linear;
  	skb->len += len - linear;
f42157cb5   Rusty Russell   tun: fallback if ...
564
565
566
  
  	return skb;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
  /* Get packet from user space buffer */
6f7c156c0   stephen hemminger   tun: dont force i...
568
569
570
  static ssize_t tun_get_user(struct tun_struct *tun,
  			    const struct iovec *iv, size_t count,
  			    int noblock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
  {
09640e636   Harvey Harrison   net: replace uses...
572
  	struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
  	struct sk_buff *skb;
a504b86e7   stephen hemminger   tun: reserves spa...
574
  	size_t len = count, align = NET_SKB_PAD;
f43798c27   Rusty Russell   tun: Allow GSO us...
575
  	struct virtio_net_hdr gso = { 0 };
6f26c9a75   Michael S. Tsirkin   tun: fix tun_chr_...
576
  	int offset = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
578
579
580
  
  	if (!(tun->flags & TUN_NO_PI)) {
  		if ((len -= sizeof(pi)) > count)
  			return -EINVAL;
6f26c9a75   Michael S. Tsirkin   tun: fix tun_chr_...
581
  		if (memcpy_fromiovecend((void *)&pi, iv, 0, sizeof(pi)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
  			return -EFAULT;
6f26c9a75   Michael S. Tsirkin   tun: fix tun_chr_...
583
  		offset += sizeof(pi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
  	}
f43798c27   Rusty Russell   tun: Allow GSO us...
585
  	if (tun->flags & TUN_VNET_HDR) {
d9d52b517   Michael S. Tsirkin   tun: add ioctl to...
586
  		if ((len -= tun->vnet_hdr_sz) > count)
f43798c27   Rusty Russell   tun: Allow GSO us...
587
  			return -EINVAL;
6f26c9a75   Michael S. Tsirkin   tun: fix tun_chr_...
588
  		if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso)))
f43798c27   Rusty Russell   tun: Allow GSO us...
589
  			return -EFAULT;
4909122fb   Herbert Xu   tun: Optimise han...
590
591
592
  		if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
  		    gso.csum_start + gso.csum_offset + 2 > gso.hdr_len)
  			gso.hdr_len = gso.csum_start + gso.csum_offset + 2;
f43798c27   Rusty Russell   tun: Allow GSO us...
593
594
  		if (gso.hdr_len > len)
  			return -EINVAL;
d9d52b517   Michael S. Tsirkin   tun: add ioctl to...
595
  		offset += tun->vnet_hdr_sz;
f43798c27   Rusty Russell   tun: Allow GSO us...
596
  	}
e01bf1c83   Rusty Russell   net: check for un...
597
  	if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) {
a504b86e7   stephen hemminger   tun: reserves spa...
598
  		align += NET_IP_ALIGN;
0eca93bcf   Herbert Xu   tun: Fix crash wi...
599
600
  		if (unlikely(len < ETH_HLEN ||
  			     (gso.hdr_len && gso.hdr_len < ETH_HLEN)))
e01bf1c83   Rusty Russell   net: check for un...
601
602
  			return -EINVAL;
  	}
6aa20a223   Jeff Garzik   drivers/net: Trim...
603

33dccbb05   Herbert Xu   tun: Limit amount...
604
605
606
607
608
  	skb = tun_alloc_skb(tun, align, len, gso.hdr_len, noblock);
  	if (IS_ERR(skb)) {
  		if (PTR_ERR(skb) != -EAGAIN)
  			tun->dev->stats.rx_dropped++;
  		return PTR_ERR(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
  	}
6f26c9a75   Michael S. Tsirkin   tun: fix tun_chr_...
610
  	if (skb_copy_datagram_from_iovec(skb, 0, iv, offset, len)) {
09f75cd7b   Jeff Garzik   [NET] drivers/net...
611
  		tun->dev->stats.rx_dropped++;
8f22757ee   Dave Jones   [TUN]: Fix leak i...
612
  		kfree_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
  		return -EFAULT;
8f22757ee   Dave Jones   [TUN]: Fix leak i...
614
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615

f43798c27   Rusty Russell   tun: Allow GSO us...
616
617
618
619
620
621
622
  	if (gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
  		if (!skb_partial_csum_set(skb, gso.csum_start,
  					  gso.csum_offset)) {
  			tun->dev->stats.rx_frame_errors++;
  			kfree_skb(skb);
  			return -EINVAL;
  		}
882553752   Michał Mirosław   net: tun: convert...
623
  	}
f43798c27   Rusty Russell   tun: Allow GSO us...
624

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
626
  	switch (tun->flags & TUN_TYPE_MASK) {
  	case TUN_TUN_DEV:
f09f7ee20   Ang Way Chuang   tun: Proper handl...
627
628
629
630
631
632
633
634
635
636
637
638
639
640
  		if (tun->flags & TUN_NO_PI) {
  			switch (skb->data[0] & 0xf0) {
  			case 0x40:
  				pi.proto = htons(ETH_P_IP);
  				break;
  			case 0x60:
  				pi.proto = htons(ETH_P_IPV6);
  				break;
  			default:
  				tun->dev->stats.rx_dropped++;
  				kfree_skb(skb);
  				return -EINVAL;
  			}
  		}
459a98ed8   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
641
  		skb_reset_mac_header(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
  		skb->protocol = pi.proto;
4c13eb665   Arnaldo Carvalho de Melo   [ETH]: Make eth_t...
643
  		skb->dev = tun->dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
645
646
647
  		break;
  	case TUN_TAP_DEV:
  		skb->protocol = eth_type_trans(skb, tun->dev);
  		break;
6403eab14   Joe Perches   drivers/net: Remo...
648
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649

f43798c27   Rusty Russell   tun: Allow GSO us...
650
651
652
653
654
655
656
657
658
659
  	if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
  		pr_debug("GSO!
  ");
  		switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
  		case VIRTIO_NET_HDR_GSO_TCPV4:
  			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
  			break;
  		case VIRTIO_NET_HDR_GSO_TCPV6:
  			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
  			break;
e36aa25a5   Sridhar Samudrala   tun: Allow tap de...
660
661
662
  		case VIRTIO_NET_HDR_GSO_UDP:
  			skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
  			break;
f43798c27   Rusty Russell   tun: Allow GSO us...
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
  		default:
  			tun->dev->stats.rx_frame_errors++;
  			kfree_skb(skb);
  			return -EINVAL;
  		}
  
  		if (gso.gso_type & VIRTIO_NET_HDR_GSO_ECN)
  			skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
  
  		skb_shinfo(skb)->gso_size = gso.gso_size;
  		if (skb_shinfo(skb)->gso_size == 0) {
  			tun->dev->stats.rx_frame_errors++;
  			kfree_skb(skb);
  			return -EINVAL;
  		}
  
  		/* Header must be checked, and gso_segs computed. */
  		skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
  		skb_shinfo(skb)->gso_segs = 0;
  	}
6aa20a223   Jeff Garzik   drivers/net: Trim...
683

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
684
  	netif_rx_ni(skb);
6aa20a223   Jeff Garzik   drivers/net: Trim...
685

09f75cd7b   Jeff Garzik   [NET] drivers/net...
686
687
  	tun->dev->stats.rx_packets++;
  	tun->dev->stats.rx_bytes += len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688
689
  
  	return count;
6aa20a223   Jeff Garzik   drivers/net: Trim...
690
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691

ee0b3e671   Badari Pulavarty   [PATCH] Remove re...
692
693
  static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
  			      unsigned long count, loff_t pos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
  {
33dccbb05   Herbert Xu   tun: Limit amount...
695
  	struct file *file = iocb->ki_filp;
ab46d7796   Herbert Xu   tun: Fix merge error
696
  	struct tun_struct *tun = tun_get(file);
631ab46b7   Eric W. Biederman   tun: Introduce tu...
697
  	ssize_t result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
698
699
700
  
  	if (!tun)
  		return -EBADFD;
6b8a66ee9   Joe Perches   tun: Convert logg...
701
702
  	tun_debug(KERN_INFO, tun, "tun_chr_write %ld
  ", count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703

6f26c9a75   Michael S. Tsirkin   tun: fix tun_chr_...
704
  	result = tun_get_user(tun, iv, iov_length(iv, count),
33dccbb05   Herbert Xu   tun: Limit amount...
705
  			      file->f_flags & O_NONBLOCK);
631ab46b7   Eric W. Biederman   tun: Introduce tu...
706
707
708
  
  	tun_put(tun);
  	return result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
709
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
  /* Put packet to the user space buffer */
6f7c156c0   stephen hemminger   tun: dont force i...
711
712
713
  static ssize_t tun_put_user(struct tun_struct *tun,
  			    struct sk_buff *skb,
  			    const struct iovec *iv, int len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
715
716
717
718
719
720
721
722
723
724
725
  {
  	struct tun_pi pi = { 0, skb->protocol };
  	ssize_t total = 0;
  
  	if (!(tun->flags & TUN_NO_PI)) {
  		if ((len -= sizeof(pi)) < 0)
  			return -EINVAL;
  
  		if (len < skb->len) {
  			/* Packet will be striped */
  			pi.flags |= TUN_PKT_STRIP;
  		}
6aa20a223   Jeff Garzik   drivers/net: Trim...
726

43b39dcdb   Michael S. Tsirkin   tun: fix tun_chr_...
727
  		if (memcpy_toiovecend(iv, (void *) &pi, 0, sizeof(pi)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
729
  			return -EFAULT;
  		total += sizeof(pi);
6aa20a223   Jeff Garzik   drivers/net: Trim...
730
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731

f43798c27   Rusty Russell   tun: Allow GSO us...
732
733
  	if (tun->flags & TUN_VNET_HDR) {
  		struct virtio_net_hdr gso = { 0 }; /* no info leak */
d9d52b517   Michael S. Tsirkin   tun: add ioctl to...
734
  		if ((len -= tun->vnet_hdr_sz) < 0)
f43798c27   Rusty Russell   tun: Allow GSO us...
735
736
737
738
739
740
741
742
743
744
745
746
  			return -EINVAL;
  
  		if (skb_is_gso(skb)) {
  			struct skb_shared_info *sinfo = skb_shinfo(skb);
  
  			/* This is a hint as to how much should be linear. */
  			gso.hdr_len = skb_headlen(skb);
  			gso.gso_size = sinfo->gso_size;
  			if (sinfo->gso_type & SKB_GSO_TCPV4)
  				gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
  			else if (sinfo->gso_type & SKB_GSO_TCPV6)
  				gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
e36aa25a5   Sridhar Samudrala   tun: Allow tap de...
747
748
  			else if (sinfo->gso_type & SKB_GSO_UDP)
  				gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
ef3db4a59   Michael S. Tsirkin   tun: avoid BUG, d...
749
  			else {
6b8a66ee9   Joe Perches   tun: Convert logg...
750
  				pr_err("unexpected GSO type: "
ef3db4a59   Michael S. Tsirkin   tun: avoid BUG, d...
751
752
753
754
755
756
757
758
759
760
761
  				       "0x%x, gso_size %d, hdr_len %d
  ",
  				       sinfo->gso_type, gso.gso_size,
  				       gso.hdr_len);
  				print_hex_dump(KERN_ERR, "tun: ",
  					       DUMP_PREFIX_NONE,
  					       16, 1, skb->head,
  					       min((int)gso.hdr_len, 64), true);
  				WARN_ON_ONCE(1);
  				return -EINVAL;
  			}
f43798c27   Rusty Russell   tun: Allow GSO us...
762
763
764
765
766
767
768
  			if (sinfo->gso_type & SKB_GSO_TCP_ECN)
  				gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN;
  		} else
  			gso.gso_type = VIRTIO_NET_HDR_GSO_NONE;
  
  		if (skb->ip_summed == CHECKSUM_PARTIAL) {
  			gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
55508d601   Michał Mirosław   net: Use skb_chec...
769
  			gso.csum_start = skb_checksum_start_offset(skb);
f43798c27   Rusty Russell   tun: Allow GSO us...
770
  			gso.csum_offset = skb->csum_offset;
10a8d94a9   Jason Wang   virtio_net: intro...
771
772
  		} else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
  			gso.flags = VIRTIO_NET_HDR_F_DATA_VALID;
f43798c27   Rusty Russell   tun: Allow GSO us...
773
  		} /* else everything is zero */
43b39dcdb   Michael S. Tsirkin   tun: fix tun_chr_...
774
775
  		if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total,
  					       sizeof(gso))))
f43798c27   Rusty Russell   tun: Allow GSO us...
776
  			return -EFAULT;
d9d52b517   Michael S. Tsirkin   tun: add ioctl to...
777
  		total += tun->vnet_hdr_sz;
f43798c27   Rusty Russell   tun: Allow GSO us...
778
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
  	len = min_t(int, skb->len, len);
43b39dcdb   Michael S. Tsirkin   tun: fix tun_chr_...
780
  	skb_copy_datagram_const_iovec(skb, 0, iv, total, len);
05c2828c7   Michael S. Tsirkin   tun: export under...
781
  	total += skb->len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
782

09f75cd7b   Jeff Garzik   [NET] drivers/net...
783
784
  	tun->dev->stats.tx_packets++;
  	tun->dev->stats.tx_bytes += len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
786
787
  
  	return total;
  }
05c2828c7   Michael S. Tsirkin   tun: export under...
788
789
790
  static ssize_t tun_do_read(struct tun_struct *tun,
  			   struct kiocb *iocb, const struct iovec *iv,
  			   ssize_t len, int noblock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
793
  	DECLARE_WAITQUEUE(wait, current);
  	struct sk_buff *skb;
05c2828c7   Michael S. Tsirkin   tun: export under...
794
  	ssize_t ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795

6b8a66ee9   Joe Perches   tun: Convert logg...
796
797
  	tun_debug(KERN_INFO, tun, "tun_chr_read
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798

61a5ff15e   Amos Kong   tun: do not put s...
799
800
  	if (unlikely(!noblock))
  		add_wait_queue(&tun->wq.wait, &wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
801
  	while (len) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
803
804
  		current->state = TASK_INTERRUPTIBLE;
  
  		/* Read frames from the queue */
89f56d1e9   Michael S. Tsirkin   tun: reuse struct...
805
  		if (!(skb=skb_dequeue(&tun->socket.sk->sk_receive_queue))) {
05c2828c7   Michael S. Tsirkin   tun: export under...
806
  			if (noblock) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
808
809
810
811
812
813
  				ret = -EAGAIN;
  				break;
  			}
  			if (signal_pending(current)) {
  				ret = -ERESTARTSYS;
  				break;
  			}
c70f18294   Eric W. Biederman   tun: Fix races be...
814
815
816
817
  			if (tun->dev->reg_state != NETREG_REGISTERED) {
  				ret = -EIO;
  				break;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
818
819
820
821
822
823
  
  			/* Nothing to read, let's sleep */
  			schedule();
  			continue;
  		}
  		netif_wake_queue(tun->dev);
43b39dcdb   Michael S. Tsirkin   tun: fix tun_chr_...
824
  		ret = tun_put_user(tun, skb, iv, len);
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
825
826
  		kfree_skb(skb);
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827
828
829
  	}
  
  	current->state = TASK_RUNNING;
61a5ff15e   Amos Kong   tun: do not put s...
830
831
  	if (unlikely(!noblock))
  		remove_wait_queue(&tun->wq.wait, &wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
832

05c2828c7   Michael S. Tsirkin   tun: export under...
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
  	return ret;
  }
  
  static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
  			    unsigned long count, loff_t pos)
  {
  	struct file *file = iocb->ki_filp;
  	struct tun_file *tfile = file->private_data;
  	struct tun_struct *tun = __tun_get(tfile);
  	ssize_t len, ret;
  
  	if (!tun)
  		return -EBADFD;
  	len = iov_length(iv, count);
  	if (len < 0) {
  		ret = -EINVAL;
  		goto out;
  	}
  
  	ret = tun_do_read(tun, iocb, iv, len, file->f_flags & O_NONBLOCK);
  	ret = min_t(ssize_t, ret, len);
631ab46b7   Eric W. Biederman   tun: Introduce tu...
854
855
  out:
  	tun_put(tun);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
857
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858
859
860
  static void tun_setup(struct net_device *dev)
  {
  	struct tun_struct *tun = netdev_priv(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861
  	tun->owner = -1;
8c644623f   Guido Guenther   [NET]: Allow grou...
862
  	tun->group = -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
864
  	dev->ethtool_ops = &tun_ethtool_ops;
9c3fea6ab   Herbert Xu   tun: Only free a ...
865
  	dev->destructor = tun_free_netdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
866
  }
f019a7a59   Eric W. Biederman   tun: Implement ip...
867
868
869
870
871
872
873
874
875
876
877
878
879
880
  /* Trivial set of netlink ops to allow deleting tun or tap
   * device with netlink.
   */
  static int tun_validate(struct nlattr *tb[], struct nlattr *data[])
  {
  	return -EINVAL;
  }
  
  static struct rtnl_link_ops tun_link_ops __read_mostly = {
  	.kind		= DRV_NAME,
  	.priv_size	= sizeof(struct tun_struct),
  	.setup		= tun_setup,
  	.validate	= tun_validate,
  };
33dccbb05   Herbert Xu   tun: Limit amount...
881
882
883
  static void tun_sock_write_space(struct sock *sk)
  {
  	struct tun_struct *tun;
438154823   Eric Dumazet   net: sock_def_rea...
884
  	wait_queue_head_t *wqueue;
33dccbb05   Herbert Xu   tun: Limit amount...
885
886
887
  
  	if (!sock_writeable(sk))
  		return;
33dccbb05   Herbert Xu   tun: Limit amount...
888
889
  	if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags))
  		return;
438154823   Eric Dumazet   net: sock_def_rea...
890
891
892
  	wqueue = sk_sleep(sk);
  	if (wqueue && waitqueue_active(wqueue))
  		wake_up_interruptible_sync_poll(wqueue, POLLOUT |
05c2828c7   Michael S. Tsirkin   tun: export under...
893
  						POLLWRNORM | POLLWRBAND);
c722c625d   Herbert Xu   tun: Only wake up...
894

80924e5f7   Vitaliy Gusev   tun: use tun_sk i...
895
  	tun = tun_sk(sk)->tun;
33dccbb05   Herbert Xu   tun: Limit amount...
896
897
898
899
900
  	kill_fasync(&tun->fasync, SIGIO, POLL_OUT);
  }
  
  static void tun_sock_destruct(struct sock *sk)
  {
80924e5f7   Vitaliy Gusev   tun: use tun_sk i...
901
  	free_netdev(tun_sk(sk)->tun->dev);
33dccbb05   Herbert Xu   tun: Limit amount...
902
  }
05c2828c7   Michael S. Tsirkin   tun: export under...
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
  static int tun_sendmsg(struct kiocb *iocb, struct socket *sock,
  		       struct msghdr *m, size_t total_len)
  {
  	struct tun_struct *tun = container_of(sock, struct tun_struct, socket);
  	return tun_get_user(tun, m->msg_iov, total_len,
  			    m->msg_flags & MSG_DONTWAIT);
  }
  
  static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
  		       struct msghdr *m, size_t total_len,
  		       int flags)
  {
  	struct tun_struct *tun = container_of(sock, struct tun_struct, socket);
  	int ret;
  	if (flags & ~(MSG_DONTWAIT|MSG_TRUNC))
  		return -EINVAL;
  	ret = tun_do_read(tun, iocb, m->msg_iov, total_len,
  			  flags & MSG_DONTWAIT);
  	if (ret > total_len) {
  		m->msg_flags |= MSG_TRUNC;
  		ret = flags & MSG_TRUNC ? ret : total_len;
  	}
  	return ret;
  }
  
  /* Ops structure to mimic raw sockets with tun */
  static const struct proto_ops tun_socket_ops = {
  	.sendmsg = tun_sendmsg,
  	.recvmsg = tun_recvmsg,
  };
33dccbb05   Herbert Xu   tun: Limit amount...
933
934
935
936
937
  static struct proto tun_proto = {
  	.name		= "tun",
  	.owner		= THIS_MODULE,
  	.obj_size	= sizeof(struct tun_sock),
  };
f019a7a59   Eric W. Biederman   tun: Implement ip...
938

980c9e8ce   David Woodhouse   tun: add tun_flag...
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
  static int tun_flags(struct tun_struct *tun)
  {
  	int flags = 0;
  
  	if (tun->flags & TUN_TUN_DEV)
  		flags |= IFF_TUN;
  	else
  		flags |= IFF_TAP;
  
  	if (tun->flags & TUN_NO_PI)
  		flags |= IFF_NO_PI;
  
  	if (tun->flags & TUN_ONE_QUEUE)
  		flags |= IFF_ONE_QUEUE;
  
  	if (tun->flags & TUN_VNET_HDR)
  		flags |= IFF_VNET_HDR;
  
  	return flags;
  }
  
  static ssize_t tun_show_flags(struct device *dev, struct device_attribute *attr,
  			      char *buf)
  {
  	struct tun_struct *tun = netdev_priv(to_net_dev(dev));
  	return sprintf(buf, "0x%x
  ", tun_flags(tun));
  }
  
  static ssize_t tun_show_owner(struct device *dev, struct device_attribute *attr,
  			      char *buf)
  {
  	struct tun_struct *tun = netdev_priv(to_net_dev(dev));
  	return sprintf(buf, "%d
  ", tun->owner);
  }
  
  static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr,
  			      char *buf)
  {
  	struct tun_struct *tun = netdev_priv(to_net_dev(dev));
  	return sprintf(buf, "%d
  ", tun->group);
  }
  
  static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL);
  static DEVICE_ATTR(owner, 0444, tun_show_owner, NULL);
  static DEVICE_ATTR(group, 0444, tun_show_group, NULL);
d647a591d   Pavel Emelyanov   [TUN]: Make the t...
987
  static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
988
  {
33dccbb05   Herbert Xu   tun: Limit amount...
989
  	struct sock *sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
991
992
  	struct tun_struct *tun;
  	struct net_device *dev;
  	int err;
74a3e5a71   Eric W. Biederman   tun: Remove unnec...
993
994
  	dev = __dev_get_by_name(net, ifr->ifr_name);
  	if (dev) {
2b980dbd7   Paul Moore   lsm: Add hooks to...
995
  		const struct cred *cred = current_cred();
f85ba7806   David Woodhouse   tun: add IFF_TUN_...
996
997
  		if (ifr->ifr_flags & IFF_TUN_EXCL)
  			return -EBUSY;
74a3e5a71   Eric W. Biederman   tun: Remove unnec...
998
999
1000
1001
1002
1003
  		if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops)
  			tun = netdev_priv(dev);
  		else if ((ifr->ifr_flags & IFF_TAP) && dev->netdev_ops == &tap_netdev_ops)
  			tun = netdev_priv(dev);
  		else
  			return -EINVAL;
2b980dbd7   Paul Moore   lsm: Add hooks to...
1004
1005
1006
1007
  		if (((tun->owner != -1 && cred->euid != tun->owner) ||
  		     (tun->group != -1 && !in_egroup_p(tun->group))) &&
  		    !capable(CAP_NET_ADMIN))
  			return -EPERM;
d7e9660ad   Linus Torvalds   Merge git://git.k...
1008
  		err = security_tun_dev_attach(tun->socket.sk);
2b980dbd7   Paul Moore   lsm: Add hooks to...
1009
1010
  		if (err < 0)
  			return err;
a7385ba21   Eric W. Biederman   tun: Fix races in...
1011
1012
1013
  		err = tun_attach(tun, file);
  		if (err < 0)
  			return err;
6aa20a223   Jeff Garzik   drivers/net: Trim...
1014
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
1016
1017
  	else {
  		char *name;
  		unsigned long flags = 0;
ca6bb5d7a   David Woodhouse   [NET]: Require CA...
1018
1019
  		if (!capable(CAP_NET_ADMIN))
  			return -EPERM;
2b980dbd7   Paul Moore   lsm: Add hooks to...
1020
1021
1022
  		err = security_tun_dev_create();
  		if (err < 0)
  			return err;
ca6bb5d7a   David Woodhouse   [NET]: Require CA...
1023

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1024
1025
1026
1027
1028
1029
1030
1031
1032
  		/* Set dev type */
  		if (ifr->ifr_flags & IFF_TUN) {
  			/* TUN device */
  			flags |= TUN_TUN_DEV;
  			name = "tun%d";
  		} else if (ifr->ifr_flags & IFF_TAP) {
  			/* TAP device */
  			flags |= TUN_TAP_DEV;
  			name = "tap%d";
6aa20a223   Jeff Garzik   drivers/net: Trim...
1033
  		} else
36989b908   Kusanagi Kouichi   tun: Return -EINV...
1034
  			return -EINVAL;
6aa20a223   Jeff Garzik   drivers/net: Trim...
1035

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1036
1037
1038
1039
1040
1041
1042
  		if (*ifr->ifr_name)
  			name = ifr->ifr_name;
  
  		dev = alloc_netdev(sizeof(struct tun_struct), name,
  				   tun_setup);
  		if (!dev)
  			return -ENOMEM;
fc54c6585   Pavel Emelyanov   [TUN]: Allow to r...
1043
  		dev_net_set(dev, net);
f019a7a59   Eric W. Biederman   tun: Implement ip...
1044
  		dev->rtnl_link_ops = &tun_link_ops;
758e43b74   Stephen Hemminger   tun: convert to n...
1045

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1046
1047
1048
  		tun = netdev_priv(dev);
  		tun->dev = dev;
  		tun->flags = flags;
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
1049
  		tun->txflt.count = 0;
d9d52b517   Michael S. Tsirkin   tun: add ioctl to...
1050
  		tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1051

33dccbb05   Herbert Xu   tun: Limit amount...
1052
1053
1054
1055
  		err = -ENOMEM;
  		sk = sk_alloc(net, AF_UNSPEC, GFP_KERNEL, &tun_proto);
  		if (!sk)
  			goto err_free_dev;
438154823   Eric Dumazet   net: sock_def_rea...
1056
1057
  		tun->socket.wq = &tun->wq;
  		init_waitqueue_head(&tun->wq.wait);
05c2828c7   Michael S. Tsirkin   tun: export under...
1058
  		tun->socket.ops = &tun_socket_ops;
33dccbb05   Herbert Xu   tun: Limit amount...
1059
1060
  		sock_init_data(&tun->socket, sk);
  		sk->sk_write_space = tun_sock_write_space;
33dccbb05   Herbert Xu   tun: Limit amount...
1061
  		sk->sk_sndbuf = INT_MAX;
33dccbb05   Herbert Xu   tun: Limit amount...
1062

80924e5f7   Vitaliy Gusev   tun: use tun_sk i...
1063
  		tun_sk(sk)->tun = tun;
33dccbb05   Herbert Xu   tun: Limit amount...
1064

2b980dbd7   Paul Moore   lsm: Add hooks to...
1065
  		security_tun_dev_post_create(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1066
  		tun_net_init(dev);
882553752   Michał Mirosław   net: tun: convert...
1067
1068
1069
  		dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST |
  			TUN_USER_FEATURES;
  		dev->features = dev->hw_features;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1070
1071
  		err = register_netdevice(tun->dev);
  		if (err < 0)
9c3fea6ab   Herbert Xu   tun: Only free a ...
1072
  			goto err_free_sk;
980c9e8ce   David Woodhouse   tun: add tun_flag...
1073
1074
1075
  		if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) ||
  		    device_create_file(&tun->dev->dev, &dev_attr_owner) ||
  		    device_create_file(&tun->dev->dev, &dev_attr_group))
6b8a66ee9   Joe Perches   tun: Convert logg...
1076
1077
  			pr_err("Failed to create tun sysfs files
  ");
980c9e8ce   David Woodhouse   tun: add tun_flag...
1078

9c3fea6ab   Herbert Xu   tun: Only free a ...
1079
  		sk->sk_destruct = tun_sock_destruct;
a7385ba21   Eric W. Biederman   tun: Fix races in...
1080
1081
1082
  
  		err = tun_attach(tun, file);
  		if (err < 0)
9c3fea6ab   Herbert Xu   tun: Only free a ...
1083
  			goto failed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1084
  	}
6b8a66ee9   Joe Perches   tun: Convert logg...
1085
1086
  	tun_debug(KERN_INFO, tun, "tun_set_iff
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1087
1088
1089
  
  	if (ifr->ifr_flags & IFF_NO_PI)
  		tun->flags |= TUN_NO_PI;
a26af1e08   Nathaniel Filardo   tun: impossible t...
1090
1091
  	else
  		tun->flags &= ~TUN_NO_PI;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1092
1093
1094
  
  	if (ifr->ifr_flags & IFF_ONE_QUEUE)
  		tun->flags |= TUN_ONE_QUEUE;
a26af1e08   Nathaniel Filardo   tun: impossible t...
1095
1096
  	else
  		tun->flags &= ~TUN_ONE_QUEUE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1097

f43798c27   Rusty Russell   tun: Allow GSO us...
1098
1099
1100
1101
  	if (ifr->ifr_flags & IFF_VNET_HDR)
  		tun->flags |= TUN_VNET_HDR;
  	else
  		tun->flags &= ~TUN_VNET_HDR;
e35259a95   Max Krasnyansky   tun: Persistent d...
1102
1103
1104
1105
1106
  	/* Make sure persistent devices do not get stuck in
  	 * xoff state.
  	 */
  	if (netif_running(tun->dev))
  		netif_wake_queue(tun->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1107
1108
  	strcpy(ifr->ifr_name, tun->dev->name);
  	return 0;
33dccbb05   Herbert Xu   tun: Limit amount...
1109
1110
   err_free_sk:
  	sock_put(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1111
1112
1113
1114
1115
   err_free_dev:
  	free_netdev(dev);
   failed:
  	return err;
  }
876bfd4d0   Herbert Xu   tun: Extend RTNL ...
1116
1117
  static int tun_get_iff(struct net *net, struct tun_struct *tun,
  		       struct ifreq *ifr)
e3b995569   Mark McLoughlin   tun: TUNGETIFF in...
1118
  {
6b8a66ee9   Joe Perches   tun: Convert logg...
1119
1120
  	tun_debug(KERN_INFO, tun, "tun_get_iff
  ");
e3b995569   Mark McLoughlin   tun: TUNGETIFF in...
1121
1122
  
  	strcpy(ifr->ifr_name, tun->dev->name);
980c9e8ce   David Woodhouse   tun: add tun_flag...
1123
  	ifr->ifr_flags = tun_flags(tun);
e3b995569   Mark McLoughlin   tun: TUNGETIFF in...
1124
1125
1126
  
  	return 0;
  }
5228ddc98   Rusty Russell   tun: TUNSETFEATUR...
1127
1128
  /* This is like a cut-down ethtool ops, except done via tun fd so no
   * privs required. */
882553752   Michał Mirosław   net: tun: convert...
1129
  static int set_offload(struct tun_struct *tun, unsigned long arg)
5228ddc98   Rusty Russell   tun: TUNSETFEATUR...
1130
  {
882553752   Michał Mirosław   net: tun: convert...
1131
  	u32 features = 0;
5228ddc98   Rusty Russell   tun: TUNSETFEATUR...
1132
1133
  
  	if (arg & TUN_F_CSUM) {
882553752   Michał Mirosław   net: tun: convert...
1134
  		features |= NETIF_F_HW_CSUM;
5228ddc98   Rusty Russell   tun: TUNSETFEATUR...
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
  		arg &= ~TUN_F_CSUM;
  
  		if (arg & (TUN_F_TSO4|TUN_F_TSO6)) {
  			if (arg & TUN_F_TSO_ECN) {
  				features |= NETIF_F_TSO_ECN;
  				arg &= ~TUN_F_TSO_ECN;
  			}
  			if (arg & TUN_F_TSO4)
  				features |= NETIF_F_TSO;
  			if (arg & TUN_F_TSO6)
  				features |= NETIF_F_TSO6;
  			arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
  		}
e36aa25a5   Sridhar Samudrala   tun: Allow tap de...
1148
1149
1150
1151
1152
  
  		if (arg & TUN_F_UFO) {
  			features |= NETIF_F_UFO;
  			arg &= ~TUN_F_UFO;
  		}
5228ddc98   Rusty Russell   tun: TUNSETFEATUR...
1153
1154
1155
1156
1157
1158
  	}
  
  	/* This gives the user a way to test for new features in future by
  	 * trying to set them. */
  	if (arg)
  		return -EINVAL;
882553752   Michał Mirosław   net: tun: convert...
1159
1160
  	tun->set_features = features;
  	netdev_update_features(tun->dev);
5228ddc98   Rusty Russell   tun: TUNSETFEATUR...
1161
1162
1163
  
  	return 0;
  }
50857e2a5   Arnd Bergmann   net/tun: handle c...
1164
1165
  static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
  			    unsigned long arg, int ifreq_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1166
  {
36b50bab5   Eric W. Biederman   tun: Grab the net...
1167
  	struct tun_file *tfile = file->private_data;
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1168
  	struct tun_struct *tun;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1169
  	void __user* argp = (void __user*)arg;
994051625   Michael S. Tsirkin   tun: socket filte...
1170
  	struct sock_fprog fprog;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171
  	struct ifreq ifr;
33dccbb05   Herbert Xu   tun: Limit amount...
1172
  	int sndbuf;
d9d52b517   Michael S. Tsirkin   tun: add ioctl to...
1173
  	int vnet_hdr_sz;
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
1174
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1175
1176
  
  	if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89)
50857e2a5   Arnd Bergmann   net/tun: handle c...
1177
  		if (copy_from_user(&ifr, argp, ifreq_len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1178
  			return -EFAULT;
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1179
1180
1181
1182
1183
1184
1185
1186
  	if (cmd == TUNGETFEATURES) {
  		/* Currently this just means: "what IFF flags are valid?".
  		 * This is needed because we never checked for invalid flags on
  		 * TUNSETIFF. */
  		return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE |
  				IFF_VNET_HDR,
  				(unsigned int __user*)argp);
  	}
876bfd4d0   Herbert Xu   tun: Extend RTNL ...
1187
  	rtnl_lock();
36b50bab5   Eric W. Biederman   tun: Grab the net...
1188
  	tun = __tun_get(tfile);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1189
  	if (cmd == TUNSETIFF && !tun) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1190
  		ifr.ifr_name[IFNAMSIZ-1] = '\0';
876bfd4d0   Herbert Xu   tun: Extend RTNL ...
1191
  		ret = tun_set_iff(tfile->net, file, &ifr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1192

876bfd4d0   Herbert Xu   tun: Extend RTNL ...
1193
1194
  		if (ret)
  			goto unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195

50857e2a5   Arnd Bergmann   net/tun: handle c...
1196
  		if (copy_to_user(argp, &ifr, ifreq_len))
876bfd4d0   Herbert Xu   tun: Extend RTNL ...
1197
1198
  			ret = -EFAULT;
  		goto unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1199
  	}
876bfd4d0   Herbert Xu   tun: Extend RTNL ...
1200
  	ret = -EBADFD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1201
  	if (!tun)
876bfd4d0   Herbert Xu   tun: Extend RTNL ...
1202
  		goto unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1203

6b8a66ee9   Joe Perches   tun: Convert logg...
1204
1205
  	tun_debug(KERN_INFO, tun, "tun_chr_ioctl cmd %d
  ", cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1206

631ab46b7   Eric W. Biederman   tun: Introduce tu...
1207
  	ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1208
  	switch (cmd) {
e3b995569   Mark McLoughlin   tun: TUNGETIFF in...
1209
  	case TUNGETIFF:
876bfd4d0   Herbert Xu   tun: Extend RTNL ...
1210
  		ret = tun_get_iff(current->nsproxy->net_ns, tun, &ifr);
e3b995569   Mark McLoughlin   tun: TUNGETIFF in...
1211
  		if (ret)
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1212
  			break;
e3b995569   Mark McLoughlin   tun: TUNGETIFF in...
1213

50857e2a5   Arnd Bergmann   net/tun: handle c...
1214
  		if (copy_to_user(argp, &ifr, ifreq_len))
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1215
  			ret = -EFAULT;
e3b995569   Mark McLoughlin   tun: TUNGETIFF in...
1216
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1217
1218
  	case TUNSETNOCSUM:
  		/* Disable/Enable checksum */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1219

882553752   Michał Mirosław   net: tun: convert...
1220
1221
1222
  		/* [unimplemented] */
  		tun_debug(KERN_INFO, tun, "ignored: set checksum %s
  ",
6b8a66ee9   Joe Perches   tun: Convert logg...
1223
  			  arg ? "disabled" : "enabled");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1224
1225
1226
1227
1228
1229
1230
1231
  		break;
  
  	case TUNSETPERSIST:
  		/* Disable/Enable persist mode */
  		if (arg)
  			tun->flags |= TUN_PERSIST;
  		else
  			tun->flags &= ~TUN_PERSIST;
6b8a66ee9   Joe Perches   tun: Convert logg...
1232
1233
1234
  		tun_debug(KERN_INFO, tun, "persist %s
  ",
  			  arg ? "enabled" : "disabled");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1235
1236
1237
1238
1239
  		break;
  
  	case TUNSETOWNER:
  		/* Set owner of the device */
  		tun->owner = (uid_t) arg;
6b8a66ee9   Joe Perches   tun: Convert logg...
1240
1241
  		tun_debug(KERN_INFO, tun, "owner set to %d
  ", tun->owner);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1242
  		break;
8c644623f   Guido Guenther   [NET]: Allow grou...
1243
1244
1245
  	case TUNSETGROUP:
  		/* Set group of the device */
  		tun->group= (gid_t) arg;
6b8a66ee9   Joe Perches   tun: Convert logg...
1246
1247
  		tun_debug(KERN_INFO, tun, "group set to %d
  ", tun->group);
8c644623f   Guido Guenther   [NET]: Allow grou...
1248
  		break;
ff4cc3ac9   Mike Kershaw   [TUNTAP]: Allow s...
1249
1250
1251
  	case TUNSETLINK:
  		/* Only allow setting the type when the interface is down */
  		if (tun->dev->flags & IFF_UP) {
6b8a66ee9   Joe Perches   tun: Convert logg...
1252
1253
1254
  			tun_debug(KERN_INFO, tun,
  				  "Linktype set failed because interface is up
  ");
48abfe05c   David S. Miller   tun: Fix minor ra...
1255
  			ret = -EBUSY;
ff4cc3ac9   Mike Kershaw   [TUNTAP]: Allow s...
1256
1257
  		} else {
  			tun->dev->type = (int) arg;
6b8a66ee9   Joe Perches   tun: Convert logg...
1258
1259
1260
  			tun_debug(KERN_INFO, tun, "linktype set to %d
  ",
  				  tun->dev->type);
48abfe05c   David S. Miller   tun: Fix minor ra...
1261
  			ret = 0;
ff4cc3ac9   Mike Kershaw   [TUNTAP]: Allow s...
1262
  		}
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1263
  		break;
ff4cc3ac9   Mike Kershaw   [TUNTAP]: Allow s...
1264

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1265
1266
1267
1268
1269
  #ifdef TUN_DEBUG
  	case TUNSETDEBUG:
  		tun->debug = arg;
  		break;
  #endif
5228ddc98   Rusty Russell   tun: TUNSETFEATUR...
1270
  	case TUNSETOFFLOAD:
882553752   Michał Mirosław   net: tun: convert...
1271
  		ret = set_offload(tun, arg);
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1272
  		break;
5228ddc98   Rusty Russell   tun: TUNSETFEATUR...
1273

f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
1274
1275
  	case TUNSETTXFILTER:
  		/* Can be set only for TAPs */
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1276
  		ret = -EINVAL;
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
1277
  		if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1278
  			break;
c0e5a8c21   Harvey Harrison   net: tun.c fix cast
1279
  		ret = update_filter(&tun->txflt, (void __user *)arg);
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1280
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1281
1282
  
  	case SIOCGIFHWADDR:
b595076a1   Uwe Kleine-König   tree-wide: fix co...
1283
  		/* Get hw address */
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
1284
1285
  		memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN);
  		ifr.ifr_hwaddr.sa_family = tun->dev->type;
50857e2a5   Arnd Bergmann   net/tun: handle c...
1286
  		if (copy_to_user(argp, &ifr, ifreq_len))
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1287
1288
  			ret = -EFAULT;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1289
1290
  
  	case SIOCSIFHWADDR:
f271b2cc7   Max Krasnyansky   tun: Fix/rewrite ...
1291
  		/* Set hw address */
6b8a66ee9   Joe Perches   tun: Convert logg...
1292
1293
1294
  		tun_debug(KERN_DEBUG, tun, "set hw address: %pM
  ",
  			  ifr.ifr_hwaddr.sa_data);
401023710   Kim B. Heino   [TUN]: Fix RTNL-l...
1295

401023710   Kim B. Heino   [TUN]: Fix RTNL-l...
1296
  		ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1297
  		break;
33dccbb05   Herbert Xu   tun: Limit amount...
1298
1299
  
  	case TUNGETSNDBUF:
89f56d1e9   Michael S. Tsirkin   tun: reuse struct...
1300
  		sndbuf = tun->socket.sk->sk_sndbuf;
33dccbb05   Herbert Xu   tun: Limit amount...
1301
1302
1303
1304
1305
1306
1307
1308
1309
  		if (copy_to_user(argp, &sndbuf, sizeof(sndbuf)))
  			ret = -EFAULT;
  		break;
  
  	case TUNSETSNDBUF:
  		if (copy_from_user(&sndbuf, argp, sizeof(sndbuf))) {
  			ret = -EFAULT;
  			break;
  		}
89f56d1e9   Michael S. Tsirkin   tun: reuse struct...
1310
  		tun->socket.sk->sk_sndbuf = sndbuf;
33dccbb05   Herbert Xu   tun: Limit amount...
1311
  		break;
d9d52b517   Michael S. Tsirkin   tun: add ioctl to...
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
  	case TUNGETVNETHDRSZ:
  		vnet_hdr_sz = tun->vnet_hdr_sz;
  		if (copy_to_user(argp, &vnet_hdr_sz, sizeof(vnet_hdr_sz)))
  			ret = -EFAULT;
  		break;
  
  	case TUNSETVNETHDRSZ:
  		if (copy_from_user(&vnet_hdr_sz, argp, sizeof(vnet_hdr_sz))) {
  			ret = -EFAULT;
  			break;
  		}
  		if (vnet_hdr_sz < (int)sizeof(struct virtio_net_hdr)) {
  			ret = -EINVAL;
  			break;
  		}
  
  		tun->vnet_hdr_sz = vnet_hdr_sz;
  		break;
994051625   Michael S. Tsirkin   tun: socket filte...
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
  	case TUNATTACHFILTER:
  		/* Can be set only for TAPs */
  		ret = -EINVAL;
  		if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
  			break;
  		ret = -EFAULT;
  		if (copy_from_user(&fprog, argp, sizeof(fprog)))
  			break;
  
  		ret = sk_attach_filter(&fprog, tun->socket.sk);
  		break;
  
  	case TUNDETACHFILTER:
  		/* Can be set only for TAPs */
  		ret = -EINVAL;
  		if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
  			break;
  		ret = sk_detach_filter(tun->socket.sk);
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1349
  	default:
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1350
1351
  		ret = -EINVAL;
  		break;
ee289b644   Joe Perches   drivers/net: remo...
1352
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353

876bfd4d0   Herbert Xu   tun: Extend RTNL ...
1354
1355
1356
1357
  unlock:
  	rtnl_unlock();
  	if (tun)
  		tun_put(tun);
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1358
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1359
  }
50857e2a5   Arnd Bergmann   net/tun: handle c...
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
  static long tun_chr_ioctl(struct file *file,
  			  unsigned int cmd, unsigned long arg)
  {
  	return __tun_chr_ioctl(file, cmd, arg, sizeof (struct ifreq));
  }
  
  #ifdef CONFIG_COMPAT
  static long tun_chr_compat_ioctl(struct file *file,
  			 unsigned int cmd, unsigned long arg)
  {
  	switch (cmd) {
  	case TUNSETIFF:
  	case TUNGETIFF:
  	case TUNSETTXFILTER:
  	case TUNGETSNDBUF:
  	case TUNSETSNDBUF:
  	case SIOCGIFHWADDR:
  	case SIOCSIFHWADDR:
  		arg = (unsigned long)compat_ptr(arg);
  		break;
  	default:
  		arg = (compat_ulong_t)arg;
  		break;
  	}
  
  	/*
  	 * compat_ifreq is shorter than ifreq, so we must not access beyond
  	 * the end of that structure. All fields that are used in this
  	 * driver are compatible though, we don't need to convert the
  	 * contents.
  	 */
  	return __tun_chr_ioctl(file, cmd, arg, sizeof(struct compat_ifreq));
  }
  #endif /* CONFIG_COMPAT */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1394
1395
  static int tun_chr_fasync(int fd, struct file *file, int on)
  {
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1396
  	struct tun_struct *tun = tun_get(file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1397
1398
1399
1400
  	int ret;
  
  	if (!tun)
  		return -EBADFD;
6b8a66ee9   Joe Perches   tun: Convert logg...
1401
1402
  	tun_debug(KERN_INFO, tun, "tun_chr_fasync %d
  ", on);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1403
1404
  
  	if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0)
9d3195225   Jonathan Corbet   tun: fasync BKL p...
1405
  		goto out;
6aa20a223   Jeff Garzik   drivers/net: Trim...
1406

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1407
  	if (on) {
609d7fa95   Eric W. Biederman   [PATCH] file: mod...
1408
  		ret = __f_setown(file, task_pid(current), PIDTYPE_PID, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1409
  		if (ret)
9d3195225   Jonathan Corbet   tun: fasync BKL p...
1410
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1411
  		tun->flags |= TUN_FASYNC;
6aa20a223   Jeff Garzik   drivers/net: Trim...
1412
  	} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1413
  		tun->flags &= ~TUN_FASYNC;
9d3195225   Jonathan Corbet   tun: fasync BKL p...
1414
1415
  	ret = 0;
  out:
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1416
  	tun_put(tun);
9d3195225   Jonathan Corbet   tun: fasync BKL p...
1417
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1418
1419
1420
1421
  }
  
  static int tun_chr_open(struct inode *inode, struct file * file)
  {
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1422
  	struct tun_file *tfile;
deed49fbb   Thomas Gleixner   net: Remove BKL f...
1423

6b8a66ee9   Joe Perches   tun: Convert logg...
1424
1425
  	DBG1(KERN_INFO, "tunX: tun_chr_open
  ");
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1426
1427
1428
1429
  
  	tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
  	if (!tfile)
  		return -ENOMEM;
c70f18294   Eric W. Biederman   tun: Fix races be...
1430
  	atomic_set(&tfile->count, 0);
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1431
  	tfile->tun = NULL;
36b50bab5   Eric W. Biederman   tun: Grab the net...
1432
  	tfile->net = get_net(current->nsproxy->net_ns);
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1433
  	file->private_data = tfile;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1434
1435
1436
1437
1438
  	return 0;
  }
  
  static int tun_chr_close(struct inode *inode, struct file *file)
  {
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1439
  	struct tun_file *tfile = file->private_data;
f0a4d0e5b   Eric W. Biederman   tun: Fix unregist...
1440
  	struct tun_struct *tun;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1441

f0a4d0e5b   Eric W. Biederman   tun: Fix unregist...
1442
  	tun = __tun_get(tfile);
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1443
  	if (tun) {
d23e43658   Herbert Xu   tun: Fix device u...
1444
  		struct net_device *dev = tun->dev;
6b8a66ee9   Joe Perches   tun: Convert logg...
1445
1446
  		tun_debug(KERN_INFO, tun, "tun_chr_close
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1447

631ab46b7   Eric W. Biederman   tun: Introduce tu...
1448
  		__tun_detach(tun);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1449

3ad2f3fbb   Daniel Mack   tree-wide: Assort...
1450
  		/* If desirable, unregister the netdevice. */
d23e43658   Herbert Xu   tun: Fix device u...
1451
1452
1453
1454
1455
1456
  		if (!(tun->flags & TUN_PERSIST)) {
  			rtnl_lock();
  			if (dev->reg_state == NETREG_REGISTERED)
  				unregister_netdevice(dev);
  			rtnl_unlock();
  		}
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1457
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1458

9c3fea6ab   Herbert Xu   tun: Only free a ...
1459
1460
  	tun = tfile->tun;
  	if (tun)
89f56d1e9   Michael S. Tsirkin   tun: reuse struct...
1461
  		sock_put(tun->socket.sk);
9c3fea6ab   Herbert Xu   tun: Only free a ...
1462

36b50bab5   Eric W. Biederman   tun: Grab the net...
1463
  	put_net(tfile->net);
631ab46b7   Eric W. Biederman   tun: Introduce tu...
1464
  	kfree(tfile);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1465
1466
1467
  
  	return 0;
  }
d54b1fdb1   Arjan van de Ven   [PATCH] mark stru...
1468
  static const struct file_operations tun_fops = {
6aa20a223   Jeff Garzik   drivers/net: Trim...
1469
  	.owner	= THIS_MODULE,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1470
  	.llseek = no_llseek,
ee0b3e671   Badari Pulavarty   [PATCH] Remove re...
1471
1472
1473
1474
  	.read  = do_sync_read,
  	.aio_read  = tun_chr_aio_read,
  	.write = do_sync_write,
  	.aio_write = tun_chr_aio_write,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1475
  	.poll	= tun_chr_poll,
50857e2a5   Arnd Bergmann   net/tun: handle c...
1476
1477
1478
1479
  	.unlocked_ioctl	= tun_chr_ioctl,
  #ifdef CONFIG_COMPAT
  	.compat_ioctl = tun_chr_compat_ioctl,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1480
1481
  	.open	= tun_chr_open,
  	.release = tun_chr_close,
6aa20a223   Jeff Garzik   drivers/net: Trim...
1482
  	.fasync = tun_chr_fasync
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1483
1484
1485
1486
1487
  };
  
  static struct miscdevice tun_miscdev = {
  	.minor = TUN_MINOR,
  	.name = "tun",
e454cea20   Kay Sievers   Driver-Core: exte...
1488
  	.nodename = "net/tun",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1489
  	.fops = &tun_fops,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1490
1491
1492
1493
1494
1495
1496
1497
  };
  
  /* ethtool interface */
  
  static int tun_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
  {
  	cmd->supported		= 0;
  	cmd->advertising	= 0;
707394972   David Decotigny   ethtool: cosmetic...
1498
  	ethtool_cmd_speed_set(cmd, SPEED_10);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
  	cmd->duplex		= DUPLEX_FULL;
  	cmd->port		= PORT_TP;
  	cmd->phy_address	= 0;
  	cmd->transceiver	= XCVR_INTERNAL;
  	cmd->autoneg		= AUTONEG_DISABLE;
  	cmd->maxtxpkt		= 0;
  	cmd->maxrxpkt		= 0;
  	return 0;
  }
  
  static void tun_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
  {
  	struct tun_struct *tun = netdev_priv(dev);
  
  	strcpy(info->driver, DRV_NAME);
  	strcpy(info->version, DRV_VERSION);
  	strcpy(info->fw_version, "N/A");
  
  	switch (tun->flags & TUN_TYPE_MASK) {
  	case TUN_TUN_DEV:
  		strcpy(info->bus_info, "tun");
  		break;
  	case TUN_TAP_DEV:
  		strcpy(info->bus_info, "tap");
  		break;
  	}
  }
  
  static u32 tun_get_msglevel(struct net_device *dev)
  {
  #ifdef TUN_DEBUG
  	struct tun_struct *tun = netdev_priv(dev);
  	return tun->debug;
  #else
  	return -EOPNOTSUPP;
  #endif
  }
  
  static void tun_set_msglevel(struct net_device *dev, u32 value)
  {
  #ifdef TUN_DEBUG
  	struct tun_struct *tun = netdev_priv(dev);
  	tun->debug = value;
  #endif
  }
7282d491e   Jeff Garzik   drivers/net: cons...
1544
  static const struct ethtool_ops tun_ethtool_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1545
1546
1547
1548
  	.get_settings	= tun_get_settings,
  	.get_drvinfo	= tun_get_drvinfo,
  	.get_msglevel	= tun_get_msglevel,
  	.set_msglevel	= tun_set_msglevel,
bee31369c   Nolan Leake   tun: keep link (c...
1549
  	.get_link	= ethtool_op_get_link,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550
  };
79d176049   Pavel Emelyanov   [TUN]: Introduce ...
1551

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1552
1553
1554
  static int __init tun_init(void)
  {
  	int ret = 0;
6b8a66ee9   Joe Perches   tun: Convert logg...
1555
1556
1557
1558
  	pr_info("%s, %s
  ", DRV_DESCRIPTION, DRV_VERSION);
  	pr_info("%s
  ", DRV_COPYRIGHT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1559

f019a7a59   Eric W. Biederman   tun: Implement ip...
1560
  	ret = rtnl_link_register(&tun_link_ops);
79d176049   Pavel Emelyanov   [TUN]: Introduce ...
1561
  	if (ret) {
6b8a66ee9   Joe Perches   tun: Convert logg...
1562
1563
  		pr_err("Can't register link_ops
  ");
f019a7a59   Eric W. Biederman   tun: Implement ip...
1564
  		goto err_linkops;
79d176049   Pavel Emelyanov   [TUN]: Introduce ...
1565
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1566
  	ret = misc_register(&tun_miscdev);
79d176049   Pavel Emelyanov   [TUN]: Introduce ...
1567
  	if (ret) {
6b8a66ee9   Joe Perches   tun: Convert logg...
1568
1569
  		pr_err("Can't register misc device %d
  ", TUN_MINOR);
79d176049   Pavel Emelyanov   [TUN]: Introduce ...
1570
1571
  		goto err_misc;
  	}
f019a7a59   Eric W. Biederman   tun: Implement ip...
1572
  	return  0;
79d176049   Pavel Emelyanov   [TUN]: Introduce ...
1573
  err_misc:
f019a7a59   Eric W. Biederman   tun: Implement ip...
1574
1575
  	rtnl_link_unregister(&tun_link_ops);
  err_linkops:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1576
1577
1578
1579
1580
  	return ret;
  }
  
  static void tun_cleanup(void)
  {
6aa20a223   Jeff Garzik   drivers/net: Trim...
1581
  	misc_deregister(&tun_miscdev);
f019a7a59   Eric W. Biederman   tun: Implement ip...
1582
  	rtnl_link_unregister(&tun_link_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1583
  }
05c2828c7   Michael S. Tsirkin   tun: export under...
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
  /* Get an underlying socket object from tun file.  Returns error unless file is
   * attached to a device.  The returned object works like a packet socket, it
   * can be used for sock_sendmsg/sock_recvmsg.  The caller is responsible for
   * holding a reference to the file for as long as the socket is in use. */
  struct socket *tun_get_socket(struct file *file)
  {
  	struct tun_struct *tun;
  	if (file->f_op != &tun_fops)
  		return ERR_PTR(-EINVAL);
  	tun = tun_get(file);
  	if (!tun)
  		return ERR_PTR(-EBADFD);
  	tun_put(tun);
  	return &tun->socket;
  }
  EXPORT_SYMBOL_GPL(tun_get_socket);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1600
1601
1602
1603
1604
1605
  module_init(tun_init);
  module_exit(tun_cleanup);
  MODULE_DESCRIPTION(DRV_DESCRIPTION);
  MODULE_AUTHOR(DRV_COPYRIGHT);
  MODULE_LICENSE("GPL");
  MODULE_ALIAS_MISCDEV(TUN_MINOR);
578454ff7   Kay Sievers   driver core: add ...
1606
  MODULE_ALIAS("devname:net/tun");