虛擬網卡程序設計

一、創建設備並攔截數據包

1、打開虛擬設備tun   (存在opentun文件夾下)

opentun.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>

/*******************代碼說明***********************
打開tun/tap設備  written by fys 2012/4/18
/*******************代碼說明***********************

/*
所在頭文件:自定義函數
函數原型:int tuntap_create (const char *dev);
函數功能:打開TUN/TAP設備,返回設備文件描述符號
入口參數:設備名字符串,"tun"或"tap"
出口參數:設備文件描述符號
*/
int tuntap_create (const char *dev)  //dev可以是字符串“tun”,也可以是“tap”
{
    struct ifreq ifr;//ifreq存放接口信息
    int fd;
    char *device = "/dev/net/tun";

    /*打開設備文件描述*/
    if ((fd = open (device, O_RDWR)) < 0)
        fprintf(stderr, "Cannot open TUN/TAP dev %s", device);
    /*打開設備文件描述*/
    memset (&ifr,0, sizeof (ifr));
    ifr.ifr_flags = IFF_NO_PI;
    /*判斷參數dev是何種設備*/
    if (!strncmp (dev, "tun", 3))//比較dev與tun的前三個字符
    { 
        ifr.ifr_flags |= IFF_TUN;
    }
    else if (!strncmp (dev, "tap", 3))
    {
        ifr.ifr_flags |= IFF_TAP;
    }
    else
    {
        fprintf(stderr, "I don't recognize device %s as a TUN or TAP device",dev);
    }
    /*判斷參數dev是何種設備*/
    if (strlen (dev) > 3)/* unit number specified? */
        strncpy (ifr.ifr_name, dev, IFNAMSIZ);

    if(ioctl(fd, TUNSETIFF, (void *)&ifr) < 0)//打開虛擬網卡
        fprintf(stderr, "Cannot ioctl TUNSETIFF %s", dev);

    if(ioctl(fd, TUNSETNOCSUM, (void *)&ifr) &lt; 0)//不校驗和
        fprintf(stderr, "Cannot ioctl TUNSETIFF %s", dev);

    fprintf(stderr, "TUN/TAP device %s opened\n", ifr.ifr_name);
    return fd;//返回設備文件描述符號
}

int main()
{
    tuntap_create("tun");//打開tun設備,返回tun文件描述符號
    system("ifconfig tun0 up");
    while(1);//使設備一直處於打開狀態,死循環。
    return 0;
}

opentun.sh

#!/bin/bash
#開啓tun設備
gcc -o opentun.exe opentun.c
./opentun.exe

2、TUN/TAP設備結構

struct tun_struct { char name[8]; //設備名 unsigned long flags; //區分tun和tap設備 struct fasync_struct *fasync; //文件異步通知結構 wait_queue_head_t read_wait; //等待隊列 struct net_device dev; //linux 抽象網絡設備結構 struct sk_buff_head txq; //網絡緩衝區隊列 struct net_device_stats stats; //網卡狀態信息結構 };

struct net_device結構是linux內核提供的統一網絡設備結構,定義了系統統一的訪問接口。

 

Tun/tap驅動中實現的網卡驅動的處理例程:

static int tun_net_open(struct net_device *dev);
static int tun_net_close(struct net_device *dev);
static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev);//數據包發送例程
static void tun_net_mclist(struct net_device *dev);//設置多點傳輸的地址鏈表
static struct net_device_stats *tun_net_stats(struct net_device *dev);//當一個應用程序需要知道網絡接口的一些統計數據時,可調用該函數,如ifconfig、netstat等。
int tun_net_init(struct net_device *dev);//網絡設備初始例程

 

字符設備部分:

在Linux中,字符設備和塊設備統一以文件的方式訪問,訪問它們的接口是統一的,都是使用open()函數打開設備文件或普通文件,用read()和write()函數實現讀寫文件等等。Tun/tap驅動定義的字符設備的訪問接口如下:

static struct file_operations tun_fops = {
owner: THIS_MODULE,
llseek: tun_chr_lseek,
read tun_chr_read,
write: tun_chr_write,
poll: tun_chr_poll,
ioctl: tun_chr_ioctl,
open: tun_chr_open,
release: tun_chr_close,
fasync: tun_chr_fasync
};

 

在內核中利用misc_register() 函數將該驅動註冊爲非標準字符設備驅動,提供字符設備具有的各種程序接口。代碼摘自linux-2.4.20\linux-2.4.20\drivers\net\tun.c

