注意:该文章中的arp应答部分是有问题的,由于作者现在已经没有实验环境无法再进行修正了,望看该文章的人注意一下

关于tun设备启用tap网卡,就是启用一个字符设备,使用open函数得到一个tun设备的文件描述符,可以使用write和read,或者pcap接口读写网卡,以下的部分为tun设备的控制代码,包括了网卡mac ip mask设置等,主要就是ioctl函数的使用

#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/if_tun.h>
#include <linux/if.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>#include <linux/if_ether.h>
#include <netinet/if_ether.h>
#include <net/if_arp.h>
#include <net/ethernet.h>
#include <net/route.h>static char * interface_name_cut (char *buf, char **name)
{  char *stat; while (*buf == ' ')                                                                                                                                                                                                                     buf++;  *name = buf;  stat = strrchr (buf, ':');  *stat = '\0';  return *name;
}//check whether the network card exists.
int check_phy_name(char *interface)
{  FILE *fp;  char buf[PROCBUFSIZ];  char *name;  fp = fopen (_PATH_PROC_NET_DEV, "r");  if (fp == NULL) {     printf("open proc file error\n");  goto EXIT1;}     fgets (buf, PROCBUFSIZ, fp);  fgets (buf, PROCBUFSIZ, fp);  while (fgets (buf, PROCBUFSIZ, fp) != NULL) {     interface_name_cut(buf, &name);  if(strcmp(interface,name)==0) {fclose(fp);return 1;  }} EXIT1:fclose(fp);  return -1;
} //设置ip和mask
static int set_addr(char *dev_name, char *ip, int flag)
{struct ifreq ifr;struct sockaddr_in sin;int sockfd;sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd == -1) {perror("tap");goto EXIT2;}snprintf(ifr.ifr_name, sizeof(dev_name), "%s", dev_name);/* Read interface flags */if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {perror(ifr.ifr_name);goto EXIT2;}memset(&sin, 0, sizeof(struct sockaddr));sin.sin_family = AF_INET;inet_aton(ip, &sin.sin_addr);memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr));if (ioctl(sockfd, flag, &ifr) < 0) {perror(ifr.ifr_name);goto EXIT2;}close(sockfd);return 1;EXIT2:close(sockfd);exit(-1);
}static int get_tun_mac(char *dev_name, uint8_t *tun_mac)
{struct ifreq ifr;int sockfd, ret;uint8_t *mac;sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd == -1) {perror("tap");goto EXIT1;}snprintf(ifr.ifr_name, sizeof(dev_name), "%s", dev_name);ret = ioctl(sockfd, SIOCGIFHWADDR, &ifr);if (ret == -1) {printf("get tun mac error\n");goto EXIT1;}   mac = (uint8_t *)ifr.ifr_hwaddr.sa_data;memcpy(tun_mac, mac, 6);close(sockfd);return 1;EXIT1:close(sockfd);exit(-1);
}static int set_tun_mac(char *dev_name, uint8_t *tun_mac)
{struct ifreq ifr;int sockfd, ret;sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd == -1) {perror("tap");goto EXIT;}snprintf(ifr.ifr_name, sizeof(dev_name), "%s", dev_name);/* Read interface flags */if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {perror(ifr.ifr_name);goto EXIT;}ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;memcpy(&ifr.ifr_hwaddr.sa_data, tun_mac, 6);ret = ioctl(sockfd, SIOCSIFHWADDR, &ifr);if (ret == -1) {printf("set tun mac error\n");goto EXIT;} close(sockfd);return 1;EXIT:close(sockfd);return -1;
}static int set_routing(char *dst, char *gw, char *genmask, char *dev)
{int sockfd;struct rtentry route;struct sockaddr_in *addr;int err = 0;if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){perror("set routing");close(sockfd);return -1;}memset(&route, 0, sizeof(route));route.rt_dev = dev;addr = (struct sockaddr_in*)&route.rt_gateway;addr->sin_family = AF_INET;addr->sin_addr.s_addr = inet_addr(gw);addr = (struct sockaddr_in*) &route.rt_dst;addr->sin_family = AF_INET;addr->sin_addr.s_addr = inet_addr(dst);addr = (struct sockaddr_in*) &route.rt_genmask;addr->sin_family = AF_INET;inet_aton(genmask, &addr->sin_addr);route.rt_flags = RTF_UP | RTF_GATEWAY;route.rt_metric = 0;if ((err = ioctl(sockfd, SIOCADDRT, &route)) != 0) {perror("ioctl routing");close(sockfd);return -1;}close(sockfd);return 1;
}static int set_gateway(char ip[16])
{int sockfd;struct sockaddr_in sockaddr;struct rtentry rt;sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){perror("set gateway");close(sockfd);exit(-1);} memset(&rt, 0, sizeof(struct rtentry));memset(&sockaddr, 0, sizeof(struct sockaddr_in));sockaddr.sin_family = AF_INET;sockaddr.sin_port = 0;inet_aton(ip, &sockaddr.sin_addr);memcpy (&rt.rt_gateway, &sockaddr, sizeof(struct sockaddr_in));((struct sockaddr_in *)&rt.rt_dst)->sin_family = AF_INET;((struct sockaddr_in *)&rt.rt_genmask)->sin_family = AF_INET;rt.rt_flags = RTF_GATEWAY;if (ioctl(sockfd, SIOCADDRT, &rt) < 0){perror("ioctl(SIOCADDRT) error in set_default_route\n");close(sockfd);exit(-1);}close(sockfd);return 1;
}int interface_up(char *name)
{int fd;struct ifreq ifr;fd = socket(AF_INET, SOCK_DGRAM, 0);if (fd < 0){fprintf(stderr, "tun : interface sokcet open failed!\n");return -1;}strcpy(ifr.ifr_name, name);if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0){perror("ioctl");exit(-1);}ifr.ifr_flags |= IFF_UP;if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0){perror("ioctl");exit(-1);}return 1;
}int interface_down(char *name)
{int fd;struct ifreq ifr;fd = socket(AF_INET, SOCK_DGRAM, 0);if (fd < 0){fprintf(stderr, "tun : interface sokcet open failed!\n");return -1;}strcpy(ifr.ifr_name, name);if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0){perror("ioctl");return -1;}ifr.ifr_flags &= ~IFF_UP;if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0){perror("ioctl");return -1;}return 1;
}//arp应答就是填充一个mac地址然后对换mac,将数据包发出
static int build_arp_response(int tunfd, char *origin_pkts,int pkts_len)
{char buf[128]={0};unsigned char mymac[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};struct ethhdr *eth_request = (struct ethhdr *)origin_pkts;struct ethhdr *eth_reply = (struct ethhdr *)buf;//原本的代码部分存在问题,所以删除了,如果有需要的自行添加,//arp的应答只需要修改下行流量的目标mac即可,将ff:ff:ff:ff:ff:ff换成mymac//调换ip和mac然后write写数据到tunfd即可return 0;
}int main(int argc, char *argv[])
{struct ifreq ifr;int tunfd;//检测主网卡是否存在 -1 no existif (check_phy_name("tap") == -1)  {memset(&ifr, 0, sizeof(ifr));ifr.ifr_flags |= (IFF_TAP | IFF_NO_PI);strncpy(ifr.ifr_name, "tap", IFNAMSIZ);tunfd = open("/dev/net/tun", O_RDWR|O_NONBLOCK);if (tunfd == -1){fprintf(stderr, "tun : /dev/net/tun open failed\n");return -1;}int ior;ior = ioctl(tunfd, TUNSETIFF, (void *)&ifr);if (ior < 0){fprintf(stderr, "tun : virtual network create failed\n");return -1;}}unsigned char mac[6] = {0x43, 0x42, 0x15, 0x57, 0x45, 0x65};char ip[] = "192.168.0.1"char mask[] = "255.255.255.0";set_tap_mac("tap", mac);if (set_addr("tap", ip, SIOCSIFADDR) == -1)                       //set ipreturn -1;if (set_addr("tap", mask, SIOCSIFNETMASK) == -1)  //set netmaskreturn -1;if (interface_up("tap") == -1){fprintf(stderr, "virtual network up failed!\n");return -1;}if (set_routing("0.0.0.0", ip, "0.0.0.0", "tap") == -1){fprintf(stderr, "virtual network set routing failed!\n");return -1;}get_tap_mac("tap", mac);printf("tun mac : %x:%x:%x:%x:%x:%x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);return 1;
}

