Multi stack support for Berkeley Sockets
The Berkeley socket API is the de facto standard for network programming.
Unfortunately this API has been designed to use one single stack for each protocol family. This is the common case for many (all?)operating systems today but the ability to access and use several protocol stacks permits new applications and simplify solutions to common problems.
Networking is also an exception for *nix systems for naming. In fact the file system has been used as a unified naming method for files, devices, fifos, unix sockets, ... and almost everything but networking.
We propose an extension to the Berkeley API having the following features:
- multiple stacks can be used at the same time
- the file system gets used for naming the stacks
- it is backward compatible with existing applications.
The new extended API has been named msockets after the most important call of the API itself msocket, namely acronym for multi-socket.
We have already implemented this extension in our umnet module of the View-OS project.
The Stack special file
Each stack can be accesses by its special file.
The stack type has been defined (see stat(2)) as
#define S_IFSTACK 0160000
Execute x permission to the special file permits the configuration of the stack while the read permission r permits just the data communication.
If a user has the x permission, she can define interfaces, addresses, routes, (like CAP_NET_ADMIN capability). w permission has not been defined yet but it could be used for high level services (like binding of sockets < 1024 or multicasting capabilities). A user without r permission gets an error if she tries to open a socket (using socket or msocket).
The msocket call
The syntax of msocket is:
#include <sys/types.h> #include <msocket.h> int msocket(char *path, int domain, int type, int protocol);
domain, type and protocol have the same meaning as in socket(2) (with some extensions, see over). path refers to the stack special file we want to use, when path is NULL the default stack gets used.
In fact, each process has a default stack for each protocol family. It is possible to redefine the default stack by using the tag SOCK_DEFAULT in the type field. Thus:
defines /dev/net/ipstack2 as the default socket for the calling process for all subsequent requests for sockets of the IPv4 protocol family.
Using msocket to define the default stack for the PF_UNSPEC family means to define /dev/net/ipstack2 as the default stack for all the protocol families it is able to manage.
When programming with msockets the former (system) call:
socket(path, domain, protocol)
is equivalent to:
msocket(NULL, path, domain, protocol)
The msocketpair call
msocketpair is an extension of socketpair like msocket extends socket.
The syntax is:
int msocketpair(char *path, int d, int type, int protocol, int sv);
Please note that msocketpair has not been implemented yet
The mstack command
mstack is a command that defines the default stack for the mstack process itself and execute (using exec(2)) the a command. As a result the command uses the stack defined by mstack as its default stack.
mstack is useful to run utilities and commands designed to work on one shell (e.g. using the standard Berkeley socket API) on one of the several stacks supported by msockets support.
The syntax of mstack is the following:
mstack [-u46npbihv] [-f num,num#] stack_mountpoint command
where u,4,6,n,p,b,i stands for PF_UNIX, PF_INET, PF_INET6, PF_NETLINK, PF_PACKET, PF_BLUETOOTH, PF_IRDA respectively, h is help, and v is verbose. Protocols can be set by listing the protocol numbers (see /usr/include/linux/socket.h). When there are no options for protocol families, the stack named in the command beames the default one for all the protocol families it supports.
$ mstack /dev/net/ipstack2 ip addr
executes the command ip stack on the stack /dev/net/ipstack2.
$ mstack /dev/net/ipstack2 bash
thus in the subshell
$ ip addr
shows the interface addresses of the /dev/net/ipstack2 stack. opens a subshell where /dev/net/ipstack2 is the default stack.