static struct miscdevice tun_miscdev= { TUN_MINOR, "net/tun", &tun_fops }; int __init tun_init(void) { … if (misc_register(&tun_miscdev)) { printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR); return -EIO; } return 0; }

 

3、

截獲發往某個地址的數據

OpenTunAndRead.c

#include &lt;stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>

/*******************代碼說明***********************
打開tun/tap設備 讀取數據  written by fys 2012/4/18
需要在另一個終端寫入數據!否則本程序不能順利執行!
/*******************代碼說明***********************

/*
所在頭文件:自定義函數
函數原型:int tuntap_create (const char *dev);
函數功能:打開TUN/TAP設備,返回設備文件描述符號
入口參數:設備名字符串,"tun"或"tap"
出口參數:設備文件描述符號
*/
int tuntap_create (const char *dev)  //dev可以是字符串“tun”,也可以是“tap”
{
    struct ifreq ifr;//ifreq存放接口信息
    int fd;
    char *device = "/dev/net/tun";

    /*以讀寫方式打開device設備,返回描述符*/
    if ((fd = open (device, O_RDWR)) < 0)
        fprintf(stderr, "Cannot open TUN/TAP dev %s", device);
    /*以讀寫方式打開device設備,返回描述符*/
    memset (&ifr,0, sizeof (ifr));
    ifr.ifr_flags = IFF_NO_PI;
    /*判斷參數dev是何種設備*/
    if (!strncmp (dev, "tun", 3))//比較dev與tun的前三個字符
    { 
        ifr.ifr_flags |= IFF_TUN;
    }
    else if (!strncmp (dev, "tap", 3))
    {
        ifr.ifr_flags |= IFF_TAP;
    }
    else
    {
        fprintf(stderr, "I don't recognize device %s as a TUN or TAP device",dev);
    }
    /*判斷參數dev是何種設備*/
    if (strlen (dev) > 3)/* unit number specified? */
        strncpy (ifr.ifr_name, dev, IFNAMSIZ);
/*
使用ioctl()函數操作字符設備文件描述符,將調用字符設備中tun_chr_ioctl 來設置已經open好的tun/tap設備,如果設置標誌爲TUNSETIFF,則調用tun_set_iff() 函數,此函數將完成很重要的一步操作,就是對網卡驅動進行註冊register_netdev(&tun-&gt;dev),網卡驅動的各個處理例程的掛接在open操作時由tun_chr_open()函數初始化好了。
*/

    if(ioctl(fd, TUNSETIFF, (void *)&ifr) < 0)//打開虛擬網卡
        fprintf(stderr, "Cannot ioctl TUNSETIFF %s", dev);

    if(ioctl(fd, TUNSETNOCSUM, (void *)&ifr) &lt; 0)//不校驗和
        fprintf(stderr, "Cannot ioctl TUNSETIFF %s", dev);

    fprintf(stderr, "TUN/TAP device %s opened\n", ifr.ifr_name);
    return fd;//返回設備文件描述符號
}

/*
所在頭文件:自定義
函數原型:int WriteToTun(int tunfd,char *buffer);
函數功能:向tun設備文件中寫數據
入口參數:tun設備文件描述符號,要寫入tun的字符串指針buffer,寫入tun的字節數SizeOfBuffer
出口參數:共寫入tun的字節數
*/
int WriteToTun(int tunfd,char *buffer,int SizeOfBuffer)
{
    int CountWriteToTun;
    CountWriteToTun = write(tunfd,buffer,SizeOfBuffer);
    printf("write %d bytes to tun\n\n",CountWriteToTun);
    return CountWriteToTun;
}

int main()
{
    int tuntapfd,CountReadFromTun;
    int i;

    char DataWriteToTun[]="hello world";//寫入tun設備的數據
    unsigned char DataReadFromTun[4096];
    tuntapfd = tuntap_create("tun");//打開tun設備,返回tun文件描述符號
    system("ifconfig tun0 up");
    while(1)
    {
        CountReadFromTun = read(tuntapfd,DataReadFromTun,sizeof(DataReadFromTun));
        for(i = 0 ; i &lt; CountReadFromTun; i++)
        {
            if ( i % 16 == 0 ) printf("\n");
            printf("%02x",DataReadFromTun[i]);//按16進制輸出,長度不足2,補零
        }
        printf("\nCountReadFromTun:%dBytes\n",CountReadFromTun);   
    }
    //while(1);//使設備一直處於打開狀態,死循環。
    return 0;
}

 

