注册 登录
自由的生活_软路由 返回首页

11的个人空间 https://bbs.routerclub.com/?499 [收藏] [复制] [分享] [RSS]

日志

LINUX 虚拟网卡tun例子

已有 1366 次阅读2012-10-2 20:39 | 网卡, LINUX

/**
 *  linux TUN 例子 代码来至
 *  http://hi.baidu.com/zkheartboy/blog/item/e96acf33508e4a40ad4b5f88.html和
 *  http://blog.csdn.net/Z_man/archive/2009/05/26/4216530.aspx
 *  建立一个tun0的虚拟网卡进行通信,程序关闭后将消失。
 *  ping 10.0.0.1
 *  Documentation/networking/tuntap.txt
 *  br_select.c bridge based on select system call.
 *  br_sigio.c  bridge based on async io and SIGIO signal.
 *  http://hi.baidu.com/zkheartboy/blog/item/e96acf33508e4a40ad4b5f88.html
 *  http://blogold.chinaunix.net/u3/114446/showart_2245279.html
 *  http://www.ibm.com/developerworks/cn/linux/l-tuntap/index.html
 */

  1. #include <fcntl.h>  
  2. #include <stdio.h>  
  3. #include <string.h>  
  4. #include <sys/socket.h>  
  5. #include <sys/ioctl.h>  
  6. #include <linux/if.h>  
  7. #include <linux/if_tun.h>  
  8. #include <sys/types.h>  
  9. #include <errno.h>  
  10. #include <net/route.h>  
  11.   
  12. /** 
  13.  *  激活接口 
  14.  */  
  15. int interface_up(char *interface_name)  
  16. {  
  17.     int s;  
  18.   
  19.     if((s = socket(PF_INET,SOCK_STREAM,0)) < 0)  
  20.     {  
  21.         printf("Error create socket :%m/n", errno);  
  22.         return -1;  
  23.     }  
  24.   
  25.     struct ifreq ifr;  
  26.     strcpy(ifr.ifr_name,interface_name);  
  27.   
  28.     short flag;  
  29.     flag = IFF_UP;  
  30.     if(ioctl(s, SIOCGIFFLAGS, &ifr) < 0)  
  31.     {  
  32.         printf("Error up %s :%m/n",interface_name, errno);  
  33.         return -1;  
  34.     }  
  35.   
  36.     ifr.ifr_ifru.ifru_flags |= flag;  
  37.   
  38.     if(ioctl(s, SIOCSIFFLAGS, &ifr) < 0)  
  39.     {  
  40.         printf("Error up %s :%m/n",interface_name, errno);  
  41.         return -1;  
  42.     }  
  43.   
  44.     return 0;  
  45.   
  46. }  
  47.   
  48. /** 
  49.  *  设置接口ip地址 
  50.  */  
  51. int set_ipaddr(char *interface_name, char *ip)  
  52. {  
  53.     int s;  
  54.   
  55.     if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0)  
  56.     {  
  57.         printf("Error up %s :%m/n",interface_name, errno);  
  58.         return -1;  
  59.     }  
  60.   
  61.     struct ifreq ifr;  
  62.     strcpy(ifr.ifr_name, interface_name);  
  63.   
  64.     struct sockaddr_in addr;  
  65.     bzero(&addr, sizeof(struct sockaddr_in));  
  66.     addr.sin_family = PF_INET;  
  67.     inet_aton(ip, &addr.sin_addr);  
  68.   
  69.     memcpy(&ifr.ifr_ifru.ifru_addr, &addr, sizeof(struct sockaddr_in));  
  70.   
  71.     if(ioctl(s, SIOCSIFADDR, &ifr) < 0)  
  72.     {  
  73.         printf("Error set %s ip :%m/n",interface_name, errno);  
  74.         return -1;  
  75.     }  
  76.   
  77.     return 0;  
  78. }  
  79.   
  80. /** 
  81.  *  创建接口 
  82.  */  
  83. int tun_create(char *dev, int flags)  
  84. {  
  85.     struct ifreq ifr;  
  86.     int fd, err;  
  87.   
  88.     if ((fd = open("/dev/net/tun", O_RDWR)) < 0)  
  89.     {  
  90.         printf("Error :%m/n", errno);  
  91.         return -1;  
  92.     }  
  93.   
  94.     memset(&ifr, 0, sizeof(ifr));  
  95.     ifr.ifr_flags |= flags;  
  96.   
  97.     if (*dev != '/0')  
  98.     {  
  99.         strncpy(ifr.ifr_name, dev, IFNAMSIZ);  
  100.     }  
  101.   
  102.     if ((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0)   
  103.     {  
  104.         printf("Error :%m/n", errno);  
  105.         close(fd);  
  106.         return -1;  
  107.     }  
  108.   
  109.     strcpy(dev, ifr.ifr_name);  
  110.   
  111.     return fd;  
  112. }  
  113.   
  114. /** 
  115.  *  增加到10.0.0.1的路由 
  116.  *  同命令:route add 10.0.0.1 dev tun0 
  117.  */  
  118. int route_add(char * interface_name)  
  119. {  
  120.     int skfd;  
  121.     struct rtentry rt;  
  122.   
  123.     struct sockaddr_in dst;  
  124.     struct sockaddr_in gw;  
  125.     struct sockaddr_in genmask;  
  126.   
  127.     memset(&rt, 0, sizeof(rt));  
  128.   
  129.     genmask.sin_addr.s_addr = inet_addr("255.255.255.255");  
  130.   
  131.     bzero(&dst,sizeof(struct sockaddr_in));  
  132.     dst.sin_family = PF_INET;  
  133.     dst.sin_addr.s_addr = inet_addr("10.0.0.1");  
  134.   
  135.     rt.rt_metric = 0;  
  136.     rt.rt_dst = *(struct sockaddr*) &dst;  
  137.     rt.rt_genmask = *(struct sockaddr*) &genmask;  
  138.   
  139.     rt.rt_dev = interface_name;  
  140.     rt.rt_flags = RTF_UP | RTF_HOST ;  
  141.   
  142.     skfd = socket(AF_INET, SOCK_DGRAM, 0);  
  143.     if(ioctl(skfd, SIOCADDRT, &rt) < 0)   
  144.     {  
  145.         printf("Error route add :%m/n", errno);  
  146.         return -1;  
  147.     }  
  148. }  
  149. int main(int argc, char *argv[])  
  150. {  
  151.     int tun, ret;  
  152.     char tun_name[IFNAMSIZ];  
  153.     unsigned char buf[4096];  
  154.     unsigned char ip[4];  
  155.   
  156.     tun_name[0] = '/0';  
  157.     tun = tun_create(tun_name, IFF_TUN | IFF_NO_PI);  
  158.     if (tun < 0)   
  159.     {  
  160.         return 1;  
  161.     }  
  162.     printf("TUN name is %s/n", tun_name);  
  163.   
  164.     //激活虚拟网卡增加到虚拟网卡的路由  
  165.     interface_up(tun_name);  
  166.     route_add(tun_name);  
  167.   
  168.     while (1) {  
  169.   
  170.         ret = read(tun, buf, sizeof(buf));  
  171.         printf("read %d bytes/n", ret);  
  172.         int i;  
  173.         for(i=0;i<ret;i++)  
  174.         {  
  175.           printf("%02x ",buf[i]);  
  176.         }  
  177.         printf("/n");  
  178.         if (ret < 0)  
  179.             break;  
  180.         memcpy(ip, &buf[12], 4);  
  181.         memcpy(&buf[12], &buf[16], 4);  
  182.         memcpy(&buf[16], ip, 4);  
  183.         buf[20] = 0;  
  184.         *((unsigned short*)&buf[22]) += 8;  
  185.         ret = write(tun, buf, ret);  
  186.         printf("write %d bytes/n", ret);  
  187.     }  
  188.   
  189.     return 0;  
  190. }  

测试方法:

1 先编译运行此程序,监听数据的读写。

2 开启另外一个终端,执行ping命令,就是本地发一个测试包到10.0.0.1

即可看到收到和接收的数据包IP包了。


路过

雷人

握手

鲜花

鸡蛋

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

QQ|Archiver|手机版|小黑屋|软路由 ( 渝ICP备15001194号-1|渝公网安备 50011602500124号 )

GMT+8, 2024-6-2 13:12 , Processed in 0.059677 second(s), 5 queries , Gzip On, Redis On.

Powered by Discuz! X3.5 Licensed

© 2001-2023 Discuz! Team.

返回顶部