xref: /openbmc/linux/drivers/net/tun.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  *  TUN - Universal TUN/TAP device driver.
3*1da177e4SLinus Torvalds  *  Copyright (C) 1999-2002 Maxim Krasnyansky <maxk@qualcomm.com>
4*1da177e4SLinus Torvalds  *
5*1da177e4SLinus Torvalds  *  This program is free software; you can redistribute it and/or modify
6*1da177e4SLinus Torvalds  *  it under the terms of the GNU General Public License as published by
7*1da177e4SLinus Torvalds  *  the Free Software Foundation; either version 2 of the License, or
8*1da177e4SLinus Torvalds  *  (at your option) any later version.
9*1da177e4SLinus Torvalds  *
10*1da177e4SLinus Torvalds  *  This program is distributed in the hope that it will be useful,
11*1da177e4SLinus Torvalds  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12*1da177e4SLinus Torvalds  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*1da177e4SLinus Torvalds  *  GNU General Public License for more details.
14*1da177e4SLinus Torvalds  *
15*1da177e4SLinus Torvalds  *  $Id: tun.c,v 1.15 2002/03/01 02:44:24 maxk Exp $
16*1da177e4SLinus Torvalds  */
17*1da177e4SLinus Torvalds 
18*1da177e4SLinus Torvalds /*
19*1da177e4SLinus Torvalds  *  Changes:
20*1da177e4SLinus Torvalds  *
21*1da177e4SLinus Torvalds  *  Mark Smith <markzzzsmith@yahoo.com.au>
22*1da177e4SLinus Torvalds  *   Use random_ether_addr() for tap MAC address.
23*1da177e4SLinus Torvalds  *
24*1da177e4SLinus Torvalds  *  Harald Roelle <harald.roelle@ifi.lmu.de>  2004/04/20
25*1da177e4SLinus Torvalds  *    Fixes in packet dropping, queue length setting and queue wakeup.
26*1da177e4SLinus Torvalds  *    Increased default tx queue length.
27*1da177e4SLinus Torvalds  *    Added ethtool API.
28*1da177e4SLinus Torvalds  *    Minor cleanups
29*1da177e4SLinus Torvalds  *
30*1da177e4SLinus Torvalds  *  Daniel Podlejski <underley@underley.eu.org>
31*1da177e4SLinus Torvalds  *    Modifications for 2.3.99-pre5 kernel.
32*1da177e4SLinus Torvalds  */
33*1da177e4SLinus Torvalds 
34*1da177e4SLinus Torvalds #define DRV_NAME	"tun"
35*1da177e4SLinus Torvalds #define DRV_VERSION	"1.6"
36*1da177e4SLinus Torvalds #define DRV_DESCRIPTION	"Universal TUN/TAP device driver"
37*1da177e4SLinus Torvalds #define DRV_COPYRIGHT	"(C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>"
38*1da177e4SLinus Torvalds 
39*1da177e4SLinus Torvalds #include <linux/config.h>
40*1da177e4SLinus Torvalds #include <linux/module.h>
41*1da177e4SLinus Torvalds #include <linux/errno.h>
42*1da177e4SLinus Torvalds #include <linux/kernel.h>
43*1da177e4SLinus Torvalds #include <linux/major.h>
44*1da177e4SLinus Torvalds #include <linux/slab.h>
45*1da177e4SLinus Torvalds #include <linux/poll.h>
46*1da177e4SLinus Torvalds #include <linux/fcntl.h>
47*1da177e4SLinus Torvalds #include <linux/init.h>
48*1da177e4SLinus Torvalds #include <linux/skbuff.h>
49*1da177e4SLinus Torvalds #include <linux/netdevice.h>
50*1da177e4SLinus Torvalds #include <linux/etherdevice.h>
51*1da177e4SLinus Torvalds #include <linux/miscdevice.h>
52*1da177e4SLinus Torvalds #include <linux/ethtool.h>
53*1da177e4SLinus Torvalds #include <linux/rtnetlink.h>
54*1da177e4SLinus Torvalds #include <linux/if.h>
55*1da177e4SLinus Torvalds #include <linux/if_arp.h>
56*1da177e4SLinus Torvalds #include <linux/if_ether.h>
57*1da177e4SLinus Torvalds #include <linux/if_tun.h>
58*1da177e4SLinus Torvalds #include <linux/crc32.h>
59*1da177e4SLinus Torvalds 
60*1da177e4SLinus Torvalds #include <asm/system.h>
61*1da177e4SLinus Torvalds #include <asm/uaccess.h>
62*1da177e4SLinus Torvalds 
63*1da177e4SLinus Torvalds #ifdef TUN_DEBUG
64*1da177e4SLinus Torvalds static int debug;
65*1da177e4SLinus Torvalds #endif
66*1da177e4SLinus Torvalds 
67*1da177e4SLinus Torvalds /* Network device part of the driver */
68*1da177e4SLinus Torvalds 
69*1da177e4SLinus Torvalds static LIST_HEAD(tun_dev_list);
70*1da177e4SLinus Torvalds static struct ethtool_ops tun_ethtool_ops;
71*1da177e4SLinus Torvalds 
72*1da177e4SLinus Torvalds /* Net device open. */
73*1da177e4SLinus Torvalds static int tun_net_open(struct net_device *dev)
74*1da177e4SLinus Torvalds {
75*1da177e4SLinus Torvalds 	netif_start_queue(dev);
76*1da177e4SLinus Torvalds 	return 0;
77*1da177e4SLinus Torvalds }
78*1da177e4SLinus Torvalds 
79*1da177e4SLinus Torvalds /* Net device close. */
80*1da177e4SLinus Torvalds static int tun_net_close(struct net_device *dev)
81*1da177e4SLinus Torvalds {
82*1da177e4SLinus Torvalds 	netif_stop_queue(dev);
83*1da177e4SLinus Torvalds 	return 0;
84*1da177e4SLinus Torvalds }
85*1da177e4SLinus Torvalds 
86*1da177e4SLinus Torvalds /* Net device start xmit */
87*1da177e4SLinus Torvalds static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
88*1da177e4SLinus Torvalds {
89*1da177e4SLinus Torvalds 	struct tun_struct *tun = netdev_priv(dev);
90*1da177e4SLinus Torvalds 
91*1da177e4SLinus Torvalds 	DBG(KERN_INFO "%s: tun_net_xmit %d\n", tun->dev->name, skb->len);
92*1da177e4SLinus Torvalds 
93*1da177e4SLinus Torvalds 	/* Drop packet if interface is not attached */
94*1da177e4SLinus Torvalds 	if (!tun->attached)
95*1da177e4SLinus Torvalds 		goto drop;
96*1da177e4SLinus Torvalds 
97*1da177e4SLinus Torvalds 	/* Packet dropping */
98*1da177e4SLinus Torvalds 	if (skb_queue_len(&tun->readq) >= dev->tx_queue_len) {
99*1da177e4SLinus Torvalds 		if (!(tun->flags & TUN_ONE_QUEUE)) {
100*1da177e4SLinus Torvalds 			/* Normal queueing mode. */
101*1da177e4SLinus Torvalds 			/* Packet scheduler handles dropping of further packets. */
102*1da177e4SLinus Torvalds 			netif_stop_queue(dev);
103*1da177e4SLinus Torvalds 
104*1da177e4SLinus Torvalds 			/* We won't see all dropped packets individually, so overrun
105*1da177e4SLinus Torvalds 			 * error is more appropriate. */
106*1da177e4SLinus Torvalds 			tun->stats.tx_fifo_errors++;
107*1da177e4SLinus Torvalds 		} else {
108*1da177e4SLinus Torvalds 			/* Single queue mode.
109*1da177e4SLinus Torvalds 			 * Driver handles dropping of all packets itself. */
110*1da177e4SLinus Torvalds 			goto drop;
111*1da177e4SLinus Torvalds 		}
112*1da177e4SLinus Torvalds 	}
113*1da177e4SLinus Torvalds 
114*1da177e4SLinus Torvalds 	/* Queue packet */
115*1da177e4SLinus Torvalds 	skb_queue_tail(&tun->readq, skb);
116*1da177e4SLinus Torvalds 	dev->trans_start = jiffies;
117*1da177e4SLinus Torvalds 
118*1da177e4SLinus Torvalds 	/* Notify and wake up reader process */
119*1da177e4SLinus Torvalds 	if (tun->flags & TUN_FASYNC)
120*1da177e4SLinus Torvalds 		kill_fasync(&tun->fasync, SIGIO, POLL_IN);
121*1da177e4SLinus Torvalds 	wake_up_interruptible(&tun->read_wait);
122*1da177e4SLinus Torvalds 	return 0;
123*1da177e4SLinus Torvalds 
124*1da177e4SLinus Torvalds drop:
125*1da177e4SLinus Torvalds 	tun->stats.tx_dropped++;
126*1da177e4SLinus Torvalds 	kfree_skb(skb);
127*1da177e4SLinus Torvalds 	return 0;
128*1da177e4SLinus Torvalds }
129*1da177e4SLinus Torvalds 
130*1da177e4SLinus Torvalds /** Add the specified Ethernet address to this multicast filter. */
131*1da177e4SLinus Torvalds static void
132*1da177e4SLinus Torvalds add_multi(u32* filter, const u8* addr)
133*1da177e4SLinus Torvalds {
134*1da177e4SLinus Torvalds 	int bit_nr = ether_crc(ETH_ALEN, addr) >> 26;
135*1da177e4SLinus Torvalds 	filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
136*1da177e4SLinus Torvalds }
137*1da177e4SLinus Torvalds 
138*1da177e4SLinus Torvalds /** Remove the specified Ethernet addres from this multicast filter. */
139*1da177e4SLinus Torvalds static void
140*1da177e4SLinus Torvalds del_multi(u32* filter, const u8* addr)
141*1da177e4SLinus Torvalds {
142*1da177e4SLinus Torvalds 	int bit_nr = ether_crc(ETH_ALEN, addr) >> 26;
143*1da177e4SLinus Torvalds 	filter[bit_nr >> 5] &= ~(1 << (bit_nr & 31));
144*1da177e4SLinus Torvalds }
145*1da177e4SLinus Torvalds 
146*1da177e4SLinus Torvalds /** Update the list of multicast groups to which the network device belongs.
147*1da177e4SLinus Torvalds  * This list is used to filter packets being sent from the character device to
148*1da177e4SLinus Torvalds  * the network device. */
149*1da177e4SLinus Torvalds static void
150*1da177e4SLinus Torvalds tun_net_mclist(struct net_device *dev)
151*1da177e4SLinus Torvalds {
152*1da177e4SLinus Torvalds 	struct tun_struct *tun = netdev_priv(dev);
153*1da177e4SLinus Torvalds 	const struct dev_mc_list *mclist;
154*1da177e4SLinus Torvalds 	int i;
155*1da177e4SLinus Torvalds 	DBG(KERN_DEBUG "%s: tun_net_mclist: mc_count %d\n",
156*1da177e4SLinus Torvalds 			dev->name, dev->mc_count);
157*1da177e4SLinus Torvalds 	memset(tun->chr_filter, 0, sizeof tun->chr_filter);
158*1da177e4SLinus Torvalds 	for (i = 0, mclist = dev->mc_list; i < dev->mc_count && mclist != NULL;
159*1da177e4SLinus Torvalds 			i++, mclist = mclist->next) {
160*1da177e4SLinus Torvalds 		add_multi(tun->net_filter, mclist->dmi_addr);
161*1da177e4SLinus Torvalds 		DBG(KERN_DEBUG "%s: tun_net_mclist: %x:%x:%x:%x:%x:%x\n",
162*1da177e4SLinus Torvalds 				dev->name,
163*1da177e4SLinus Torvalds 				mclist->dmi_addr[0], mclist->dmi_addr[1], mclist->dmi_addr[2],
164*1da177e4SLinus Torvalds 				mclist->dmi_addr[3], mclist->dmi_addr[4], mclist->dmi_addr[5]);
165*1da177e4SLinus Torvalds 	}
166*1da177e4SLinus Torvalds }
167*1da177e4SLinus Torvalds 
168*1da177e4SLinus Torvalds static struct net_device_stats *tun_net_stats(struct net_device *dev)
169*1da177e4SLinus Torvalds {
170*1da177e4SLinus Torvalds 	struct tun_struct *tun = netdev_priv(dev);
171*1da177e4SLinus Torvalds 	return &tun->stats;
172*1da177e4SLinus Torvalds }
173*1da177e4SLinus Torvalds 
174*1da177e4SLinus Torvalds /* Initialize net device. */
175*1da177e4SLinus Torvalds static void tun_net_init(struct net_device *dev)
176*1da177e4SLinus Torvalds {
177*1da177e4SLinus Torvalds 	struct tun_struct *tun = netdev_priv(dev);
178*1da177e4SLinus Torvalds 
179*1da177e4SLinus Torvalds 	switch (tun->flags & TUN_TYPE_MASK) {
180*1da177e4SLinus Torvalds 	case TUN_TUN_DEV:
181*1da177e4SLinus Torvalds 		/* Point-to-Point TUN Device */
182*1da177e4SLinus Torvalds 		dev->hard_header_len = 0;
183*1da177e4SLinus Torvalds 		dev->addr_len = 0;
184*1da177e4SLinus Torvalds 		dev->mtu = 1500;
185*1da177e4SLinus Torvalds 
186*1da177e4SLinus Torvalds 		/* Zero header length */
187*1da177e4SLinus Torvalds 		dev->type = ARPHRD_NONE;
188*1da177e4SLinus Torvalds 		dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
189*1da177e4SLinus Torvalds 		dev->tx_queue_len = TUN_READQ_SIZE;  /* We prefer our own queue length */
190*1da177e4SLinus Torvalds 		break;
191*1da177e4SLinus Torvalds 
192*1da177e4SLinus Torvalds 	case TUN_TAP_DEV:
193*1da177e4SLinus Torvalds 		/* Ethernet TAP Device */
194*1da177e4SLinus Torvalds 		dev->set_multicast_list = tun_net_mclist;
195*1da177e4SLinus Torvalds 
196*1da177e4SLinus Torvalds 		ether_setup(dev);
197*1da177e4SLinus Torvalds 		random_ether_addr(dev->dev_addr);
198*1da177e4SLinus Torvalds 		dev->tx_queue_len = TUN_READQ_SIZE;  /* We prefer our own queue length */
199*1da177e4SLinus Torvalds 		break;
200*1da177e4SLinus Torvalds 	}
201*1da177e4SLinus Torvalds }
202*1da177e4SLinus Torvalds 
203*1da177e4SLinus Torvalds /* Character device part */
204*1da177e4SLinus Torvalds 
205*1da177e4SLinus Torvalds /* Poll */
206*1da177e4SLinus Torvalds static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
207*1da177e4SLinus Torvalds {
208*1da177e4SLinus Torvalds 	struct tun_struct *tun = file->private_data;
209*1da177e4SLinus Torvalds 	unsigned int mask = POLLOUT | POLLWRNORM;
210*1da177e4SLinus Torvalds 
211*1da177e4SLinus Torvalds 	if (!tun)
212*1da177e4SLinus Torvalds 		return -EBADFD;
213*1da177e4SLinus Torvalds 
214*1da177e4SLinus Torvalds 	DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);
215*1da177e4SLinus Torvalds 
216*1da177e4SLinus Torvalds 	poll_wait(file, &tun->read_wait, wait);
217*1da177e4SLinus Torvalds 
218*1da177e4SLinus Torvalds 	if (skb_queue_len(&tun->readq))
219*1da177e4SLinus Torvalds 		mask |= POLLIN | POLLRDNORM;
220*1da177e4SLinus Torvalds 
221*1da177e4SLinus Torvalds 	return mask;
222*1da177e4SLinus Torvalds }
223*1da177e4SLinus Torvalds 
224*1da177e4SLinus Torvalds /* Get packet from user space buffer */
225*1da177e4SLinus Torvalds static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, size_t count)
226*1da177e4SLinus Torvalds {
227*1da177e4SLinus Torvalds 	struct tun_pi pi = { 0, __constant_htons(ETH_P_IP) };
228*1da177e4SLinus Torvalds 	struct sk_buff *skb;
229*1da177e4SLinus Torvalds 	size_t len = count, align = 0;
230*1da177e4SLinus Torvalds 
231*1da177e4SLinus Torvalds 	if (!(tun->flags & TUN_NO_PI)) {
232*1da177e4SLinus Torvalds 		if ((len -= sizeof(pi)) > count)
233*1da177e4SLinus Torvalds 			return -EINVAL;
234*1da177e4SLinus Torvalds 
235*1da177e4SLinus Torvalds 		if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi)))
236*1da177e4SLinus Torvalds 			return -EFAULT;
237*1da177e4SLinus Torvalds 	}
238*1da177e4SLinus Torvalds 
239*1da177e4SLinus Torvalds 	if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV)
240*1da177e4SLinus Torvalds 		align = NET_IP_ALIGN;
241*1da177e4SLinus Torvalds 
242*1da177e4SLinus Torvalds 	if (!(skb = alloc_skb(len + align, GFP_KERNEL))) {
243*1da177e4SLinus Torvalds 		tun->stats.rx_dropped++;
244*1da177e4SLinus Torvalds 		return -ENOMEM;
245*1da177e4SLinus Torvalds 	}
246*1da177e4SLinus Torvalds 
247*1da177e4SLinus Torvalds 	if (align)
248*1da177e4SLinus Torvalds 		skb_reserve(skb, align);
249*1da177e4SLinus Torvalds 	if (memcpy_fromiovec(skb_put(skb, len), iv, len))
250*1da177e4SLinus Torvalds 		return -EFAULT;
251*1da177e4SLinus Torvalds 
252*1da177e4SLinus Torvalds 	skb->dev = tun->dev;
253*1da177e4SLinus Torvalds 	switch (tun->flags & TUN_TYPE_MASK) {
254*1da177e4SLinus Torvalds 	case TUN_TUN_DEV:
255*1da177e4SLinus Torvalds 		skb->mac.raw = skb->data;
256*1da177e4SLinus Torvalds 		skb->protocol = pi.proto;
257*1da177e4SLinus Torvalds 		break;
258*1da177e4SLinus Torvalds 	case TUN_TAP_DEV:
259*1da177e4SLinus Torvalds 		skb->protocol = eth_type_trans(skb, tun->dev);
260*1da177e4SLinus Torvalds 		break;
261*1da177e4SLinus Torvalds 	};
262*1da177e4SLinus Torvalds 
263*1da177e4SLinus Torvalds 	if (tun->flags & TUN_NOCHECKSUM)
264*1da177e4SLinus Torvalds 		skb->ip_summed = CHECKSUM_UNNECESSARY;
265*1da177e4SLinus Torvalds 
266*1da177e4SLinus Torvalds 	netif_rx_ni(skb);
267*1da177e4SLinus Torvalds 	tun->dev->last_rx = jiffies;
268*1da177e4SLinus Torvalds 
269*1da177e4SLinus Torvalds 	tun->stats.rx_packets++;
270*1da177e4SLinus Torvalds 	tun->stats.rx_bytes += len;
271*1da177e4SLinus Torvalds 
272*1da177e4SLinus Torvalds 	return count;
273*1da177e4SLinus Torvalds }
274*1da177e4SLinus Torvalds 
275*1da177e4SLinus Torvalds static inline size_t iov_total(const struct iovec *iv, unsigned long count)
276*1da177e4SLinus Torvalds {
277*1da177e4SLinus Torvalds 	unsigned long i;
278*1da177e4SLinus Torvalds 	size_t len;
279*1da177e4SLinus Torvalds 
280*1da177e4SLinus Torvalds 	for (i = 0, len = 0; i < count; i++)
281*1da177e4SLinus Torvalds 		len += iv[i].iov_len;
282*1da177e4SLinus Torvalds 
283*1da177e4SLinus Torvalds 	return len;
284*1da177e4SLinus Torvalds }
285*1da177e4SLinus Torvalds 
286*1da177e4SLinus Torvalds /* Writev */
287*1da177e4SLinus Torvalds static ssize_t tun_chr_writev(struct file * file, const struct iovec *iv,
288*1da177e4SLinus Torvalds 			      unsigned long count, loff_t *pos)
289*1da177e4SLinus Torvalds {
290*1da177e4SLinus Torvalds 	struct tun_struct *tun = file->private_data;
291*1da177e4SLinus Torvalds 
292*1da177e4SLinus Torvalds 	if (!tun)
293*1da177e4SLinus Torvalds 		return -EBADFD;
294*1da177e4SLinus Torvalds 
295*1da177e4SLinus Torvalds 	DBG(KERN_INFO "%s: tun_chr_write %ld\n", tun->dev->name, count);
296*1da177e4SLinus Torvalds 
297*1da177e4SLinus Torvalds 	return tun_get_user(tun, (struct iovec *) iv, iov_total(iv, count));
298*1da177e4SLinus Torvalds }
299*1da177e4SLinus Torvalds 
300*1da177e4SLinus Torvalds /* Write */
301*1da177e4SLinus Torvalds static ssize_t tun_chr_write(struct file * file, const char __user * buf,
302*1da177e4SLinus Torvalds 			     size_t count, loff_t *pos)
303*1da177e4SLinus Torvalds {
304*1da177e4SLinus Torvalds 	struct iovec iv = { (void __user *) buf, count };
305*1da177e4SLinus Torvalds 	return tun_chr_writev(file, &iv, 1, pos);
306*1da177e4SLinus Torvalds }
307*1da177e4SLinus Torvalds 
308*1da177e4SLinus Torvalds /* Put packet to the user space buffer */
309*1da177e4SLinus Torvalds static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
310*1da177e4SLinus Torvalds 				       struct sk_buff *skb,
311*1da177e4SLinus Torvalds 				       struct iovec *iv, int len)
312*1da177e4SLinus Torvalds {
313*1da177e4SLinus Torvalds 	struct tun_pi pi = { 0, skb->protocol };
314*1da177e4SLinus Torvalds 	ssize_t total = 0;
315*1da177e4SLinus Torvalds 
316*1da177e4SLinus Torvalds 	if (!(tun->flags & TUN_NO_PI)) {
317*1da177e4SLinus Torvalds 		if ((len -= sizeof(pi)) < 0)
318*1da177e4SLinus Torvalds 			return -EINVAL;
319*1da177e4SLinus Torvalds 
320*1da177e4SLinus Torvalds 		if (len < skb->len) {
321*1da177e4SLinus Torvalds 			/* Packet will be striped */
322*1da177e4SLinus Torvalds 			pi.flags |= TUN_PKT_STRIP;
323*1da177e4SLinus Torvalds 		}
324*1da177e4SLinus Torvalds 
325*1da177e4SLinus Torvalds 		if (memcpy_toiovec(iv, (void *) &pi, sizeof(pi)))
326*1da177e4SLinus Torvalds 			return -EFAULT;
327*1da177e4SLinus Torvalds 		total += sizeof(pi);
328*1da177e4SLinus Torvalds 	}
329*1da177e4SLinus Torvalds 
330*1da177e4SLinus Torvalds 	len = min_t(int, skb->len, len);
331*1da177e4SLinus Torvalds 
332*1da177e4SLinus Torvalds 	skb_copy_datagram_iovec(skb, 0, iv, len);
333*1da177e4SLinus Torvalds 	total += len;
334*1da177e4SLinus Torvalds 
335*1da177e4SLinus Torvalds 	tun->stats.tx_packets++;
336*1da177e4SLinus Torvalds 	tun->stats.tx_bytes += len;
337*1da177e4SLinus Torvalds 
338*1da177e4SLinus Torvalds 	return total;
339*1da177e4SLinus Torvalds }
340*1da177e4SLinus Torvalds 
341*1da177e4SLinus Torvalds /* Readv */
342*1da177e4SLinus Torvalds static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv,
343*1da177e4SLinus Torvalds 			    unsigned long count, loff_t *pos)
344*1da177e4SLinus Torvalds {
345*1da177e4SLinus Torvalds 	struct tun_struct *tun = file->private_data;
346*1da177e4SLinus Torvalds 	DECLARE_WAITQUEUE(wait, current);
347*1da177e4SLinus Torvalds 	struct sk_buff *skb;
348*1da177e4SLinus Torvalds 	ssize_t len, ret = 0;
349*1da177e4SLinus Torvalds 
350*1da177e4SLinus Torvalds 	if (!tun)
351*1da177e4SLinus Torvalds 		return -EBADFD;
352*1da177e4SLinus Torvalds 
353*1da177e4SLinus Torvalds 	DBG(KERN_INFO "%s: tun_chr_read\n", tun->dev->name);
354*1da177e4SLinus Torvalds 
355*1da177e4SLinus Torvalds 	len = iov_total(iv, count);
356*1da177e4SLinus Torvalds 	if (len < 0)
357*1da177e4SLinus Torvalds 		return -EINVAL;
358*1da177e4SLinus Torvalds 
359*1da177e4SLinus Torvalds 	add_wait_queue(&tun->read_wait, &wait);
360*1da177e4SLinus Torvalds 	while (len) {
361*1da177e4SLinus Torvalds 		const u8 ones[ ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
362*1da177e4SLinus Torvalds 		u8 addr[ ETH_ALEN];
363*1da177e4SLinus Torvalds 		int bit_nr;
364*1da177e4SLinus Torvalds 
365*1da177e4SLinus Torvalds 		current->state = TASK_INTERRUPTIBLE;
366*1da177e4SLinus Torvalds 
367*1da177e4SLinus Torvalds 		/* Read frames from the queue */
368*1da177e4SLinus Torvalds 		if (!(skb=skb_dequeue(&tun->readq))) {
369*1da177e4SLinus Torvalds 			if (file->f_flags & O_NONBLOCK) {
370*1da177e4SLinus Torvalds 				ret = -EAGAIN;
371*1da177e4SLinus Torvalds 				break;
372*1da177e4SLinus Torvalds 			}
373*1da177e4SLinus Torvalds 			if (signal_pending(current)) {
374*1da177e4SLinus Torvalds 				ret = -ERESTARTSYS;
375*1da177e4SLinus Torvalds 				break;
376*1da177e4SLinus Torvalds 			}
377*1da177e4SLinus Torvalds 
378*1da177e4SLinus Torvalds 			/* Nothing to read, let's sleep */
379*1da177e4SLinus Torvalds 			schedule();
380*1da177e4SLinus Torvalds 			continue;
381*1da177e4SLinus Torvalds 		}
382*1da177e4SLinus Torvalds 		netif_wake_queue(tun->dev);
383*1da177e4SLinus Torvalds 
384*1da177e4SLinus Torvalds 		/** Decide whether to accept this packet. This code is designed to
385*1da177e4SLinus Torvalds 		 * behave identically to an Ethernet interface. Accept the packet if
386*1da177e4SLinus Torvalds 		 * - we are promiscuous.
387*1da177e4SLinus Torvalds 		 * - the packet is addressed to us.
388*1da177e4SLinus Torvalds 		 * - the packet is broadcast.
389*1da177e4SLinus Torvalds 		 * - the packet is multicast and
390*1da177e4SLinus Torvalds 		 *   - we are multicast promiscous.
391*1da177e4SLinus Torvalds 		 *   - we belong to the multicast group.
392*1da177e4SLinus Torvalds 		 */
393*1da177e4SLinus Torvalds 		memcpy(addr, skb->data,
394*1da177e4SLinus Torvalds 		       min_t(size_t, sizeof addr, skb->len));
395*1da177e4SLinus Torvalds 		bit_nr = ether_crc(sizeof addr, addr) >> 26;
396*1da177e4SLinus Torvalds 		if ((tun->if_flags & IFF_PROMISC) ||
397*1da177e4SLinus Torvalds 				memcmp(addr, tun->dev_addr, sizeof addr) == 0 ||
398*1da177e4SLinus Torvalds 				memcmp(addr, ones, sizeof addr) == 0 ||
399*1da177e4SLinus Torvalds 				(((addr[0] == 1 && addr[1] == 0 && addr[2] == 0x5e) ||
400*1da177e4SLinus Torvalds 				  (addr[0] == 0x33 && addr[1] == 0x33)) &&
401*1da177e4SLinus Torvalds 				 ((tun->if_flags & IFF_ALLMULTI) ||
402*1da177e4SLinus Torvalds 				  (tun->chr_filter[bit_nr >> 5] & (1 << (bit_nr & 31)))))) {
403*1da177e4SLinus Torvalds 			DBG(KERN_DEBUG "%s: tun_chr_readv: accepted: %x:%x:%x:%x:%x:%x\n",
404*1da177e4SLinus Torvalds 					tun->dev->name, addr[0], addr[1], addr[2],
405*1da177e4SLinus Torvalds 					addr[3], addr[4], addr[5]);
406*1da177e4SLinus Torvalds 			ret = tun_put_user(tun, skb, (struct iovec *) iv, len);
407*1da177e4SLinus Torvalds 			kfree_skb(skb);
408*1da177e4SLinus Torvalds 			break;
409*1da177e4SLinus Torvalds 		} else {
410*1da177e4SLinus Torvalds 			DBG(KERN_DEBUG "%s: tun_chr_readv: rejected: %x:%x:%x:%x:%x:%x\n",
411*1da177e4SLinus Torvalds 					tun->dev->name, addr[0], addr[1], addr[2],
412*1da177e4SLinus Torvalds 					addr[3], addr[4], addr[5]);
413*1da177e4SLinus Torvalds 			kfree_skb(skb);
414*1da177e4SLinus Torvalds 			continue;
415*1da177e4SLinus Torvalds 		}
416*1da177e4SLinus Torvalds 	}
417*1da177e4SLinus Torvalds 
418*1da177e4SLinus Torvalds 	current->state = TASK_RUNNING;
419*1da177e4SLinus Torvalds 	remove_wait_queue(&tun->read_wait, &wait);
420*1da177e4SLinus Torvalds 
421*1da177e4SLinus Torvalds 	return ret;
422*1da177e4SLinus Torvalds }
423*1da177e4SLinus Torvalds 
424*1da177e4SLinus Torvalds /* Read */
425*1da177e4SLinus Torvalds static ssize_t tun_chr_read(struct file * file, char __user * buf,
426*1da177e4SLinus Torvalds 			    size_t count, loff_t *pos)
427*1da177e4SLinus Torvalds {
428*1da177e4SLinus Torvalds 	struct iovec iv = { buf, count };
429*1da177e4SLinus Torvalds 	return tun_chr_readv(file, &iv, 1, pos);
430*1da177e4SLinus Torvalds }
431*1da177e4SLinus Torvalds 
432*1da177e4SLinus Torvalds static void tun_setup(struct net_device *dev)
433*1da177e4SLinus Torvalds {
434*1da177e4SLinus Torvalds 	struct tun_struct *tun = netdev_priv(dev);
435*1da177e4SLinus Torvalds 
436*1da177e4SLinus Torvalds 	skb_queue_head_init(&tun->readq);
437*1da177e4SLinus Torvalds 	init_waitqueue_head(&tun->read_wait);
438*1da177e4SLinus Torvalds 
439*1da177e4SLinus Torvalds 	tun->owner = -1;
440*1da177e4SLinus Torvalds 
441*1da177e4SLinus Torvalds 	SET_MODULE_OWNER(dev);
442*1da177e4SLinus Torvalds 	dev->open = tun_net_open;
443*1da177e4SLinus Torvalds 	dev->hard_start_xmit = tun_net_xmit;
444*1da177e4SLinus Torvalds 	dev->stop = tun_net_close;
445*1da177e4SLinus Torvalds 	dev->get_stats = tun_net_stats;
446*1da177e4SLinus Torvalds 	dev->ethtool_ops = &tun_ethtool_ops;
447*1da177e4SLinus Torvalds 	dev->destructor = free_netdev;
448*1da177e4SLinus Torvalds }
449*1da177e4SLinus Torvalds 
450*1da177e4SLinus Torvalds static struct tun_struct *tun_get_by_name(const char *name)
451*1da177e4SLinus Torvalds {
452*1da177e4SLinus Torvalds 	struct tun_struct *tun;
453*1da177e4SLinus Torvalds 
454*1da177e4SLinus Torvalds 	ASSERT_RTNL();
455*1da177e4SLinus Torvalds 	list_for_each_entry(tun, &tun_dev_list, list) {
456*1da177e4SLinus Torvalds 		if (!strncmp(tun->dev->name, name, IFNAMSIZ))
457*1da177e4SLinus Torvalds 		    return tun;
458*1da177e4SLinus Torvalds 	}
459*1da177e4SLinus Torvalds 
460*1da177e4SLinus Torvalds 	return NULL;
461*1da177e4SLinus Torvalds }
462*1da177e4SLinus Torvalds 
463*1da177e4SLinus Torvalds static int tun_set_iff(struct file *file, struct ifreq *ifr)
464*1da177e4SLinus Torvalds {
465*1da177e4SLinus Torvalds 	struct tun_struct *tun;
466*1da177e4SLinus Torvalds 	struct net_device *dev;
467*1da177e4SLinus Torvalds 	int err;
468*1da177e4SLinus Torvalds 
469*1da177e4SLinus Torvalds 	tun = tun_get_by_name(ifr->ifr_name);
470*1da177e4SLinus Torvalds 	if (tun) {
471*1da177e4SLinus Torvalds 		if (tun->attached)
472*1da177e4SLinus Torvalds 			return -EBUSY;
473*1da177e4SLinus Torvalds 
474*1da177e4SLinus Torvalds 		/* Check permissions */
475*1da177e4SLinus Torvalds 		if (tun->owner != -1 &&
476*1da177e4SLinus Torvalds 		    current->euid != tun->owner && !capable(CAP_NET_ADMIN))
477*1da177e4SLinus Torvalds 			return -EPERM;
478*1da177e4SLinus Torvalds 	}
479*1da177e4SLinus Torvalds 	else if (__dev_get_by_name(ifr->ifr_name))
480*1da177e4SLinus Torvalds 		return -EINVAL;
481*1da177e4SLinus Torvalds 	else {
482*1da177e4SLinus Torvalds 		char *name;
483*1da177e4SLinus Torvalds 		unsigned long flags = 0;
484*1da177e4SLinus Torvalds 
485*1da177e4SLinus Torvalds 		err = -EINVAL;
486*1da177e4SLinus Torvalds 
487*1da177e4SLinus Torvalds 		/* Set dev type */
488*1da177e4SLinus Torvalds 		if (ifr->ifr_flags & IFF_TUN) {
489*1da177e4SLinus Torvalds 			/* TUN device */
490*1da177e4SLinus Torvalds 			flags |= TUN_TUN_DEV;
491*1da177e4SLinus Torvalds 			name = "tun%d";
492*1da177e4SLinus Torvalds 		} else if (ifr->ifr_flags & IFF_TAP) {
493*1da177e4SLinus Torvalds 			/* TAP device */
494*1da177e4SLinus Torvalds 			flags |= TUN_TAP_DEV;
495*1da177e4SLinus Torvalds 			name = "tap%d";
496*1da177e4SLinus Torvalds 		} else
497*1da177e4SLinus Torvalds 			goto failed;
498*1da177e4SLinus Torvalds 
499*1da177e4SLinus Torvalds 		if (*ifr->ifr_name)
500*1da177e4SLinus Torvalds 			name = ifr->ifr_name;
501*1da177e4SLinus Torvalds 
502*1da177e4SLinus Torvalds 		dev = alloc_netdev(sizeof(struct tun_struct), name,
503*1da177e4SLinus Torvalds 				   tun_setup);
504*1da177e4SLinus Torvalds 		if (!dev)
505*1da177e4SLinus Torvalds 			return -ENOMEM;
506*1da177e4SLinus Torvalds 
507*1da177e4SLinus Torvalds 		tun = netdev_priv(dev);
508*1da177e4SLinus Torvalds 		tun->dev = dev;
509*1da177e4SLinus Torvalds 		tun->flags = flags;
510*1da177e4SLinus Torvalds 		/* Be promiscuous by default to maintain previous behaviour. */
511*1da177e4SLinus Torvalds 		tun->if_flags = IFF_PROMISC;
512*1da177e4SLinus Torvalds 		/* Generate random Ethernet address. */
513*1da177e4SLinus Torvalds 		*(u16 *)tun->dev_addr = htons(0x00FF);
514*1da177e4SLinus Torvalds 		get_random_bytes(tun->dev_addr + sizeof(u16), 4);
515*1da177e4SLinus Torvalds 		memset(tun->chr_filter, 0, sizeof tun->chr_filter);
516*1da177e4SLinus Torvalds 
517*1da177e4SLinus Torvalds 		tun_net_init(dev);
518*1da177e4SLinus Torvalds 
519*1da177e4SLinus Torvalds 		if (strchr(dev->name, '%')) {
520*1da177e4SLinus Torvalds 			err = dev_alloc_name(dev, dev->name);
521*1da177e4SLinus Torvalds 			if (err < 0)
522*1da177e4SLinus Torvalds 				goto err_free_dev;
523*1da177e4SLinus Torvalds 		}
524*1da177e4SLinus Torvalds 
525*1da177e4SLinus Torvalds 		err = register_netdevice(tun->dev);
526*1da177e4SLinus Torvalds 		if (err < 0)
527*1da177e4SLinus Torvalds 			goto err_free_dev;
528*1da177e4SLinus Torvalds 
529*1da177e4SLinus Torvalds 		list_add(&tun->list, &tun_dev_list);
530*1da177e4SLinus Torvalds 	}
531*1da177e4SLinus Torvalds 
532*1da177e4SLinus Torvalds 	DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name);
533*1da177e4SLinus Torvalds 
534*1da177e4SLinus Torvalds 	if (ifr->ifr_flags & IFF_NO_PI)
535*1da177e4SLinus Torvalds 		tun->flags |= TUN_NO_PI;
536*1da177e4SLinus Torvalds 
537*1da177e4SLinus Torvalds 	if (ifr->ifr_flags & IFF_ONE_QUEUE)
538*1da177e4SLinus Torvalds 		tun->flags |= TUN_ONE_QUEUE;
539*1da177e4SLinus Torvalds 
540*1da177e4SLinus Torvalds 	file->private_data = tun;
541*1da177e4SLinus Torvalds 	tun->attached = 1;
542*1da177e4SLinus Torvalds 
543*1da177e4SLinus Torvalds 	strcpy(ifr->ifr_name, tun->dev->name);
544*1da177e4SLinus Torvalds 	return 0;
545*1da177e4SLinus Torvalds 
546*1da177e4SLinus Torvalds  err_free_dev:
547*1da177e4SLinus Torvalds 	free_netdev(dev);
548*1da177e4SLinus Torvalds  failed:
549*1da177e4SLinus Torvalds 	return err;
550*1da177e4SLinus Torvalds }
551*1da177e4SLinus Torvalds 
552*1da177e4SLinus Torvalds static int tun_chr_ioctl(struct inode *inode, struct file *file,
553*1da177e4SLinus Torvalds 			 unsigned int cmd, unsigned long arg)
554*1da177e4SLinus Torvalds {
555*1da177e4SLinus Torvalds 	struct tun_struct *tun = file->private_data;
556*1da177e4SLinus Torvalds 	void __user* argp = (void __user*)arg;
557*1da177e4SLinus Torvalds 	struct ifreq ifr;
558*1da177e4SLinus Torvalds 
559*1da177e4SLinus Torvalds 	if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89)
560*1da177e4SLinus Torvalds 		if (copy_from_user(&ifr, argp, sizeof ifr))
561*1da177e4SLinus Torvalds 			return -EFAULT;
562*1da177e4SLinus Torvalds 
563*1da177e4SLinus Torvalds 	if (cmd == TUNSETIFF && !tun) {
564*1da177e4SLinus Torvalds 		int err;
565*1da177e4SLinus Torvalds 
566*1da177e4SLinus Torvalds 		ifr.ifr_name[IFNAMSIZ-1] = '\0';
567*1da177e4SLinus Torvalds 
568*1da177e4SLinus Torvalds 		rtnl_lock();
569*1da177e4SLinus Torvalds 		err = tun_set_iff(file, &ifr);
570*1da177e4SLinus Torvalds 		rtnl_unlock();
571*1da177e4SLinus Torvalds 
572*1da177e4SLinus Torvalds 		if (err)
573*1da177e4SLinus Torvalds 			return err;
574*1da177e4SLinus Torvalds 
575*1da177e4SLinus Torvalds 		if (copy_to_user(argp, &ifr, sizeof(ifr)))
576*1da177e4SLinus Torvalds 			return -EFAULT;
577*1da177e4SLinus Torvalds 		return 0;
578*1da177e4SLinus Torvalds 	}
579*1da177e4SLinus Torvalds 
580*1da177e4SLinus Torvalds 	if (!tun)
581*1da177e4SLinus Torvalds 		return -EBADFD;
582*1da177e4SLinus Torvalds 
583*1da177e4SLinus Torvalds 	DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd);
584*1da177e4SLinus Torvalds 
585*1da177e4SLinus Torvalds 	switch (cmd) {
586*1da177e4SLinus Torvalds 	case TUNSETNOCSUM:
587*1da177e4SLinus Torvalds 		/* Disable/Enable checksum */
588*1da177e4SLinus Torvalds 		if (arg)
589*1da177e4SLinus Torvalds 			tun->flags |= TUN_NOCHECKSUM;
590*1da177e4SLinus Torvalds 		else
591*1da177e4SLinus Torvalds 			tun->flags &= ~TUN_NOCHECKSUM;
592*1da177e4SLinus Torvalds 
593*1da177e4SLinus Torvalds 		DBG(KERN_INFO "%s: checksum %s\n",
594*1da177e4SLinus Torvalds 		    tun->dev->name, arg ? "disabled" : "enabled");
595*1da177e4SLinus Torvalds 		break;
596*1da177e4SLinus Torvalds 
597*1da177e4SLinus Torvalds 	case TUNSETPERSIST:
598*1da177e4SLinus Torvalds 		/* Disable/Enable persist mode */
599*1da177e4SLinus Torvalds 		if (arg)
600*1da177e4SLinus Torvalds 			tun->flags |= TUN_PERSIST;
601*1da177e4SLinus Torvalds 		else
602*1da177e4SLinus Torvalds 			tun->flags &= ~TUN_PERSIST;
603*1da177e4SLinus Torvalds 
604*1da177e4SLinus Torvalds 		DBG(KERN_INFO "%s: persist %s\n",
605*1da177e4SLinus Torvalds 		    tun->dev->name, arg ? "disabled" : "enabled");
606*1da177e4SLinus Torvalds 		break;
607*1da177e4SLinus Torvalds 
608*1da177e4SLinus Torvalds 	case TUNSETOWNER:
609*1da177e4SLinus Torvalds 		/* Set owner of the device */
610*1da177e4SLinus Torvalds 		tun->owner = (uid_t) arg;
611*1da177e4SLinus Torvalds 
612*1da177e4SLinus Torvalds 		DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner);
613*1da177e4SLinus Torvalds 		break;
614*1da177e4SLinus Torvalds 
615*1da177e4SLinus Torvalds #ifdef TUN_DEBUG
616*1da177e4SLinus Torvalds 	case TUNSETDEBUG:
617*1da177e4SLinus Torvalds 		tun->debug = arg;
618*1da177e4SLinus Torvalds 		break;
619*1da177e4SLinus Torvalds #endif
620*1da177e4SLinus Torvalds 
621*1da177e4SLinus Torvalds 	case SIOCGIFFLAGS:
622*1da177e4SLinus Torvalds 		ifr.ifr_flags = tun->if_flags;
623*1da177e4SLinus Torvalds 		if (copy_to_user( argp, &ifr, sizeof ifr))
624*1da177e4SLinus Torvalds 			return -EFAULT;
625*1da177e4SLinus Torvalds 		return 0;
626*1da177e4SLinus Torvalds 
627*1da177e4SLinus Torvalds 	case SIOCSIFFLAGS:
628*1da177e4SLinus Torvalds 		/** Set the character device's interface flags. Currently only
629*1da177e4SLinus Torvalds 		 * IFF_PROMISC and IFF_ALLMULTI are used. */
630*1da177e4SLinus Torvalds 		tun->if_flags = ifr.ifr_flags;
631*1da177e4SLinus Torvalds 		DBG(KERN_INFO "%s: interface flags 0x%lx\n",
632*1da177e4SLinus Torvalds 				tun->dev->name, tun->if_flags);
633*1da177e4SLinus Torvalds 		return 0;
634*1da177e4SLinus Torvalds 
635*1da177e4SLinus Torvalds 	case SIOCGIFHWADDR:
636*1da177e4SLinus Torvalds 		memcpy(ifr.ifr_hwaddr.sa_data, tun->dev_addr,
637*1da177e4SLinus Torvalds 				min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr));
638*1da177e4SLinus Torvalds 		if (copy_to_user( argp, &ifr, sizeof ifr))
639*1da177e4SLinus Torvalds 			return -EFAULT;
640*1da177e4SLinus Torvalds 		return 0;
641*1da177e4SLinus Torvalds 
642*1da177e4SLinus Torvalds 	case SIOCSIFHWADDR:
643*1da177e4SLinus Torvalds 		/** Set the character device's hardware address. This is used when
644*1da177e4SLinus Torvalds 		 * filtering packets being sent from the network device to the character
645*1da177e4SLinus Torvalds 		 * device. */
646*1da177e4SLinus Torvalds 		memcpy(tun->dev_addr, ifr.ifr_hwaddr.sa_data,
647*1da177e4SLinus Torvalds 				min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr));
648*1da177e4SLinus Torvalds 		DBG(KERN_DEBUG "%s: set hardware address: %x:%x:%x:%x:%x:%x\n",
649*1da177e4SLinus Torvalds 				tun->dev->name,
650*1da177e4SLinus Torvalds 				tun->dev_addr[0], tun->dev_addr[1], tun->dev_addr[2],
651*1da177e4SLinus Torvalds 				tun->dev_addr[3], tun->dev_addr[4], tun->dev_addr[5]);
652*1da177e4SLinus Torvalds 		return 0;
653*1da177e4SLinus Torvalds 
654*1da177e4SLinus Torvalds 	case SIOCADDMULTI:
655*1da177e4SLinus Torvalds 		/** Add the specified group to the character device's multicast filter
656*1da177e4SLinus Torvalds 		 * list. */
657*1da177e4SLinus Torvalds 		add_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
658*1da177e4SLinus Torvalds 		DBG(KERN_DEBUG "%s: add multi: %x:%x:%x:%x:%x:%x\n",
659*1da177e4SLinus Torvalds 				tun->dev->name,
660*1da177e4SLinus Torvalds 				(u8)ifr.ifr_hwaddr.sa_data[0], (u8)ifr.ifr_hwaddr.sa_data[1],
661*1da177e4SLinus Torvalds 				(u8)ifr.ifr_hwaddr.sa_data[2], (u8)ifr.ifr_hwaddr.sa_data[3],
662*1da177e4SLinus Torvalds 				(u8)ifr.ifr_hwaddr.sa_data[4], (u8)ifr.ifr_hwaddr.sa_data[5]);
663*1da177e4SLinus Torvalds 		return 0;
664*1da177e4SLinus Torvalds 
665*1da177e4SLinus Torvalds 	case SIOCDELMULTI:
666*1da177e4SLinus Torvalds 		/** Remove the specified group from the character device's multicast
667*1da177e4SLinus Torvalds 		 * filter list. */
668*1da177e4SLinus Torvalds 		del_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
669*1da177e4SLinus Torvalds 		DBG(KERN_DEBUG "%s: del multi: %x:%x:%x:%x:%x:%x\n",
670*1da177e4SLinus Torvalds 				tun->dev->name,
671*1da177e4SLinus Torvalds 				(u8)ifr.ifr_hwaddr.sa_data[0], (u8)ifr.ifr_hwaddr.sa_data[1],
672*1da177e4SLinus Torvalds 				(u8)ifr.ifr_hwaddr.sa_data[2], (u8)ifr.ifr_hwaddr.sa_data[3],
673*1da177e4SLinus Torvalds 				(u8)ifr.ifr_hwaddr.sa_data[4], (u8)ifr.ifr_hwaddr.sa_data[5]);
674*1da177e4SLinus Torvalds 		return 0;
675*1da177e4SLinus Torvalds 
676*1da177e4SLinus Torvalds 	default:
677*1da177e4SLinus Torvalds 		return -EINVAL;
678*1da177e4SLinus Torvalds 	};
679*1da177e4SLinus Torvalds 
680*1da177e4SLinus Torvalds 	return 0;
681*1da177e4SLinus Torvalds }
682*1da177e4SLinus Torvalds 
683*1da177e4SLinus Torvalds static int tun_chr_fasync(int fd, struct file *file, int on)
684*1da177e4SLinus Torvalds {
685*1da177e4SLinus Torvalds 	struct tun_struct *tun = file->private_data;
686*1da177e4SLinus Torvalds 	int ret;
687*1da177e4SLinus Torvalds 
688*1da177e4SLinus Torvalds 	if (!tun)
689*1da177e4SLinus Torvalds 		return -EBADFD;
690*1da177e4SLinus Torvalds 
691*1da177e4SLinus Torvalds 	DBG(KERN_INFO "%s: tun_chr_fasync %d\n", tun->dev->name, on);
692*1da177e4SLinus Torvalds 
693*1da177e4SLinus Torvalds 	if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0)
694*1da177e4SLinus Torvalds 		return ret;
695*1da177e4SLinus Torvalds 
696*1da177e4SLinus Torvalds 	if (on) {
697*1da177e4SLinus Torvalds 		ret = f_setown(file, current->pid, 0);
698*1da177e4SLinus Torvalds 		if (ret)
699*1da177e4SLinus Torvalds 			return ret;
700*1da177e4SLinus Torvalds 		tun->flags |= TUN_FASYNC;
701*1da177e4SLinus Torvalds 	} else
702*1da177e4SLinus Torvalds 		tun->flags &= ~TUN_FASYNC;
703*1da177e4SLinus Torvalds 
704*1da177e4SLinus Torvalds 	return 0;
705*1da177e4SLinus Torvalds }
706*1da177e4SLinus Torvalds 
707*1da177e4SLinus Torvalds static int tun_chr_open(struct inode *inode, struct file * file)
708*1da177e4SLinus Torvalds {
709*1da177e4SLinus Torvalds 	DBG1(KERN_INFO "tunX: tun_chr_open\n");
710*1da177e4SLinus Torvalds 	file->private_data = NULL;
711*1da177e4SLinus Torvalds 	return 0;
712*1da177e4SLinus Torvalds }
713*1da177e4SLinus Torvalds 
714*1da177e4SLinus Torvalds static int tun_chr_close(struct inode *inode, struct file *file)
715*1da177e4SLinus Torvalds {
716*1da177e4SLinus Torvalds 	struct tun_struct *tun = file->private_data;
717*1da177e4SLinus Torvalds 
718*1da177e4SLinus Torvalds 	if (!tun)
719*1da177e4SLinus Torvalds 		return 0;
720*1da177e4SLinus Torvalds 
721*1da177e4SLinus Torvalds 	DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name);
722*1da177e4SLinus Torvalds 
723*1da177e4SLinus Torvalds 	tun_chr_fasync(-1, file, 0);
724*1da177e4SLinus Torvalds 
725*1da177e4SLinus Torvalds 	rtnl_lock();
726*1da177e4SLinus Torvalds 
727*1da177e4SLinus Torvalds 	/* Detach from net device */
728*1da177e4SLinus Torvalds 	file->private_data = NULL;
729*1da177e4SLinus Torvalds 	tun->attached = 0;
730*1da177e4SLinus Torvalds 
731*1da177e4SLinus Torvalds 	/* Drop read queue */
732*1da177e4SLinus Torvalds 	skb_queue_purge(&tun->readq);
733*1da177e4SLinus Torvalds 
734*1da177e4SLinus Torvalds 	if (!(tun->flags & TUN_PERSIST)) {
735*1da177e4SLinus Torvalds 		list_del(&tun->list);
736*1da177e4SLinus Torvalds 		unregister_netdevice(tun->dev);
737*1da177e4SLinus Torvalds 	}
738*1da177e4SLinus Torvalds 
739*1da177e4SLinus Torvalds 	rtnl_unlock();
740*1da177e4SLinus Torvalds 
741*1da177e4SLinus Torvalds 	return 0;
742*1da177e4SLinus Torvalds }
743*1da177e4SLinus Torvalds 
744*1da177e4SLinus Torvalds static struct file_operations tun_fops = {
745*1da177e4SLinus Torvalds 	.owner	= THIS_MODULE,
746*1da177e4SLinus Torvalds 	.llseek = no_llseek,
747*1da177e4SLinus Torvalds 	.read	= tun_chr_read,
748*1da177e4SLinus Torvalds 	.readv	= tun_chr_readv,
749*1da177e4SLinus Torvalds 	.write	= tun_chr_write,
750*1da177e4SLinus Torvalds 	.writev = tun_chr_writev,
751*1da177e4SLinus Torvalds 	.poll	= tun_chr_poll,
752*1da177e4SLinus Torvalds 	.ioctl	= tun_chr_ioctl,
753*1da177e4SLinus Torvalds 	.open	= tun_chr_open,
754*1da177e4SLinus Torvalds 	.release = tun_chr_close,
755*1da177e4SLinus Torvalds 	.fasync = tun_chr_fasync
756*1da177e4SLinus Torvalds };
757*1da177e4SLinus Torvalds 
758*1da177e4SLinus Torvalds static struct miscdevice tun_miscdev = {
759*1da177e4SLinus Torvalds 	.minor = TUN_MINOR,
760*1da177e4SLinus Torvalds 	.name = "tun",
761*1da177e4SLinus Torvalds 	.fops = &tun_fops,
762*1da177e4SLinus Torvalds 	.devfs_name = "net/tun",
763*1da177e4SLinus Torvalds };
764*1da177e4SLinus Torvalds 
765*1da177e4SLinus Torvalds /* ethtool interface */
766*1da177e4SLinus Torvalds 
767*1da177e4SLinus Torvalds static int tun_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
768*1da177e4SLinus Torvalds {
769*1da177e4SLinus Torvalds 	cmd->supported		= 0;
770*1da177e4SLinus Torvalds 	cmd->advertising	= 0;
771*1da177e4SLinus Torvalds 	cmd->speed		= SPEED_10;
772*1da177e4SLinus Torvalds 	cmd->duplex		= DUPLEX_FULL;
773*1da177e4SLinus Torvalds 	cmd->port		= PORT_TP;
774*1da177e4SLinus Torvalds 	cmd->phy_address	= 0;
775*1da177e4SLinus Torvalds 	cmd->transceiver	= XCVR_INTERNAL;
776*1da177e4SLinus Torvalds 	cmd->autoneg		= AUTONEG_DISABLE;
777*1da177e4SLinus Torvalds 	cmd->maxtxpkt		= 0;
778*1da177e4SLinus Torvalds 	cmd->maxrxpkt		= 0;
779*1da177e4SLinus Torvalds 	return 0;
780*1da177e4SLinus Torvalds }
781*1da177e4SLinus Torvalds 
782*1da177e4SLinus Torvalds static void tun_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
783*1da177e4SLinus Torvalds {
784*1da177e4SLinus Torvalds 	struct tun_struct *tun = netdev_priv(dev);
785*1da177e4SLinus Torvalds 
786*1da177e4SLinus Torvalds 	strcpy(info->driver, DRV_NAME);
787*1da177e4SLinus Torvalds 	strcpy(info->version, DRV_VERSION);
788*1da177e4SLinus Torvalds 	strcpy(info->fw_version, "N/A");
789*1da177e4SLinus Torvalds 
790*1da177e4SLinus Torvalds 	switch (tun->flags & TUN_TYPE_MASK) {
791*1da177e4SLinus Torvalds 	case TUN_TUN_DEV:
792*1da177e4SLinus Torvalds 		strcpy(info->bus_info, "tun");
793*1da177e4SLinus Torvalds 		break;
794*1da177e4SLinus Torvalds 	case TUN_TAP_DEV:
795*1da177e4SLinus Torvalds 		strcpy(info->bus_info, "tap");
796*1da177e4SLinus Torvalds 		break;
797*1da177e4SLinus Torvalds 	}
798*1da177e4SLinus Torvalds }
799*1da177e4SLinus Torvalds 
800*1da177e4SLinus Torvalds static u32 tun_get_msglevel(struct net_device *dev)
801*1da177e4SLinus Torvalds {
802*1da177e4SLinus Torvalds #ifdef TUN_DEBUG
803*1da177e4SLinus Torvalds 	struct tun_struct *tun = netdev_priv(dev);
804*1da177e4SLinus Torvalds 	return tun->debug;
805*1da177e4SLinus Torvalds #else
806*1da177e4SLinus Torvalds 	return -EOPNOTSUPP;
807*1da177e4SLinus Torvalds #endif
808*1da177e4SLinus Torvalds }
809*1da177e4SLinus Torvalds 
810*1da177e4SLinus Torvalds static void tun_set_msglevel(struct net_device *dev, u32 value)
811*1da177e4SLinus Torvalds {
812*1da177e4SLinus Torvalds #ifdef TUN_DEBUG
813*1da177e4SLinus Torvalds 	struct tun_struct *tun = netdev_priv(dev);
814*1da177e4SLinus Torvalds 	tun->debug = value;
815*1da177e4SLinus Torvalds #endif
816*1da177e4SLinus Torvalds }
817*1da177e4SLinus Torvalds 
818*1da177e4SLinus Torvalds static u32 tun_get_link(struct net_device *dev)
819*1da177e4SLinus Torvalds {
820*1da177e4SLinus Torvalds 	struct tun_struct *tun = netdev_priv(dev);
821*1da177e4SLinus Torvalds 	return tun->attached;
822*1da177e4SLinus Torvalds }
823*1da177e4SLinus Torvalds 
824*1da177e4SLinus Torvalds static u32 tun_get_rx_csum(struct net_device *dev)
825*1da177e4SLinus Torvalds {
826*1da177e4SLinus Torvalds 	struct tun_struct *tun = netdev_priv(dev);
827*1da177e4SLinus Torvalds 	return (tun->flags & TUN_NOCHECKSUM) == 0;
828*1da177e4SLinus Torvalds }
829*1da177e4SLinus Torvalds 
830*1da177e4SLinus Torvalds static int tun_set_rx_csum(struct net_device *dev, u32 data)
831*1da177e4SLinus Torvalds {
832*1da177e4SLinus Torvalds 	struct tun_struct *tun = netdev_priv(dev);
833*1da177e4SLinus Torvalds 	if (data)
834*1da177e4SLinus Torvalds 		tun->flags &= ~TUN_NOCHECKSUM;
835*1da177e4SLinus Torvalds 	else
836*1da177e4SLinus Torvalds 		tun->flags |= TUN_NOCHECKSUM;
837*1da177e4SLinus Torvalds 	return 0;
838*1da177e4SLinus Torvalds }
839*1da177e4SLinus Torvalds 
840*1da177e4SLinus Torvalds static struct ethtool_ops tun_ethtool_ops = {
841*1da177e4SLinus Torvalds 	.get_settings	= tun_get_settings,
842*1da177e4SLinus Torvalds 	.get_drvinfo	= tun_get_drvinfo,
843*1da177e4SLinus Torvalds 	.get_msglevel	= tun_get_msglevel,
844*1da177e4SLinus Torvalds 	.set_msglevel	= tun_set_msglevel,
845*1da177e4SLinus Torvalds 	.get_link	= tun_get_link,
846*1da177e4SLinus Torvalds 	.get_rx_csum	= tun_get_rx_csum,
847*1da177e4SLinus Torvalds 	.set_rx_csum	= tun_set_rx_csum
848*1da177e4SLinus Torvalds };
849*1da177e4SLinus Torvalds 
850*1da177e4SLinus Torvalds static int __init tun_init(void)
851*1da177e4SLinus Torvalds {
852*1da177e4SLinus Torvalds 	int ret = 0;
853*1da177e4SLinus Torvalds 
854*1da177e4SLinus Torvalds 	printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
855*1da177e4SLinus Torvalds 	printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
856*1da177e4SLinus Torvalds 
857*1da177e4SLinus Torvalds 	ret = misc_register(&tun_miscdev);
858*1da177e4SLinus Torvalds 	if (ret)
859*1da177e4SLinus Torvalds 		printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR);
860*1da177e4SLinus Torvalds 	return ret;
861*1da177e4SLinus Torvalds }
862*1da177e4SLinus Torvalds 
863*1da177e4SLinus Torvalds static void tun_cleanup(void)
864*1da177e4SLinus Torvalds {
865*1da177e4SLinus Torvalds 	struct tun_struct *tun, *nxt;
866*1da177e4SLinus Torvalds 
867*1da177e4SLinus Torvalds 	misc_deregister(&tun_miscdev);
868*1da177e4SLinus Torvalds 
869*1da177e4SLinus Torvalds 	rtnl_lock();
870*1da177e4SLinus Torvalds 	list_for_each_entry_safe(tun, nxt, &tun_dev_list, list) {
871*1da177e4SLinus Torvalds 		DBG(KERN_INFO "%s cleaned up\n", tun->dev->name);
872*1da177e4SLinus Torvalds 		unregister_netdevice(tun->dev);
873*1da177e4SLinus Torvalds 	}
874*1da177e4SLinus Torvalds 	rtnl_unlock();
875*1da177e4SLinus Torvalds 
876*1da177e4SLinus Torvalds }
877*1da177e4SLinus Torvalds 
878*1da177e4SLinus Torvalds module_init(tun_init);
879*1da177e4SLinus Torvalds module_exit(tun_cleanup);
880*1da177e4SLinus Torvalds MODULE_DESCRIPTION(DRV_DESCRIPTION);
881*1da177e4SLinus Torvalds MODULE_AUTHOR(DRV_COPYRIGHT);
882*1da177e4SLinus Torvalds MODULE_LICENSE("GPL");
883*1da177e4SLinus Torvalds MODULE_ALIAS_MISCDEV(TUN_MINOR);
884