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 <stdio.h>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>//recvfrom
#include <netinet/ether.h>//ETH_P_ALL
#include <arpa/inet.h>//inet_ntop
#include <net/if.h>//ifreq
#include <sys/ioctl.h>//ioctl
#include <netpacket/packet.h>//sockaddr_ll
#include <pthread.h>
#include <stdlib.h>
#include <sqlite3.h>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<nrow;i++){for(j=0;j<ncolumn;j++){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 <= 255) && (b >= 0 && b <= 255) && (c >= 0 && c <= 255) && (d >= 0 && d<= 255)){//写入数据库char sqlite3_ip[64]="";sprintf(sqlite3_ip,"insert into persons values('%s');",add_ip);sqlite3_get_table(db,sqlite3_ip,&dbResult,&nrow,&ncolumn,&errmsg);printf("数据库已更新!\n");}else{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<nrow;i++){for(j=0;j<ncolumn;j++){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 <= 255) && (b >= 0 && b <= 255) && (c >= 0 && c <= 255) && (d >= 0 && d<= 255)){//写入数据库char sqlite3_ip[64]="";sprintf(sqlite3_ip,"delete from persons where IP='%s';",delete_ip);sqlite3_get_table(db,sqlite3_ip,&dbResult,&nrow,&ncolumn,&errmsg);printf("数据库已更新!\n");}else{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 < 255 ;i++){//ens33网口组arp的请求包unsigned char buf_all_1[42]={0xff,0xff,0xff,0xff,0xff,0xff,//目的mac广播0x00,0x0c,0x29,0xf3,0x98,0x3e,//源mac0x08,0x06,//帧类型0x00,0x01,//硬件类型0x08,0x00,//协议类型6,4,0x00,0x01,//op0x00,0x0c,0x29,0xf3,0x98,0x3e,//发送端mac192,168,7,2,//发送端ip0x00,0x00,0x00,0x00,0x00,0x00,192,168,7,i   };//获取网络接口类型struct ifreq ethreq3;strncpy(ethreq3.ifr_name, "ens33", IFNAMSIZ);ioctl(sockfd, SIOCGIFINDEX,  &ethreq3);//定义一个网络接口变量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,//源mac0x08,0x06,//帧类型0x00,0x01,//硬件类型0x08,0x00,//协议类型6,4,0x00,0x01,//op0x00,0x0c,0x29,0xf3,0x98,0x48,//发送端mac192,168,8,2,//发送端ip0x00,0x00,0x00,0x00,0x00,0x00,192,168,8,i   };//获取网络接口类型struct ifreq ethreq4;strncpy(ethreq4.ifr_name, "ens33", IFNAMSIZ);ioctl(sockfd, SIOCGIFINDEX,  &ethreq4);//定义一个网络接口变量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<nrow;i++){for(j=0;j<ncolumn;j++){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、目的ipchar 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<nrow;i++){for(j=0;j<ncolumn;j++){//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;//标志位归0ret == sqlite3_get_table(db,find_ip2,&dbResult,&nrow,&ncolumn,&errmsg);if(ret == SQLITE_OK){int i,j,index;index=ncolumn;for(i=0;i<nrow;i++){for(j=0;j<ncolumn;j++){//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; //柏标志为清0if(ip_buf[9] == 1){//ICMP//通过目的ip找到目的MACchar 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<nrow;i++){for(j=0;j<ncolumn;j++){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组装到发送的位置//网关到A53unsigned char buf_34[1500] = "";//目的MAC:00:53:50:00:2c:59buf[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,  &ethreq);//定义一个网络接口变量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->1unsigned char buf_21[1500] = "";//目的MAC 80:fa:5b:26:d4:10buf[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,  &ethreq);//定义一个网络接口变量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、目的ipchar 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保存在数据库中,方便组装icmpunsigned short arp_accept = ntohs(*(unsigned short * )(ip_buf+6));if(2 == arp_accept){int mac_flag = 0;//再插入数据库之前,先判断有没有一样的IP和MACret == 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<nrow;i++){for(j=0;j<ncolumn;j++){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和源IPchar str[128]="";sprintf(str,"insert into person values('%s','%s');",src_ip,src_mac);sqlite3_get_table(db,str,&dbResult,&nrow,&ncolumn,&errmsg);}index++;}}} }}}
}

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

  1. c语言编程10000次模拟抛硬币,用c语言模拟抛硬币的过程

    来源:学生作业帮 编辑:作业帮 分类:综合作业 时间:2021/05/20 17:49:43 用c语言模拟抛硬币的过程 要输入抛硬币的次数,输出里要有数字面和印花面的次数,最后算出得到数字面和印花面的 ...

  2. 用 C语言模拟买猫的过程

    这是一个防止代码丢的笔记 最近在学习C语言,同时也在读<编码>这本书,读着读着突然有一种想把编码中的电路实现出来的想法,由于现实世界中缺少材料(大量的电线.开关和灯泡等等),所以产生了用C ...

  3. vs编译器 printf 控制台输出_【语言教程】通过语言了解GCC编译器工作过程

    通过c语言了解GCC编译器如何工作的 比特 下面是c语言初学必看的打印helloworld #include int main(){ printf("hello, world\n" ...

  4. 网络路由器查表过程模拟

    任务及要求 编程模拟路由器查表过程,用(目的地址 掩码 下一跳)的IP路由表以及目的地址作为输入,为目的地址查找路由表,找出正确的下一跳并输出结果. 1. 建立一个路由表 f=open('路由表.tx ...

  5. 分析动态网页客户-服务器工作过程,网页制作中asp技术的应用

    摘    要: 是在当前我国信息化技术发展速度不断加快, 对于用户和企业来讲对信息的需求方式产生了很多转变, 用户或者是企业对多样性.时效性.安全性以及大容量性的信息需求量更大.所以说在网站的制作上需 ...

  6. 路由器的工作原理,形成,转发数据包的过程

    一.路由器的工作原理 二.路由表的形成 三.静态路由和默认路由 四.路由器转发数据包的封装过程 五.静态路由和默认路由的配置 概述: 在只有一个网段的网络中,包可以很容易地从源主机到达目标主机,但是如 ...

  7. 什么是交换机?描述一下工作过程?交换机基本功能、交换机是如何转发数据包的,什么是三层交换机?和二层交换机有什么区别?三层交换机是否可以代替路由器?为什么?

    ** 14. 什么是交换机?描述一下工作过程? ** 交换机是一种工作在数据链路层对流量进行转发的网络设备.主要应用于延长传输距离,解决冲突域,实现单播等功能. ** 工作过程: **当流量进入交换机 ...

  8. ☀️手把手教你Python+matplotlib模拟锁相放大器的原理以及工作过程☀️《❤️记得收藏❤️》

    ☀️手把手教你Python+matplotlib模拟锁相放大器的原理以及工作过程☀️<❤️记得收藏❤️> 目录

  9. adc0809工作过程C语言,ADC0809的工作原理

    目录1.主要特性 2.内部逻辑结构 3.转换过程 A/D转换器是模拟信号源与计算机或其它数字系统之间联系的桥梁,其任务是将连续变化的模拟信号转换为数字信号,以便计算机等数字系统进行处理.存储.控制和显 ...

最新文章

  1. python复制文件夹不阻塞_Python学习第54天(阻塞(blocking) IO和非阻塞(non-blocking)IO)...
  2. matlab 图像操作函数的详解
  3. 从输入 URL 到页面加载完的过程中都发生了什么事情 —— 网络优化篇
  4. c语言第1章ppt,c语言第1章课件.ppt
  5. Linux-Ubuntu中使用apt进行软件的安装与卸载
  6. linux系统下用到的小知识点积累
  7. react 小程序转换_如何将AngularJS 1.x应用程序转换为React应用程序-一次转换一个组件。
  8. cell数组变为字符串_cell转字符串
  9. 创建SSIS包—建立端到端的package
  10. 主键冲突报什么代码_MySQL主键设计
  11. 测试鼠标宏软件,KINBAS VP900鼠标宏设置软件
  12. R语言将两个矩阵数据进行相乘、抽取矩阵的正对角线元素值
  13. Linux系统下强制删除文件
  14. redis锁的几种实现
  15. Android扩展知识 - 减轻C盘压力,扩大C盘空闲容量
  16. java写培根披萨和海鲜披萨_培根海鲜披萨的做法【图解】_培根海鲜披萨的家常做法_培根海鲜披萨怎么做_下午茶...
  17. 线性筛——约数的个数
  18. python电子表格_Python操作 Excel表格
  19. 创业者要处理好的10大关系
  20. 关于TF转换信息(Transforms)的理解

热门文章

  1. 微x模块怎么导入主题_python math数学模块
  2. 找不到mfc140u.dll或者Microsoft Visual C++ 2017 Redistributable一直安装失败解决
  3. 6G的应用场景有哪些?中国移动带你畅想
  4. Spring +SpringMVC+SpringDataJpa之采购订单页面展示
  5. 周易、命理、风水、姓名与命运交流周易研究心得:姓名学
  6. 程序员防猝死指南—恋爱婚姻指南—程序员养生攻略
  7. 【ALM】西门子Polarion产品助力汽车企业通过ASPICE认证
  8. 【Java之简易[图书借阅系统]】戳进来看看
  9. 某手游智能反外挂产品原理浅析之美
  10. 一:项目需求分析;开发环境介绍;