2009-06-16 19 views
13

この問題を解決するのに苦労しています。Linuxトンネルドライバとやりとりするプログラムを作成しようとしています。非常に基本的なレベルでは、ネットワークトンネルを介してデータを転送できるアプリケーションを作成したいだけです。しかし、これを達成するためにトンネルドライバを適切にセットアップする方法については、私は完全に犠牲になっています。Linux tunドライバとのインタフェース方法

私はUbuntu 9.04で開発しており、トンネルドライバカーネルモジュールをロードしています。

/dev/net/tunのデバイスがありますが、/dev/tunXのデバイスはありません。

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

私は/dev/net/tunデバイスを見しようとすると、次のエラーが提示されています:

例えば、私は次のエラーを取得、私は /sbin/ifconfig tun0 upを実行するたびに - 私は ifconfigを使用して、これらのデバイスを作成することができません基本的には、小さなプログラムを経由して /dev/tunXを開こう

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

、シンプル

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

retu rns -1:アプリケーションはrootとして実行されており、このトンネルデバイスを開けません。 /dev/net/tunを開くことは可能ですが、代わりに新しい/dev/tunXデバイスを生成するようには見えません。

したがって、要約すると、Linuxトンネルドライバを使用したいアプリケーションを作成するにはどうすればよいですか?どんな洞察も大変高く評価されます。

ありがとうございます。 〜ロバート

答えて

13

/usr/src/linux/Documentation/networking/tuntap.txtを読んでください。

あなたはopen/dev/net/tunデバイスになっています。開いたfd上の次のioctlは、tun0(または名前を付けたいもの)のネットワークインターフェイスを作成します。 Linuxのネットワークインターフェイスは、/dev/*デバイスには対応していません。

+0

@rmrobins;実際にこれを稼働させるためにあなたは何をしましたか?私はあなたの元の質問に非常によく似た問題があると信じています。私は/ dev/net/tunデバイスを見えるようにしていますが、これを開いてもネットワークインタフェースは生成されません。私はbr_select.cとbr_sigio.cの例を使用しようとしています。 – simon

+0

上記のように、/ dev/net/tunを開きます。次に、ioctlを使用して実際のインタフェース自体を作成します。 ioctlはTUNSETIFFと呼ばれ、引数はstruct ifreq型です。 ifreq構造体のフラグはIFF_TUNに設定する必要があります。 ioctlが返されると、ifreq構造体のifr_nameフィールドは、開かれたインタフェースの名前で設定されます。お役に立てれば! – rmrobins

0

実施例については、http://vtun.cvs.sourceforge.net/viewvc/vtun/tun/examples/を参照してください。

+2

私はこれらの例を見るのに多くの時間を費やしましたが、実際には動作しません!彼らは/ dev/tunXデバイスを直接オープンしようとしますが、これは間違っています(ephemientが提供するリンクで示されています)。これは実際に私の混乱の多くを引き起こしました。 – rmrobins

10

/dev/tunXデバイスファイルはありません。代わりに/dev/net/tunを開き、を介してtun0に「ポイント」を設定します。基本的な手順を示すために、コマンドラインツールip tun tapを使用してTUNインターフェイスを作成し、そのTUNデバイスから読み取るCコードを表示します。だから、コマンドラインを介してTUNインターフェイスを作成するには:

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 

は、今、私たちは tun0を作成しました。ユーザ空間プログラムからこのインタフェースへパケットを読み書きするには、 ioctl()を使用して /dev/net/tunデバイスファイルと対話する必要があります。ここでは、 tun0インターフェイスに到着したパケットを読み取り、サイズを印刷する例を示します。

#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; 
} 
関連する問題