This file documents the Linux Usernet network interface version 1.1.

Copyright (c) 1998 Mark Wooding

Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.

Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the sections entitled `Copying' and `GNU General Public License' are included exactly as in the original, and provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.

Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by the copyright holder.

The Linux Usernet network interface
***********************************

Usernet allows network interfaces to be attached to character devices.  Any packets sent through the network interface will be passed to the process reading the device, and data written to the device will appear to have been received from the network interface.

This file documents Linux Usernet version 1.1.

The GNU General Public License
******************************

     [file gpl.texi not included]

Introduction
************

Access to Linux's networking tends to be fairly high-level.  A user process can send and receive datagrams, or set up connections to other processes easily enough.  Privileged processes can build arbitrary IP packets and send them, although raw IP sockets only receive packets for protocols unrecognised by the kernel.  Getting hold of all packets sent to a particular host is rather more difficult, though.  However, this can be a useful thing to want to do.  Usernet is a small kernel module which enables user processes to attach to a network interface and read and write packets to it.

Usernet works by creating pairs of character devices and network interfaces. Any packet Linux sends to the network interface is sent unchanged to the process reading the character device; similarly, when a block of data is written to the character device, Usernet claims that it was received from the corresponding network interface.

The diald program needs to be able to trap packets sent along a particular route to know when to open a dialup connection.  The current implementation sets up a SLIP interface on a pseudoterminal, which is kludgy at best.  It could be modified to use a Usernet interface, and read and write packets from there.

The application which motivated the writing of Usernet was setting up a virtual private network (VPN).  Each end could set up a point-to-point Usernet interface, and run a fairly small daemon, which would read packets sent to the remote end, encrypt them and retransmit them as IP-in-IP encapsulated datagrams, and decrypt any received IP-in-IP datagrams and reinsert them through the Usernet interface.

Overview and technical details
******************************

This chapter explains in more detail how Usernet is arranged and how it works.

Attachments
===========

The Usernet kernel module creates attachments between character devices and network interfaces.  Any packet sent by the kernel through the network interface can be read from the character device.  Any buffers sent to the device will appear to have been received by the attached interface.

The Usernet module understands two types of attachments:

  * Persistent attachments between character devices with low minor device numbers are initialised when the module is loaded.  The network interfaces always exist, and can be configured at boot time if the module is loaded early enough.

  * Transient attachments are set up dynamically when a process opens a Usernet device with no preattached interface.  The network interface is created when the device is opened, and destroyed again when the device is closed.  Each open of the device creates a separate attachment, so you only need one device for any number of transient attachments.

Usernet imposes a limitation on the number of attachments, mainly to stop runaway processes from gobbling kernel resources; there aren't any pre-allocated tables which would prevent you from hiking this parameter upwards if you had a reason to.

Usernet devices
===============

Usernet claims a major device number (chosen at configuration time: see Installing).

The lowest numbered minor devices are persistently attached to network interfaces: the network device unetN is attached to minor device N, conventionally named /dev/unetN.

If a device is opened for which there is no persistent attachment, a new network interface is allocated and a transient attachment is made.  Each separate open(2) call creates a new network interface and attachment, which are destroyed again when the file descriptor on the device is closed. It's normal to have one device with no persistent attachment, named /dev/unet.

Configuring and installing
**************************

Usernet is meant to be both simple to set up for most people, and sufficiently flexible to meet more advanced needs.

Configuration options
=====================

Configuration is performed using GNU Autoconf.  Running the supplied configure script without any options will configure Usernet to compile properly under most Linux systems.

The standard options accepted by Autoconf-generated configure scripts are described in Running configure Scripts (Creating Automatic Configuration Scripts).  In addition to the standard Autoconf options, Usernet's script understands these:

--with-linux-source=DIR
     Informs the configuration script that the Linux kernel sources are available in directory DIR.  The configuration script will find your source code in most sane installations.

--with-module-dir=DIR
     Informs the configuration script that the compiled kernel module is to be installed in directory DIR.  The configuration script will find somewhere sensible in most sane installations.

--with-major-device=NUM
     Sets the major device of all Usernet character devices to NUM.  Only change this if you find that Usernet is conflicting with some other device.