启用tun设备开启tap虚拟网卡功能相关推荐

  1. linux上使用tun/tap设备模拟一个虚拟网卡,并将该虚拟网卡连接到新创建的网桥上

    目录 linux上使用tun/tap设备模拟一个虚拟网卡,并将该虚拟网卡连接到新创建的网桥上 一.tun/tap设备简介 二.在linux上使用tun/tap设备模拟一个虚拟网卡 三. 创建网桥连接到 ...

  2. tun/tap虚拟网卡收发机制解析

    文章目录 收发机制原理 共性 虚拟网卡和物理网卡的通信 网络传输包格式 接收机制 发送机制 服务器端的转发机制 本章要研究的是openxxx的收发原理,实际上研究就是研究tun/tap网卡驱动的相关原 ...

  3. tun/tap虚拟网卡

    简介 虚拟网卡Tun/tap驱动是一个开源项目,支持很多的类UNIX平台,OpenVPN和Vtun都是基于它实现隧道包封装.本文将介绍tun/tap驱动的使用并分析虚拟网卡tun/tap驱动程序在li ...

  4. linux下使用tun/tap虚拟网卡

    tun/tap虚拟网卡介绍 tun是一种虚拟网络设备,tun设备一端连接着用户程序,一端连接着内核协议栈,任何时候从协议栈发到tun网卡的数据都能从用户程序中读到,而从用户程序写入/dev/net/t ...

  5. PCI设备驱动与虚拟网卡驱动源码分析

    虚拟网卡驱动例程 #include<linux/module.h> #include<linux/sched.h> #include<linux/kernel.h> ...

  6. Linux TUN/TAP 虚拟网卡编程入门https://backreference.org/2010/03/26/tuntap-interface-tutorial/...

    原文: https://backreference.org/2010/03/26/tuntap-interface-tutorial/ (为防和谐,下文中p=屁) Tun/Tap interface ...

  7. 虚拟网卡 TUN/TAP 驱动程序设计原理

    简介 虚拟网卡Tun/tap驱动是一个开源项目,支持很多的类UNIX平台,OpenVPN和Vtun都是基于它实现隧道包封装.本文将介绍tun/tap驱动的使用并分析虚拟网卡tun/tap驱动程序在li ...

  8. linux虚拟网卡tun,Centos7 创建虚拟网卡(tun/tap)

    创建网卡.创建网桥并建立桥接 [root@kolla ~]# cat create.sh create_br(){ tunctl -t storage -u root brctl addbr virb ...

  9. linux 虚拟网卡 源码,Linux的虚拟网卡TUN和TAP

    TUN/TAP 提供了给用户空间程序的包的接收和传输,它可以看成是简单的点对点设备或是 以太网设备.它不是从物理设备接收包,而是从用户空间程序接收包.它发送包不是通过物 理设备来发送包,而是将这些包写 ...

