欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

模拟路由器

程序员文章站 2022-06-03 21:09:52
...
//路由器,功能为:存储,转发即抓包,改变包的内容
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <string.h>
#include <netpacket/packet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <unistd.h>
#include <pthread.h>
#include "get_interface.h"
#include <stdlib.h>
typedef struct st_my_arp //arp应答内容:目的mac 与 目的主机ip
{
    char ip_str[4];
    char mac_str[6];
} ST_MY_ARP;
typedef struct st_my_ethname_and_arp
{
    char ethname[10];
    ST_MY_ARP my_eth_st[256]; //结构体嵌套
} ST_MY_ETHNAME_AND_ARP;
ST_MY_ARP my_arp[256];                    //在my_rcv_arp中赋值
ST_MY_ETHNAME_AND_ARP my_ethname_arp[10]; //在获取ethname后赋值

unsigned char *my_find_from_arp(unsigned char *p, unsigned char *p_ethname) //一个参数为目的ip,另一个为ethname
{
    //应该先进行arp请求,然后获取到arp应答的内容,写到结构体里,应传进来一个结构体数组(arp应答的mac与ip)
    //应该传进来一个(eth与arp应答结构体数组的)结构体数组,传进来一个现在转发时发送用的哪个eth
    printf("---------------------------------------进入从arp表里找目的mac\n");
    unsigned char *my_arp_dst_mac = (unsigned char *)malloc(6);
    int j = 0;
    for (j = 0; j < get_interface_num(); j++) //找网卡
    {
        printf("2222222222222222222222222进入从arp表里找目的mac\n");
        if (memcmp(my_ethname_arp[j].ethname, p_ethname, 10) == 0) //此处可能有问题:1参数name占20字节,2参数name10字节
        {
            printf("网卡比较成功\n");
            printf("现在是第%d个my_ethname_arp\n", j);
            break;
        }
    }
    //上面得到了现在所用的带网卡的结构体即my_ethname_arp[j].ethname
    int i = 0;
    for (i = 0; i < 256; i++) //找ip对应的mac
    {
        printf("3333333333333333333333333333进入从arp表里找目的mac\n");

         printf("现在验证my_ethname_arp[j].my_eth_st[i].ip_str------\n");
         int uu=0;
                        for (uu = 0; uu < 4; uu++)
                        {
                            printf("-----------i=%d\n",i);
                            printf("%02x:", *(unsigned char*)(my_ethname_arp[j].my_eth_st[i].ip_str + uu));
                        }

                        printf("\n");
        if (memcmp(my_ethname_arp[j].my_eth_st[i].ip_str, p, 4) == 0)
        {
            printf("ip匹配成功\n");
            //将对应的mac赋值给p
            memcpy(my_arp_dst_mac, my_ethname_arp[j].my_eth_st[i].mac_str, 6);
             int tt=0;
                        for (tt = 0; tt < 6; tt++)
                        {
                            printf("%02x:", *( my_ethname_arp[j].my_eth_st[i].mac_str + tt));
                        }
            return my_arp_dst_mac;
        }
        
    }
   
            printf("4444444444444444444444444进入从arp表里找目的mac\n");
            
            my_arp_dst_mac = NULL;
            return my_arp_dst_mac;
        
}

