2017-04-27 121 views
0

我正在使用libpcap解码一些ip数据包。有关使用libpcap的以太网/ IP标头主机/地址的问题?

但我发现以太网ether_shost/ether_dhost和ip saddr/daddr解码都是一样的。

我在哪里搞砸了?

在此先感谢。

这里的回调函数的一部分:

void 
got_packet(u_char *args, const struct pcap_pkthdr *header, 
    const u_char *packet) 
{ 
    ... 
    eth_h = (struct ether_header *) packet; 
    struct ether_addr shost, dhost; 
    memcpy(&shost, eth_h->ether_shost, sizeof(shost)); 
    memcpy(&dhost, eth_h->ether_dhost, sizeof(dhost)); 
    printf("L2 DLT_EN10MB: %s -> %s\n", ether_ntoa(&shost), ether_ntoa(&dhost)); // shost == dhost? 

    if (ntohs(eth_h->ether_type) != ETHERTYPE_IP) { 
     return; 
    } 

    // only work for L2 DLT_EN10MB 
    ip_h = (struct iphdr *) (packet + sizeof(struct ether_header)); 
    if (ip_h->version != 4) { 
     return; 
    } 

    struct in_addr saddr, daddr; 
    saddr.s_addr = ip_h->saddr; 
    daddr.s_addr = ip_h->daddr; 

    printf("%s -> %s\n", inet_ntoa(saddr), inet_ntoa(daddr)); // saddr == daddr? 
    printf("%" PRIu32 " -> %" PRIu32 "\n", ntohl(ip_h->saddr), ntohl(ip_h->daddr)); // actually not the same 
    ... 
} 

回答

1

inet_ntoa执行以下操作:

  • 放地址的字符串形式到缓冲区
  • 返回缓冲区的地址

关键是它使用了相同缓冲每次你打电话给它!

所以,当这条线运行:

printf("%s -> %s\n", inet_ntoa(saddr), inet_ntoa(daddr)); 

首先它会放一个地址在缓冲区中,然后它会把其他地址在缓冲区中,然后将打印缓冲区的内容两倍。

你可以通过存储在自己单独的缓冲区中的字符串解决这个问题:

char saddr_str[INET_ADDRSTRLEN]; 
char daddr_str[INET_ADDRSTRLEN]; 
strcpy(saddr_str, inet_ntoa(saddr)); 
strcpy(daddr_str, inet_ntoa(daddr)); 
printf("%s -> %s\n", saddr_str, daddr_str); 

或致电printf两次:

printf("%s -> ", inet_ntoa(saddr)); 
printf("%s\n", inet_ntoa(daddr)); 

 

ether_ntoa有同样的问题。