最新文章

  1. 阿里云centos配置nginx和nodejs
  2. 反季大清仓,最低仅需34.9元
  3. (周星驰版)学习委托的最好实例 (转载+自己补充了注释)
  4. origin安装包_作图技巧|研究生需要会的20个Origin操作,作图又快又好看(二)...
  5. 针对C64x+的一些优化经验
  6. promise 和 Observable 的区别
  7. struts2中一些常用的写法 记录
  8. matlab绘图基础,matlab绘图基础
  9. win7设置固定IP重启后无法上网,ipconfig显示为自动配置IPV4 169.254的地址
  10. ASCII码表_全_完整版
  11. Smobiler客户端会话
  12. Pojo、Po、Vo、Dto的含义
  13. 基础篇——人工智能相关方向学习路线指引
  14. 关于点焊,你知道多少
  15. 切入点和切入点表达式(AOP面向切面编程)
  16. Python面试题大全总结
  17. BeanCopy和BeanCopier在实际开发中的使用(属性copy效率优化)
  18. 安装Arch(含输入法配置)
  19. 基于MRS-Hudi构建数据湖的典型应用场景介绍
  20. MBT测试实例:做个“机器人”,使其随机、持续的对“web页面”做交互性测试(二)涉及工具

热门文章

  1. matlab插值比较-griddata/interp2
  2. 【电气专业知识问答】 问:电厂中设置的系统安全装置有哪些?
  3. 人际交往中的9个锦囊妙计,书呆子也能学会!
  4. 一生必读经典书籍大全
  5. Python实现微信自动抢红包~再也不怕错过了
  6. Java进阶之多线程
  7. 【转】OpenCV人脸识别
  8. 域分析工具BloodHound使用教程
  9. contextMenuStrip的创建和使用
  10. 腾讯新一代企业级云数据库CynosDB(NewCDB)