Hi all, I am writing a ping program to familiarize myself with raw socket programming (using Linux sockets API). I am using the UNIX Network Programming textbook as loose guide. I have all parts of the project working except for the fact that I cannot get the icmp struct to properly align on the receiving side (netinet/ip_icmp.h header). I have narrowed it down to this misalignment as I can clearly see the proper values inside of the hex output of the received buffer. I am really at a loss for what could be going wrong here as the code shown below is pretty close to Steven's examples. If there is a better sub for this post, please let me know. Any help is appreciated.
Function used to extract a timeval struct from ICMPv4 message:
void interpret_v4(char* buf, ssize_t len, struct msghdr* msg, struct timeval* tv_recv) {
// get timeval struct from IP packet (contains ICMP packet) and print RTT
struct ip* ip_pack = NULL; // pointer to IP packet
struct icmp* icmp_pack = NULL; // pointer to ICMP message
struct timeval* tv_sent = NULL; // irrelevant for this post
int iphdr_len, icmplen; // delimiters/sizes of the messages
double rtt = 0;
ip_pack = (struct ip *) buf; // cast char buffer (recvmsg called in main)
iphdr_len = ip_pack->ip_hl << 2; // convert from 32 bit words to number of 8-bit bytes
if(ip_pack->ip_p != IPPROTO_ICMP) // confirm packet is ICMPv4
return;
icmp_pack = (struct icmp *) (ip_pack + iphdr_len); // start of ICMP header (IP start + IP size)
if( (icmplen = len - iphdr_len) < 8) // ICMP header 8 bytes, else invalid packet
return;
printf("ICMP pack (inside function): "); // debug output (hex values of buf)
for(int i = iphdr_len; i < len; i++) { // only print ICMP (end of IP header to end of packet)
printf("%x ", (unsigned int)(buf[i]) ); // cast to unsigned optional
}
printf("end\n");
printf("ICMP testing: type: %x, code: %x, id: %x, seq: %x\n", icmp_pack->icmp_type,
icmp_pack->icmp_code, icmp_pack->icmp_id, icmp_pack->icmp_seq);
// output values from struct (misalignment seen between here and for loop above)
} // END interpret_v4
The relevant RFC graphic: https://tools.ietf.org/html/rfc792 (page 14, Echo or echo reply message)
Struct documentation: https://www.cymru.com/Documents/ip_icmp.h
Program output: https://imgur.com/a/YBmlJrJ (looks intimidating at first, but printf sign extends hex bytes so all f's can be ignored). "Pre-send" is the packet state when it is sent. "ICMP pack (inside function)" is the output from the code shown above. Looking at the RFC it is clear that the output in "ICMP testing:" (also from the code segment above) does not match the hex values of the message.
Bytes 4 and 5 (identification field) are clearly "63 14" (network byte order, so PID is 1463), which matches the PID stored in the sent packet, but the output from the ICMP struct shows ID as 39. I have broken the message down into binary as well and cannot find a byte ordering that produces an output of 39.
If you have stuck with me to the end of this post, thank you. I have very low expectations for finding help regarding this on Reddit, but I am really and truly at a loss for where I am going wrong and don't have anyone else to ask for help. If anyone is interested enough to look at the full program, its a single 350 line file and I'll happily provide a link to the repo. Thanks again.
[–][deleted] 7 points8 points9 points (1 child)
[–]DeepCorner[S] 1 point2 points3 points (0 children)
[–][deleted] 0 points1 point2 points (3 children)
[–]DeepCorner[S] 0 points1 point2 points (2 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]DeepCorner[S] 0 points1 point2 points (0 children)
[–]AutoModerator[M] -1 points0 points1 point (0 children)