CS 422

Lab 1: Writing a Packet Analyzer

Due Date: February 21st, 2008, 11:59pm.

Frequently Asked Questions

Example of how  to use gethostbyaddr(): iptoname.c

IMPORTANT

This project will be graded in the machines in the lab (sslab01 to sslab25) so make sure it runs in this environment.

As you have noticed, the compiler in this environment is a 64 bit compiler so you have to consider this in your implementation.

Purpose Of The Lab The objective of this lab is to show students the details of  TCP/IP datagrams.

Background Reading And Work

To complete this lab assignment, you need to understand the format of IP, ICMP, UDP, TCP, and ARP datagrams, which are explained in your textbook. Another good reference is available here.

You also need to understand the meaning of the terms network byte order and host byte order. Finally, familiarize yourself with the functions: ntohs and ntohl.

PSO presentation slides are available here.

Overview

Most of the ethernet frames that you will find in an ethernet are either ARP or IP packets. ARP (Address Resolution Protocol) is a protocol that is used to obtain mappings from IP addresses to hardware addresses. IP packets are the basic transfer unit on the TCP/IP internet. The ethernet type field in the ethernet frame is used to distinguish what kind of packet (ARP or IP) is encapsulated in the ethernet frame data area. Here are some assigned values for  the ethernet type field:
/* Some Assigned Ethernet Type Numbers */

#define EPT_IP          0x0800          /* type: Internet Protocol      */
#define EPT_ARP         0x0806          /* type: ARP                    */

ICMP, UDP, and TCP are protocols that run on top of IP. This means that packets that belong to these protocols are encapsulated in the data section of IP packets. The ip_proto field in the IP header specifies the encapsulated protocol. Here are some assigned protocol numbers that you will find in the ip_proto field:
/* Some Assigned Protocol Numbers */

#define IPT_ICMP        1       /* protocol type for ICMP packets       */
#define IPT_TCP         6       /* protocol type for TCP packets        */
#define IPT_UDP         17      /* protocol type for UDP packets        */

ARP packets are encapsulated directly on the ethernet frame data area.

Writing the analyze Command

In this lab you will  write a command analyze to decode IP, ICMP, UDP, TCP, and ARP datagrams.
% analyze filename
analyze will print the different headers of the captured packets in the file filename in the following way:
  1. It will print the ethernet header in the way indicated below.
  2. If the ethernet frame contains an IP packet, then it prints the IP header, (the format of the output is described below).
    1. If the IP packet encapsulates an ICMP packet, then it prints the ICMP header.
    2. If the IP packet encapsulates an UDP packet, then it prints the UDP header and a few data bytes.
    3. If the IP packet encapsulates a TCP header, then it prints the TCP header and a few data bytes.
  3. If the ethernet frame contains an ARP packet, it prints the ARP header.
Your program should display the fields of the datagram header as shown below:

ETHER:  ----- Ether Header -----
ETHER:  
ETHER:  Packet size = 178 bytes
ETHER:  Destination = 8:0:20:1c:f:ee, 
ETHER:  Source      = 0:c0:4f:79:ed:87, 
ETHER:  Ethertype = 0800 (IP)
ETHER:  
IP:   ----- IP Header -----
IP:   
IP:   Version = 4
IP:   Header length = 20 bytes
IP:   Type of service = 0x00
IP:         xxx. .... = 0 (precedence)
IP:         ...0 .... = normal delay
IP:         .... 0... = normal throughput
IP:         .... .0.. = normal reliability
IP:   Total length = 164 bytes
IP:   Identification = 32484
IP:   Flags = 0x4
IP:         .1.. .... = do not fragment
IP:         ..0. .... = last fragment
IP:   Fragment offset = 0 bytes
IP:   Time to live = 255 seconds/hops
IP:   Protocol = 6 (TCP)
IP:   Header checksum = e6f5
IP:   Source address = 128.10.3.106, xinu6.cs.purdue.edu
IP:   Destination address = 128.10.3.10, ector.cs.purdue.edu
IP:   No options
IP:   
TCP:  ----- TCP Header -----
TCP:  
TCP:  Source port = 708
TCP:  Destination port = 2049 (Sun RPC)
TCP:  Sequence number = 1438029708
TCP:  Acknowledgement number = 3430040415
TCP:  Data offset = 20 bytes
TCP:  Flags = 0x18
TCP:        ..0. .... = No urgent pointer
TCP:        ...1 .... = Acknowledgement
TCP:        .... 1... = Push
TCP:        .... .0.. = No reset
TCP:        .... ..0. = No Syn
TCP:        .... ...0 = No Fin
TCP:  Window = 8760
TCP:  Checksum = 0x921e
TCP:  Urgent pointer = 0
TCP:  No options
TCP:  
TCP:  Data: (first 64 bytes) 
... Note: Data has been stripped...