//抓包,并改变包的dstmac
void *deal_fun(void *arg)
{
    int sockfd = (int)arg;
    printf("sockfd=%d\n", sockfd);
    //这种函数下次记住,一看就是通过全局变量来完成工作的
    getinterface();

    //将getinterface()里的name直接写入自己的结构体
    int mm=0;
    for ( mm = 0; mm < get_interface_num() ; mm++)
    {
        memcpy(my_ethname_arp[mm].ethname,net_interface[mm].name,10);
    }
    
    
    while (1)
    {

        unsigned char buf[1500] = "";
        //由于sockraw 无法分析iip 所以写null
        int len = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);
        printf("len = %d\n", len);

        unsigned short mac_type = ntohs(*(unsigned short *)(buf + 12));

        if (mac_type == 0x0806)
        {
            if (buf[21] == 2) //确定类型是arp应答
            {
                //根据第几块网卡的ip,和现在收到包的源ip前三位是否相同,确定应改的arp表ii。
                int ii = 0;
                for (ii = 0; ii < get_interface_num(); ii++)
                {
                    if (memcmp(buf + 28, net_interface[ii].ip, 3) == 0)//28代表arp中的源ip
                        break;
                }

               // memcpy(my_ethname_arp[ii].ethname, net_interface[ii].name, 10);
                char ip_str[16] = "";
                char mac_str[18] = "";
                inet_ntop(AF_INET, buf + 28, ip_str, 16); //arp应答的源ip

                unsigned char xxx = *(unsigned char *)(buf + 28 + 3);
                sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x",
                        buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);
                printf("获得arp应答的源ip与源mac%s----%s\n", ip_str, mac_str);
                //下面将ip与mac写到全局结构体
                memcpy(my_ethname_arp[ii].my_eth_st[xxx].ip_str, buf + 28, 4);
                memcpy(my_ethname_arp[ii].my_eth_st[xxx].mac_str, buf + 22, 6);
                
                //验证写入是否有问题
                 int oo = 0;
                 printf("现在验证写入的mac------");
                        for (oo = 0; oo < 6; oo++)
                        {
                            
                            printf("%02x:", *(unsigned char*)( my_ethname_arp[ii].my_eth_st[xxx].mac_str+ oo));
                        }

                        printf("\n");
                        printf("现在验证写入的ip------");
                        for (oo = 0; oo < 4; oo++)
                        {
                            printf("%02x:", *(unsigned char*)( my_ethname_arp[ii].my_eth_st[xxx].ip_str+ oo));
                        }

                        printf("\n");
                // printf("现在是自己的arp表\n");
                // sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x",
                //         my_ethname_arp[ii].my_eth_st[xxx].mac_str,my_ethname_arp[ii].my_eth_st[xxx].mac_str+1\
                //         ,my_ethname_arp[ii].my_eth_st[xxx].mac_str+2,my_ethname_arp[ii].my_eth_st[xxx].mac_str+3\
                //         ,my_ethname_arp[ii].my_eth_st[xxx].mac_str+4,my_ethname_arp[ii].my_eth_st[xxx].mac_str+5);
                // printf("获得arp应答的源ip与源mac%s----%s\n",my_ethname_arp[ii].my_eth_st[xxx].ip_str , my_ethname_arp[ii].my_eth_st[xxx].mac_str);
            }
        }

        //现在应该完成了arp表的写入工作
        else if (mac_type == 0x0800)
        {
            printf("-----收到一只Ip报文\n");
            unsigned char *dst_ip = buf + 14 + 16; //跳过以太网头部,以及ip头的前几位,来到目的ip的位置

            int i = 0;
            for (i = 0; i < get_interface_num(); i++)
            {
                //判断buf中的目的ip和路由器的哪块网卡同一网段
                if (memcmp(dst_ip, net_interface[i].ip, 3) == 0 && memcmp(dst_ip, net_interface[i].ip, 4) != 0)
                {
                    printf("dddddddddddddddddddddddd\n");
                    //修改buf中源mac,为路由器的和目的ip相同网段的mac
                    memcpy(buf + 6, net_interface[i].mac, 6);
                    unsigned char *dst_mac = my_find_from_arp(dst_ip, net_interface[i].name);
                    // int j = 0;

                    // for (j = 0; j < 6; j++)
                    // {
                    //     printf("%02x:", *(dst_mac + j));
                    // }

                    printf("\n");
                    if (dst_mac == NULL)
                    {
                        //发送arp

                        unsigned char a[6] = "";
                        int jj = 0;
                        for (jj = 0; jj < 6; jj++)
                        {
                            sscanf(((unsigned char *)net_interface[i].mac) + jj, "%c", a + jj);
                        }
                        unsigned char b[4] = "";
                        for (jj = 0; jj < 4; jj++)
                        {
                            sscanf((unsigned char *)net_interface[i].ip + jj, "%c", b + jj);
                        }

                        unsigned char c[4] = "";
                        for (jj = 0; jj < 4; jj++)
                        {
                            sscanf((unsigned char *)dst_ip + jj, "%c", c + jj); //收到一个包,这个包中ip已知,但mac未知,故将ip考给arp协议
                        }

                        unsigned char msg[] = {
                            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, //目的mac
                            a[0], a[1], a[2], a[3], a[4], a[5], //源mac
                            0x08, 0x06,                         //帧类型 arp

                            //arp 报文头
                            0x00, 0x01, //硬件类型
                            0x08, 0x00, //协议类型
                            6,
                            4,
                            0x00, 0x01,                         //arp请求命令
                            0x00, 0x0c, 0x29, 0xb3, 0x34, 0x0b, //源mac
                            b[0], b[1], b[2], b[3],             //源ip
                            0, 0, 0, 0, 0, 0,                   //目的mac
                            c[0], c[1], c[2], c[3]              //目的ip(209房兴业)240windows成功 181失败
                            //写255失败的原因 根本就没有255这个地址啊,arp本身就是广播,它一看没有255那算了
                        };

                        //发送arp
                        //获取本地网络接口

                        struct ifreq ethreq;
                        strncpy(ethreq.ifr_name, net_interface[i].name, IFNAMSIZ);
                        ioctl(sockfd, SIOGIFINDEX, &ethreq);

                        //将本地接口赋值给sll
                        struct sockaddr_ll sll;
                        bzero(&sll, sizeof(sll));
                        sll.sll_ifindex = ethreq.ifr_ifindex;
                        sendto(sockfd, msg, 42, 0, (struct sockaddr *)&sll, sizeof(sll));

                        break;
                    }
                    else if (dst_mac != NULL)
                    {
                        printf("dddddddddddddddddddddddddddddddd\n");
                        memcpy(buf, dst_mac, 6);
                        printf("mac地址为");
                        int j = 0;
                        for (j = 0; j < 6; j++)
                        {

                            printf("%02x:", *(buf + j));
                        }
                    }
                    //获取本地网络接口
                    struct ifreq ethreq;
                    strncpy(ethreq.ifr_name, net_interface[i].name, IFNAMSIZ);
                    ioctl(sockfd, SIOGIFINDEX, &ethreq);

                    //将本地接口赋值给sll
                    struct sockaddr_ll sll;
                    bzero(&sll, sizeof(sll));
                    sll.sll_ifindex = ethreq.ifr_ifindex;
                    sendto(sockfd, buf, len, 0, (struct sockaddr *)&sll, sizeof(sll));
                }
            }
        }
    }
}

int main(int argc, char const *argv[])
{
    int sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (sockfd == -1)
    {
        perror("sockfd");
    }

    pthread_t tid;
    pthread_create(&tid, NULL, deal_fun, (void *)sockfd);
    pthread_detach(tid);

    sleep(100000);
    close(sockfd);
    return 0;
}

#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

#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
}

相关标签: 网络编程