如何在 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() 等例程。