IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 使用C语言,模拟路由器的工作过程 -> 正文阅读

[C++知识库]使用C语言,模拟路由器的工作过程

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,//源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,  &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,//源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,  &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、目的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<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;//标志位归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<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; //柏标志为清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<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组装到发送的位置
                //网关到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,  &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->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,  &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、目的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<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和源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++;
                        }
                    }
                } 
            }

        }

    }
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-04 17:19:43  更:2021-09-04 17:21:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 19:47:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码