模拟路由器

//路由器,功能为:存储,转发即抓包,改变包的内容
#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
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值