使用C语言,模拟路由器的工作过程 您所在的位置:网站首页 路由器测试项目是什么 使用C语言,模拟路由器的工作过程

使用C语言,模拟路由器的工作过程

2023-12-05 16:09| 来源: 网络整理| 查看: 265

1.路由器

完成不同网段之间的通信,下面通过一个代码来具体演示路由器的工作过程 总结:这个项目耗时两天半完成,旨在理解原始套接字如何接收数据,发送数据。同时熟练使用sqlite3数据库 模拟两个不同网段进行通信,主要是进行ping的时候。 1.两个不同的网段再ping的时候,是ping不通的。 2.再ping其他网段的时候,首先是发送arp的请求包,然后再发送icmp数据包,arp来获取目的IP的MAC地址,如果能够找到这个mac地址,那么就能够组装到icmp数据包上,从而完成通信。 3.当发送icmp数据包的时候,到达我们所模拟的路由器的时候,查找arp缓存表中是否有对应IP的mac地址,如果有,那么就组装到目的mac上即可,没有就ping不同啦。

这个代码看看里面的内容就好,理解一下就行,实现起来硬件也需要进行改动,因为虚拟机和windows是同一个网段上的,本来就可以直接ping通,所以需要再加上两个网卡,将window上的网关改为虚拟机一端的ip,然后另两个端口再改成不一样的。。。