--with-persistent-devices=NUM
     Sets the number of persistent attachment devices created by Usernet when it's loaded to NUM.  The default is 1.

--with-transient-minor=NUM
     Sets the minor device number of the device special file /dev/unet, used to create transient attachments, to NUM.  The default is 256; you only need to change this if you've created a lot of persistent devices.

--with-max-queue-length=NUM
     Sets the maximum number of packets Usernet will queue for the process reading from an attached character device to NUM.  You probably don't need to fiddle with this.

--with-max-interfaces=NUM
     Sets the maximum number of attached network interfaces Usernet will allow to exist at any given time to NUM.  The default is fairly generous, so you shouldn't need to play with this unless you're doing something rather strange.

--with-debugging
     Enables profuse logging of things Usernet is doing, including complete hex dumps of all the network packets the module processes.

Compiling and installing
========================

Once Usernet has been autoconfigured, you should be able to type

     $ make
     ...
     $ su root
     Password:
     # make install
     ...

and the module will compile and install.

You'll need to create the character devices to allow processes to talk to Userdev.  The script makedev.unet will create the appropriate devices.  Run without any options, it will create devices appropriate to the configuration passed to configure.  Type

     makedev.unet --help

for information about the options it supports: they're not particularly useful if you got the configuration right.

If you later change your configuration, run makedev.unet again and it will set everything straight.

The unetcfg program
*******************

A Usernet attachment can be interrogated and configured using the unetcfg program supplied.

Invoking unetcfg
================

The unetcfg program is called as:

     unetcfg [OPTION...] COMMAND...

The various OPTIONs supported are as follows:

-h
--help
     Displays a helpful and informative summary of unetcfg's option syntax.

-V
--version
     Displays the version number of your copy of unetcfg.

-v
--verbose
     Enables output of largely useless status messages.  These might be of use when unetcfg doesn't seem to be doing what you want it to.

Each COMMAND is executed in turn, from left to right.  The command namees may be abbreviated, as long as the abbreviation is not ambiguous.

Most of the commands work with a current attachment, which is assumed to be standard input by default.  The current attachment may be changed using the select and fd commands (see Selecting attachments).

Changing the current attachment
===============================

These commands change the current attachment.  You can use them as often as you like in a single invocation of unetcfg.

 -- Command: select FILENAME
     Selects FILENAME as the current attachment.  Further operations will be performed on the named device.

     The command name select is optional: an argument which isn't a command name is assumed to be a filename to select.

 -- Command: fd FILEDESC
     Selects an open file descriptor to be the current attachment.  As well as boring old file descriptor numbers, you can use the names stdin, stdout and stderr.

     Note that it's really silly to set the current attachment to be standard output and then perform commands which write to stdout:

          unetcfg fd stdout show

     Don't do this.

Attachment status
=================

These commands write useful information about the current attachment to standard output.

 -- Command: show
     Writes information about the current attachment to standard output.  The format of the information is not intended to be processed by other programs, and may vary between releases of the software.

 -- Command: ifname
     Writes the name of the currently attached network interface to standard error.  This can be useful in configuration scripts.  For example:

          ifname=`unetcfg fd 3 ifname`
          ifconfig $ifname localend pointopoint remoteend

Protocol settings
=================

Each packet received by a network interface must have a protocol stamped on it.  Packets injected by writing to a Usernet-attached device are stamped with the attachment's current protocol.  The following command allows the current attachment's protocol to be set.

 -- Command: protocol PROTO
     Sets the protocol stamped on packets injected through the current attachment.  A list of currently known protocols may be obtained by specifying the special protocol name help.  The default protocol is always IP.

Setting debugging options
=========================

 -- Command: help [COMMAND]
     With no arguments, displays a summary of the commands available.  With a COMMAND argument, displays help on that command.

Programming Usernet
*******************

This chapter documents Usernet's programming interface.  It's not particularly complicated, you'll be glad to hear.

Opening and closing
===================

Opening and closing Usernet devices is simple and obvious.  Calling open(2) on the appropriate special file opens the device.  What happens now depends on whether the device has a persistent attachment to a network interface:

  * If the device has a persistent attachment, a check is made to see whether the device has already been opened by another process.  If this is the case, open returns EBUSY.  If the device was not already opened, it is marked as open and a file descriptor is returned.

  * If the device does not have a persistent attachment, a fresh network interface is allocated and attached to the device.  A file descriptor for the opened device is returned.

