描述:
Linux支持PF_PACKET类型的套接字,用于实现用户层的网络协议。通过该SOCK_RAW类型的Packet socket,应用程序可以直接接收带完整数据帧,处理完毕后再使用该socket发出数据帧。因此可以实现更底层的网络协议。也可以通过该类型的Socket实现网络抓包。
以太网的侦结构如下:
-----------------------------------------------------
| 目的地址 | 源地址 | 类型 | 数据 |
-----------------------------------------------------
| 6 byte | 6 byte | 2 byte | 46~1500 byte |
函数描述
int socket(int domain, int type, int protocol);
第一个参数,协议簇,填写PF_PACKET
第二个参数,填写SOCK_RAW,表明这是原始socket,这样数据包就不会经过协议栈的处理了。
第三个参数,希望接受到的消息类型。参考If_ether.h中的协议定义,ETH_P_ALL表示不管什么类型的协议都读取。
具体参数介绍请参考man 2 socket
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <linux/if_ether.h>
int main(int argc, char const *argv[])
{
int sock_fd, len;
char buf[BUFSIZ];
sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); //创建socket
if (sock_fd < 0)
{
perror("Create Socket Fail;");
return -1;
}
while (1)
{
len = recvfrom(sock_fd, buf, BUFSIZ, 0,NULL,NULL); //读取来自网卡的数据
if (len > 0)
{
for (size_t i = 0; i < len; i++)
{
printf("%02x", buf[i]);
}
printf("\n");
}
}
close(sock_fd);
return 0;
}