我有这个代码,它应该从我正在收听的套接字打印每个数据包的目标和源MAC地址:
sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);
if(sock_raw < 0)
{
printf("Socket Error\n");
return 1;
}
while(1)
{
saddr_size = sizeof saddr;
//Receive a packet
data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , (socklen_t*)&saddr_size);
if(data_size <0 )
{
printf("Recvfrom error , failed to get packets\n");
return 1;
}
//Now process the packet
ProcessPacket(buffer , data_size);
}
close(sock_raw);
............
fprintf(logfile,"\n###########################################################");
struct ether_header *ethh;
ethh = (struct ether_header *)Buffer;
fprintf(logfile,"\n\n***********************ETHERNET Packet*************************\n");
fprintf(logfile,"\n");
fprintf(logfile,"Ethernet Header\n");
fprintf(logfile," |-Source Address : %s\n", ether_ntoa((struct ether_addr *)ðh->ether_dhost));
fprintf(logfile," |-Destination Address : %s\n", ether_ntoa((struct ether_addr *)ðh->ether_shost));
fprintf(logfile,"\n");
fprintf(logfile,"\n###########################################################");
问题是当我运行ping或其他东西时,我希望在我的ether_addr结构的ether_dhost变量中看到我正在侦听的PC的MAC。但是,从该变量打印的MAC不是我的。更多的源MAC不是我所期望的。
有人可以向我解释发生了什么,并可能为我的代码提供修复程序吗?
谢谢!
答案 0 :(得分:1)
在sock_raw手册页中,“Raw套接字允许在用户空间中实现新的IPv4协议。原始套接字接收或发送不包含链路级头的原始数据报。”因此,在您的示例中,即使您将缓冲区转换为以太网头结构,您实际上也没有获得以太网头。
要接收以太网标头,您需要一个AF_PACKET套接字。这是您的代码的调整版本,应该做您想要的。
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <arpa/inet.h>
static FILE *logfile;
static void ProcessPacket(const void *Buffer, ssize_t data_size) {
fprintf(logfile,"\n###########################################################");
struct ether_header *ethh;
ethh = (struct ether_header *)Buffer;
fprintf(logfile,"\n\n***********************ETHERNET Packet*************************\n");
fprintf(logfile,"\n");
fprintf(logfile,"Ethernet Header\n");
fprintf(logfile," |-Source Address : %s\n", ether_ntoa((struct ether_addr *)ðh->ether_dhost));;
fprintf(logfile," |-Destination Address : %s\n", ether_ntoa((struct ether_addr *)ðh->ether_shost));
fprintf(logfile,"\n");
fprintf(logfile,"\n###########################################################");
}
int main(int argc, char **argv) {
logfile = stdout;
int sock_raw = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
char buffer[65536];
if(sock_raw < 0)
{
printf("Socket Error\n");
return 1;
}
while(1)
{
//Receive a packet
ssize_t data_size = recvfrom(sock_raw , buffer , sizeof(buffer) , 0 , NULL, NULL);
if(data_size <0 )
{
printf("Recvfrom error , failed to get packets\n");
break;
}
//Now process the packet
ProcessPacket(buffer , data_size);
}
close(sock_raw);
return 0;
}