I'm trying to extract tcp payload from a packet , and here's a minimal case of capture callback:
void capture_callback (u_char *hdr , const struct pcap_pkthdr* pkthdr , const u_char* buff)
{
struct ether_header *eptr = (struct ether_header *) buff;
buff += sizeof (ether_header); /* jump over ethernet header: 14 bytes */
if ( ntohs (eptr->ether_type) == ETHERTYPE_IP )
{
struct ip *iph;
struct tcphdr *tcp_header;
iph = (struct ip *) buff;
buff += sizeof (ip); /* jump over ip header */
if ( iph->ip_p == IPPROTO_TCP )
{
tcp_header = (struct tcphdr *) buff;
buff += sizeof (tcphdr); /* jump over tcp header */
cout << inet_ntoa (iph->ip_src) << ":" << ntohs (tcp_header->th_sport) <<
" --> " << inet_ntoa(iph->ip_dst) << ":" << ntohs (tcp_header->th_dport) << endl;
}
}
}
But something went wrong here , source and destination IP address are the same.
And besides , how can i print out payload ? Since i can't just convert a unsigned char array to a char array explicitly, which ends on "\0" , it might get wrong.
192.168.56.1:48065 --> 192.168.56.1:80
192.168.56.80:80 --> 192.168.56.80:48065
EDIT
---------------------
THanks to Celeda , i solved the ip address issue by separating the call of inet_ntoa:
cout << "IP: " << inet_ntoa (iph->ip_src) << ":" << ntohs (tcp_header->th_sport) <<
" --> ";
cout << inet_ntoa(iph->ip_dst) << ":" << ntohs (tcp_header->th_dport) << endl;
And now the second part , i'm using:
cout << hex << buff << endl;
For HTTP protocol , and i'm not seeing anything like "GET /" , but multiple blank line
EDIT 2
--------------------------
I'm not so sure about TCP options for now , i'll check more documents about details , but for now this functions well.
if ( iph->ip_p == IPPROTO_TCP )
{
tcp_header = (struct tcphdr *) buff;
buff += tcp_header->th_off * 4;
cout << "IP: " << inet_ntoa (iph->ip_src) << ":" << ntohs (tcp_header->th_sport) <<
" --> ";
cout << inet_ntoa(iph->ip_dst) << ":" << ntohs (tcp_header->th_dport) << endl;
for ( int i = 0 ; i < iph->ip_len - iph->ip_off * 4; i ++ )
{
if ( isascii (buff[i]) )
{
cout << buff[i];
}
}
cout << endl << "-----------" << endl;
}
buffis not quite pointing to the right place. I see you dobuff += sizeof (tcphdr)but maybe there are TCP options you need to skip over as well. I also don't know C++ so I'm not sure whathex << buffactually does. Yet I suspect it expects a NUL-terminated string; I think you need to use some function that takes a length as input so it won't go beyond the end of the packet. - Celada