Recently, we have been studying the implementation of TCP/IP protocol. The establishment of the experimental platform requires a large number of network adapters, and tap and Tun are good choices. However, after the Tun module IOCTL is simply mounted in Ubuntu to start the device, you still cannot use tap/tun. Then google finally found a solution: Install tunctl and create an interface.
1. Download tunctl and decompress make & make install
2. sudo./tunctl-u root-T tap0
Then you can use ifconfig to configure tap0. Tap virtual ethernet device. Tun virtual network layer device.
Working principle of TAP/TUN:
We can see that we need to configure the IP address of the TAP/TUN to accept the data, and also need to configure the relevant route table items to route to our virtual network card.
Configure the nic and route
Sudo ifconfig tap0 192.168.0.1
Sudo route add-net 192.168.0.0 netmask 255.255.255.0 GW 192.168.0.1
Then we can program and implement the processing of the application.
The following is a simple Reader Program:
# Include <Linux/if_tun.h> # include <stdio. h> # include <unistd. h> # include <sys/socket. h> # include <sys/types. h> # include <fcntl. h> # include <sys/IOCTL. h> # include <Linux/if. h> # include <error. h> # include <string. h> // memset # include <ARPA/inet. h> // ntohs # define in # define out # define tapdev "/dev/NET/TUN" # define buffersize 1024 # define flag_tun 0x01 # define flag_tap0x02int tun_create (char * dev_type, char * dev_name/* null default */); int tun_echo (); int FD =-1; // file descriptor of the deviceunsigned char buffer [buffersize]; int buf_len = 0; int flag = 0; // parameter: argv [1]: "tap" or "tun" // argv [2]: name of the deviceint main (INT argc, char * argv []) {char * dev_name = NULL; If (argc <2) {printf ("Usage: cmd dev_type \ r \ n"); Return-1 ;} if (argc = 3 & strlen (argv [2]) <5) {dev_name = argv [2];} FD = tun_create (argv [1], dev_name ); if (FD <0) {return-1 ;}System ("sudo ifconfig tap0 192.168.0.1"); // configure the NIC
System ("sudo route add-net 192.168.0.0 netmask 255.255.255.0 GW 192.168.0.1"); // configure the route
Buf_len = read (FD, buffer, buffersize); While (buf_len> 0) {printf ("% d \ r \ n", buf_len ); /* deal with the data */showinfo (); // The result is simply output here. This function can be replaced with other application functions if (buf_len> = buffersize) {// buffer is fulledsleep (5); continue;} buf_len + = read (FD, buffer + buf_len, BUFFERSIZE-buf_len);} int tun_create (char * dev_type, char * dev_name) {struct ifreq IFR; If (FD = open (tapdev, o_rdwr) <0) {perror ("tap open error"); return- 1;} memset (& IFR, 0, sizeof (IFR); IFR. ifr_flags = iff_no_pi; If (! Strncmp (dev_type, "tun", 3) {IFR. ifr_flags | = iff_tun; flag | = flag_tun;} else if (! Strncmp (dev_type, "tap", 3) {IFR. ifr_flags | = iff_tap; flag | = flag_tap;} If (dev_name! = NULL) {strncpy (IFR. ifr_name, dev_name, strlen (dev_name) + 1);} If (IOCTL (FD, tunsetiff, (void *) & IFR) <0) {perror ("IOCTL error: "); Return-1;} printf (" % s is used \ r \ n ", IFR. ifr_name); Return FD;} int showinfo () {int I, offset; unsigned char out_buffer [120]; If (flag & flag_tun) {If (buf_len <20) {printf ("Too short packet! \ R \ n "); buf_len = 0; Return-1 ;}} else if (flag & flag_tap) {// process Ethernet header if (buf_len <14 + 20) {printf ("Too short packet! \ R \ n "); buf_len = 0; Return-1;} out_buffer [0] = '\ 0'; // destination MAC addressfor (offset = 0; offset <6; offset ++) sprintf (out_buffer + strlen (out_buffer), "% 2x. ", buffer [offset]); out_buffer [strlen (out_buffer)-1] = '\ 0'; printf (" DEST Mac: % s ", out_buffer ); // source MAC addressout_buffer [0] = '\ 0'; For (; offset <12; offset ++) sprintf (out_buffer + strlen (out_buffer), "% 2x. ", buffer [offset]); out_buffer [strlen (out_buffer)-1] = '\ 0'; printf (" source MAC: % s ", out_buffer ); printf ("Mac type: % d \ n", ntohs (buffer [offset]); offset + = 2; buf_len-= 14 ;} else {printf ("unknow packet \ r \ n"); buf_len = 0; Return-1;} // process the IP header, skip other options to process buf_len-= ntohs (buffer [Offset + 2]); // deal with the IP addressoffset + = 12; printf ("% d. % d. % d. % d \ r \ n ", buffer [offset], buffer [Offset + 1], buffer [Offset + 2], buffer [Offset + 3]); offset + = 4; printf ("% d. % d. % d. % d \ r \ n ", buffer [offset], buffer [Offset + 1], buffer [Offset + 2], buffer [Offset + 3]); Return 0 ;}
After compilation, run./A. Out tap with the following output:
The source MAC address is the virtual NIC address for verification:
The destination address should be set in IOCTL. The IP addresses are all 0.0.0.0. This is because it is not a normal IP packet, but ARP data, so there is no IP address.