162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci.. include:: <isonum.txt> 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci=============================== 562306a36Sopenharmony_ciUniversal TUN/TAP device driver 662306a36Sopenharmony_ci=============================== 762306a36Sopenharmony_ci 862306a36Sopenharmony_ciCopyright |copy| 1999-2000 Maxim Krasnyansky <max_mk@yahoo.com> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci Linux, Solaris drivers 1162306a36Sopenharmony_ci Copyright |copy| 1999-2000 Maxim Krasnyansky <max_mk@yahoo.com> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci FreeBSD TAP driver 1462306a36Sopenharmony_ci Copyright |copy| 1999-2000 Maksim Yevmenkin <m_evmenkin@yahoo.com> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci Revision of this document 2002 by Florian Thiel <florian.thiel@gmx.net> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci1. Description 1962306a36Sopenharmony_ci============== 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci TUN/TAP provides packet reception and transmission for user space programs. 2262306a36Sopenharmony_ci It can be seen as a simple Point-to-Point or Ethernet device, which, 2362306a36Sopenharmony_ci instead of receiving packets from physical media, receives them from 2462306a36Sopenharmony_ci user space program and instead of sending packets via physical media 2562306a36Sopenharmony_ci writes them to the user space program. 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci In order to use the driver a program has to open /dev/net/tun and issue a 2862306a36Sopenharmony_ci corresponding ioctl() to register a network device with the kernel. A network 2962306a36Sopenharmony_ci device will appear as tunXX or tapXX, depending on the options chosen. When 3062306a36Sopenharmony_ci the program closes the file descriptor, the network device and all 3162306a36Sopenharmony_ci corresponding routes will disappear. 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci Depending on the type of device chosen the userspace program has to read/write 3462306a36Sopenharmony_ci IP packets (with tun) or ethernet frames (with tap). Which one is being used 3562306a36Sopenharmony_ci depends on the flags given with the ioctl(). 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci The package from http://vtun.sourceforge.net/tun contains two simple examples 3862306a36Sopenharmony_ci for how to use tun and tap devices. Both programs work like a bridge between 3962306a36Sopenharmony_ci two network interfaces. 4062306a36Sopenharmony_ci br_select.c - bridge based on select system call. 4162306a36Sopenharmony_ci br_sigio.c - bridge based on async io and SIGIO signal. 4262306a36Sopenharmony_ci However, the best example is VTun http://vtun.sourceforge.net :)) 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci2. Configuration 4562306a36Sopenharmony_ci================ 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci Create device node:: 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci mkdir /dev/net (if it doesn't exist already) 5062306a36Sopenharmony_ci mknod /dev/net/tun c 10 200 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci Set permissions:: 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci e.g. chmod 0666 /dev/net/tun 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci There's no harm in allowing the device to be accessible by non-root users, 5762306a36Sopenharmony_ci since CAP_NET_ADMIN is required for creating network devices or for 5862306a36Sopenharmony_ci connecting to network devices which aren't owned by the user in question. 5962306a36Sopenharmony_ci If you want to create persistent devices and give ownership of them to 6062306a36Sopenharmony_ci unprivileged users, then you need the /dev/net/tun device to be usable by 6162306a36Sopenharmony_ci those users. 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci Driver module autoloading 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci Make sure that "Kernel module loader" - module auto-loading 6662306a36Sopenharmony_ci support is enabled in your kernel. The kernel should load it on 6762306a36Sopenharmony_ci first access. 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci Manual loading 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci insert the module by hand:: 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci modprobe tun 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci If you do it the latter way, you have to load the module every time you 7662306a36Sopenharmony_ci need it, if you do it the other way it will be automatically loaded when 7762306a36Sopenharmony_ci /dev/net/tun is being opened. 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci3. Program interface 8062306a36Sopenharmony_ci==================== 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci3.1 Network device allocation 8362306a36Sopenharmony_ci----------------------------- 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci``char *dev`` should be the name of the device with a format string (e.g. 8662306a36Sopenharmony_ci"tun%d"), but (as far as I can see) this can be any valid network device name. 8762306a36Sopenharmony_ciNote that the character pointer becomes overwritten with the real device name 8862306a36Sopenharmony_ci(e.g. "tun0"):: 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci #include <linux/if.h> 9162306a36Sopenharmony_ci #include <linux/if_tun.h> 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci int tun_alloc(char *dev) 9462306a36Sopenharmony_ci { 9562306a36Sopenharmony_ci struct ifreq ifr; 9662306a36Sopenharmony_ci int fd, err; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) 9962306a36Sopenharmony_ci return tun_alloc_old(dev); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci memset(&ifr, 0, sizeof(ifr)); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci /* Flags: IFF_TUN - TUN device (no Ethernet headers) 10462306a36Sopenharmony_ci * IFF_TAP - TAP device 10562306a36Sopenharmony_ci * 10662306a36Sopenharmony_ci * IFF_NO_PI - Do not provide packet information 10762306a36Sopenharmony_ci */ 10862306a36Sopenharmony_ci ifr.ifr_flags = IFF_TUN; 10962306a36Sopenharmony_ci if( *dev ) 11062306a36Sopenharmony_ci strscpy_pad(ifr.ifr_name, dev, IFNAMSIZ); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){ 11362306a36Sopenharmony_ci close(fd); 11462306a36Sopenharmony_ci return err; 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci strcpy(dev, ifr.ifr_name); 11762306a36Sopenharmony_ci return fd; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci3.2 Frame format 12162306a36Sopenharmony_ci---------------- 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ciIf flag IFF_NO_PI is not set each frame format is:: 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci Flags [2 bytes] 12662306a36Sopenharmony_ci Proto [2 bytes] 12762306a36Sopenharmony_ci Raw protocol(IP, IPv6, etc) frame. 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci3.3 Multiqueue tuntap interface 13062306a36Sopenharmony_ci------------------------------- 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ciFrom version 3.8, Linux supports multiqueue tuntap which can uses multiple 13362306a36Sopenharmony_cifile descriptors (queues) to parallelize packets sending or receiving. The 13462306a36Sopenharmony_cidevice allocation is the same as before, and if user wants to create multiple 13562306a36Sopenharmony_ciqueues, TUNSETIFF with the same device name must be called many times with 13662306a36Sopenharmony_ciIFF_MULTI_QUEUE flag. 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci``char *dev`` should be the name of the device, queues is the number of queues 13962306a36Sopenharmony_cito be created, fds is used to store and return the file descriptors (queues) 14062306a36Sopenharmony_cicreated to the caller. Each file descriptor were served as the interface of a 14162306a36Sopenharmony_ciqueue which could be accessed by userspace. 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci:: 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci #include <linux/if.h> 14662306a36Sopenharmony_ci #include <linux/if_tun.h> 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci int tun_alloc_mq(char *dev, int queues, int *fds) 14962306a36Sopenharmony_ci { 15062306a36Sopenharmony_ci struct ifreq ifr; 15162306a36Sopenharmony_ci int fd, err, i; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (!dev) 15462306a36Sopenharmony_ci return -1; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci memset(&ifr, 0, sizeof(ifr)); 15762306a36Sopenharmony_ci /* Flags: IFF_TUN - TUN device (no Ethernet headers) 15862306a36Sopenharmony_ci * IFF_TAP - TAP device 15962306a36Sopenharmony_ci * 16062306a36Sopenharmony_ci * IFF_NO_PI - Do not provide packet information 16162306a36Sopenharmony_ci * IFF_MULTI_QUEUE - Create a queue of multiqueue device 16262306a36Sopenharmony_ci */ 16362306a36Sopenharmony_ci ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_MULTI_QUEUE; 16462306a36Sopenharmony_ci strcpy(ifr.ifr_name, dev); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci for (i = 0; i < queues; i++) { 16762306a36Sopenharmony_ci if ((fd = open("/dev/net/tun", O_RDWR)) < 0) 16862306a36Sopenharmony_ci goto err; 16962306a36Sopenharmony_ci err = ioctl(fd, TUNSETIFF, (void *)&ifr); 17062306a36Sopenharmony_ci if (err) { 17162306a36Sopenharmony_ci close(fd); 17262306a36Sopenharmony_ci goto err; 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci fds[i] = fd; 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci return 0; 17862306a36Sopenharmony_ci err: 17962306a36Sopenharmony_ci for (--i; i >= 0; i--) 18062306a36Sopenharmony_ci close(fds[i]); 18162306a36Sopenharmony_ci return err; 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ciA new ioctl(TUNSETQUEUE) were introduced to enable or disable a queue. When 18562306a36Sopenharmony_cicalling it with IFF_DETACH_QUEUE flag, the queue were disabled. And when 18662306a36Sopenharmony_cicalling it with IFF_ATTACH_QUEUE flag, the queue were enabled. The queue were 18762306a36Sopenharmony_cienabled by default after it was created through TUNSETIFF. 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cifd is the file descriptor (queue) that we want to enable or disable, when 19062306a36Sopenharmony_cienable is true we enable it, otherwise we disable it:: 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci #include <linux/if.h> 19362306a36Sopenharmony_ci #include <linux/if_tun.h> 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci int tun_set_queue(int fd, int enable) 19662306a36Sopenharmony_ci { 19762306a36Sopenharmony_ci struct ifreq ifr; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci memset(&ifr, 0, sizeof(ifr)); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci if (enable) 20262306a36Sopenharmony_ci ifr.ifr_flags = IFF_ATTACH_QUEUE; 20362306a36Sopenharmony_ci else 20462306a36Sopenharmony_ci ifr.ifr_flags = IFF_DETACH_QUEUE; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci return ioctl(fd, TUNSETQUEUE, (void *)&ifr); 20762306a36Sopenharmony_ci } 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ciUniversal TUN/TAP device driver Frequently Asked Question 21062306a36Sopenharmony_ci========================================================= 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci1. What platforms are supported by TUN/TAP driver ? 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ciCurrently driver has been written for 3 Unices: 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci - Linux kernels 2.2.x, 2.4.x 21762306a36Sopenharmony_ci - FreeBSD 3.x, 4.x, 5.x 21862306a36Sopenharmony_ci - Solaris 2.6, 7.0, 8.0 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci2. What is TUN/TAP driver used for? 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ciAs mentioned above, main purpose of TUN/TAP driver is tunneling. 22362306a36Sopenharmony_ciIt is used by VTun (http://vtun.sourceforge.net). 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ciAnother interesting application using TUN/TAP is pipsecd 22662306a36Sopenharmony_ci(http://perso.enst.fr/~beyssac/pipsec/), a userspace IPSec 22762306a36Sopenharmony_ciimplementation that can use complete kernel routing (unlike FreeS/WAN). 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci3. How does Virtual network device actually work ? 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ciVirtual network device can be viewed as a simple Point-to-Point or 23262306a36Sopenharmony_ciEthernet device, which instead of receiving packets from a physical 23362306a36Sopenharmony_cimedia, receives them from user space program and instead of sending 23462306a36Sopenharmony_cipackets via physical media sends them to the user space program. 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ciLet's say that you configured IPv6 on the tap0, then whenever 23762306a36Sopenharmony_cithe kernel sends an IPv6 packet to tap0, it is passed to the application 23862306a36Sopenharmony_ci(VTun for example). The application encrypts, compresses and sends it to 23962306a36Sopenharmony_cithe other side over TCP or UDP. The application on the other side decompresses 24062306a36Sopenharmony_ciand decrypts the data received and writes the packet to the TAP device, 24162306a36Sopenharmony_cithe kernel handles the packet like it came from real physical device. 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci4. What is the difference between TUN driver and TAP driver? 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ciTUN works with IP frames. TAP works with Ethernet frames. 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ciThis means that you have to read/write IP packets when you are using tun and 24862306a36Sopenharmony_ciethernet frames when using tap. 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci5. What is the difference between BPF and TUN/TAP driver? 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ciBPF is an advanced packet filter. It can be attached to existing 25362306a36Sopenharmony_cinetwork interface. It does not provide a virtual network interface. 25462306a36Sopenharmony_ciA TUN/TAP driver does provide a virtual network interface and it is possible 25562306a36Sopenharmony_cito attach BPF to this interface. 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci6. Does TAP driver support kernel Ethernet bridging? 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ciYes. Linux and FreeBSD drivers support Ethernet bridging. 260