私はこの問題を理解するのに苦労しています-私はLinuxトンネルドライバーと相互作用するプログラムを書こうとしています。非常に基本的なレベルでは、ネットワークトンネルを介してデータを転送できるアプリケーションを作成したいだけです。しかし、これを達成するためにトンネルドライバーを適切に設定する方法について私は完全に途方に暮れています。
Ubuntu 9.04で開発していて、トンネルドライバーカーネルモジュールをロードしています。
デバイス/dev/net/tun
は存在しますが、/dev/tunX
デバイスはありません。 ifconfig
を使用してこれらのデバイスを作成できません-たとえば、/sbin/ifconfig tun0 up
を実行するたびに、次のエラーが発生します。
tun0:インターフェースフラグの取得中にエラーが発生しました:そのようなデバイスはありません。
/dev/net/tun
デバイスを調べようとすると、次のエラーが表示されます。
cat:/ dev/net/tun:ファイル記述子が不良状態です。
小さなプログラムを介して/dev/tunX
を開こうとすると、基本的には単純です
tun_fd = open( "/dev/tun0", O_RDWR )
-1を返します。アプリケーションはrootとして実行されていますが、このトンネルデバイスを開くことはできません。 /dev/net/tun
を開くことは可能ですが、代わりに使用する新しい/dev/tunX
デバイスを生成するようには見えません。
それで、要約すると、Linuxトンネルドライバーを使用したいアプリケーションをどのように作成するのでしょうか。どんな洞察も大歓迎です。
ありがとう; 〜ロバート
/usr/src/linux/Documentation/networking/tuntap.txt
を読んでください。
open
/dev/net/tun
デバイスを使用することになっています。開いているfdの後続のioctl
は、tun0
(または名前を付けたいもの)ネットワークインターフェイスを作成します。 Linuxのネットワークインターフェイスは、どの/dev/*
デバイスにも対応していません。
_/dev/tunX
_デバイスファイルはありません。代わりに、_/dev/net/tun
_を開き、ioctl()
を介して_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;
}
_
私はこれについての素敵なイントロチュートリアルに出くわしました
http://backreference.org/2010/03/26/tuntap-interface-tutorial/
ソースtarballが付属しています。
それはこの質問と同じGoogleの結果のセットにありました。 :-)