OpenTunAndRead.sh

#!/bin/bash
gcc -o OpenTunAndRead.exe OpenTunAndRead.c
./OpenTunAndRead.exe

NetConfigAndPing.sh

#!/bin/bash
#配置虛擬網卡以及需要截獲的IP
ifconfig tun0 10.10.10.1 up  #整個網絡,路由表中無法查詢的包都送到全零網絡中
route add 10.10.10.2 dev tun0  #該route命令指明目標爲10.10.10.2的包由網卡tun0路由出去
route add 119.75.217.56 dev tun0 #截獲所有發向www.baidu.com的數據
route add 218.30.66.102 dev tun0 #截獲所有發向www.sina.com的數據
#ping 10.10.10.2
#route add 219.245.89.102 dev tun0

 

操作:

1、一個終端執行 ./OpenTunAndRead.sh
2、另一個終端執行./NetConfigAndPing.sh
3、在網頁中輸入地址119.75.217.56則虛擬網卡會截獲發往該地址的數據

(要截獲的地址數據在NetConfigAndPing.sh中設置)

 

 

4500003c06a040004006038d0a0a0a01
da1e4266
94f200509af8a7e000000000
a00216d086cc0000020405b40402080a
007aa1400000000001030305
CountReadFromTun:60Bytes

0a0a0a01  10.10.10.1 虛擬網卡地址

da1e4266  218.30.66.102 www.sina.com地址

二、http://blog.csdn.net/stonesharp/article/details/6563713#

TUN/TAP 虛擬網絡設備的原理比較簡單,他在Linux內核中添加了一個TUN/TAP虛擬網絡設備的驅動程序和一個與之相關連的字符設備 /dev/net/tun,字符設備tun作爲用戶空間和內核空間交換數據的接口。當內核將數據包發送到虛擬網絡設備時,數據包被保存在設備相關的一個隊 列中,直到用戶空間程序通過打開的字符設備tun的描述符讀取時,它纔會被拷貝到用戶空間的緩衝區中,其效果就相當於,數據包直接發送到了用戶空間。通過 系統調用write發送數據包時其原理與此類似。
值得注意的是:一次read系統調用,有且只有一個數據包被傳送到用戶空間,並且當用戶空間的緩衝區比較小時,數據包將被截斷,剩餘部分將永久地消失,write系統調用與read類似,每次只發送一個數據包。所以在編寫此類程序的時候,請用足夠大的緩衝區,直接調用系統調用read/write,避免採用C語言的帶緩存的IO函數。

 

三、MN VINC攔截數據包併發送給HA,HA改變包地址後再將包發給MN

CaptureSendReceivePackets.c

/***********************程序說明***********************
打開tun設備,將虛擬設備文件/dev/tun中的數據顯示在終端上;
以socket將虛擬設備文件中的數據傳給HA,
測試:接收HA發來的數據並寫入虛擬網卡。
written by fys 2012/5/8
************************程序說明***********************/

#include &lt;stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>

#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>

#define REMOTEPORT 4567          //REMOTEPORT即HA開放的接收MN數據的端口
#define REMOTEIP "219.245.89.102" //REMOTEIP即HA的IP,本機測試用127.0.0.1

/*
所在頭文件:自定義函數
函數原型:int tuntap_create (const char *dev);
函數功能:打開TUN/TAP設備,返回設備文件描述符號
入口參數:設備名字符串,"tun"或"tap"
出口參數:設備文件描述符號
*/
int tuntap_create (const char *dev)  //dev可以是字符串“tun”,也可以是“tap”
{
    struct ifreq ifr;//ifreq存放接口信息
    int fd;
    char *device = "/dev/net/tun";

    /*以讀寫方式打開device設備,返回描述符*/
    if ((fd = open (device, O_RDWR)) < 0)
        fprintf(stderr, "Cannot open TUN/TAP dev %s", device);
    /*以讀寫方式打開device設備,返回描述符*/
    memset (&ifr,0, sizeof (ifr));
    ifr.ifr_flags = IFF_NO_PI;
    /*判斷參數dev是何種設備*/
    if (!strncmp (dev, "tun", 3))//比較dev與tun的前三個字符
    { 
        ifr.ifr_flags |= IFF_TUN;
    }
    else if (!strncmp (dev, "tap", 3))
    {
        ifr.ifr_flags |= IFF_TAP;
    }
    else
    {
        fprintf(stderr, "I don't recognize device %s as a TUN or TAP device",dev);
    }
    /*判斷參數dev是何種設備*/
    if (strlen (dev) > 3)/* unit number specified? */
        strncpy (ifr.ifr_name, dev, IFNAMSIZ);

    if(ioctl(fd, TUNSETIFF, (void *)&ifr) < 0)//打開虛擬網卡
        fprintf(stderr, "Cannot ioctl TUNSETIFF %s", dev);

    if(ioctl(fd, TUNSETNOCSUM, (void *)&ifr) &lt; 0)//不校驗和
        fprintf(stderr, "Cannot ioctl TUNSETIFF %s", dev);

    fprintf(stderr, "TUN/TAP device %s opened\n", ifr.ifr_name);
    return fd;//返回設備文件描述符號
}

