1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
# libvdestack
A network namespace as a library, i.e.
Internet of Threads through Network Namespaces.
## Install libvdestack
libvdestack uses the cmake, so the standard procedure to compile and install the library is:
```
$ mkdir build
$ cd build
$ cmake ..
$ make
$ sudo make install
```
## Tutorial
By libvdestack a program can use one (or even several)
private networking protocol stack(s), thus a program can be assigned
its own IP address(es), routing etc.
The header file needed to use libvdestack in your C programs is:
```
#include <libvdeplug.h>
```
The following function call creates a networking stack connected to a vxvde network.
```
struct vdestack *stack;
stack = vde_addstack("vxvde://224.1.2.3", NULL);
```
This stack has a localhost interface and virtual interface named "vde0" connected to the specified
vxvde network.
It is possible to create a socket of the vdestack in this way:
```
int sockfd = vde_msocket(stack, AF_INET6, SOCK_STREAM, 0);
```
The file descriptor returned by vde\_msocket is a standard socket descriptor, so all the functions
and system calls can be used on *sockfd* in the example as they could have been used on any other socket
opened by socket(2). In other words the single different call to use a vdestack socket instead
of a standard socket is the socket creation function: *vde_msocket* instead of *socket*.
Vdestack sockets can be inherited by fork(2). The common technique to fork a process for each
new connection descriptor returned by accept(2) can be applied to vdestack sockets, too.
It is possible to define several different stacks in a program and create sockets on each one of them
just by properly assigning the first argument of vde\_msocket. The usual networking stack is still
available using the socket(2) system call.
If required by the program:
```
vde_delstack(stack);
```
closes a stack.
It is possible to define a default stack:
```
vde_default_stack(stack);
```
The default stack will be used by any successive socket(2) call. (It is implemented by a shared library
interposition of the *socket* interface function).
So after a user defines:
```
vde_default_stack(mystack);
```
The call:
```
fd = socket(AF_INET, SOCK_STREAM, 0);
```
is equivalent to:
```
fd = vde_msocket(mystack, AF_INET, SOCK_STREAM, 0);
```
Use
```
vde_default_stack(NULL);
```
to undefine the current default stack.
## Address/Route definition
Vdestack's virtual interfaces must be configured. IP address, netmask, routing must be properly set.
Libvdestack is a library which creates a network namespace. So a program using libvdestack is provided
with a specific instance of a kernel stack, thus all the libraries and system calls available for
the standard stack, can be used on a vdestack.
Unfortunately we have not yet found convenient libraries to set IP addresses and routes manually or by dhcp.
(Libnl and libnl-route should work, but the procedure to set addresses and routes is rather daunting).
Vde\_stackcmd runs a (configuration) command (or a sequence of comma separated configuration commands) in the
private networking namespace of a vdestack.
For example, an interface with a static ip address and a static default route can be defined as follows:
```
vde_stackcmd(stack,
"/bin/busybox ip link set vde0 up;"
"/bin/busybox ip addr add 10.0.0.2/24 dev vde0;"
"/bin/busybox ip route add default via 10.0.0.254");
```
It is also possible to run a dhcp client to configure a vdestack interface:
```
vde_stackcmd(stack,
"/bin/busybox ip link set vde0 up;"
"/bin/busybox udhcpc -q -s /home/user/bin/dhcpscript -i vde0");
```
## A complete example:
The following source file implements a multiclient tcp echo server (using fork) running on a vdestack.
```
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <vdestack.h>
struct vdestack *mystack;
static void getstatus(int signo) {
int status;
wait(&status);
}
int main(int arg, char *argv[]) {
struct sockaddr_in servaddr, cliaddr;
int fd, connfd;
char buf[BUFSIZ];
mystack = vde_addstack("vde://", NULL);
vde_stackcmd(mystack,"/bin/busybox ip addr add 192.168.250.100/24 dev vde0;"
"/bin/busybox ip link set vde0 up;"
"/bin/busybox ip route add default via 192.168.250.1");
signal(SIGCHLD, getstatus);
fd = vde_msocket(mystack, AF_INET, SOCK_STREAM, 0);
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(5000);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
exit(1);
listen (fd, 5);
for ( ; ; ) {
int n;
socklen_t clilen = sizeof(cliaddr);
connfd = accept (fd, (struct sockaddr *) &cliaddr, &clilen);
switch (fork()) {
case 0:
close(fd);
printf("new conn %d pid %d\n", connfd, getpid());
while ( (n = recv(connfd, buf, BUFSIZ, 0)) > 0) {
printf("pid %d GOT: %*.*s",getpid(),n,n,buf);
send(connfd, buf, n, 0);
}
printf("close conn %d pid %d\n", connfd, getpid());
close(connfd);
exit(0);
default:
close(connfd);
break;
case -1:
exit(1);
}
}
close(fd);
vde_delstack(mystack);
}
```
|