package main import ( "bufio" "fmt" "iptcp/pkg/ipstack" "net/netip" "os" "strings" ) func main() { // checks that a config file is passed as an argument if len(os.Args) == 1 { fmt.Printf("Usage: %s \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) // create a scanner to read from stdin for command-line inputs scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { line := scanner.Text() switch line { // 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 } } }