linux下网络传输(模拟路由器)

1.项目目的:实现开发板和计算机之间的通信。
2.项目描述:路由器项目可以获取通信双方的MAC地址,通过修改ICMP包来实现数据的转发,从而实现不同网段的通信。除此之外,还可以通过过滤ARP缓存表来实现防火墙的功能,并可以实时打印网卡信息和ARP缓存表。在程序运行过程中路由器可以Ping开发板或者主机来检查线路。
3.所用技术:
使用原始套接字Socket抓取链路层数据包。
通过文件IO的库函数,用链表的相关操作实现IP过滤配置文档。 
对ARP、ICMP数据包进行拆解和组装。

使用线程池来提高程序的运行效率

4.代码部分

get_interface.h

#ifndef GET_INTERFACE_H
#define GET_INTERFACE_H

#define MAXINTERFACES 16    /* 最大接口数 */

typedef struct interface{
	char name[20];		//接口名字
	unsigned char ip[4];		//IP地址
	unsigned char mac[6];		//MAC地址
	unsigned char netmask[4];	//子网掩码
	unsigned char br_ip[4];		//广播地址
	int  flag;			//状态
}INTERFACE;
extern INTERFACE net_interface[MAXINTERFACES];//接口数据

/******************************************************************
函	数:	int getinterface()
功	能:	获取接口信息
参	数:	无
*******************************************************************/
extern void getinterface();

/******************************************************************
函	数:	int get_interface_num()
功	能:	获取实际接口数量
参	数:	接口数量
*******************************************************************/
int get_interface_num();
#endif

get_interface.c

#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/ether.h>	
#include "get_interface.h"
int interface_num=0;//接口数量
INTERFACE net_interface[MAXINTERFACES];//接口数据

