成功演示:
其他操作指令:
抓包成功图片:
Makefile
CC=gcc
target=main
$(target):main.o get_interface.o link.o -lpthread
$(CC) main.o get_interface.o link.o -o $(target) -lpthread
%*.o:%*.c
$(CC) -c $^ -o $@
clean:
rm -rf *.o $(target)
main.c–主要执行文件
#include
#include
#include
#include
#include
#include
#include
#include
#include "get_interface.h"
#include "link.h"
MY_ROU * roulink_head = NULL;
MY_ARP * arplink_head = NULL;
int sockfd = 0;
/
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);
}
//
void * callback2_arp(void *arg)
{
arp_mac_ip *p = (arp_mac_ip*)arg;
//printf("将 ARP 应答的 IP 和 MAC 存入缓存链n");
//printf("### %sn", p->stc_ip);
if(arp_searcharplink(arplink_head, p->stc_ip) == 0)
{
printf("插入链表中没有的ARP 应答 IP 和 MACn");
arplink_head = arp_pTailInsert( arplink_head, p->stc_mac ,p->stc_ip);
}
pthread_exit(NULL);
}
//
//
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 = %sn", 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 = %dn", i);
//printf("检索到的所有网卡名字net_interface[i].name = %sn", net_interface[i].name);
//printf("net_interface[i].ip = %sn",ip);
//---------------------[调试]----------------------------------------//
if(strncmp(ip, dst_ip, 9) == 0)//根据目标网段 查找活跃网卡
{
//网卡结构体
struct ifreq ethreq;
strncpy(ethreq.ifr_name, net_interface[i].name , IFNAMSIZ);//指定网卡名字
printf("网卡名字:%sn", 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缓存表 对应 MACn");
//指定目的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 = %dn", 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 = %dn", send_len);
//-------------------[调试]------------------------//
}
}
else
{//没在链表中没有找到目的IP,需要重新组arp包才行
//printf("***************组ARP包n");
int i = 0;
for(; i < 3; i++)
{
//printf("%sn",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 = %dn",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 = %dn",send_len);
}
if(arp_searcharplink(arplink_head, dst_ip) == 1)
{
//1
//2C-4D-54-57-04-7F
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("****3次发ARP过程中检索到ICMP包 1 网段****n");
// printf("send_len ICMP 1 = %dn", send_len);
//-------------------[调试]------------------------//
}
//2
// 开发板MAC(每次启动都会变化):00:53:50:00:3B:DB
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;
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 = %dn", send_len);
//-------------------[调试]------------------------//
}
break;
}
}
}
return;
}
}
//--------------------------------------------拿到网卡,开始检索对应网卡所有数据,对比【结束】------------------------------------------------------//
pthread_exit(NULL);
}
//
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=%dn",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 = %dn",++i, strlen(recv_buff + 30));
// printf("Rvfbuf=%pn",recv_buff);
// int kk=0;
// while(kk<98)
// {
// printf("Rvfbuf[%d]=%dn",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;//保存目的MACIP的结构体,安全措施,防止栈空间释放导致给线程传参为空,失败
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:%sn",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;
}
link.h–链表结构体、函数定义以及一些结构体
#include
#include
#include
#define RECV_SIZE 2048
typedef struct My_buf
{
unsigned char buf[RECV_SIZE];
int my_buf_date_len;
}ip_buf;
typedef struct Arp_mac_ip
{
char stc_mac[18];
char stc_ip[16];
}arp_mac_ip;
extern void title();
/
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];//接口数据
extern void getinterface();
int get_interface_num();
#endif
get_interface.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "get_interface.h"
int interface_num=0;//接口数量
INTERFACE net_interface[MAXINTERFACES];//接口数据
int get_interface_num(){
return interface_num;
}
void getinterface()
{
struct ifreq buf[MAXINTERFACES];
struct ifconf ifc;
int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
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=%dnn", interface_num);
char buff[20]="";
int ip;
int if_len = interface_num;
while (if_len-- > 0)
{
printf("%sn", 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("UPn");
net_interface[if_len].flag = 1;
}
else{
printf("DOWNn");
net_interface[if_len].flag = 0;
}
}
else
{
char str[256];
sprintf(str, "SIOCGIFFLAGS ioctl %s", buf[if_len].ifr_name);
perror(str);
}
if (!(ioctl(sock_raw_fd, SIOCGIFADDR, (char *) &buf[if_len])))
{
printf("IP:%sn",(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:%sn",(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:%sn",(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);
}
if (!(ioctl(sock_raw_fd, SIOCGIFHWADDR, (char *) &buf[if_len])))
{
printf("MAC:%02x:%02x:%02x:%02x:%02x:%02xnn",
(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
}