Skip to content

K1ASER/CS144-Router

Repository files navigation

user: jlenz
Late extension was taken on this assignment.

Introduction:
This program implements the NAT and static routing requirements of Lab 5 of 
CS144. All deviations from the requirements as well as design choices that 
were made will be defined in this file.

Design Notes:
All functionality from Lab 3 is in tact if the program is run without the -n 
flag.  All shortcomings of the previous submission have been corrected.  In 
addition, except for making some of the functions publically accessable and 
bug fixes, the sr_router.c is largly unchanged from Lab 3.  New functionality 
was placed in the sr_nat.c file.

Unlike Lab 3, the NAT allows (not exactly sure what the "technical term" is 
here) packet deflection.  What this means is that if a packet is received on 
an interface and the NAT determines the packet's route should be out the same 
interface that the packet was received, the NAT will route the packet back out 
the same interface.  If this was not the case, the two HTTP servers could not 
talk to each other in the lab's setup.  Since the NAT is the default gateway 
for both of the servers, it made sense to have this functionality.

I modified the Makefile in this project to do an incremental build more along 
what I am used to seeing so objects stay in a folder separate from the 
source.  I also fixed the file so the Cygwin define will get added correctly 
for newer (1.7.x) and 64-bit versions of Cygwin.  For this reason the all, 
sr, clean, and submit targets work fine, but other targets that happened to 
be in the Makefile (such as sr.purify or dist) may not as a result (since I 
didn't know what they were for...).  There should be no reason the old 
Makefile would not work (provided you add sr_nat.c to the list of sources) 
if this an issue.

New packet headers for now needed types have been added to sr_protocol.h (such 
as TCP headers and ICMP type 11 and type 3 headers).

When unspecified, rather than choosing what the sample solution did, I 
prefered to lean on the side of what a "real" NAT would do.  For example, the 
sample solution allows the HTTP servers to ping the internal interface of the 
router, and my solution explicitly forbids this.  

NAT will fail "closed" rather than fail "open" when an unsupported protocol is 
detected.  Thus, only ICMP and TCP can traverse the NAT (UDP cannot).  In the 
case that an unsupported protocol attempt to traverse the NAT, the NAT 
silently drops the packet.

The external ports & ICMP identifiers are created in series starting at 
50000 and going up to 59999.  Separate linear allocations are done 
independantly for TCP and ICMP (as in if ICMP creates a mapping for 50000, 
a TCP connection can also have a mapping for 50000).  Note: there is a slight 
shortcoming in the code where if there are 10,000 active mapping for a 
provided type the code will enter an infinite loop when it tries to allocate 
the 10,001st.  Considering this is a LOT of connections to be active at one 
time, I didn't think to put handling in for this case.

A new TCP connection is created with the NAT detects a SYN packet sent in 
either direction.  It will be promoted to the "established" state if the NAT 
sees a SYN sent in BOTH directions.  It will be demoted back to "transitory" 
when a FIN is sent on the connection in EITHER direction.

Simultaneous open is supported.  The amount of time the NAT will hold the 
packet is the same as the transitory timeout.  One caveat is that a mapping 
must exist prior to attempting a simultaneous open.  Since this process works 
the same as NAT hole-punching as described on Piazza, this seemed like an 
acceptable requirement.

TCP mapping timeouts are tracked at a connection level (rather then a mapping 
level).  When the connection times out, it is deleted from the list of 
connections on that mapping.  When no more connections exist, the mapping is 
torn down.

ICMP mapping timeouts are tracked as a mapping level (since the timeout is 
always the same and there is no means of tracking individual connections).

The timeout for a NAT connection is reset each time is is looked up.  This is 
done based on the assumption that you would not look up a mapping unless there 
was traffic that caused you to be interested in it.

NAT supports all required ICMP packets as specified by NAT RFCs, even though 
they were not required by the lab (I saw the discussion on Piazza after I had 
already implemented it).  For this reason, the NAT will allow Destination 
Unreachable and Time Expired ICMP packets to traverse the NAT if an associated 
mapping exists.  It also makes the handling of ICMP packets look much more 
complicated (since there are now packets inside of packets on which we are 
performing NAT table lookups).

NAT file as some functions labeled as "trusted" in the function name.  These 
functions are non-thread safe counterparts to the original provided API.  
They differ by both assuming the NAT mutex is locked and by providing a 
shared pointer rather than a copy.  These are used for when modification of 
the mapping is required (such as adding a new connection).

My usual strategy for endianness has been that data in a packet should be in 
network order, and ALL other data should be in host order.  However, I broke 
this tennant with the NAT mappings.  Since NAT mappings are looked up with 
pure equal and not equal operations, and are usually performed on data in 
packets, it made sense to store mappings in network order.

Pseudo-Code of NAT functionality:
Functionality for TCP and ICMP are very similar, but not quite the same.  
For this reason, I have chosen in the README to provide pseudo-code to help 
in understanding the overall NAT program flow when a packet is received.  In 
addition, the handling, while in small chunks, looks somewhat unweidly in 
code form.
There is some extra code in each of the two cases based around any required 
extra steps (such as creating new connections for TCP or finding assocuated 
connections to ICMP Unreachable or Time Expired packets), but the flow is 
still the same in each case.

- NAT receives IP datagram
- Call appropriate handling function for TCP or ICMP based on IP protocol.
- Perform an integrity check on the packet (i.e. checksum good).
- If packet came on the internal interface and has one of our IP addresses, 
  process packet as in Lab 3. Done.
- Else if packet came on the internal interface (outbound)
  - Perform a NAT lookup.
  - If one does not exist, create one (TCP will only create if packet is a SYN)
  - Perform NAT translation
  - Route as in Lab 3. Done.
- Else (inbound)
  - If destination is not router and the packet's route keeps it external to the NAT
    - Allow routing without modification as in Lab 3. Done.
  - Else if packet if for the router's internal interface, drop the packet. Done.
  - Else, perform a NAT lookup
    - If one exists, perform translation and route the packet as in Lab 3.  Done.
    - Otherwise, assume the packet was actually for the router and process as in Lab 3. Done.

About

Repository for Lab 3 & 5 for CS144

Resources

Stars

Watchers

Forks

Packages

No packages published