/******************************************************************
函	数:	int get_interface_num()
功	能:	获取接口数量
参	数:	无
*******************************************************************/
int get_interface_num(){
	return interface_num;
}
/******************************************************************
函	数:	int getinterface()
功	能:	获取接口信息
参	数:	无
*******************************************************************/
void getinterface(){
	struct ifreq buf[MAXINTERFACES];    /* ifreq结构数组 */
	struct ifconf ifc;                  /* ifconf结构 */
	
	int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	 /* 初始化ifconf结构 */
    ifc.ifc_len = sizeof(buf);
    ifc.ifc_buf = (caddr_t) buf;
 
    /* 获得接口列表 */
    if (ioctl(sock_raw_fd, SIOCGIFCONF, (char *) &ifc) == -1){
        perror("SIOCGIFCONF ioctl");
        return ;
    }
    interface_num = ifc.ifc_len / sizeof(struct ifreq); /* 接口数量 */
    printf("interface_num=%d\n\n", interface_num);
 	char buff[20]="";
	int ip;
	int if_len = interface_num;
    while (if_len-- > 0){ /* 遍历每个接口 */
        printf("%s\n", buf[if_len].ifr_name); /* 接口名称 */
        sprintf(net_interface[if_len].name, "%s", buf[if_len].ifr_name); /* 接口名称 */
		printf("-%d-%s--\n",if_len,net_interface[if_len].name);
        /* 获得接口标志 */
        if (!(ioctl(sock_raw_fd, SIOCGIFFLAGS, (char *) &buf[if_len]))){
            /* 接口状态 */
            if (buf[if_len].ifr_flags & IFF_UP){
                printf("UP\n");
				net_interface[if_len].flag = 1;
            }
            else{
                printf("DOWN\n");
				net_interface[if_len].flag = 0;
            }
        }else{
            char str[256];
            sprintf(str, "SIOCGIFFLAGS ioctl %s", buf[if_len].ifr_name);
            perror(str);
        }
 
        /* IP地址 */
        if (!(ioctl(sock_raw_fd, SIOCGIFADDR, (char *) &buf[if_len]))){
			printf("IP:%s\n",(char*)inet_ntoa(((struct sockaddr_in*) (&buf[if_len].ifr_addr))->sin_addr));
			bzero(buff,sizeof(buff));
			sprintf(buff, "%s", (char*)inet_ntoa(((struct sockaddr_in*) (&buf[if_len].ifr_addr))->sin_addr));
			inet_pton(AF_INET, buff, &ip);
			memcpy(net_interface[if_len].ip, &ip, 4);
		}else{
            char str[256];
            sprintf(str, "SIOCGIFADDR ioctl %s", buf[if_len].ifr_name);
            perror(str);
        }
 
        /* 子网掩码 */
        if (!(ioctl(sock_raw_fd, SIOCGIFNETMASK, (char *) &buf[if_len]))){
            printf("netmask:%s\n",(char*)inet_ntoa(((struct sockaddr_in*) (&buf[if_len].ifr_addr))->sin_addr));
			bzero(buff,sizeof(buff));
			sprintf(buff, "%s", (char*)inet_ntoa(((struct sockaddr_in*) (&buf[if_len].ifr_addr))->sin_addr));
			inet_pton(AF_INET, buff, &ip);
			memcpy(net_interface[if_len].netmask, &ip, 4);
        }else{
            char str[256];
            sprintf(str, "SIOCGIFADDR ioctl %s", buf[if_len].ifr_name);
            perror(str);
        }
 
        /* 广播地址 */
        if (!(ioctl(sock_raw_fd, SIOCGIFBRDADDR, (char *) &buf[if_len]))){
            printf("br_ip:%s\n",(char*)inet_ntoa(((struct sockaddr_in*) (&buf[if_len].ifr_addr))->sin_addr));
			bzero(buff,sizeof(buff));
			sprintf(buff, "%s", (char*)inet_ntoa(((struct sockaddr_in*) (&buf[if_len].ifr_addr))->sin_addr));
			inet_pton(AF_INET, buff, &ip);
			memcpy(net_interface[if_len].br_ip, &ip, 4);
        }else{
            char str[256];
            sprintf(str, "SIOCGIFADDR ioctl %s", buf[if_len].ifr_name);
            perror(str);
        }

        /*MAC地址 */
		if (!(ioctl(sock_raw_fd, SIOCGIFHWADDR, (char *) &buf[if_len]))){
			printf("MAC:%02x:%02x:%02x:%02x:%02x:%02x\n\n",
					(unsigned char) buf[if_len].ifr_hwaddr.sa_data[0],
					(unsigned char) buf[if_len].ifr_hwaddr.sa_data[1],
					(unsigned char) buf[if_len].ifr_hwaddr.sa_data[2],
					(unsigned char) buf[if_len].ifr_hwaddr.sa_data[3],
					(unsigned char) buf[if_len].ifr_hwaddr.sa_data[4],
					(unsigned char) buf[if_len].ifr_hwaddr.sa_data[5]);
			memcpy(net_interface[if_len].mac, (unsigned char *)buf[if_len].ifr_hwaddr.sa_data, 6);
		}else{
            char str[256];
            sprintf(str, "SIOCGIFHWADDR ioctl %s", buf[if_len].ifr_name);
            perror(str);
        }
    }//–while end
    close(sock_raw_fd);   //关闭socket
}

thread_pool.h

#ifndef __THREAD_POOL_H__
#define __THREAD_POOL_H__
#include <pthread.h>
 /*********************************************************************
* 任务回调函数,也可根据需要自行修改
*********************************************************************/
typedef void *(*pool_task_f)(void *arg);

/*********************************************************************
* 任务句柄
*********************************************************************/
typedef struct _task{
	pool_task_f process;/*回调函数,任务运行时会调用此函数,注意也可声明成其它形式*/
	void *arg;     /*回调函数的参数*/
	struct _task *next;
}pool_task;

