TUN(4) BSD Kernel Interfaces Manual TUN(4)NAMEtun — Tunnel Network Interface
SYNOPSIS
pseudo-device tun 4
DESCRIPTION
The tun interface is a software loopback mechanism that can be loosely
described as the network interface analog of the pty(4), that is, tun
does for network interfaces what the pty driver does for terminals.
The tun driver, like the pty driver, provides two interfaces: an inter‐
face like the usual facility it is simulating (a network interface in the
case of tun, or a terinal for pty), and a character-special device
“control” interface.
The network interfaces are named tun0, tun1, etc, as many in all as the
count figure given on the pseudo-device line. Each one supports the
usual network-interface ioctl(2)s, such as SIOCSIFADDR and
SIOCSIFNETMASK, and thus can be used with ifconfig(8) like any other
interface. At boot time, they are POINTOPOINT interfaces, but this can
be changed; see the description of the control device, below. When the
system chooses to transmit a packet on the network interface, the packet
can be read from the control device (it appears as “input” there); writ‐
ing a packet to the control device generates an input packet on the net‐
work interface, as if the (nonexistent) hardware had just received it.
There are two control interfaces. The data interface, normally
/dev/tunN, is exclusive-open (it cannot be opened if it is already open),
is normally restricted to the super-user, and can “transmit” and
“receive” packets. The control interface, normally /dev/tuncN, cannot
send and receive packets, but can be opened by many processes at once; it
is intended for status queries and changes (many of which can also be
implemented with ioctl() calls on the data interface). There are a num‐
ber of status bits that can be set or cleared via the control interfaces;
they are mentioned below where applicable, and they are all summarized in
the discussions of the control interfaces.
The data interface
The data interface supports read(2), write(2), and ioctl(2) calls to,
respectively, collect “output” packets, generate “input” packets, and
perform control functions. As mentioned above, this interface is exclu‐
sive-open; if the SUONLY bit is set (which it is by default), it cannot
be opened at all except by the super-user. By default, a read() call
will return an error (EHOSTDOWN) if the interface is not “ready” (which
means that the control device is open and the interface's address has
been set); if preferred, the RRWAIT bit can be set, in which case a
read() call will block (even if non-blocking I/O has been enabled) until
the interface is ready. Once the interface is ready, read() will return
a packet if one is available; if not, it will either block until one is
or return EWOULDBLOCK, depending on whether non-blocking I/O has been
enabled. If the packet is longer than is allowed for in the buffer
passed to read(), the extra data will be silently dropped.
The first byte of data will always be the address family (eg, AF_INET) of
the packet. By default, the packet data follows immediately, but if the
PREPADDR bit is set, the address to which the packet is to be sent is
placed after the address family byte and before the packet data. The
size and layout of the address depends on the address family; for
AF_INET, for example, it is a struct in_addr. A write(2) call passes a
packet in to be “received” on the pseudo-interface. Each write() call
supplies exactly one packet; the packet length is taken from the amount
of data provided to write(). The first byte must be the address family
of the packet, much as in packets returned by read(); the packet data
always follows immediately. A large number of ioctl(2) calls are also
supported. They are defined in ⟨net/if_tun.h⟩.
TUNSDEBUG The argument should be a pointer to an int; this sets the
internal debugging variable to that value. What, if any‐
thing, this variable controls is not documented here; see
the source code.
TUNGDEBUG The argument should be a pointer to an int; this stores the
internal debugging variable's value into it.
TUNSMODE The argument should be a pointer to an int; its value must
be IFF_POINTOPOINT or IFF_BROADCAST. The type of the cor‐
responding tunn interface is set to the supplied type. If
the value is anything else, an EINVAL error occurs. The
interface must be down at the time; if it is up, an EBUSY
error occurs.
The data control device also supports select(2) for read; selecting for
write is pointless, and always succeeds, since writes are always non‐
blocking (if the packet cannot be accepted for a transient reason (eg, no
buffer space available), it is silently dropped; if the reason is not
transient (eg, packet too large), an error is returned).
On the last close of the data device, by default, the interface is
brought down (as if with “ifconfig tunn down”); if the STAYUP bit is set,
this is not done. In either case, all queued packets are thrown away.
(If the interface is up when the data device is not open, either because
of STAYUP or because it was explicitly brought up, output packets are
always thrown away rather than letting them pile up.)
The control interface
The alternative control interface is a text-based interface designed for
shell-script or human use; it allows control of many of the things that
can be done with ioctl() calls on the data interface, and a few more as
well.
read()s on the control interface always return a single line of text (or
just the beginning of the line, if the buffer passed to read(2) was too
small to take the whole line). The line contains items in the general
format “item=value”, where item is a keyword and value is a value appro‐
priate to the keyword. This line is intended for human use; programs
should use the ioctl() interface. Here is an actual example (broken
because of width restrictions):
unit=0 flags=(open,inited,!rcoll,iaset,!dstaddr,!rwait,!async,
!nbio,!brdaddr,prepaddr,stayup,suonly,rrwait) type=broadcast
mtu=1500 coll=0 ipkts=0/0 opkts=0/0 pgrp=0
Note that the current file offset is ignored for reads, so using a tool
like cat(1) will result in infinite output. Use something more like
“head -1” for command-line use. It is possible to select(2) for reading
on this device, which will indicate that the device is readable whenever
the state is changed.
Writes to the control interface are interpreted as modifications to the
state. Each write() call is treated separately. The data written is
broken at whitespace (blanks, tabs, newlines); each resulting fragment
has its first character examined. If this character is a ‘+’ or ‘-’, the
rest of the fragment is taken as a flag name, and the flag is turned on
(for ‘+’) or off (for ‘-’). (Flag names are as generated on reads; they
are the same as the TUN_xxx constants, with the leading TUN_ removed and
the rest lowercased.) If the first character is ‘t’, the second charac‐
ter must be ‘b’ or ‘p’, and the interface type is set to IFF_BROADCAST or
IFF_POINTOPOINT, respectively. If the first character is ‘g’ or ‘m’, the
rest of the fragment is taken as a number in decimal (possibly with a
leading - sign) and the result is taken as a new process group, for ‘g’
or MTU, for ‘m’. (The MTU must not be less than 1; attempts to set it so
return EIO.)
This interface is useful for command-line reconfiguration, such as set‐
ting the interface type at boot time, with
SEE ALSOintro(4), inet(4)BUGS
The SUONLY bit is a botch, especially since the control interface, which
is never restricted by the kernel, can change it. Access control really
should be handled by the permission bits on the /dev entries for the data
and control devices; this bit is a historical artifact.
The process-group values for SIGIO signals should be checked; as it
stands, the driver can be used (by anyone who can open the control or
data device) to send any desired signal to an arbitrary process or
process group. (Until this is fixed, you should be careful to set the
permisison bits to allow only root to open the control device, and either
do the same for the data device or leave the SUONLY bit set.)
OpenBSD March 10, 1996 OpenBSD