タブインターフェイスからデータを読み取るには?

タブインターフェイスからデータを読み取るには?

ブリッジとチューニング/タップデバイスに問題があります。

実際、最大の問題は、コンパイルする前にブリッジとタブインターフェイスを作成しようとしていることです。私のコードはコンパイル時にこのインタフェースを使用する必要があります。私のプロジェクトコードからthe Contikihttps://github.com/contiki-os/contiki) コードがコンパイルされ、タブインタフェースと通信を生成するために使用されます。

コマンドを使用してソースコードを実行するとすべてがうまくいきsudoますが、前述のように最初にクリックインターフェイスを作成し、コマンドなしでコードを実行する必要がありますsudo

したがって、私のコードがコマンドを使用して実行されると、応答は次のようになりますsudoifconfig tap0

tap0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fc00::231  prefixlen 7  scopeid 0x0<global>
        inet6 fe80::cc9f:ddff:fe50:7d9a  prefixlen 64  scopeid 0x20<link>
        ether ce:9f:dd:50:7d:9a  txqueuelen 1000  (Ethernet)
        RX packets 50  bytes 12195 (12.1 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 52  bytes 7869 (7.8 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

この状態では、私のプロジェクトは正常に実行されます。

ただし、次のコマンドを使用してクリックインターフェイスを作成しようとしています。

sudo ip tuntap add mode tap tap0 user myusername
sudo ifconfig tap0 up
sudo ip link set tap0 up
sudo ip -6 address add fc00::231/7 dev tap0
sudo ip address add dev tap0 scope link fe80::cc9f:ddff:fe50:7d9a

それからifconfig tap0答えが来ます。

tap0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet6 fe80::cc9f:ddff:fe50:7d9a  prefixlen 128  scopeid 0x20<link>
        inet6 fc00::231  prefixlen 7  scopeid 0x0<global>
        ether 06:ea:8d:0e:66:74  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

だから、Contikiコードを修正した後、tap0インターフェイスを読み取ろうとします。

ret = read(fd, uip_buf, UIP_BUFSIZE);

ただし、ret値は-1です。 (sudoで実行するとint値が返されます。) tap0 インタフェースの状態を変更できればRUNNINGret値も取得できると思いましたが、どうすればいいかわかりません。

私が何をすべきかを知っている人はいますか?

注:tapdev6.cの修正

void
tapdev_init(void)
{
  printf("INIT TAP DEV!!!!!!!!!!!!!!!!! \n");
  net_fd = open(DEVTAP, O_RDWR);
  if(net_fd == -1) {
    perror("tapdev: tapdev_init: open");
    return;
  }

#ifdef __linux
  {
    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
    printf("INIT0 net_fd %d \n", net_fd);
    if (ioctl(/*net_fd*/4, TUNSETIFF, (void *) &ifr) < 0) {
        printf("INIT FAIL \n");
      perror("Unable to init tunnel interface\n");
      //exit(1);
    }
    printf("INIT1 net_fd %d \n", net_fd);
    ioctl(/*net_fd*/4, SIOCGIFHWADDR, &ifr);
    printf("INIT2 net_fd %d \n", net_fd);
  }
  /* Linux (ubuntu) */
char buf[256];
     snprintf(buf, sizeof(buf), "ip link set tap0 up");
     system(buf);
     PRINTF("%s\n", buf);
     snprintf(buf, sizeof(buf), "ip -6 address add fc00::231/7 dev tap0");
     system(buf);
     PRINTF("%s\n", buf);
     snprintf(buf, sizeof(buf), "ip -6 route add fc00::0/7 dev tap0");
     system(buf);
     PRINTF("%s\n", buf);

  /* freebsd */

    //try to set hw address
     // 12:bc:34:76:c9:2f
    ifr.ifr_hwaddr.sa_data[0] = 0x12;
    ifr.ifr_hwaddr.sa_data[1] = 0xbc;
    ifr.ifr_hwaddr.sa_data[2] = 0x34;
    ifr.ifr_hwaddr.sa_data[3] = 0x76;
    ifr.ifr_hwaddr.sa_data[4] = 0xc9;
    ifr.ifr_hwaddr.sa_data[5] = 0x2f;
  printf("Lan device %s\n", ifr.ifr_name);
  printf("LAN HW addr %02X:%02X:%02X:%02X:%02X:%02X\n",
          (unsigned char)ifr.ifr_hwaddr.sa_data[0],
          (unsigned char)ifr.ifr_hwaddr.sa_data[1],
          (unsigned char)ifr.ifr_hwaddr.sa_data[2],
          (unsigned char)ifr.ifr_hwaddr.sa_data[3],
          (unsigned char)ifr.ifr_hwaddr.sa_data[4],
          (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
#endif /* Linux */

  lasttime = 0;

}

ベストアンサー1

-ESUDO

真剣に、クリックインターフェイスの所有者を設定する必要があります。以下を試してください。

ip tuntap add tap0 mode tap user USER

USERユーザーが開いたハンドルを介して読み書きします/dev/net/tun。失敗した読み取りではなく、ioctl(TUNSETIFF)戻り値を確認することに気を付けていないようです。

opentap(ifname)これは、それを実行しているユーザーが正しい権限を持っていると仮定し、Tapインターフェースのfdハンドルを開く必要がある単純な関数です。

#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int opentap(char *ifn)
{
    int fd;
    struct ifreq ifr = { 0 };
    if (snprintf(ifr.ifr_name, sizeof ifr.ifr_name, "%s", ifn)
            >= sizeof ifr.ifr_name) {
        errno = ENAMETOOLONG; return -1;
    }
    if ((fd = open("/dev/net/tun", O_RDWR)) == -1) return -1;
    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
    if (ioctl(fd, TUNSETIFF, &ifr) == -1) {
        int e = errno; close(fd); errno = e; return -1;
    }
    return fd;
}

おすすめ記事