Homework 6: A raw socket ping tool

Due date: Apr. 29, 2019

In this homework, we use Linux raw sockets to implement a network diagnostics tool similar to ping. You may use any language that compiles to a binary file.

You may use this resource as an initial guide to using raw sockets. Specifically, you are to use Ethernet raw sockets: socket(AF_PACKET, SOCK_RAW,...)

Manual local ping

As a first step, send a standard ICMP ECHO request to a machine on your local network. Any machine will do, but you are guaranteed to have one: your gateway to the Internet. Here is a usage example.

./hw6 --de aa:bb:cc:dd:ee:ff --se aa:bb:cc:dd:ee:ff --si --di

where the --de/--se parameter specify the destination/source Ethernet address, and --di/--si specify the destination/source IP address. (Use getopt_long to parse the command line parameters.) Initially, confirm with ping that your gateway indeed responds to ping. For now, manually up the appropriate ethernet and ip addresses using ifconfig (source), ip route and arp.

To send the ICMP ECHO request, you will need to assemble ethernet, IP and ICMP headers as appropriate. As an intermediate step, observe the response from the gateway with tcpdump. Once a response is appearing, add the functionality to receive the ICMP ECHO reply. Send one ECHO request per second, and print out the outcome in the standard ping format.

Remote IP ping

Try changing the --di parameter to the IP address of a remote Internet host. Assuming the remote host responds to ping, your application should work for remote IPs without further modification.

Now make the program work with only the --di. This will require looking the two ethernet addresses, and the local IP address.

Get the remote mac address and IP using the routing table

cat /proc/net/route


cat /proc/net/arp

Get the local mac address and ip using ioctl. To see how, use strace to observe ifconfig doing it

strace ifconfig

This lists all the system calls made by ifconfig to produce its output. Your program should now work with just a --di parameter supplied.

TCP ping

Add parameters --tcp, to enable tcp mode, and --dp / --sp for destination- and source port. Send a SYN packet, and report (ping-style), the time it takes to receive a SYNACK back. If you get a response, but it is not a SYNACK, report this as well, but report round-trip-time no matter what packet you get back from the destination.

TTL-restricted ping

Add a parameter --ttl, to specify the time to live field in the IP header. This should work with both TCP and ICMP pings. If you get back a TTL EXPIRED ICMP message from an intermediate host, report this, together with the round trip time, similar to the traceroute command.


Add a parameter --rstprobe, to be used together with the --tcp option. Instead of sending a SYN and waiting for a SYNACK, send a packet without a SYN, and wait for an RST. Are there machines that don't respond with a SYNACK, but do respond with an RST?


Turn in your work using this link. Make sure your solution folder includes a Makefile. Make sure your Makefile includes a target named hw6. To test your turn-in, clone your turn-in repository, change to the new directory, type "make hw6", then test your hw6 binary.