aboutsummaryrefslogtreecommitdiff
path: root/cmd/vrouter/main.go
blob: f338b8016fb25d164bffb24c017042b442cf35ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package main

import (
	"bufio"
	"fmt"
	"iptcp/pkg/ipstack"
	// "iptcp/pkg/tcpstack"
	"net/netip"
	"os"
	"strings"
	// "strconv"
)

func main() {
	// checks that a config file is passed as an argument
	if len(os.Args) == 1 {
		fmt.Printf("Usage:  %s <configFile>\n", os.Args[0])
		os.Exit(1)
	}

	// get config file name from command line argument
	fileName := os.Args[2]

	// initialize the router with its config file
	err := ipstack.Initialize(fileName)
	if err != nil {
		// return if there is an error
		return
	}

	// register the test protocol
	ipstack.RegisterProtocolHandler(ipstack.TEST_PROTOCOL)
	// register the rip protocol for the router
	ipstack.RegisterProtocolHandler(ipstack.RIP_PROTOCOL)
	// register the TCP protocol for the handler
	ipstack.RegisterProtocolHandler(ipstack.TCP_PROTOCOL)


	// create a scanner to read from stdin for command-line inputs
	scanner := bufio.NewScanner(os.Stdin)

	for scanner.Scan() {
		line := scanner.Text()
		tokens := strings.Split(line, " ")
		switch tokens[0] {
		// print the interfaces
		case "li":
			fmt.Println("Name\tAddr/Prefix\tState")
			fmt.Println(ipstack.SprintInterfaces())
		// print the neighbors
		case "ln":
			fmt.Println("Iface\tVIP\t\tUDPAddr")
			fmt.Println(ipstack.SprintNeighbors())
		// print the routing table
		case "lr":
			fmt.Println("T\tPrefix\t\tNext Hop\tCost")
			fmt.Println(ipstack.SprintRoutingTable())
		// exit the program
		case "q":
			ipstack.CleanUp()
			os.Exit(0)
		case "exit":
			ipstack.CleanUp()
			os.Exit(0)
		default:
			if len(line) > 4 {
				// disable an interface
				if line[:4] == "down" {
					ifaceName := line[5:]
					ipstack.InterfaceDownREPL(ifaceName)
				}

				// attempts to send message to destination
				if line[:4] == "send" {
					// get IP address and message that follows it
					IPAndMessage := strings.Split(line, " ")
					ipAddr := IPAndMessage[1]
					message := IPAndMessage[2:]

					// combine message into one string
					messageToSend := strings.Join(message, " ")
					messageToSendBytes := []byte(messageToSend)

					// get the longest prefix match for the destination
					address, _ := netip.ParseAddr(ipAddr)
					hop, err := ipstack.Route(address)
					if err != nil {
						fmt.Println(err)
						continue
					}

					myAddr := hop.Interface.IpPrefix.Addr()
					// attempt to send the message to the destination
					for _, neighbor := range ipstack.GetNeighbors()[hop.Interface.Name] {
						if neighbor.VipAddr == address ||
							neighbor.VipAddr == hop.VIP {
							// send the message to the neighbor
							bytesWritten, err := ipstack.SendIP(&myAddr, neighbor, ipstack.TEST_PROTOCOL, messageToSendBytes, ipAddr, nil)
							fmt.Printf("Sent %d bytes to %s\n", bytesWritten, neighbor.VipAddr.String())
							if err != nil {
								fmt.Println(err)
							}
						}
					}
				}
			}
			if len(line) > 2 {
				// enable an interface
				if line[:2] == "up" {
					// get interface name
					ifaceName := line[3:]
					ipstack.InterfaceUpREPL(ifaceName)
				}
			} else {
				fmt.Println("Invalid command: ", line)
				fmt.Println("Commands: ")
				fmt.Println("  exit/q Terminate this program")
				fmt.Println("    li List interfaces")
				fmt.Println("    lr List routes")
				fmt.Println("    ln List available neighbors")
				fmt.Println("    up Enable an interface")
				fmt.Println("  down Disable an interface")
				fmt.Println("  send Send test packet")
			}
			continue
		}
	}
}