如何在 libpcap 中获取数据包长度和 IP 地址
How do I get packet length and ip addresses in libpcap
来自this示例
void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *buffer)
{
int size = header->len;
//Get the IP Header part of this packet , excluding the ethernet header
struct iphdr *iph = (struct iphdr*)(buffer + sizeof(struct ethhdr));
++total;
switch (iph->protocol) //Check the Protocol and do accordingly...
{
case 1: //ICMP Protocol
++icmp;
print_icmp_packet( buffer , size);
break;
case 2: //IGMP Protocol
++igmp;
break;
case 6: //TCP Protocol
++tcp;
print_tcp_packet(buffer , size);
break;
case 17: //UDP Protocol
++udp;
print_udp_packet(buffer , size);
break;
default: //Some Other Protocol like ARP etc.
++others;
break;
}
printf("TCP : %d UDP : %d ICMP : %d IGMP : %d Others : %d Total : %d\r", tcp , udp , icmp , igmp , others , total);
}
我猜可变大小是 header 的大小。如何获取整个数据包的大小?
此外,如何将 uint32_t IP 地址转换为 xxx.xxx.xxx.xxx 形式的人类可读 IP 地址?
不是,header->len
是这个数据包的长度,就是你想要的。
查看头文件pcap.h
struct pcap_pkthdr {
struct timeval ts; /* time stamp */
bpf_u_int32 caplen; /* length of portion present */
bpf_u_int32 len; /* length this packet (off wire) */
};
您可以使用 sprintf()
将 uint32_t ip
字段转换为 xxx.xxx.xxx.xxx
variable size is, I guess, the size of the header.
你猜错了
引用 pcap 手册页:
Packets are read with pcap_dispatch() or pcap_loop(), which
process one or more packets, calling a callback routine for each
packet, or with pcap_next() or pcap_next_ex(), which return the
next packet. The callback for pcap_dispatch() and pcap_loop() is
supplied a pointer to a struct pcap_pkthdr, which includes the
following members:
ts a struct timeval containing the time when the packet
was captured
caplen a bpf_u_int32 giving the number of bytes of the
packet that are available from the capture
len a bpf_u_int32 giving the length of the packet, in
bytes (which might be more than the number of bytes
available from the capture, if the length of the
packet is larger than the maximum number of bytes to
capture).
所以"len"是数据包的总长度。但是,可能没有 "len" 字节的可用数据;如果捕获是使用 "snapshot length" 完成的,例如使用 tcpdump、dumpcap 或 TShark 使用 -s
选项,则数据包可能已被截短,并且 "caplen" 将指示多少字节您实际拥有的数据。
但是请注意,以太网数据包的最小长度为 60 字节(不包括末尾的 4 字节 FCS,您可能不会在捕获中获得),包括 14 字节以太网 header;这意味着必须填充短数据包。 60-14 = 46,因此如果主机通过以太网发送长度小于 46 字节的 IP 数据包,它必须填充以太网数据包。
这意味着"len"字段给出了以太网数据包的总长度,但是如果从[中减去以太网header的l4字节=33=],你不会得到IP包的长度。为此,您需要在 "total length" 字段中查看 IP header。 (不要假设它会小于或等于 "len" 的值 - 14 - 机器可能发送了无效的 IP 数据包。)
Also, how do I convert uint32_t IP addresses to human readable IP addresses of the form xxx.xxx.xxx.xxx?
通过调用 inet_ntoa()
、inet_ntoa_r()
或 inet_ntop()
等例程。
来自this示例
void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *buffer)
{
int size = header->len;
//Get the IP Header part of this packet , excluding the ethernet header
struct iphdr *iph = (struct iphdr*)(buffer + sizeof(struct ethhdr));
++total;
switch (iph->protocol) //Check the Protocol and do accordingly...
{
case 1: //ICMP Protocol
++icmp;
print_icmp_packet( buffer , size);
break;
case 2: //IGMP Protocol
++igmp;
break;
case 6: //TCP Protocol
++tcp;
print_tcp_packet(buffer , size);
break;
case 17: //UDP Protocol
++udp;
print_udp_packet(buffer , size);
break;
default: //Some Other Protocol like ARP etc.
++others;
break;
}
printf("TCP : %d UDP : %d ICMP : %d IGMP : %d Others : %d Total : %d\r", tcp , udp , icmp , igmp , others , total);
}
我猜可变大小是 header 的大小。如何获取整个数据包的大小?
此外,如何将 uint32_t IP 地址转换为 xxx.xxx.xxx.xxx 形式的人类可读 IP 地址?
不是,header->len
是这个数据包的长度,就是你想要的。
查看头文件pcap.h
struct pcap_pkthdr {
struct timeval ts; /* time stamp */
bpf_u_int32 caplen; /* length of portion present */
bpf_u_int32 len; /* length this packet (off wire) */
};
您可以使用 sprintf()
将 uint32_t ip
字段转换为 xxx.xxx.xxx.xxx
variable size is, I guess, the size of the header.
你猜错了
引用 pcap 手册页:
Packets are read with pcap_dispatch() or pcap_loop(), which
process one or more packets, calling a callback routine for each
packet, or with pcap_next() or pcap_next_ex(), which return the
next packet. The callback for pcap_dispatch() and pcap_loop() is
supplied a pointer to a struct pcap_pkthdr, which includes the
following members:
ts a struct timeval containing the time when the packet
was captured
caplen a bpf_u_int32 giving the number of bytes of the
packet that are available from the capture
len a bpf_u_int32 giving the length of the packet, in
bytes (which might be more than the number of bytes
available from the capture, if the length of the
packet is larger than the maximum number of bytes to
capture).
所以"len"是数据包的总长度。但是,可能没有 "len" 字节的可用数据;如果捕获是使用 "snapshot length" 完成的,例如使用 tcpdump、dumpcap 或 TShark 使用 -s
选项,则数据包可能已被截短,并且 "caplen" 将指示多少字节您实际拥有的数据。
但是请注意,以太网数据包的最小长度为 60 字节(不包括末尾的 4 字节 FCS,您可能不会在捕获中获得),包括 14 字节以太网 header;这意味着必须填充短数据包。 60-14 = 46,因此如果主机通过以太网发送长度小于 46 字节的 IP 数据包,它必须填充以太网数据包。
这意味着"len"字段给出了以太网数据包的总长度,但是如果从[中减去以太网header的l4字节=33=],你不会得到IP包的长度。为此,您需要在 "total length" 字段中查看 IP header。 (不要假设它会小于或等于 "len" 的值 - 14 - 机器可能发送了无效的 IP 数据包。)
Also, how do I convert uint32_t IP addresses to human readable IP addresses of the form xxx.xxx.xxx.xxx?
通过调用 inet_ntoa()
、inet_ntoa_r()
或 inet_ntop()
等例程。