diff options
Diffstat (limited to 'cmd/vhost')
-rw-r--r-- | cmd/vhost/main.go | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/cmd/vhost/main.go b/cmd/vhost/main.go new file mode 100644 index 0000000..7c32df8 --- /dev/null +++ b/cmd/vhost/main.go @@ -0,0 +1,209 @@ +package main + +import ( + "bufio" + "fmt" + "iptcp/pkg/ipstack" + // "iptcp/pkg/tcpstack" + "net/netip" + "os" + "strings" + "strconv" +) + +func main() { + if len(os.Args) == 1 { + fmt.Printf("Usage: %s <configFile>\n", os.Args[0]) + os.Exit(1) + } + + fileName := os.Args[2] + + err := ipstack.Initialize(fileName) + if err != nil { + return + } + ipstack.RegisterProtocolHandler(ipstack.TEST_PROTOCOL) + ipstack.RegisterProtocolHandler(ipstack.TCP_PROTOCOL) + + // create a map of sockets + sockets := make(map[int]*ipstack.VTCPConn) + + scanner := bufio.NewScanner(os.Stdin) + + for scanner.Scan() { + line := scanner.Text() + tokens := strings.Split(line, " ") + switch tokens[0] { + case "li": + fmt.Println("Name\tAddr/Prefix\tState") + fmt.Println(ipstack.SprintInterfaces()) + case "ln": + fmt.Println("Iface\tVIP\tUDPAddr") + fmt.Println(ipstack.SprintNeighbors()) + case "lr": + fmt.Println("T\tPrefix\tNext Hop\tCost") + fmt.Println(ipstack.SprintRoutingTable()) + case "q": + ipstack.CleanUp() + os.Exit(0) + case "exit": + ipstack.CleanUp() + os.Exit(0) + case "down": + // get interface name + ifaceName := tokens[1] + ipstack.InterfaceDownREPL(ifaceName) + case "up": + // get interface name + ifaceName := tokens[1] + ipstack.InterfaceUpREPL(ifaceName) + case "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) + + address, _ := netip.ParseAddr(ipAddr) + hop, err := ipstack.Route(address) + if err != nil { + fmt.Println(err) + continue + } + myAddr := hop.Interface.IpPrefix.Addr() + for _, neighbor := range ipstack.GetNeighbors()[hop.Interface.Name] { + if neighbor.VipAddr == address || + neighbor.VipAddr == hop.VIP && hop.Type == "S" { + 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) + } + } + } +// ********************************************TCP REPL*************************************************************** + case "a": + // accept a connection + // get the port number + port := line[2:] + uint16Port, err := strconv.ParseUint(port, 10, 16) + if err != nil { + fmt.Println(err) + continue + } + // listen on the port + listener, err := ipstack.VListen(uint16(uint16Port)) + if err != nil { + fmt.Println(err) + continue + } + go func() { + for { + conn, err := listener.VAccept() + if err != nil { + fmt.Println(err) + } + sockets[conn.Socket] = conn + } + }() + case "c": + if len(tokens) != 3 { + fmt.Println("Invalid command: ", line) + continue + } + // connect to a port + vipAddr := tokens[1] + port := tokens[2] + uint16Port, err := strconv.ParseUint(port, 10, 16) + if err != nil { + fmt.Println(err) + continue + } + conn, err := ipstack.VConnect(vipAddr, uint16(uint16Port)) + if err != nil { + fmt.Println(err) + continue + } + sockets[conn.Socket] = conn + case "ls": + // list sockets + fmt.Println("SID\tLAddr\t\tLPort\tRAddr\t\tRPort\tRStatus") + fmt.Println(ipstack.SprintSockets()) + case "s": + if len(tokens) < 3 { + fmt.Println("Invalid command: ", line) + continue + } + socketID, err := strconv.Atoi(tokens[1]) + if err != nil { + fmt.Println(err) + continue + } + conn, _ := sockets[socketID] + message := tokens[2:] + messageToSend := strings.Join(message, " ") + messageToSendBytes := []byte(messageToSend) + bytesWritten, err := conn.VWrite(messageToSendBytes) + if err != nil { + fmt.Println(err) + continue + } + fmt.Printf("Sent %d bytes\n", bytesWritten) + case "r": + if len(tokens) != 3 { + fmt.Println("Invalid command: ", line) + continue + } + socketID, err := strconv.Atoi(tokens[1]) + if err != nil { + fmt.Println(err) + continue + } + numberOfBytes, err := strconv.Atoi(tokens[2]) + if err != nil { + fmt.Println(err) + continue + } + conn, _ := sockets[socketID] + // buffer := make([]byte, numberOfBytes) + bytesRead, message, err := conn.VRead(numberOfBytes) + if err != nil { + fmt.Println(err) + continue + } + fmt.Printf("Read %d bytes: %s\n", bytesRead, message) + case "cl": + // close a socket + if len(tokens) != 2 { + fmt.Println("Invalid command: ", line) + continue + } + socketID, err := strconv.Atoi(tokens[1]) + if err != nil { + fmt.Println(err) + continue + } + conn, _ := sockets[socketID] + err = conn.VClose() + if err != nil { + fmt.Println(err) + continue + } + default: + fmt.Println("Invalid command: ", line) + fmt.Println("Commands: ") + fmt.Println(" exit 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 + } + } +} |