Turn in this assignment by e-mailing to jmoroney@hawaii.edu your code specified below.
You may do this assignment in groups of up to three.
This assignment asks you to implement two programs, both similar to the two programs in assignment 9. You may re-use and adapt any code anyone on your team created for assignment 9.
The first program creates an IPv6 ping (echo request) packet and sends it to your second program. Your second program forwards packets according to its routing table, either dropping them, or forwarding them to another router (another instance of the same program). Your routing program should also print what happens with each received program, i.e. forwarded or dropped.
As in assignment 9, the routing tables for this assignment are static and specified in the command-line arguments, so you do not need to implement any routing protocol, or indeed, even a routing table.
Write a C program, pinggen6, to create and send a valid ICMPv6 echo request packet. This packet begins with a valid IPv6 header as in Assignment 9, followed by the byte 128 (echo request), three bytes of zero (this sends the checksum as zero). The next two bytes are an identifier selected by your program (the process ID returned by getpid is suitable). The following two-bytes are a sequence number (increasing from 0). This may optionally be followed by 8 bytes of time obtained from gettimeofday.
pinggen6 takes four command-line arguments: a local and a remote port number and two IPv6 addresses. It then creates a socket, binds it to the local port number, creates a packet as described above, and sends it to ::1 (localhost) at the remote UDP port number given on the command line. That is, you are sending the IPv6 packet (consisting of an IPv6 header and ICMPv6 content) over IPv6 and UDP to your router6 program described below.
After sending the packet, pinggen6 reads from the socket and prints any packets it receives.
For example,
$ ./pinggen6 9876 12345 1:2:3::4 5:6:7:8:9:a:b:c
creates a packet with an IPv6 header with source address 1:2:3::4 (the same as 1:2:3:0:0:0:0:4) and destination address 5:6:7:8:9:a:b:c, and an ICMP echo request payload as described above. It sends this packet to the IPv6 localhost address (::1) from UDP port 9876 to UDP port 12345, then listens for any incoming messages on UDP port 9876.
The pinggen6 program may be tested against itself. For this, you will need two windows, and run the following commands, one in each of the two windows.
$ ./pinggen6 9876 12345 1:2:3::4 9:8:7::6
$ ./pinggen6 12345 9876 9:8:7::6 1:2:3::4
If your pinggen6 command works correctly, the second call should deliver a packet to the program running in the first window.
For this assignment, and as in assignment 9, the routing table will be specified as a series of command-line arguments, each of the form:
destination/gateway/mask/interface
Each such argument is used to build a routing table entry, in the order given on the command line.
Command-line arguments are also used to specify the router's interfaces and IP addresses:
+interface/local-IPv6/mask/my-UDP-port/peer-UDP-port
These interface definitions begin with the character "+" and include:
The two types of arguments may be provided in any order on the command line. Only the order of the routing table entries is significant.
To listen on different interfaces (i.e. receive from different sockets bound to different UDP port numbers), your program must have either multiple threads (recommended, but slightly harder), or multiple processes (slightly easier). Multiple threads are created with pthread_create, multiple processes with fork. If you use pthreads, you may need to link your code with -lpthread, e.g.
cc -o router6 router6.c -lpthread
I am going to simulate a simple network with two hosts and two routers. Each router has two interfaces, one connected to the host, the other to the other router.
This simple network needs three IPv6 network numbers. I will use 2001:2:3:4::/64, 2002:3:4:5::/64, and 2003:4:5:6::/64.
To run these four programs at the same time, I will open 4 different windows, and run one of these commands in each of the windows:
$ ./router6 +eth0/2001:2:3:4::1/64/12345/9876 2001:2:3:4::/2001:2:3:4::2/64/eth0 +eth1/2002:3:4:5::1/64/12346/12347 2002:3:4:5::/2002:3:4:5::2/64/eth1 2003:4:5:6::/2002:3:4:5::2/64/eth1
$ ./router6 +eth0/2002:3:4:5::2/64/12347/12346 2002:3:4:5::/2002:3:4:5::1/64/eth0 +eth1/2003:4:5:6::1/64/12348/9875 2003:4:5:6::/2003:4:5:6::2/64/eth1 2001:2:3:4::/2002:3:4:5::1/64/eth0
$ ./pinggen6 9876 12345 2001:2:3:4::2 2003:4:5:6::2
$ ./pinggen6 9875 12348 2003:4:5:6::2 2001:2:3:4::2
With these commands, the packet from the first pinggen started should be delivered from the first router to the second, and from the second router to the second host. If the second host is not yet running, the packet is dropped by UDP.
When the second host is started, the ping travels all the way to the first host, where it is ignored (unless you have extra time and wish to do extra work, in which case you may have your code respond to the echo request with a corresponding echo reply).
Note that the UDP port number corresponding to each simulated interface must be unique, since at most one socket can be bound to a port.
forwarding 2001:2:3:4::2 to next hop 2002:3:4:5::1 on eth0or
dropping 2001:2:3:4::5
Either message may be followed by additional detail, such as "no route" or (optional) "Hop Limit zero".
Please follow the examples above in reporting the results of your routing table lookup. This makes it easier for the TA to grade a large number of assignments.
Turn in your source code for pinggen6.c and router6.c (and any other code, e.g. header files).
fork duplicates the current process, so there are two new processes running. The two processes are nearly identical -- the main difference is in the return value from fork, which is 0 in the child, and the child's process ID in the parent.
Each of your processes can independently read from one interface (a socket bound to the appropriate UDP port) and send the packet to its destination. Each process has its own copy of the command-line arguments. Because your threads/processes do not need to communicate with each other, having them as separate processes may simplify your life -- no process can influence any other process (unless both try to bind a socket to the same port!).
pthread_create creates a new thread within the current process. The thread is a C function which executes concurrently with the main thread. As a practical matter, each thread has its own local variables, but threads share global variables, including any pointers. Because of this, a bug in one thread may affect other threads. However, threads are used more frequently then processes because the shared global variables, if used appropriately, can be used for communication between the threads (communication between processes is also possible, but more cumbersome).
For this assignment, no communication is needed between different threads/processes, so both mechanisms are appropriate. However, because in programming threads are used more often than processes, you may want to gain experience using threads.
Much more information about both fork and pthread_create is available in man pages and online.
If you have extra time, you are welcome to send valid ICMPv6 echo reply packets in response to valid echo request packets. See RFC 4443 for details.
If you include the time (the additional 8 bytes from gettimeofday) in the echo request, then when you receive the echo reply, you can print the resulting round-trip time. For this to work, the echo reply must have the same payload as the echo request, that is, the system generating the echo reply must copy the payload from the echo request.
You are welcome to decrement the hop limit when forwarding a packet, and drop the packet if the hop limit reaches zero. If you do this, you may want to support an optional 5th argument to pinggen6, specifying the initial hop limit (if not specified, use 64).
If you do decrement the hop limit and discard packets, you may also send destination unreachable packets back to the source. This would allow you to implement the functionality of traceroute.
You are welcome to implement checksums. Please see RFC 2460,
Section 8.1 for details.
Computer Networks, ICS 451
Instructor: Edo Biagioni