ETHER:  ----- Ether Header -----
ETHER:  
ETHER:  Packet size = 170 bytes
ETHER:  Destination = 0:c0:4f:79:ed:87, 
ETHER:  Source      = 8:0:20:1c:f:ee, 
ETHER:  Ethertype = 0800 (IP)
ETHER:  
IP:   ----- IP Header -----
IP:   
IP:   Version = 4
IP:   Header length = 20 bytes
IP:   Type of service = 0x00
IP:         xxx. .... = 0 (precedence)
IP:         ...0 .... = normal delay
IP:         .... 0... = normal throughput
IP:         .... .0.. = normal reliability
IP:   Total length = 156 bytes
IP:   Identification = 50607
IP:   Flags = 0x4
IP:         .1.. .... = do not fragment
IP:         ..0. .... = last fragment
IP:   Fragment offset = 0 bytes
IP:   Time to live = 255 seconds/hops
IP:   Protocol = 6 (TCP)
IP:   Header checksum = 23af
IP:   Source address = 128.10.3.10, ector.cs.purdue.edu
IP:   Destination address = 128.10.3.106, xinu6.cs.purdue.edu
IP:   No options
IP:   
TCP:  ----- TCP Header -----
TCP:  
TCP:  Source port = 2049
TCP:  Destination port = 708 (Sun RPC)
TCP:  Sequence number = 3430040415
TCP:  Acknowledgement number = 1438029832
TCP:  Data offset = 20 bytes
TCP:  Flags = 0x18
TCP:        ..0. .... = No urgent pointer
TCP:        ...1 .... = Acknowledgement
TCP:        .... 1... = Push
TCP:        .... .0.. = No reset
TCP:        .... ..0. = No Syn
TCP:        .... ...0 = No Fin
TCP:  Window = 8760
TCP:  Checksum = 0x29c5
TCP:  Urgent pointer = 0
TCP:  No options
TCP:  
TCP:  Data: (first 64 bytes) 
... Note: Data has been stripped...

See lab1-src/packet-examples for output of packets of other protocols.


IMPORTANT:

Try to emulate the output of the examples in lab1-src/packet-examples. You can use lab1-src/analyze-example (executable binary) to compare your output.

Before you start developing the analyze command, download, uncompress and untar the file lab1-src.tgz ( the untared directory is in lab1-src/ ). This file has the analyze.c file that you will use to start your program. analyze.c uses the OpenFrame and GetFrame functions to read the packets from the packet files. The description on how to use the OpenFrame and GetFrame functions is in dumpframe.h.

The files ether.h, ip.h, arp.h, tcp.h, udp.h, and icmp.h include the structures that represent the headers for the packets for the different protocols. You will find also some example packets that you can use to test your program.

When printing IP addresses also print the corresponding host name. Use the function gethostbyaddr to translate IP addresses to host names. See the corresponding man page to find out how to use gethostbyaddr.

When printing the TCP or UDP port numbers, also print the service the port is related to if any. For example, port 23/TCP is related to TELNET etc. You are only required to print the services related to the following services; on TCP: telnet, ftp, nfs, smtp, http, gopher, whois, and finger. on UDP: nfs and sunrpc. To find out what are the ports that correspond to these services, grep the output of the command "ypcat services" or see the list of registered port numbers of the Internet Assigned Numbers Authority at http://www.isi.edu/in-notes/iana/assignments/port-numbers

Implementation Details

Declare a local array (unsigned character buffer) with size 1518 bytes (getFrame does not return the 64-bit preamble). Call getFrame to read a packet into the local buffer. To decode the different fields first declare a pointer to an ethernet header and assign to it the beginning of the buffer. Do the same for IP and other encapsulated packets.
 

#include <sys/types.h>
#include "ether.h"
#include "ip.h"
#include "tcp.h"
#include "icmp.h"
#include "arp.h"
#include "udp.h"

main()
{
    ....
    unsigned char buffer[1518];

    /* openFrame(...) etc */

    /* For all packets in the file */
    while ( (n = getFrame( buffer )) > 0 ) {

        /* Decode ethernet header */
    struct eh * e = (struct eh *) buffer;

    /*
     * Print ethernet header.
     * Ethernet source and destination addresses are in: e->eh_dst and e->eh->src.
     */

    /*
     * Use ntohs to convert ethernet type from network to host byte order.
     * You have to do that with all short and long fields.
     */
    printf("Ethertype = %04x, ntohs( e->eh_type ));

    /* Demultiplex ethernet type */
    if ( ntohs( e->eh_type ) == EPT_IP ) {
        /* This is an IP packet. Decode IP header */

        struct ip * ip = (struct * ip) e->eh_data;

        /* IP packet fields can be found in ip->ip_len, ip->_proto ... etc. */

        /* print ip header fields */
    }

. . .
Integer fields in the IP datagram that are longer than one byte must be converted from network byte order to host byte order. The functions ntohs and ntohl perform the conversion for short (16-bit) and long (32-bit) integers.
 

Turning in your files.


This lab is due at 11:59pm,  February 21st, 2008.

To turnin your lab1 follow these instructions:

1. Login to access a lab machine.

2. cd to lab1-src/ and type "make clean"

3. Type "make" to make sure that your lab1 is built correctly.

4. Type "make clean" again.

5. cd one directory above lab1-src/

6. Type:

turnin -c cs422 -p lab1 lab1-src
7. Check that your files have been submitted correctly by typing:
turnin -c cs422 -p lab1 -v