1 diff -Nurb linux-2.6.22-525/drivers/net/Makefile linux-2.6.22-526/drivers/net/Makefile
2 --- linux-2.6.22-525/drivers/net/Makefile 2008-07-13 23:58:01.000000000 -0400
3 +++ linux-2.6.22-526/drivers/net/Makefile 2008-07-13 23:58:45.000000000 -0400
6 # Makefile for the Linux network (ethercard) device drivers.
10 obj-$(CONFIG_E1000) += e1000/
11 obj-$(CONFIG_E1000E) += e1000e/
12 obj-$(CONFIG_IBM_EMAC) += ibm_emac/
13 diff -Nurb linux-2.6.22-525/drivers/net/vnet_tun.c linux-2.6.22-526/drivers/net/vnet_tun.c
14 --- linux-2.6.22-525/drivers/net/vnet_tun.c 1969-12-31 19:00:00.000000000 -0500
15 +++ linux-2.6.22-526/drivers/net/vnet_tun.c 2008-07-14 16:22:57.000000000 -0400
18 + * TUN - Universal TUN/TAP device driver.
19 + * Copyright (C) 1999-2002 Maxim Krasnyansky <maxk@qualcomm.com>
20 + * Modifications for PlanetLab by
21 + * Mark Huang <mlhuang@cs.princeton.edu>
22 + * Copyright (C) 2005 The Trustees of Princeton University
23 + * Ported to PlanetLab 4.2 by Sapan Bhatia <sapanb@cs.princeton.edu>
25 + * Modifications for PlanetLab by
26 + * Mark Huang <mlhuang@cs.princeton.edu>
27 + * Copyright (C) 2005 The Trustees of Princeton University
29 + * This program is free software; you can redistribute it and/or modify
30 + * it under the terms of the GNU General Public License as published by
31 + * the Free Software Foundation; either version 2 of the License, or
32 + * (at your option) any later version.
34 + * This program is distributed in the hope that it will be useful,
35 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 + * GNU General Public License for more details.
39 + * $Id: vnet_tun.c,v 1.10 2007/03/07 21:25:26 mef Exp $
43 + * Daniel Podlejski <underley@underley.eu.org>
44 + * Modifications for 2.3.99-pre5 kernel.
47 +#define TUN_VER "1.5"
51 +#define dbg(format, args...) do { if (vnet_verbose >= 2) { printk(format, ## args); } } while (0)
52 +#define err(format, args...) do { if (vnet_verbose >= 1) { printk(format, ## args); } } while (0)
54 +#include <linux/version.h>
55 +#include <linux/module.h>
56 +#include <linux/errno.h>
57 +#include <linux/kernel.h>
58 +#include <linux/major.h>
59 +#include <linux/slab.h>
60 +#include <linux/poll.h>
61 +#include <linux/fcntl.h>
62 +#include <linux/init.h>
63 +#include <linux/random.h>
64 +#include <linux/skbuff.h>
65 +#include <linux/netdevice.h>
66 +#include <linux/etherdevice.h>
67 +#include <linux/miscdevice.h>
68 +#include <linux/rtnetlink.h>
69 +#include <linux/if.h>
70 +#include <linux/if_arp.h>
71 +#include <linux/if_ether.h>
72 +#include <linux/if_tun.h>
73 +#include <net/sock.h>
75 +#include <asm/system.h>
76 +#include <asm/uaccess.h>
79 + * PlanetLab TAP device
81 + * A single, persistent tap0 to /dev/net/tun tunnel. Packets sent out
82 + * the tap0 device, via either IP or raw sockets, are queued to both
83 + * the sending slice's /dev/net/tun queue, and the root queue. Only
84 + * one reader of each queue is allowed at a time. Any type of packet
85 + * may be written to /dev/net/tun and received via packet socket(s)
86 + * bound to tap0. However, only locally destined IP packets will be
87 + * injected into the stack, and such packets are subject to the same
88 + * connection tracking and ownership assignment that all inbound IP
89 + * packets are subject to.
92 +struct net_device tun_netdev;
93 +static struct net_device_stats tun_stats;
98 +get_sk_xid(struct sock *sk)
101 + return (int) sk->sk_nid >= 0 ? sk->sk_nid : 0;
104 + if (in_interrupt() && print_once) {
106 + printk(KERN_EMERG "vnet_tun: get-sk_xid called in interrupt context! Stephen: Don't Panic.\n");
108 + return current->xid;
112 +#define set_sk_xid(sk,xid) sk->sk_nid=xid
113 +#define set_skb_xid(skb,xid) skb->skb_tag=xid
114 +#define get_skb_xid(skb) skb->skb_tag
116 +/* Extended fields */
118 + unsigned long mark;
119 + long timestamp_sec;
120 + long timestamp_usec;
122 +#define TUN_PKT_EXT 0x0002
126 +/* UID hash function stolen from kernel/user.c */
127 +#define XIDHASH_BITS 8
128 +#define XIDHASH_SZ (1 << XIDHASH_BITS)
129 +#define XIDHASH_MASK (XIDHASH_SZ - 1)
130 +#define __xidhashfn(xid) (((xid >> XIDHASH_BITS) + xid) & XIDHASH_MASK)
132 +static struct list_head tun_dev_hash[XIDHASH_SZ];
133 +static rwlock_t tun_dev_hash_lock = RW_LOCK_UNLOCKED;
136 +get_file_xid(struct file *file)
138 + return file->f_xid;
142 +set_file_xid(struct file *file, xid_t xid)
147 +static struct tun_struct *tun_get_by_xid(xid_t xid)
149 + struct tun_struct *tun;
151 + read_lock_bh(&tun_dev_hash_lock);
153 + list_for_each_entry(tun, &tun_dev_hash[__xidhashfn(xid)], list) {
154 + if (tun->owner == xid) {
155 + read_unlock_bh(&tun_dev_hash_lock);
160 + read_unlock_bh(&tun_dev_hash_lock);
165 +/* Network device part of the driver */
167 +static void tun_xmit(struct sk_buff *skb, struct tun_struct *tun)
169 + /* Drop packet if interface is not attached */
170 + if (!tun || !tun->attached)
173 + dbg("%s:%d: tun_xmit %d\n", tun->dev->name, tun->owner, skb->len);
176 + if (skb_queue_len(&tun->readq) >= tun->dev->tx_queue_len)
179 + skb = skb_clone(skb, GFP_ATOMIC);
183 + skb_queue_tail(&tun->readq, skb);
185 + /* Notify and wake up reader process */
186 + if (tun->flags & TUN_FASYNC)
187 + kill_fasync(&tun->fasync, SIGIO, POLL_IN);
188 + wake_up_interruptible(&tun->read_wait);
192 + tun->stats.tx_dropped++;
193 + tun_stats.tx_dropped++;
196 +/* Net device start xmit */
197 +static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
199 + xid_t xid, skb_xid;
200 + struct tun_struct *tun;
201 + skb_xid=get_skb_xid(skb);
203 + xid=get_sk_xid(skb->sk);
207 + tun = tun_get_by_xid(xid);
209 + set_skb_xid(skb, xid);
211 + tun_xmit(skb, tun);
213 + /* Copy root on packets that the slice is not listening for */
214 + if ((!tun || !tun->attached) && xid) {
215 + tun = tun_get_by_xid(0);
216 + tun_xmit(skb, tun);
223 +static void tun_net_mclist(struct net_device *dev)
225 + /* Nothing to do for multicast filters.
226 + * We always accept all frames. */
230 +static struct net_device_stats *tun_net_stats(struct net_device *dev)
232 + struct tun_struct *tun = tun_get_by_xid(current->xid);
233 + return tun ? &tun->stats : &tun_stats;
236 +/* Character device part */
239 +static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
241 + struct tun_struct *tun = file->private_data;
242 + unsigned int mask = POLLOUT | POLLWRNORM;
247 + dbg("%s:%d: tun_chr_poll\n", tun->dev->name, tun->owner);
249 + poll_wait(file, &tun->read_wait, wait);
251 + if (skb_queue_len(&tun->readq))
252 + mask |= POLLIN | POLLRDNORM;
257 +/* Get packet from user space buffer */
258 +static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, size_t count)
260 + struct tun_pi pi = { 0, __constant_htons(ETH_P_IP) };
261 + struct tun_pi_ext pi_ext;
262 + struct sk_buff *skb;
263 + size_t len = count;
265 + if (!(tun->flags & TUN_NO_PI)) {
266 + if ((len -= sizeof(pi)) < 0)
269 + if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi)))
272 + if (pi.flags & TUN_PKT_EXT) {
273 + if ((len -= sizeof(pi_ext)) < 0)
276 + if (memcpy_fromiovec((void *)&pi_ext, iv, sizeof(pi_ext)))
281 + if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {
282 + tun->stats.rx_dropped++;
283 + tun_stats.rx_dropped++;
287 + skb_reserve(skb, 2);
288 + if (memcpy_fromiovec(skb_put(skb, len), iv, len))
291 + skb->dev = tun->dev;
292 + switch (tun->flags & TUN_TYPE_MASK) {
294 + skb_reset_mac_header(skb);
295 + skb->protocol = pi.proto;
298 + skb->protocol = eth_type_trans(skb, tun->dev);
302 + if (tun->flags & TUN_NOCHECKSUM)
303 + skb->ip_summed = CHECKSUM_UNNECESSARY;
306 + set_skb_xid(skb, tun->owner);
310 + tun->stats.rx_packets++;
311 + tun->stats.rx_bytes += len;
312 + tun_stats.rx_packets++;
313 + tun_stats.rx_bytes += len;
318 +static inline size_t iov_total(const struct iovec *iv, unsigned long count)
323 + for (i = 0, len = 0; i < count; i++)
324 + len += iv[i].iov_len;
329 +/* Writev - Obsolete in 2.6.22, but let's keep this aroudn just in case */
330 +static ssize_t tun_chr_writev(struct file * file, const struct iovec *iv,
331 + unsigned long count, loff_t *pos)
333 + struct tun_struct *tun = file->private_data;
338 + dbg("%s:%d: tun_chr_write %ld\n", tun->dev->name, tun->owner, count);
340 + return tun_get_user(tun, (struct iovec *) iv, iov_total(iv, count));
344 +static ssize_t tun_chr_write(struct file * file, const char __user * buf,
345 + size_t count, loff_t *pos)
347 + struct iovec iv = { (void __user *) buf, count };
348 + return tun_chr_writev(file, &iv, 1, pos);
351 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
353 +static inline void skb_get_timestamp(const struct sk_buff *skb, struct timeval *stamp)
355 + stamp->tv_sec = skb->stamp.tv_sec;
356 + stamp->tv_usec = skb->stamp.tv_usec;
359 +static inline void skb_set_timestamp(struct sk_buff *skb, const struct timeval *stamp)
361 + skb->stamp.tv_sec = stamp->tv_sec;
362 + skb->stamp.tv_usec = stamp->tv_usec;
365 +static void __net_timestamp(struct sk_buff *skb)
369 + do_gettimeofday(&tv);
370 + skb_set_timestamp(skb, &tv);
375 +/* Put packet to the user space buffer */
376 +static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
377 + struct sk_buff *skb,
378 + struct iovec *iv, int len)
381 + struct tun_pi_ext pi_ext;
382 + struct timeval stamp;
385 + if (!(tun->flags & TUN_NO_PI)) {
386 + struct iovec iv1 = { iv->iov_base, iv->iov_len };
388 + if ((len -= sizeof(pi)) < 0)
391 + if (memcpy_fromiovec((void *)&pi, &iv1, sizeof(pi)))
394 + if (pi.flags & TUN_PKT_EXT) {
395 + if ((len -= sizeof(pi_ext)) < 0)
398 + /* We might not have a timestamp, get one */
399 + skb_get_timestamp(skb, &stamp);
400 + if (stamp.tv_sec == 0) {
401 + __net_timestamp(skb);
402 + skb_get_timestamp(skb, &stamp);
405 + pi.flags = TUN_PKT_EXT;
406 + pi.proto = skb->protocol;
407 + pi_ext.timestamp_sec = stamp.tv_sec;
408 + pi_ext.timestamp_usec = stamp.tv_usec;
409 + pi_ext.mark = skb->skb_tag;
412 + pi.proto = skb->protocol;
415 + if (len < skb->len) {
416 + /* Packet will be striped */
417 + pi.flags |= TUN_PKT_STRIP;
420 + if (memcpy_toiovec(iv, (void *) &pi, sizeof(pi)))
422 + total += sizeof(pi);
424 + if (pi.flags & TUN_PKT_EXT) {
425 + if (memcpy_toiovec(iv, (void *) &pi_ext, sizeof(pi_ext)))
427 + total += sizeof(pi_ext);
431 + len = min_t(int, skb->len, len);
433 + skb_copy_datagram_iovec(skb, 0, iv, len);
436 + tun->stats.tx_packets++;
437 + tun->stats.tx_bytes += len;
438 + tun_stats.tx_packets++;
439 + tun_stats.tx_bytes += len;
444 +/* Readv - Obsolete in 2.6.22, but let's keep this aroudn just in case */
445 +static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv,
446 + unsigned long count, loff_t *pos)
448 + struct tun_struct *tun = file->private_data;
449 + DECLARE_WAITQUEUE(wait, current);
450 + struct sk_buff *skb;
451 + ssize_t len, ret = 0;
456 + dbg("%s:%d: tun_chr_read\n", tun->dev->name, tun->owner);
458 + len = iov_total(iv, count);
462 + add_wait_queue(&tun->read_wait, &wait);
464 + current->state = TASK_INTERRUPTIBLE;
466 + /* Read frames from the queue */
467 + if (!(skb=skb_dequeue(&tun->readq))) {
468 + if (file->f_flags & O_NONBLOCK) {
472 + if (signal_pending(current)) {
473 + ret = -ERESTARTSYS;
477 + /* Nothing to read, let's sleep */
482 + ret = tun_put_user(tun, skb, (struct iovec *) iv, len);
488 + current->state = TASK_RUNNING;
489 + remove_wait_queue(&tun->read_wait, &wait);
495 +static ssize_t tun_chr_read(struct file * file, char __user * buf,
496 + size_t count, loff_t *pos)
498 + struct iovec iv = { buf, count };
499 + return tun_chr_readv(file, &iv, 1, pos);
502 +static int tun_set_iff(struct file *file, struct ifreq *ifr)
504 + struct tun_struct *tun;
506 + tun = tun_get_by_xid(get_file_xid(file));
511 + /* Check permissions */
512 + if (tun->owner != -1 &&
513 + get_file_xid(file) != tun->owner && !capable(CAP_NET_ADMIN))
517 + /* Create a new queue */
518 + tun = kmalloc(sizeof(struct tun_struct), GFP_KERNEL);
521 + memset(tun, 0, sizeof(struct tun_struct));
523 + tun->dev = &tun_netdev;
525 + skb_queue_head_init(&tun->readq);
526 + init_waitqueue_head(&tun->read_wait);
528 + tun->owner = get_file_xid(file);
530 + write_lock_bh(&tun_dev_hash_lock);
531 + list_add(&tun->list, &tun_dev_hash[__xidhashfn(get_file_xid(file))]);
532 + write_unlock_bh(&tun_dev_hash_lock);
535 + dbg("%s:%d: tun_set_iff\n", tun->dev->name, tun->owner);
537 + tun->flags = TUN_TAP_DEV;
539 + if (ifr->ifr_flags & IFF_NO_PI)
540 + tun->flags |= TUN_NO_PI;
542 + file->private_data = tun;
545 + strcpy(ifr->ifr_name, tun->dev->name);
549 +static int tun_chr_ioctl(struct inode *inode, struct file *file,
550 + unsigned int cmd, unsigned long arg)
552 + struct tun_struct *tun = file->private_data;
554 + if (cmd == TUNSETIFF && !tun) {
558 + if (copy_from_user(&ifr, (void __user *)arg, sizeof(ifr)))
560 + ifr.ifr_name[IFNAMSIZ-1] = '\0';
562 + err = tun_set_iff(file, &ifr);
567 + if (copy_to_user((void __user *)arg, &ifr, sizeof(ifr)))
575 + dbg("%s:%d: tun_chr_ioctl cmd %d\n", tun->dev->name, tun->owner, cmd);
579 + /* Disable/Enable checksum */
581 + tun->flags |= TUN_NOCHECKSUM;
583 + tun->flags &= ~TUN_NOCHECKSUM;
585 + dbg("%s:%d: checksum %s\n",
586 + tun->dev->name, tun->owner, arg ? "disabled" : "enabled");
589 + case TUNSETPERSIST:
592 + /* Not applicable */
602 +static int tun_chr_fasync(int fd, struct file *file, int on)
604 + struct tun_struct *tun = file->private_data;
610 + dbg("%s:%d: tun_chr_fasync %d\n", tun->dev->name, tun->owner, on);
612 + if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0)
616 + ret = f_setown(file, current->pid, 0);
619 + tun->flags |= TUN_FASYNC;
621 + tun->flags &= ~TUN_FASYNC;
626 +static int tun_chr_open(struct inode *inode, struct file * file)
628 + dbg("tunX: tun_chr_open\n");
629 + file->private_data = NULL;
633 +static int tun_chr_close(struct inode *inode, struct file *file)
635 + struct tun_struct *tun = file->private_data;
640 + dbg("%s:%d: tun_chr_close\n", tun->dev->name, tun->owner);
642 + tun_chr_fasync(-1, file, 0);
644 + /* Detach from net device */
645 + file->private_data = NULL;
648 + /* Drop read queue */
649 + skb_queue_purge(&tun->readq);
654 +static struct file_operations tun_fops = {
655 + .owner = THIS_MODULE,
656 + .llseek = no_llseek,
657 + .read = tun_chr_read,
658 + //.readv = tun_chr_readv,
659 + .write = tun_chr_write,
660 + //.writev = tun_chr_writev,
661 + .poll = tun_chr_poll,
662 + .ioctl = tun_chr_ioctl,
663 + .open = tun_chr_open,
664 + .release = tun_chr_close,
665 + .fasync = tun_chr_fasync
668 +static struct miscdevice tun_miscdev = {
669 + .minor = TUN_MINOR,
672 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
673 + .devfs_name = "net/tun",
677 +int __init tun_init(void)
680 + struct net_device *dev = &tun_netdev;
683 + /* Initialize hash table */
684 + for (i = 0; i < XIDHASH_SZ; i++)
685 + INIT_LIST_HEAD(&tun_dev_hash[i]);
687 + ret = misc_register(&tun_miscdev);
689 + err("tun: Can't register misc device %d\n", TUN_MINOR);
693 + memset(dev, 0, sizeof(struct net_device));
695 + /* Ethernet TAP Device */
696 + dev->set_multicast_list = tun_net_mclist;
698 + /* Generate random Ethernet address. */
699 + *(u16 *)dev->dev_addr = htons(0x00FF);
700 + get_random_bytes(dev->dev_addr + sizeof(u16), 4);
704 + dev->flags |= IFF_NOARP | IFF_POINTOPOINT;
705 + dev->flags &= ~IFF_MULTICAST;
707 + SET_MODULE_OWNER(dev);
708 + dev->hard_start_xmit = tun_net_xmit;
709 + dev->get_stats = tun_net_stats;
711 + strcpy(dev->name, "tap0");
713 + ret = register_netdev(dev);
715 + misc_deregister(&tun_miscdev);
720 +void __exit tun_cleanup(void)
722 + struct tun_struct *tun, *nxt;
725 + misc_deregister(&tun_miscdev);
727 + write_lock_bh(&tun_dev_hash_lock);
728 + for (i = 0; i < XIDHASH_SZ; i++) {
729 + list_for_each_entry_safe(tun, nxt, &tun_dev_hash[i], list) {
730 + skb_queue_purge(&tun->readq);
734 + write_unlock_bh(&tun_dev_hash_lock);
736 + unregister_netdev(&tun_netdev);
739 +module_init(tun_init);
740 +module_cleanup(tun_cleanup);
741 +MODULE_LICENSE("GPL");