zoukankan      html  css  js  c++  java
  • Linux下的TUN/TAP编程

    linux下实现虚拟网卡
    我们在使用VMWARE的虚拟化软件时经常会发现它们能都能虚拟出一个网卡,貌似很神奇的技术,其实在Linux下很简单,有两种虚拟设

    备,TUN时点对点的设备,tap表示以太网设备的,做为虚拟网卡驱动,Tun/tap驱动程序的数据接收和发送并不直接和真实网卡打交道,而是通

    过用户态来转交。在linux下,要实现核心态和用户态数据的交互,有多种方式:可以通用socket创建特殊套接字,利用套接字实现数据交

    互;通过proc文件系统创建文件来进行数据交互;还可以使用设备文件的方式,访问设备文件会调用设备驱动相应的例程,设备驱动本身就

    是核心态和用户态的一个接口,Tun/tap驱动就是利用设备文件实现用户态和核心态的数据交互。

    #include <unistd.h>
    #include <stdio.h>
    #include <curses.h>
    #include <string.h>
    #include <assert.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <signal.h>
    #include <unistd.h>
    #include <linux/if_tun.h>
    #include <netinet/in.h>
    #include <sys/ioctl.h>
    #include <sys/time.h>
    #include <linux/if.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <errno.h>
    #include <fcntl.h>  
    int tun_creat(char *dev,int flags)
    {
     struct ifreq ifr;
     int fd,err;
     assert(dev != NULL);
     if((fd = open ("/dev/net/tun",O_RDWR))<0) //you can replace it to tap to create tap device.
      return fd;
     memset(&ifr,0,sizeof (ifr));
     ifr.ifr_flags|=flags;
     if(*dev != '/0')
      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()
    {
     int tun,ret;
     char tun_name[IFNAMSIZ];
     unsigned char buf[4096];
     tun_name[0]='/0';
     tun = tun_creat(tun_name,IFF_TAP|IFF_NO_PI);
     if(tun<0)
     {
      perror("tun_create");
      return 1;
     }
     printf("TUN name is %s/n",tun_name);
            while (1) {
                    unsigned char ip[4];

                     ret = read(tun, buf, sizeof(buf));
                    if (ret < 0)
                            break;
                    memcpy(ip, &buf[12], 4);
                    memcpy(&buf[12], &buf[16], 4);
                    memcpy(&buf[16], ip, 4);
                     buf[20] = 0;
                    *((unsigned short*)&buf[22]) += 8;
                    printf("read %d bytes/n", ret);
                     ret = write(tun, buf, ret);
                    printf("write %d bytes/n", ret);
            }
     return 0;
    }

    另开启一个终端

    路由配置:

    ifconfig devname 10.0.0.1 up;    //10.0.0.1是本虚拟网卡的IP地址,uP是激活该网卡

    route add -net 10.0.0.2 netmask 255.255.255.255 dev devname

    ping 10.0.0.2

    开始测试

  • 相关阅读:
    HDU 1272 小希的迷宫 (并查集)
    HDU 5723 Abandoned country (最小生成树 + dfs)
    HDU 5744 Keep On Movin (贪心)
    探索Redis设计与实现2:Redis内部数据结构详解——dict
    探索Redis设计与实现1:Redis 的基础数据结构概览
    重新学习Mysql数据13:Mysql主从复制,读写分离,分表分库策略与实践
    重新学习MySQL数据库12:从实践sql语句优化开始
    重新学习MySQL数据库11:以Java的视角来聊聊SQL注入
    重新学习MySQL数据库10:MySQL里的那些日志们
    重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系
  • 原文地址:https://www.cnblogs.com/heidsoft/p/3525788.html
Copyright © 2011-2022 走看看