1695 lines · 38.4 KB · C
RawDownload
/* *  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: * *  Mike Kershaw <dragorn@kismetwireless.net> 2005/08/14 *    Add TUNSETLINK ioctl to set the link encapsulation * *  Mark Smith <markzzzsmith@yahoo.com.au> *    Use random_ether_addr() for tap MAC address. * *  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. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #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>" #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>#include <linux/compat.h>#include <linux/if.h>#include <linux/if_arp.h>#include <linux/if_ether.h>#include <linux/if_tun.h>#include <linux/crc32.h>#include <linux/nsproxy.h>#include <linux/virtio_net.h>#include <linux/rcupdate.h>#include <net/net_namespace.h>#include <net/netns/generic.h>#include <net/rtnetlink.h>#include <net/sock.h> #include <asm/uaccess.h> /* Uncomment to enable debugging *//* #define TUN_DEBUG 1 */ #ifdef TUN_DEBUGstatic int debug; #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)#else#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)#endif #define FLT_EXACT_COUNT 8struct 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];}; struct tun_file {	atomic_t count;	struct tun_struct *tun;	struct net *net;}; struct tun_sock; struct tun_struct {	struct tun_file		*tfile;	unsigned int 		flags;	uid_t			owner;	gid_t			group; 	struct net_device	*dev;	netdev_features_t	set_features;#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \			  NETIF_F_TSO6|NETIF_F_UFO)	struct fasync_struct	*fasync; 	struct tap_filter       txflt;	struct socket		socket;	struct socket_wq	wq; 	int			vnet_hdr_sz; #ifdef TUN_DEBUG	int debug;#endif}; 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);} static int tun_attach(struct tun_struct *tun, struct file *file){	struct tun_file *tfile = file->private_data;	int err; 	ASSERT_RTNL(); 	netif_tx_lock_bh(tun->dev); 	err = -EINVAL;	if (tfile->tun)		goto out; 	err = -EBUSY;	if (tun->tfile)		goto out; 	err = 0;	tfile->tun = tun;	tun->tfile = tfile;	tun->socket.file = file;	netif_carrier_on(tun->dev);	dev_hold(tun->dev);	sock_hold(tun->socket.sk);	atomic_inc(&tfile->count); out:	netif_tx_unlock_bh(tun->dev);	return err;} static void __tun_detach(struct tun_struct *tun){	/* Detach from net device */	netif_tx_lock_bh(tun->dev);	netif_carrier_off(tun->dev);	tun->tfile = NULL;	tun->socket.file = NULL;	netif_tx_unlock_bh(tun->dev); 	/* Drop read queue */	skb_queue_purge(&tun->socket.sk->sk_receive_queue); 	/* 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();} static struct tun_struct *__tun_get(struct tun_file *tfile){	struct tun_struct *tun = NULL; 	if (atomic_inc_not_zero(&tfile->count))		tun = tfile->tun; 	return tun;} static struct tun_struct *tun_get(struct file *file){	return __tun_get(file->private_data);} static void tun_put(struct tun_struct *tun){	struct tun_file *tfile = tun->tfile; 	if (atomic_dec_and_test(&tfile->count))		tun_detach(tfile->tun);} /* TAP filtering */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; 	/* Remaining multicast addresses are hashed,	 * unicast will leave the filter disabled. */	memset(filter->mask, 0, sizeof(filter->mask));	for (; n < uf.count; n++) {		if (!is_multicast_ether_addr(addr[n].u)) {			err = 0; /* no filter */			goto done;		}		addr_hash_set(filter->mask, addr[n].u);	} 	/* 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 (ether_addr_equal(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);} /* Network device part of the driver */ static const struct ethtool_ops tun_ethtool_ops; /* 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) {		wake_up_all(&tun->wq.wait);		if (atomic_dec_and_test(&tfile->count))			__tun_detach(tun);	}} static void tun_free_netdev(struct net_device *dev){	struct tun_struct *tun = netdev_priv(dev); 	sk_release_kernel(tun->socket.sk);} /* 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 */static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev){	struct tun_struct *tun = netdev_priv(dev); 	tun_debug(KERN_INFO, tun, "tun_net_xmit %d\n", skb->len); 	/* Drop packet if interface is not attached */	if (!tun->tfile)		goto drop; 	/* 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; 	if (tun->socket.sk->sk_filter &&	    sk_filter(tun->socket.sk, skb))		goto drop; 	if (skb_queue_len(&tun->socket.sk->sk_receive_queue) >= dev->tx_queue_len) {		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. */			dev->stats.tx_fifo_errors++;		} else {			/* Single queue mode.			 * Driver handles dropping of all packets itself. */			goto drop;		}	} 	/* Orphan the skb - required as we might hang on to it	 * for indefinite time. */	skb_orphan(skb); 	/* Enqueue packet */	skb_queue_tail(&tun->socket.sk->sk_receive_queue, skb); 	/* Notify and wake up reader process */	if (tun->flags & TUN_FASYNC)		kill_fasync(&tun->fasync, SIGIO, POLL_IN);	wake_up_interruptible_poll(&tun->wq.wait, POLLIN |				   POLLRDNORM | POLLRDBAND);	return NETDEV_TX_OK; drop:	dev->stats.tx_dropped++;	kfree_skb(skb);	return NETDEV_TX_OK;} static void tun_net_mclist(struct net_device *dev){	/*	 * 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.	 */} #define MIN_MTU 68#define MAX_MTU 65535 static inttun_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;} static netdev_features_t tun_net_fix_features(struct net_device *dev,	netdev_features_t features){	struct tun_struct *tun = netdev_priv(dev); 	return (features & tun->set_features) | (features & ~TUN_USER_FEATURES);}#ifdef CONFIG_NET_POLL_CONTROLLERstatic 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;}#endifstatic const struct net_device_ops tun_netdev_ops = {	.ndo_uninit		= tun_net_uninit,	.ndo_open		= tun_net_open,	.ndo_stop		= tun_net_close,	.ndo_start_xmit		= tun_net_xmit,	.ndo_change_mtu		= tun_net_change_mtu,	.ndo_fix_features	= tun_net_fix_features,#ifdef CONFIG_NET_POLL_CONTROLLER	.ndo_poll_controller	= tun_poll_controller,#endif}; static const struct net_device_ops tap_netdev_ops = {	.ndo_uninit		= tun_net_uninit,	.ndo_open		= tun_net_open,	.ndo_stop		= tun_net_close,	.ndo_start_xmit		= tun_net_xmit,	.ndo_change_mtu		= tun_net_change_mtu,	.ndo_fix_features	= tun_net_fix_features,	.ndo_set_rx_mode	= tun_net_mclist,	.ndo_set_mac_address	= eth_mac_addr,

Lines 1–500 of 1695.