aboutsummaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/ipstack/ipstack.go597
1 files changed, 400 insertions, 197 deletions
diff --git a/pkg/ipstack/ipstack.go b/pkg/ipstack/ipstack.go
index da2d504..51ea07c 100644
--- a/pkg/ipstack/ipstack.go
+++ b/pkg/ipstack/ipstack.go
@@ -11,6 +11,8 @@ import (
"net/netip"
"time"
"encoding/binary"
+ "bytes"
+ "unicode"
)
const (
@@ -19,6 +21,10 @@ const (
STATIC_COST uint32 = 4294967295 // 2^32 - 1
MaxEntries = 64
INFINITY = 15
+ SIZE_OF_RIP_ENTRY = 12
+ SIZE_OF_RIP_MESSAGE = 6
+ RIP_PROTOCOL = 12
+ TEST_PROTOCOL = 0
)
// STRUCTS ---------------------------------------------------------------------
@@ -33,6 +39,7 @@ type Interface struct {
}
type Neighbor struct {
+ Name string
VipAddr netip.Addr
UdpAddr netip.AddrPort
@@ -56,7 +63,6 @@ type Hop struct {
Cost uint32
VipAsStr string
Type string
- // added this for printing purposes
}
// GLOBAL VARIABLES (data structures) ------------------------------------------
@@ -64,14 +70,15 @@ var myVIP Interface
var myInterfaces []*Interface
var myNeighbors = make(map[string][]*Neighbor)
-// var myRIPNeighbors = make(map[string]Neighbor)
-type HandlerFunc func(int, string, *[]byte) error
+var myRIPNeighbors = make([]netip.Addr, 0)
+
+type HandlerFunc func(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.IPv4Header) error
-var protocolHandlers = make(map[uint16]HandlerFunc)
+var protocolHandlers = make(map[int]HandlerFunc)
-// var routingTable = routingtable.New()
var routingTable = make(map[netip.Prefix]Hop)
+// ************************************** INIT FUNCTIONS **********************************************************
// reference: https://github.com/brown-csci1680/lecture-examples/blob/main/ip-demo/cmd/udp-ip-recv/main.go
func createUDPConn(UdpAddr netip.AddrPort, conn *net.UDPConn, isN bool) error {
listenString := UdpAddr.String()
@@ -128,20 +135,12 @@ func Initialize(lnxFilePath string) error {
}
go InterfaceListenerRoutine(i.RecvSocket, i.SocketChannel)
myInterfaces = append(myInterfaces, i)
-
- // TODO: (FOR HOSTS ONLY)
- // add STATIC to routing table
- // if !static {
- // ifacePrefix := netip.MustParsePrefix("0.0.0.0/0")
- // routingTable[ifacePrefix] = Hop{STATIC_COST, iface.Name, "S"}
- // static = true
- // }
- // Took this out for printing purposes for REPL FYI
}
// 2) initialize the neighbors connected to the node and into the routing table
for _, neighbor := range lnxConfig.Neighbors {
n := &Neighbor{
+ Name: neighbor.InterfaceName,
VipAddr: neighbor.DestAddr,
UdpAddr: neighbor.UDPAddr,
SendSocket: net.UDPConn{},
@@ -161,13 +160,21 @@ func Initialize(lnxFilePath string) error {
routingTable[neighborPrefix] = Hop{LOCAL_COST, neighbor.InterfaceName, "L"}
}
- for _, route := range lnxConfig.StaticRoutes {
+ for _, route := range lnxConfig.RipNeighbors {
+ // add to RIP neighbors
+ myRIPNeighbors = append(myRIPNeighbors, route)
+ }
+
+ // StaticRoutes: make(map[netip.Prefix]netip.Addr, 0),
+ for prefix, addr := range lnxConfig.StaticRoutes {
// add to routing table
- prefix := netip.MustParsePrefix("0.0.0.0/0")
- routingTable[prefix] = Hop{LOCAL_COST, route.String(), "S"}
+ routingTable[prefix] = Hop{STATIC_COST, addr.String(), "S"}
}
- // added for printing purposes for REPL FYI
+ SendUpdates()
+ // add protocol handlers
+ protocolHandlers[RIP_PROTOCOL] = handleRIP
+ protocolHandlers[TEST_PROTOCOL] = handleTestPackets
return nil
}
@@ -216,6 +223,8 @@ func InterfaceListenerRoutine(socket net.UDPConn, signal <-chan bool) {
}
}
+// ************************************** DOWN/UP FUNCTIONS ******************************************************
+
func InterfaceUp(iface *Interface) {
iface.State = true
iface.SocketChannel <- true
@@ -227,8 +236,7 @@ func InterfaceUpREPL(ifaceName string) {
fmt.Println("Error getting interface by name", err)
return
}
- iface.State = true
- iface.SocketChannel <- true
+ InterfaceUp(iface)
}
// we could do either of these but the REPL results in less work done in router and host
@@ -244,22 +252,22 @@ func InterfaceDownREPL(ifaceName string) {
fmt.Println("Error getting interface by name", err)
return
}
- iface.SocketChannel <- false
- iface.State = false
+ InterfaceDown(iface)
}
-// same as above comment
+// ************************************** 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 GetNeighborByIP(ipAddr string) (*Neighbor, error) {
+ // iterate through the neighbors and return the one with the same ipAddr
for _, neighbors := range myNeighbors {
for _, neighbor := range neighbors {
if neighbor.VipAddr.String() == ipAddr {
@@ -272,7 +280,16 @@ func GetNeighborByIP(ipAddr string) (*Neighbor, error) {
}
func GetRouteByIP(ipAddr string) (*Neighbor, error) {
+ // iterate through the routing table and return the one with the same ipAddr
+ var defaultRoute *Neighbor
for prefix, hop := range routingTable {
+ // gets the default route
+ if hop.Type == "S" {
+ defaultRoute, _ = GetNeighborByIP(hop.VipAsStr)
+ continue
+ }
+
+ // TODO @ MICHAEL: get the longest prefix match
netIP := net.ParseIP(prefix.Addr().String())
if netIP.String() == ipAddr {
fmt.Println("found route", hop.VipAsStr)
@@ -285,7 +302,8 @@ func GetRouteByIP(ipAddr string) (*Neighbor, error) {
}
}
- return nil, errors.Errorf("No interface with ip %s", ipAddr)
+ fmt.Println("returning default route", defaultRoute.VipAddr.String())
+ return defaultRoute, nil
}
func GetNeighborsToInterface(ifaceName string) ([]*Neighbor, error) {
@@ -300,6 +318,20 @@ func GetMyVIP() Interface {
return myVIP
}
+func GetInterfaces() []*Interface {
+ return myInterfaces
+}
+
+func GetNeighbors() map[string][]*Neighbor {
+ return myNeighbors
+}
+
+func GetRoutes() map[netip.Prefix]Hop {
+ return routingTable
+}
+
+// ************************************** PRINT FUNCTIONS **********************************************************
+
func SprintInterfaces() {
for _, iface := range myInterfaces {
if iface.State {
@@ -338,6 +370,7 @@ func DebugNeighbors() {
}
}
+// TODO @ MICHAEL:
// func RemoveNeighbor(neighbor Neighbor) {
// // TODO: remove from routing table
// myRoutes := GetRoutes()
@@ -359,6 +392,8 @@ func DebugNeighbors() {
// }
// untested function above
+// ************************************** BASIC FUNCTIONS **********************************************************
+
func CleanUp() {
fmt.Print("Cleaning up...\n")
// go through the interfaces, pop thread & close the UDP FDs
@@ -396,7 +431,7 @@ func CleanUp() {
}
// TODO: have it take TTL so we can decrement it when forwarding
-func SendIP(src Interface, dest *Neighbor, protocolNum int, message []byte, destIP string) error {
+func SendIP(src *Interface, dest *Neighbor, protocolNum int, message []byte, destIP string) error {
hdr := ipv4header.IPv4Header{
Version: 4,
Len: 20, // Header length is always 20 when no IP options
@@ -428,36 +463,18 @@ func SendIP(src Interface, dest *Neighbor, protocolNum int, message []byte, dest
log.Fatalln("Error marshalling header: ", err)
}
+ // Combine the header and the message into a single byte array
bytesToSend := make([]byte, 0, len(headerBytes)+len(message))
bytesToSend = append(bytesToSend, headerBytes...)
bytesToSend = append(bytesToSend, []byte(message)...)
- // Send the message to the "link-layer" addr:port on UDP
- listenAddr, err := net.ResolveUDPAddr("udp4", dest.UdpAddr.String())
- if err != nil {
- return err
- }
- // idk that this is ^^
bytesWritten, err := dest.SendSocket.Write(bytesToSend)
if err != nil {
return err
}
-
- // send to the dest.UdpAddr without the SendSocket
- // conn, err := net.DialUDP("udp4", nil, listenAddr)
- // if err != nil {
- // fmt.Println(err, "here5")
- // return err
- // }
-
- // bytesWritten, err := conn.Write(bytesToSend)
- // if err != nil {
- // fmt.Println(err, "here6")
- // return err
- // }
- // what we had previously just in case
- fmt.Printf("Sent %d bytes to %s\n", bytesWritten, listenAddr.String())
+ // TODO @ MICHAEL UPDATE with appropriate src
+ fmt.Printf("Sent %d bytes to %s\n", bytesWritten, dest.UdpAddr.String())
return nil
}
@@ -466,6 +483,7 @@ func RecvIP(conn net.UDPConn, isOpen *bool) error {
buffer := make([]byte, MAX_IP_PACKET_SIZE) // TODO: fix wordking
// Read on the UDP port
+ // Too much printing so I commented it out
// fmt.Println("wating to read from UDP socket")
_, _, err := conn.ReadFromUDP(buffer)
if err != nil {
@@ -516,120 +534,183 @@ func RecvIP(conn net.UDPConn, isOpen *bool) error {
// drop the packet
return nil
}
- if hdr.Protocol == 12 {
- // RIP
- // 1) check if the message is for me, if so, sendUP (aka call the correct handler)
- command := message[0]
- if command == 1 {
- // request
- // SendUpdates()
- } else if command == 2 {
- numEntries := message[1]
-
- entries := make([]RIPEntry, 0, numEntries)
- for i := 0; i < int(numEntries); i++ {
- offset := 4 + 2 + i*12
- address := binary.BigEndian.Uint32(message[offset : offset+4])
- mask := binary.BigEndian.Uint32(message[offset+4 : offset+8])
- cost := binary.BigEndian.Uint32(message[offset+8 : offset+12])
- entries = append(entries, RIPEntry{address: address, mask: mask, cost: cost})
- }
+ switch hdr.Protocol {
+ case 0:
+ // call the test packet handler
+ err = protocolHandlers[int(hdr.Protocol)](nil, nil, message, hdr)
+ if err != nil {
+ fmt.Println("Error handling test packet", err)
+ return err
+ }
+ case 12:
+ // call the RIP handler
+ err = protocolHandlers[int(hdr.Protocol)](nil, nil, message, hdr)
+ if err != nil {
+ fmt.Println("Error handling RIP", err)
+ return err
+ }
+ default:
+ return nil
+
+ }
- // add to routing table
- for _, entry := range entries {
- address := fmt.Sprintf("%d.%d.%d.%d", byte(entry.address>>24), byte(entry.address>>16), byte(entry.address>>8), byte(entry.address))
- mask := fmt.Sprintf("%d.%d.%d.%d", byte(entry.mask>>24), byte((entry.mask>>16)&0xff), byte((entry.mask>>8)&0xff), byte(entry.mask&0xff))
-
- // check if the entry is already in the routing table
- if _, ok := routingTable[netip.MustParsePrefix(address+"/24")]; ok {
- // if so, check if the cost is the same
- // if routingTable[netip.MustParsePrefix(address+"/24")].Cost == entry.cost {
- // // if so, do nothing
- // continue
- // } else {
- // // if not, update the cost
- // routingTable[netip.MustParsePrefix(address+"/24")] = Hop{entry.cost, mask, "R"}
- // }
- continue
- }
- // fmt.Println(entry.cost)
- routingTable[netip.MustParsePrefix(address+"/24")] = Hop{entry.cost + 1, mask, "R"}
- }
+ return nil
+}
+
+// ************************************** Protocol Handlers *******************************************************
+
+func handleRIP(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.IPv4Header) error {
+ command := message[0]
+ switch command {
+ case 1:
+ // request
+ SendUpdates()
+ case 2:
+ numEntries := message[1]
+
+ // parse the entries
+ entries := make([]RIPEntry, 0, numEntries)
+ for i := 0; i < int(numEntries); i++ {
+ offset := SIZE_OF_RIP_MESSAGE + i*SIZE_OF_RIP_ENTRY
+
+ // each field is 4 bytes
+ address := binary.BigEndian.Uint32(message[offset : offset+4])
+ mask := binary.BigEndian.Uint32(message[offset+4 : offset+8])
+ cost := binary.BigEndian.Uint32(message[offset+8 : offset+12])
+
+ // add to entries
+ entries = append(entries, RIPEntry{address: address, mask: mask, cost: cost})
}
- } else {
- // 2) check if the message is for me, if so, sendUP (aka call the correct handler)
- if hdr.Dst.String() == myVIP.IpPrefix.Addr().String() {
- fmt.Println("for me")
- if hdr.Protocol == 0 {
- fmt.Printf("Received test packet: Src: %s, Dst: %s, TTL: %d, Data: %s\n",
- hdr.Src.String(), hdr.Dst.String(), hdr.TTL, string(message))
- return nil
+ // add to routing table
+ for _, entry := range entries {
+ address := fmt.Sprintf("%d.%d.%d.%d", byte(entry.address>>24), byte(entry.address>>16), byte(entry.address>>8), byte(entry.address))
+ mask := fmt.Sprintf("%d.%d.%d.%d", byte(entry.mask>>24), byte((entry.mask>>16)), byte((entry.mask>>8)), byte(entry.mask))
+
+ if address == "0.0.0.0" {
+ continue
+ }
+
+ // TODO @ MICHAEL: check if the entry is already in the routing table and update if need be
+ if _, ok := routingTable[netip.MustParsePrefix(address+"/24")]; ok {
+ continue
}
-
+
+ routingTable[netip.MustParsePrefix(address+"/24")] = Hop{entry.cost + 1, mask, "R"}
}
- // if not, need to forward the packer to a neighbor or check the table
- // after decrementing TTL and updating checksum
- hdr.TTL--
- // update checksum
- headerBytes, err = hdr.Marshal()
- if err != nil {
- log.Fatalln("Error marshalling header: ", err)
+ }
+
+ return nil
+}
+
+func handleTestPackets(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.IPv4Header) error {
+ // 2) check if the message is for me, if so, sendUP (aka call the correct handler)
+ // filter the message, still not the same
+ // TODO @ MICHAEL
+ message = bytes.Map(func(r rune) rune {
+ if unicode.IsPrint(r) {
+ return r
}
- hdr.Checksum = int(ComputeChecksum(headerBytes))
- headerBytes, err = hdr.Marshal()
- if err != nil {
- log.Fatalln("Error marshalling header: ", err)
+ return -1
+ }, message)
+
+ for _, interfaces := range myInterfaces {
+ if hdr.Dst.String() == interfaces.IpPrefix.Addr().String() {
+ fmt.Printf("Received test packet: Src: %s, Dst: %s, TTL: %d, Data: %s\n",
+ hdr.Src.String(), hdr.Dst.String(), hdr.TTL, string(message))
+ return nil
}
- bytesToSend := make([]byte, 0, len(headerBytes)+len(message))
- bytesToSend = append(bytesToSend, headerBytes...)
- bytesToSend = append(bytesToSend, []byte(message)...)
-
-
- // 3) check if message is for a neighbor, if so, sendIP there
- for _, neighbors := range myNeighbors {
- // fmt.Println(neighbors)
- for _, neighbor := range neighbors {
- if hdr.Dst.String() == neighbor.VipAddr.String() {
- fmt.Println("for neighbor")
- // send the packet to the neighbor
- err := SendIP(myVIP, neighbor, hdr.Protocol, bytesToSend, hdr.Dst.String())
- if err != nil {
- fmt.Println("Error sending IP packet", err)
- return err
+ }
+
+ // TODO @ MICHAEL: check if this is correct...
+ // if not, need to forward the packer to a neighbor or check the table
+ // after decrementing TTL and updating checksum
+ hdr.TTL--
+ // update checksum
+ headerBytes, err := hdr.Marshal()
+ if err != nil {
+ log.Fatalln("Error marshalling header: ", err)
+ }
+
+ hdr.Checksum = int(ComputeChecksum(headerBytes))
+ headerBytes, err = hdr.Marshal()
+ if err != nil {
+ log.Fatalln("Error marshalling header: ", err)
+ }
+ bytesToSend := make([]byte, 0, len(headerBytes)+len(message))
+ bytesToSend = append(bytesToSend, headerBytes...)
+ bytesToSend = append(bytesToSend, message...)
+
+
+ // 3) check if message is for a neighbor, if so, sendIP there
+ // fmt.Println("checking neighbors")
+ for _, neighbors := range myNeighbors {
+ for _, neighbor := range neighbors {
+ // check for matching neighbor
+ if hdr.Dst.String() == neighbor.VipAddr.String() {
+ // get the source interface and set dst to it
+ for _, interfaces := range myInterfaces {
+ if interfaces.Name == neighbor.Name {
+ err = SendIP(interfaces, neighbor, hdr.Protocol, bytesToSend, hdr.Dst.String())
+ if err != nil {
+ fmt.Println(err)
+ }
+ break
}
- return nil
}
+ return nil
}
}
- // fmt.Println("No neighbors, checking Routes")
- // 4) check forwarding table. if so, forward to the neighbor with that VIP
-
- for prefix, hop := range routingTable {
- netIP := net.ParseIP(prefix.Addr().String())
- if netIP.String() == hdr.Dst.String() {
- // send the packet to next hop
- neighbors, err := GetNeighborByIP(hop.VipAsStr)
+ }
+ // 4) check forwarding table. if so, forward to the neighbor with that VIP
+ // fmt.Println("checking routing table")
+ for prefix, hop := range routingTable {
+ netIP := net.ParseIP(prefix.Addr().String())
+ // check if the destination is in the routing table
+ if netIP.String() == hdr.Dst.String() {
+ // send the packet to next hop
+ // get the corresponding neighbor
+ neighbor, err := GetNeighborByIP(hop.VipAsStr)
+ if err != nil {
+ fmt.Println("Error getting neighbor by IP", err)
+ // check if there is a route to hop.VipAsStr
+ // this should be done recursively yeah?
+ neighbor, err = GetRouteByIP(hop.VipAsStr)
if err != nil {
- fmt.Println("Error getting neighbor by IP", err)
- return err
+ fmt.Println("Error getting route by IP", err)
+ return nil
}
- err = SendIP(myVIP, neighbors, hdr.Protocol, bytesToSend, hdr.Dst.String())
- if err != nil {
- fmt.Println("Error sending IP packet", err)
- return err
+ for _, interfaces := range myInterfaces {
+ if interfaces.Name == neighbor.Name {
+ err = SendIP(interfaces, neighbor, hdr.Protocol, bytesToSend, hdr.Dst.String())
+ if err != nil {
+ fmt.Println(err)
+ }
+ break
+ }
}
return nil
}
+ // get the source interface and set dst to it
+ for _, interfaces := range myInterfaces {
+ if interfaces.Name == neighbor.Name {
+ err = SendIP(interfaces, neighbor, hdr.Protocol, bytesToSend, hdr.Dst.String())
+ if err != nil {
+ fmt.Println(err)
+ }
+ break
+ }
+ }
+ return nil
}
- // send 10.2.0.3 hello
- // 5) if not, drop the packet
- return nil
}
+ // 5) if not, drop the packet
return nil
}
+// ************************************** CHECKSUM FUNCTIONS ******************************************************
+
func ComputeChecksum(b []byte) uint16 {
checksum := header.Checksum(b, 0)
checksumInv := checksum ^ 0xffff
@@ -643,17 +724,9 @@ func ValidateChecksum(b []byte, fromHeader uint16) uint16 {
return checksum
}
-func GetInterfaces() []*Interface {
- return myInterfaces
-}
-
-func GetNeighbors() map[string][]*Neighbor {
- return myNeighbors
-}
+// ************************************** RIP FUNCTIONS **********************************************************
-func GetRoutes() map[netip.Prefix]Hop {
- return routingTable
-}
+// TODO @ MICHAEL: LONGEST PREFIX MATCHING
func NewRIPMessage(command uint8, entries []RIPEntry) *RIPMessage {
return &RIPMessage{
@@ -695,13 +768,14 @@ func SendRIPMessage(src Interface, dest *Neighbor, message *RIPMessage) error {
bytesToSend := make([]byte, 0, len(headerBytes)+4+1+1+len(message.entries)*12)
bytesToSend = append(bytesToSend, headerBytes...)
-
- buf := make([]byte, 4+1+1+len(message.entries)*12)
+ // 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
for i, entry := range message.entries {
- offset := 4 + 2 + i*12
+ offset := SIZE_OF_RIP_MESSAGE + i*SIZE_OF_RIP_ENTRY
+ // each field is 4 bytes
binary.BigEndian.PutUint32(buf[offset:offset+4], entry.address)
binary.BigEndian.PutUint32(buf[offset+4:offset+8], entry.mask)
binary.BigEndian.PutUint32(buf[offset+8:offset+12], entry.cost)
@@ -709,71 +783,200 @@ func SendRIPMessage(src Interface, dest *Neighbor, message *RIPMessage) error {
bytesToSend = append(bytesToSend, buf...)
+ // send RIP message
_, err = dest.SendSocket.Write(bytesToSend)
if err != nil {
return err
}
-
- // what we had previously just in case
- // lots of printing
- // fmt.Printf("Sent %d bytes to %s\n", bytesWritten, dest.UdpAddr.String())
return nil
}
-func SendUpdates() {
- entries := make([]RIPEntry, len(routingTable))
- for prefix, hop := range routingTable {
- netIP := net.ParseIP(prefix.Addr().String())
- ipBytes := netIP.To4()
- ipUint32 := uint32(ipBytes[0]) << 24 | uint32(ipBytes[1]) << 16 | uint32(ipBytes[2]) << 8 | uint32(ipBytes[3])
+func RequestRip() {
+ // create RIP message
+ message := NewRIPMessage(1, []RIPEntry{})
- if netIP.String() == "0.0.0.0" {
+ // 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
}
+ }
+}
- if hop.Type == "S" {
- continue
+// 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
+// }
+// entry := &RIPEntry{
+// address: ConvertIPToUint32(iface2.IpPrefix.Addr().String()),
+// cost: 1,
+// mask: ConvertIPToUint32(iface.IpPrefix.Addr().String()),
+// }
+// entries = append(entries, *entry)
+// }
+// }
+
+// // create RIP entries from its neighbors
+// for prefix, hop := range routingTable {
+
+// // convert prefix to uint32
+// ipUint32 := ConvertIPToUint32(prefix.Addr().String())
+
+// // dont send RIP entries for static routes
+// if hop.Type == "S" {
+// continue
+// }
+
+// // get
+// 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() {
+// // TODO @ MICHAEL: using myVIP
+// // BUG: this is not correct
+// neighborUint32 := ConvertIPToUint32(myVIP.IpPrefix.Addr().String())
+
+// // Split Horizon with Poisoned Reverse
+// cost := hop.Cost
+// if hop.Type == "R" {
+// cost = INFINITY
+// }
+
+// // create RIP entry
+// entry := &RIPEntry{
+// address: ipUint32,
+// cost: cost,
+// mask: neighborUint32,
+// }
+
+// // add to entries and create RIP message
+// entries = append(entries, *entry)
+// message := NewRIPMessage(2, entries)
+
+// // send RIP message
+// err := SendRIPMessage(myVIP, neighbor, message)
+// if err != nil {
+// continue
+// }
+// }
+// }
+// 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
+ }
+ // cost should be 0 but it is one
+ entry := &RIPEntry{
+ address: ConvertIPToUint32(iface2.IpPrefix.Addr().String()),
+ cost: LOCAL_COST,
+ mask: ConvertIPToUint32(iface.IpPrefix.Addr().String()),
+ }
+ entries = append(entries, *entry)
+
+ entry = &RIPEntry{
+ address: ConvertIPToUint32(iface.IpPrefix.Addr().String()),
+ cost: LOCAL_COST,
+ mask: ConvertIPToUint32(iface2.IpPrefix.Addr().String()),
+ }
+ entries = append(entries, *entry)
}
+ }
- for _, neighbors := range myNeighbors {
- for _, neighbor := range neighbors {
- neighborBits := net.ParseIP(myVIP.IpPrefix.Addr().String())
- neighborBits = neighborBits.To4()
- neighborUint32 := uint32(neighborBits[0]) << 24 | uint32(neighborBits[1]) << 16 | uint32(neighborBits[2]) << 8 | uint32(neighborBits[3])
- cost := hop.Cost
- if hop.Type == "R" {
- cost = INFINITY
- }
- entry := &RIPEntry{
- address: ipUint32,
- cost: cost,
- mask: neighborUint32,
+ // 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
}
- entries = append(entries, *entry)
- message := NewRIPMessage(2, entries)
+ }
+
+ // create RIP entry
+ entry := &RIPEntry{
+ address: ipUint32,
+ cost: LOCAL_COST,
+ mask: neighborUint32,
+ }
- err := SendRIPMessage(myVIP, neighbor, message)
- if err != nil {
- // fmt.Println("Error sending RIP packet")
- continue
+ // 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
+ }
}
}
+
}
+ }
+}
+func ifaceContainsIP(iface Interface, ip netip.Addr) bool {
+ // check if the ip is in the interface's prefix
+ if iface.IpPrefix.Contains(netip.MustParseAddr(ip.String())) {
+ return true
}
+ return false
}
-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()
- }
- }
- }
-} \ No newline at end of file
+func ConvertIPToUint32(ip string) uint32 {
+ netIP := net.ParseIP(ip)
+ ipBytes := netIP.To4()
+ ipUint32 := uint32(ipBytes[0]) << 24 | uint32(ipBytes[1]) << 16 | uint32(ipBytes[2]) << 8 | uint32(ipBytes[3])
+ return ipUint32
+}
+
+// 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: Triggereed Updates \ No newline at end of file