aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/vhost/main.go91
-rw-r--r--cmd/vrouter/main.go113
-rw-r--r--pkg/ipstack/ipstack.go548
-rw-r--r--pkg/ipstack/ipstack_test.go517
-rwxr-xr-xvhostbin3093677 -> 3029942 bytes
-rwxr-xr-xvrouterbin3094162 -> 3099799 bytes
6 files changed, 671 insertions, 598 deletions
diff --git a/cmd/vhost/main.go b/cmd/vhost/main.go
index 02158c4..4684c2f 100644
--- a/cmd/vhost/main.go
+++ b/cmd/vhost/main.go
@@ -3,22 +3,25 @@ package main
import (
"bufio"
"fmt"
- "os"
"iptcp/pkg/ipstack"
+ "net/netip"
+ "os"
"strings"
)
func main() {
-
- if len(os.Args) != 2 {
+ if len(os.Args) == 1 {
fmt.Printf("Usage: %s <configFile>\n", os.Args[0])
os.Exit(1)
}
- fileName := os.Args[1]
-
- go ipstack.Initialize(fileName)
+ fileName := os.Args[2]
+ err := ipstack.Initialize(fileName)
+ if err != nil {
+ return
+ }
+ ipstack.RegisterProtocolHandler(ipstack.TEST_PROTOCOL)
scanner := bufio.NewScanner(os.Stdin)
@@ -53,40 +56,54 @@ func main() {
// combine message into one string
messageToSend := strings.Join(message, " ")
messageToSendBytes := []byte(messageToSend)
-
- // check if ipAddr is in neighbor table
- iface, err := ipstack.GetNeighborByIP(ipAddr)
- if err != nil {
- fmt.Println(err)
- // check if ipAddr is in routing table
- iface, err = ipstack.GetRouteByIP(ipAddr)
- if err != nil {
- fmt.Println(err)
- continue
- }
-
- for _, interfaces := range ipstack.GetInterfaces() {
- if interfaces.Name == iface.Name {
- err = ipstack.SendIP(interfaces, iface, 0, messageToSendBytes, ipAddr, nil)
- if err != nil {
- fmt.Println(err)
- }
- break
+ hop, err := ipstack.LongestPrefix(netip.MustParseAddr(ipAddr))
+ myAddr := hop.Interface.IpPrefix.Addr()
+ for _, neighbor := range ipstack.GetNeighbors()[hop.Interface.Name] {
+ if neighbor.VipAddr == netip.MustParseAddr(ipAddr) {
+ err = ipstack.SendIP(&myAddr, neighbor, ipstack.TEST_PROTOCOL, messageToSendBytes, ipAddr, nil)
+ if err != nil {
+ fmt.Println(err)
}
}
- continue
- }
- for _, interfaces := range ipstack.GetInterfaces() {
- if interfaces.Name == iface.Name {
- err = ipstack.SendIP(interfaces, iface, 0, messageToSendBytes, ipAddr, nil)
- if err != nil {
- fmt.Println(err)
- }
- break
- }
}
- continue
+ //
+ // // check if ipAddr is in neighbor table
+ // iface, err := ipstack.GetNeighborByIP(ipAddr)
+ // if err != nil {
+ // fmt.Println(err)
+ //
+ // // check if ipAddr is in routing table
+ // iface, err = ipstack.GetRouteByIP(ipAddr)
+ // if err != nil {
+ // fmt.Println(err)
+ // continue
+ // }
+ //
+ // for _, interfaces := range ipstack.GetInterfaces() {
+ // if interfaces.Name == iface.Name {
+ // src := interfaces.IpPrefix.Addr()
+ // err = ipstack.SendIP(&src, iface, 0, messageToSendBytes, ipAddr, nil)
+ // if err != nil {
+ // fmt.Println(err)
+ // }
+ // break
+ // }
+ // }
+ // continue
+ // }
+ // for _, interfaces := range ipstack.GetInterfaces() {
+ // if interfaces.Name == iface.Name {
+ // src := interfaces.IpPrefix.Addr()
+ // err = ipstack.SendIP(&src, iface, 0, messageToSendBytes, ipAddr, nil)
+ // if err != nil {
+ // fmt.Println(err)
+ // }
+ // break
+ // }
+ // }
+ // continue
+ //}
}
}
if len(line) > 2 {
@@ -99,4 +116,4 @@ func main() {
continue
}
}
-} \ No newline at end of file
+}
diff --git a/cmd/vrouter/main.go b/cmd/vrouter/main.go
index eb7a1eb..ba7f285 100644
--- a/cmd/vrouter/main.go
+++ b/cmd/vrouter/main.go
@@ -3,33 +3,37 @@ package main
import (
"bufio"
"fmt"
- "os"
- "time"
"iptcp/pkg/ipstack"
+ "net/netip"
+ "os"
"strings"
-
)
func main() {
- if len(os.Args) != 2 {
+ if len(os.Args) == 1 {
fmt.Printf("Usage: %s <configFile>\n", os.Args[0])
os.Exit(1)
}
- fileName := os.Args[1]
+ fileName := os.Args[2]
- go ipstack.Initialize(fileName)
+ err := ipstack.Initialize(fileName)
+ if err != nil {
+ return
+ }
+ ipstack.RegisterProtocolHandler(ipstack.TEST_PROTOCOL)
+ ipstack.RegisterProtocolHandler(ipstack.RIP_PROTOCOL)
// TODO @ MICHAEL: Dont know why its not running instantly
- go func() {
- for {
- ipstack.RequestRip()
- // takes time to compute I think
- // TODO @ MICHAEL
- time.Sleep(2 * time.Second)
- }
- }()
-
+ //go func() {
+ // for {
+ // ipstack.RequestRip()
+ // // takes time to compute I think
+ // // TODO @ MICHAEL
+ // time.Sleep(2 * time.Second)
+ // }
+ //}()
+
// TODO @ MICHEAL
// go ipstack.CheckAndUpdateRoutingTable()
@@ -66,42 +70,55 @@ func main() {
// combine message into one string
messageToSend := strings.Join(message, " ")
messageToSendBytes := []byte(messageToSend)
-
- // check if ipAddr is in neighbor table
- iface, err := ipstack.GetNeighborByIP(ipAddr)
- if err != nil {
- fmt.Println(err)
- // check if ipAddr is in routing table
- iface, err = ipstack.GetRouteByIP(ipAddr)
- if err != nil {
- fmt.Println(err)
- continue
- }
-
- // get the interface to send from
- for _, interfaces := range ipstack.GetInterfaces() {
- if interfaces.Name == iface.Name {
- err = ipstack.SendIP(interfaces, iface, 0, messageToSendBytes, ipAddr, nil)
- if err != nil {
- fmt.Println(err)
- }
- break
+ hop, err := ipstack.LongestPrefix(netip.MustParseAddr(ipAddr))
+ myAddr := hop.Interface.IpPrefix.Addr()
+ for _, neighbor := range ipstack.GetNeighbors()[hop.Interface.Name] {
+ if neighbor.VipAddr == netip.MustParseAddr(ipAddr) {
+ err = ipstack.SendIP(&myAddr, neighbor, ipstack.TEST_PROTOCOL, messageToSendBytes, ipAddr, nil)
+ if err != nil {
+ fmt.Println(err)
}
}
- continue
}
- // neighbor was found, send to neighbor
- for _, interfaces := range ipstack.GetInterfaces() {
- if interfaces.Name == iface.Name {
- err = ipstack.SendIP(interfaces, iface, 0, messageToSendBytes, ipAddr, nil)
- if err != nil {
- fmt.Println(err)
- }
- break
- }
- }
- continue
+
+ //// check if ipAddr is in neighbor table
+ //iface, err := ipstack.GetNeighborByIP(ipAddr)
+ //if err != nil {
+ // fmt.Println(err)
+ //
+ // // check if ipAddr is in routing table
+ // iface, err = ipstack.GetRouteByIP(ipAddr)
+ // if err != nil {
+ // fmt.Println(err)
+ // continue
+ // }
+ //
+ // // get the interface to send from
+ // for _, interfaces := range ipstack.GetInterfaces() {
+ // if interfaces.Name == iface.Name {
+ // src := interfaces.IpPrefix.Addr()
+ // err = ipstack.SendIP(&src, iface, 0, messageToSendBytes, ipAddr, nil)
+ // if err != nil {
+ // fmt.Println(err)
+ // }
+ // break
+ // }
+ // }
+ // continue
+ //}
+ //// neighbor was found, send to neighbor
+ //for _, interfaces := range ipstack.GetInterfaces() {
+ // if interfaces.Name == iface.Name {
+ // src := interfaces.IpPrefix.Addr()
+ // err = ipstack.SendIP(&src, iface, 0, messageToSendBytes, ipAddr, nil)
+ // if err != nil {
+ // fmt.Println(err)
+ // }
+ // break
+ // }
+ //}
+ //continue
}
}
if len(line) > 2 {
@@ -114,4 +131,4 @@ func main() {
continue
}
}
-} \ No newline at end of file
+}
diff --git a/pkg/ipstack/ipstack.go b/pkg/ipstack/ipstack.go
index 0cc1fff..e47c741 100644
--- a/pkg/ipstack/ipstack.go
+++ b/pkg/ipstack/ipstack.go
@@ -1,6 +1,7 @@
package ipstack
import (
+ "encoding/binary"
"fmt"
ipv4header "github.com/brown-csci1680/iptcp-headers"
"github.com/google/netstack/tcpip/header"
@@ -10,21 +11,20 @@ import (
"net"
"net/netip"
"time"
- "encoding/binary"
// "bytes"
// "unicode"
)
const (
- MAX_IP_PACKET_SIZE = 1400
- LOCAL_COST uint32 = 0
- 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
+ MAX_IP_PACKET_SIZE = 1400
+ LOCAL_COST uint32 = 0
+ 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 ---------------------------------------------------------------------
@@ -39,12 +39,9 @@ type Interface struct {
}
type Neighbor struct {
- Name string
+ Name string
VipAddr netip.Addr
UdpAddr netip.AddrPort
-
- SendSocket net.UDPConn
- SocketChannel chan bool
}
type RIPMessage struct {
@@ -55,14 +52,16 @@ type RIPMessage struct {
type RIPEntry struct {
address uint32
- cost uint32
- mask uint32
+ cost uint32
+ mask uint32
}
type Hop struct {
- Cost uint32
- VipAsStr string
- Type string
+ Cost uint32
+ Type string
+
+ Interface *Interface
+ VIP netip.Addr
}
// GLOBAL VARIABLES (data structures) ------------------------------------------
@@ -70,7 +69,7 @@ var myVIP Interface
var myInterfaces []*Interface
var myNeighbors = make(map[string][]*Neighbor)
-var myRIPNeighbors = make([]netip.Addr, 0)
+var myRIPNeighbors = make([]netip.Addr, 0)
type HandlerFunc func(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.IPv4Header) error
@@ -80,25 +79,17 @@ 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 {
+func createUDPListener(UdpAddr netip.AddrPort, conn *net.UDPConn) error {
listenString := UdpAddr.String()
listenAddr, err := net.ResolveUDPAddr("udp4", listenString)
if err != nil {
return errors.WithMessage(err, "Error resolving address->\t"+listenString)
}
- if !isN {
- tmpConn, err := net.ListenUDP("udp4", listenAddr)
- if err != nil {
- return errors.WithMessage(err, "Could not bind to UDP port->\t"+listenString)
- }
- *conn = *tmpConn
- } else {
- tmpConn, err := net.DialUDP("udp4", nil, listenAddr)
- if err != nil {
- return errors.WithMessage(err, "Could not bind to UDP port->\t"+listenString)
- }
- *conn = *tmpConn
+ tmpConn, err := net.ListenUDP("udp4", listenAddr)
+ if err != nil {
+ return errors.WithMessage(err, "Could not bind to UDP port->\t"+listenString)
}
+ *conn = *tmpConn
return nil
}
@@ -110,9 +101,8 @@ func Initialize(lnxFilePath string) error {
return errors.WithMessage(err, "Error parsing config file->\t"+lnxFilePath)
}
- // 1) initialize the interfaces on this node here and into the routing table
- static := false
- interfaceToReturn := Interface{}
+ // 1) add each local if to the routing table, as dictated by its subnet
+ // static := false
for _, iface := range lnxConfig.Interfaces {
prefix := netip.PrefixFrom(iface.AssignedIP, iface.AssignedPrefix.Bits())
i := &Interface{
@@ -123,77 +113,60 @@ func Initialize(lnxFilePath string) error {
SocketChannel: make(chan bool),
State: true,
}
- if interfaceToReturn == (Interface{}) {
- interfaceToReturn = *i
- myVIP = *i
- }
// Added this for printing purposes for REPL FYI, if you have a better way lmk
- err := createUDPConn(iface.UDPAddr, &i.RecvSocket, false)
+ err := createUDPListener(iface.UDPAddr, &i.RecvSocket)
if err != nil {
return errors.WithMessage(err, "Error creating UDP socket for interface->\t"+iface.Name)
}
- go InterfaceListenerRoutine(i.RecvSocket, i.SocketChannel)
+
+ go InterfaceListenerRoutine(i)
myInterfaces = append(myInterfaces, i)
+ routingTable[prefix] = Hop{STATIC_COST, "L", i, prefix.Addr()}
+
// TODO @ MICHAEL: The hop shouldn't be the interface name
- if !static {
- ifacePrefix := netip.MustParsePrefix("0.0.0.0/0")
- routingTable[ifacePrefix] = Hop{STATIC_COST, iface.Name, "S"}
- static = true
- }
+ //if !static {
+ // ifacePrefix := netip.MustParsePrefix("0.0.0.0/0")
+ // routingTable[ifacePrefix] = Hop{STATIC_COST, "S", nil}
+ // static = true
+ //}
}
- // 2) initialize the neighbors connected to the node and into the routing table
+ // 2) add neighbors to if->neighbors map
for _, neighbor := range lnxConfig.Neighbors {
n := &Neighbor{
- Name: neighbor.InterfaceName,
- VipAddr: neighbor.DestAddr,
- UdpAddr: neighbor.UDPAddr,
- SendSocket: net.UDPConn{},
- SocketChannel: make(chan bool),
- }
-
- err := createUDPConn(neighbor.UDPAddr, &n.SendSocket, true)
- if err != nil {
- return errors.WithMessage(err, "Error creating UDP socket for neighbor->\t"+neighbor.DestAddr.String())
+ Name: neighbor.InterfaceName,
+ VipAddr: neighbor.DestAddr,
+ UdpAddr: neighbor.UDPAddr,
}
myNeighbors[neighbor.InterfaceName] = append(myNeighbors[neighbor.InterfaceName], n)
-
- // add to routing table
- // TODO: REVISIT AND SEE IF "24" IS CORRECT
- neighborPrefix := netip.PrefixFrom(neighbor.DestAddr, 24)
- routingTable[neighborPrefix] = Hop{LOCAL_COST, neighbor.InterfaceName, "L"}
- }
-
- 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
- routingTable[prefix] = Hop{STATIC_COST, addr.String(), "S"}
}
+ //
+ //for _, route := range lnxConfig.RipNeighbors {
+ // // add to RIP neighbors
+ // myRIPNeighbors = append(myRIPNeighbors, route)
+ //}
- go SendUpdates()
// add protocol handlers
- protocolHandlers[RIP_PROTOCOL] = handleRIP
- protocolHandlers[TEST_PROTOCOL] = handleTestPackets
return nil
}
-func InterfaceListenerRoutine(socket net.UDPConn, signal <-chan bool) {
+func InterfaceListenerRoutine(i *Interface) {
+ // decompose the interface
+ prefix := i.IpPrefix
+ socket := i.RecvSocket
+ signal := i.SocketChannel
+
+ // booleans to control listening routine
isUp := true
- // testing purposes set to TRUE
closed := false
// go routine that hangs on the recv
fmt.Println("MAKING GO ROUTINE TO LISTEN:\t", socket.LocalAddr().String())
go func() {
- defer func() { // on close, set isUp to false
+ defer func() {
fmt.Println("exiting go routine that listens on ", socket.LocalAddr().String())
}()
@@ -206,7 +179,7 @@ func InterfaceListenerRoutine(socket net.UDPConn, signal <-chan bool) {
}
// TODO: remove these "training wheels"
time.Sleep(1 * time.Millisecond)
- err := RecvIP(socket, &isUp)
+ err := RecvIP(prefix, socket, &isUp)
if err != nil {
fmt.Println("Error receiving IP packet", err)
return
@@ -286,41 +259,6 @@ func GetNeighborByIP(ipAddr string) (*Neighbor, error) {
return nil, errors.Errorf("No interface with ip %s", ipAddr)
}
-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)
- neighbor, err := GetNeighborByIP(hop.VipAsStr)
- if err != nil {
- fmt.Println("Error getting neighbors to interface", err)
- neighbor, err = GetRouteByIP(hop.VipAsStr)
- if err != nil {
- fmt.Println("Error getting route by IP", err)
- return nil, err
- }
- // continue // fix with longest prefix matching?
- }
- return neighbor, nil
- }
- }
-
- if defaultRoute == nil {
- return nil, errors.Errorf("No route to ip %s", ipAddr)
- }
- fmt.Println("returning default route", defaultRoute.VipAddr.String())
- return defaultRoute, nil
-}
-
func GetNeighborsToInterface(ifaceName string) ([]*Neighbor, error) {
if neighbors, ok := myNeighbors[ifaceName]; ok {
return neighbors, nil
@@ -368,11 +306,11 @@ func SprintNeighbors() {
func SprintRoutingTable() {
for prefix, hop := range routingTable {
if hop.Type == "L" {
- fmt.Printf("%s\t%s\tLOCAL:%s\t%d\n", hop.Type, prefix.String(), hop.VipAsStr, 0)
+ fmt.Printf("%s\t%s\tLOCAL:%s\t%d\n", hop.Type, prefix.String(), hop.Interface.Name, 0)
} else if hop.Type == "S" {
- fmt.Printf("%s\t%s\t%s\t%s\n", hop.Type, prefix.String(), hop.VipAsStr, "-")
+ fmt.Printf("%s\t%s\t%s\t%s\n", hop.Type, prefix.String(), myVIP.IpPrefix.Addr().String(), "-")
} else {
- fmt.Printf("%s\t%s\t%s\t%d\n", hop.Type, prefix.String(), hop.VipAsStr, hop.Cost)
+ fmt.Printf("%s\t%s\t%s\t%d\n", hop.Type, prefix.String(), hop.VIP, hop.Cost)
}
}
}
@@ -385,7 +323,7 @@ func DebugNeighbors() {
}
}
-// TODO @ MICHAEL:
+// TODO @ MICHAEL:
// func RemoveNeighbor(neighbor Neighbor) {
// // TODO: remove from routing table
// myRoutes := GetRoutes()
@@ -394,7 +332,7 @@ func DebugNeighbors() {
// delete(myRoutes, prefix)
// }
// }
-
+
// // TODO: remove from myNeighbors
// myNeighbors[neighbor.VipAddr.String()] = nil
@@ -422,19 +360,6 @@ func CleanUp() {
}
}
- // go through the neighbors, pop thread & close the UDP FDs
- for _, neighbor := range myNeighbors {
- for _, n := range neighbor {
- if n.SocketChannel != nil {
- close(n.SocketChannel)
- }
- err := n.SendSocket.Close()
- if err != nil {
- continue
- }
- }
- }
-
// delete all the neighbors
myNeighbors = make(map[string][]*Neighbor)
// delete all the interfaces
@@ -446,7 +371,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, hdr *ipv4header.IPv4Header) error {
+func SendIP(src *netip.Addr, dest *Neighbor, protocolNum int, message []byte, destIP string, hdr *ipv4header.IPv4Header) error {
if hdr == nil {
hdr = &ipv4header.IPv4Header{
Version: 4,
@@ -459,28 +384,14 @@ func SendIP(src *Interface, dest *Neighbor, protocolNum int, message []byte, des
TTL: 32,
Protocol: protocolNum,
Checksum: 0, // Should be 0 until checksum is computed
- Src: src.IpPrefix.Addr(),
+ Src: *src,
Dst: netip.MustParseAddr(destIP),
Options: []byte{},
}
} else {
- hdr = &ipv4header.IPv4Header{
- Version: 4,
- Len: 20, // Header length is always 20 when no IP options
- TOS: 0,
- TotalLen: ipv4header.HeaderLen + len(message),
- ID: 0,
- Flags: 0,
- FragOff: 0,
- TTL: hdr.TTL - 1,
- Protocol: protocolNum,
- Checksum: 0, // Should be 0 until checksum is computed
- Src: src.IpPrefix.Addr(),
- Dst: netip.MustParseAddr(destIP),
- Options: []byte{},
- }
+ hdr.TTL--
}
-
+
// Assemble the header into a byte array
headerBytes, err := hdr.Marshal()
if err != nil {
@@ -501,17 +412,24 @@ func SendIP(src *Interface, dest *Neighbor, protocolNum int, message []byte, des
bytesToSend = append(bytesToSend, headerBytes...)
bytesToSend = append(bytesToSend, []byte(message)...)
- bytesWritten, err := dest.SendSocket.Write(bytesToSend)
+ 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())
+ }
+ // *conn = *tmpConn
+
+ bytesWritten, err := tmpConn.Write(bytesToSend)
if err != nil {
return err
}
-
+
fmt.Printf("Sent %d bytes to %s\n", bytesWritten, dest.VipAddr.String())
return nil
}
-func RecvIP(conn net.UDPConn, isOpen *bool) error {
+func RecvIP(prefix netip.Prefix, conn net.UDPConn, isOpen *bool) error {
buffer := make([]byte, MAX_IP_PACKET_SIZE) // TODO: fix wordking
// Read on the UDP port
@@ -559,37 +477,72 @@ func RecvIP(conn net.UDPConn, isOpen *bool) error {
// drop the packet
return nil
}
-
+
// check if the checksum is valid
if checksumState == "FAIL" {
// drop the packet
return nil
}
- 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
+
+ // 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)
+ fmt.Println("checking if it's for me!")
+ if hdr.Dst == prefix.Addr() {
+ // see if there is a handler for this protocol
+ if handler, ok := protocolHandlers[hdr.Protocol]; ok {
+ err := handler(&myVIP, nil, message, hdr)
+ if err != nil {
+ fmt.Println(err)
+ }
}
- default:
return nil
-
}
+ // 4) check forwarding table.
+ // if it's a local hop, send to that iface
+ // if it's a RIP hop, send to the neighbor with that VIP
+ fmt.Println("checking routing table")
+ hop, err := LongestPrefix(hdr.Dst)
+ if err == nil { // on no err, found a match
+ fmt.Println("found route", hop.VIP)
+ if hop.Type == "S" {
+ // default, static route
+ // drop in this case
+ return nil
+ }
+
+ // local and RIP hops
+ if hop.Type == "L" || hop.Type == "R" {
+ // if it's a local route, then the name is the interface name
+ for _, neighbor := range myNeighbors[hop.Interface.Name] {
+ if neighbor.VipAddr == hdr.Dst {
+ err2 := SendIP(nil, neighbor, hdr.Protocol, message, hdr.Dst.String(), hdr)
+ if err2 != nil {
+ return err2
+ }
+ }
+ }
+ }
+ }
+
+ // if not in table, drop packet
return nil
}
// ************************************** Protocol Handlers *******************************************************
+func RegisterProtocolHandler(protocolNum int) bool {
+ if protocolNum == RIP_PROTOCOL {
+ protocolHandlers[protocolNum] = handleRIP
+ return true
+ }
+ if protocolNum == TEST_PROTOCOL {
+ protocolHandlers[protocolNum] = handleTestPackets
+ return true
+ }
+ return false
+}
+
func handleRIP(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.IPv4Header) error {
command := message[0]
switch command {
@@ -617,20 +570,22 @@ func handleRIP(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.I
// 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))
+ mask := binary.LittleEndian.Uint32(message[4:8])
+ prefix := netip.PrefixFrom(netip.MustParseAddr(address), int(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 {
+ if _, ok := routingTable[prefix]; ok {
continue
}
+
if entry.cost == 17 {
- routingTable[netip.MustParsePrefix(address+"/24")] = Hop{0, mask, "R"}
+ routingTable[prefix] = Hop{0, "R", src, prefix.Addr()}
} else {
- routingTable[netip.MustParsePrefix(address+"/24")] = Hop{entry.cost + 1, mask, "R"}
+ routingTable[prefix] = Hop{entry.cost + 1, "R", src, prefix.Addr()}
}
}
}
@@ -639,96 +594,104 @@ func handleRIP(src *Interface, dest *Neighbor, message []byte, hdr *ipv4header.I
}
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)
-
- // potentially unneeded
- // message = bytes.Map(func(r rune) rune {
- // if unicode.IsPrint(r) {
- // return r
- // }
- // return -1
- // }, message)
-
- fmt.Println("checking my interfaces")
- 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
- }
- }
-
- // if not, need to forward the packer to a neighbor or check the table
- // after decrementing TTL and updating checksum
- // DONE IN SENDIP FUNCTION
-
- // 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, message, hdr.Dst.String(), hdr)
- if err != nil {
- fmt.Println(err)
- }
- break
- }
- }
- return nil
- }
- }
- }
- // 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 route by IP", err)
- return nil
- }
- for _, interfaces := range myInterfaces {
- if interfaces.Name == neighbor.Name {
- err = SendIP(interfaces, neighbor, hdr.Protocol, message, hdr.Dst.String(), hdr)
- 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, message, hdr.Dst.String(), hdr)
- if err != nil {
- fmt.Println(err)
- }
- break
- }
- }
- return nil
- }
- }
-
- // 5) if not, drop the packet
+ 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
}
+//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)
+//
+// // potentially unneeded
+// // message = bytes.Map(func(r rune) rune {
+// // if unicode.IsPrint(r) {
+// // return r
+// // }
+// // return -1
+// // }, message)
+//
+// fmt.Println("checking my interfaces")
+// 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
+// }
+// }
+//
+// // if not, need to forward the packer to a neighbor or check the table
+// // after decrementing TTL and updating checksum
+// // DONE IN SENDIP FUNCTION
+//
+// // 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, message, hdr.Dst.String(), hdr)
+// if err != nil {
+// fmt.Println(err)
+// }
+// break
+// }
+// }
+// return nil
+// }
+// }
+// }
+// // 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 route by IP", err)
+// return nil
+// }
+// for _, interfaces := range myInterfaces {
+// if interfaces.Name == neighbor.Name {
+// src := interfaces.IpPrefix.Addr()
+// err = SendIP(&src, neighbor, hdr.Protocol, message, hdr.Dst.String(), hdr)
+// 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 {
+// src := interfaces.IpPrefix.Addr()
+// err = SendIP(&src, neighbor, hdr.Protocol, message, hdr.Dst.String(), hdr)
+// if err != nil {
+// fmt.Println(err)
+// }
+// break
+// }
+// }
+// return nil
+// }
+// }
+//
+// // 5) if not, drop the packet
+// return nil
+//}
+
// ************************************** CHECKSUM FUNCTIONS ******************************************************
func ComputeChecksum(b []byte) uint16 {
@@ -747,12 +710,24 @@ func ValidateChecksum(b []byte, fromHeader uint16) uint16 {
// ************************************** RIP FUNCTIONS **********************************************************
// TODO @ MICHAEL: LONGEST PREFIX MATCHING
+func LongestPrefix(src netip.Addr) (Hop, error) {
+ possibleBits := [5]int{32, 24, 16, 8, 0}
+ for _, bits := range possibleBits {
+ cmpPrefix := netip.PrefixFrom(src, bits)
+ for prefix, hop := range routingTable {
+ if cmpPrefix.Overlaps(prefix) {
+ return hop, nil
+ }
+ }
+ }
+ return Hop{}, errors.Errorf("No route to ip %s on table.", src)
+}
func NewRIPMessage(command uint8, entries []RIPEntry) *RIPMessage {
return &RIPMessage{
- command: command,
+ command: command,
numEntries: uint8(len(entries)),
- entries: entries,
+ entries: entries,
}
}
@@ -787,9 +762,9 @@ 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...)
-
+
// make the RIP message
- buf := make([]byte, SIZE_OF_RIP_MESSAGE + len(message.entries)*SIZE_OF_RIP_ENTRY)
+ buf := make([]byte, SIZE_OF_RIP_MESSAGE+len(message.entries)*SIZE_OF_RIP_ENTRY)
buf[0] = message.command
buf[1] = message.numEntries
@@ -804,7 +779,12 @@ func SendRIPMessage(src Interface, dest *Neighbor, message *RIPMessage) error {
bytesToSend = append(bytesToSend, buf...)
// send RIP message
- _, err = dest.SendSocket.Write(bytesToSend)
+ 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())
+ }
+ _, err = tmpConn.Write(bytesToSend)
if err != nil {
return err
}
@@ -854,7 +834,7 @@ func RequestRip() {
// // create RIP entries from its neighbors
// for prefix, hop := range routingTable {
-
+
// // convert prefix to uint32
// ipUint32 := ConvertIPToUint32(prefix.Addr().String())
@@ -866,15 +846,15 @@ func RequestRip() {
// // 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
+// // BUG: this is not correct
// neighborUint32 := ConvertIPToUint32(myVIP.IpPrefix.Addr().String())
-
+
// // Split Horizon with Poisoned Reverse
// cost := hop.Cost
// if hop.Type == "R" {
@@ -919,15 +899,15 @@ func SendUpdates() {
// 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()),
+ 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()),
+ cost: 17,
+ mask: ConvertIPToUint32(iface2.IpPrefix.Addr().String()),
}
entries = append(entries, *entry)
}
@@ -944,12 +924,12 @@ func SendUpdates() {
break
}
}
-
+
// create RIP entry
entry := &RIPEntry{
address: ipUint32,
- cost: LOCAL_COST,
- mask: neighborUint32,
+ cost: LOCAL_COST,
+ mask: neighborUint32,
}
// add to entries and create RIP message
@@ -967,7 +947,7 @@ func SendUpdates() {
}
}
- }
+ }
}
func ifaceContainsIP(iface Interface, ip netip.Addr) bool {
@@ -981,10 +961,14 @@ func ifaceContainsIP(iface Interface, ip netip.Addr) bool {
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])
+ ipUint32 := uint32(ipBytes[0])<<24 | uint32(ipBytes[1])<<16 | uint32(ipBytes[2])<<8 | uint32(ipBytes[3])
return ipUint32
}
+func intersect(n1, n2 netip.Prefix) bool {
+ return n1.Overlaps(n2)
+}
+
// TODO @ MICHEAL: Handle links going down and link recovery
// func CheckAndUpdateRoutingTable() {
// for {
@@ -1000,4 +984,4 @@ func ConvertIPToUint32(ip string) uint32 {
// }
// }
-// TODO @ MICHAEL: Triggered Updates and Split Horizon with Poisoned Reverse \ No newline at end of file
+// TODO @ MICHAEL: Triggered Updates and Split Horizon with Poisoned Reverse
diff --git a/pkg/ipstack/ipstack_test.go b/pkg/ipstack/ipstack_test.go
index 941c4e9..5cef903 100644
--- a/pkg/ipstack/ipstack_test.go
+++ b/pkg/ipstack/ipstack_test.go
@@ -2,252 +2,307 @@ package ipstack
import (
"fmt"
- ipv4header "github.com/brown-csci1680/iptcp-headers"
- "net"
"net/netip"
"testing"
- "time"
)
-func TestInitialize(t *testing.T) {
- lnxFilePath := "../../doc-example/r2.lnx"
- err := Initialize(lnxFilePath)
- if err != nil {
- t.Error(err)
- }
- fmt.Printf("Interfaces:\n%s\n\n", SprintInterfaces())
- fmt.Printf("Neighbors:\n%s\n", SprintNeighbors())
- fmt.Printf("RoutingTable:\n%s\n", SprintRoutingTable())
-
- fmt.Println("TestInitialize successful")
- t.Cleanup(func() { CleanUp() })
-}
-
-func TestInterfaceUpThenDown(t *testing.T) {
- lnxFilePath := "../../doc-example/r2.lnx"
- err := Initialize(lnxFilePath)
- if err != nil {
- t.Error(err)
- }
-
- iface, err := GetInterfaceByName("if0")
- if err != nil {
- t.Error(err)
- }
-
- InterfaceUp(iface)
- if iface.State == false {
- t.Error("iface state should be true")
- }
-
- fmt.Printf("Interfaces:\n%s\n", SprintInterfaces())
-
- time.Sleep(5 * time.Millisecond) // allow time to print
-
- InterfaceDown(iface)
- if iface.State == true {
- t.Error("iface state should be false")
- }
-
- time.Sleep(5 * time.Millisecond) // allow time to print
-
- fmt.Printf("Interfaces:\n%s\n", SprintInterfaces())
-
- fmt.Println("TestInterfaceUpThenDown successful")
- t.Cleanup(func() { CleanUp() })
-}
-
-func TestInterfaceUpThenDownTwice(t *testing.T) {
- lnxFilePath := "../../doc-example/r2.lnx"
- err := Initialize(lnxFilePath)
- if err != nil {
- t.Error(err)
- }
-
- iface, err := GetInterfaceByName("if0")
- if err != nil {
- t.Error(err)
- }
-
- InterfaceUp(iface)
- if iface.State == false {
- t.Error("iface state should be true")
- }
-
- fmt.Printf("Interfaces:\n%s\n", SprintInterfaces())
-
- time.Sleep(5 * time.Millisecond) // allow time to print
-
- fmt.Println("putting interface down")
- InterfaceDown(iface)
- if iface.State == true {
- t.Error("iface state should be false")
- }
-
- time.Sleep(3 * time.Millisecond)
-
- fmt.Println("putting interface back up for 3 iterations")
- InterfaceUp(iface)
- if iface.State == false {
- t.Error("iface state should be true")
- }
- time.Sleep(3 * time.Millisecond) // allow time to print
-
- fmt.Println("putting interface down")
- InterfaceDown(iface)
- if iface.State == true {
- t.Error("iface state should be false")
- }
-
- time.Sleep(5 * time.Millisecond) // allow time to print
-
- fmt.Printf("Interfaces:\n%s\n", SprintInterfaces())
-
- fmt.Println("TestInterfaceUpThenDownTwice successful")
- t.Cleanup(func() { CleanUp() })
-}
-
-func TestSendIPToNeighbor(t *testing.T) {
- lnxFilePath := "../../doc-example/r2.lnx"
- err := Initialize(lnxFilePath)
- if err != nil {
- t.Error(err)
- }
-
- // get the first neighbor of this interface
- iface, err := GetInterfaceByName("if0")
- if err != nil {
- t.Error(err)
- }
- neighbors, err := GetNeighborsToInterface("if0")
- if err != nil {
- t.Error(err)
- }
-
- // setup a neighbor listener socket
- testNeighbor := neighbors[0]
- // close the socket so we can listen on it
- err = testNeighbor.SendSocket.Close()
- if err != nil {
- t.Error(err)
- }
-
- fmt.Printf("Interfaces:\n%s\n", SprintInterfaces())
- fmt.Printf("Neighbors:\n%s\n", SprintNeighbors())
-
- listenString := testNeighbor.UdpAddr.String()
- fmt.Println("listening on " + listenString)
- listenAddr, err := net.ResolveUDPAddr("udp4", listenString)
- if err != nil {
- t.Error(err)
+//func TestInitialize(t *testing.T) {
+// lnxFilePath := "../../doc-example/r2.lnx"
+// err := Initialize(lnxFilePath)
+// if err != nil {
+// t.Error(err)
+// }
+// fmt.Printf("Interfaces:\n%s\n\n", SprintInterfaces())
+// fmt.Printf("Neighbors:\n%s\n", SprintNeighbors())
+// fmt.Printf("RoutingTable:\n%s\n", SprintRoutingTable())
+//
+// fmt.Println("TestInitialize successful")
+// t.Cleanup(func() { CleanUp() })
+//}
+//
+//func TestInterfaceUpThenDown(t *testing.T) {
+// lnxFilePath := "../../doc-example/r2.lnx"
+// err := Initialize(lnxFilePath)
+// if err != nil {
+// t.Error(err)
+// }
+//
+// iface, err := GetInterfaceByName("if0")
+// if err != nil {
+// t.Error(err)
+// }
+//
+// InterfaceUp(iface)
+// if iface.State == false {
+// t.Error("iface state should be true")
+// }
+//
+// fmt.Printf("Interfaces:\n%s\n", SprintInterfaces())
+//
+// time.Sleep(5 * time.Millisecond) // allow time to print
+//
+// InterfaceDown(iface)
+// if iface.State == true {
+// t.Error("iface state should be false")
+// }
+//
+// time.Sleep(5 * time.Millisecond) // allow time to print
+//
+// fmt.Printf("Interfaces:\n%s\n", SprintInterfaces())
+//
+// fmt.Println("TestInterfaceUpThenDown successful")
+// t.Cleanup(func() { CleanUp() })
+//}
+//
+//func TestInterfaceUpThenDownTwice(t *testing.T) {
+// lnxFilePath := "../../doc-example/r2.lnx"
+// err := Initialize(lnxFilePath)
+// if err != nil {
+// t.Error(err)
+// }
+//
+// iface, err := GetInterfaceByName("if0")
+// if err != nil {
+// t.Error(err)
+// }
+//
+// InterfaceUp(iface)
+// if iface.State == false {
+// t.Error("iface state should be true")
+// }
+//
+// fmt.Printf("Interfaces:\n%s\n", SprintInterfaces())
+//
+// time.Sleep(5 * time.Millisecond) // allow time to print
+//
+// fmt.Println("putting interface down")
+// InterfaceDown(iface)
+// if iface.State == true {
+// t.Error("iface state should be false")
+// }
+//
+// time.Sleep(3 * time.Millisecond)
+//
+// fmt.Println("putting interface back up for 3 iterations")
+// InterfaceUp(iface)
+// if iface.State == false {
+// t.Error("iface state should be true")
+// }
+// time.Sleep(3 * time.Millisecond) // allow time to print
+//
+// fmt.Println("putting interface down")
+// InterfaceDown(iface)
+// if iface.State == true {
+// t.Error("iface state should be false")
+// }
+//
+// time.Sleep(5 * time.Millisecond) // allow time to print
+//
+// fmt.Printf("Interfaces:\n%s\n", SprintInterfaces())
+//
+// fmt.Println("TestInterfaceUpThenDownTwice successful")
+// t.Cleanup(func() { CleanUp() })
+//}
+//
+//func TestSendIPToNeighbor(t *testing.T) {
+// lnxFilePath := "../../doc-example/r2.lnx"
+// err := Initialize(lnxFilePath)
+// if err != nil {
+// t.Error(err)
+// }
+//
+// // get the first neighbor of this interface
+// iface, err := GetInterfaceByName("if0")
+// if err != nil {
+// t.Error(err)
+// }
+// neighbors, err := GetNeighborsToInterface("if0")
+// if err != nil {
+// t.Error(err)
+// }
+//
+// // setup a neighbor listener socket
+// testNeighbor := neighbors[0]
+// // close the socket so we can listen on it
+// err = testNeighbor.SendSocket.Close()
+// if err != nil {
+// t.Error(err)
+// }
+//
+// fmt.Printf("Interfaces:\n%s\n", SprintInterfaces())
+// fmt.Printf("Neighbors:\n%s\n", SprintNeighbors())
+//
+// listenString := testNeighbor.UdpAddr.String()
+// fmt.Println("listening on " + listenString)
+// listenAddr, err := net.ResolveUDPAddr("udp4", listenString)
+// if err != nil {
+// t.Error(err)
+// }
+// recvSocket, err := net.ListenUDP("udp4", listenAddr)
+// if err != nil {
+// t.Error(err)
+// }
+// testNeighbor.SendSocket = *recvSocket
+//
+// sent := false
+// go func() {
+// buffer := make([]byte, MAX_IP_PACKET_SIZE)
+// fmt.Println("wating to read from UDP socket")
+// _, sourceAddr, err := recvSocket.ReadFromUDP(buffer)
+// if err != nil {
+// t.Error(err)
+// }
+// fmt.Println("read from UDP socket")
+// hdr, err := ipv4header.ParseHeader(buffer)
+// if err != nil {
+// t.Error(err)
+// }
+// headerSize := hdr.Len
+// headerBytes := buffer[:headerSize]
+// checksumFromHeader := uint16(hdr.Checksum)
+// computedChecksum := ValidateChecksum(headerBytes, checksumFromHeader)
+//
+// var checksumState string
+// if computedChecksum == checksumFromHeader {
+// checksumState = "OK"
+// } else {
+// checksumState = "FAIL"
+// }
+// message := buffer[headerSize:]
+// fmt.Printf("Received IP packet from %s\nHeader: %v\nChecksum: %s\nMessage: %s\n",
+// sourceAddr.String(), hdr, checksumState, string(message))
+// if err != nil {
+// t.Error(err)
+// }
+//
+// sent = true
+// }()
+//
+// time.Sleep(10 * time.Millisecond)
+//
+// // send a message to the neighbor
+// fmt.Printf("sending message to neighbor\t%t\n", sent)
+// err = SendIP(*iface, *testNeighbor, 0, []byte("You are my firest neighbor!"))
+// if err != nil {
+// t.Error(err)
+// }
+//
+// fmt.Printf("SENT message to neighbor\t%t\n", sent)
+// // give a little time for the message to be sent
+// time.Sleep(1000 * time.Millisecond)
+// if !sent {
+// t.Error("Message not sent")
+// t.Fail()
+// }
+//
+// fmt.Println("TestSendIPToNeighbor successful")
+// t.Cleanup(func() { CleanUp() })
+//}
+//
+//func TestRecvIP(t *testing.T) {
+// lnxFilePath := "../../doc-example/r2.lnx"
+// err := Initialize(lnxFilePath)
+// if err != nil {
+// t.Error(err)
+// }
+//
+// // get the first neighbor of this interface to RecvIP from
+// iface, err := GetInterfaceByName("if0")
+// if err != nil {
+// t.Error(err)
+// }
+// InterfaceUp(iface)
+//
+// // setup a random socket to send an ip packet from
+// listenAddr, err := net.ResolveUDPAddr("udp4", "127.0.0.1:6969")
+// sendSocket, err := net.ListenUDP("udp4", listenAddr)
+//
+// // send a message to the neighbor
+// ifaceAsNeighbor := Neighbor{
+// VipAddr: iface.IpPrefix.Addr(),
+// UdpAddr: iface.UdpAddr,
+// SendSocket: iface.RecvSocket,
+// SocketChannel: iface.SocketChannel,
+// }
+// fakeIface := Interface{
+// Name: "if69",
+// IpPrefix: netip.MustParsePrefix("10.69.0.1/24"),
+// UdpAddr: netip.MustParseAddrPort("127.0.0.1:6969"),
+// RecvSocket: net.UDPConn{},
+// SocketChannel: nil,
+// State: true,
+// }
+// err = SendIP(fakeIface, ifaceAsNeighbor, 0, []byte("hello"))
+// if err != nil {
+// return
+// }
+//
+// time.Sleep(10 * time.Millisecond)
+//
+// // TODO: potenially make this a channel, so it actually checks values.
+// // For now, you must read the message from the console.
+//
+// err = sendSocket.Close()
+// if err != nil {
+// t.Error(err)
+// }
+// t.Cleanup(func() { CleanUp() })
+//}
+
+func TestIntersect(t *testing.T) {
+ net1 := netip.MustParsePrefix("1.1.1.1/24")
+ net2 := netip.MustParsePrefix("1.1.1.2/24")
+ net3 := netip.MustParsePrefix("1.0.0.1/24")
+ net4 := netip.MustParsePrefix("0.0.0.0/0") // default route
+ net5 := netip.MustParsePrefix("1.1.1.1/32")
+
+ res00 := intersect(net1, net5)
+ if !res00 {
+ t.Error("net1 and net2 should intersect")
+ t.Fail()
}
- recvSocket, err := net.ListenUDP("udp4", listenAddr)
- if err != nil {
- t.Error(err)
+ res01 := intersect(net5, net1)
+ if res01 {
+ t.Error("net1 and net2 should not intersect")
+ t.Fail()
}
- testNeighbor.SendSocket = *recvSocket
-
- sent := false
- go func() {
- buffer := make([]byte, MAX_IP_PACKET_SIZE)
- fmt.Println("wating to read from UDP socket")
- _, sourceAddr, err := recvSocket.ReadFromUDP(buffer)
- if err != nil {
- t.Error(err)
- }
- fmt.Println("read from UDP socket")
- hdr, err := ipv4header.ParseHeader(buffer)
- if err != nil {
- t.Error(err)
- }
- headerSize := hdr.Len
- headerBytes := buffer[:headerSize]
- checksumFromHeader := uint16(hdr.Checksum)
- computedChecksum := ValidateChecksum(headerBytes, checksumFromHeader)
-
- var checksumState string
- if computedChecksum == checksumFromHeader {
- checksumState = "OK"
- } else {
- checksumState = "FAIL"
- }
- message := buffer[headerSize:]
- fmt.Printf("Received IP packet from %s\nHeader: %v\nChecksum: %s\nMessage: %s\n",
- sourceAddr.String(), hdr, checksumState, string(message))
- if err != nil {
- t.Error(err)
- }
-
- sent = true
- }()
- time.Sleep(10 * time.Millisecond)
-
- // send a message to the neighbor
- fmt.Printf("sending message to neighbor\t%t\n", sent)
- err = SendIP(*iface, *testNeighbor, 0, []byte("You are my firest neighbor!"))
- if err != nil {
- t.Error(err)
+ res1 := intersect(net1, net2)
+ if !res1 {
+ t.Error("net1 and net2 should intersect")
+ t.Fail()
}
-
- fmt.Printf("SENT message to neighbor\t%t\n", sent)
- // give a little time for the message to be sent
- time.Sleep(1000 * time.Millisecond)
- if !sent {
- t.Error("Message not sent")
+ res0 := intersect(net2, net1)
+ if !res0 {
+ t.Error("net1 and net2 should intersect")
t.Fail()
}
- fmt.Println("TestSendIPToNeighbor successful")
- t.Cleanup(func() { CleanUp() })
-}
-
-func TestRecvIP(t *testing.T) {
- lnxFilePath := "../../doc-example/r2.lnx"
- err := Initialize(lnxFilePath)
- if err != nil {
- t.Error(err)
+ res6 := intersect(net1, net3)
+ if res6 {
+ t.Error("net1 and net3 should not intersect")
+ t.Fail()
}
-
- // get the first neighbor of this interface to RecvIP from
- iface, err := GetInterfaceByName("if0")
- if err != nil {
- t.Error(err)
+ res2 := intersect(net2, net3)
+ if res2 {
+ t.Error("net2 and net3 should not intersect")
+ t.Fail()
}
- InterfaceUp(iface)
-
- // setup a random socket to send an ip packet from
- listenAddr, err := net.ResolveUDPAddr("udp4", "127.0.0.1:6969")
- sendSocket, err := net.ListenUDP("udp4", listenAddr)
-
- // send a message to the neighbor
- ifaceAsNeighbor := Neighbor{
- VipAddr: iface.IpPrefix.Addr(),
- UdpAddr: iface.UdpAddr,
- SendSocket: iface.RecvSocket,
- SocketChannel: iface.SocketChannel,
+ res3 := intersect(net1, net4)
+ if !res3 {
+ t.Error("net1 and net4 should intersect")
+ t.Fail()
}
- fakeIface := Interface{
- Name: "if69",
- IpPrefix: netip.MustParsePrefix("10.69.0.1/24"),
- UdpAddr: netip.MustParseAddrPort("127.0.0.1:6969"),
- RecvSocket: net.UDPConn{},
- SocketChannel: nil,
- State: true,
+ res4 := intersect(net2, net4)
+ if !res4 {
+ t.Error("net2 and net4 should intersect")
+ t.Fail()
}
- err = SendIP(fakeIface, ifaceAsNeighbor, 0, []byte("hello"))
- if err != nil {
- return
+ res5 := intersect(net3, net4)
+ if !res5 {
+ t.Error("net3 and net4 should intersect")
+ t.Fail()
}
- time.Sleep(10 * time.Millisecond)
-
- // TODO: potenially make this a channel, so it actually checks values.
- // For now, you must read the message from the console.
-
- err = sendSocket.Close()
- if err != nil {
- t.Error(err)
- }
- t.Cleanup(func() { CleanUp() })
+ fmt.Println("TestIntersect successful")
}
diff --git a/vhost b/vhost
index 4664392..5e7c87a 100755
--- a/vhost
+++ b/vhost
Binary files differ
diff --git a/vrouter b/vrouter
index d7d51b4..c8b6e86 100755
--- a/vrouter
+++ b/vrouter
Binary files differ