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