Closing a transiently attached device will release and destroy the attached network interface.

Configuring the interface
=========================

Usernet interfaces can be configured using some simple ioctl(2) calls supported by the Usernet character devices.  The constants and data structures required are defined in the header file unet.h provided in the distribution.

Most of the configuration work is performed on the network interface, and this is done using the traditional ioctl calls on an open socket's file descriptor.

The following ioctl calls are provided for configuring Usernet attachments.

 -- ioctl call: UNIOCGINFO
     Returns the a summary of the attachment's current configuration.  The argument is a pointer to a structure of type struct unet_info, which contains the following members:

     char uni_ifname[UNET_NAMEMAX];
          Interface name string.  This may be passed to the ifconfig program, or to the interface configuration ioctl calls to configure the attached network interface.

     unsigned short uni_mtu;
          Maximum transmission unit of the attached interface.  This is also available by calling SIOCGIFMTU, and may be set by calling SIOCSIFMTU.

     unsigned short uni_family;
          Address family of the attached interface.  This is usually AF_UNIX, although it may be changed by calling SIOCSIFADDR.

     unsigned short uni_proto;
          Network protocol number stamped onto packets to be sent from the attached network interface.  The default, which is probably good enough, is ETH_P_IP.  This field may be changed by calling UNIOCSPROTO.

     unsigned int uni_flags;
          An inclusive-OR of the following possible values:

          UNIF_TRANS
               Attachment is transient.

          UNIF_OPEN
               Currently always set.  Ignore this bit.

          UNIF_DEBUG
               Debugging enabled on this interface.

     Example:

          struct unet_info uni;
          int fd = open("/dev/unet", O_RDWR);
          if (fd < 0)
            die("couldn't open /dev/unet: %s", strerror(errno));
          if (ioctl(fd, UNIOCGINFO, &uni) < 0)
            die("couldn't get config information: %s", strerror(errno));
          printf("interface name = `%s'\n", uni.uni_ifname);

 -- ioctl call: UNIOCSDEBUG
     Sets or clears the debug state for a Usernet attachment.  If the argument is nonzero, the debug flag is set; if zero, the flag is cleared.  When debugging is enabled for an attachment, Usernet logs packets sent and received through it, and most changes to the attachment's state, to the kernel log.

 -- ioctl call: UNIOCGPROTO
     Reads the protocol number stamped onto packets submitted by an attached Usernet interface.  The value returned by the ioctl call is identical to the uni_proto member returned by UNIOCGINFO.

 -- ioctl call: UNIOCSPROTO
     Sets the protocl number stamped onto outgoing packets.  The protocol number, passed as the ioctl's argument, must be one of the constants defined in linux/if_ether.h.

 -- ioctl call: UNIOCGGDEBUG
     Reads the global debug flag.  When global debugging is enabled, all newly created attachments have debugging turned on automatically, and various global events are logged to the kernel log.

 -- ioctl call: UNIOCSGDEBUG
     Sets the global debug flag; if the argument is nonzero, the global debug flag is set; if zero, the flag is cleared.

 -- ioctl call: UNIOCDUMP
     Dumps an attachment's information to the kernel log device.

 -- ioctl call: UNIOCGMAXIF
     Returns the total number of attachments permitted.

 -- ioctl call: UNIOCSMAXIF
     Configures the total number of attachments permitted.  It is an error to reduce this below the number of attachments currently in existence.

Sending and receiving
=====================

A packet may be sent through a Usernet interface using the standard write(2) system call.  The buffer passed to write must be a complete packet; no coalescing or buffering is performed by Usernet.  It's always possible to write to a Usernet device and writing always succeeds without blocking.  However, packets may be silently rejected by the network stack.

Packets received by a Usernet interface are available to programs via the standard read(2) system call.  If the destination buffer is too small for a complete packet, the remainder of the packet is silently discarded.  If no packets are available for reading, the process is blocked (unless nonblocking I/O was explicitly requested).

Programs may call select(2) to wait for packets to arrive from an attached Usernet device.