aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Doan <daviddoan@Davids-MacBook-Pro-70.local>2023-10-23 15:25:05 -0400
committerDavid Doan <daviddoan@Davids-MacBook-Pro-70.local>2023-10-23 15:25:05 -0400
commit766ee3654c3ccca3b9a80d26736bfcbb9e37d708 (patch)
tree26b0e83af07be0479bb543b0deccbc1160173f5f
parent56c17d8bd24d2934d4d5b8e2a44baf0b4b92dc41 (diff)
comments and refactoring
-rw-r--r--pkg/ipstack/ipstack.go262
-rwxr-xr-xvhostbin0 -> 3110259 bytes
-rwxr-xr-xvrouterbin0 -> 3110267 bytes
3 files changed, 33 insertions, 229 deletions
diff --git a/pkg/ipstack/ipstack.go b/pkg/ipstack/ipstack.go
index 6588afc..038a2d4 100644
--- a/pkg/ipstack/ipstack.go
+++ b/pkg/ipstack/ipstack.go
@@ -21,9 +21,9 @@ const (
MaxEntries = 64
INFINITY = 16
SIZE_OF_RIP_ENTRY = 12
- SIZE_OF_RIP_MESSAGE = 6
RIP_PROTOCOL = 200
TEST_PROTOCOL = 0
+ SIZE_OF_RIP_HEADER = 4
)
// STRUCTS ---------------------------------------------------------------------
@@ -193,11 +193,6 @@ func InterfaceListenerRoutine(i *Interface) {
return
}
- //if !isUp { // don't call the listeners if interface is down
- // continue
- //}
-
- // TODO: remove these "training wheels"
time.Sleep(1 * time.Millisecond)
err := RecvIP(i, &isUp)
if err != nil {
@@ -299,7 +294,7 @@ func GetRoutes() map[netip.Prefix]Hop {
// ************************************** PRINT FUNCTIONS **********************************************************
-// Sprint functions return a string representation of the myInterfaces data structure
+// returns a string representation of the myInterfaces data structure
func SprintInterfaces() string {
tmp := ""
for _, iface := range myInterfaces {
@@ -314,7 +309,7 @@ func SprintInterfaces() string {
return tmp
}
-// Sprint functions return a string representation of the myNeighbors data structure
+// returns a string representation of the myNeighbors data structure
func SprintNeighbors() string {
tmp := ""
for _, iface := range myInterfaces {
@@ -329,12 +324,15 @@ func SprintNeighbors() string {
return tmp
}
+// returns a string representation of the routingTable data structure
func SprintRoutingTable() string {
tmp := ""
for prefix, hop := range routingTable {
if hop.Type == "L" {
- tmp += fmt.Sprintf("%s\t%s\tLOCAL:%s\t%d\n", hop.Type, prefix.String(), hop.Interface.Name, 0)
+ // if the hop is local, print LOCAL
+ tmp += fmt.Sprintf("%s\t%s\tLOCAL:%s\t%d\n", hop.Type, prefix.String(), hop.Interface.Name, hop.Cost)
} else if hop.Type == "S" {
+ // if the hop is static, don't print the cost
tmp += fmt.Sprintf("%s\t%s\t%s\t%s\n", hop.Type, prefix.String(), hop.VIP.String(), "-")
} else {
tmp += fmt.Sprintf("%s\t%s\t%s\t%d\n", hop.Type, prefix.String(), hop.VIP.String(), hop.Cost)
@@ -345,13 +343,17 @@ func SprintRoutingTable() string {
// ************************************** BASIC FUNCTIONS **********************************************************
+// cleans up the data structures and closes the UDP sockets
func CleanUp() {
fmt.Print("Cleaning up...\n")
+
// go through the interfaces, pop thread & close the UDP FDs
for _, iface := range myInterfaces {
+ // close the channel
if iface.SocketChannel != nil {
close(iface.SocketChannel)
}
+ // close the UDP FD
err := iface.RecvSocket.Close()
if err != nil {
continue
@@ -368,13 +370,14 @@ func CleanUp() {
time.Sleep(5 * time.Millisecond)
}
-// TODO: have it take TTL so we can decrement it when forwarding
+// SendIP sends an IP packet to a destination
func SendIP(src *netip.Addr, dest *Neighbor, protocolNum int, message []byte, destIP string, hdr *ipv4header.IPv4Header) (int, error) {
+ // check if the interface is up
iface, err := GetInterfaceByName(dest.Name)
if !iface.State {
return -1, errors.New("error: interface is down")
}
-
+ // if the header is nil, create a new one
if hdr == nil {
hdr = &ipv4header.IPv4Header{
Version: 4,
@@ -392,6 +395,7 @@ func SendIP(src *netip.Addr, dest *Neighbor, protocolNum int, message []byte, de
Options: []byte{},
}
} else {
+ // if the header is not nil, decrement the TTL
hdr = &ipv4header.IPv4Header{
Version: 4,
Len: 20, // Header length is always 20 when no IP options
@@ -430,13 +434,10 @@ func SendIP(src *netip.Addr, dest *Neighbor, protocolNum int, message []byte, de
bytesToSend = append(bytesToSend, []byte(message)...)
sendAddr, err := net.ResolveUDPAddr("udp4", dest.UdpAddr.String())
- // tmpConn, err := net.DialUDP("udp4", nil, sendAddr)
- // get the interface of this neighbor
if err != nil {
return -1, errors.WithMessage(err, "Could not bind to UDP port->\t"+dest.UdpAddr.String())
}
- // bytesWritten, err := tmpConn.Write(bytesToSend)
// TODO: make this faster by removing call
bytesWritten, err := iface.RecvSocket.WriteToUDP(bytesToSend, sendAddr)
if err != nil {
@@ -447,33 +448,31 @@ func SendIP(src *netip.Addr, dest *Neighbor, protocolNum int, message []byte, de
return bytesWritten, nil
}
+
+// RecvIP receives an IP packet from a source
func RecvIP(iface *Interface, isOpen *bool) error {
- buffer := make([]byte, MAX_IP_PACKET_SIZE) // TODO: fix wordking
+ buffer := make([]byte, MAX_IP_PACKET_SIZE) // TODO: fix wording
// Read on the UDP port
- // Too much printing so I commented it out
// fmt.Println("wating to read from UDP socket")
_, _, err := iface.RecvSocket.ReadFromUDP(buffer)
if err != nil {
return err
}
+ // check if the interface is up
if !*isOpen {
return errors.New("interface is down")
}
// Marshal the received byte array into a UDP header
- // NOTE: This does not validate the checksum or check any fields
- // (You'll need to do this part yourself)
hdr, err := ipv4header.ParseHeader(buffer)
if err != nil {
- // What should you if the message fails to parse?
- // Your node should not crash or exit when you get a bad message.
- // Instead, simply drop the packet and return to processing.
fmt.Println("Error parsing header", err)
return err
}
+ // checksum validation
headerSize := hdr.Len
headerBytes := buffer[:headerSize]
checksumFromHeader := uint16(hdr.Checksum)
@@ -504,11 +503,13 @@ func RecvIP(iface *Interface, isOpen *bool) error {
return nil
}
- // at this point, the packet is valid. next steps consider the forwarding of the packet
- // 2) check if the message is for me, if so, sendUP (aka call the correct handler)
//if hdr.Protocol != RIP_PROTOCOL {
// fmt.Println("I see a non-rip packet")
//}
+
+ // at this point, the packet is valid. next steps consider the forwarding of the packet
+
+ // 2) check if the message is for me, if so, sendUP (aka call the correct handler)
for _, myIface := range myInterfaces {
if hdr.Dst == myIface.IpPrefix.Addr() {
// see if there is a handler for this protocol
@@ -571,8 +572,8 @@ func RecvIP(iface *Interface, isOpen *bool) error {
// ************************************** RIP Routines *******************************************************
+// creates a byte array that represents a RIP message
func makeRipMessage(command uint16, entries []RIPEntry) []byte {
- SIZE_OF_RIP_HEADER := 2 * 2 // 2 uint16s
if command == 1 { // request message
buf := make([]byte, SIZE_OF_RIP_HEADER)
binary.BigEndian.PutUint16(buf[0:2], command)
@@ -581,19 +582,23 @@ func makeRipMessage(command uint16, entries []RIPEntry) []byte {
}
// else, command == 2, response message
+ // create the buffer
bufLen := SIZE_OF_RIP_HEADER + // sizeof uint16 is 2, we have two of them
len(entries)*SIZE_OF_RIP_ENTRY // each entry is 12
buf := make([]byte, bufLen)
+ // fill in the header
binary.BigEndian.PutUint16(buf[0:2], command)
binary.BigEndian.PutUint16(buf[2:4], uint16(len(entries)))
+ // fill in the entries
for i, entry := range entries {
- offset := 2*2 + i*SIZE_OF_RIP_ENTRY
+ offset := SIZE_OF_RIP_HEADER + i*SIZE_OF_RIP_ENTRY
binary.BigEndian.PutUint32(buf[offset:offset+4], entry.cost) // 0-3 = 4 bytes
copy(buf[offset+4:offset+8], entry.prefix.Addr().AsSlice()) // 4-7 = 4 bytes
+ // convert the prefix to a uint32
ipv4Netmask := uint32(0xffffffff)
ipv4Netmask <<= 32 - entry.prefix.Bits()
binary.BigEndian.PutUint32(buf[offset+8:offset+12], ipv4Netmask)
@@ -602,6 +607,7 @@ func makeRipMessage(command uint16, entries []RIPEntry) []byte {
return buf
}
+
func periodicUpdateRoutine() {
for {
// for each periodic update, we want to send our nodes in the table
@@ -763,7 +769,7 @@ func RegisterProtocolHandler(protocolNum int) bool {
func handleRIP(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.IPv4Header) error {
// parse the RIP message
- SIZE_OF_RIP_HEADER := 2 * 2
+ // SIZE_OF_RIP_HEADER := 2 * 2
command := int(binary.BigEndian.Uint16(message[0:2]))
switch command {
case 1:
@@ -944,206 +950,4 @@ func LongestPrefix(src netip.Addr) (Hop, error) {
}
}
return Hop{}, errors.Errorf("No route to ip %s on table.", src)
-}
-
-//
-//func SendRIPMessage(src Interface, dest *Neighbor, message *RIPMessage) error {
-// hdr := ipv4header.IPv4Header{
-// Version: 4,
-// Len: 20, // Header length is always 20 when no IP options
-// TOS: 0,
-// TotalLen: ipv4header.HeaderLen + 4 + len(message.entries)*SIZE_OF_RIP_ENTRY,
-// ID: 0,
-// Flags: 0,
-// FragOff: 0,
-// TTL: 32,
-// Protocol: RIP_PROTOCOL,
-// Checksum: 0, // Should be 0 until checksum is computed
-// Src: src.IpPrefix.Addr(),
-// Dst: netip.MustParseAddr(dest.VipAddr.String()),
-// Options: []byte{},
-// }
-//
-// headerBytes, err := hdr.Marshal()
-// if err != nil {
-// return err
-// }
-//
-// hdr.Checksum = int(ComputeChecksum(headerBytes))
-//
-// headerBytes, err = hdr.Marshal()
-// if err != nil {
-// log.Fatalln("Error marshalling header: ", err)
-// }
-//
-// bytesToSend := make([]byte, 0)
-// bytesToSend = append(bytesToSend, headerBytes...)
-//
-// // make the RIP message
-// //buf := make([]byte, SIZE_OF_RIP_MESSAGE+len(message.entries)*SIZE_OF_RIP_ENTRY)
-// //buf[0] = message.command
-// //buf[1] = message.numEntries
-//
-// buf := make([]byte, 4)
-// binary.BigEndian.PutUint16(buf[0:2], message.command)
-// binary.BigEndian.PutUint16(buf[2:], message.numEntries)
-//
-// bytesToSend = append(bytesToSend, buf...)
-//
-// for _, entry := range message.entries {
-// // offset := SIZE_OF_RIP_MESSAGE + i*SIZE_OF_RIP_ENTRY
-// // each field is 4 bytes
-// buf := make([]byte, SIZE_OF_RIP_ENTRY)
-// binary.BigEndian.PutUint32(buf, entry.address) // 0-3 = 4 bytes
-// binary.BigEndian.PutUint32(buf[3:8], entry.mask) // 4-7 = 4 bytes
-// binary.BigEndian.PutUint32(buf[8:], entry.cost) // 8-11 = 4 bytes
-//
-// bytesToSend = append(bytesToSend, buf...)
-// }
-//
-// // send RIP message
-// sendAddr, err := net.ResolveUDPAddr("udp4", dest.UdpAddr.String())
-// // tmpConn, err := net.DialUDP("udp4", nil, sendAddr)
-// if err != nil {
-// return errors.WithMessage(err, "Could not bind to UDP port->\t"+dest.UdpAddr.String())
-// }
-//
-// iface, err := GetInterfaceByName(dest.Name)
-// //_, err = tmpConn.Write(bytesToSend)
-// _, err = iface.RecvSocket.WriteToUDP(bytesToSend, sendAddr)
-// if err != nil {
-// return err
-// }
-//
-// return nil
-//}
-
-//func RequestRip() {
-// // create RIP message
-// message := NewRIPMessage(1, []RIPEntry{})
-//
-// // send RIP message to RIP neighbors
-// for _, neighbors := range myNeighbors {
-// for _, neighbor := range neighbors {
-// // check if neighbor is RIP neighbor
-// // if not, continue
-// for _, ripNeighbor := range myRIPNeighbors {
-// if neighbor.VipAddr.String() == ripNeighbor.String() {
-// // send RIP message
- // err := SendRIPMessage(myVIP, neighbor, message)
-// if err != nil {
-// continue
-// }
-// }
-// }
-// continue
-// }
-// }
-//}
-//
-//func BroadcastPeriodicUpdates() {
-// // for each periodic update, we want to send our nodes in the table
-// entries := make([]RIPEntry, len(routingTable))
-// for prefix, hop := range routingTable {
-// entries = append(entries,
-// RIPEntry{
-// address: ConvertIPToUint32(prefix.Addr().String()),
-// mask: uint32(prefix.Bits()),
-// cost: hop.Cost,
-// })
-// }
-// message := NewRIPMessage(2, entries)
-//
-// // send to each neighbor
-// for _, iface := range myInterfaces {
-// for _, n := range myNeighbors[iface.Name] {
-// err := SendRIPMessage(*iface, n, message)
-// if err != nil {
-// fmt.Printf("Error sending RIP message to %s\n", n.VipAddr.String())
-// continue
-// }
-// }
-// }
-//
-//}
-
-//// THIS MIGHT BE WRONG...
-//func SendUpdates() {
-// entries := make([]RIPEntry, len(routingTable))
-// // create RIP entries from its interfaces to one another
-// for _, iface := range myInterfaces {
-// for _, iface2 := range myInterfaces {
-// if iface.Name == iface2.Name {
-// continue
-// }
-// // TODO @ MICHAEL: fix this
-// // hardcoded way to get cost to 0, fix if you want a better way
-// entry := &RIPEntry{
-// address: ConvertIPToUint32(iface2.IpPrefix.Addr().String()),
-// cost: 17,
-// mask: ConvertIPToUint32(iface.IpPrefix.Addr().String()),
-// }
-// entries = append(entries, *entry)
-//
-// entry = &RIPEntry{
-// address: ConvertIPToUint32(iface.IpPrefix.Addr().String()),
-// cost: 17,
-// mask: ConvertIPToUint32(iface2.IpPrefix.Addr().String()),
-// }
-// entries = append(entries, *entry)
-// }
-// }
-//
-// // create RIP entries from its neighbors
-// for _, neighbors := range myNeighbors {
-// for _, neighbor := range neighbors {
-// ipUint32 := ConvertIPToUint32(neighbor.VipAddr.String())
-// var neighborUint32 uint32
-// for _, interfaces := range myInterfaces {
-// if ifaceContainsIP(*interfaces, neighbor.VipAddr) {
-// neighborUint32 = ConvertIPToUint32(interfaces.IpPrefix.Addr().String())
-// break
-// }
-// }
-//
-// // create RIP entry
-// entry := &RIPEntry{
-// address: ipUint32,
-// cost: LOCAL_COST,
-// mask: neighborUint32,
-// }
-//
-// // add to entries and create RIP message
-// entries = append(entries, *entry)
-// message := NewRIPMessage(2, entries)
-//
-// // send RIP message
-// for _, Interfaces := range myInterfaces {
-// if Interfaces.Name == neighbor.Name {
- // err := SendRIPMessage(myVIP, neighbor, message)
-// if err != nil {
-// continue
-// }
-// }
-// }
-//
-// }
-// }
-//}
-
-// TODO @ MICHEAL: Handle links going down and link recovery
-// func CheckAndUpdateRoutingTable() {
-// for {
-// time.Sleep(12 * time.Second)
-// for prefix, hop := range routingTable {
-// // delete route if not refreshed in 12 seconds
-// // not sure if there is a better way to do this
-// if hop.Type == "R" {
-// delete(routingTable, prefix)
-// SendUpdates()
-// }
-// }
-// }
-// }
-
-// TODO @ MICHAEL: Triggered Updates and Split Horizon with Poisoned Reverse
+} \ No newline at end of file
diff --git a/vhost b/vhost
new file mode 100755
index 0000000..06cd653
--- /dev/null
+++ b/vhost
Binary files differ
diff --git a/vrouter b/vrouter
new file mode 100755
index 0000000..230afe9
--- /dev/null
+++ b/vrouter
Binary files differ