如何在libpcap中获取数据包长度和IP地址

时间:2015-07-08 03:09:13

标签: linux tcp udp 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);
}

我猜,可变大小是标头的大小。如何获得整个数据包的大小?

另外,如何将uint32_t IP地址转换为xxx.xxx.xxx.xxx格式的人类可读IP地址?

2 个答案:

答案 0 :(得分:1)

  

我猜,可变大小是标题的大小。

你猜错了。

引用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"可用数据字节;如果捕获是使用"快照长度"完成的,例如使用-s选项使用tcpdump,dumpcap或TShark,则数据包可能已被缩短,并且" caplen&# 34;表示你实际拥有多少字节的数据。

但请注意,以太网数据包的最小长度为60个字节(不包括最后的4字节FCS,您可能无法获得捕获),包括14字节以太网接头;这意味着必须填充短数据包。 60-14 = 46,所以如果主机通过以太网发送长度小于46字节的IP数据包,它必须填充以太网数据包。

这意味着" len" field给出了 Ethernet 数据包的总长度,但是如果你从" len"中减去以太网头的l4字节,你将无法获得IP数据包的长度。为此,您需要在"总长度"中查找IP标头。领域。 (不要认为它会小于或等于" len" - 14 - 机器可能发送了无效的IP数据包。)

  

另外,如何将uint32_t IP地址转换为xxx.xxx.xxx.xxx格式的人类可读IP地址?

通过调用inet_ntoa()inet_ntoa_r()inet_ntop()等例程。

答案 1 :(得分:0)

不,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