diff options
author | David Doan <daviddoan@Davids-MacBook-Pro-70.local> | 2023-10-23 15:25:05 -0400 |
---|---|---|
committer | David Doan <daviddoan@Davids-MacBook-Pro-70.local> | 2023-10-23 15:25:05 -0400 |
commit | 766ee3654c3ccca3b9a80d26736bfcbb9e37d708 (patch) | |
tree | 26b0e83af07be0479bb543b0deccbc1160173f5f | |
parent | 56c17d8bd24d2934d4d5b8e2a44baf0b4b92dc41 (diff) |
comments and refactoring
-rw-r--r-- | pkg/ipstack/ipstack.go | 262 | ||||
-rwxr-xr-x | vhost | bin | 0 -> 3110259 bytes | |||
-rwxr-xr-x | vrouter | bin | 0 -> 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 Binary files differBinary files differ |