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)