/*********************************************************************
* 线程池句柄
*********************************************************************/
typedef struct
{
	pthread_t *threadid;		/* 线程号 */
	int threads_limit;			/* 线程池中允许的活动线程数目 */
	int destroy_flag;			/* 是否销毁线程池 , 0销毁,1不销毁*/
	pool_task *queue_head;	/* 链表结构,线程池中所有等待任务 */
	int task_in_queue;			/* 当前等待队列的任务数目 */
	pthread_mutex_t queue_lock;	/* 锁 */
	pthread_cond_t queue_ready;	/* 条件变量 */
}pool_t;
/*********************************************************************
*功能:		初始化线程池结构体并创建线程
*参数:		
			pool:线程池句柄
			threads_limit:线程池中线程的数量
*返回值:	无
*********************************************************************/
void pool_init(pool_t *pool, int threads_limit);

/*********************************************************************
*功能:		销毁线程池,等待队列中的任务不会再被执行,
			但是正在运行的线程会一直,把任务运行完后再退出
*参数:		线程池句柄
*返回值:	成功:0,失败非0
*********************************************************************/
int pool_uninit(pool_t *pool);

/*********************************************************************
*功能:		向线程池中添加一个任务
*参数:		
			pool:线程池句柄
			process:任务处理函数
			arg:任务参数
*返回值:	0
*********************************************************************/
int pool_add_task(pool_t *pool, pool_task_f process, void *arg);
#endif

thread_pool.c

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>

#include "thread_pool.h"

static void *pool_thread_server(void *arg);

/*********************************************************************
*功能:		初始化线程池结构体并创建线程
*参数:		
			pool:线程池句柄
			threads_limit:线程池中线程的数量
*返回值:	无
*********************************************************************/
void pool_init(pool_t *pool, int threads_limit)
{
	pool->threads_limit = threads_limit;
	pool->queue_head = NULL;
	pool->task_in_queue = 0;
	pool->destroy_flag = 0;
	/*创建存放线程ID的空间*/
	pool->threadid = (pthread_t *)calloc(threads_limit, sizeof(pthread_t));
	int i = 0;
	/*初始化互斥锁和条件变量*/
	pthread_mutex_init(&(pool->queue_lock), NULL);
	pthread_cond_init(&(pool->queue_ready), NULL);
	/*循环创建threads_limit个线程*/
	for (i = 0; i < threads_limit; i++){
		pthread_create(&(pool->threadid[i]), NULL, pool_thread_server, pool);
	}
	return;
}

/*********************************************************************
*功能:		销毁线程池,等待队列中的任务不会再被执行,
			但是正在运行的线程会一直,把任务运行完后再退出
*参数:		线程池句柄
*返回值:	成功:0,失败非0
*********************************************************************/
int pool_uninit(pool_t *pool)
{
	pool_task *head = NULL;
	int i;
	
	pthread_mutex_lock(&(pool->queue_lock));
	if(pool->destroy_flag)/* 防止两次调用 */
		return -1;
	pool->destroy_flag = 1;
	pthread_mutex_unlock(&(pool->queue_lock));
	/* 唤醒所有等待线程,线程池要销毁了 */
	pthread_cond_broadcast(&(pool->queue_ready));
	/* 阻塞等待线程退出,否则就成僵尸了 */
	for (i = 0; i < pool->threads_limit; i++)
		pthread_join(pool->threadid[i], NULL);
	free(pool->threadid);
	/* 销毁等待队列 */
	pthread_mutex_lock(&(pool->queue_lock));
	while(pool->queue_head != NULL){
		head = pool->queue_head;
		pool->queue_head = pool->queue_head->next;
		free(head);
	}
	pthread_mutex_unlock(&(pool->queue_lock));
	/*条件变量和互斥量也别忘了销毁*/
	pthread_mutex_destroy(&(pool->queue_lock));
	pthread_cond_destroy(&(pool->queue_ready));
	return 0;
}

