在C代码中打印的MAC不正确

时间:2013-05-25 19:30:53

标签: c sockets ethernet mac-address

我有这个代码,它应该从我正在收听的套接字打印每个数据包的目标和源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 *)&ethh->ether_dhost));
fprintf(logfile,"   |-Destination Address : %s\n", ether_ntoa((struct ether_addr *)&ethh->ether_shost));
fprintf(logfile,"\n");
fprintf(logfile,"\n###########################################################");

问题是当我运行ping或其他东西时,我希望在我的ether_addr结构的ether_dhost变量中看到我正在侦听的PC的MAC。但是,从该变量打印的MAC不是我的。更多的源MAC不是我所期望的。

有人可以向我解释发生了什么,并可能为我的代码提供修复程序吗?

谢谢!

1 个答案:

答案 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 *)&ethh->ether_dhost));;
    fprintf(logfile,"   |-Destination Address : %s\n", ether_ntoa((struct ether_addr *)&ethh->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;
}