419 lines
17 KiB
C
419 lines
17 KiB
C
|
#include <sys/socket.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <string.h>
|
|||
|
#include <netinet/ether.h>
|
|||
|
#include <sys/ioctl.h>
|
|||
|
#include <net/if.h>
|
|||
|
#include <netpacket/packet.h>
|
|||
|
#include <sys/ioctl.h>
|
|||
|
#include "get_interface.h"
|
|||
|
#include "link.h"
|
|||
|
|
|||
|
|
|||
|
MY_ROU * roulink_head = NULL;
|
|||
|
MY_ARP * arplink_head = NULL;
|
|||
|
int sockfd = 0;
|
|||
|
//*************************人机交互线程**********************************
|
|||
|
void *callback1(void *arg)
|
|||
|
{
|
|||
|
while(1)
|
|||
|
{
|
|||
|
printf("输入相应的序号,实现对应功能\n");
|
|||
|
int usercmd = -1;
|
|||
|
scanf("%d", &usercmd);
|
|||
|
switch (usercmd)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
getchar();
|
|||
|
title();
|
|||
|
break;
|
|||
|
case 2:
|
|||
|
getchar();//接收输入2的回车
|
|||
|
roulink_head=rou_pTailInsert(roulink_head);
|
|||
|
break;
|
|||
|
case 3:
|
|||
|
getchar();
|
|||
|
roulink_head=rou_pDeleteLink(roulink_head);
|
|||
|
break;
|
|||
|
case 4:
|
|||
|
getchar();
|
|||
|
rou_print_link(roulink_head);/*将指针pHead传入输出函数遍历输出*/
|
|||
|
printf("链表打印完毕!\n");
|
|||
|
break;
|
|||
|
case 5:
|
|||
|
arp_print_link(arplink_head);
|
|||
|
break;
|
|||
|
case 10:
|
|||
|
printf("10:退出路由器,释放IP、ARP链表\n");
|
|||
|
getchar();
|
|||
|
arp_freeLink(arplink_head);
|
|||
|
rou_freeLink(roulink_head);//释放链表
|
|||
|
exit(1);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
pthread_exit(NULL);
|
|||
|
}
|
|||
|
//*************************人机交互线程**********************************
|
|||
|
|
|||
|
|
|||
|
//*************************ARP应答的IP和MAC存入缓存链表线程【开始】**************//
|
|||
|
void * callback2_arp(void *arg)
|
|||
|
{
|
|||
|
arp_mac_ip *p = (arp_mac_ip*)arg;
|
|||
|
|
|||
|
//printf("将 ARP 应答的 IP 和 MAC 存入缓存链\n");
|
|||
|
//printf("### %s\n", p->stc_ip);
|
|||
|
if(arp_searcharpLink(arplink_head, p->stc_ip) == 0)
|
|||
|
{
|
|||
|
printf("插入链表中没有的ARP 应答 IP 和 MAC\n");
|
|||
|
arplink_head = arp_pTailInsert( arplink_head, p->stc_mac ,p->stc_ip);
|
|||
|
}
|
|||
|
|
|||
|
pthread_exit(NULL);
|
|||
|
}
|
|||
|
//*************************ARP应答的IP和MAC存入缓存链表线程【结束】***************//
|
|||
|
|
|||
|
|
|||
|
//*************************IP包转发线程【开始】**********************************//
|
|||
|
void *callback3_ip(void *arg)
|
|||
|
{
|
|||
|
|
|||
|
//发送接口的结构体
|
|||
|
struct sockaddr_ll sll;
|
|||
|
ip_buf *pthread_ip_buf = (ip_buf *)arg;
|
|||
|
|
|||
|
|
|||
|
unsigned char * ip_head= pthread_ip_buf->buf + 14;
|
|||
|
char dst_ip[16] = "";
|
|||
|
|
|||
|
inet_ntop(AF_INET, ip_head + 16, dst_ip, 16);
|
|||
|
printf("IP包转发线程中 目的 dst_ip = %s\n", dst_ip);
|
|||
|
|
|||
|
|
|||
|
int i = 0;
|
|||
|
for (i = 0; i < 16; i++)
|
|||
|
{
|
|||
|
|
|||
|
unsigned char ip[16]="";
|
|||
|
inet_ntop(AF_INET,net_interface[i].ip, ip, 16);//get_interface文件中得到的都是32位无符号整形数据(计算机数据),现转成成点分十进制(人能够书别的)
|
|||
|
|
|||
|
//---------------------[调试]----------------------------------------//
|
|||
|
//printf("设置网卡循环进入次数 i = %d\n", i);
|
|||
|
//printf("检索到的所有网卡名字net_interface[i].name = %s\n", net_interface[i].name);
|
|||
|
//printf("net_interface[i].ip = %s\n",ip);
|
|||
|
//---------------------[调试]----------------------------------------//
|
|||
|
|
|||
|
if(strncmp(ip, dst_ip, 9) == 0)//根据目标网段 查找活跃网卡
|
|||
|
{
|
|||
|
//网卡结构体
|
|||
|
struct ifreq ethreq;
|
|||
|
strncpy(ethreq.ifr_name, net_interface[i].name , IFNAMSIZ);//指定网卡名字
|
|||
|
printf("网卡名字:%s\n", ethreq.ifr_name);
|
|||
|
|
|||
|
if(ioctl(sockfd, SIOCGIFINDEX, ðreq) == -1)//获取网卡接口地址
|
|||
|
{
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
bzero(&sll, sizeof(sll));
|
|||
|
sll.sll_ifindex = ethreq.ifr_ifindex;//将网卡的接口类型赋值给发送接口
|
|||
|
break;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//printf("找不到网段对应的网卡,继续查\n");
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//--------------------------------------------拿到网卡,开始检索对应网卡所有数据,对比【开始】------------------------------------------------------//
|
|||
|
if(strcmp(dst_ip + strlen(dst_ip) - 3, "255") == 0)//是 否为广 播地址
|
|||
|
{
|
|||
|
// printf("是广播地址, 退出线\n");
|
|||
|
return;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//printf("不是广播地址,判断是否为回 环地址\n");
|
|||
|
if(strcmp("127.0.0.1", dst_ip) == 0)
|
|||
|
{
|
|||
|
//printf("是回 环地址, 退出线\n");
|
|||
|
return;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//printf("查找ARP缓存表 对应 MAC\n");
|
|||
|
//指定目的MAC地址
|
|||
|
//可以在链表中找到目的IP,组ICMP包的目的MAC就可以了
|
|||
|
//之所以这样,是因为在网络中的ICMP包里,变化的只有目的MAC,源MAC、IP都不会发生变动
|
|||
|
if(arp_searcharpLink(arplink_head, dst_ip) == 1)
|
|||
|
{
|
|||
|
//1网段中 指定目标IP是主机的IP、MAC
|
|||
|
//2C-4D-54-57-04-7F
|
|||
|
//printf("****icmp****\n");
|
|||
|
if(strncmp("192.168.1.49", dst_ip, 9) == 0)
|
|||
|
{
|
|||
|
pthread_ip_buf->buf[0]=0x2C;
|
|||
|
pthread_ip_buf->buf[1]=0x4D;
|
|||
|
pthread_ip_buf->buf[2]=0x54;
|
|||
|
pthread_ip_buf->buf[3]=0x57;
|
|||
|
pthread_ip_buf->buf[4]=0x04;
|
|||
|
pthread_ip_buf->buf[5]=0x7F;//目标
|
|||
|
int send_len = sendto(sockfd, pthread_ip_buf->buf, pthread_ip_buf->my_buf_date_len, 0, (struct sockaddr *)&sll, sizeof(sll));
|
|||
|
|
|||
|
//-------------------[调试]------------------------//
|
|||
|
//printf("****1 网段 icmp缓存表****\n");
|
|||
|
// printf("send_len ICMP 1 = %d\n", send_len);
|
|||
|
//-------------------[调试]------------------------//
|
|||
|
|
|||
|
}
|
|||
|
//2网段中 指定目标IP是开发板的IP、MAC
|
|||
|
// 00:53:50:00:01:33
|
|||
|
else if(strncmp("192.168.2.100", dst_ip, 9) == 0)
|
|||
|
{
|
|||
|
pthread_ip_buf->buf[0]=0x00;
|
|||
|
pthread_ip_buf->buf[1]=0x53;
|
|||
|
pthread_ip_buf->buf[2]=0x50;
|
|||
|
pthread_ip_buf->buf[3]=0x00;
|
|||
|
pthread_ip_buf->buf[4]=0x59;
|
|||
|
pthread_ip_buf->buf[5]=0x12;
|
|||
|
|
|||
|
//发送给套接字的数据长度,是实际传送过来的长度(main中的IP包有收到具体长度信息)
|
|||
|
int send_len = sendto(sockfd, pthread_ip_buf->buf, pthread_ip_buf->my_buf_date_len, 0, (struct sockaddr *)&sll, sizeof(sll));
|
|||
|
|
|||
|
//-------------------[调试]------------------------//
|
|||
|
//printf("****2 网段 icmp缓存表****\n");
|
|||
|
// printf("send_len ICMP 2 = %d\n", send_len);
|
|||
|
//-------------------[调试]------------------------//
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{//没在链表中没有找到目的IP,需要重新组arp包才行
|
|||
|
|
|||
|
//printf("***************组ARP包\n");
|
|||
|
int i = 0;
|
|||
|
for(; i < 3; i++)
|
|||
|
{
|
|||
|
//printf("%s\n",dst_ip);
|
|||
|
//比对到1网段的数据
|
|||
|
if(strstr(dst_ip,"192.168.1") != 0)
|
|||
|
{
|
|||
|
printf("发送网段1arp包\n");
|
|||
|
unsigned char arp_buf[42] = {
|
|||
|
0xff,0xff,0xff,0xff,0xff,0xff,//目的mac,广播的形式发出去,等待目的IP恢复后覆盖
|
|||
|
0x00,0x0c,0x29,0xfa,0x7c,0x9e,//源mac
|
|||
|
0x08, 0x00,//协议类型
|
|||
|
0, 1,//硬件类型
|
|||
|
6,
|
|||
|
4,
|
|||
|
0, 1,//op
|
|||
|
0x00,0x0c,0x29,0xfa,0x7c,0x9e,//源mac(网卡1 ech0的MAC)
|
|||
|
192,168,1,88,//源IP是路由器1网段的网关,通过它发送到2网段
|
|||
|
0x00,0x00,0x00,0x00,0x00,0x00,//目的mac,等待目的IP恢复后覆盖
|
|||
|
0,0,0,0
|
|||
|
//192,168,1,49,
|
|||
|
};
|
|||
|
int int_ip=0;
|
|||
|
inet_pton(AF_INET, dst_ip, &int_ip);
|
|||
|
unsigned char *intp=(char *)&int_ip;
|
|||
|
arp_buf[38]=intp[0];
|
|||
|
arp_buf[39]=intp[1];
|
|||
|
arp_buf[40]=intp[2];
|
|||
|
arp_buf[41]=intp[3];
|
|||
|
int send_len = sendto(sockfd, arp_buf, sizeof(arp_buf), 0, (struct sockaddr *)&sll, sizeof(sll));
|
|||
|
printf("send_len 11 = %d\n",send_len);
|
|||
|
|
|||
|
}
|
|||
|
//网卡2,ech1的MAC:00:0c:29:fa:7c:a8
|
|||
|
else if(strstr(dst_ip,"192.168.2") != 0)
|
|||
|
{
|
|||
|
printf("发送网段2arp包\n");
|
|||
|
unsigned char arp_buf[42] = {
|
|||
|
0xff,0xff,0xff,0xff,0xff,0xff,//目的mac
|
|||
|
0x00,0x0c,0x29,0xfa,0x7c,0xa8,//源mac
|
|||
|
0x08, 0x00,//协议类型
|
|||
|
0, 1,//硬件类型
|
|||
|
6,
|
|||
|
4,
|
|||
|
0, 1,//op
|
|||
|
0x00,0x0c,0x29,0xfa,0x7c,0xa8,//源mac
|
|||
|
192,168,2,89,//源IP是路由器2网段的网关,通过它发送到1网段
|
|||
|
0x00,0x00,0x00,0x00,0x00,0x00,//目的mac
|
|||
|
192,168,2,100,
|
|||
|
};
|
|||
|
int send_len = sendto(sockfd, arp_buf, sizeof(arp_buf), 0, (struct sockaddr *)&sll, sizeof(sll));
|
|||
|
printf("send_len 22 = %d\n",send_len);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if(arp_searcharpLink(arplink_head, dst_ip) == 1)
|
|||
|
{
|
|||
|
//1
|
|||
|
//2C-4D-54-57-04-7F
|
|||
|
if(strncmp("192.168.0.11", dst_ip, 9) == 0)
|
|||
|
{
|
|||
|
pthread_ip_buf->buf[0] = 0xA8;
|
|||
|
pthread_ip_buf->buf[1] = 0x5E;
|
|||
|
pthread_ip_buf->buf[2] = 0x45;
|
|||
|
pthread_ip_buf->buf[3] = 0xC1;
|
|||
|
pthread_ip_buf->buf[4] = 0x8B;
|
|||
|
pthread_ip_buf->buf[5] = 0x99;
|
|||
|
int send_len = sendto(sockfd, pthread_ip_buf->buf, pthread_ip_buf->my_buf_date_len, 0, (struct sockaddr *)&sll, sizeof(sll));
|
|||
|
//-------------------[调试]------------------------//
|
|||
|
//printf("****3次发ARP过程中检索到ICMP包 1 网段****\n");
|
|||
|
// printf("send_len ICMP 1 = %d\n", send_len);
|
|||
|
//-------------------[调试]------------------------//
|
|||
|
}
|
|||
|
//2
|
|||
|
// 开发板MAC(每次启动都会变化):1C:59:74:81:4A:43
|
|||
|
// 1C:59:74:81:4A:43
|
|||
|
|
|||
|
else if(strncmp("192.168.1.1", dst_ip, 9) == 0)
|
|||
|
{
|
|||
|
pthread_ip_buf->buf[0] = 0x1c;
|
|||
|
pthread_ip_buf->buf[1] = 0x59;
|
|||
|
pthread_ip_buf->buf[2] = 0x74;
|
|||
|
pthread_ip_buf->buf[3] = 0x81;
|
|||
|
pthread_ip_buf->buf[4] = 0x4A;
|
|||
|
pthread_ip_buf->buf[5] = 0x43;
|
|||
|
int send_len = sendto(sockfd, pthread_ip_buf->buf, pthread_ip_buf->my_buf_date_len, 0, (struct sockaddr *)&sll, sizeof(sll));
|
|||
|
//-------------------[调试]------------------------//
|
|||
|
//printf("****3次发ARP过程中检索到ICMP包 2 网段****\n");
|
|||
|
// printf("send_len ICMP 2 = %d\n", send_len);
|
|||
|
//-------------------[调试]------------------------//
|
|||
|
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
//--------------------------------------------拿到网卡,开始检索对应网卡所有数据,对比【结束】------------------------------------------------------//
|
|||
|
|
|||
|
|
|||
|
pthread_exit(NULL);
|
|||
|
|
|||
|
}
|
|||
|
//*************************建IP包转发线程【结束】**********************************//
|
|||
|
|
|||
|
int main()
|
|||
|
{
|
|||
|
//创建原始套接字,接收发送方的网卡信息
|
|||
|
sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
|||
|
if(sockfd<0)
|
|||
|
{
|
|||
|
perror("sockfd:");
|
|||
|
return 0;
|
|||
|
}
|
|||
|
getinterface();//拿取网卡信息(虚拟机的所有网卡,包括回环网卡)
|
|||
|
|
|||
|
pthread_t pth;
|
|||
|
pthread_create(&pth, NULL, callback1, NULL);//人机交互线程,这里可以放在main里面
|
|||
|
|
|||
|
int len = 0;
|
|||
|
|
|||
|
char recv_buff[RECV_SIZE]="";//原始套接字数据包大约为1500个字节
|
|||
|
ssize_t recv_len=0;
|
|||
|
while(1)
|
|||
|
{
|
|||
|
//开始接收其他人的网卡信息
|
|||
|
bzero(recv_buff,sizeof(recv_buff));
|
|||
|
|
|||
|
//[recv_len]设置成全局变量,让线程可以共用数据
|
|||
|
recv_len = recvfrom(sockfd, recv_buff, sizeof(recv_buff), 0, NULL, NULL);
|
|||
|
if(recv_len<=0||recv_len>RECV_SIZE)
|
|||
|
{
|
|||
|
perror("recvfrom");
|
|||
|
continue;
|
|||
|
}
|
|||
|
//printf("链路层截取数据包长度 recv_len=%d\n",recv_len);
|
|||
|
|
|||
|
//MAC包类型
|
|||
|
unsigned short mac_type = 0;
|
|||
|
mac_type = ntohs( *((unsigned short *)(recv_buff + 12)));
|
|||
|
if(mac_type == 0x0800)
|
|||
|
{
|
|||
|
//printf("-----------ip数据包------------\n");
|
|||
|
unsigned char *ip_head = recv_buff + 14;
|
|||
|
unsigned char dst_ip[16] ="";
|
|||
|
inet_ntop(AF_INET, ip_head + 16, dst_ip, 16);
|
|||
|
|
|||
|
//IP包的类型
|
|||
|
if(ip_head[9] == 1)
|
|||
|
{
|
|||
|
//printf("-----ICMP数据包\n");
|
|||
|
//查找过滤IP链表中存在我们指定的目的IP吗
|
|||
|
if(rou_searcharpLink(roulink_head, dst_ip) == 0)
|
|||
|
{
|
|||
|
static int i=0;
|
|||
|
|
|||
|
//-----------调试,打印原始套接字接收到的数据内容是否是空--------------------//
|
|||
|
//printf("i=%d IP包中的目的IP = %d\n",++i, strlen(recv_buff + 30));
|
|||
|
// printf("Rvfbuf=%p\n",recv_buff);
|
|||
|
// int kk=0;
|
|||
|
// while(kk<98)
|
|||
|
// {
|
|||
|
// printf("Rvfbuf[%d]=%d\n",kk,recv_buff[kk]);
|
|||
|
// kk++;
|
|||
|
|
|||
|
// }
|
|||
|
//----------------------------[调试]---------------------------------------//
|
|||
|
|
|||
|
usleep(1000);
|
|||
|
ip_buf *recv = (ip_buf *)malloc(sizeof(ip_buf));
|
|||
|
recv->my_buf_date_len = recv_len;
|
|||
|
memcpy(recv->buf, recv_buff, recv_len);
|
|||
|
|
|||
|
//线程的创建放在满足它的条件中,while循环,满足就进来创建一个,切记不要放到条件外面创建线程,否则只会创建一个,导致所有情况共用一个线程
|
|||
|
pthread_t pth2;
|
|||
|
//最后数据包是ICMP的整包
|
|||
|
pthread_create(&pth2, NULL, callback3_ip, (void*)recv);
|
|||
|
pthread_detach(pth2);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
else if(mac_type == 0x0806)
|
|||
|
{
|
|||
|
arp_mac_ip * head_mac_ip = NULL;//保存目的MAC\IP的结构体,安全措施,防止栈空间释放导致给线程传参为空,失败
|
|||
|
head_mac_ip = (arp_mac_ip *)malloc(sizeof(arp_mac_ip ));
|
|||
|
|
|||
|
|
|||
|
unsigned char *arp_head = recv_buff + 14;
|
|||
|
unsigned char * arp_src_mac = arp_head + 8;//跳过[4.硬件类型、5.协议类型、6.硬件地址长度、7.协议地址长度、8.OP,拿到源MAC地址首地址信息]
|
|||
|
unsigned char stc_mac[18] = "";
|
|||
|
sprintf(stc_mac, "%02x:%02x:%02x:%02x:%02x:%02x", arp_src_mac[0],\
|
|||
|
arp_src_mac[1],\
|
|||
|
arp_src_mac[2], \
|
|||
|
arp_src_mac[3],\
|
|||
|
arp_src_mac[4], \
|
|||
|
arp_src_mac[5]);
|
|||
|
strcpy(head_mac_ip->stc_mac, stc_mac);
|
|||
|
|
|||
|
unsigned char src_ip[16] = "";
|
|||
|
inet_ntop(AF_INET, arp_head + 14, src_ip, 16);//拿到源IP
|
|||
|
strcpy(head_mac_ip->stc_ip, src_ip);
|
|||
|
|
|||
|
//-----------------------------------[调试]-----------------------------------//
|
|||
|
//printf("-----------arp数据包------------\n");
|
|||
|
//printf("arp 源mac:%s\n",head_mac_ip->stc_mac);
|
|||
|
//printf("arp 源IP:src_ip = %s \n", src_ip);
|
|||
|
//-----------------------------------[调试]-----------------------------------//
|
|||
|
|
|||
|
//线程中只保存源ARP的MAC、IP,目的主机的MAC、IP,在IP线程中指定(写死)
|
|||
|
pthread_t pth1;
|
|||
|
pthread_create(&pth1, NULL, callback2_arp, (void*)head_mac_ip);
|
|||
|
pthread_detach(pth1);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|