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)