/*
所在頭文件:自定義
函數原型:int WriteToTun(int tunfd,char *buffer);
函數功能:向tun設備文件中寫數據
入口參數:tun設備文件描述符號,要寫入tun的字符串指針buffer,寫入tun的字節數SizeOfBuffer
出口參數:共寫入tun的字節數
*/
int WriteToTun(int tunfd,char *buffer,int SizeOfBuffer)
{
    int CountWriteToTun;
    CountWriteToTun = write(tunfd,buffer,SizeOfBuffer);
    printf("write %d bytes to tun\n\n",CountWriteToTun);
    return CountWriteToTun;
}

int main()
{
    /*與tun相關的變量定義*/
    int tuntapfd;               //打開的虛擬設備的文件描述符
    int CountReadFromTun,CountWriteToTun,CountSendToHA,CountReceiveFromHA;
    int tempi,tempj;
    int IDReadFromTun = 0;
    unsigned char DataReadFromTun[4096];
    unsigned char DataReceiveFromHA[4096];
    unsigned char DataSendToHA[4096];
    /*與tun相關的變量定義*/

    /*與socket相關的變量定義*/
    int sockfd;                  //套接字描述符
    struct sockaddr_in addr;  //套接字數據類型,用來存放HA目的套接字
    int addr_len;             //變量addr的長度
    /*與socket相關的變量定義*/

    /*創建套接字*/
    if(( sockfd = socket(AF_INET,SOCK_DGRAM,0))&lt;0)
    {
        perror("error");
        exit(1);
    }
    else
    {
        printf("socket created successfully!\n");
        printf("socket id:%d\n",sockfd);
        printf("remote ip:%s\n",REMOTEIP);
        printf("remote port: %d\n\n",REMOTEPORT);
    }
    /*創建套接字*/
    addr_len=sizeof(struct sockaddr_in);
    bzero(&addr,sizeof(addr));

    /*HA套接字地址*/
    addr.sin_family=AF_INET;
    addr.sin_port=htons(REMOTEPORT);
    addr.sin_addr.s_addr=inet_addr(REMOTEIP);
    /*HA套接字地址*/

    tuntapfd = tuntap_create("tun");  //打開tun設備,返回tun文件描述符號
    system("ifconfig tun0 up");       //使虛擬網卡工作
    while(1)
    {
        //unsigned char MyPingIP[4];
        /*從TUN中讀取數據*/
        CountReadFromTun = read(tuntapfd,DataReadFromTun,sizeof(DataReadFromTun));
        if(CountReadFromTun&lt;0)break;
        /*從TUN中讀取數據*/
        /*將從TUN中讀取的數據顯示到終端*/
        for(tempi = 0 ; tempi &lt; CountReadFromTun; tempi++)
        {
            if ( tempi % 16 == 0 ) printf("\n");
            printf("%02x",DataReadFromTun[tempi]);
            //x表示無符號16進制數字並以小寫表示,02表示長度不足2,前面補零
            //例如:若DataReadFromTun[0]存儲的數爲00000110 ,則輸出爲 06
        }
        printf("\nAbove data is from tun of MN!\n");
        printf("Count bytes read from tun of MN:%dBytes\n",CountReadFromTun);
        /*將從TUN中讀取的數據顯示到終端*/
        /*將TUN中的數據發送給HA*/
        CountSendToHA = sendto(sockfd,DataReadFromTun,CountReadFromTun,0,(struct sockaddr *)&addr,addr_len);
        printf("Count bytes send to HA:%dBytes\n",CountSendToHA);
        /*將TUN中的數據發送給HA*/
        /*接收從HA發來的數據*/
        CountReceiveFromHA = recvfrom(sockfd,DataReceiveFromHA,sizeof(DataReceiveFromHA),0,(struct sockaddr *)&addr,&addr_len);
        /*接收從HA發來的數據*/

        /*將從HA接收的數據顯示到終端*/
        for(tempj = 0 ; tempj &lt; CountReceiveFromHA; tempj++)
        {
            if ( tempj % 16 == 0 ) printf("\n");
            printf("%02x",DataReceiveFromHA[tempj]);
        }
        printf("\nAbove data is from HA!\n");
        printf("Count bytes receive from HA:%dBytes\n",CountReceiveFromHA);
        /*將從HA接收的數據顯示到終端*/
        /*將從MN接收的數據寫入虛擬網卡*/
        CountWriteToTun = write(tuntapfd,DataReceiveFromHA,CountReceiveFromHA);
        printf("Count bytes write to tun:%dbytes\n", CountWriteToTun);
        /*將交換源目的地址後的數據寫入TUN*/

        printf("The serial number of the data:%d\n",IDReadFromTun);
            IDReadFromTun++;
    }//end while

    return 0;
}

 

