From 148e4909212a22fd9631219d1e80946cc7d4ab2d Mon Sep 17 00:00:00 2001 From: Will George Date: Tue, 25 Aug 2020 10:58:38 -0400 Subject: [PATCH 1/6] Add "specialCommands", "hostname" command, and simple state tracking This ensures that a "show running-config" or "show version" command will correctly display the configured hostname. This approach is NOT scalable, and is probably a dead-end. That said it meets the need for today for simple workflow testing in Netpalm. --- cis.go | 49 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/cis.go b/cis.go index 108bb5b..872168c 100644 --- a/cis.go +++ b/cis.go @@ -1,8 +1,10 @@ package main import ( + "fmt" "log" "strconv" + "strings" "github.com/gliderlabs/ssh" "golang.org/x/crypto/ssh/terminal" @@ -11,7 +13,8 @@ import ( // ssh listernet func sshListener(portNumber int, done chan bool) { - supportedCommands := make(map[string]string) + basicCommands := make(map[string]string) + specialCommands := make(map[string]string) contextSearch := make(map[string]string) contextHierarchy := make(map[string]string) @@ -21,7 +24,7 @@ func sshListener(portNumber int, done chan bool) { contextSearch["enable"] = "#" contextSearch["en"] = "#" contextSearch["base"] = ">" - + contextHierarchy["(config)#"] = "#" contextHierarchy["#"] = ">" contextHierarchy[">"] = "exit" @@ -29,7 +32,7 @@ func sshListener(portNumber int, done chan bool) { hostname := "cisgo1000v" password := "admin" - supportedCommands["show version"] = `Cisco IOS XE Software, Version 16.04.01 + specialCommands["show version"] = `Cisco IOS XE Software, Version 16.04.01 Cisco IOS Software [Everest], CSR1000V Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.4.1, RELEASE SOFTWARE (fc2) Technical Support: http://www.cisco.com/techsupport Copyright (c) 1986-2016 by Cisco Systems, Inc. @@ -44,7 +47,7 @@ documentation or "License Notice" file accompanying the IOS-XE software, or the applicable URL provided on the flyer accompanying the IOS-XE software. ROM: IOS-XE ROMMON -csr1000v uptime is 4 hours, 55 minutes +%[1]v uptime is 4 hours, 55 minutes Uptime for this control processor is 4 hours, 56 minutes System returned to ROM by reload System image file is "bootflash:packages.conf" @@ -73,7 +76,7 @@ Processor board ID 9FKLJWM5EB0 0K bytes of at webui:. Configuration register is 0x2102` - supportedCommands["show ip interface brief"] = `Interface IP-Address OK? Method Status Protocol + basicCommands["show ip interface brief"] = `Interface IP-Address OK? Method Status Protocol FastEthernet0/0 10.0.2.27 YES NVRAM up up Serial0/0 unassigned YES NVRAM administratively down down FastEthernet0/1 unassigned YES NVRAM administratively down down @@ -98,7 +101,7 @@ FastEthernet3/14 unassigned YES unset up down FastEthernet3/15 unassigned YES unset up down Vlan1 unassigned YES NVRAM up down` - supportedCommands["show running-config"] = `Building configuration... + specialCommands["show running-config"] = `Building configuration... Current configuration : 2114 bytes ! @@ -107,7 +110,7 @@ service timestamps debug datetime msec service timestamps log datetime msec no service password-encryption ! -hostname herpa derpa +hostname %[1]s ! boot-start-marker boot-end-marker @@ -265,8 +268,10 @@ line vty 5 15 transport input ssh ! ! -end` - +end +` + basicCommands["terminal length 0"] = " " + basicCommands["terminal width 511"] = " " ssh.Handle(func(s ssh.Session) { // io.WriteString(s, fmt.Sprintf(SHOW_VERSION_PAGING_DISABLED)) @@ -277,31 +282,51 @@ end` if err != nil { break } + response := line log.Println(line) - if supportedCommands[response] != "" { + if basicCommands[response] != "" { // lookup supported commands for response - term.Write(append([]byte(supportedCommands[response]), '\n')) + term.Write(append([]byte(basicCommands[response]), '\n')) + } else if response == "" { // return if nothing is entered term.Write(append([]byte(response))) + } else if contextSearch[response] != "" { // switch contexts as needed term.SetPrompt(string(hostname + contextSearch[response])) contextState = contextSearch[response] - } else if response == "exit" { + + } else if response == "exit" || response == "end" { // drop down configs if required if contextHierarchy[contextState] == "exit" { break + } else { term.SetPrompt(string(hostname + contextHierarchy[contextState])) contextState = contextHierarchy[contextState] } + + } else if specialCommands[response] != "" { + term.Write(append([]byte(fmt.Sprintf(specialCommands[response], hostname)))) + + } else if contextState != ">" { // we're in config mode + fields := strings.Fields(response) + command := fields[0] + if command == "hostname" { + hostname = strings.Join(fields[1:], " ") + log.Printf("Setting hostname to %s\n", hostname) + term.SetPrompt(hostname + contextState) + } + } else { term.Write(append([]byte("% Ambiguous command: \""+response+"\""), '\n')) } + } log.Println("terminal closed") + }) portString := ":" + strconv.Itoa(portNumber) From e07149a6ff1c00866af5b938d91db335401f5546 Mon Sep 17 00:00:00 2001 From: Will George Date: Tue, 25 Aug 2020 11:01:54 -0400 Subject: [PATCH 2/6] Adds a simple example Dockerfile. Very likely this is not best-practice compliant. But it functions well enough for today --- Dockerfile | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..5021a0c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,6 @@ +FROM golang:1.15.0-buster +ADD . /app +WORKDIR /app +ENV GO111MODULE=on +RUN go mod download +CMD go run cis.go \ No newline at end of file From f7a323d605c509a5b5f942a2fca31696ba478608 Mon Sep 17 00:00:00 2001 From: Will George Date: Tue, 25 Aug 2020 18:03:05 -0400 Subject: [PATCH 3/6] Add "reset state" command to quickly revert state. --- cis.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/cis.go b/cis.go index 872168c..142d631 100644 --- a/cis.go +++ b/cis.go @@ -29,7 +29,9 @@ func sshListener(portNumber int, done chan bool) { contextHierarchy["#"] = ">" contextHierarchy[">"] = "exit" - hostname := "cisgo1000v" + defaultHostname := "cisgo1000v" + defaultContextState := ">" + hostname := defaultHostname password := "admin" specialCommands["show version"] = `Cisco IOS XE Software, Version 16.04.01 @@ -74,7 +76,8 @@ Processor board ID 9FKLJWM5EB0 3985132K bytes of physical memory. 7774207K bytes of virtual hard disk at bootflash:. 0K bytes of at webui:. -Configuration register is 0x2102` +Configuration register is 0x2102 +` basicCommands["show ip interface brief"] = `Interface IP-Address OK? Method Status Protocol FastEthernet0/0 10.0.2.27 YES NVRAM up up @@ -276,7 +279,7 @@ end // io.WriteString(s, fmt.Sprintf(SHOW_VERSION_PAGING_DISABLED)) term := terminal.NewTerminal(s, hostname+contextSearch["base"]) - contextState := ">" + contextState := defaultContextState for { line, err := term.ReadLine() if err != nil { @@ -285,7 +288,13 @@ end response := line log.Println(line) - if basicCommands[response] != "" { + if response == "reset state" { + log.Println("resetting internal state") + contextState = defaultContextState + hostname = defaultHostname + term.SetPrompt(hostname + contextState) + + } else if basicCommands[response] != "" { // lookup supported commands for response term.Write(append([]byte(basicCommands[response]), '\n')) @@ -318,6 +327,9 @@ end hostname = strings.Join(fields[1:], " ") log.Printf("Setting hostname to %s\n", hostname) term.SetPrompt(hostname + contextState) + + } else { + term.Write(append([]byte("% Ambiguous command: \""+response+"\""), '\n')) } } else { From ddafd0e59a901e3bdc668f275f856699cd9f6ae0 Mon Sep 17 00:00:00 2001 From: William George Date: Fri, 28 Aug 2020 06:50:07 -0400 Subject: [PATCH 4/6] Revert "Add "reset state" command to quickly revert state." This reverts commit 700bcf53c34cfc3a3ac74482888af2d78141885f. --- cis.go | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/cis.go b/cis.go index 142d631..872168c 100644 --- a/cis.go +++ b/cis.go @@ -29,9 +29,7 @@ func sshListener(portNumber int, done chan bool) { contextHierarchy["#"] = ">" contextHierarchy[">"] = "exit" - defaultHostname := "cisgo1000v" - defaultContextState := ">" - hostname := defaultHostname + hostname := "cisgo1000v" password := "admin" specialCommands["show version"] = `Cisco IOS XE Software, Version 16.04.01 @@ -76,8 +74,7 @@ Processor board ID 9FKLJWM5EB0 3985132K bytes of physical memory. 7774207K bytes of virtual hard disk at bootflash:. 0K bytes of at webui:. -Configuration register is 0x2102 -` +Configuration register is 0x2102` basicCommands["show ip interface brief"] = `Interface IP-Address OK? Method Status Protocol FastEthernet0/0 10.0.2.27 YES NVRAM up up @@ -279,7 +276,7 @@ end // io.WriteString(s, fmt.Sprintf(SHOW_VERSION_PAGING_DISABLED)) term := terminal.NewTerminal(s, hostname+contextSearch["base"]) - contextState := defaultContextState + contextState := ">" for { line, err := term.ReadLine() if err != nil { @@ -288,13 +285,7 @@ end response := line log.Println(line) - if response == "reset state" { - log.Println("resetting internal state") - contextState = defaultContextState - hostname = defaultHostname - term.SetPrompt(hostname + contextState) - - } else if basicCommands[response] != "" { + if basicCommands[response] != "" { // lookup supported commands for response term.Write(append([]byte(basicCommands[response]), '\n')) @@ -327,9 +318,6 @@ end hostname = strings.Join(fields[1:], " ") log.Printf("Setting hostname to %s\n", hostname) term.SetPrompt(hostname + contextState) - - } else { - term.Write(append([]byte("% Ambiguous command: \""+response+"\""), '\n')) } } else { From 6c9709d6644ba555e0d84cef10c657a6e9f34c23 Mon Sep 17 00:00:00 2001 From: Will George Date: Tue, 25 Aug 2020 18:03:05 -0400 Subject: [PATCH 5/6] Add "reset state" command to quickly revert state. --- cis.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/cis.go b/cis.go index 872168c..142d631 100644 --- a/cis.go +++ b/cis.go @@ -29,7 +29,9 @@ func sshListener(portNumber int, done chan bool) { contextHierarchy["#"] = ">" contextHierarchy[">"] = "exit" - hostname := "cisgo1000v" + defaultHostname := "cisgo1000v" + defaultContextState := ">" + hostname := defaultHostname password := "admin" specialCommands["show version"] = `Cisco IOS XE Software, Version 16.04.01 @@ -74,7 +76,8 @@ Processor board ID 9FKLJWM5EB0 3985132K bytes of physical memory. 7774207K bytes of virtual hard disk at bootflash:. 0K bytes of at webui:. -Configuration register is 0x2102` +Configuration register is 0x2102 +` basicCommands["show ip interface brief"] = `Interface IP-Address OK? Method Status Protocol FastEthernet0/0 10.0.2.27 YES NVRAM up up @@ -276,7 +279,7 @@ end // io.WriteString(s, fmt.Sprintf(SHOW_VERSION_PAGING_DISABLED)) term := terminal.NewTerminal(s, hostname+contextSearch["base"]) - contextState := ">" + contextState := defaultContextState for { line, err := term.ReadLine() if err != nil { @@ -285,7 +288,13 @@ end response := line log.Println(line) - if basicCommands[response] != "" { + if response == "reset state" { + log.Println("resetting internal state") + contextState = defaultContextState + hostname = defaultHostname + term.SetPrompt(hostname + contextState) + + } else if basicCommands[response] != "" { // lookup supported commands for response term.Write(append([]byte(basicCommands[response]), '\n')) @@ -318,6 +327,9 @@ end hostname = strings.Join(fields[1:], " ") log.Printf("Setting hostname to %s\n", hostname) term.SetPrompt(hostname + contextState) + + } else { + term.Write(append([]byte("% Ambiguous command: \""+response+"\""), '\n')) } } else { From b0b4f4a8090d4f41f3bee3f61f5d543d33314969 Mon Sep 17 00:00:00 2001 From: will george Date: Mon, 31 Aug 2020 02:48:16 -0400 Subject: [PATCH 6/6] refactor simple status, big commands to separate files --- .gitignore | 2 + cis.go | 389 +++++------------- config/show_ip_int_bri.txt | 24 ++ config/show_running-config.txt | 168 ++++++++ config/show_version.txt | 43 ++ .../x/crypto/ssh/terminal/terminal.go | 2 +- 6 files changed, 341 insertions(+), 287 deletions(-) create mode 100644 .gitignore create mode 100644 config/show_ip_int_bri.txt create mode 100644 config/show_running-config.txt create mode 100644 config/show_version.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b8a713d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode +*.exe \ No newline at end of file diff --git a/cis.go b/cis.go index 142d631..bb34b14 100644 --- a/cis.go +++ b/cis.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "io/ioutil" "log" "strconv" "strings" @@ -10,330 +11,146 @@ import ( "golang.org/x/crypto/ssh/terminal" ) -// ssh listernet +const ( + defaultHostname = "cisgo1000v" + defaultContextState = ">" + password = "admin" +) + +func readFile(filename string) string { + content, err := ioutil.ReadFile(filename) + if err != nil { + log.Fatal(err) + } + return string(content) +} + +type commandGroup struct { + basic map[string]string + hostname map[string]string + mode map[string]string +} + +func newCommandGroup() *commandGroup { + cmds := new(commandGroup) + cmds.basic = make(map[string]string) + cmds.basic["terminal length 0"] = " " + cmds.basic["terminal width 511"] = " " + cmds.basic["show ip interface brief"] = readFile("config/show_ip_int_bri.txt") + + cmds.hostname = make(map[string]string) + cmds.hostname["show version"] = readFile("config/show_version.txt") + cmds.hostname["show running-config"] = readFile("config/show_running-config.txt") + + cmds.mode = make(map[string]string) + cmds.mode["conf t"] = "(config)#" + cmds.mode["configure terminal"] = "(config)#" + cmds.mode["configure t"] = "(config)#" + cmds.mode["enable"] = "#" + cmds.mode["en"] = "#" + cmds.mode["base"] = ">" + return cmds +} + +type internalState struct { + hostname string + currentMode string // >, #, or (config)# + prompt string +} + +func (s *internalState) setMode(mode string) { + s.currentMode = mode + s.prompt = s.hostname + s.currentMode +} + +func (s *internalState) setHostname(hostname string) { + s.hostname = hostname + s.prompt = s.hostname + s.currentMode +} + +func (s *internalState) exit() bool { + switch s.currentMode { + case ">": + return false + case "#": + s.setMode(">") + case "(config)#": + s.setMode("#") + } + return true +} + +func newState() *internalState { + // log.Println("created new internalState") + return &internalState{defaultHostname, defaultContextState, defaultHostname + defaultContextState} +} + +// ssh listener func sshListener(portNumber int, done chan bool) { - basicCommands := make(map[string]string) - specialCommands := make(map[string]string) - contextSearch := make(map[string]string) - contextHierarchy := make(map[string]string) + commandGroup := newCommandGroup() - contextSearch["conf t"] = "(config)#" - contextSearch["configure terminal"] = "(config)#" - contextSearch["configure t"] = "(config)#" - contextSearch["enable"] = "#" - contextSearch["en"] = "#" - contextSearch["base"] = ">" + contextHierarchy := make(map[string]string) contextHierarchy["(config)#"] = "#" contextHierarchy["#"] = ">" contextHierarchy[">"] = "exit" - defaultHostname := "cisgo1000v" - defaultContextState := ">" - hostname := defaultHostname - password := "admin" - - specialCommands["show version"] = `Cisco IOS XE Software, Version 16.04.01 -Cisco IOS Software [Everest], CSR1000V Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.4.1, RELEASE SOFTWARE (fc2) -Technical Support: http://www.cisco.com/techsupport -Copyright (c) 1986-2016 by Cisco Systems, Inc. -Compiled Sun 27-Nov-16 13:02 by mcpre -Cisco IOS-XE software, Copyright (c) 2005-2016 by cisco Systems, Inc. -All rights reserved. Certain components of Cisco IOS-XE software are -licensed under the GNU General Public License ("GPL") Version 2.0. The -software code licensed under GPL Version 2.0 is free software that comes -with ABSOLUTELY NO WARRANTY. You can redistribute and/or modify such -GPL code under the terms of GPL Version 2.0. For more details, see the -documentation or "License Notice" file accompanying the IOS-XE software, -or the applicable URL provided on the flyer accompanying the IOS-XE -software. -ROM: IOS-XE ROMMON -%[1]v uptime is 4 hours, 55 minutes -Uptime for this control processor is 4 hours, 56 minutes -System returned to ROM by reload -System image file is "bootflash:packages.conf" -Last reload reason: reload -This product contains cryptographic features and is subject to United -States and local country laws governing import, export, transfer and -use. Delivery of Cisco cryptographic products does not imply -third-party authority to import, export, distribute or use encryption. -Importers, exporters, distributors and users are responsible for -compliance with U.S. and local country laws. By using this product you -agree to comply with applicable laws and regulations. If you are unable -to comply with U.S. and local laws, return this product immediately. -A summary of U.S. laws governing Cisco cryptographic products may be found at: -http://www.cisco.com/wwl/export/crypto/tool/stqrg.html -If you require further assistance please contact us by sending email to -export@cisco.com. -License Level: ax -License Type: Default. No valid license found. -Next reload license Level: ax -cisco CSR1000V (VXE) processor (revision VXE) with 2052375K/3075K bytes of memory. -Processor board ID 9FKLJWM5EB0 -10 Gigabit Ethernet interfaces -32768K bytes of non-volatile configuration memory. -3985132K bytes of physical memory. -7774207K bytes of virtual hard disk at bootflash:. -0K bytes of at webui:. -Configuration register is 0x2102 -` - - basicCommands["show ip interface brief"] = `Interface IP-Address OK? Method Status Protocol -FastEthernet0/0 10.0.2.27 YES NVRAM up up -Serial0/0 unassigned YES NVRAM administratively down down -FastEthernet0/1 unassigned YES NVRAM administratively down down -Serial0/1 unassigned YES NVRAM administratively down down -FastEthernet1/0 unassigned YES NVRAM administratively down down -FastEthernet2/0 unassigned YES NVRAM administratively down down -FastEthernet3/0 unassigned YES unset up down -FastEthernet3/1 unassigned YES unset up down -FastEthernet3/2 unassigned YES unset up down -FastEthernet3/3 unassigned YES unset up down -FastEthernet3/4 unassigned YES unset up down -FastEthernet3/5 unassigned YES unset up down -FastEthernet3/6 unassigned YES unset up down -FastEthernet3/7 unassigned YES unset up down -FastEthernet3/8 unassigned YES unset up down -FastEthernet3/9 unassigned YES unset up down -FastEthernet3/10 unassigned YES unset up down -FastEthernet3/11 unassigned YES unset up down -FastEthernet3/12 unassigned YES unset up down -FastEthernet3/13 unassigned YES unset up down -FastEthernet3/14 unassigned YES unset up down -FastEthernet3/15 unassigned YES unset up down -Vlan1 unassigned YES NVRAM up down` - - specialCommands["show running-config"] = `Building configuration... - -Current configuration : 2114 bytes -! -version 12.4 -service timestamps debug datetime msec -service timestamps log datetime msec -no service password-encryption -! -hostname %[1]s -! -boot-start-marker -boot-end-marker -! -! -no aaa new-model -memory-size iomem 5 -no ip icmp rate-limit unreachable -ip cef -! -! -! -! -no ip domain lookup -ip domain name test -ip auth-proxy max-nodata-conns 3 -ip admission max-nodata-conns 3 -! -! -! -! -! -! -! -! -! -! -! -! -! -! -! -username admin privilege 15 secret 5 $1$M1ce$SKeVGg2lUCPrsLkJMIdWf. -! -! -ip tcp synwait-time 5 -ip ssh version 2 -ip scp server enable -! -! -! -! -! -interface FastEthernet0/0 - description netpalm - ip address 10.0.2.27 255.255.255.0 - duplex auto - speed auto -! -interface Serial0/0 - no ip address - shutdown - clock rate 2000000 -! -interface FastEthernet0/1 - no ip address - shutdown - duplex auto - speed auto -! -interface Serial0/1 - no ip address - shutdown - clock rate 2000000 -! -interface FastEthernet1/0 - no ip address - shutdown - duplex auto - speed auto -! -interface FastEthernet2/0 - no ip address - shutdown - duplex auto - speed auto -! -interface FastEthernet3/0 -! -interface FastEthernet3/1 -! -interface FastEthernet3/2 -! -interface FastEthernet3/3 -! -interface FastEthernet3/4 -! -interface FastEthernet3/5 -! -interface FastEthernet3/6 -! -interface FastEthernet3/7 -! -interface FastEthernet3/8 -! -interface FastEthernet3/9 -! -interface FastEthernet3/10 -! -interface FastEthernet3/11 -! -interface FastEthernet3/12 -! -interface FastEthernet3/13 -! -interface FastEthernet3/14 -! -interface FastEthernet3/15 -! -interface Vlan1 - no ip address -! -ip forward-protocol nd -! -! -no ip http server -no ip http secure-server -! -ip access-list standard bob -ip access-list standard yip -! -snmp-server community test RO -snmp-server community location RO yip -snmp-server community contact RO bob -no cdp log mismatch duplex -! -! -! -control-plane -! -! -! -! -! -! -! -! -! -! -line con 0 - exec-timeout 0 0 - privilege level 15 - logging synchronous -line aux 0 - exec-timeout 0 0 - privilege level 15 - logging synchronous -line vty 0 4 - privilege level 15 - login local - transport input ssh -line vty 5 15 - privilege level 15 - login local - transport input ssh -! -! -end -` - basicCommands["terminal length 0"] = " " - basicCommands["terminal width 511"] = " " + thisState := newState() + ssh.Handle(func(s ssh.Session) { - // io.WriteString(s, fmt.Sprintf(SHOW_VERSION_PAGING_DISABLED)) - term := terminal.NewTerminal(s, hostname+contextSearch["base"]) - contextState := defaultContextState + term := terminal.NewTerminal(s, thisState.prompt) for { - line, err := term.ReadLine() + response, err := term.ReadLine() if err != nil { break } - response := line - log.Println(line) + log.Println(response) if response == "reset state" { log.Println("resetting internal state") - contextState = defaultContextState - hostname = defaultHostname - term.SetPrompt(hostname + contextState) - - } else if basicCommands[response] != "" { - // lookup supported commands for response - term.Write(append([]byte(basicCommands[response]), '\n')) + thisState = newState() + term.SetPrompt(thisState.prompt) } else if response == "" { // return if nothing is entered term.Write(append([]byte(response))) - } else if contextSearch[response] != "" { + } else if commandGroup.basic[response] != "" { + // lookup supported commands for response + term.Write(append([]byte(commandGroup.basic[response]), '\n')) + + } else if commandGroup.mode[response] != "" { // switch contexts as needed - term.SetPrompt(string(hostname + contextSearch[response])) - contextState = contextSearch[response] + thisState.setMode(commandGroup.mode[response]) + term.SetPrompt(thisState.prompt) } else if response == "exit" || response == "end" { // drop down configs if required - if contextHierarchy[contextState] == "exit" { - break - + if thisState.exit() { // "true" means we're still active, "false" means we're done + term.SetPrompt(thisState.prompt) } else { - term.SetPrompt(string(hostname + contextHierarchy[contextState])) - contextState = contextHierarchy[contextState] + break } - } else if specialCommands[response] != "" { - term.Write(append([]byte(fmt.Sprintf(specialCommands[response], hostname)))) + } else if commandGroup.hostname[response] != "" { + term.Write([]byte(fmt.Sprintf(commandGroup.hostname[response], thisState.hostname))) - } else if contextState != ">" { // we're in config mode + } else if thisState.currentMode != ">" { // we're in config mode fields := strings.Fields(response) command := fields[0] if command == "hostname" { - hostname = strings.Join(fields[1:], " ") - log.Printf("Setting hostname to %s\n", hostname) - term.SetPrompt(hostname + contextState) + thisState.setHostname(strings.Join(fields[1:], " ")) + log.Printf("Setting hostname to %s\n", thisState.hostname) + term.SetPrompt(thisState.prompt) } else { - term.Write(append([]byte("% Ambiguous command: \""+response+"\""), '\n')) + term.Write([]byte("% Ambiguous command: \"" + response + "\"\n")) } } else { - term.Write(append([]byte("% Ambiguous command: \""+response+"\""), '\n')) + term.Write([]byte("% Ambiguous command: \"" + response + "\"\n")) } } diff --git a/config/show_ip_int_bri.txt b/config/show_ip_int_bri.txt new file mode 100644 index 0000000..7bd3cac --- /dev/null +++ b/config/show_ip_int_bri.txt @@ -0,0 +1,24 @@ +Interface IP-Address OK? Method Status Protocol +FastEthernet0/0 10.0.2.27 YES NVRAM up up +Serial0/0 unassigned YES NVRAM administratively down down +FastEthernet0/1 unassigned YES NVRAM administratively down down +Serial0/1 unassigned YES NVRAM administratively down down +FastEthernet1/0 unassigned YES NVRAM administratively down down +FastEthernet2/0 unassigned YES NVRAM administratively down down +FastEthernet3/0 unassigned YES unset up down +FastEthernet3/1 unassigned YES unset up down +FastEthernet3/2 unassigned YES unset up down +FastEthernet3/3 unassigned YES unset up down +FastEthernet3/4 unassigned YES unset up down +FastEthernet3/5 unassigned YES unset up down +FastEthernet3/6 unassigned YES unset up down +FastEthernet3/7 unassigned YES unset up down +FastEthernet3/8 unassigned YES unset up down +FastEthernet3/9 unassigned YES unset up down +FastEthernet3/10 unassigned YES unset up down +FastEthernet3/11 unassigned YES unset up down +FastEthernet3/12 unassigned YES unset up down +FastEthernet3/13 unassigned YES unset up down +FastEthernet3/14 unassigned YES unset up down +FastEthernet3/15 unassigned YES unset up down +Vlan1 unassigned YES NVRAM up down diff --git a/config/show_running-config.txt b/config/show_running-config.txt new file mode 100644 index 0000000..2b0b1bf --- /dev/null +++ b/config/show_running-config.txt @@ -0,0 +1,168 @@ +Building configuration... + +Current configuration : 2114 bytes +! +version 12.4 +service timestamps debug datetime msec +service timestamps log datetime msec +no service password-encryption +! +hostname %[1]s +! +boot-start-marker +boot-end-marker +! +! +no aaa new-model +memory-size iomem 5 +no ip icmp rate-limit unreachable +ip cef +! +! +! +! +no ip domain lookup +ip domain name test +ip auth-proxy max-nodata-conns 3 +ip admission max-nodata-conns 3 +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +username admin privilege 15 secret 5 $1$M1ce$SKeVGg2lUCPrsLkJMIdWf. +! +! +ip tcp synwait-time 5 +ip ssh version 2 +ip scp server enable +! +! +! +! +! +interface FastEthernet0/0 +description netpalm +ip address 10.0.2.27 255.255.255.0 +duplex auto +speed auto +! +interface Serial0/0 +no ip address +shutdown +clock rate 2000000 +! +interface FastEthernet0/1 +no ip address +shutdown +duplex auto +speed auto +! +interface Serial0/1 +no ip address +shutdown +clock rate 2000000 +! +interface FastEthernet1/0 +no ip address +shutdown +duplex auto +speed auto +! +interface FastEthernet2/0 +no ip address +shutdown +duplex auto +speed auto +! +interface FastEthernet3/0 +! +interface FastEthernet3/1 +! +interface FastEthernet3/2 +! +interface FastEthernet3/3 +! +interface FastEthernet3/4 +! +interface FastEthernet3/5 +! +interface FastEthernet3/6 +! +interface FastEthernet3/7 +! +interface FastEthernet3/8 +! +interface FastEthernet3/9 +! +interface FastEthernet3/10 +! +interface FastEthernet3/11 +! +interface FastEthernet3/12 +! +interface FastEthernet3/13 +! +interface FastEthernet3/14 +! +interface FastEthernet3/15 +! +interface Vlan1 +no ip address +! +ip forward-protocol nd +! +! +no ip http server +no ip http secure-server +! +ip access-list standard bob +ip access-list standard yip +! +snmp-server community test RO +snmp-server community location RO yip +snmp-server community contact RO bob +no cdp log mismatch duplex +! +! +! +control-plane +! +! +! +! +! +! +! +! +! +! +line con 0 +exec-timeout 0 0 +privilege level 15 +logging synchronous +line aux 0 +exec-timeout 0 0 +privilege level 15 +logging synchronous +line vty 0 4 +privilege level 15 +login local +transport input ssh +line vty 5 15 +privilege level 15 +login local +transport input ssh +! +! +end diff --git a/config/show_version.txt b/config/show_version.txt new file mode 100644 index 0000000..7b7c703 --- /dev/null +++ b/config/show_version.txt @@ -0,0 +1,43 @@ +Cisco IOS XE Software, Version 16.04.01 +Cisco IOS Software [Everest], CSR1000V Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.4.1, RELEASE SOFTWARE (fc2) +Technical Support: http://www.cisco.com/techsupport +Copyright (c) 1986-2016 by Cisco Systems, Inc. +Compiled Sun 27-Nov-16 13:02 by mcpre +Cisco IOS-XE software, Copyright (c) 2005-2016 by cisco Systems, Inc. +All rights reserved. Certain components of Cisco IOS-XE software are +licensed under the GNU General Public License ("GPL") Version 2.0. The +software code licensed under GPL Version 2.0 is free software that comes +with ABSOLUTELY NO WARRANTY. You can redistribute and/or modify such +GPL code under the terms of GPL Version 2.0. For more details, see the +documentation or "License Notice" file accompanying the IOS-XE software, +or the applicable URL provided on the flyer accompanying the IOS-XE +software. +ROM: IOS-XE ROMMON +%[1]v uptime is 4 hours, 55 minutes +Uptime for this control processor is 4 hours, 56 minutes +System returned to ROM by reload +System image file is "bootflash:packages.conf" +Last reload reason: reload +This product contains cryptographic features and is subject to United +States and local country laws governing import, export, transfer and +use. Delivery of Cisco cryptographic products does not imply +third-party authority to import, export, distribute or use encryption. +Importers, exporters, distributors and users are responsible for +compliance with U.S. and local country laws. By using this product you +agree to comply with applicable laws and regulations. If you are unable +to comply with U.S. and local laws, return this product immediately. +A summary of U.S. laws governing Cisco cryptographic products may be found at: +http://www.cisco.com/wwl/export/crypto/tool/stqrg.html +If you require further assistance please contact us by sending email to +export@cisco.com. +License Level: ax +License Type: Default. No valid license found. +Next reload license Level: ax +cisco CSR1000V (VXE) processor (revision VXE) with 2052375K/3075K bytes of memory. +Processor board ID 9FKLJWM5EB0 +10 Gigabit Ethernet interfaces +32768K bytes of non-volatile configuration memory. +3985132K bytes of physical memory. +7774207K bytes of virtual hard disk at bootflash:. +0K bytes of at webui:. +Configuration register is 0x2102 diff --git a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go index 0dd1651..aa2013a 100644 --- a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go +++ b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go @@ -523,7 +523,7 @@ func (t *Terminal) handleKey(key rune) (line string, ok bool) { t.setLine(runes, len(runes)) } } - case keyNewline: //replaced keyEnter + case keyEnter, keyNewline: //replaced keyEnter t.moveCursorToPos(len(t.line)) t.queue([]rune("\r\n")) line = string(t.line)