#include #include #include #include #include #include //recvfrom #include //ETH_P_ALL #include //inet_ntop #include //ifreq #include //ioctl #include //sockaddr_ll #include #include #include void show(void);//菜单函数 void * my_fun(void * arg);//线程的回调函数 //全局变量定义,方便线程使用 int sockfd; //套接字 int ret; //调用数据库是的返回值 char * errmsg; sqlite3 *db; char ** dbResult; int nrow; int ncolumn; int main() { //创建套接字,原始套接字 sockfd = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL)); if(sockfd > 0) { printf("原始套接字创建成功:%d\n",sockfd); } //************************************************************************************************************************************************** //数据库的打开使用 //************************************************************************************************************************************************** //打开数据库 ret = sqlite3_open("ip.db",&db); //如果ret==SQLITE_OK 那么就是这一条语言成功执行了 if(ret == SQLITE_OK) { printf("防火墙数据库打开成功!\n"); } else { printf("数据库打开失败!\n"); } ret = sqlite3_open("mac.db",&db); if(ret == SQLITE_OK) { printf("ARP缓存数据库打开成功!\n"); } else { printf("数据库打开失败!\n"); } //使用非回调办法增加一张数据表 sqlite3_get_table(db,"create table persons (IP text primary key);",&dbResult,&nrow,&ncolumn,&errmsg); // arp缓存的数据库 sqlite3_get_table(db,"create table person (ip text primary key,mac text);",&dbResult,&nrow,&ncolumn,&errmsg); //使用回调方法去增加数据 char str[128]=""; printf("防火墙中的IP有:\n"); //想要添加,从这个地方就可以添加 char get_ip[16]="192.168.7.5"; sprintf(str,"insert into persons values('%s');",get_ip); sqlite3_get_table(db,str,&dbResult,&nrow,&ncolumn,&errmsg); //使用非回调函数查询数据 ret == sqlite3_get_table(db,"select * from persons;",&dbResult,&nrow,&ncolumn,&errmsg); if(ret==SQLITE_OK) { int i,j,index; index=ncolumn; for(i=0;i printf(" %s ",dbResult[index]); index++; } printf("\n"); } sqlite3_free_table(dbResult); } //选择标志位 int chose = 0; show();//菜单展示 int pthread_flag = 0; while(1) { printf("请输入您的选择:"); scanf("%d",&chose); getchar(); if(1 == chose) { char add_ip[32]=""; printf("请输入添加的黑名单IP:格式如:192.168.1.1\n"); fgets(add_ip,sizeof(add_ip),stdin); add_ip[strlen(add_ip)-1]='\0'; //printf("获得到了:%s\n",add_ip); //格式校验 int a=0,b=0,c=0,d=0; sscanf(add_ip,"%d.%d.%d.%d",&a,&b,&c,&d); if((a >= 0 && a = 0 && b = 0 && c = 0 && d printf("您输入有误\n"); } } else if(2 == chose) { ret == sqlite3_get_table(db,"select * from persons;",&dbResult,&nrow,&ncolumn,&errmsg); if(ret==SQLITE_OK) { int i,j,index; index=ncolumn; for(i=0;i printf(" %s ",dbResult[index]); index++; } printf("\n"); } sqlite3_free_table(dbResult); } } else if(3 == chose) { char delete_ip[32]=""; printf("请输入删除的黑名单IP:格式如:192.168.1.1\n"); fgets(delete_ip,sizeof(delete_ip),stdin); delete_ip[strlen(delete_ip)-1]='\0'; printf("获得到了:%s\n",delete_ip); //格式校验 int a=0,b=0,c=0,d=0; sscanf(delete_ip,"%d.%d.%d.%d",&a,&b,&c,&d); if((a >= 0 && a = 0 && b = 0 && c = 0 && d printf("您输入有误\n"); } } else if(4 == chose) { if(0 == pthread_flag ) { printf("路由器已运行!\n"); pthread_flag++; pthread_t pth; pthread_create(&pth,NULL,my_fun,NULL); pthread_detach(pth); } else { printf("路由器正在运行,请不要重复开启!\n"); } } else if(5 == chose) { //在路由器开启之前,发送arp广播数据包 //两个端口均要发送广播消息 printf("arp广播发送!\n"); int i = 1; for(i = 1;i 0xff,0xff,0xff,0xff,0xff,0xff,//目的mac广播 0x00,0x0c,0x29,0xf3,0x98,0x3e,//源mac 0x08,0x06,//帧类型 0x00,0x01,//硬件类型 0x08,0x00,//协议类型 6, 4, 0x00,0x01,//op 0x00,0x0c,0x29,0xf3,0x98,0x3e,//发送端mac 192,168,7,2,//发送端ip 0x00,0x00,0x00,0x00,0x00,0x00, 192,168,7,i }; //获取网络接口类型 struct ifreq ethreq3; strncpy(ethreq3.ifr_name, "ens33", IFNAMSIZ); ioctl(sockfd, SIOCGIFINDEX, ðreq3); //定义一个网络接口变量 struct sockaddr_ll sll3; bzero(&sll3, sizeof(sll3)); sll3.sll_ifindex = ethreq3.ifr_ifindex; //发送 sendto(sockfd,buf_all_1,42,0,(struct sockaddr *)&sll3,sizeof(sll3)); //ens33网口组arp的请求包 unsigned char buf_all_2[42]={ 0xff,0xff,0xff,0xff,0xff,0xff,//目的mac广播 0x00,0x0c,0x29,0xf3,0x98,0x48,//源mac 0x08,0x06,//帧类型 0x00,0x01,//硬件类型 0x08,0x00,//协议类型 6, 4, 0x00,0x01,//op 0x00,0x0c,0x29,0xf3,0x98,0x48,//发送端mac 192,168,8,2,//发送端ip 0x00,0x00,0x00,0x00,0x00,0x00, 192,168,8,i }; //获取网络接口类型 struct ifreq ethreq4; strncpy(ethreq4.ifr_name, "ens33", IFNAMSIZ); ioctl(sockfd, SIOCGIFINDEX, ðreq4); //定义一个网络接口变量 struct sockaddr_ll sll4; bzero(&sll4, sizeof(sll4)); sll4.sll_ifindex = ethreq4.ifr_ifindex; //发送 sendto(sockfd,buf_all_2,42,0,(struct sockaddr *)&sll4,sizeof(sll4)); } } else if(6 == chose) { ret == sqlite3_get_table(db,"select * from person;",&dbResult,&nrow,&ncolumn,&errmsg); if(ret==SQLITE_OK) { int i,j,index; index=ncolumn; for(i=0;i printf(" %s ",dbResult[index]); index++; } printf("\n"); } //sqlite3_free_table(dbResult); } } else if(9 == chose) { show(); } else if(0 == chose) { //关闭套接字 close(sockfd); //关闭数据库 sqlite3_close(db); printf("系统结束!\n"); exit(0); } else { printf("对不起,您的输入有误"); } } //************************************************************************************************************************************************** //接收数据包,并进行解析 //************************************************************************************************************************************************** //接收所有的数据 //关闭套接字 close(sockfd); //关闭数据库 sqlite3_close(db); return 0; } void show(void) { printf("************************************************\n"); printf("**********路由器黑名单管理系统******************\n"); printf("**************1.添加黑名单IP********************\n"); printf("**************2.显示所有黑名单******************\n"); printf("**************3.删除黑名单**********************\n"); printf("**************4.开启路由器**********************\n"); printf("**************5.刷新ARP表缓存*******************\n"); printf("**************6.显示所有ARP表缓存***************\n"); printf("**************9.重新打印菜单********************\n"); printf("**************0.退出此系统**********************\n"); printf("************************************************\n"); } void * my_fun(void * arg) { while(1) { unsigned char buf[1500] = ""; ssize_t len = recvfrom(sockfd,buf,sizeof(buf),0,NULL,NULL); unsigned char det_mac[18] = ""; unsigned char src_mac[18] = ""; unsigned short mac_type = ntohs(*(unsigned short *)(buf + 12)); //printf("mac_type=\n", mac_type); sprintf(det_mac,"%02x:%02x:%02x:%02x:%02x:%02x",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]); sprintf(src_mac,"%02x:%02x:%02x:%02x:%02x:%02x",buf[6],buf[7],buf[8],buf[9],buf[10],buf[11]); //printf("[%3ld]MAC:[%s]->[%s]:%#x\n",len,src_mac,det_mac,mac_type); if(mac_type == 0x0800) { unsigned char *ip_buf = buf + 14; //源ip、目的ip char src_ip[16] = ""; char dst_ip[16] = ""; inet_ntop(AF_INET,(void *)ip_buf+12,src_ip,16); inet_ntop(AF_INET,(void *)ip_buf+16,dst_ip,16); //设置标志为 int flag=0; char find_ip[64]=""; char find_ip2[64]=""; sprintf(find_ip,"select * from persons where IP='%s';",src_ip); sprintf(find_ip2,"select * from persons where IP='%s';",dst_ip); ret == sqlite3_get_table(db,find_ip,&dbResult,&nrow,&ncolumn,&errmsg); if(ret == SQLITE_OK) { int i,j,index; index=ncolumn; for(i=0;i //printf(" %s ",dbResult[index]); if(strcmp(src_ip,dbResult[index])==0) { flag ++; } index++; } } sqlite3_free_table(dbResult); if(flag != 0) { printf("防火墙发现含有隐患的IP,已将其拦截! \n"); continue; } } flag = 0;//标志位归0 ret == sqlite3_get_table(db,find_ip2,&dbResult,&nrow,&ncolumn,&errmsg); if(ret == SQLITE_OK) { int i,j,index; index=ncolumn; for(i=0;i //printf(" %s ",dbResult[index]); if(strcmp(dst_ip,dbResult[index])==0) { flag ++; } index++; } } sqlite3_free_table(dbResult); if(flag != 0) { printf("防火墙发现含有隐患的IP,已将其拦截! \n"); continue; } } flag = 0; //柏标志为清0 if(ip_buf[9] == 1) { //ICMP //通过目的ip找到目的MAC char find_mac[18]=""; ret == sqlite3_get_table(db,"select * from person;",&dbResult,&nrow,&ncolumn,&errmsg); if(ret==SQLITE_OK) { int i,j,index; index=ncolumn; for(i=0;i if(strcmp(dst_ip,dbResult[index]) == 0) { memcpy(find_mac,dbResult[index+1],18); } index++; } } } //将获得到的目的MAC 进行解包 unsigned char find_buf_one[6]=""; sscanf(find_mac,"%02x:%02x:%02x:%02x:%02x:%02x",(unsigned int *)&find_buf_one[0],(unsigned int *)&find_buf_one[1],(unsigned int *)&find_buf_one[2],(unsigned int *)&find_buf_one[3],(unsigned int *)&find_buf_one[4],(unsigned int *)&find_buf_one[5]); if(0 == strcmp(src_mac,"80:fa:5b:26:d4:10")) { //printf("MAC:[%s]->[%s]\n",src_mac,det_mac); //printf("IP:[%s]->[%s]\n",src_ip,dst_ip); //根据IP判断防火墙 //建立数据库,在数据库中遍历 //查询数据,如果没有此ip则创建一个数据,如果有判断其mac是否更改 //sqlite3_exec(db,"insert into persons values(arp_ip,arp_mac);",NULL,NULL,&errmsg); //printf("协议类型:ICMP\n"); //printf("\n"); //在数据库中找到目的IP对应的mac组装到发送的位置 //网关到A53 unsigned char buf_34[1500] = ""; //目的MAC:00:53:50:00:2c:59 buf[0] = find_buf_one[0]; buf[1] = find_buf_one[1]; buf[2] = find_buf_one[2]; buf[3] = find_buf_one[3]; buf[4] = find_buf_one[4]; buf[5] = find_buf_one[5]; //源MAC 00:0c:29:f3:98:48 buf[6] = 0x00; buf[7] = 0x0c; buf[8] = 0x29; buf[9] = 0xf3; buf[10] = 0x98; buf[11] = 0x48; //memcpy(buf_34,buf,strlen(buf)+1); //获取网络接口类型 struct ifreq ethreq; strncpy(ethreq.ifr_name, "ens38", IFNAMSIZ); ioctl(sockfd, SIOCGIFINDEX, ðreq); //定义一个网络接口变量 struct sockaddr_ll sll; bzero(&sll, sizeof(sll)); sll.sll_ifindex = ethreq.ifr_ifindex; //发送 sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&sll,sizeof(sll)); } if(0 == strcmp(src_mac,"00:53:50:00:2c:59")) { //printf("----------A53----------\n"); //printf("MAC:[%s]->[%s]\n",src_mac,det_mac); //printf("IP:[%s]->[%s]\n",src_ip,dst_ip); //printf("协议类型:ICMP\n"); //printf("\n"); //2->1 unsigned char buf_21[1500] = ""; //目的MAC 80:fa:5b:26:d4:10 buf[0] = find_buf_one[0]; buf[1] = find_buf_one[1]; buf[2] = find_buf_one[2]; buf[3] = find_buf_one[3]; buf[4] = find_buf_one[4]; buf[5] = find_buf_one[5]; //源MAC 00:0c:29:f3:98:3e buf[6] = 0x00; buf[7] = 0x0c; buf[8] = 0x29; buf[9] = 0xf3; buf[10] = 0x98; buf[11] = 0x3e; //memcpy(buf_34,buf,strlen(buf)+1); //获取网络接口类型 struct ifreq ethreq; strncpy(ethreq.ifr_name, "ens33", IFNAMSIZ); ioctl(sockfd, SIOCGIFINDEX, ðreq); //定义一个网络接口变量 struct sockaddr_ll sll; bzero(&sll, sizeof(sll)); sll.sll_ifindex = ethreq.ifr_ifindex; //发送 sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&sll,sizeof(sll)); } } } else if(mac_type == 0x0806) { unsigned char *ip_buf = buf + 14; //源ip、目的ip char src_ip[16] = ""; char dst_ip[16] = ""; inet_ntop(AF_INET,(void *)ip_buf+14,src_ip,16); inet_ntop(AF_INET,(void *)ip_buf+24,dst_ip,16); //将接收RP的应答包,将其ip与mac保存在数据库中,方便组装icmp unsigned short arp_accept = ntohs(*(unsigned short * )(ip_buf+6)); if(2 == arp_accept) { int mac_flag = 0; //再插入数据库之前,先判断有没有一样的IP和MAC ret == sqlite3_get_table(db,"select * from person;",&dbResult,&nrow,&ncolumn,&errmsg); if(ret==SQLITE_OK) { int i,j,index; index=ncolumn; for(i=0;i if(strcmp(src_ip,dbResult[index])== 0) { if(strcmp(src_mac,dbResult[index+1])==0) { printf("数据库中已有此arp缓存,无需添加\n"); } else { printf("IP对应的mac更改了!\n"); char update_buf[128]=""; sprintf(update_buf,"updata person set mac = '%s' where ip = '%s';",src_mac,src_ip); } } else { //取出其应答包的源MAC和源IP char str[128]=""; sprintf(str,"insert into person values('%s','%s');",src_ip,src_mac); sqlite3_get_table(db,str,&dbResult,&nrow,&ncolumn,&errmsg); } index++; } } } } } } }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有