1、原始套接字概述
原始套接字(SOCK_RAW)
1、一种不同于SOCK_STREAM(TCP)、SOCK_DGRAM(UDP)的套接字,它实现于系统核心
2、可以接收本机网卡(数据链路层)上所有的数据帧(数据包),对于监听网络流量和分析网络数据很有作用
3、开发人员可发送自己组装的数据包到网络上
4、广泛应用于高级网络编程
5、网络专家、黑客通常会用此来编写奇特的网络程序
1.1创建原始套接字
int socket(PF_PACKET, SOCK_RAW, protocol)
功能:
创建链路层的原始套接字
参数:
protocol:指定可以接收或发送的数据包类型
ETH_P_IP:IPV4数据包
ETH_P_ARP:ARP数据包
ETH_P_ALL:任何协议类型的数据包
返回值:
成功(>0):链路层套接字
失败(<0):出错
创建原始套接字案例
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <stdlib.h> //exit
int main(int argc, char const *argv[])
{
/* code */
//创建原始套接字
int sfd=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
if(sfd <0)
{
perror("socket");
exit(0);
}
printf("sfd=%d\n",sfd);
return 0;
}
1.2协议格式
1.3MAC头部
1.4解析MAC头案例
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <stdlib.h> //exit
int main(int argc, char const *argv[])
{
/* code */
//创建原始套接字
int sfd=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
if(sfd <0)
{
perror("socket");
exit(0);
}
while(1)
{
//收数据
unsigned char buf[1500]="";
recvfrom(sfd,buf,sizeof(buf),0,NULL,NULL);
//解析MAC头
unsigned char dstmac[18]="";
unsigned char srcmac[18]="";
unsigned short mactype=0;
//解析目的MAC
sprintf(dstmac,"%02x:%02x:%02x:%02x:%02x:%02x",
buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]);
//解析源MAC
sprintf(srcmac,"%02x:%02x:%02x:%02x:%02x:%02x",
buf[6],buf[7],buf[8],buf[9],buf[10],buf[11]);
//解析协议类型
mactype=ntohs(*(unsigned short*)(buf+12));
printf("%s---------->%s\n",srcmac,dstmac);
if(mactype == 0x0800)
{
printf("-----------IP-----------\n");
}
else if(mactype == 0x0806)
{
printf("-----------ARP-----------\n");
}
else if(mactype == 0x8035)
{
printf("-----------RARP-----------\n");
}
else
{
printf("-----------其它协议-----------\n");
}
}
return 0;
}