How to interface with the Linux tun driver

后端 未结 3 1804
攒了一身酷
攒了一身酷 2020-12-13 04:56

I\'m having a hard time figuring this problem out - I am trying to write a program that will interact with the Linux tunnel driver. At a very basic level, I simply want to c

相关标签:
3条回答
  • 2020-12-13 05:36

    Read /usr/src/linux/Documentation/networking/tuntap.rst.

    You are supposed to open the /dev/net/tun device. A subsequent ioctl on the open fd will create the tun0 (or whatever you wish to name it) network interface. Linux's network interfaces do not correspond to any /dev/* device.

    0 讨论(0)
  • 2020-12-13 05:47

    There are no /dev/tunX device files. Instead, you open the /dev/net/tun and configure it via ioctl() to "point" to tun0. To show the basic procedure, I will create the TUN interface using the command line tool ip tun tap and then show the C code to read from that TUN device. So to create the tun interface via commands line:

    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
    

    Now we have tun0 created. To read / write packets to this interface from an user space program you need to interact with the /dev/net/tun device file using ioctl(). Here is an example that will read the packets arriving at the tun0 interface and print the size:

    #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;
    }
    
    0 讨论(0)
  • 2020-12-13 05:59

    I came across a nice intro tutorial about this

    http://backreference.org/2010/03/26/tuntap-interface-tutorial/

    It comes with a source tarball.

    It was in the same set of Google results as this question. :-)

    0 讨论(0)
提交回复
热议问题