I am spending my sunday on understanding packet sniffing with libpcap and I came so far that I can read packets and metadata. When I was checking my code by sniffing on some packets, I found that I must have an error somewhere.
When I sniff the webpage from my father: http://www.telpho.de , I get the whole server response back. Starting from 200 OK until ... But on each packet, there are 4 bytes in the beginning which are not ASCII. In the code below, when i change the for loop to (i = 0), the 4 bytes get printed as well. When i leave it at (i = 4), then the payload gets displayed perfectly from the first ASCII character received.
My question now, do I calculate data_offset wrong? Are there any flags which I didnt set? Did i forgot to count the tcp options in ?
I also thought it has maybe to do with padding. The TCP standard says that the TCP header length should be a multiple of 32. But 32 - 20 = 12.. so this are 3 bytes difference.
Could it for example be that the calculation is like this?
TCP_HDR_SIZE = 32
sizeof(struct tcphdr) = 20
tcp->doff = 8
sizeof(struct tcphdr) + tcp->doff = 28
TCP_HDR_SIZE - 28 = 4 <--- the 4 bytes i am looking for??? Maybe options?
Here is the code:
void handle_packet_ip(const struct pcap_pkthdr *header, const u_char* data) {
struct ip *ip;
struct tcphdr *tcp;
int ip_len;
int data_offset;
int payload_len;
int i;
unsigned char* payload;
ip = (struct ip*)(data + sizeof(struct ether_header));
ip_len = (ip->ip_hl & 0x0f) * 4;
tcp = (struct tcphdr*)(data + sizeof(struct ether_header) + ip_len);
printf("sizeof(ip): %d\n", sizeof(struct ip));
printf("ip_len: %d\n", ip_len);
printf("sizeof(ether_header): %d\n", sizeof(struct ether_header));
printf("sizeof(tcp): %d\n", sizeof(struct tcphdr));
data_offset = sizeof(struct ether_header) + ip_len + sizeof(struct tcphdr) + tcp->doff;
payload_len = header->len - data_offset;
payload = (unsigned char*)(data + data_offset);
printf("IP PACKET\n");
printf("\tlen: %u\n", ntohs(ip->ip_len));
printf("\tsrc: %s\n", inet_ntoa(ip->ip_src));
printf("\tdst: %s\n", inet_ntoa(ip->ip_dst));
printf("\thl: %d\n", (ip->ip_hl & 0x0f));
printf("READ TCP\n");
printf("\tsrc port: %u\n", ntohs(tcp->source));
printf("\tdst port: %u\n", ntohs(tcp->dest));
printf("\tdata_offset: %d\n", data_offset);
printf("\tdoff: %d-%d\n", tcp->doff, ntohs(tcp->doff));
printf("\tpayload len: %d\n", payload_len);
printf("\tFLAGS\n");
printf("\t\tFIN: %i\n", tcp->fin);
printf("\t\tSYN: %i\n", tcp->syn);
printf("\t\tACK: %i\n", tcp->ack);
printf("PAYLOAD: \n");
**for (i = 4; i < payload_len; ++i) {**
printf("%c", payload[i]);
}
printf("\n");
printf("\n");
printf("END OF PAYLOAD\n");
}
Output:
Grabbed Packet:
Length: 74
Capture Length: 74
sizeof(ip): 20
ip_len: 20
sizeof(ether_header): 14
sizeof(tcp): 20
IP PACKET
len: 60
src: 80.237.132.106
dst: 192.168.0.17
hl: 5
READ TCP
src port: 80
dst port: 57662
data_offset: 62 **this should be 64 ??**
doff: 8
payload len: 10
FLAGS
FIN: 0
SYN: 1
ACK: 1