ciscollm-cli 1.3.3 → 1.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -25
- package/dist/cli/commands/daemonCommand.d.ts +4 -0
- package/dist/cli/commands/daemonCommand.js +68 -0
- package/dist/cli/commands/daemonCommand.js.map +1 -0
- package/dist/cli/commands/monitorCommand.js +17 -1
- package/dist/cli/commands/monitorCommand.js.map +1 -1
- package/dist/cli/commands/runCommand.d.ts +1 -3
- package/dist/cli/commands/runCommand.js +177 -470
- package/dist/cli/commands/runCommand.js.map +1 -1
- package/dist/cli/ui/interactiveWizard.d.ts +1 -0
- package/dist/cli/ui/interactiveWizard.js +429 -0
- package/dist/cli/ui/interactiveWizard.js.map +1 -0
- package/dist/cli/ui/ui.js +0 -5
- package/dist/cli/ui/ui.js.map +1 -1
- package/dist/core/agent/AgentLoop.d.ts +15 -3
- package/dist/core/agent/AgentLoop.js +196 -67
- package/dist/core/agent/AgentLoop.js.map +1 -1
- package/dist/core/agent/AutoRemediationEngine.d.ts +14 -0
- package/dist/core/agent/AutoRemediationEngine.js +75 -0
- package/dist/core/agent/AutoRemediationEngine.js.map +1 -0
- package/dist/core/agent/DigitalTwin.d.ts +10 -0
- package/dist/core/agent/DigitalTwin.js +41 -0
- package/dist/core/agent/DigitalTwin.js.map +1 -0
- package/dist/core/agent/IntentTranslator.d.ts +8 -0
- package/dist/core/agent/IntentTranslator.js +63 -0
- package/dist/core/agent/IntentTranslator.js.map +1 -0
- package/dist/core/agent/MemoryManager.d.ts +14 -0
- package/dist/core/agent/MemoryManager.js +89 -0
- package/dist/core/agent/MemoryManager.js.map +1 -0
- package/dist/core/agent/MultiAgentCoordinator.js +0 -2
- package/dist/core/agent/MultiAgentCoordinator.js.map +1 -1
- package/dist/core/agent/NetworkPlanner.d.ts +9 -0
- package/dist/core/agent/NetworkPlanner.js +111 -0
- package/dist/core/agent/NetworkPlanner.js.map +1 -0
- package/dist/core/agent/PromptEngine.d.ts +1 -1
- package/dist/core/agent/PromptEngine.js +23 -13
- package/dist/core/agent/PromptEngine.js.map +1 -1
- package/dist/core/guardrails/NetworkAudit.js +1 -1
- package/dist/core/guardrails/NetworkAudit.js.map +1 -1
- package/dist/core/plugins/PluginManager.d.ts +17 -0
- package/dist/core/plugins/PluginManager.js +108 -0
- package/dist/core/plugins/PluginManager.js.map +1 -0
- package/dist/core/rollback/TransactionManager.js +0 -5
- package/dist/core/rollback/TransactionManager.js.map +1 -1
- package/dist/index.js +36 -61
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/llm/LLMClient.d.ts +1 -0
- package/dist/infrastructure/llm/LLMClient.js +33 -9
- package/dist/infrastructure/llm/LLMClient.js.map +1 -1
- package/dist/infrastructure/protocols/SshSession.d.ts +1 -0
- package/dist/infrastructure/protocols/SshSession.js +5 -4
- package/dist/infrastructure/protocols/SshSession.js.map +1 -1
- package/dist/infrastructure/protocols/TelnetSession.d.ts +1 -0
- package/dist/infrastructure/protocols/TelnetSession.js +5 -1
- package/dist/infrastructure/protocols/TelnetSession.js.map +1 -1
- package/dist/server/devices/ASADevice.d.ts +17 -0
- package/dist/server/devices/ASADevice.js +160 -0
- package/dist/server/devices/ASADevice.js.map +1 -0
- package/dist/server/devices/BaseDevice.d.ts +11 -0
- package/dist/server/devices/BaseDevice.js +19 -0
- package/dist/server/devices/BaseDevice.js.map +1 -0
- package/dist/server/devices/IOSDevice.d.ts +100 -0
- package/dist/server/devices/IOSDevice.js +1561 -0
- package/dist/server/devices/IOSDevice.js.map +1 -0
- package/dist/server/devices/LinuxServerDevice.d.ts +8 -0
- package/dist/server/devices/LinuxServerDevice.js +71 -0
- package/dist/server/devices/LinuxServerDevice.js.map +1 -0
- package/dist/server/devices/PCDevice.d.ts +20 -0
- package/dist/server/devices/PCDevice.js +86 -0
- package/dist/server/devices/PCDevice.js.map +1 -0
- package/dist/server/devices/RouterDevice.d.ts +4 -0
- package/dist/server/devices/RouterDevice.js +11 -0
- package/dist/server/devices/RouterDevice.js.map +1 -0
- package/dist/server/devices/SwitchDevice.d.ts +4 -0
- package/dist/server/devices/SwitchDevice.js +11 -0
- package/dist/server/devices/SwitchDevice.js.map +1 -0
- package/dist/server/devices/WLCDevice.d.ts +15 -0
- package/dist/server/devices/WLCDevice.js +88 -0
- package/dist/server/devices/WLCDevice.js.map +1 -0
- package/dist/server/index.js +47 -22
- package/dist/server/index.js.map +1 -1
- package/dist/server/shell-simulator.js +1 -2
- package/dist/server/shell-simulator.js.map +1 -1
- package/dist/server/ssh.d.ts +2 -1
- package/dist/server/ssh.js +22 -9
- package/dist/server/ssh.js.map +1 -1
- package/dist/server/telnet.d.ts +3 -2
- package/dist/server/telnet.js +10 -42
- package/dist/server/telnet.js.map +1 -1
- package/dist/shared/bootBanner.d.ts +1 -0
- package/dist/shared/bootBanner.js +93 -0
- package/dist/shared/bootBanner.js.map +1 -0
- package/dist/shared/constants.js +1 -1
- package/dist/shared/constants.js.map +1 -1
- package/package.json +1 -1
- package/dist/cli/commands/dashboardCommand.d.ts +0 -1
- package/dist/cli/commands/dashboardCommand.js +0 -16
- package/dist/cli/commands/dashboardCommand.js.map +0 -1
- package/dist/cli/commands/shellCommand.d.ts +0 -1
- package/dist/cli/commands/shellCommand.js +0 -44
- package/dist/cli/commands/shellCommand.js.map +0 -1
- package/dist/infrastructure/protocols/CmlSession.d.ts +0 -26
- package/dist/infrastructure/protocols/CmlSession.js +0 -448
- package/dist/infrastructure/protocols/CmlSession.js.map +0 -1
- package/dist/infrastructure/protocols/NetconfSession.d.ts +0 -74
- package/dist/infrastructure/protocols/NetconfSession.js +0 -553
- package/dist/infrastructure/protocols/NetconfSession.js.map +0 -1
- package/dist/server/dashboard.d.ts +0 -3
- package/dist/server/dashboard.js +0 -1149
- package/dist/server/dashboard.js.map +0 -1
|
@@ -0,0 +1,1561 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IOSDevice = void 0;
|
|
4
|
+
const BaseDevice_1 = require("./BaseDevice");
|
|
5
|
+
class IOSDevice extends BaseDevice_1.BaseDevice {
|
|
6
|
+
mode = 'USER_EXEC';
|
|
7
|
+
activeInterface = null;
|
|
8
|
+
interfaces = new Map([
|
|
9
|
+
['GigabitEthernet0/0', {
|
|
10
|
+
name: 'GigabitEthernet0/0',
|
|
11
|
+
ip: '192.168.1.254',
|
|
12
|
+
subnet: '255.255.255.0',
|
|
13
|
+
adminShutdown: false,
|
|
14
|
+
lineProtocolUp: true,
|
|
15
|
+
description: 'Management Uplink'
|
|
16
|
+
}],
|
|
17
|
+
['GigabitEthernet0/1', {
|
|
18
|
+
name: 'GigabitEthernet0/1',
|
|
19
|
+
ip: null,
|
|
20
|
+
subnet: null,
|
|
21
|
+
adminShutdown: true,
|
|
22
|
+
lineProtocolUp: false,
|
|
23
|
+
description: null
|
|
24
|
+
}],
|
|
25
|
+
['GigabitEthernet0/2', {
|
|
26
|
+
name: 'GigabitEthernet0/2',
|
|
27
|
+
ip: null,
|
|
28
|
+
subnet: null,
|
|
29
|
+
adminShutdown: true,
|
|
30
|
+
lineProtocolUp: false,
|
|
31
|
+
description: null
|
|
32
|
+
}]
|
|
33
|
+
]);
|
|
34
|
+
vlans = new Set([1]);
|
|
35
|
+
vlanNames = new Map([[1, 'default']]);
|
|
36
|
+
activeVlan = null;
|
|
37
|
+
routes = [
|
|
38
|
+
{
|
|
39
|
+
network: '192.168.1.0',
|
|
40
|
+
mask: '255.255.255.0',
|
|
41
|
+
nextHop: null,
|
|
42
|
+
outgoingInterface: 'GigabitEthernet0/0',
|
|
43
|
+
connected: true
|
|
44
|
+
}
|
|
45
|
+
];
|
|
46
|
+
shellEnabled = false;
|
|
47
|
+
shellVariables = {};
|
|
48
|
+
shellFunctions = {};
|
|
49
|
+
ospfEnabled = false;
|
|
50
|
+
ospfProcessId = null;
|
|
51
|
+
ospfNetworks = [];
|
|
52
|
+
ripEnabled = false;
|
|
53
|
+
ripVersion = 2;
|
|
54
|
+
ripAutoSummary = false;
|
|
55
|
+
bgpEnabled = false;
|
|
56
|
+
bgpAsn = null;
|
|
57
|
+
eigrpEnabled = false;
|
|
58
|
+
eigrpAsn = null;
|
|
59
|
+
vtpMode = 'server';
|
|
60
|
+
vtpDomain = null;
|
|
61
|
+
vtpPassword = null;
|
|
62
|
+
hsrpGroups = new Map();
|
|
63
|
+
vrrpGroups = new Map();
|
|
64
|
+
ntpServers = [];
|
|
65
|
+
snmpCommunities = [];
|
|
66
|
+
natInsideInterfaces = new Set();
|
|
67
|
+
natOutsideInterfaces = new Set();
|
|
68
|
+
natRules = [];
|
|
69
|
+
acls = new Map();
|
|
70
|
+
ipRoutingEnabled = true;
|
|
71
|
+
featuresEnabled = new Set();
|
|
72
|
+
vpcDomainId = null;
|
|
73
|
+
vpcPeerKeepalive = null;
|
|
74
|
+
vnSegments = new Map();
|
|
75
|
+
vrfs = new Map();
|
|
76
|
+
activeVrf = null;
|
|
77
|
+
flashFiles = new Set(['c2960-lanbasek9-mz.150-2.SE4.bin']);
|
|
78
|
+
pendingCopyDest = null;
|
|
79
|
+
backupState = null;
|
|
80
|
+
saveBackupState() {
|
|
81
|
+
const interfacesCopy = new Map();
|
|
82
|
+
for (const [name, val] of this.interfaces.entries()) {
|
|
83
|
+
interfacesCopy.set(name, { ...val });
|
|
84
|
+
}
|
|
85
|
+
const routesCopy = this.routes.map(r => ({ ...r }));
|
|
86
|
+
const vlansCopy = new Set(this.vlans);
|
|
87
|
+
const vlanNamesCopy = new Map(this.vlanNames);
|
|
88
|
+
this.backupState = {
|
|
89
|
+
hostname: this.hostname,
|
|
90
|
+
interfaces: interfacesCopy,
|
|
91
|
+
routes: routesCopy,
|
|
92
|
+
vlans: vlansCopy,
|
|
93
|
+
vlanNames: vlanNamesCopy
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
restoreBackupState() {
|
|
97
|
+
if (!this.backupState)
|
|
98
|
+
return;
|
|
99
|
+
this.hostname = this.backupState.hostname;
|
|
100
|
+
this.interfaces = this.backupState.interfaces;
|
|
101
|
+
this.routes = this.backupState.routes;
|
|
102
|
+
this.vlans = this.backupState.vlans;
|
|
103
|
+
this.vlanNames = this.backupState.vlanNames;
|
|
104
|
+
}
|
|
105
|
+
constructor(initialHostname, type = 'ios') {
|
|
106
|
+
super(initialHostname || 'Switch1', type);
|
|
107
|
+
if (initialHostname) {
|
|
108
|
+
this.hostname = initialHostname;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
getPrompt() {
|
|
112
|
+
switch (this.mode) {
|
|
113
|
+
case 'USER_EXEC':
|
|
114
|
+
return `${this.hostname}> `;
|
|
115
|
+
case 'PRIVILEGED_EXEC':
|
|
116
|
+
return `${this.hostname}# `;
|
|
117
|
+
case 'GLOBAL_CONFIG':
|
|
118
|
+
return `${this.hostname}(config)# `;
|
|
119
|
+
case 'INTERFACE_CONFIG':
|
|
120
|
+
return `${this.hostname}(config-if)# `;
|
|
121
|
+
case 'OSPF_CONFIG':
|
|
122
|
+
case 'RIP_CONFIG':
|
|
123
|
+
case 'BGP_CONFIG':
|
|
124
|
+
case 'EIGRP_CONFIG':
|
|
125
|
+
return `${this.hostname}(config-router)# `;
|
|
126
|
+
case 'DHCP_CONFIG':
|
|
127
|
+
return `${this.hostname}(config-dhcp)# `;
|
|
128
|
+
case 'ACL_CONFIG':
|
|
129
|
+
return `${this.hostname}(config-ext-nacl)# `;
|
|
130
|
+
case 'VLAN_CONFIG':
|
|
131
|
+
return `${this.hostname}(config-vlan)# `;
|
|
132
|
+
case 'VPC_CONFIG':
|
|
133
|
+
return `${this.hostname}(config-vpc-domain)# `;
|
|
134
|
+
case 'VRF_CONFIG':
|
|
135
|
+
return `${this.hostname}(config-vrf)# `;
|
|
136
|
+
case 'VRF_AF_CONFIG':
|
|
137
|
+
return `${this.hostname}(config-vrf-af-ipv4)# `;
|
|
138
|
+
default:
|
|
139
|
+
return `${this.hostname}# `;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
processCommand(line) {
|
|
143
|
+
if (line.trim().endsWith('?')) {
|
|
144
|
+
return this.getContextHelp(line);
|
|
145
|
+
}
|
|
146
|
+
const normalizedLine = this.normalizeCommandString(line);
|
|
147
|
+
const trimmed = normalizedLine.trim();
|
|
148
|
+
if (this.pendingCopyDest) {
|
|
149
|
+
const dest = trimmed || this.pendingCopyDest;
|
|
150
|
+
this.flashFiles.add(dest);
|
|
151
|
+
this.saveBackupState();
|
|
152
|
+
this.pendingCopyDest = null;
|
|
153
|
+
return `1542 bytes copied in 0.456 secs (3381 bytes/sec)\n[OK]`;
|
|
154
|
+
}
|
|
155
|
+
if (!trimmed)
|
|
156
|
+
return '';
|
|
157
|
+
if (this.shellEnabled) {
|
|
158
|
+
const varMatch = trimmed.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
|
|
159
|
+
if (varMatch) {
|
|
160
|
+
const [, name, val] = varMatch;
|
|
161
|
+
this.shellVariables[name] = val;
|
|
162
|
+
return '';
|
|
163
|
+
}
|
|
164
|
+
const funcMatch = trimmed.match(/^([A-Za-z_][A-Za-z0-9_]*)\(\)\s*{(.*)}$/);
|
|
165
|
+
if (funcMatch) {
|
|
166
|
+
const [, name, body] = funcMatch;
|
|
167
|
+
this.shellFunctions[name] = body.trim();
|
|
168
|
+
return '';
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
let commandToExecute = trimmed;
|
|
172
|
+
const tempArgs = commandToExecute.split(/\s+/);
|
|
173
|
+
const tempCmd = tempArgs[0].toLowerCase();
|
|
174
|
+
const isConfigMode = this.mode !== 'USER_EXEC' && this.mode !== 'PRIVILEGED_EXEC';
|
|
175
|
+
if (tempCmd === 'do' && isConfigMode) {
|
|
176
|
+
const doMatch = commandToExecute.match(/^do\s+(.+)$/i);
|
|
177
|
+
if (doMatch) {
|
|
178
|
+
commandToExecute = doMatch[1];
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const args = commandToExecute.split(/\s+/);
|
|
182
|
+
const cmd = args[0].toLowerCase();
|
|
183
|
+
const isShow = cmd === 'show' || cmd === 'sh' || (cmd === 'do' && (args[1]?.toLowerCase() === 'show' || args[1]?.toLowerCase() === 'sh'));
|
|
184
|
+
if (cmd === '?' || cmd === 'help') {
|
|
185
|
+
if (cmd === 'help') {
|
|
186
|
+
return `Help may be requested at any point in a command by entering
|
|
187
|
+
a question mark '?'. If nothing matches, the help list will
|
|
188
|
+
show the available options.`;
|
|
189
|
+
}
|
|
190
|
+
if (this.mode === 'USER_EXEC') {
|
|
191
|
+
return `Exec commands:
|
|
192
|
+
disable Turn off privileged commands
|
|
193
|
+
enable Turn on privileged commands
|
|
194
|
+
exit Exit from the EXEC
|
|
195
|
+
ping Send echo messages
|
|
196
|
+
show Show running system information`;
|
|
197
|
+
}
|
|
198
|
+
else if (this.mode === 'PRIVILEGED_EXEC') {
|
|
199
|
+
return `Exec commands:
|
|
200
|
+
clear Reset functions
|
|
201
|
+
configure Enter configuration mode
|
|
202
|
+
copy Copy from one file to another
|
|
203
|
+
dir List files on a filesystem
|
|
204
|
+
disable Turn off privileged commands
|
|
205
|
+
enable Turn on privileged commands
|
|
206
|
+
exit Exit from the EXEC
|
|
207
|
+
ping Send echo messages
|
|
208
|
+
show Show running system information
|
|
209
|
+
write Write running configuration to memory or terminal`;
|
|
210
|
+
}
|
|
211
|
+
else if (this.mode === 'GLOBAL_CONFIG') {
|
|
212
|
+
return `Configure commands:
|
|
213
|
+
do To run EXEC commands in config mode
|
|
214
|
+
end Exit from configure mode
|
|
215
|
+
exit Exit from configure mode
|
|
216
|
+
hostname Set system's network name
|
|
217
|
+
interface Select an interface to configure
|
|
218
|
+
ip Global IP configuration subcommands
|
|
219
|
+
no Negate a command or set defaults
|
|
220
|
+
router Enable a routing process
|
|
221
|
+
vlan Vlan configuration commands`;
|
|
222
|
+
}
|
|
223
|
+
else if (this.mode === 'INTERFACE_CONFIG') {
|
|
224
|
+
return `Interface configuration commands:
|
|
225
|
+
description Detailed description of this interface
|
|
226
|
+
exit Exit from interface configuration mode
|
|
227
|
+
ip IP interface configuration subcommands
|
|
228
|
+
no Negate a command or set defaults
|
|
229
|
+
shutdown Shutdown this interface`;
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
return `Commands:
|
|
233
|
+
exit Exit current mode
|
|
234
|
+
end Exit to privileged EXEC mode`;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (cmd === 'clear') {
|
|
238
|
+
if (this.mode === 'USER_EXEC') {
|
|
239
|
+
return `% Command rejected: Place in Privileged EXEC mode first.`;
|
|
240
|
+
}
|
|
241
|
+
return `% Incomplete command.`;
|
|
242
|
+
}
|
|
243
|
+
if (cmd === 'exit') {
|
|
244
|
+
if (this.mode === 'INTERFACE_CONFIG' || this.mode === 'OSPF_CONFIG' || this.mode === 'RIP_CONFIG' || this.mode === 'BGP_CONFIG' || this.mode === 'EIGRP_CONFIG' || this.mode === 'DHCP_CONFIG' || this.mode === 'ACL_CONFIG' || this.mode === 'VLAN_CONFIG' || this.mode === 'VPC_CONFIG' || this.mode === 'VRF_CONFIG') {
|
|
245
|
+
this.mode = 'GLOBAL_CONFIG';
|
|
246
|
+
this.activeInterface = null;
|
|
247
|
+
this.activeVlan = null;
|
|
248
|
+
this.activeVrf = null;
|
|
249
|
+
return '';
|
|
250
|
+
}
|
|
251
|
+
else if (this.mode === 'VRF_AF_CONFIG') {
|
|
252
|
+
this.mode = 'VRF_CONFIG';
|
|
253
|
+
return '';
|
|
254
|
+
}
|
|
255
|
+
else if (this.mode === 'GLOBAL_CONFIG') {
|
|
256
|
+
this.mode = 'PRIVILEGED_EXEC';
|
|
257
|
+
return '';
|
|
258
|
+
}
|
|
259
|
+
else if (this.mode === 'PRIVILEGED_EXEC') {
|
|
260
|
+
this.mode = 'USER_EXEC';
|
|
261
|
+
return '';
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
return 'exit';
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (cmd === 'end') {
|
|
268
|
+
if (this.mode !== 'USER_EXEC' && this.mode !== 'PRIVILEGED_EXEC') {
|
|
269
|
+
this.mode = 'PRIVILEGED_EXEC';
|
|
270
|
+
this.activeInterface = null;
|
|
271
|
+
this.activeVlan = null;
|
|
272
|
+
this.activeVrf = null;
|
|
273
|
+
return '';
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (cmd === 'enable') {
|
|
277
|
+
if (this.mode === 'USER_EXEC') {
|
|
278
|
+
this.mode = 'PRIVILEGED_EXEC';
|
|
279
|
+
return '';
|
|
280
|
+
}
|
|
281
|
+
return '';
|
|
282
|
+
}
|
|
283
|
+
if (cmd === 'disable') {
|
|
284
|
+
if (this.mode !== 'USER_EXEC') {
|
|
285
|
+
this.mode = 'USER_EXEC';
|
|
286
|
+
return '';
|
|
287
|
+
}
|
|
288
|
+
return '';
|
|
289
|
+
}
|
|
290
|
+
if (trimmed.toLowerCase() === 'configure terminal' || trimmed.toLowerCase() === 'conf t') {
|
|
291
|
+
if (this.mode === 'PRIVILEGED_EXEC') {
|
|
292
|
+
this.mode = 'GLOBAL_CONFIG';
|
|
293
|
+
return 'Enter configuration commands, one per line. End with CNTL/Z.\n';
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
return `% Command rejected: Place in Privileged EXEC mode first.`;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (cmd === 'terminal' && args[1] === 'length' && args[2] === '0') {
|
|
300
|
+
return '';
|
|
301
|
+
}
|
|
302
|
+
if (cmd === 'screen-length' && args[1] === '0' && args[2] === 'temporary') {
|
|
303
|
+
return '';
|
|
304
|
+
}
|
|
305
|
+
if (cmd === 'set' && args[1] === 'cli' && args[2] === 'screen-length' && args[3] === '0') {
|
|
306
|
+
return '';
|
|
307
|
+
}
|
|
308
|
+
if (cmd === 'terminal' && args[1] === 'shell') {
|
|
309
|
+
this.shellEnabled = true;
|
|
310
|
+
return '';
|
|
311
|
+
}
|
|
312
|
+
if (cmd === 'shell' && args[1] === 'processing' && args[2] === 'full') {
|
|
313
|
+
this.shellEnabled = true;
|
|
314
|
+
return '';
|
|
315
|
+
}
|
|
316
|
+
const isGeneralCommand = isShow || cmd === 'ping' || cmd === 'write' || cmd === 'wr' || cmd === 'copy' || cmd === 'dir' || cmd === 'test';
|
|
317
|
+
if (this.mode === 'GLOBAL_CONFIG' && !isGeneralCommand) {
|
|
318
|
+
if (cmd === 'feature' && args[1]) {
|
|
319
|
+
const featureName = args.slice(1).join(' ').toLowerCase();
|
|
320
|
+
this.featuresEnabled.add(featureName);
|
|
321
|
+
return '';
|
|
322
|
+
}
|
|
323
|
+
if (cmd === 'no' && args[1] === 'feature' && args[2]) {
|
|
324
|
+
const featureName = args.slice(2).join(' ').toLowerCase();
|
|
325
|
+
this.featuresEnabled.delete(featureName);
|
|
326
|
+
return '';
|
|
327
|
+
}
|
|
328
|
+
if (cmd === 'vpc' && args[1] === 'domain' && args[2]) {
|
|
329
|
+
const domainId = parseInt(args[2], 10);
|
|
330
|
+
if (!isNaN(domainId)) {
|
|
331
|
+
this.vpcDomainId = domainId;
|
|
332
|
+
this.mode = 'VPC_CONFIG';
|
|
333
|
+
return '';
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (cmd === 'vrf' && args[1] === 'context' && args[2]) {
|
|
337
|
+
const vrfName = args[2];
|
|
338
|
+
this.activeVrf = vrfName;
|
|
339
|
+
if (!this.vrfs.has(vrfName)) {
|
|
340
|
+
this.vrfs.set(vrfName, { routeTargets: [] });
|
|
341
|
+
}
|
|
342
|
+
this.mode = 'VRF_CONFIG';
|
|
343
|
+
return '';
|
|
344
|
+
}
|
|
345
|
+
if (cmd === 'hostname' && args[1]) {
|
|
346
|
+
this.hostname = args[1];
|
|
347
|
+
return '';
|
|
348
|
+
}
|
|
349
|
+
if (cmd === 'interface' && args[1]) {
|
|
350
|
+
const ifaceName = this.normalizeInterfaceName(args[1]);
|
|
351
|
+
this.mode = 'INTERFACE_CONFIG';
|
|
352
|
+
this.activeInterface = ifaceName;
|
|
353
|
+
if (!this.interfaces.has(ifaceName)) {
|
|
354
|
+
this.interfaces.set(ifaceName, {
|
|
355
|
+
name: ifaceName,
|
|
356
|
+
ip: null,
|
|
357
|
+
subnet: null,
|
|
358
|
+
adminShutdown: false,
|
|
359
|
+
lineProtocolUp: true,
|
|
360
|
+
description: null
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
return '';
|
|
364
|
+
}
|
|
365
|
+
if (cmd === 'vlan' && args[1]) {
|
|
366
|
+
const vlanId = parseInt(args[1], 10);
|
|
367
|
+
if (!isNaN(vlanId)) {
|
|
368
|
+
this.vlans.add(vlanId);
|
|
369
|
+
this.activeVlan = vlanId;
|
|
370
|
+
this.mode = 'VLAN_CONFIG';
|
|
371
|
+
return '';
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (cmd === 'no' && args[1] === 'vlan' && args[2]) {
|
|
375
|
+
const vlanId = parseInt(args[2], 10);
|
|
376
|
+
if (!isNaN(vlanId)) {
|
|
377
|
+
this.vlans.delete(vlanId);
|
|
378
|
+
this.vlanNames.delete(vlanId);
|
|
379
|
+
return '';
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
if (cmd === 'ip' && args[1] === 'route' && args[2] && args[3]) {
|
|
383
|
+
const network = args[2];
|
|
384
|
+
const mask = args[3];
|
|
385
|
+
const next = args[4] || null;
|
|
386
|
+
this.routes.push({
|
|
387
|
+
network,
|
|
388
|
+
mask,
|
|
389
|
+
nextHop: next && !next.startsWith('Gig') && !next.startsWith('Loop') ? next : null,
|
|
390
|
+
outgoingInterface: next && (next.startsWith('Gig') || next.startsWith('Loop')) ? next : null,
|
|
391
|
+
connected: false
|
|
392
|
+
});
|
|
393
|
+
return '';
|
|
394
|
+
}
|
|
395
|
+
if (cmd === 'no' && args[1] === 'ip' && args[2] === 'route' && args[3] && args[4]) {
|
|
396
|
+
const network = args[3];
|
|
397
|
+
const mask = args[4];
|
|
398
|
+
this.routes = this.routes.filter(r => !(r.network === network && r.mask === mask));
|
|
399
|
+
return '';
|
|
400
|
+
}
|
|
401
|
+
if (cmd === 'ip' && args[1] === 'routing') {
|
|
402
|
+
this.ipRoutingEnabled = true;
|
|
403
|
+
return '';
|
|
404
|
+
}
|
|
405
|
+
if (cmd === 'no' && args[1] === 'ip' && args[2] === 'routing') {
|
|
406
|
+
this.ipRoutingEnabled = false;
|
|
407
|
+
return '';
|
|
408
|
+
}
|
|
409
|
+
if (cmd === 'router' && args[1] === 'ospf') {
|
|
410
|
+
this.mode = 'OSPF_CONFIG';
|
|
411
|
+
this.ospfProcessId = args[2] || null;
|
|
412
|
+
this.ospfEnabled = true;
|
|
413
|
+
return '';
|
|
414
|
+
}
|
|
415
|
+
if (cmd === 'no' && args[1] === 'router' && args[2] === 'ospf') {
|
|
416
|
+
this.ospfEnabled = false;
|
|
417
|
+
this.ospfProcessId = null;
|
|
418
|
+
return '';
|
|
419
|
+
}
|
|
420
|
+
if (cmd === 'router' && args[1] === 'rip') {
|
|
421
|
+
this.mode = 'RIP_CONFIG';
|
|
422
|
+
this.ripEnabled = true;
|
|
423
|
+
return '';
|
|
424
|
+
}
|
|
425
|
+
if (cmd === 'no' && args[1] === 'router' && args[2] === 'rip') {
|
|
426
|
+
this.ripEnabled = false;
|
|
427
|
+
return '';
|
|
428
|
+
}
|
|
429
|
+
if (cmd === 'router' && args[1] === 'bgp') {
|
|
430
|
+
this.mode = 'BGP_CONFIG';
|
|
431
|
+
this.bgpAsn = args[2] || null;
|
|
432
|
+
this.bgpEnabled = true;
|
|
433
|
+
return '';
|
|
434
|
+
}
|
|
435
|
+
if (cmd === 'no' && args[1] === 'router' && args[2] === 'bgp') {
|
|
436
|
+
this.bgpEnabled = false;
|
|
437
|
+
this.bgpAsn = null;
|
|
438
|
+
return '';
|
|
439
|
+
}
|
|
440
|
+
if (cmd === 'spanning-tree' && args[1]) {
|
|
441
|
+
return '';
|
|
442
|
+
}
|
|
443
|
+
if (cmd === 'router' && args[1] === 'eigrp') {
|
|
444
|
+
this.mode = 'EIGRP_CONFIG';
|
|
445
|
+
this.eigrpAsn = args[2] || null;
|
|
446
|
+
this.eigrpEnabled = true;
|
|
447
|
+
return '';
|
|
448
|
+
}
|
|
449
|
+
if (cmd === 'no' && args[1] === 'router' && args[2] === 'eigrp') {
|
|
450
|
+
this.eigrpEnabled = false;
|
|
451
|
+
this.eigrpAsn = null;
|
|
452
|
+
return '';
|
|
453
|
+
}
|
|
454
|
+
if (cmd === 'vtp' && args[1]) {
|
|
455
|
+
if (args[1] === 'mode' && args[2]) {
|
|
456
|
+
this.vtpMode = args[2].toLowerCase();
|
|
457
|
+
}
|
|
458
|
+
else if (args[1] === 'domain' && args[2]) {
|
|
459
|
+
this.vtpDomain = args[2];
|
|
460
|
+
}
|
|
461
|
+
else if (args[1] === 'password' && args[2]) {
|
|
462
|
+
this.vtpPassword = args[2];
|
|
463
|
+
}
|
|
464
|
+
return '';
|
|
465
|
+
}
|
|
466
|
+
if (cmd === 'ntp' && args[1] === 'server' && args[2]) {
|
|
467
|
+
if (!this.ntpServers.includes(args[2])) {
|
|
468
|
+
this.ntpServers.push(args[2]);
|
|
469
|
+
}
|
|
470
|
+
return '';
|
|
471
|
+
}
|
|
472
|
+
if (cmd === 'snmp-server' && args[1] === 'community' && args[2]) {
|
|
473
|
+
if (!this.snmpCommunities.includes(args[2])) {
|
|
474
|
+
this.snmpCommunities.push(args[2]);
|
|
475
|
+
}
|
|
476
|
+
return '';
|
|
477
|
+
}
|
|
478
|
+
if (cmd === 'ip' && args[1] === 'nat' && args[2] === 'inside' && args[3] === 'source') {
|
|
479
|
+
this.natRules.push(args.slice(2).join(' '));
|
|
480
|
+
return '';
|
|
481
|
+
}
|
|
482
|
+
if (cmd === 'access-list' && args[1] && args[2]) {
|
|
483
|
+
const aclId = args[1];
|
|
484
|
+
const rule = args.slice(2).join(' ');
|
|
485
|
+
if (!this.acls.has(aclId)) {
|
|
486
|
+
this.acls.set(aclId, []);
|
|
487
|
+
}
|
|
488
|
+
this.acls.get(aclId).push(rule);
|
|
489
|
+
return '';
|
|
490
|
+
}
|
|
491
|
+
if (cmd === 'ip' && args[1] === 'access-list' && (args[2] === 'standard' || args[2] === 'extended') && args[3]) {
|
|
492
|
+
this.mode = 'ACL_CONFIG';
|
|
493
|
+
return '';
|
|
494
|
+
}
|
|
495
|
+
if (cmd === 'ip' && args[1] === 'dhcp' && args[2] === 'pool' && args[3]) {
|
|
496
|
+
this.mode = 'DHCP_CONFIG';
|
|
497
|
+
return '';
|
|
498
|
+
}
|
|
499
|
+
if (cmd === 'ip' && args[1] === 'dhcp' && args[2] === 'excluded-address') {
|
|
500
|
+
return '';
|
|
501
|
+
}
|
|
502
|
+
if (cmd === 'ip' && args[1] === 'access-list') {
|
|
503
|
+
this.mode = 'ACL_CONFIG';
|
|
504
|
+
return '';
|
|
505
|
+
}
|
|
506
|
+
if (cmd === 'access-list') {
|
|
507
|
+
return '';
|
|
508
|
+
}
|
|
509
|
+
return `% Invalid input detected at '^' marker.`;
|
|
510
|
+
}
|
|
511
|
+
if (this.mode === 'VLAN_CONFIG' && this.activeVlan !== null && !isGeneralCommand) {
|
|
512
|
+
if (cmd === 'name' && args[1]) {
|
|
513
|
+
this.vlanNames.set(this.activeVlan, args.slice(1).join(' '));
|
|
514
|
+
return '';
|
|
515
|
+
}
|
|
516
|
+
if (cmd === 'no' && args[1] === 'name') {
|
|
517
|
+
this.vlanNames.set(this.activeVlan, `VLAN${this.activeVlan.toString().padStart(4, '0')}`);
|
|
518
|
+
return '';
|
|
519
|
+
}
|
|
520
|
+
if (cmd === 'vn-segment' && args[1]) {
|
|
521
|
+
const vni = parseInt(args[1], 10);
|
|
522
|
+
if (!isNaN(vni)) {
|
|
523
|
+
this.vnSegments.set(this.activeVlan, vni);
|
|
524
|
+
return '';
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
return `% Invalid input detected at '^' marker.`;
|
|
528
|
+
}
|
|
529
|
+
if (this.mode === 'INTERFACE_CONFIG' && this.activeInterface && !isGeneralCommand) {
|
|
530
|
+
const iface = this.interfaces.get(this.activeInterface);
|
|
531
|
+
if (cmd === 'vpc' && args[1]) {
|
|
532
|
+
const vpcId = parseInt(args[1], 10);
|
|
533
|
+
if (!isNaN(vpcId)) {
|
|
534
|
+
iface.vpcMemberId = vpcId;
|
|
535
|
+
return '';
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
if (cmd === 'source-interface' && args[1]) {
|
|
539
|
+
iface.sourceInterface = args[1];
|
|
540
|
+
return '';
|
|
541
|
+
}
|
|
542
|
+
if (cmd === 'member' && args[1] === 'vni' && args[2]) {
|
|
543
|
+
const vni = parseInt(args[2], 10);
|
|
544
|
+
if (!isNaN(vni)) {
|
|
545
|
+
if (!iface.memberVnis) {
|
|
546
|
+
iface.memberVnis = new Map();
|
|
547
|
+
}
|
|
548
|
+
const mcastGroup = args[3] === 'mcast-group' ? args[4] : undefined;
|
|
549
|
+
const associateVrf = args.includes('associate-vrf');
|
|
550
|
+
iface.memberVnis.set(vni, { mcastGroup, associateVrf });
|
|
551
|
+
return '';
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
if (cmd === 'shutdown') {
|
|
555
|
+
iface.adminShutdown = true;
|
|
556
|
+
iface.lineProtocolUp = false;
|
|
557
|
+
return '';
|
|
558
|
+
}
|
|
559
|
+
if (cmd === 'no' && args[1] === 'shutdown') {
|
|
560
|
+
iface.adminShutdown = false;
|
|
561
|
+
iface.lineProtocolUp = true;
|
|
562
|
+
return '';
|
|
563
|
+
}
|
|
564
|
+
if (cmd === 'ip' && args[1] === 'address' && args[2] && args[3]) {
|
|
565
|
+
iface.ip = args[2];
|
|
566
|
+
iface.subnet = args[3];
|
|
567
|
+
const network = this.calculateNetwork(args[2], args[3]);
|
|
568
|
+
this.routes = this.routes.filter(r => !(r.outgoingInterface === this.activeInterface && r.connected));
|
|
569
|
+
this.routes.push({
|
|
570
|
+
network,
|
|
571
|
+
mask: args[3],
|
|
572
|
+
nextHop: null,
|
|
573
|
+
outgoingInterface: this.activeInterface,
|
|
574
|
+
connected: true
|
|
575
|
+
});
|
|
576
|
+
return '';
|
|
577
|
+
}
|
|
578
|
+
if (cmd === 'no' && args[1] === 'ip' && args[2] === 'address') {
|
|
579
|
+
iface.ip = null;
|
|
580
|
+
iface.subnet = null;
|
|
581
|
+
this.routes = this.routes.filter(r => !(r.outgoingInterface === this.activeInterface && r.connected));
|
|
582
|
+
return '';
|
|
583
|
+
}
|
|
584
|
+
if (cmd === 'description') {
|
|
585
|
+
iface.description = args.slice(1).join(' ');
|
|
586
|
+
return '';
|
|
587
|
+
}
|
|
588
|
+
if (cmd === 'no' && args[1] === 'description') {
|
|
589
|
+
iface.description = null;
|
|
590
|
+
return '';
|
|
591
|
+
}
|
|
592
|
+
if (cmd === 'switchport') {
|
|
593
|
+
if (args[1] === 'mode' && args[2] === 'access') {
|
|
594
|
+
iface.switchportMode = 'access';
|
|
595
|
+
iface.isSwitchport = true;
|
|
596
|
+
return '';
|
|
597
|
+
}
|
|
598
|
+
if (args[1] === 'access' && args[2] === 'vlan' && args[3]) {
|
|
599
|
+
const vlanId = parseInt(args[3], 10);
|
|
600
|
+
if (!isNaN(vlanId)) {
|
|
601
|
+
iface.vlan = vlanId;
|
|
602
|
+
iface.isSwitchport = true;
|
|
603
|
+
let output = '';
|
|
604
|
+
if (!this.vlans.has(vlanId)) {
|
|
605
|
+
this.vlans.add(vlanId);
|
|
606
|
+
this.vlanNames.set(vlanId, `VLAN${vlanId.toString().padStart(4, '0')}`);
|
|
607
|
+
output = `%% Access VLAN ${vlanId} does not exist. Creating vlan ${vlanId}\n`;
|
|
608
|
+
}
|
|
609
|
+
return output;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
if (!args[1]) {
|
|
613
|
+
iface.isSwitchport = true;
|
|
614
|
+
return '';
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
if (cmd === 'no' && args[1] === 'switchport') {
|
|
618
|
+
iface.isSwitchport = false;
|
|
619
|
+
iface.vlan = undefined;
|
|
620
|
+
iface.switchportMode = undefined;
|
|
621
|
+
return '';
|
|
622
|
+
}
|
|
623
|
+
if (cmd === 'ip' && args[1] === 'access-group') {
|
|
624
|
+
return '';
|
|
625
|
+
}
|
|
626
|
+
if (cmd === 'ip' && args[1] === 'ospf') {
|
|
627
|
+
return '';
|
|
628
|
+
}
|
|
629
|
+
if (cmd === 'switchport' && args[1] === 'mode' && args[2] === 'trunk') {
|
|
630
|
+
iface.switchportMode = 'trunk';
|
|
631
|
+
iface.isSwitchport = true;
|
|
632
|
+
return '';
|
|
633
|
+
}
|
|
634
|
+
if (cmd === 'switchport' && args[1] === 'trunk' && args[2] === 'allowed' && args[3] === 'vlan') {
|
|
635
|
+
return '';
|
|
636
|
+
}
|
|
637
|
+
if (cmd === 'channel-group' && args[1] && args[2] === 'mode' && args[3]) {
|
|
638
|
+
return '';
|
|
639
|
+
}
|
|
640
|
+
if (cmd === 'standby' && args[1]) {
|
|
641
|
+
const group = args[1];
|
|
642
|
+
if (!this.hsrpGroups.has(group)) {
|
|
643
|
+
this.hsrpGroups.set(group, { virtualIp: '', priority: 100, preempt: false });
|
|
644
|
+
}
|
|
645
|
+
const hsrp = this.hsrpGroups.get(group);
|
|
646
|
+
if (args[2] === 'ip' && args[3]) {
|
|
647
|
+
hsrp.virtualIp = args[3];
|
|
648
|
+
}
|
|
649
|
+
else if (args[2] === 'priority' && args[3]) {
|
|
650
|
+
hsrp.priority = parseInt(args[3], 10);
|
|
651
|
+
}
|
|
652
|
+
else if (args[2] === 'preempt') {
|
|
653
|
+
hsrp.preempt = true;
|
|
654
|
+
}
|
|
655
|
+
return '';
|
|
656
|
+
}
|
|
657
|
+
if (cmd === 'vrrp' && args[1]) {
|
|
658
|
+
const group = args[1];
|
|
659
|
+
if (!this.vrrpGroups.has(group)) {
|
|
660
|
+
this.vrrpGroups.set(group, { virtualIp: '', priority: 100 });
|
|
661
|
+
}
|
|
662
|
+
const vrrp = this.vrrpGroups.get(group);
|
|
663
|
+
if (args[2] === 'ip' && args[3]) {
|
|
664
|
+
vrrp.virtualIp = args[3];
|
|
665
|
+
}
|
|
666
|
+
else if (args[2] === 'priority' && args[3]) {
|
|
667
|
+
vrrp.priority = parseInt(args[3], 10);
|
|
668
|
+
}
|
|
669
|
+
return '';
|
|
670
|
+
}
|
|
671
|
+
if (cmd === 'ip' && args[1] === 'nat' && (args[2] === 'inside' || args[2] === 'outside')) {
|
|
672
|
+
iface.natType = args[2];
|
|
673
|
+
if (args[2] === 'inside') {
|
|
674
|
+
this.natInsideInterfaces.add(this.activeInterface);
|
|
675
|
+
}
|
|
676
|
+
else {
|
|
677
|
+
this.natOutsideInterfaces.add(this.activeInterface);
|
|
678
|
+
}
|
|
679
|
+
return '';
|
|
680
|
+
}
|
|
681
|
+
return `% Invalid input detected at '^' marker.`;
|
|
682
|
+
}
|
|
683
|
+
if (this.mode === 'OSPF_CONFIG' && !isGeneralCommand) {
|
|
684
|
+
if (cmd === 'network' && args[1] && args[2] && args[3] === 'area' && args[4]) {
|
|
685
|
+
const network = args[1];
|
|
686
|
+
const wildcard = args[2];
|
|
687
|
+
const area = args[4];
|
|
688
|
+
this.ospfNetworks.push({ network, wildcard, area });
|
|
689
|
+
return '';
|
|
690
|
+
}
|
|
691
|
+
if (cmd === 'network' || cmd === 'router-id') {
|
|
692
|
+
return '';
|
|
693
|
+
}
|
|
694
|
+
if (cmd === 'passive-interface' || (cmd === 'no' && args[1] === 'passive-interface')) {
|
|
695
|
+
return '';
|
|
696
|
+
}
|
|
697
|
+
return `% Invalid input detected at '^' marker.`;
|
|
698
|
+
}
|
|
699
|
+
if (this.mode === 'RIP_CONFIG' && !isGeneralCommand) {
|
|
700
|
+
if (cmd === 'version' && (args[1] === '1' || args[1] === '2')) {
|
|
701
|
+
this.ripVersion = parseInt(args[1], 10);
|
|
702
|
+
return '';
|
|
703
|
+
}
|
|
704
|
+
if (cmd === 'no' && args[1] === 'auto-summary') {
|
|
705
|
+
this.ripAutoSummary = false;
|
|
706
|
+
return '';
|
|
707
|
+
}
|
|
708
|
+
if (cmd === 'auto-summary') {
|
|
709
|
+
this.ripAutoSummary = true;
|
|
710
|
+
return '';
|
|
711
|
+
}
|
|
712
|
+
if (cmd === 'network' && args[1]) {
|
|
713
|
+
return '';
|
|
714
|
+
}
|
|
715
|
+
if (cmd === 'passive-interface' || (cmd === 'no' && args[1] === 'passive-interface')) {
|
|
716
|
+
return '';
|
|
717
|
+
}
|
|
718
|
+
return `% Invalid input detected at '^' marker.`;
|
|
719
|
+
}
|
|
720
|
+
if (this.mode === 'BGP_CONFIG' && !isGeneralCommand) {
|
|
721
|
+
if (cmd === 'neighbor' && args[1]) {
|
|
722
|
+
return '';
|
|
723
|
+
}
|
|
724
|
+
if (cmd === 'no' && args[1] === 'neighbor' && args[2]) {
|
|
725
|
+
return '';
|
|
726
|
+
}
|
|
727
|
+
if (cmd === 'network' && args[1]) {
|
|
728
|
+
return '';
|
|
729
|
+
}
|
|
730
|
+
if (cmd === 'no' && args[1] === 'auto-summary') {
|
|
731
|
+
return '';
|
|
732
|
+
}
|
|
733
|
+
if (cmd === 'auto-summary') {
|
|
734
|
+
return '';
|
|
735
|
+
}
|
|
736
|
+
if (cmd === 'address-family' && args[1] === 'l2vpn' && args[2] === 'evpn') {
|
|
737
|
+
return '';
|
|
738
|
+
}
|
|
739
|
+
if (cmd === 'send-community') {
|
|
740
|
+
return '';
|
|
741
|
+
}
|
|
742
|
+
return `% Invalid input detected at '^' marker.`;
|
|
743
|
+
}
|
|
744
|
+
if (this.mode === 'VPC_CONFIG' && !isGeneralCommand) {
|
|
745
|
+
if (cmd === 'peer-keepalive' && args[1] === 'destination') {
|
|
746
|
+
this.vpcPeerKeepalive = commandToExecute;
|
|
747
|
+
return '';
|
|
748
|
+
}
|
|
749
|
+
if (cmd === 'system-priority' || cmd === 'role' || cmd === 'peer-gateway' || cmd === 'peer-switch') {
|
|
750
|
+
return '';
|
|
751
|
+
}
|
|
752
|
+
return `% Invalid input detected at '^' marker.`;
|
|
753
|
+
}
|
|
754
|
+
if (this.mode === 'VRF_CONFIG' && this.activeVrf && !isGeneralCommand) {
|
|
755
|
+
const vrf = this.vrfs.get(this.activeVrf);
|
|
756
|
+
if (cmd === 'vni' && args[1]) {
|
|
757
|
+
vrf.vni = parseInt(args[1], 10);
|
|
758
|
+
return '';
|
|
759
|
+
}
|
|
760
|
+
if (cmd === 'rd' && args[1]) {
|
|
761
|
+
vrf.rd = args.slice(1).join(' ');
|
|
762
|
+
return '';
|
|
763
|
+
}
|
|
764
|
+
if (cmd === 'address-family' && args[1] === 'ipv4' && args[2] === 'unicast') {
|
|
765
|
+
this.mode = 'VRF_AF_CONFIG';
|
|
766
|
+
return '';
|
|
767
|
+
}
|
|
768
|
+
return `% Invalid input detected at '^' marker.`;
|
|
769
|
+
}
|
|
770
|
+
if (this.mode === 'VRF_AF_CONFIG' && this.activeVrf && !isGeneralCommand) {
|
|
771
|
+
const vrf = this.vrfs.get(this.activeVrf);
|
|
772
|
+
if (cmd === 'route-target' && args[1] === 'both' && args[2]) {
|
|
773
|
+
vrf.routeTargets.push(args.slice(1).join(' '));
|
|
774
|
+
return '';
|
|
775
|
+
}
|
|
776
|
+
return `% Invalid input detected at '^' marker.`;
|
|
777
|
+
}
|
|
778
|
+
if (this.mode === 'EIGRP_CONFIG' && !isGeneralCommand) {
|
|
779
|
+
if (cmd === 'network' && args[1]) {
|
|
780
|
+
return '';
|
|
781
|
+
}
|
|
782
|
+
if (cmd === 'no' && args[1] === 'auto-summary') {
|
|
783
|
+
return '';
|
|
784
|
+
}
|
|
785
|
+
if (cmd === 'auto-summary') {
|
|
786
|
+
return '';
|
|
787
|
+
}
|
|
788
|
+
if (cmd === 'passive-interface' || (cmd === 'no' && args[1] === 'passive-interface')) {
|
|
789
|
+
return '';
|
|
790
|
+
}
|
|
791
|
+
return `% Invalid input detected at '^' marker.`;
|
|
792
|
+
}
|
|
793
|
+
if (this.mode === 'DHCP_CONFIG' && !isGeneralCommand) {
|
|
794
|
+
if (cmd === 'network' || cmd === 'default-router' || cmd === 'dns-server') {
|
|
795
|
+
return '';
|
|
796
|
+
}
|
|
797
|
+
return `% Invalid input detected at '^' marker.`;
|
|
798
|
+
}
|
|
799
|
+
if (this.mode === 'ACL_CONFIG' && !isGeneralCommand) {
|
|
800
|
+
if (cmd === 'permit' || cmd === 'deny') {
|
|
801
|
+
return '';
|
|
802
|
+
}
|
|
803
|
+
return `% Invalid input detected at '^' marker.`;
|
|
804
|
+
}
|
|
805
|
+
if (isShow) {
|
|
806
|
+
const showArgs = cmd === 'do' ? args.slice(2) : args.slice(1);
|
|
807
|
+
const showCmd = showArgs[0]?.toLowerCase();
|
|
808
|
+
if (showCmd === 'vpc') {
|
|
809
|
+
const domainId = this.vpcDomainId || 10;
|
|
810
|
+
const peerStatus = this.vpcPeerKeepalive ? 'peer adjacency formed ok' : 'peer link not configured';
|
|
811
|
+
const keepaliveStatus = this.vpcPeerKeepalive ? 'peer is alive' : 'peer keep-alive not configured';
|
|
812
|
+
return `Legend:
|
|
813
|
+
(*) - local vPC is down, dynamic backup loop preventer
|
|
814
|
+
|
|
815
|
+
vPC domain id : ${domainId}
|
|
816
|
+
Peer status : ${peerStatus}
|
|
817
|
+
vPC keep-alive status : ${keepaliveStatus}
|
|
818
|
+
Configuration-consistency status : success
|
|
819
|
+
Per-vlan consistency status : success
|
|
820
|
+
Type-2 consistency status : success
|
|
821
|
+
vPC role : primary
|
|
822
|
+
Number of vPCs configured : ${Array.from(this.interfaces.values()).filter(i => i.vpcMemberId !== undefined).length}
|
|
823
|
+
Peer Gateway : Enabled
|
|
824
|
+
`;
|
|
825
|
+
}
|
|
826
|
+
if (showCmd === 'nve' && showArgs[1] === 'interface') {
|
|
827
|
+
const nveIface = Array.from(this.interfaces.values()).find(i => i.name.toLowerCase().startsWith('nve'));
|
|
828
|
+
if (!nveIface) {
|
|
829
|
+
return '% NVE interface is not configured';
|
|
830
|
+
}
|
|
831
|
+
const sourceInt = nveIface.sourceInterface || 'Loopback0';
|
|
832
|
+
return `Interface: ${nveIface.name}, State: Up, Encapsulation: VXLAN
|
|
833
|
+
Source-Interface: ${sourceInt} (10.0.0.1)
|
|
834
|
+
`;
|
|
835
|
+
}
|
|
836
|
+
if (showCmd === 'nve' && showArgs[1] === 'vni') {
|
|
837
|
+
const nveIface = Array.from(this.interfaces.values()).find(i => i.name.toLowerCase().startsWith('nve'));
|
|
838
|
+
if (!nveIface || !nveIface.memberVnis) {
|
|
839
|
+
return `Interface VNI Multicast-group State Mode vPC Dev\n` +
|
|
840
|
+
`--------- -------- ----------------- ----- ---- -------\n`;
|
|
841
|
+
}
|
|
842
|
+
let out = `Interface VNI Multicast-group State Mode vPC Dev\n` +
|
|
843
|
+
`--------- -------- ----------------- ----- ---- -------\n`;
|
|
844
|
+
for (const [vni, details] of nveIface.memberVnis.entries()) {
|
|
845
|
+
const mcast = details.mcastGroup || 'n/a';
|
|
846
|
+
out += `${nveIface.name.padEnd(9)} ${vni.toString().padEnd(8)} ${mcast.padEnd(17)} Up CP n/a\n`;
|
|
847
|
+
}
|
|
848
|
+
return out;
|
|
849
|
+
}
|
|
850
|
+
if (showCmd === 'bgp' && showArgs[1] === 'l2vpn' && showArgs[2] === 'evpn' && showArgs[3] === 'summary') {
|
|
851
|
+
const bgpAs = this.bgpAsn || '65000';
|
|
852
|
+
return `BGP summary information for VRF default, address family L2VPN EVPN
|
|
853
|
+
BGP router identifier 10.0.0.1, local AS number ${bgpAs}
|
|
854
|
+
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
|
|
855
|
+
10.0.0.2 4 ${bgpAs} 120 125 47 0 0 01:24:55 2
|
|
856
|
+
`;
|
|
857
|
+
}
|
|
858
|
+
if (showCmd === 'version' || showCmd === 'ver') {
|
|
859
|
+
return `Cisco IOS Software, C2960 Software (C2960-LANBASEK9-M), Version 15.0(2)SE4, RELEASE SOFTWARE (fc1)
|
|
860
|
+
Technical Support: http://www.cisco.com/techsupport
|
|
861
|
+
Copyright (c) 1986-2013 by Cisco Systems, Inc.
|
|
862
|
+
Compiled Wed 26-Jun-13 02:49 by prod_rel_team
|
|
863
|
+
|
|
864
|
+
ROM: Bootstrap program is 12.2(44)SE Version
|
|
865
|
+
BOOTLDR: C2960 Boot Loader (C2960-HBOOT-M) Version 12.2(44)SE, RELEASE SOFTWARE (fc1)
|
|
866
|
+
|
|
867
|
+
Switch1 uptime is 2 hours, 15 minutes
|
|
868
|
+
System returned to ROM by power-on
|
|
869
|
+
System image file is "flash:/c2960-lanbasek9-mz.150-2.SE4.bin"
|
|
870
|
+
|
|
871
|
+
This product contains cryptographic features and is subject to Y...
|
|
872
|
+
`;
|
|
873
|
+
}
|
|
874
|
+
if (showCmd === 'ip' && showArgs[1]?.startsWith('int') && showArgs[2]?.startsWith('br')) {
|
|
875
|
+
let out = 'Interface IP-Address OK? Method Status Protocol\n';
|
|
876
|
+
for (const [name, status] of this.interfaces.entries()) {
|
|
877
|
+
const ip = status.ip || 'unassigned';
|
|
878
|
+
const method = status.ip ? 'manual' : 'unset';
|
|
879
|
+
const adminStatus = status.adminShutdown ? 'administratively down' : 'up';
|
|
880
|
+
const protocolStatus = status.lineProtocolUp ? 'up' : 'down';
|
|
881
|
+
out += `${name.padEnd(26)} ${ip.padEnd(15)} YES ${method.padEnd(6)} ${adminStatus.padEnd(21)} ${protocolStatus}\n`;
|
|
882
|
+
}
|
|
883
|
+
return out;
|
|
884
|
+
}
|
|
885
|
+
if (showCmd?.startsWith('run')) {
|
|
886
|
+
let out = `Building configuration...\n\nCurrent configuration : 1542 bytes\n!\nversion 15.0\n!\nhostname ${this.hostname}\n!\n`;
|
|
887
|
+
for (const [name, status] of this.interfaces.entries()) {
|
|
888
|
+
out += `interface ${name}\n`;
|
|
889
|
+
if (status.description) {
|
|
890
|
+
out += ` description ${status.description}\n`;
|
|
891
|
+
}
|
|
892
|
+
if (status.isSwitchport) {
|
|
893
|
+
out += ` switchport\n`;
|
|
894
|
+
if (status.switchportMode) {
|
|
895
|
+
out += ` switchport mode ${status.switchportMode}\n`;
|
|
896
|
+
}
|
|
897
|
+
if (status.vlan) {
|
|
898
|
+
out += ` switchport access vlan ${status.vlan}\n`;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
if (status.ip) {
|
|
902
|
+
out += ` ip address ${status.ip} ${status.subnet}\n`;
|
|
903
|
+
}
|
|
904
|
+
if (status.adminShutdown) {
|
|
905
|
+
out += ` shutdown\n`;
|
|
906
|
+
}
|
|
907
|
+
out += `!\n`;
|
|
908
|
+
}
|
|
909
|
+
for (const r of this.routes) {
|
|
910
|
+
if (!r.connected) {
|
|
911
|
+
out += `ip route ${r.network} ${r.mask} ${r.nextHop || r.outgoingInterface}\n`;
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
if (this.ospfEnabled) {
|
|
915
|
+
out += `router ospf ${this.ospfProcessId || '10'}\n`;
|
|
916
|
+
for (const net of this.ospfNetworks) {
|
|
917
|
+
out += ` network ${net.network} ${net.wildcard} area ${net.area}\n`;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
out += `!\nend\n`;
|
|
921
|
+
return out;
|
|
922
|
+
}
|
|
923
|
+
if (showCmd === 'ip' && showArgs[1] === 'protocols') {
|
|
924
|
+
let out = '';
|
|
925
|
+
if (this.ospfEnabled) {
|
|
926
|
+
out += `Routing Protocol is "ospf ${this.ospfProcessId || '10'}"\n` +
|
|
927
|
+
` Outgoing update filter list for all interfaces is not set\n` +
|
|
928
|
+
` Incoming update filter list for all interfaces is not set\n` +
|
|
929
|
+
` Router ID 192.168.1.254\n` +
|
|
930
|
+
` Number of areas in this router is 1. 1 normal 0 stub 0 nssa\n` +
|
|
931
|
+
` Routing for Networks:\n`;
|
|
932
|
+
if (this.ospfNetworks.length > 0) {
|
|
933
|
+
for (const net of this.ospfNetworks) {
|
|
934
|
+
out += ` ${net.network}/${this.getPrefixLength(this.wildcardToSubnet(net.wildcard))} area ${net.area}\n`;
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
else {
|
|
938
|
+
out += ` 192.168.1.0/24 area 0\n`;
|
|
939
|
+
}
|
|
940
|
+
out += ` Routing Information Sources:\n` +
|
|
941
|
+
` Gateway Distance Last Update\n` +
|
|
942
|
+
` Distance: (default is 110)\n\n`;
|
|
943
|
+
}
|
|
944
|
+
if (this.ripEnabled) {
|
|
945
|
+
out += `Routing Protocol is "rip"\n` +
|
|
946
|
+
` Sending updates every 30 seconds, next due in 15 seconds\n` +
|
|
947
|
+
` Invalid 180 seconds, hold down 180, flushed 240\n` +
|
|
948
|
+
` Outgoing update filter list for all interfaces is not set\n` +
|
|
949
|
+
` Incoming update filter list for all interfaces is not set\n` +
|
|
950
|
+
` Redistributing: rip\n` +
|
|
951
|
+
` Default version control: send version ${this.ripVersion}, receive version ${this.ripVersion}\n` +
|
|
952
|
+
` Interface Send Recv Triggered RIP Key-chain\n`;
|
|
953
|
+
for (const name of this.interfaces.keys()) {
|
|
954
|
+
out += ` ${name.padEnd(21)} ${this.ripVersion} ${this.ripVersion}\n`;
|
|
955
|
+
}
|
|
956
|
+
out += ` Automatic network summarization is ${this.ripAutoSummary ? 'in effect' : 'not in effect'}\n` +
|
|
957
|
+
` Maximum path: 4\n` +
|
|
958
|
+
` Routing for Networks:\n` +
|
|
959
|
+
` 192.168.1.0\n` +
|
|
960
|
+
` Routing Information Sources:\n` +
|
|
961
|
+
` Gateway Distance Last Update\n` +
|
|
962
|
+
` Distance: (default is 120)\n\n`;
|
|
963
|
+
}
|
|
964
|
+
if (this.bgpEnabled) {
|
|
965
|
+
out += `Routing Protocol is "bgp ${this.bgpAsn || '65000'}"\n` +
|
|
966
|
+
` Outgoing update filter list for all interfaces is not set\n` +
|
|
967
|
+
` Incoming update filter list for all interfaces is not set\n` +
|
|
968
|
+
` IGP synchronization is disabled\n` +
|
|
969
|
+
` Automatic route summarization is disabled\n` +
|
|
970
|
+
` Routing Information Sources:\n` +
|
|
971
|
+
` Gateway Distance Last Update\n` +
|
|
972
|
+
` Distance: external 20 internal 200 local 200\n\n`;
|
|
973
|
+
}
|
|
974
|
+
if (this.eigrpEnabled) {
|
|
975
|
+
out += `Routing Protocol is "eigrp ${this.eigrpAsn || '100'}"\n` +
|
|
976
|
+
` Outgoing update filter list for all interfaces is not set\n` +
|
|
977
|
+
` Incoming update filter list for all interfaces is not set\n` +
|
|
978
|
+
` Default networks being advertised:\n` +
|
|
979
|
+
` 192.168.1.0\n` +
|
|
980
|
+
` EIGRP-IPv4 Protocol for AS(${this.eigrpAsn || '100'})\n` +
|
|
981
|
+
` Metric weight K1=1, K2=0, K3=1, K4=0, K5=0\n` +
|
|
982
|
+
` NSF-aware route hold timer is 240s\n` +
|
|
983
|
+
` Router-ID: 192.168.1.254\n` +
|
|
984
|
+
` Topology Kisspoint limit: 100\n` +
|
|
985
|
+
` Routing Information Sources:\n` +
|
|
986
|
+
` Gateway Distance Last Update\n` +
|
|
987
|
+
` Distance: internal 90 external 170\n\n`;
|
|
988
|
+
}
|
|
989
|
+
if (!out) {
|
|
990
|
+
out = '*** No routing protocols configured ***\n';
|
|
991
|
+
}
|
|
992
|
+
return out;
|
|
993
|
+
}
|
|
994
|
+
if (showCmd === 'ip' && showArgs[1]?.startsWith('ro')) {
|
|
995
|
+
if (!this.ipRoutingEnabled) {
|
|
996
|
+
return '% IP routing table is not enabled';
|
|
997
|
+
}
|
|
998
|
+
let out = `Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP\n\n`;
|
|
999
|
+
out += `Gateway of last resort is not set\n\n`;
|
|
1000
|
+
for (const r of this.routes) {
|
|
1001
|
+
if (r.connected && r.outgoingInterface) {
|
|
1002
|
+
const iface = this.interfaces.get(r.outgoingInterface);
|
|
1003
|
+
if (iface && iface.adminShutdown) {
|
|
1004
|
+
continue;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
const code = r.connected ? 'C' : 'S';
|
|
1008
|
+
const target = r.nextHop ? `via ${r.nextHop}` : `directly connected, ${r.outgoingInterface || 'Null0'}`;
|
|
1009
|
+
out += `${code} ${r.network}/${this.getPrefixLength(r.mask)} is ${target}\n`;
|
|
1010
|
+
}
|
|
1011
|
+
return out;
|
|
1012
|
+
}
|
|
1013
|
+
if (showCmd === 'ip' && showArgs[1] === 'ospf' && showArgs[2]?.startsWith('ne')) {
|
|
1014
|
+
if (!this.ospfEnabled) {
|
|
1015
|
+
return '% OSPF is not enabled';
|
|
1016
|
+
}
|
|
1017
|
+
return `Neighbor ID Pri State Dead Time Address Interface\n` +
|
|
1018
|
+
`2.2.2.2 1 FULL/DR 00:00:35 192.168.1.2 GigabitEthernet0/0\n`;
|
|
1019
|
+
}
|
|
1020
|
+
if (showCmd === 'ip' && showArgs[1] === 'ospf' && showArgs[2]?.startsWith('in')) {
|
|
1021
|
+
if (!this.ospfEnabled) {
|
|
1022
|
+
return '% OSPF is not enabled';
|
|
1023
|
+
}
|
|
1024
|
+
return `GigabitEthernet0/0 is up, line protocol is up \n` +
|
|
1025
|
+
` Internet Address 192.168.1.254/24, Area 0 \n` +
|
|
1026
|
+
` Process ID ${this.ospfProcessId || '10'}, Router ID 192.168.1.254, Network Type BROADCAST, Cost: 1\n`;
|
|
1027
|
+
}
|
|
1028
|
+
if (showCmd === 'ip' && showArgs[1] === 'ospf' && !showArgs[2]) {
|
|
1029
|
+
if (!this.ospfEnabled) {
|
|
1030
|
+
return '% OSPF is not enabled';
|
|
1031
|
+
}
|
|
1032
|
+
return ` Routing Process "ospf ${this.ospfProcessId || '10'}" with ID 192.168.1.254\n` +
|
|
1033
|
+
` Supports only single TOS(TOS0) routes\n` +
|
|
1034
|
+
` Supports opaque LSA\n`;
|
|
1035
|
+
}
|
|
1036
|
+
if (showCmd?.startsWith('vl') && (showArgs[1]?.startsWith('br') || !showArgs[1])) {
|
|
1037
|
+
let out = 'VLAN Name Status Ports\n';
|
|
1038
|
+
out += '---- -------------------------------- --------- -------------------------------\n';
|
|
1039
|
+
for (const vid of this.vlans) {
|
|
1040
|
+
const name = this.vlanNames.get(vid) || `VLAN${vid.toString().padStart(4, '0')}`;
|
|
1041
|
+
const ports = Array.from(this.interfaces.values())
|
|
1042
|
+
.filter(iface => iface.vlan === vid)
|
|
1043
|
+
.map(iface => this.shortenInterfaceName(iface.name))
|
|
1044
|
+
.join(', ');
|
|
1045
|
+
out += `${vid.toString().padEnd(4)} ${name.padEnd(32)} active ${ports}\n`;
|
|
1046
|
+
}
|
|
1047
|
+
return out;
|
|
1048
|
+
}
|
|
1049
|
+
if (showCmd === 'cdp' && showArgs[1]?.startsWith('ne')) {
|
|
1050
|
+
return `Capability Codes: R - Router, T - Trans Bridge, B - Source Route Bridge
|
|
1051
|
+
S - Switch, H - Host, I - IGMP, r - Repeater, P - Phone
|
|
1052
|
+
|
|
1053
|
+
Device ID Local Intrfce Holdtme Capability Platform Port ID
|
|
1054
|
+
Switch2 Gig 0/1 125 S I WS-C2960- Gig 0/1
|
|
1055
|
+
`;
|
|
1056
|
+
}
|
|
1057
|
+
if (showCmd === 'vtp' && showArgs[1] === 'status') {
|
|
1058
|
+
return `VTP Version capability : 1 to 3\n` +
|
|
1059
|
+
`VTP version running : 1\n` +
|
|
1060
|
+
`VTP Operating Mode : ${this.vtpMode}\n` +
|
|
1061
|
+
`VTP Domain Name : ${this.vtpDomain || ''}\n` +
|
|
1062
|
+
`VTP Pruning Mode : Disabled\n` +
|
|
1063
|
+
`VTP V2 Mode : Disabled\n` +
|
|
1064
|
+
`VTP Traps Generation : Disabled\n` +
|
|
1065
|
+
`MD5 digest : 0x94 0xC2 0x6E 0x93 0xA3 0xE2 0xD4 0xFA \n` +
|
|
1066
|
+
`Configuration last modified by 0.0.0.0 at 0-0-00 00:00:00\n`;
|
|
1067
|
+
}
|
|
1068
|
+
if (showCmd === 'standby' && (showArgs[1] === 'brief' || !showArgs[1])) {
|
|
1069
|
+
let out = ' Preempt State Active Standby Virtual IP\n';
|
|
1070
|
+
for (const [group, hsrp] of this.hsrpGroups.entries()) {
|
|
1071
|
+
out += `Gi0/1 ${group.padEnd(6)} ${hsrp.priority.toString().padEnd(4)} ${hsrp.preempt ? 'P' : ' '} Active local unknown ${hsrp.virtualIp}\n`;
|
|
1072
|
+
}
|
|
1073
|
+
if (this.hsrpGroups.size === 0) {
|
|
1074
|
+
out = '*** No HSRP standby groups configured ***\n';
|
|
1075
|
+
}
|
|
1076
|
+
return out;
|
|
1077
|
+
}
|
|
1078
|
+
if (showCmd === 'vrrp' && (showArgs[1] === 'brief' || !showArgs[1])) {
|
|
1079
|
+
let out = 'Interface Grp Fip Pri Time Own Pre State Master addr Group addr\n';
|
|
1080
|
+
for (const [group, vrrp] of this.vrrpGroups.entries()) {
|
|
1081
|
+
out += `Gi0/1 ${group.padEnd(4)} 1 ${vrrp.priority.toString().padEnd(3)} 3.609 N Y Master local ${vrrp.virtualIp}\n`;
|
|
1082
|
+
}
|
|
1083
|
+
if (this.vrrpGroups.size === 0) {
|
|
1084
|
+
out = '*** No VRRP groups configured ***\n';
|
|
1085
|
+
}
|
|
1086
|
+
return out;
|
|
1087
|
+
}
|
|
1088
|
+
if (showCmd === 'ip' && showArgs[1] === 'nat' && showArgs[2] === 'translations') {
|
|
1089
|
+
let out = 'Pro Inside global Inside local Outside local Outside global\n';
|
|
1090
|
+
for (const rule of this.natRules) {
|
|
1091
|
+
out += `tcp 192.0.2.1:80 192.168.1.10:80 --- ---\n`;
|
|
1092
|
+
}
|
|
1093
|
+
if (this.natRules.length === 0) {
|
|
1094
|
+
out = '*** No NAT translations active ***\n';
|
|
1095
|
+
}
|
|
1096
|
+
return out;
|
|
1097
|
+
}
|
|
1098
|
+
if (showCmd === 'access-lists') {
|
|
1099
|
+
let out = '';
|
|
1100
|
+
for (const [aclId, rules] of this.acls.entries()) {
|
|
1101
|
+
out += `Standard IP access list ${aclId}\n`;
|
|
1102
|
+
rules.forEach((rule, idx) => {
|
|
1103
|
+
out += ` ${(idx + 1) * 10} ${rule}\n`;
|
|
1104
|
+
});
|
|
1105
|
+
}
|
|
1106
|
+
if (this.acls.size === 0) {
|
|
1107
|
+
out = '*** No access lists configured ***\n';
|
|
1108
|
+
}
|
|
1109
|
+
return out;
|
|
1110
|
+
}
|
|
1111
|
+
if (showCmd === 'ntp' && (showArgs[1] === 'status' || showArgs[1] === 'associations')) {
|
|
1112
|
+
if (this.ntpServers.length === 0) {
|
|
1113
|
+
return 'NTP is not enabled.\n';
|
|
1114
|
+
}
|
|
1115
|
+
let out = 'Clock is synchronized, stratum 2, reference is ' + this.ntpServers[0] + '\n';
|
|
1116
|
+
out += 'nominal freq is 250.0000 Hz, actual freq is 250.0000 Hz, precision is 2**24\n';
|
|
1117
|
+
return out;
|
|
1118
|
+
}
|
|
1119
|
+
if (showCmd === 'lldp' && showArgs[1]?.startsWith('ne')) {
|
|
1120
|
+
return `Device ID Local Intf Hold-time Capability Port ID
|
|
1121
|
+
Switch2 Gi0/1 120 S Gi0/1
|
|
1122
|
+
Total entries displayed: 1
|
|
1123
|
+
`;
|
|
1124
|
+
}
|
|
1125
|
+
if (showCmd === 'interfaces' && showArgs[1] === 'status') {
|
|
1126
|
+
return `Port Name Status Vlan Duplex Speed Type
|
|
1127
|
+
Gi0/0 Management Uplink connected routed a-full a-1000 10/100/1000BaseTX
|
|
1128
|
+
Gi0/1 disabled 1 auto auto 10/100/1000BaseTX
|
|
1129
|
+
Gi0/2 disabled 1 auto auto 10/100/1000BaseTX
|
|
1130
|
+
`;
|
|
1131
|
+
}
|
|
1132
|
+
return `% Unrecognized show command: show ${showArgs.join(' ')}`;
|
|
1133
|
+
}
|
|
1134
|
+
if (cmd === 'write' || cmd === 'wr') {
|
|
1135
|
+
return `Building configuration...\n[OK]`;
|
|
1136
|
+
}
|
|
1137
|
+
if (cmd === 'copy' && args[1]?.startsWith('run') && args[2]?.startsWith('sta')) {
|
|
1138
|
+
return `Destination filename [startup-config]? \nBuilding configuration...\n[OK]`;
|
|
1139
|
+
}
|
|
1140
|
+
if (cmd === 'copy' && args[1]?.startsWith('run') && args[2]?.startsWith('flash:')) {
|
|
1141
|
+
const destFile = args[2].replace(/^flash:/i, '');
|
|
1142
|
+
this.pendingCopyDest = destFile || 'backup-agent.cfg';
|
|
1143
|
+
return `Destination filename [${this.pendingCopyDest}]? `;
|
|
1144
|
+
}
|
|
1145
|
+
if (cmd === 'dir' && args[1] === 'flash:') {
|
|
1146
|
+
let out = `Directory of flash:/\n\n`;
|
|
1147
|
+
let index = 1;
|
|
1148
|
+
let totalBytesUsed = 0;
|
|
1149
|
+
out += ` ${index++} -rw- 4414921 Mar 01 1993 00:02:18 +00:00 c2960-lanbasek9-mz.150-2.SE4.bin\n`;
|
|
1150
|
+
totalBytesUsed += 4414921;
|
|
1151
|
+
if (this.flashFiles.has('backup-agent.cfg')) {
|
|
1152
|
+
out += ` ${index++} -rw- 1542 May 31 2026 12:24:17 +00:00 backup-agent.cfg\n`;
|
|
1153
|
+
totalBytesUsed += 1542;
|
|
1154
|
+
}
|
|
1155
|
+
const totalBytes = 32514048;
|
|
1156
|
+
const freeBytes = totalBytes - totalBytesUsed;
|
|
1157
|
+
out += `\n${totalBytes} bytes total (${freeBytes} bytes free)\n`;
|
|
1158
|
+
return out;
|
|
1159
|
+
}
|
|
1160
|
+
if (cmd === 'configure' && args[1] === 'replace' && args[2]?.startsWith('flash:')) {
|
|
1161
|
+
const file = args[2].replace(/^flash:/i, '');
|
|
1162
|
+
if (!this.flashFiles.has(file)) {
|
|
1163
|
+
return `% Error opening flash:${file} (No such file or directory)`;
|
|
1164
|
+
}
|
|
1165
|
+
this.restoreBackupState();
|
|
1166
|
+
return `Total number of passes: 1\nRollback Done\n`;
|
|
1167
|
+
}
|
|
1168
|
+
if (cmd === 'ping' && args[1]) {
|
|
1169
|
+
const ip = args[1];
|
|
1170
|
+
return `Sending 5, 100-byte ICMP Echos to ${ip}, timeout is 2 seconds:
|
|
1171
|
+
!!!!!
|
|
1172
|
+
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/1/4 ms
|
|
1173
|
+
`;
|
|
1174
|
+
}
|
|
1175
|
+
if (cmd === 'test' && args[1] === 'trigger-syslog') {
|
|
1176
|
+
const msgText = args.slice(2).join(' ');
|
|
1177
|
+
BaseDevice_1.simulatorEvents.emit('syslog', msgText);
|
|
1178
|
+
return `[Simulator Test] Triggered syslog: ${msgText}`;
|
|
1179
|
+
}
|
|
1180
|
+
return `% Unrecognized command: ${trimmed}`;
|
|
1181
|
+
}
|
|
1182
|
+
normalizeCommandString(line) {
|
|
1183
|
+
const trimmed = line.trim();
|
|
1184
|
+
if (!trimmed)
|
|
1185
|
+
return '';
|
|
1186
|
+
if (trimmed.toLowerCase().startsWith('do ')) {
|
|
1187
|
+
const rest = trimmed.substring(3);
|
|
1188
|
+
return 'do ' + this.normalizeCommandString(rest);
|
|
1189
|
+
}
|
|
1190
|
+
const parts = trimmed.split(/\s+/);
|
|
1191
|
+
if (parts.length === 0 || !parts[0])
|
|
1192
|
+
return trimmed;
|
|
1193
|
+
let cmd = parts[0].toLowerCase();
|
|
1194
|
+
if (cmd === 'conf' || cmd === 'config' || cmd === 'configure') {
|
|
1195
|
+
parts[0] = 'configure';
|
|
1196
|
+
if (parts[1] && (parts[1].toLowerCase() === 't' || parts[1].toLowerCase() === 'term' || parts[1].toLowerCase() === 'terminal')) {
|
|
1197
|
+
parts[1] = 'terminal';
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
else if (cmd === 'int' || cmd === 'inter' || cmd === 'interface') {
|
|
1201
|
+
parts[0] = 'interface';
|
|
1202
|
+
if (parts[1]) {
|
|
1203
|
+
parts[1] = this.normalizeInterfaceName(parts[1]);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
else if (cmd === 'sh' || cmd === 'sho' || cmd === 'show') {
|
|
1207
|
+
parts[0] = 'show';
|
|
1208
|
+
}
|
|
1209
|
+
else if (cmd === 'en' || cmd === 'ena' || cmd === 'enab' || cmd === 'enable') {
|
|
1210
|
+
parts[0] = 'enable';
|
|
1211
|
+
}
|
|
1212
|
+
else if (cmd === 'di' || cmd === 'dis' || cmd === 'disa' || cmd === 'disable') {
|
|
1213
|
+
parts[0] = 'disable';
|
|
1214
|
+
}
|
|
1215
|
+
else if (cmd === 'ex' || cmd === 'exi' || cmd === 'exit') {
|
|
1216
|
+
parts[0] = 'exit';
|
|
1217
|
+
}
|
|
1218
|
+
else if (cmd === 'end') {
|
|
1219
|
+
parts[0] = 'end';
|
|
1220
|
+
}
|
|
1221
|
+
else if (cmd === 'wr' || cmd === 'wri' || cmd === 'write') {
|
|
1222
|
+
parts[0] = 'write';
|
|
1223
|
+
}
|
|
1224
|
+
else if (cmd === 'p' || cmd === 'pi' || cmd === 'pin' || cmd === 'ping') {
|
|
1225
|
+
parts[0] = 'ping';
|
|
1226
|
+
}
|
|
1227
|
+
else if (cmd === 'net' || cmd === 'network') {
|
|
1228
|
+
parts[0] = 'network';
|
|
1229
|
+
}
|
|
1230
|
+
else if (cmd === 'sw' || cmd === 'swit' || cmd === 'switch' || cmd === 'switchport') {
|
|
1231
|
+
parts[0] = 'switchport';
|
|
1232
|
+
}
|
|
1233
|
+
else if (cmd === 'no') {
|
|
1234
|
+
if (parts.length > 1) {
|
|
1235
|
+
const normalizedSub = this.normalizeCommandString(parts.slice(1).join(' '));
|
|
1236
|
+
return 'no ' + normalizedSub;
|
|
1237
|
+
}
|
|
1238
|
+
return trimmed;
|
|
1239
|
+
}
|
|
1240
|
+
cmd = parts[0].toLowerCase();
|
|
1241
|
+
if (cmd === 'show') {
|
|
1242
|
+
if (parts[1]) {
|
|
1243
|
+
const sub = parts[1].toLowerCase();
|
|
1244
|
+
if (sub === 'ru' || sub === 'run' || sub === 'runn' || sub === 'running' || sub === 'running-config') {
|
|
1245
|
+
parts[1] = 'running-config';
|
|
1246
|
+
}
|
|
1247
|
+
else if (sub === 'vl' || sub === 'vla' || sub === 'vlan') {
|
|
1248
|
+
parts[1] = 'vlan';
|
|
1249
|
+
}
|
|
1250
|
+
else if (sub === 'ip') {
|
|
1251
|
+
if (parts[2]) {
|
|
1252
|
+
const sub2 = parts[2].toLowerCase();
|
|
1253
|
+
if (sub2 === 'ro' || sub2 === 'rou' || sub2 === 'rout' || sub2 === 'route') {
|
|
1254
|
+
parts[2] = 'route';
|
|
1255
|
+
}
|
|
1256
|
+
else if (sub2 === 'int' || sub2 === 'inter' || sub2 === 'interface') {
|
|
1257
|
+
parts[2] = 'interface';
|
|
1258
|
+
if (parts[3] && (parts[3].toLowerCase() === 'br' || parts[3].toLowerCase() === 'brief')) {
|
|
1259
|
+
parts[3] = 'brief';
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
else if (sub2 === 'ospf') {
|
|
1263
|
+
if (parts[3]) {
|
|
1264
|
+
const sub3 = parts[3].toLowerCase();
|
|
1265
|
+
if (sub3 === 'ne' || sub3 === 'nei' || sub3 === 'neig' || sub3 === 'neigh' || sub3 === 'neighbor') {
|
|
1266
|
+
parts[3] = 'neighbor';
|
|
1267
|
+
}
|
|
1268
|
+
else if (sub3 === 'in' || sub3 === 'int' || sub3 === 'interface') {
|
|
1269
|
+
parts[3] = 'interface';
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
else if (cmd === 'ip') {
|
|
1278
|
+
if (parts[1]) {
|
|
1279
|
+
const sub = parts[1].toLowerCase();
|
|
1280
|
+
if (sub === 'add' || sub === 'addr' || sub === 'address') {
|
|
1281
|
+
parts[1] = 'address';
|
|
1282
|
+
}
|
|
1283
|
+
else if (sub === 'ro' || sub === 'rou' || sub === 'rout' || sub === 'route') {
|
|
1284
|
+
parts[1] = 'route';
|
|
1285
|
+
}
|
|
1286
|
+
else if (sub === 'routing') {
|
|
1287
|
+
parts[1] = 'routing';
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
else if (cmd === 'router') {
|
|
1292
|
+
if (parts[1]) {
|
|
1293
|
+
const sub = parts[1].toLowerCase();
|
|
1294
|
+
if (sub === 'os' || sub === 'osp' || sub === 'ospf') {
|
|
1295
|
+
parts[1] = 'ospf';
|
|
1296
|
+
}
|
|
1297
|
+
else if (sub === 'ri' || sub === 'rip') {
|
|
1298
|
+
parts[1] = 'rip';
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
else if (cmd === 'shutdown' || cmd === 'shut') {
|
|
1303
|
+
parts[0] = 'shutdown';
|
|
1304
|
+
}
|
|
1305
|
+
else if (cmd === 'description' || cmd === 'desc') {
|
|
1306
|
+
parts[0] = 'description';
|
|
1307
|
+
}
|
|
1308
|
+
else if (cmd === 'switchport') {
|
|
1309
|
+
if (parts[1]) {
|
|
1310
|
+
const sub1 = parts[1].toLowerCase();
|
|
1311
|
+
if (sub1 === 'mo' || sub1 === 'mod' || sub1 === 'mode') {
|
|
1312
|
+
parts[1] = 'mode';
|
|
1313
|
+
if (parts[2]) {
|
|
1314
|
+
const sub2 = parts[2].toLowerCase();
|
|
1315
|
+
if (sub2 === 'ac' || sub2 === 'acc' || sub2 === 'access') {
|
|
1316
|
+
parts[2] = 'access';
|
|
1317
|
+
}
|
|
1318
|
+
else if (sub2 === 'tr' || sub2 === 'tru' || sub2 === 'trun' || sub2 === 'trunk') {
|
|
1319
|
+
parts[2] = 'trunk';
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
else if (sub1 === 'ac' || sub1 === 'acc' || sub1 === 'access') {
|
|
1324
|
+
parts[1] = 'access';
|
|
1325
|
+
if (parts[2]) {
|
|
1326
|
+
const sub2 = parts[2].toLowerCase();
|
|
1327
|
+
if (sub2 === 'vl' || sub2 === 'vla' || sub2 === 'vlan') {
|
|
1328
|
+
parts[2] = 'vlan';
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
else if (sub1 === 'tr' || sub1 === 'tru' || sub1 === 'trun' || sub1 === 'trunk') {
|
|
1333
|
+
parts[1] = 'trunk';
|
|
1334
|
+
if (parts[2]) {
|
|
1335
|
+
const sub2 = parts[2].toLowerCase();
|
|
1336
|
+
if (sub2 === 'al' || sub2 === 'all' || sub2 === 'allow' || sub2 === 'allowed') {
|
|
1337
|
+
parts[2] = 'allowed';
|
|
1338
|
+
if (parts[3] && (parts[3].toLowerCase() === 'vl' || parts[3].toLowerCase() === 'vla' || parts[3].toLowerCase() === 'vlan')) {
|
|
1339
|
+
parts[3] = 'vlan';
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
return parts.join(' ');
|
|
1347
|
+
}
|
|
1348
|
+
normalizeInterfaceName(name) {
|
|
1349
|
+
const lower = name.toLowerCase();
|
|
1350
|
+
if (lower.startsWith('gigabitethernet')) {
|
|
1351
|
+
return 'GigabitEthernet' + name.substring(15);
|
|
1352
|
+
}
|
|
1353
|
+
if (lower.startsWith('gig')) {
|
|
1354
|
+
return 'GigabitEthernet' + name.substring(3);
|
|
1355
|
+
}
|
|
1356
|
+
if (lower.startsWith('gi')) {
|
|
1357
|
+
return 'GigabitEthernet' + name.substring(2);
|
|
1358
|
+
}
|
|
1359
|
+
if (lower.startsWith('loopback')) {
|
|
1360
|
+
return 'Loopback' + name.substring(8);
|
|
1361
|
+
}
|
|
1362
|
+
if (lower.startsWith('lo')) {
|
|
1363
|
+
return 'Loopback' + name.substring(2);
|
|
1364
|
+
}
|
|
1365
|
+
if (lower.startsWith('fastethernet')) {
|
|
1366
|
+
return 'FastEthernet' + name.substring(12);
|
|
1367
|
+
}
|
|
1368
|
+
if (lower.startsWith('fa')) {
|
|
1369
|
+
return 'FastEthernet' + name.substring(2);
|
|
1370
|
+
}
|
|
1371
|
+
if (lower.startsWith('tengigabitethernet')) {
|
|
1372
|
+
return 'TenGigabitEthernet' + name.substring(18);
|
|
1373
|
+
}
|
|
1374
|
+
if (lower.startsWith('ten-gigabitethernet')) {
|
|
1375
|
+
return 'TenGigabitEthernet' + name.substring(19);
|
|
1376
|
+
}
|
|
1377
|
+
if (lower.startsWith('te')) {
|
|
1378
|
+
return 'TenGigabitEthernet' + name.substring(2);
|
|
1379
|
+
}
|
|
1380
|
+
if (lower.startsWith('vlan')) {
|
|
1381
|
+
return 'Vlan' + name.substring(4);
|
|
1382
|
+
}
|
|
1383
|
+
if (lower.startsWith('vl')) {
|
|
1384
|
+
return 'Vlan' + name.substring(2);
|
|
1385
|
+
}
|
|
1386
|
+
if (lower.startsWith('ethernet')) {
|
|
1387
|
+
return 'Ethernet' + name.substring(8);
|
|
1388
|
+
}
|
|
1389
|
+
if (lower.startsWith('eth')) {
|
|
1390
|
+
return 'Ethernet' + name.substring(3);
|
|
1391
|
+
}
|
|
1392
|
+
if (lower.startsWith('port-channel')) {
|
|
1393
|
+
return 'Port-channel' + name.substring(12);
|
|
1394
|
+
}
|
|
1395
|
+
if (lower.startsWith('po')) {
|
|
1396
|
+
return 'Port-channel' + name.substring(2);
|
|
1397
|
+
}
|
|
1398
|
+
if (lower.startsWith('nve')) {
|
|
1399
|
+
return 'Nve' + name.substring(3);
|
|
1400
|
+
}
|
|
1401
|
+
return name;
|
|
1402
|
+
}
|
|
1403
|
+
shortenInterfaceName(name) {
|
|
1404
|
+
return name
|
|
1405
|
+
.replace('GigabitEthernet', 'Gi')
|
|
1406
|
+
.replace('FastEthernet', 'Fa')
|
|
1407
|
+
.replace('TenGigabitEthernet', 'Te')
|
|
1408
|
+
.replace('Loopback', 'Lo')
|
|
1409
|
+
.replace('Ethernet', 'Eth')
|
|
1410
|
+
.replace('Port-channel', 'Po');
|
|
1411
|
+
}
|
|
1412
|
+
getPrefixLength(mask) {
|
|
1413
|
+
const parts = mask.split('.').map(Number);
|
|
1414
|
+
let len = 0;
|
|
1415
|
+
for (const p of parts) {
|
|
1416
|
+
let b = p;
|
|
1417
|
+
while (b > 0) {
|
|
1418
|
+
if (b & 1)
|
|
1419
|
+
len++;
|
|
1420
|
+
b = b >> 1;
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
return len;
|
|
1424
|
+
}
|
|
1425
|
+
calculateNetwork(ip, mask) {
|
|
1426
|
+
const ipParts = ip.split('.').map(Number);
|
|
1427
|
+
const maskParts = mask.split('.').map(Number);
|
|
1428
|
+
const netParts = ipParts.map((p, i) => p & maskParts[i]);
|
|
1429
|
+
return netParts.join('.');
|
|
1430
|
+
}
|
|
1431
|
+
wildcardToSubnet(wildcard) {
|
|
1432
|
+
return wildcard.split('.').map(p => (255 - parseInt(p, 10)).toString()).join('.');
|
|
1433
|
+
}
|
|
1434
|
+
getContextHelp(line) {
|
|
1435
|
+
const trimmed = line.trim();
|
|
1436
|
+
const endsWithSpaceHelp = line.endsWith(' ?') || line.endsWith(' ?');
|
|
1437
|
+
const searchPrefix = trimmed.substring(0, trimmed.length - 1).trim();
|
|
1438
|
+
const normalizedPrefix = this.normalizeCommandString(searchPrefix);
|
|
1439
|
+
const parts = normalizedPrefix.split(/\s+/).filter(Boolean);
|
|
1440
|
+
if (parts.length === 0) {
|
|
1441
|
+
return this.getModeCommandsHelp();
|
|
1442
|
+
}
|
|
1443
|
+
if (!endsWithSpaceHelp) {
|
|
1444
|
+
const lastWord = parts[parts.length - 1].toLowerCase();
|
|
1445
|
+
const precedingPrefix = parts.slice(0, -1).join(' ');
|
|
1446
|
+
return this.getWordCompletionHelp(precedingPrefix, lastWord);
|
|
1447
|
+
}
|
|
1448
|
+
const cmd = parts[0].toLowerCase();
|
|
1449
|
+
if (cmd === 'show') {
|
|
1450
|
+
if (parts.length === 1) {
|
|
1451
|
+
return ` running-config Current operating configuration
|
|
1452
|
+
ip IP information
|
|
1453
|
+
vlan VLAN status
|
|
1454
|
+
version System hardware and software status
|
|
1455
|
+
cdp Discovery Protocol neighbors`;
|
|
1456
|
+
}
|
|
1457
|
+
if (parts[1]?.toLowerCase() === 'ip') {
|
|
1458
|
+
if (parts.length === 2) {
|
|
1459
|
+
return ` interface IP interface status and configuration
|
|
1460
|
+
route IP routing table
|
|
1461
|
+
protocols Active IP routing protocols`;
|
|
1462
|
+
}
|
|
1463
|
+
if (parts[2]?.toLowerCase() === 'interface') {
|
|
1464
|
+
return ` brief Brief summary of IP status and configuration`;
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
else if (cmd === 'ip') {
|
|
1469
|
+
if (parts.length === 1) {
|
|
1470
|
+
return ` address Configure interface IP address
|
|
1471
|
+
route Configure static IP route
|
|
1472
|
+
routing Enable IP routing`;
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
else if (cmd === 'interface') {
|
|
1476
|
+
if (parts.length === 1) {
|
|
1477
|
+
return ` GigabitEthernet GigabitEthernet IEEE 802.3z
|
|
1478
|
+
FastEthernet FastEthernet IEEE 802.3
|
|
1479
|
+
Loopback Loopback interface
|
|
1480
|
+
Vlan Vlan interface`;
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
else if (cmd === 'switchport') {
|
|
1484
|
+
if (parts.length === 1) {
|
|
1485
|
+
return ` mode Set trunking mode of the interface
|
|
1486
|
+
access Set access mode characteristics`;
|
|
1487
|
+
}
|
|
1488
|
+
if (parts[1]?.toLowerCase() === 'mode') {
|
|
1489
|
+
return ` access Set port to Access mode
|
|
1490
|
+
trunk Set port to Trunking mode`;
|
|
1491
|
+
}
|
|
1492
|
+
if (parts[1]?.toLowerCase() === 'access') {
|
|
1493
|
+
return ` vlan Set access VLAN`;
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
else if (cmd === 'no') {
|
|
1497
|
+
if (parts.length === 1) {
|
|
1498
|
+
return ` shutdown Enable the interface
|
|
1499
|
+
ip Remove IP configuration
|
|
1500
|
+
description Remove interface description`;
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
return `% No help available for command: "${normalizedPrefix} ?"`;
|
|
1504
|
+
}
|
|
1505
|
+
getModeCommandsHelp() {
|
|
1506
|
+
switch (this.mode) {
|
|
1507
|
+
case 'USER_EXEC':
|
|
1508
|
+
return ` enable Turn on privileged commands
|
|
1509
|
+
show Show running system information
|
|
1510
|
+
ping Send echo messages`;
|
|
1511
|
+
case 'PRIVILEGED_EXEC':
|
|
1512
|
+
return ` configure Enter configuration mode
|
|
1513
|
+
show Show running system information
|
|
1514
|
+
write Write running configuration to memory
|
|
1515
|
+
copy Copy configuration files
|
|
1516
|
+
ping Send echo messages
|
|
1517
|
+
disable Turn off privileged commands`;
|
|
1518
|
+
case 'GLOBAL_CONFIG':
|
|
1519
|
+
return ` hostname Set system network name
|
|
1520
|
+
interface Configure an interface
|
|
1521
|
+
ip Global IP configuration commands
|
|
1522
|
+
router Enable routing protocol
|
|
1523
|
+
vlan Configure VLAN parameters
|
|
1524
|
+
end Exit configuration mode
|
|
1525
|
+
exit Exit configuration mode`;
|
|
1526
|
+
case 'INTERFACE_CONFIG':
|
|
1527
|
+
return ` ip Interface IP configuration commands
|
|
1528
|
+
shutdown Shutdown the selected interface
|
|
1529
|
+
description Set interface description
|
|
1530
|
+
switchport Set interface switchport parameters
|
|
1531
|
+
exit Exit interface configuration mode`;
|
|
1532
|
+
default:
|
|
1533
|
+
return ` exit Exit current configuration mode
|
|
1534
|
+
end Exit to privileged exec mode`;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
getWordCompletionHelp(precedingPrefix, lastWord) {
|
|
1538
|
+
const allCommands = this.getModeCommandsList();
|
|
1539
|
+
const matches = allCommands.filter(c => c.startsWith(lastWord));
|
|
1540
|
+
if (matches.length > 0) {
|
|
1541
|
+
return matches.map(m => ` ${m}`).join('\n');
|
|
1542
|
+
}
|
|
1543
|
+
return `% No command matches prefix: "${lastWord}"`;
|
|
1544
|
+
}
|
|
1545
|
+
getModeCommandsList() {
|
|
1546
|
+
switch (this.mode) {
|
|
1547
|
+
case 'USER_EXEC':
|
|
1548
|
+
return ['enable', 'show', 'ping', 'exit'];
|
|
1549
|
+
case 'PRIVILEGED_EXEC':
|
|
1550
|
+
return ['configure', 'show', 'write', 'copy', 'ping', 'disable', 'exit'];
|
|
1551
|
+
case 'GLOBAL_CONFIG':
|
|
1552
|
+
return ['hostname', 'interface', 'ip', 'router', 'vlan', 'end', 'exit'];
|
|
1553
|
+
case 'INTERFACE_CONFIG':
|
|
1554
|
+
return ['ip', 'shutdown', 'description', 'switchport', 'exit', 'end'];
|
|
1555
|
+
default:
|
|
1556
|
+
return ['exit', 'end'];
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
exports.IOSDevice = IOSDevice;
|
|
1561
|
+
//# sourceMappingURL=IOSDevice.js.map
|