From this example
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);
}
variable size is, I guess, the size of the header. How do I get the size of the whole packet?
Also, how do I convert uint32_t IP addresses to human readable IP addresses of the form xxx.xxx.xxx.xxx?
variable size is, I guess, the size of the header.
You have guessed incorrectly.
To quote the pcap man page:
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).
so "len" is the total length of the packet. However, there may not be "len" bytes of data available; if the capture was done with a "snapshot length", for example with tcpdump, dumpcap, or TShark using the -s
option, the packet could have been cut short, and "caplen" would indicate how many bytes of data you actually have.
Note, however, that Ethernet packets have a minimum length of 60 bytes (not counting the 4-byte FCS at the end, which you probably won't get in your capture), including the 14-byte Ethernet header; this means that short packets must be padded. 60-14 = 46, so if a host sends, over Ethernet, an IP packet that's less than 46 bytes long, it must pad the Ethernet packet.
This means that the "len" field gives the total length of the Ethernet packet, but if you subtract the l4 bytes of Ethernet header from "len", you won't get the length of the IP packet. To get that, you'll need to look in the IP header at the "total length" field. (Don't assume it'll be less than or equal to the value of "len" - 14 - a machine might have sent an invalid IP packet.)
Also, how do I convert uint32_t IP addresses to human readable IP addresses of the form xxx.xxx.xxx.xxx?
By calling routines such as inet_ntoa()
, inet_ntoa_r()
, or inet_ntop()
.