Lab 07: Experiment with ICMP

Goals

Credits

The work is based on discussion at stackoverflow http://stackoverflow.com/questions/15458438/implementing-traceroute-using-icmp-in-c. Additional information comes from Unix Network Programming by W. Richard Stevens, and from the website that discusses the various data structures for IP addresses, https://beej.us/guide/bgnet/output/html/multipage/sockaddr_inman.html.

Introduction

ICMP, or the Internet Control Message Protocol, is a message exchange protocol. It is widely used for various message exchange and information probing at the network layer. Popular tools such as traceroute and ping are examples of ICMP applications. The protocol logically resides within the IP protocol, though in reality it works on top of the IP layer.

This website illustrates the relation between IP and ICMP, as well ICMP header format, the type, and the code that ICMP packet carries.

Traceroute is a program that is available on Linux hosts. One can use this tool to examine the path between the current host and the destination host. For example, the following is a screen capture of using traceroute to see the path from the local host to the host www.example.org

% traceroute www.example.org
traceroute to www.example.org (93.184.216.34), 30 hops max, 60 byte packets
 1  134.82.56.254 (134.82.56.254)  1.132 ms  1.179 ms  1.236 ms
 2  172.30.254.41 (172.30.254.41)  0.364 ms  0.432 ms  0.496 ms
 3  134.82.253.1 (134.82.253.1)  0.912 ms  0.902 ms  0.860 ms
 4  ncc-1701.bucknell.edu (134.82.252.254)  1.203 ms  1.299 ms  1.225 ms
 5  ae-0.590.rtr01.nbrd.net.pennren.net (162.223.16.32)  7.857 ms  7.874 ms  7.850 ms
 6  204.238.76.49 (204.238.76.49)  8.035 ms  7.977 ms  8.036 ms
 7  204.238.76.54 (204.238.76.54)  12.120 ms  12.165 ms  12.172 ms
 8  198.71.47.249 (198.71.47.249)  12.140 ms  12.191 ms  12.190 ms
 9  198-7-25-16.edgecastcdn.net (198.7.25.16)  20.444 ms  20.417 ms  20.449 ms
10  93.184.216.34 (93.184.216.34)  20.145 ms  20.242 ms  20.354 ms

Similarly, one can ping a remote host to see if the remote host is alive and how long would it take to get to the remote host.

% ping www.example.org
PING www.example.org (93.184.216.34) 56(84) bytes of data.
64 bytes from 93.184.216.34: icmp_seq=1 ttl=53 time=20.2 ms
64 bytes from 93.184.216.34: icmp_seq=2 ttl=53 time=20.2 ms
64 bytes from 93.184.216.34: icmp_seq=3 ttl=53 time=20.1 ms
64 bytes from 93.184.216.34: icmp_seq=4 ttl=53 time=20.0 ms
^C
--- www.example.org ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3772ms
rtt min/avg/max/mdev = 20.042/20.176/20.262/0.132 ms

Your tasks

Your tasks in this lab is to implement the traceroute program from a program example found on stackoverflow.

You man find many different traceroute implementations on the internet. You are going to use a particular one as a starting point for your work, download the program, understand what and how it does its work, revise it to fulfill our goals.

Part 1: Preparation

Create a working directory: Create directory lab07 in your csci363/labs/ directory. Your work will be saved in the lab07 directory.

Read the post : Read the stackoverflow post at http://stackoverflow.com/questions/15458438/implementing-traceroute-using-icmp-in-c. Understand what is discussed.

Download the program : The stackoverflow post contains a complete set of code that works after the suggested revision in the Answer section. Copy and paste the code segments into your text editor and save them in two separate files, the header file, and the implementation file. Name the header file as icmp_exp.h and the implementation file as traceroute.c. Note that the original post named the header file libsock. We want to change it to be icmp_exp.h. You'd also change the implementation file to reflect the name change of the header file. Make sure you revise the program from the original post as the Answer suggests.

Compile and run the program : Create a proper Makefile that will compile the source code and create an executable called mytraceroute. Because traceroute is an existing Linux program, we don't want the names to be confused. The syntax of the program should be now correct and you can create an executable by simply doing a make. The program won't run as it is because the local host IP is listed as the author's host IP (172.30.104.59). Search for the pattern and locate where this address is. You need to change this address to your VM's IP address. Once you make this change, you should be able to run on the program on your VM (not on your regular Linux machine as portion of the program requires root privilege.) Give it a try!

% make
% ./mytraceroute 134.82.10.249
% ./mytraceroute 93.184.216.34

The first IP belongs to www.bucknell.edu, the second IP belongs to www.example.org. You can find a few other hosts to trace if you'd like. In particular, try to compare the behavior of this program with that of Linux traceroute. Make sure to try a few sites that are far away.

Once the program is working, you are asked to do a sequence of revisions to make the program better and easier to use. Along the way, you are asked to read some Linux manual pages and pages from the web to answer some technical questions.