HA.c

/***********************程序說明***************************
這是HA的程序,接收CaptureAndSendPackets.c(即MN)發送的數據包,
顯示在終端上,並寫入虛擬網卡,測試:將改變源目的地址後發送給MN
written by fys 2012/5/8
************************程序說明***************************/

#include &lt;stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <fcntl.h>
#include <sys/types.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>
#include <pthread.h> 
#include <sys/time.h>

#define LOCALPORT 4567

int tuntap_create (const char *dev)  //dev可以是字符串“tun”,也可以是“tap”
{
    struct ifreq ifr;//ifreq存放接口信息
    int fd;
    char *device = "/dev/net/tun";

    /*以讀寫方式打開device設備,返回描述符*/
    if ((fd = open (device, O_RDWR)) < 0)
        fprintf(stderr, "Cannot open TUN/TAP dev %s", device);
    /*以讀寫方式打開device設備,返回描述符*/
    memset (&ifr,0, sizeof (ifr));
    ifr.ifr_flags = IFF_NO_PI;
    /*判斷參數dev是何種設備*/
    if (!strncmp (dev, "tun", 3))//比較dev與tun的前三個字符
    { 
        ifr.ifr_flags |= IFF_TUN;
    }
    else if (!strncmp (dev, "tap", 3))
    {
        ifr.ifr_flags |= IFF_TAP;
    }
    else
    {
        fprintf(stderr, "I don't recognize device %s as a TUN or TAP device",dev);
    }
    /*判斷參數dev是何種設備*/
    if (strlen (dev) > 3)/* unit number specified? */
        strncpy (ifr.ifr_name, dev, IFNAMSIZ);

    if(ioctl(fd, TUNSETIFF, (void *)&ifr) &lt; 0)//打開虛擬網卡
        fprintf(stderr, "Cannot ioctl TUNSETIFF %s", dev);

    if(ioctl(fd, TUNSETNOCSUM, (void *)&ifr) &lt; 0)//不校驗和
        fprintf(stderr, "Cannot ioctl TUNSETIFF %s", dev);

    fprintf(stderr, "TUN/TAP device %s opened\n", ifr.ifr_name);
    return fd;//返回設備文件描述符號
}

int WriteToTun(int tunfd,char *buffer,int SizeOfBuffer)
{
    int CountWriteToTun;
    CountWriteToTun = write(tunfd,buffer,SizeOfBuffer);
    printf("write %d bytes to tun\n\n",CountWriteToTun);
    return CountWriteToTun;
}