/*********************************************************************
*功能:		向任务队列中添加一个任务
*参数:		
			pool:线程池句柄
			process:任务处理函数
			arg:任务参数
*返回值:	无
*********************************************************************/
static void enqueue_task(pool_t *pool, pool_task_f process, void *arg)
{
	pool_task *task = NULL;
	pool_task *member = NULL;
	
	pthread_mutex_lock(&(pool->queue_lock));
	
	if(pool->task_in_queue >= pool->threads_limit){
		printf("task_in_queue > threads_limit!\n");
		pthread_mutex_unlock (&(pool->queue_lock));
		return;
	}
	
	task = (pool_task *)calloc(1, sizeof(pool_task));
	assert(task != NULL);
	task->process = process;
	task->arg = arg;
	task->next = NULL;
	pool->task_in_queue++;
	member = pool->queue_head;
	if(member != NULL){
		while(member->next != NULL)	/* 将任务加入到任务链连的最后位置. */
			member = member->next;
		member->next = task;
	}else{
		pool->queue_head = task;	/* 如果是第一个任务的话,就指向头 */
	}
	printf("\ttasks %d\n", pool->task_in_queue);
	/* 等待队列中有任务了,唤醒一个等待线程 */
	pthread_cond_signal (&(pool->queue_ready));
	pthread_mutex_unlock (&(pool->queue_lock));
}

/*********************************************************************
*功能:		从任务队列中取出一个任务
*参数:		线程池句柄
*返回值:	任务句柄
*********************************************************************/
static pool_task *dequeue_task(pool_t *pool)
{
	pool_task *task = NULL;
	
	pthread_mutex_lock(&(pool->queue_lock));
	/* 判断线程池是否要销毁了 */
	if(pool->destroy_flag){
		pthread_mutex_unlock(&(pool->queue_lock));
		printf("thread 0x%lx will be destroyed\n", pthread_self());
		pthread_exit(NULL);
	}
	/* 如果等待队列为0并且不销毁线程池,则处于阻塞状态 */
	if(pool->task_in_queue == 0){
		while((pool->task_in_queue == 0) && (!pool->destroy_flag)){
			printf("thread 0x%lx is leisure\n", pthread_self());
			/* 注意:pthread_cond_wait是一个原子操作,等待前会解锁,唤醒后会加锁 */
			pthread_cond_wait(&(pool->queue_ready), &(pool->queue_lock));
		}
	}else{
		/* 等待队列长度减去1,并取出队列中的第一个元素 */
		pool->task_in_queue--;
		task = pool->queue_head;
		pool->queue_head = task->next;
		printf("thread 0x%lx received a task\n", pthread_self());
	}
	pthread_mutex_unlock(&(pool->queue_lock));
	return task;
}

/*********************************************************************
*功能:		向线程池中添加一个任务
*参数:		
			pool:线程池句柄
			process:任务处理函数
			arg:任务参数
*返回值:	0
*********************************************************************/
int pool_add_task(pool_t *pool, pool_task_f process, void *arg)
{
	enqueue_task(pool, process, arg);
	return 0;
}

/*********************************************************************
*功能:		线程池服务程序
*参数:		略
*返回值:	略
*********************************************************************/
static void *pool_thread_server(void *arg)
{
	pool_t *pool = NULL;
	
	pool = (pool_t *)arg;
	while(1){
		pool_task *task = NULL;
		task = dequeue_task(pool);
		/*调用回调函数,执行任务*/
		if(task != NULL){
			printf ("thread 0x%lx is busy\n", pthread_self());
			task->process(task->arg);
			free(task);
			task = NULL;
		}
	}
	/*这一句应该是不可达的*/
	pthread_exit(NULL);	 
	return NULL;
}

main.h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/if.h>				//struct ifreq
#include <sys/ioctl.h>			//ioctl、SIOCGIFADDR
#include <sys/socket.h>
#include <netinet/ether.h>		//ETH_P_ALL
#include <netpacket/packet.h>	//struct sockaddr_ll
#include <pthread.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <netinet/in.h>
#include "get_interface.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
typedef struct node{
	char ip_buf[20];
	char mac_buf[20];
	struct node *next;
}ROUTER;
typedef struct pNpde{
	int f_ip_1;
	int f_ip_2;
	int f_ip_3;
	int f_ip_4;
	char f_ip_buf[20];
	struct pNpde *next;
}FILTER;

ROUTER *head=NULL;//初始化头结点
FILTER *phead=NULL;//初始化防火墙头结点
int fp;

