TAPデバイス間のブリッジ転送

昨日TAPデバイスが認識出来たので2つのTAPデバイスをブリッジさせるコードを書いた。昔作ったツールの評価用にこれが欲しかったのだ。
書いてみると今度はさくっと動いた。コードは以下のような感じ

#include <net/if.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define max(a,b) ((a)>(b) ? (a):(b))

int tap_alloc(char *dev)
{

  struct ifreq ifr;
  int fd, err;

  if( (fd = open("/dev/net/tun", O_RDWR)) < 0 )
    return -1;

  memset(&ifr, 0, sizeof(ifr));

  /* Flags: IFF_TUN   - TUN device (no Ethernet headers) 
   *        IFF_TAP   - TAP device  
   *
   *        IFF_NO_PI - Do not provide packet information  
   */ 
  ifr.ifr_flags = IFF_TAP; 
  if( *dev )
    strncpy(ifr.ifr_name, dev, IFNAMSIZ);

  if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
    close(fd);
    return err;
  }
  strcpy(dev, ifr.ifr_name);
  return fd;
}              

int main()
{
  char ifname0[] = "tap0";
  char ifname1[] = "tap1";
  int fd0;
  int fd1;
  int fm; 
  fd_set fds;

  int len;
  char buf[1024];

  fd0 = tap_alloc(ifname0);
  fd1 = tap_alloc(ifname1);

  fm = max(fd0, fd1) + 1;

  while(1)
    {
      FD_ZERO(&fds);

      FD_SET(fd0,&fds);
      FD_SET(fd1,&fds);

      select(fm,&fds, NULL, NULL, NULL);

      if(FD_ISSET(fd0, &fds)){

	len = read(fd0,buf,sizeof(buf)); 
	write(fd1,buf,len);
      }
      if(FD_ISSET(fd1, &fds)){
	len = read(fd1,buf,sizeof(buf));
	write(fd0,buf,len);
      }		

    }
}

確認方法

  • 前もって/sbin/modprobe tunでtunモジュールを立ち上げておく
  • 本プログラムを実行
  • /sbin/ifconfig -aでtap0とtap1が見えることを確認
  • ifconfigでtap0とtap1にIPアドレスを割り当て
  • tap0のIPアドレスARPエントリを登録しておいて、tap0の同一ネットワークの別IPにtelnetを仕掛けてみる
  • tap1側はtcpdumpを流しておく
  • 結果は以下。tap0から送出されたSYNパケットがtap1にブリッジされていることが確認出来る
10:25:49.011218 IP 192.168.2.1.2304 > 192.168.2.100.telnet: S
 2006705718:2006705718(0) win 5840
 
        0x0000:  4510 003c fc4d 4000 4006 b8a8 c0a8 0201  E..<.M@.@.......
        0x0010:  c0a8 0264 0900 0017 779b e636 0000 0000  ...d....w..6....
        0x0020:  a002 16d0 1e54 0000 0204 05b4 0402 080a  .....T..........
        0x0030:  000f 2632 0000 0000 0103 0303            ..&2........

I made a code to bridge between two tap devices. This code will help evaluating my networking tool.