使用libpcap捕获IP数据包时遇到问题

时间:2015-03-02 12:00:47

标签: endianness libpcap

首先是结构:

/* Ethernet addresses are 6 bytes */
#define ETHER_ADDR_LEN  6

/* Ethernet header */
struct sniff_ethernet {
    u_char ether_dhost[ETHER_ADDR_LEN]; /* Destination host address */
    u_char ether_shost[ETHER_ADDR_LEN]; /* Source host address */
    u_short ether_type; /* IP? ARP? RARP? etc */
};
#define ETHERTYPE_IP        0x0800      /* IP */

/* IP header */
struct sniff_ip {
    u_char ip_vhl;      /* version << 4 | header length >> 2 */
    u_char ip_tos;      /* type of service */
    u_short ip_len;     /* total length */
    u_short ip_id;      /* identification */
    u_short ip_off;     /* fragment offset field */
    u_char ip_ttl;      /* time to live */
    u_char ip_p;        /* protocol */
    u_short ip_sum;     /* checksum */
    struct in_addr ip_src,ip_dst; /* source and dest address */
};
#define IP_HL(ip)       (((ip)->ip_vhl) & 0x0f)
#define IP_V(ip)        (((ip)->ip_vhl) >> 4)

我已使用pcap_open_live打开了网络设备,pcap_datalink为该设备的DLT_EN10MB,但我收到了大量长度为0,版本号怪异等的IP标头。 这是一个输出这个的片段:

    eth = (struct sniff_ethernet*)(packet);
    ip = (struct sniff_ip*)(eth + 14); /* ETHERNET = 14 */
    int version_ip = IP_V(ip);
    int size_ip = IP_HL(ip)*4;

     printf("caplen=%d len=%d eth->type=%d version_ip=%d size_ip=%d !\n", header.caplen, header.len, eth->ether_type, version_ip, size_ip);

一些示例输出:

caplen=94 len=94 eth->type=8 version_ip=0 size_ip=0 !
caplen=159 len=159 eth->type=8 version_ip=9 size_ip=12 !
caplen=110 len=110 eth->type=8 version_ip=0 size_ip=12 !
caplen=200 len=336 eth->type=8 version_ip=4 size_ip=20 ! (this one is OK)

这里发生了什么?

  • 为什么eth类型为0x0008而不是0x0800?字节序?
  • 奇怪的IP头版本有什么用?
  • IP报头长度如何低于20个字节?

1 个答案:

答案 0 :(得分:0)

发现问题......

eth = (struct sniff_ethernet*)(packet);
ip = (struct sniff_ip*)(eth + 14); /* should be (packet + 14) */

'智能'C指针算术不会增加14个字节,而是14*sizeof(struct sniff_ethernet)