void link_creat_head(ROUTER **p_head,ROUTER *p_new);
ROUTER* link_search_ip(ROUTER *head,char *ip);
ROUTER* link_search_mac(ROUTER *head,char *mac);
void link_init(ROUTER *head);
void link_print(ROUTER *head);
void link_free(ROUTER *head);
void  RecvData(int sockfd);
void SendData(int sockfd,char *dest_ip,char *recvbuf);
//---------------------------------------------------------
void ShowMenue();
void SetFirewall();
void LookFireWall();
void fire_creat_head(FILTER **p_head,FILTER *p_new);
void ReadFile();
FILTER* fire_search_ip(FILTER *head,char *ip);

mian.c

#include "main.h"
#include "thread_pool.h"
void * m_read(void *arg)//线程一
{
	int sockfd=(int )arg;
	RecvData(sockfd);
}
void * m_infor(void *arg)//线程二
{
	int sockfd=(int )arg;
	while(1)
	{
		//printf("命令:");
		fflush(stdout);
		char buf_order[50]="";
		fgets(buf_order,sizeof(buf_order),stdin);
		buf_order[strlen(buf_order)-1]='\0';
		if(strcmp(buf_order,"help")==0)
		{
			ShowMenue();
			continue;
		}
		if(strcmp(buf_order,"arp")==0)//查看路由器arp表
		{
			link_print(head);
			
			break;
		}
		if(strcmp(buf_order,"ifconfig")==0)//查看路由器网卡信息
		{
			printf("%s:\n",net_interface[1].name);
			printf("ip:%s\n",net_interface[1].ip);
			printf("mac:%s\n",net_interface[1].mac);
			printf("netmask:%s\n",(char *)net_interface[1].netmask);
			printf("\n");
			printf("%s:\n",net_interface[2].name);
			printf("ip:%s\n",net_interface[2].ip);
			printf("mac:%s\n",net_interface[2].mac);
			printf("netmask:%s\n",net_interface[2].netmask);
			
		}
		if(strcmp(buf_order,"firewall")==0)//设置防火墙
		{
			SetFirewall(fp);
			continue;
		}
		if(strcmp(buf_order,"lsfire")==0)//查看防火墙
		{
			LookFireWall();
			continue;
		}
		else
		{
			continue;
		}
	}
	
	close(fp);
}
//接受数据

void thread_pool_demo(void *arg)
{
	int sockfd=(int )arg;
	pool_t pool;
	pool_init(&pool, 2);//初始化一个线程池,其中创建2个线程
	pool_add_task(&pool, m_read, (void *)sockfd);//线程一
	pool_add_task(&pool, m_infor, (void *)sockfd);//线程二
}
int main()
{
	//1.创建原始套接字
	int sockfd=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
	if(sockfd<0)
	{
		 perror("socket");
	}
	fp= open("./fireip",O_RDWR|O_CREAT,0777);//存放IP列表的文件
	getinterface();
	get_interface_num();
	ReadFile();//读取文件中的过滤IP
	thread_pool_demo((void *)sockfd);
	while(1);
	//pool_uninit(&pool);//删除线程池
}
//显示菜单
void ShowMenue()
{
	printf("**********************************\n");
	printf("*           请按以下命令输入     *\n");
	printf("*    help:	打印帮助信息		 *\n");
	printf("*     arp:	查看路由器的arp表	 *\n");
	printf("*ifconfig:	查看路由器网卡信息	 *\n");
	printf("*firewall:	设置防火墙		     *\n");
	printf("*  lsfire:	查看防火墙		     *\n");
	printf("**********************************\n");
}
//查看防火墙
void LookFireWall()
{
	FILTER *f_mov=phead;
	if(phead==NULL)
	{
		printf("没有设置防火墙\n");
		return;
	}
	
	while(f_mov!=NULL)
	{
		printf("ip:%s\n",f_mov->f_ip_buf);
		f_mov=f_mov->next;
	}
}
//设置防火墙
void SetFirewall()
{
	char fire_ip[20];
	printf("请输入要添加到防火墙中的IP\n");
	fgets(fire_ip,sizeof(fire_ip),stdin);
	fire_ip[strlen(fire_ip)-1]='\0';
	FILTER * p_new=(FILTER*)malloc(sizeof(FILTER));//申请一个新节点
	sscanf(fire_ip,"%d:%d:%d:%d",&(p_new->f_ip_1),&(p_new->f_ip_2),&(p_new->f_ip_3),&(p_new->f_ip_4));
	strcpy(p_new->f_ip_buf,fire_ip);
	fire_creat_head(&phead,p_new);
	//printf("%d %d %d %d",(p_new->f_ip_1),(p_new->f_ip_2),(p_new->f_ip_3),(p_new->f_ip_4));
	//把IP以4个字节的方式存到文件中
	write(fp,&(p_new->f_ip_1),sizeof(int)); 
	write(fp,&(p_new->f_ip_2),sizeof(int));
	write(fp,&(p_new->f_ip_3),sizeof(int));
	write(fp,&(p_new->f_ip_4),sizeof(int));
}
//防火墙创建结点
void fire_creat_head(FILTER **p_head,FILTER *p_new)
{
	FILTER *p_mov=*p_head;
	if(*p_head==NULL)				//当第一次加入链表为空时,head执行p_new
	{
		*p_head=p_new;
		p_new->next=NULL;
	}
	else	//第二次及以后加入链表
	{		
		while(p_mov->next!=NULL)
		{
			p_mov=p_mov->next;	//找到原有链表的最后一个节点
		}	
		p_mov->next=p_new;		//将新申请的节点加入链表
		p_new->next=NULL;
	}
}

