I have an IP packet stored in a char buffer:
char packet[] = "450000CC68C4000001114C4F0A0A0A0AEFFFFFFADEA9076C00B832074D2D534541524348202A20485454502F312E310D0A484F53543A203233392E3235352E3235352E3235303A313930300D0A4D414E3A2022737364703A646973636F766572220D0A4D583A20310D0A53543A2075726E3A6469616C2D6D756C746973637265656E2D6F72673A736572766963653A6469616C3A310D0A555345522D4147454E543A20476F6F676C65204368726F6D652F3130372E302E353330342E313130204D6163204F5320580D0A0D0A"
I am try to parse this IP header using netinet/ip.h ip definition.
But when i try to print the ip packet details like ip header length, it is printing garbage:
#include <netinet/ip.h>
void decodeIPPacket(const char *packet)
{
struct ip *ipHdr = (struct ip*)(long)packet;
printf("decodeIPPacket:: IP Len: %d", ipHdr->ip_len);
printf("decodeIPPacket:: srcip: %u", ipHdr->ip_src.s_addr);
printf("decodeIPPacket:: dstip: %u", ipHdr->ip_dst.s_addr);
}
decodeIPPacket:: IP Len: 12336
decodeIPPacket:: srcip: 808464432
decodeIPPacket:: dstip: 825307440
What am i doing wrong here?
Every character in your string represent a nybble in hexadecimal. You need to convert every 2 char
from ASCII to hexadecimal as a byte.
#include <netinet/ip.h>
#include <stdio.h>
#include <string.h>
char string[] =
"450000CC68C4000001114C4F0A0A0A0AEFFFFFFADEA9076C00B832074D2D53454152434820"
"2A20485454502F312E310D0A484F53543A203233392E3235352E3235352E3235303A313930"
"300D0A4D414E3A2022737364703A646973636F766572220D0A4D583A20310D0A53543A2075"
"726E3A6469616C2D6D756C746973637265656E2D6F72673A736572766963653A6469616C3A"
"310D0A555345522D4147454E543A20476F6F676C65204368726F6D652F3130372E302E3533"
"30342E313130204D6163204F5320580D0A0D0A";
int main() {
char *pos = string;
int packetLen = strlen(string) / 2;
unsigned char packet[packetLen];
struct sockaddr_in source, dest;
/* Read only 20 bytes (40 nybbles)
* to store only IPv4 header.
* NOTE: IPv4 header is not always
* 20 bytes. Can contain 'options' field.
* You have to extract ihl value first.
*/
for (size_t i = 0; i < 40; ++i) {
sscanf(pos, "%2hhx", &packet[i]);
pos += 2;
}
struct iphdr *iph = (struct iphdr *)packet;
memset(&source, 0, sizeof(source));
source.sin_addr.s_addr = iph->saddr;
memset(&dest, 0, sizeof(dest));
dest.sin_addr.s_addr = iph->daddr;
printf("IP Version: %d\n", (unsigned int)iph->version);
printf("IP Header Length: %d Bytes\n", ((unsigned int)(iph->ihl)) * 4);
printf("Type Of Service: %d\n", (unsigned int)iph->tos);
printf("IP Total Length: %d Bytes(Size of Packet)\n",
ntohs(iph->tot_len));
printf("Identification: %d\n", ntohs(iph->id));
printf("TTL: %d\n", (unsigned int)iph->ttl);
printf("Protocol: %d\n", (unsigned int)iph->protocol);
printf("Checksum: %d\n", ntohs(iph->check));
printf("Source Adddress: %.4x\n", source.sin_addr);
}
Output:
IP Version: 4
IP Header Length: 20 Bytes
Type Of Service: 0
IP Total Length: 204 Bytes(Size of Packet)
Identification: 26820
TTL: 1
Protocol: 17
Checksum: 19535
Source Adddress: a0a0a0a
Destination Adddress: faffffef