2009-06-16 15 views
13

Ich habe eine harte Zeit, dieses Problem herauszufinden - ich versuche, ein Programm zu schreiben, das mit dem Linux-Tunnel-Treiber interagieren wird. Auf einer sehr einfachen Ebene möchte ich einfach eine Anwendung erstellen, die in der Lage ist, Daten über einen Netzwerk-Tunnel zu übertragen. Ich bin jedoch völlig ratlos, wie ich den Tunneltreiber richtig einrichten kann, um dies zu erreichen.Wie man mit dem Linux tun Treiber eingeht

Ich entwickle auf Ubuntu 9.04, und ich habe den Tunnel-Treiber Kernel-Modul geladen.

Es gibt das Gerät /dev/net/tun, jedoch gibt es keine /dev/tunX Geräte. Ich bin nicht in der Lage, diese Geräte mit ifconfig zu schaffen - wenn ich /sbin/ifconfig tun0 up laufen, zum Beispiel, bekomme ich folgende Fehlermeldung:

tun0: ERROR while getting interface flags: No such device.

Wenn ich an dem /dev/net/tun Gerät zu suchen versuche, wird der folgende Fehler dargestellt:

cat: /dev/net/tun: File descriptor in bad state.

Versuch /dev/tunX über ein kleines Programm zu öffnen, im Grunde einfach ein retu

tun_fd = open("/dev/tun0", O_RDWR) 

rns -1: Die Anwendung läuft als root und kann dieses Tunnelgerät immer noch nicht öffnen. Es ist möglich, /dev/net/tun zu öffnen, jedoch scheint dies kein neues /dev/tunX Gerät zu generieren, das stattdessen verwendet werden kann.

So in der Zusammenfassung - wie geht man über eine Anwendung zu schreiben, die den Linux-Tunnel-Treiber verwenden möchte? Alle Einsichten würden sehr geschätzt werden.

Danke; ~ Robert

Antwort

13

/usr/src/linux/Documentation/networking/tuntap.txt lesen.

Du zu open soll die /dev/net/tun Gerät. Eine nachfolgende ioctl auf dem offenen fd wird die Netzwerkschnittstelle tun0 (oder was auch immer Sie wollen) erstellen. Die Netzwerkschnittstellen von Linux entsprechen keinem /dev/* Gerät.

+0

@rmbrobins; Was hast du getan, um das wirklich funktionieren zu lassen? Ich glaube, ich habe ein sehr ähnliches Problem mit Ihrer ursprünglichen Frage. Ich habe das/dev/net/tun Gerät sichtbar, aber das Öffnen dieses erzeugt keine Netzwerkschnittstelle. Ich habe versucht, die Beispiele br_select.c und br_sigio.c zu verwenden. – simon

+0

Wie oben erwähnt, öffnen Sie/dev/net/tun. Dann wird ein ioctl verwendet, um die eigentliche Schnittstelle selbst zu erstellen. Das ioctl heißt TUNSETIFF und das Argument hat den Typ struct ifreq. Die Flags der ifreq-Struktur sollten auf IFF_TUN gesetzt sein. Sobald das ioctl zurückgegeben wurde, wird das ifr_name-Feld der ifreq-Struktur mit dem Namen der geöffneten Schnittstelle festgelegt. Hoffe das hilft! – rmrobins

0
+2

Ich habe viel Zeit mit diesen Beispielen verbracht, aber sie funktionieren nicht! Sie versuchen, die/dev/tunX-Geräte direkt zu öffnen, was inkorrekt ist (wie durch den Link gezeigt, den der Ephemient bereitgestellt hat). Dies verursachte tatsächlich viel von meiner Verwirrung. – rmrobins

10

Es gibt keine /dev/tunX Gerätedateien. Stattdessen öffnen Sie die /dev/net/tun und konfigurieren sie über ioctl() zu "Punkt" zu tun0. Um die grundlegende Prozedur anzuzeigen, werde ich die TUN-Schnittstelle mit dem Befehlszeilentool ip tun tap erstellen und dann den C-Code zum Lesen von diesem TUN-Gerät anzeigen. So um die tun-Schnittstelle über Befehle Zeile zu erstellen:

sudo ip tuntap add mode tun dev tun0 
ip addr add 10.0.0.0/24 dev tun0 # give it an ip 
ip link set dev tun0 up # bring the if up 
ip route get 10.0.0.2 # check that packets to 10.0.0.x are going through tun0 
ping 10.0.0.2 # leave this running in another shell to be able to see the effect of the next example 

Jetzt haben wir tun0 erstellt.Um Pakete von einem Benutzer-Space-Programm an diese Schnittstelle zu lesen/schreiben, müssen Sie mit der /dev/net/tun Gerätedatei unter Verwendung von ioctl() interagieren. Hier ist ein Beispiel, das die an der Schnittstelle tun0 ankommenden Pakete liest und die folgende Größe ausdruckt:

#include <fcntl.h> /* O_RDWR */ 
#include <string.h> /* memset(), memcpy() */ 
#include <stdio.h> /* perror(), printf(), fprintf() */ 
#include <stdlib.h> /* exit(), malloc(), free() */ 
#include <sys/ioctl.h> /* ioctl() */ 

/* includes for struct ifreq, etc */ 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <linux/if.h> 
#include <linux/if_tun.h> 

int tun_open(char *devname) 
{ 
    struct ifreq ifr; 
    int fd, err; 

    if ((fd = open("/dev/net/tun", O_RDWR)) == -1) { 
     perror("open /dev/net/tun");exit(1); 
    } 
    memset(&ifr, 0, sizeof(ifr)); 
    ifr.ifr_flags = IFF_TUN; 
    strncpy(ifr.ifr_name, devname, IFNAMSIZ); // devname = "tun0" or "tun1", etc 

    /* ioctl will use ifr.if_name as the name of TUN 
    * interface to open: "tun0", etc. */ 
    if ((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) == -1) { 
    perror("ioctl TUNSETIFF");close(fd);exit(1); 
    } 

    /* After the ioctl call the fd is "connected" to tun device specified 
    * by devname ("tun0", "tun1", etc)*/ 

    return fd; 
} 


int main(int argc, char *argv[]) 
{ 
    int fd, nbytes; 
    char buf[1600]; 

    fd = tun_open("tun0"); /* devname = ifr.if_name = "tun0" */ 
    printf("Device tun0 opened\n"); 
    while(1) { 
    nbytes = read(fd, buf, sizeof(buf)); 
    printf("Read %d bytes from tun0\n", nbytes); 
    } 
    return 0; 
}