//根据IP在防火墙里面查看
FILTER* fire_search_ip(FILTER *p_head,char *ip)
{
	FILTER *p_mov=p_head;
	while(p_mov!=NULL)
	{
		if(strcmp(p_mov->f_ip_buf,ip)==0)
			return p_mov;
		else
			p_mov=p_mov->next;
	}
	return NULL;
}
//读取文件中的内容并且组成IP
void ReadFile()
{
	int ret=0;
	char buf[1024]="";
	char IP_buf[1024]="";
	int i=0;
	FILTER * p_new=(FILTER*)malloc(sizeof(FILTER));//申请一个新节点
	do
	{
		
		//把4个IP字符段组成字符串
		i++;
		//memset(buf,0,sizeof(buf));
		if(i==1)
		{
			ret = read(fp,&(p_new->f_ip_1),sizeof(int));
		}
		if(i==2)
		{
			ret = read(fp,&(p_new->f_ip_2),sizeof(int));
		}
		if(i==3)
		{
			ret = read(fp,&(p_new->f_ip_3),sizeof(int));
		}
		if(i==4)
		{
			ret = read(fp,&(p_new->f_ip_4),sizeof(int));
			sprintf(p_new->f_ip_buf,"%d:%d:%d:%d\n",(int)(p_new->f_ip_1),(int)(p_new->f_ip_2),(int)(p_new->f_ip_3),(int)(p_new->f_ip_4));
			fire_creat_head(&phead,p_new);
			p_new=(FILTER*)malloc(sizeof(FILTER));//申请一个新节点
			i=0;
		}
		
		//使用读到的数据
	}while(ret>0);//ret:实际读到的字节数,如果ret=0,说明后面没有内容了,就不用再读了,所以退出循环
}
//----------------------------------------------
//给链表添加一个节点	
void link_creat_head(ROUTER **p_head,ROUTER *p_new)
{
	ROUTER *p_mov=*p_head;
	if(*p_head==NULL)				//当第一次加入链表为空时,head执行p_new
	{
		*p_head=p_new;
		p_new->next=NULL;
	}
	else	//第二次及以后加入链表
	{		
		while(p_mov->next!=NULL)
		{
			p_mov=p_mov->next;	//找到原有链表的最后一个节点
		}	
		p_mov->next=p_new;		//将新申请的节点加入链表
		p_new->next=NULL;
	}
}
//根据查找节点
ROUTER* link_search_ip(ROUTER *p_head,char *ip)
{
	ROUTER *p_mov=p_head;
	while(p_mov!=NULL)
	{
		if(strcmp(p_mov->ip_buf,ip)==0)//&&strlen(p_mov->mac_buf)!=0
			return p_mov;
		else
			p_mov=p_mov->next;
	}
	return NULL;
}
//根据mac查找节点
ROUTER* link_search_mac(ROUTER *p_head,char *mac)
{
	ROUTER *p_mov=p_head;
	while(p_mov!=NULL)
	{
		if(strcmp(p_mov->mac_buf,mac)==0)//&&strlen(p_mov->ip_buf)!=0)
			return p_mov;
		else
			p_mov=p_mov->next;
	}
	return NULL;
}
//遍历链表
void link_print(ROUTER *p_head)
{
	ROUTER *p_mov=p_head;
	while(p_mov!=NULL)
	{
		printf("ip:%s mac:%s\n",p_mov->ip_buf,p_mov->mac_buf);
		p_mov=p_mov->next;
	}
	
}
//链表的释放
void link_free(ROUTER *p_head)
{
	ROUTER *pb;
	while(p_head!=NULL)
	{
		pb=p_head;
		p_head=p_head->next;
		free(pb);
	}
}
void  RecvData(int sockfd)
{
	char a8_mac[20]="";//源Mac地址,发送端Mac地址
	char a8_ip[20]="";//源IP地址
	char pc_ip[20]="";//目的端IP地址
	char pc_mac[40]="";//目的端mac地址
	while(1)
	{
		//处理ARP请求包,保存源IP,源mac
		unsigned char recv_buf[2048]="";
		int len=recvfrom(sockfd,recv_buf,2048,0,NULL,NULL);
		if(recv_buf[12]==0x08 && recv_buf[13]==0x06)//进入ARP段
		{
				sprintf(a8_mac,"%02x:%02x:%02x:%02x:%02x:%02x",recv_buf[22],recv_buf[23],recv_buf[24],recv_buf[25],recv_buf[26],recv_buf[27]);
				sprintf(a8_ip,"%d:%d:%d:%d\n",recv_buf[28],recv_buf[29],recv_buf[30],recv_buf[31]);
				if(link_search_ip(head,a8_ip)==NULL)//链表为空
				{
					ROUTER * p_new=(ROUTER*)malloc(sizeof(ROUTER));//申请一个新节点
					strcpy(p_new->mac_buf,a8_mac);
					strcpy(p_new->ip_buf,a8_ip);
					link_creat_head(&head,p_new);
					//link_print(head);
				}
				//link_print(head);
		}
		if(recv_buf[12]==0x08 && recv_buf[13]==0x00)//进入IP段
		{
			//if(recv_buf[23]==0x01)//接收ICMP包,获得PC端IP地址
			{
				sprintf(pc_ip,"%d:%d:%d:%d\n",recv_buf[30],recv_buf[31],recv_buf[32],recv_buf[33]);
				if(link_search_ip(head,pc_ip)==NULL)//链表为空
				{
					//发送数据获到PC端mac地址
					SendData(sockfd,pc_ip,recv_buf);
				}else
				{
					ROUTER* p_new_link=link_search_ip(head,pc_ip);
					if(strlen(p_new_link->mac_buf)!=0)
					{
						//修改接收到的ICMP包
						sscanf(p_new_link->mac_buf,"%02x:%02x:%02x:%02x:%02x:%02x",(int*)&recv_buf[0],(int*)&recv_buf[1],
						(int*)&recv_buf[2],(int*)&recv_buf[3],(int*)&recv_buf[4],(int*)&recv_buf[5]);//更改ICMP包 目的地址
						
						
						if(strncmp("10",pc_ip,2)==0)
						{
							memcpy(recv_buf+6,net_interface[2].mac,6);
							struct ifreq ethreq; 
							bzero(ðreq,sizeof(ethreq));
							strcpy(ethreq.ifr_name,net_interface[2].name);
							ioctl(sockfd,SIOCGIFINDEX,ðreq);
							struct sockaddr_ll sll;
							bzero(&sll,sizeof(sll));
							sll.sll_ifindex=ethreq.ifr_ifindex;
							if(fire_search_ip(phead,pc_ip)==NULL)
							{
								sendto(sockfd,recv_buf,len,0,(struct sockaddr*)&sll, sizeof(sll));
							}
						}
						if(strncmp("192",pc_ip,3)==0)
						{
							memcpy(recv_buf+6,net_interface[1].mac,6);
							struct ifreq ethreq; 
							bzero(ðreq,sizeof(ethreq));
							strcpy(ethreq.ifr_name,net_interface[1].name);
							ioctl(sockfd,SIOCGIFINDEX,ðreq);
							struct sockaddr_ll sll;
							bzero(&sll,sizeof(sll));
							sll.sll_ifindex=ethreq.ifr_ifindex;
							if(fire_search_ip(phead,pc_ip)==NULL)
							{
								sendto(sockfd,recv_buf,len,0,(struct sockaddr*)&sll, sizeof(sll));
							}
						}
				 
					}
					
				
				}
			}
		}
		//link_print(head);
	}
}
void SendData(int sockfd,char *dest_ip,char *recvbuf)
{
	//路由器向PC端发送改完的Arp包获取目的端的Mac地址
	  //1.组包,准备数据
	unsigned char send_buf[42]={
	//dest_mac
	0xff,0xff,0xff,0xff,0xff,0xff,
	//src_mac,eth1的网关mac地址0x00,0x0C,0x29,0x7F,0x50,0x79,
	0x00,0x00,0x00,0x00,0x00,0x00,
	//type
	0x08,0x06,
	//arp
	0x00,0x01,
	0x08,0x00,
	0x06,0x04,
	0x00,0x01,//请求,两个字节
	0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,
	//目的端口的ip地址
	recvbuf[30],recvbuf[31],recvbuf[32],recvbuf[33]
	};
	memcpy(send_buf+6,net_interface[2].mac,6);
	memcpy(send_buf+22,net_interface[2].mac,6);
	memcpy(send_buf+22+6,net_interface[2].ip,4);
	 //选择eth1网关,并发送数据
	//printf("%s\n",dest_ip);

	if(strncmp("10",dest_ip,2)==0)
	{
		struct ifreq ethreq; 
		bzero(ðreq,sizeof(ethreq));
		strcpy(ethreq.ifr_name,net_interface[2].name);
		ioctl(sockfd,SIOCGIFINDEX,ðreq);
		struct sockaddr_ll sll;
		bzero(&sll,sizeof(sll));
		sll.sll_ifindex=ethreq.ifr_ifindex;
		if(fire_search_ip(phead,dest_ip)==NULL)
		{
			sendto(sockfd,send_buf,42,0,(struct sockaddr*)&sll, sizeof(sll));
		}
	}
	if(strncmp("192",dest_ip,3)==0)
	{
		struct ifreq ethreq; 
		bzero(ðreq,sizeof(ethreq));
		strcpy(ethreq.ifr_name,net_interface[1].name);
		ioctl(sockfd,SIOCGIFINDEX,ðreq);
		struct sockaddr_ll sll;
		bzero(&sll,sizeof(sll));
		sll.sll_ifindex=ethreq.ifr_ifindex;
		if(fire_search_ip(phead,dest_ip)==NULL)
		{
			sendto(sockfd,send_buf,42,0,(struct sockaddr*)&sll, sizeof(sll));
		}
	}

}

makefile

CC = gcc  
MAINC = get_interface.c
AA = thread_pool.c
BB = main.c
EXEC = main
CFLAGS = -lpthread -ldl

main:  
	@$(CC)  $(MAINC) $(AA) $(BB) -o $(EXEC) $(CFLAGS) 
clean:
	@rm $(EXEC) -rf
run:
	@sudo ./$(EXEC)
	

猜你喜欢

转载自blog.csdn.net/qq_35703848/article/details/79723884