以太网帧以7字节前导码和1字节帧开始符开头(物理层),紧跟源地址和目的地址(MAC层)。
IP数据包在DATA字段中,数据段最小为46字节。
IP包的源IP地址和目的IP地址从格式中看出分别从第12字节、第16字节开始(序号从0字节数起)。
#include
#include
#include
#include
#include
typedef unsigned char uchar;
#define BUF_SIZE 2048
#define MIN_ETH_PAYLOAD 46
#define MAC_ADDR_OFFSET (6+6+2)
int main()
{
int len = 0;
uchar buff[BUF_SIZE] = {0};
//AF_PACKET /* Packet family. */
//SOCK_RAW /* Raw protocol interface. */
//ETH_P_ALL /* Every packet (be careful!!!) */
int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(sock < 0)
{
printf("create socket failed!");
return -1;
}
while (true)
{
len = recvfrom(sock, buff, BUF_SIZE, 0, NULL, NULL);
if(len < MIN_ETH_PAYLOAD)
{
printf("catch invalid data!");
return -1;
}
//打印MAC信息
printf("Source MAC %X:%X:%X:%X:%X:%X",
(uchar)buff[6], (uchar)buff[7], (uchar)buff[8],
(uchar)buff[9], (uchar)buff[10], (uchar)buff[11]);
printf(" ---> Dest MAC %X:%X:%X:%X:%X:%X\n",
(uchar)buff[0], (uchar)buff[1], (uchar)buff[2],
(uchar)buff[3], (uchar)buff[4], (uchar)buff[5]);
//打印IP信息
printf("Source IP %d.%d.%d.%d",
(uchar)buff[MAC_ADDR_OFFSET + 12], (uchar)buff[MAC_ADDR_OFFSET + 13],
(uchar)buff[MAC_ADDR_OFFSET + 14], (uchar)buff[MAC_ADDR_OFFSET + 15]);
printf(" ---> Dest IP %d.%d.%d.%d\n",
(uchar)buff[MAC_ADDR_OFFSET + 16], (uchar)buff[MAC_ADDR_OFFSET + 17],
(uchar)buff[MAC_ADDR_OFFSET + 18], (uchar)buff[MAC_ADDR_OFFSET + 19]);
}
return 0;
}
抓包的方法简洁有效,相对的我们需要了解以太网帧和IP包的格式,才能知道数据包字段值的意义。
值得注意的是,不同版本的协议格式略有不同。