aboutsummaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/ipstack/ipstack.go315
1 files changed, 158 insertions, 157 deletions
diff --git a/pkg/ipstack/ipstack.go b/pkg/ipstack/ipstack.go
index c843bee..6bce6e8 100644
--- a/pkg/ipstack/ipstack.go
+++ b/pkg/ipstack/ipstack.go
@@ -4,13 +4,14 @@ package ipstack
// This class is divided as follows:
// 1) INIT FUNCTIONS
// 2) DOWN/UP FUNCTIONS
-// 3) GETTER FUNCTIONS
-// 4) PRINT FUNCTIONS
-// 5) ROUTE FUNCTIONS
-// 6) RIP FUNCTIONS
-// 7) PROTOCOL HANDLERS
-// 8) CHECKSUM FUNCTIONS
-// 9) HELPERS
+// 3) SEND/RECV FUNCTIONS
+// 4) CHECKSUM FUNCTIONS
+// 5) RIP FUNCTIONS
+// 6) PROTOCOL HANDLERS
+// 7) HELPER FUNCTIONS
+// 8) GETTER FUNCTIONS
+// 9) PRINT FUNCTIONS
+// 10) CLEANUP FUNCTION
import (
"encoding/binary"
@@ -317,108 +318,7 @@ func InterfaceDownREPL(ifaceName string) {
InterfaceDown(iface)
}
-// ************************************** GETTER FUNCTIONS **********************************************************
-func GetInterfaceByName(ifaceName string) (*Interface, error) {
- // iterate through the interfaces and return the one with the same name
- for _, iface := range myInterfaces {
- if iface.Name == ifaceName {
- return iface, nil
- }
- }
- return nil, errors.Errorf("No interface with name %s", ifaceName)
-}
-
-func GetInterfaces() []*Interface {
- return myInterfaces
-}
-
-func GetNeighbors() map[string][]*Neighbor {
- return myNeighbors
-}
-
-func GetRoutes() map[netip.Prefix]Hop {
- return routingTable
-}
-
-// ************************************** PRINT FUNCTIONS **********************************************************
-
-// SprintInterfaces returns a string representation of the interfaces data structure
-func SprintInterfaces() string {
- tmp := ""
- for _, iface := range myInterfaces {
- if iface.State {
- // if the state is up, print UP
- tmp += fmt.Sprintf("%s\t%s\t%s\n", iface.Name, iface.IpPrefix.String(), "UP")
- } else {
- // if the state is down, print DOWN
- tmp += fmt.Sprintf("%s\t%s\t%s\n", iface.Name, iface.IpPrefix.String(), "DOWN")
- }
- }
- return tmp
-}
-
-// SprintNeighbors returns a string representation of the neighbors data structure
-func SprintNeighbors() string {
- tmp := ""
- for _, iface := range myInterfaces {
- if !iface.State {
- // if the interface is down, skip it
- continue
- }
- for _, n := range myNeighbors[iface.Name] {
- tmp += fmt.Sprintf("%s\t%s\t%s\n", iface.Name, n.VipAddr.String(), n.UdpAddr.String())
- }
- }
- return tmp
-}
-
-// SprintRoutingTable returns a string representation of the routing table
-func SprintRoutingTable() string {
- tmp := ""
- for prefix, hop := range routingTable {
- if hop.Type == "L" {
- // 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)
- }
- }
- return tmp
-}
-
-// ************************************** BASIC FUNCTIONS **********************************************************
-
-// CleanUp 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.Socket.Close()
- if err != nil {
- continue
- }
- }
-
- // delete all the neighbors
- myNeighbors = make(map[string][]*Neighbor)
- // delete all the interfaces
- myInterfaces = nil
- // delete the routing table
- routingTable = make(map[netip.Prefix]Hop)
-
- time.Sleep(5 * time.Millisecond)
-}
-
-// ************************************** ROUTE FUNCTIONS **********************************************************
+// ************************************** SEND/RECV FUNCTIONS *******************************************************
// SendIP sends an IP packet to a destination
//
@@ -630,44 +530,23 @@ func RecvIP(iface *Interface, isOpen *bool) error {
return nil
}
-// ************************************** RIP FUNCTIONS *******************************************************
-
-// MakeRipMessage returns the byte array to be used in SendIp for a RIP packet
-func MakeRipMessage(command uint16, entries []RIPEntry) []byte {
- if command == 1 { // request message
- buf := make([]byte, SIZE_OF_RIP_HEADER)
- binary.BigEndian.PutUint16(buf[0:2], command)
- binary.BigEndian.PutUint16(buf[2:4], uint16(0))
- return buf
- }
-
- // 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)))
+// ************************************** CHECKSUM FUNCTIONS ******************************************************
+// reference: https://github.com/brown-csci1680/lecture-examples/blob/main/ip-demo/cmd/udp-ip-recv/main.go
+func ComputeChecksum(b []byte) uint16 {
+ checksum := header.Checksum(b, 0)
+ checksumInv := checksum ^ 0xffff
- // fill in the entries
- for i, entry := range entries {
- 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
+ return checksumInv
+}
- // convert the prefix to a uint32
- ipv4Netmask := uint32(0xffffffff)
- ipv4Netmask <<= 32 - entry.prefix.Bits()
- binary.BigEndian.PutUint32(buf[offset+8:offset+12], ipv4Netmask)
- }
+func ValidateChecksum(b []byte, fromHeader uint16) uint16 {
+ checksum := header.Checksum(b, fromHeader)
- return buf
+ return checksum
}
+// ************************************** RIP FUNCTIONS *******************************************************
+
// PeriodicUpdateRoutine sends RIP updates to neighbors every 5 seconds
// TODO: (performace) consider making this multithreaded and loops above more efficient
func PeriodicUpdateRoutine() {
@@ -973,21 +852,6 @@ func HandleTestPackets(src *Interface, message []byte, hdr *ipv4header.IPv4Heade
return nil
}
-// ************************************** CHECKSUM FUNCTIONS ******************************************************
-// reference: https://github.com/brown-csci1680/lecture-examples/blob/main/ip-demo/cmd/udp-ip-recv/main.go
-func ComputeChecksum(b []byte) uint16 {
- checksum := header.Checksum(b, 0)
- checksumInv := checksum ^ 0xffff
-
- return checksumInv
-}
-
-func ValidateChecksum(b []byte, fromHeader uint16) uint16 {
- checksum := header.Checksum(b, fromHeader)
-
- return checksum
-}
-
// *********************************************** HELPERS **********************************************************
// Route returns the next HOP, based on longest prefix match for a given ip
@@ -1004,3 +868,140 @@ func Route(src netip.Addr) (Hop, error) {
}
return Hop{}, errors.Errorf("error ROUTE: destination %s does not exist on routing table.", src)
}
+
+// MakeRipMessage returns the byte array to be used in SendIp for a RIP packet
+func MakeRipMessage(command uint16, entries []RIPEntry) []byte {
+ if command == 1 { // request message
+ buf := make([]byte, SIZE_OF_RIP_HEADER)
+ binary.BigEndian.PutUint16(buf[0:2], command)
+ binary.BigEndian.PutUint16(buf[2:4], uint16(0))
+ return buf
+ }
+
+ // 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 := 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)
+ }
+
+ return buf
+}
+
+// ************************************** GETTER FUNCTIONS **********************************************************
+func GetInterfaceByName(ifaceName string) (*Interface, error) {
+ // iterate through the interfaces and return the one with the same name
+ for _, iface := range myInterfaces {
+ if iface.Name == ifaceName {
+ return iface, nil
+ }
+ }
+ return nil, errors.Errorf("No interface with name %s", ifaceName)
+}
+
+func GetInterfaces() []*Interface {
+ return myInterfaces
+}
+
+func GetNeighbors() map[string][]*Neighbor {
+ return myNeighbors
+}
+
+func GetRoutes() map[netip.Prefix]Hop {
+ return routingTable
+}
+
+// ************************************** PRINT FUNCTIONS **********************************************************
+
+// SprintInterfaces returns a string representation of the interfaces data structure
+func SprintInterfaces() string {
+ tmp := ""
+ for _, iface := range myInterfaces {
+ if iface.State {
+ // if the state is up, print UP
+ tmp += fmt.Sprintf("%s\t%s\t%s\n", iface.Name, iface.IpPrefix.String(), "UP")
+ } else {
+ // if the state is down, print DOWN
+ tmp += fmt.Sprintf("%s\t%s\t%s\n", iface.Name, iface.IpPrefix.String(), "DOWN")
+ }
+ }
+ return tmp
+}
+
+// SprintNeighbors returns a string representation of the neighbors data structure
+func SprintNeighbors() string {
+ tmp := ""
+ for _, iface := range myInterfaces {
+ if !iface.State {
+ // if the interface is down, skip it
+ continue
+ }
+ for _, n := range myNeighbors[iface.Name] {
+ tmp += fmt.Sprintf("%s\t%s\t%s\n", iface.Name, n.VipAddr.String(), n.UdpAddr.String())
+ }
+ }
+ return tmp
+}
+
+// SprintRoutingTable returns a string representation of the routing table
+func SprintRoutingTable() string {
+ tmp := ""
+ for prefix, hop := range routingTable {
+ if hop.Type == "L" {
+ // 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)
+ }
+ }
+ return tmp
+}
+
+// ************************************** CLEANUP FUNCTIONS **********************************************************
+
+// CleanUp 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.Socket.Close()
+ if err != nil {
+ continue
+ }
+ }
+
+ // delete all the neighbors
+ myNeighbors = make(map[string][]*Neighbor)
+ // delete all the interfaces
+ myInterfaces = nil
+ // delete the routing table
+ routingTable = make(map[netip.Prefix]Hop)
+
+ time.Sleep(5 * time.Millisecond)
+} \ No newline at end of file