int main(int argc,char *argv[])
{
    int tuntapfd;
    int sockfd;
    int IDofDataFromMN=0; //從MN接收的組序號,即接收的第幾組數據
    int CountFromMN;      //從MN接收的一組數據的字節數
    int CountSendToMN;
    int CountWriteToTun;
    int CountReadFromTun;
    int tempi;
    int tempj;
    unsigned char DataFromMN[4096];//存放從MN發來的數據
    unsigned char DataReadFromTun[4096];
    unsigned char DataSendToMN[4096];
    unsigned char tempIP[4];

    struct sockaddr_in addr;
    int addr_len;
    /*創建本地套接字*/
    if((sockfd=socket(AF_INET,SOCK_DGRAM,0))&lt;0)
    {
        perror("error");
        exit(1);
    }
    else
    {
        printf("socket created successfully!\n");
        printf("socked id:%d\n",sockfd);
    }
    /*創建本地套接字*/
    addr_len = sizeof(struct sockaddr_in);
    bzero(&addr,sizeof(addr));

    /*本地套接字屬性*/
    addr.sin_family = AF_INET;
    addr.sin_port = htons(LOCALPORT);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    /*本地套接字屬性*/
    /*綁定本地套接字的端口和IP*/
    if(bind(sockfd,(struct sockaddr *)&addr,sizeof(addr))&lt;0)
    {
        perror("error");
        exit(1);
    }
    else
    {
        printf("bind successfully!\n");       
        printf("local port:%d \n\n",LOCALPORT);
    }
    /*綁定本地套接字的端口和IP*/

    /*創建並打開虛擬網卡*/
    tuntapfd = tuntap_create("tun"); 
    system("ifconfig tun0 up");      
    /*創建並打開虛擬網卡*/

    while(1)
    {
        bzero(DataFromMN,sizeof(DataFromMN));
        CountFromMN = recvfrom(sockfd,DataFromMN,sizeof(DataFromMN),0,(struct sockaddr *)&addr,&addr_len);
        /*將從MN接收的數據顯示在終端上*/
        for(tempi = 0 ; tempi &lt; CountFromMN; tempi++)
        {
            if ( tempi % 16 == 0 ) printf("\n");
            printf("%02x",DataFromMN[tempi]);
            //x表示無符號16進制數字並以小寫表示,02表示長度不足2,前面補零
            //例如:若DataReadFromTun[0]存儲的數爲00000110 ,則輸出爲 06
        }
        printf("\nAbove data is from MN!\n");
        printf("Received message length:%dBytes\n",CountFromMN);
        printf("Received message from:%s\n",inet_ntoa(addr.sin_addr));
        /*將從MN接收的數據顯示在終端上*/

        /*將從MN接收的數據寫入虛擬網卡*/
        CountWriteToTun = write(tuntapfd,DataFromMN,CountFromMN);
        printf("Count bytes write to tun:%dbytes\n", CountWriteToTun);
        /*將從MN接收的數據寫入虛擬網卡*/

        /*從TUN中讀取CN傳來的數據DataReadFromTun即CN傳到HA的數據???*/
        //這段語句塊可能出錯,上面的語句塊向虛擬網卡寫入數據,此處讀出的數據是什麼?(前面寫入的orCN發來的?)
        //CountReadFromTun = read(tuntapfd,DataReadFromTun,sizeof(DataReadFromTun));
        //if(CountReadFromTun&lt;0) break;
        /*從TUN中讀取CN傳來的數據DataReadFromTun即CN傳到HA的數據???*/
        /*將從TUN中讀取的包即CN發到HA的包??顯示到終端上*/
        //printf("Data read from tun:");
        //for(tempj = 0 ; tempj &lt; CountReadFromTun; tempj++)
        //{
        //    if ( tempj % 16 == 0 ) printf("\n" );
        //    printf("%02x",DataReadFromTun[tempj]);
        //}
        /*將從TUN中讀取的包即CN發到HA的包??顯示到終端上*/

        /*測試:改變接收到包源目的地址*/   
        memcpy(tempIP, &DataFromMN[12], 4);
        memcpy(&DataFromMN[12], &DataFromMN[16], 4);
        memcpy(&DataFromMN[16], tempIP, 4);
        /*測試:改變接收到包源目的地址*/       
        /*實際發送給MN的數據改變此處的賦值*/
        //測試時是直接將DataFromMN的源目的地址交換後給DataSendToMN的
        DataSendToMN = DataFromMN;       
        /*實際發送給MN的數據改變此處的賦值*/

        /*測試:將TUN中數據(這是測試語句塊,還不是CN發來的)發送給MN*/
        CountSendToMN = sendto(sockfd,DataSendToMN,sizeof(DataSendToMN),0,(struct sockaddr *)&addr,addr_len);
        printf("Count send to MN from HA:%dBytes\n",CountSendToMN);
        /*測試:將TUN中數據(這是測試語句塊,還不是CN發來的)發送給MN*/

        printf("The serial number of the data:%d\n\n",IDofDataFromMN);
            IDofDataFromMN++;

    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章