---
name: "tun"
section: "4"
platform: "openbsd"
package: "man"
version: "8.0-current-20261101"
release: "OpenBSD 8.0-current (2026-11-01)"
platforms: ["linux", "freebsd", "openbsd"]
url: "https://new.carta.tech/tun"
---

# tun(4)

network tunnel pseudo-device

## NAME

**tun**, **tap** – network tunnel pseudo-device

## SYNOPSIS

**pseudo-device tun**

**#include \<sys/types.h\>**

**#include \<net/if\_tun.h\>**

## DESCRIPTION

The **tun** pseudo-device driver provides character special devices for communicating with the kernel network stack via the **tun** and **tap** network interfaces. Packets sent to these interfaces can be read from the device special file by a userland process and processed as desired. Packets written to the device special file by the userland process are injected back into the kernel networking subsystem.

**tun** and **tap** interfaces can be created at runtime using the **ifconfig** **iface***N* **create** command, or by opening the character special devices */dev/tunN* or */dev/tapN* respectively.

The minor number of the device special files are associated with the unit number of the network interfaces.

Each device has an exclusive open property: it cannot be opened if it is already open and in use by another process. On the last close of the device all queued packets are discarded. If the device was created by opening a device special file it will be automatically destroyed. The last close of a device special file associated with an interface created via [ifconfig(8)](/ifconfig/8.md) will be marked as not running and traffic sent out the will be dropped.

Each read returns at most one packet; if insufficient buffer space is provided, the packet is truncated. Each write supplies exactly one packet. Writes never block. If the protocol queue is full, the packet is dropped, a “collision” is counted, and ENOBUFS is returned.

The following [ioctl(2)](/ioctl/2.md) special commands defined in ⟨net/if\_tun.h⟩ are supported:

- TUNGIFINFO *struct tuninfo \**

  - TUNSIFINFO *struct tuninfo \**

  Get or set the interface characteristics.

  ```
  /* iface info */
  struct tuninfo {
          u_int   mtu;
          u_short type;
          u_short flags;
          u_int   baudrate;
  };
  ```

  *flags* and *type* are set by the kernel when an interface is created, and must be set to the same values that the kernel provided.

- TUNSIFMODE *int*, *\**

  Provided for backwards compatibility. The flags set must match what the kernel initialised them to.

- TUNSCAP *struct*, *tun\_capabilities*, *\**

  Enable the prepending of network packets with a *struct* *tun\_hdr* offload header, and set which interface offload capabilities userland can handle on behalf of the kernel.

  ```
  struct tun_capabilities {
  	uint32_t	tun_if_capabilities;
  };
  ```

  The *tun\_if\_capabilities* field is set with IFCAP values from ⟨net/if.h⟩. It is acceptable to enable the offload header without enabling any interface offload capabilities.

  The prepending of network packets with a *struct* *tun\_hdr* offload header is disabled, and the interface offload capabilities are reset when the device special file is closed.

- TUNGCAP *struct*, *tun\_capabilities*, *\**

  Get which interface offload capabilities are currently enabled. If the interface has not been configured with TUNSCAP this command will fail with ENODEV.

- TUNDCAP

  Disable the prepending of network packets with the *struct* *tun\_hdr* offload header, and clear interface offload capabilities.

The generic ioctls FIONREAD, FIONBIO, FIOASYNC, FIOSETOWN, FIOGETOWN are also supported.

### Point-to-Point Layer 3 tunnel interface (tun)

Each packet read from or written to a **tun** interface is prefixed with a tunnel header consisting of a 4-byte network byte order integer containing the address family of the packet. **tun** supports AF\_INET, AF\_INET6, and AF\_MPLS packets.

### Ethernet tunnel interface (tap)

Each packet read from or written to a **tap** interface is an Ethernet packet. The Ethernet CRC at the end of the frame is not required.

The device special files for **tap** interfaces support the following additional [ioctl(2)](/ioctl/2.md) commands:

- SIOCGIFADDR *uint8\_t*\[ETHER\_ADDR\_LEN\]

  - SIOCSIFADDR *uint8\_t*\[ETHER\_ADDR\_LEN\]

  Get or set the link layer address (MAC address) of the interface.

### Network offload support

When network offload support has been enabled with the TUNSCAP [ioctl(2)](/ioctl/2.md) command, *struct* *tun\_hdr* is prepended to packets read from and written to the device special file.

The kernel will populate the offload header for reads from the device special file depending on which interface offload capabilities are enabled. A program may use any offload feature when writing to the device special file regardless of which interface offload capabilities are enabled. The offload header can be read from one device special file and written directly to another without interpretation or modification.

```
struct tun_hdr {
	uint16_t	th_flags;
	uint16_t	th_pad;
	uint16_t	th_vtag;
	uint16_t	th_mss;
};
```

The fields in the *struct* *tun\_hdr* are in host native byte order.

The following flags can be set in *th\_flags* to specify which offloads are requested for the current packet:

- TUN\_H\_VTAG

  *th\_vtag* is set.

- TUN\_H\_TCP\_MSS

  TCP segmentation offload is requested for the current packet. The maximum segment size is specified in *th\_mss*.

- TUN\_H\_IPV4\_CSUM

  IPv4 header checksum calculation requested.

- TUN\_H\_TCP\_CSUM

  TCP checksum calculation requested.

- TUN\_H\_UDP\_CSUM

  UDP checksum calculation requested.

- TUN\_H\_ICMP\_CSUM

  ICMP checksum calculation requested.

Only one of TUN\_H\_TCP\_CSUM, TUN\_H\_UDP\_CSUM, and TUN\_H\_ICMP\_CSUM can be specified at a time. TUN\_H\_VTAG can only be used with **tap** interfaces.

*th\_pad* should be set to 0 when writing to the device special file, and ignored when reading from the device special file.

## FILES

- */dev/tun\**

  - */dev/tap\**

  ## ERRORS

If open fails, [errno(2)](/errno/2.md) may be set to one of:

- \[ENXIO\]

  Not that many devices configured.

- \[EBUSY\]

  Device was already open.

If a [write(2)](/write/2.md) call fails, [errno(2)](/errno/2.md) is set to one of:

- \[EMSGSIZE\]

  The packet supplied was too small or too large. The maximum sized packet allowed is currently 16384 bytes.

- \[ENOMEM\]

  There were no mbufs.

[ioctl(2)](/ioctl/2.md) commands may fail with:

- \[EINVAL\]

  Invalid parameters were specified.

- \[ENOTTY\]

  Unrecognized ioctl command.

A [read(2)](/read/2.md) call may fail because of:

- \[EIO\]

  The associated interface has been destroyed.

- \[EWOULDBLOCK\]

  Non-blocking I/O was selected and no packets were available.

## SEE ALSO

[ioctl(2)](/ioctl/2.md), [inet(4)](/inet/4.md), [intro(4)](/intro/4.md), [netintro(4)](/netintro/4.md), [hostname.if(5)](/hostname.if/5.md), [ifconfig(8)](/ifconfig/8.md), [netstart(8)](/netstart/8.md)

## HISTORY

**tun** interfaces originally supported both Layer 3 and Ethernet packets by reconfiguring the type of interface with TUNSIFINFO. Ethernet packet support was split into the separate **tap** interface in OpenBSD 5.9.

## AUTHORS

**tun** was written by Julian Onions ⟨*Julian.Onions@nexor.co.uk*⟩ at Nottingham University.

The **tap** interface functionality was written by Claudio Jeker ⟨*claudio@openbsd.org*⟩.
