aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/example/main.go5
-rw-r--r--doc-example/binaries.example.json17
-rw-r--r--doc-example/nodes.json7
-rw-r--r--pkg/ipstack/ipstack.go193
-rw-r--r--pkg/ipstack/ipstack_test.go20
-rw-r--r--pkg/lnxconfig/lnxconfig.go11
-rw-r--r--pkg/routingtable/routingtable.go51
7 files changed, 199 insertions, 105 deletions
diff --git a/cmd/example/main.go b/cmd/example/main.go
index 5b6ae61..383e490 100644
--- a/cmd/example/main.go
+++ b/cmd/example/main.go
@@ -2,7 +2,7 @@ package main
import (
"fmt"
- "iptcp-jailpt2/pkg/lnxconfig"
+ "iptcp/pkg/lnxconfig"
"net/netip"
"os"
)
@@ -24,5 +24,8 @@ func main() {
for _, iface := range lnxConfig.Interfaces {
prefixForm := netip.PrefixFrom(iface.AssignedIP, iface.AssignedPrefix.Bits())
fmt.Printf("%s has IP %s\n", iface.Name, prefixForm.String())
+
+ fmt.Printf(iface.UDPAddr.String() + "\n")
+ fmt.Printf(iface.AssignedIP.String() + "\n")
}
}
diff --git a/doc-example/binaries.example.json b/doc-example/binaries.example.json
new file mode 100644
index 0000000..b6ff6d9
--- /dev/null
+++ b/doc-example/binaries.example.json
@@ -0,0 +1,17 @@
+{
+ "h1": {
+ "binary_path": "./vhost"
+ },
+ "h2": {
+ "binary_path": "./vhost"
+ },
+ "h3": {
+ "binary_path": "./vhost"
+ },
+ "r1": {
+ "binary_path": "./vrouter"
+ },
+ "r2": {
+ "binary_path": "./vrouter"
+ }
+} \ No newline at end of file
diff --git a/doc-example/nodes.json b/doc-example/nodes.json
new file mode 100644
index 0000000..7b91355
--- /dev/null
+++ b/doc-example/nodes.json
@@ -0,0 +1,7 @@
+{
+ "h1": "host",
+ "h2": "host",
+ "h3": "host",
+ "r1": "router",
+ "r2": "router"
+} \ No newline at end of file
diff --git a/pkg/ipstack/ipstack.go b/pkg/ipstack/ipstack.go
index 770fd17..abaa09f 100644
--- a/pkg/ipstack/ipstack.go
+++ b/pkg/ipstack/ipstack.go
@@ -2,102 +2,147 @@ package ipstack
import (
"fmt"
- ipv4header "github.com/brown-csci1680/iptcp-headers"
- "github.com/google/netstack/tcpip/header"
"github.com/pkg/errors"
- "../../pkg/lnxconfig"
- "log"
+ "iptcp/pkg/lnxconfig"
"net"
"net/netip"
- "os"
)
const (
- MAX_IP_PACKET_SIZE = 1400
+ MAX_IP_PACKET_SIZE = 1400
+ LOCAL_COST uint32 = 4294967295 // 2^32 - 1
+ STATIC_COST uint32 = 1
)
+// STRUCTS ---------------------------------------------------------------------
type Interface struct {
- Name string
- AssignedIP netip.Addr
- AssignedPrefix netip.Prefix
+ Name string
+ IpAddress netip.Addr
+ IpPrefix netip.Prefix
- UDPAddr netip.AddrPort
- State bool
- neighbors map[netip.AddrPort]netip.AddrPort
+ RecvSocket net.Conn
+ SocketChannel chan<- bool
+ State bool
}
-// type Host struct {
-// Interface Interface
-// Neighbors []Neighbor
-// }
-
-// type Router struct {
-// Interfaces []Interface
-// Neighbors []Neighbor
-// RIPNeighbors []Neighbor
-// }
+type Neighbor struct {
+ VipAddr netip.Addr
+ UdpAddr netip.AddrPort
-
-type Neighbor struct{
- DestAddr netip.Addr
- UDPAddr netip.AddrPort
-
- InterfaceName string
+ SendSocket net.Conn
+ SocketChannel chan<- bool
}
type RIPMessage struct {
- command uint8_t;
- numEntries uint8_t;
- entries []RIPEntry;
+ command uint8
+ numEntries uint8
+ entries []RIPEntry
}
type RIPEntry struct {
- addr netip.Addr;
- cost uint16_t;
- mask netip.Prefix;
+ addr netip.Addr
+ cost uint32
+ mask netip.Prefix
}
-myInterfaces := make([]Interface);
-myNeighbors := make(map[string]Neighbor)
-myRIPNeighbors := make(map[string]Neighbor)
-protocolHandlers := make(map[uint16]HandlerFunc)
-// routingTable := make(map[Address]Routing)
+type Hop struct {
+ Cost uint32
+ VipAsStr string
+}
-func Initialize(config IpConfig) (error) {
- if len(os.Args) != 2 {
- fmt.Printf("Usage: %s <configFile>\n", os.Args[0])
- os.Exit(1)
+// GLOBAL VARIABLES (data structures) ------------------------------------------
+var myInterfaces []Interface
+var myNeighbors = make(map[string]Neighbor)
+
+// var myRIPNeighbors = make(map[string]Neighbor)
+type HandlerFunc func(int, string, *[]byte) error
+
+var protocolHandlers = make(map[uint16]HandlerFunc)
+
+// var routingTable = routingtable.New()
+var routingTable = make(map[netip.Prefix]Hop)
+
+// 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.Conn) error {
+ listenString := UdpAddr.String()
+ listenAddr, err := net.ResolveUDPAddr("udp4", listenString)
+ if err != nil {
+ return errors.WithMessage(err, "Error resolving address->\t"+listenString)
}
- fileName := os.Args[1]
+ 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
+}
+
+func Initialize(lnxFilePath string) error {
+ //if len(os.Args) != 2 {
+ // fmt.Printf("Usage: %s <configFile>\n", os.Args[0])
+ // os.Exit(1)
+ //}
+ //lnxFilePath := os.Args[1]
// Parse the file
- lnxConfig, err := lnxconfig.ParseConfig(fileName)
+ lnxConfig, err := lnxconfig.ParseConfig(lnxFilePath)
if err != nil {
- panic(err)
+ return errors.WithMessage(err, "Error parsing config file->\t"+lnxFilePath)
}
- // populate routing table???
+ // 1) initialize the interfaces on this node here and into the routing table
for _, iface := range lnxConfig.Interfaces {
- myInterfaces = append(myInterfaces, Interface{iface.Name, iface.AssignedIP, iface.AssignedPrefix, iface.UDPAddr, 0})
+ i := &Interface{
+ Name: iface.Name,
+ IpAddress: iface.AssignedIP,
+ IpPrefix: iface.AssignedPrefix,
+ RecvSocket: nil,
+ SocketChannel: nil,
+ State: false,
+ }
+ err := createUDPConn(iface.UDPAddr, &i.RecvSocket)
+ if err != nil {
+ return errors.WithMessage(err, "Error creating UDP socket for interface->\t"+iface.Name)
+ }
+ myInterfaces = append(myInterfaces, *i)
+
+ // add to routing table
+ ifacePrefix := netip.PrefixFrom(iface.AssignedIP, iface.AssignedPrefix.Bits())
+ routingTable[ifacePrefix] = Hop{STATIC_COST, iface.Name}
}
+ // 2) initialize the neighbors connected to the node
for _, neighbor := range lnxConfig.Neighbors {
- myNeighbors[neighbor.DestAddr.String()] = Neighbor{neighbor.DestAddr, neighbor.UDPAddr, neighbor.InterfaceName}
- }
+ n := &Neighbor{
+ VipAddr: neighbor.DestAddr,
+ UdpAddr: neighbor.UDPAddr,
+ SendSocket: nil,
+ }
+ err := createUDPConn(neighbor.UDPAddr, &n.SendSocket)
+ if err != nil {
+ return errors.WithMessage(err, "Error creating UDP socket for neighbor->\t"+neighbor.DestAddr.String())
+ }
+ // TODO: make a hash map
+ myNeighbors[neighbor.InterfaceName] = *n
- // add RIP neighbors
- for _, neighbor := range lnxConfig.RipNeighbors {
- myRIPNeighbors[neighbor.DestAddr.String()] = Neighbor{neighbor.DestAddr, neighbor.UDPAddr, neighbor.InterfaceName}
+ // add to routing table
+ neighborPrefix := netip.PrefixFrom(neighbor.DestAddr, 24)
+ routingTable[neighborPrefix] = Hop{LOCAL_COST, neighbor.InterfaceName}
}
+
+ return nil
}
+/*
+
func ListerToInterfaces() {
for _, iface := range myInterfaces {
go RecvIp(iface)
}
}
-func RecvIp(iface Interface) (error) {
+func RecvIp(iface Interface) error {
for {
buffer := make([]byte, MAX_IP_PACKET_SIZE)
_, sourceAddr, err := iface.udp.ReadFrom(buffer)
@@ -125,7 +170,7 @@ func RecvIp(iface Interface) (error) {
checksumState = "FAIL"
continue
}
-
+
// check ttl
ttl := data[8]
if ttl == 0 {
@@ -133,7 +178,6 @@ func RecvIp(iface Interface) (error) {
continue
}
-
destAddr := netip.AddrFrom(data[16:20])
protocolNum := data[9]
@@ -174,7 +218,7 @@ func ValidateChecksum(b []byte, fromHeader uint16) uint16 {
return checksum
}
-func SendIp(dst netip.Addr, port uint16, protocolNum uint16, data []byte, iface Interface) (error) {
+func SendIp(dst netip.Addr, port uint16, protocolNum uint16, data []byte, iface Interface) error {
bindLocalAddr, err := net.ResolveUDPAddr("udp4", iface.UDPAddr.String())
if err != nil {
log.Panicln("Error resolving address: ", err)
@@ -248,15 +292,10 @@ func ComputeChecksum(b []byte) uint16 {
return checksumInv
}
-func ForwardIP(data []byte) (error) {
-}
-
-type HandlerFunc = func help(*Packet, []interface{}) (error) {
-
- // do smth with packet
+func ForwardIP(data []byte) error {
}
-func AddRecvHandler(protocolNum uint8, callbackFunc HandlerFunc) (error) {
+func AddRecvHandler(protocolNum uint8, callbackFunc HandlerFunc) error {
if protocolHandlers[protocolNum] != nil {
fmt.Printf("Warning: Handler for protocol %d already exists", protocolNum)
}
@@ -264,7 +303,7 @@ func AddRecvHandler(protocolNum uint8, callbackFunc HandlerFunc) (error) {
return nil
}
-func RemoveRecvHandler(protocolNum uint8) (error) {
+func RemoveRecvHandler(protocolNum uint8) error {
// consider error
if protocolHandlers[protocolNum] == nil {
return errors.Errorf("No handler for protocol %d", protocolNum)
@@ -281,18 +320,28 @@ func RemoveRecvHandler(protocolNum uint8) (error) {
// newRIPMessage.entries = make([]RIPEntry, newRIPMessage.numEntries)
// }
-func PrintNeighbors() {
- for _, iface := range myNeighbors {
- fmt.Printf("%s\n", iface.addr.String())
- }
+func GetNeighbors() []netip.Addr {
+ return myNeighbors
}
+*/
func PrintInterfaces() {
for _, iface := range myInterfaces {
- fmt.Printf("%s\n", iface.addr.String())
+ fmt.Printf("%s\t%s\t%t\n", iface.Name, iface.IpPrefix.String(), iface.State)
}
}
-func GetNeighbors() ([]netip.Addr) {
- return myNeighbors
+
+func PrintNeighbors() {
+ for ifaceName, neighbor := range myNeighbors {
+ fmt.Printf("%s\t%s\t%s\n", ifaceName, neighbor.IpAddress.String(), neighbor.UdpAddr.String())
+ }
}
+func SprintRoutingTable() string {
+ message := ""
+ for prefix, hop := range routingTable {
+ message += fmt.Sprintf("%s\t%s\t%d\n", prefix.String(), hop.VipAsStr, hop.Cost)
+ }
+
+ return message
+}
diff --git a/pkg/ipstack/ipstack_test.go b/pkg/ipstack/ipstack_test.go
new file mode 100644
index 0000000..5530b9d
--- /dev/null
+++ b/pkg/ipstack/ipstack_test.go
@@ -0,0 +1,20 @@
+package ipstack
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestInitialize(t *testing.T) {
+ lnxFilePath := "../../doc-example/r2.lnx"
+ err := Initialize(lnxFilePath)
+ if err != nil {
+ t.Error(err)
+ }
+ fmt.Println("TestInitialize successful")
+ PrintInterfaces()
+ fmt.Println("Interfaces^^")
+ PrintNeighbors()
+ fmt.Println("Neighbors^^")
+ fmt.Println(SprintRoutingTable())
+}
diff --git a/pkg/lnxconfig/lnxconfig.go b/pkg/lnxconfig/lnxconfig.go
index d0699f9..8e43613 100644
--- a/pkg/lnxconfig/lnxconfig.go
+++ b/pkg/lnxconfig/lnxconfig.go
@@ -17,17 +17,6 @@ const (
RoutingTypeRIP RoutingMode = 2
)
-/*
- * NOTE: These data structures only represent structure of a
- * configuration file. In your implementation, you will still need to
- * build your own data structures that store relevant information
- * about your links, interfaces, etc. at runtime.
- *
- * These structs only represent the things in the config file--you
- * will probably only parse these at startup in order to set up your own
- * data structures.
- *
- */
type IPConfig struct {
Interfaces []InterfaceConfig
Neighbors []NeighborConfig
diff --git a/pkg/routingtable/routingtable.go b/pkg/routingtable/routingtable.go
index 7f7e2b2..90b64ae 100644
--- a/pkg/routingtable/routingtable.go
+++ b/pkg/routingtable/routingtable.go
@@ -7,17 +7,26 @@ import (
)
type Address struct {
- addr netip.Addr
- prefix netip.Prefix
+ Addr netip.Addr
+ Prefix netip.Prefix
}
-type Route struct {
- dest Address
- cost uint32
- mask netip.Prefix
+type Hop struct {
+ Cost uint32
+ VipAsStr string
}
-var table map[Address]Route
+type RoutingTable map[Address]Hop
+
+const (
+ STATIC_COST uint32 = 4294967295 // 2^32 - 1
+)
+
+// TODO: consider making this take in arguments, such as a config file
+func New() *RoutingTable {
+ var table = make(RoutingTable)
+ return &table
+}
//func Initialize(config lnxconfig.IPConfig) error {
// if len(os.Args) != 2 {
@@ -42,39 +51,39 @@ var table map[Address]Route
//
//}
-func AddRoute(dest Address, cost uint32, mask netip.Prefix) error {
- if _, ok := table[dest]; ok {
+func AddRoute(srcAddr Address, cost uint32, addrAsStr string, tableReference *RoutingTable) error {
+ if _, ok := (*tableReference)[srcAddr]; ok {
return errors.New("Route already exists")
}
- table[dest] = Route{dest, cost, mask}
+ (*tableReference)[srcAddr] = Hop{cost, addrAsStr}
return nil
}
-func RemoveRoute(dest Address) error {
- if _, ok := table[dest]; !ok {
+func RemoveRoute(dest Address, table *RoutingTable) error {
+ if _, ok := (*table)[dest]; !ok {
return errors.New("Route doesn't exist")
}
- delete(table, dest)
+ delete(*table, dest)
return nil
}
// TODO: implement this with most specific prefix matching
-func GetRoute(dest Address) (Route, error) {
+func Route(dest Address, table *RoutingTable) (Hop, error) {
// get the most specific route
- for key, value := range table {
- if key.prefix.Contains(dest.addr) {
- return value, nil
+ for address, route := range *table {
+ if address.Prefix.Contains(dest.Addr) {
+ return route, nil
}
}
- return Route{}, errors.New("Route doesn't exist")
+ return Hop{}, errors.New("Route doesn't exist")
}
-func SprintRoutingTable() string {
+func SprintRoutingTable(table *RoutingTable) string {
message := ""
- for address, route := range table {
- message += fmt.Sprintf("%s/%d\t%d\n", address.addr, address.prefix, route.cost)
+ for address, route := range *table {
+ message += fmt.Sprintf("%s/%d\t%d\n", address.Addr, address.Prefix, route.Cost)
}
return message