使用 libpcap 捕获 IP 数据包时遇到问题
Trouble capturing IP packets with 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 header ,奇怪的版本号等。
这是一个输出这个的片段:
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 header 版本怎么了?
- IP header 长度怎么能低于 20 字节?
发现问题...
eth = (struct sniff_ethernet*)(packet);
ip = (struct sniff_ip*)(eth + 14); /* should be (packet + 14) */
'smart' C 指针算法不添加 14 个字节,但 14*sizeof(struct sniff_ethernet)
。
首先是结构:
/* 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 header ,奇怪的版本号等。
这是一个输出这个的片段:
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 header 版本怎么了?
- IP header 长度怎么能低于 20 字节?
发现问题...
eth = (struct sniff_ethernet*)(packet);
ip = (struct sniff_ip*)(eth + 14); /* should be (packet + 14) */
'smart' C 指针算法不添加 14 个字节,但 14*sizeof(struct sniff_ethernet)
。