Answer some questions : Create an answers.txt file. Record your answers to the following questions in that file. These questions are related to your current version of the program traceroute.c. Label the answers as traceroute questions.

  1. In the socket() system call, the parameters SOCK_RAW and IPPROTO_ICMP are used. What do these two parameters mean? What is the key difference between SOCK_RAW and the ones we used to use such as SOCK_STREAM and SOCK_DGRAM? You probably will need to read manual page section 7 for the subject of raw and for the subject of ip.
  2. Next to the socket() system call, a statement reads
    struct ip *ip_hdr = (struct ip *) buf;
    
    What does it mean? What is the memory address of the variable ip_hdr after this statement?
  3. You were asked to change the IP address from the original 172.30.104.59 to your VM's IP to make the program work on the VM. Try to change it to the IP address of a Linux workstation and run the program on the Linux workstation in the Dana 132 lab. What happens when you run the program on your Linux machine? Now go back and look at the program, what does the parameter IP_HDRINCL in the call setsockopt() mean? (Manual page section 7 for ip should give you answers.) The manual page would say that the application program can supply the IP header, do you see which part of the traceroute.c program builds an IP header? Where?
  4. The library call inet_pton() is used a number of times in traceroute.c. Read the manual page about this call and briefly explain what it does.
  5. The author used a function named csum(). What does it do? What is the key difference between this function and the internet checksum function you wrote? What is the data for which this checksum is computed in this line?
    ip_hdr->ip_sum = csum ((unsigned short *) buf, 9);
    
  6. The next line of the program reads,
    struct icmphdr *icmphd = (struct icmphdr *) (buf + 20);
    
    What does it mean? Why (buf + 20)?
  7. When setting up the ICMP packet header, the program has the following lines.
    icmphd->type = ICMP_ECHO;
    icmphd->code = 0;
    
    What is the numerical value of ICMP_ECHO? You may have to look for it in the file /usr/include/netinet/ip_icmp.h. What does ICMP code zero (0) mean?
  8. When printing the host IP address and hop limit, the program checks for a condition
    if (icmphd2->type != 0)
    
    What does (icmphd2->type == 0) mean here? Find out what is the actual numerical value of the type returned here (other than 0) using either a debugging tool or a print statement. Then find out what that type means by searching for it in ICMP type and code list.
  9. In the last segment of this program, the library call inet_ntoa() is used. Briefly describe what it does. What is the difference between the value that this library function return and its parameter (in our case addr2.sin_addr)?

Part 2: Revise the traceroute.c program

Now you have a working version of the program that can do the work of a regular Linux application traceroute, you are asked to revise the program to make it more user-friendly, and provide other desired features.

  1. Comment and format the program to make it more professional looking. At the least, you should do the following.
  2. The current version of the program uses a hard-coded IP address for the originating host, where the program is running. For example, you'd have to put in the IP for your VM in the program. If you want to run the program in a different machine, you'd have to revise the program to change the IP address to the computer where you run the program. We want to change this behavior. Write a function named get_host_ip() that can retrieve the host IP in its dot-format. There are different ways of doing it. You can use a combination of gethostname() and getaddrinfo(), or getifaddr(). Use the function get_host_ip() to replace the hard-coded IP address in the traceroute.c program.
  3. In a test earlier in this lab, you probably have found out that your program traceroute.c doesn't behave exactly the same as the Linux traceroute. In running mytraceroute, when a router doesn't respond to the echo request, your program will simply wait indefinitely, while the Linux traceroute is able to skip that router by printing a line similar to the following, that is, simply printing a few '*' and continuing on with next router (next hop).
    17  * * *
    18  * * *
    
    You are asked to modify the program to have the same behavior. You need to set the socket receiving timer option so when the timer expires, the recvfrom() call returns a negative value. You need to use the call setsockopt(). Read manual page section 7 for the subject socket for more specific information.
  4. Another difference between your program and the Linux traceroute is that the Linux traceroute prints three time values needed to reach a router (and eventually the destination). Revise your program so that it behaves just like the Linux traceroute in this manner.

Part 3: Read and understand BSD Unix ping program

In the above exercise, we discussed a method of creating customized IP packet (ICMP packet in this case) to accomplish some functionality. The method used there is to provide a valid IP header and packet ICMP packet as the data segment of the IP packet. Another approach is to create the socket using the ICMP as the protocol option as we did before, then provide the ICMP packet information including the ICMP header and the data, and let the TCP/IP software stack build the IP packet using this ICMP packet as its data. This is the approach BSD Unix used.

Copy the source code. Copy the source code of BSD Unix ping program from ~cs363/Spring16/student/labs/lab07 by recursively copying the entire directory to your directory. Among the files you copied, you should a directory named ping. This is a complete working program along with a Makefile. You can ftp this collection of files to your VM, compile and run the program there. The program should work as expected.

Read and explain how the program works. Answer the following questions after reading the program. Label the questions as ping questions. Explain the following:

  1. How the ICMP packet information is encapsulated in the IP packet.
  2. Which part of the program is responsible for periodically sending ICMP packet and how the timing is controlled.
  3. Which part of the program is responsible for receiving the packet as the result of ping.
  4. Where and how the ICMP packet is built.
  5. How the round trip time is computed.

Extra credit work

Revise the program using the pattern in the first part of the lab, that is, build your own IP packet using the ICMP packet as the data for the IP packet.

Congratulations! You just finished this lab.