/
PGT_Interface.cs
688 lines (631 loc) · 32.1 KB
/
PGT_Interface.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
/*
* #########################################################################*/
/* # #*/
/* # This file is part of CDP2VISIO project, which is written #*/
/* # as a PGT plug-in to help network inventory and Visio drawing #*/
/* # creation based on CDP protocol discovery on Cisco IOS routers. #*/
/* # #*/
/* # You may not use this file except in compliance with the license. #*/
/* # #*/
/* # Copyright Laszlo Frank (c) 2014-2017 #*/
/* # #*/
/* #########################################################################*/
using PGT.Common;
using PGT.ExtensionInterfaces;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace CDP2VISIO
{
public class PGT_Interface : ICustomActionHandler
{
#region Fields
private CDPDataSet local_dataset;
private bool _terminated = false;
private PGTDataSet.ScriptSettingRow ScriptSettings;
/// <summary>
/// The name of the inventory file that is to be created
/// </summary>
private string InventoryFileName;
/// <summary>
/// Indicates, that the inventory file has already been pre-provisioned with configuration details
/// when the script started.
/// </summary>
private bool InventoryPreProvisioned = false;
/// <summary>
/// Controls whether newly discovered CDP neighbors will also be added to script and therefore be discovered, too
/// </summary>
private bool AllowRecursion = true;
/// <summary>
/// The provider of current instance
/// </summary>
private ICustomActionHandlerProvider cahProvider = null;
public ICustomActionHandlerProvider Provider => this.cahProvider;
#endregion
public void Initialize(IScriptExecutorBase Executor)
{
DebugEx.WriteLine("Initializing PGTNetworkDiscovery CustomActionHandler... ", DebugLevel.Informational);
_terminated = false;
local_dataset = new CDPDataSet();
local_dataset.Clear();
ScriptSettings = SettingsManager.GetCurrentScriptSettings();
Guid engineID = Executor.EngineID;
// search an existing inventory file and load. used later for checking domain boundary
InventoryFileName = string.Format("{0}{1}{2}.xml", Helper.GetWorkingDirectory(), Options.Default.InventoryDBDirectory, engineID.ToString());
DebugEx.WriteLine(string.Format("Checking for pre-existing inventory file {0}... ", InventoryFileName), DebugLevel.Informational);
if (File.Exists(InventoryFileName))
{
try
{
local_dataset.ReadXml(InventoryFileName);
InventoryPreProvisioned = true;
AllowRecursion = local_dataset.Parameters.First()?.AllowRecursion ?? Options.Default.MRUActiveDiscovery;
DebugEx.WriteLine(string.Format("Inventory file loaded successfully. Active discovery is {0}.", AllowRecursion ? "enabled" : "disabled"), DebugLevel.Informational);
}
catch (Exception Ex)
{
DebugEx.WriteLine(string.Format("Error loading inventory file : {0}", Ex.InnerExceptionsMessage()));
}
}
else
{
AllowRecursion = Options.Default.MRUActiveDiscovery;
DebugEx.WriteLine(string.Format("File {0} does not exist. Active discovery is {1}.", InventoryFileName, AllowRecursion ? "enabled" : "disabled"), DebugLevel.Informational);
}
}
public void Terminate()
{
DebugEx.WriteLine("Terminating PGTNetworkDiscovery CustomActionHandler and saving Inventory information", DebugLevel.Informational);
bool RetryWrite = true;
while (RetryWrite)
{
try
{
if (!Directory.Exists(Path.GetDirectoryName(InventoryFileName))) Directory.CreateDirectory(Path.GetDirectoryName(InventoryFileName));
var LockedBy = PGT.Common.FileUtil.WhoIsLocking(InventoryFileName);
if (LockedBy.Count > 0)
{
string ProcessList = string.Join(";", LockedBy.Select(p => p.ProcessName));
RetryWrite = MessageBox.Show(string.Format("The file {0} is being used by processes : {1}. Do you want to retry ?", InventoryFileName, ProcessList), "Could not create inventory file", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.Yes;
}
else
{
local_dataset.WriteXml(InventoryFileName);
RetryWrite = false;
if (!InventoryPreProvisioned && MessageBox.Show("Do you want to save the inventory to a specific file ?\r\nIf you choose No, the temporary inventory file will be retained.", "Save As", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "CDP Inventory database|*.xml|All Files|*.*";
if (sfd.ShowDialog() == DialogResult.OK)
{
try
{
local_dataset.WriteXml(sfd.FileName);
MessageBox.Show("Inventory saved successfully", "Operation completed", MessageBoxButtons.OK, MessageBoxIcon.Information);
try
{
// as the inventory file was not pre-provisioned and hence the CDP2Visio handler will not be searching for it
// we can safely delete the file
File.Delete(InventoryFileName);
}
catch (Exception Ex)
{
string msg = string.Format("Error while removing temporary inventory file : {0}", InventoryFileName, Ex.Message);
DebugEx.WriteLine(Ex.InnerExceptionsMessage());
}
}
catch (Exception Ex)
{
string msg = string.Format("Unfortunately an unexpected error occurred while saving inventory to file {0}. Error is : {1}", sfd.FileName, Ex.InnerExceptionsMessage());
DebugEx.WriteLine(msg);
MessageBox.Show(msg, "Could not create inventory file", MessageBoxButtons.YesNo, MessageBoxIcon.Error);
}
}
}
}
}
catch (Exception Ex)
{
string msg = string.Format("Unfortunately an unexpected error occurred while writing inventory to file {0}. Error is : {1}. Do you want to retry ?", InventoryFileName, Ex.InnerExceptionsMessage());
DebugEx.WriteLine(msg);
RetryWrite = MessageBox.Show(msg, "Could not create inventory file", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.Yes;
}
}
_terminated = true;
}
public bool LoggingRequired()
{
return false;
}
public bool DoCustomAction(IScriptExecutorBase Executor, DeviceConnectionInfo ConnectionInfo, out dynamic ActionResult, out bool ConnectionDropped, out bool BreakExecution)
{
bool result = false;
ActionResult = "Custom action not implemented";
ConnectionDropped = false;
BreakExecution = false;
IScriptableSession st = (IScriptableSession)Executor.Session;
int DeviceID = 0;
if (ConnectionInfo.CustomActionID == "PGTNetworkDiscovery")
{
if (ConnectionInfo.VendorName.ToLowerInvariant() == "cisco")
{
#region Cisco
ActionResult = "Error processing PGTNetworkDiscovery for Cisco";
string show_ver = string.Empty;
string device_type = "router";
string actual_hostname = string.Empty;
string show_inventory = string.Empty;
string system_serial = string.Empty;
#region SHOW VER, Virtual switch, Stacked switch
Executor.ShowActivity("Retrieving device information...");
show_ver = st.ExecCommand("sh ver");
actual_hostname = st.GetHostName();
string virtualswitch = st.ExecCommand("sh switch virtual");
bool isVSS = false;
try
{
isVSS = virtualswitch.SplitByLine().First().Split(':')[1].ToLowerInvariant().Trim() == "virtual switch";
}
catch (Exception Ex)
{
DebugEx.WriteLine(String.Format("CDP2VISIO : error parsing \"sh virtual switch\" output : {0}", Ex.InnerExceptionsMessage()), DebugLevel.Debug);
}
int stackCount = 0;
string stackedswitches = st.ExecCommand("sh switch");
try
{
if (stackedswitches.ToLowerInvariant().StartsWith("switch/stack"))
stackCount = stackedswitches.SplitByLine().Count(l => l.SplitBySpace()[0].Trim('*').IsInt());
}
catch (Exception Ex)
{
DebugEx.WriteLine(String.Format("CDP2VISIO : error parsing \"sh switch\" output : {0}", Ex.InnerExceptionsMessage()), DebugLevel.Debug);
}
#endregion
try
{
#region Identify device
show_inventory = st.ExecCommand("show inventory");
// Indicates that we are connected to an ASA, using later for VLAN discovery
bool isASA = show_inventory.IndexOf("Adaptive Security Appliance") >= 0;
// some switches doe no support the "show inventory" command
bool exec_error = show_inventory.ToLowerInvariant().Contains("invalid input detected") || ScriptSettings.FailedCommandPattern.SplitBySemicolon().Any(w => show_inventory.IndexOf(w) >= 0);
if (exec_error)
{
DebugEx.WriteLine(String.Format("CDP2VISIO : switch does not support \"sh inventory\" command, parsing version information"), DebugLevel.Debug);
// try to parse sh_version to get system serial numbers
try
{
system_serial = string.Join(",", show_ver.SplitByLine().Where(l => l.StartsWith("System serial number")).Select(l => l.Split(':')[1].Trim()));
}
catch (Exception Ex)
{
DebugEx.WriteLine(String.Format("CDP2VISIO : error searching serial number in \"sh version\" output : {0}", Ex.InnerExceptionsMessage()), DebugLevel.Debug);
}
}
else
{
// This should return system serial most of the time
try
{
if (stackCount > 0)
{
// if stackCount > 0 the switch supported the "show switch" command. Probably also understands "show module"
string modules = st.ExecCommand("show module");
// some switches who support the "show switch" command may still do not understand "show modules"
exec_error = modules.ToLowerInvariant().Contains("invalid input detected") || ScriptSettings.FailedCommandPattern.SplitBySemicolon().Any(w => modules.IndexOf(w) >= 0);
if (exec_error)
{
DebugEx.WriteLine(String.Format("CDP2VISIO : switch does not support \"sh module\" command, parsing version information"), DebugLevel.Debug);
// try to parse sh_version to get system serial numbers
system_serial = string.Join(",", show_ver.SplitByLine().Where(l => l.StartsWith("System serial number")).Select(l => l.Split(':')[1].Trim()));
}
else
{
// select lines starting with a number. These are assumed the be the switches in stack
var switchList = modules.SplitByLine().Where(l => l.SplitBySpace()[0].Trim('*').IsInt());
// each line contains the serial number in th 4th column
system_serial = string.Join(",", switchList.Select(m => m.SplitBySpace()[3]));
}
}
else system_serial = show_inventory.SplitByLine().First(l => l.StartsWith("PID:")).Split(',')[2].Split(':')[1].Trim();
}
catch (Exception Ex)
{
system_serial = "parsing error";
DebugEx.WriteLine(string.Format("Error parsing serial number : {0}", Ex.InnerExceptionsMessage()), DebugLevel.Error);
}
}
#endregion
#region Add New Device to DB with inlist
// Two devices considered identical if :
// - have the same hostname, or
// - have the same IPAddress
CDPDataSet.DevicesRow device_row = local_dataset.Devices.FirstOrDefault(d =>
d.IP_Address.SplitBySemicolon().Any(thisIP => thisIP == ConnectionInfo.DeviceIP) ||
d.Name.SplitBySemicolon().Any(thisName => DottedNameSpace.CompateTLD(thisName, ConnectionInfo.HostName))
);
if (device_row == null) //If NOT found in the DB have to ADD as new
{
device_row = local_dataset.Devices.NewDevicesRow();
device_row.SystemSerial = system_serial;
device_row.IP_Address = ConnectionInfo.DeviceIP;
device_row.Name = actual_hostname;
device_row.VersionInfo = show_ver;
device_row.Type = isASA ? "ASA" : isVSS ? "VSS" : stackCount > 1 ? string.Format("Stack{0}", stackCount) : device_type;
device_row.Inventory = show_inventory;
local_dataset.Devices.AddDevicesRow(device_row);
DeviceID = device_row.ID;
}
else //IF found in the existing DB have to update!
{
device_row.VersionInfo = show_ver;
device_row.Inventory = show_inventory;
device_row.SystemSerial = system_serial;
if (isASA) device_row.Type = "ASA";
else if (isVSS) device_row.Type = "VSS";
else if (stackCount > 1) device_row.Type = string.Format("Stack{0}", stackCount);
}
#endregion
#region SHOW CDP NEIGHBOUR
if (!isASA)
{
Executor.ShowActivity("Checking for CDP neighbors...");
string cdpResult = st.ExecCommand("sh cdp neighbors detail");
CDPParser thisParser;
if (show_ver.IndexOf("NX-OS") >= 0)
{
thisParser = new NXOS_CDPParser(Executor, ConnectionInfo, AllowRecursion);
thisParser.ProcessCDPResult(cdpResult, device_row, local_dataset);
}
else
{
thisParser = new IOS_CDPParser(Executor, ConnectionInfo, AllowRecursion);
thisParser.ProcessCDPResult(cdpResult, device_row, local_dataset);
}
}
#endregion
#region Collect interface configuration details for CDP connected interfaces
Executor.ShowActivity("Collecting CDP connected interface information...");
var query_local_interfaces = from device in local_dataset.Devices
where (device.ID == device_row.ID)
join neigh in local_dataset.Neighbours on device.ID equals neigh.Parent_ID
select new
{
local_int = neigh.Local_Interface,
ID = device.ID,
};
foreach (var thisInterface in query_local_interfaces)
{
CDP2VISIO.CDPDataSet.InterfacesRow interface_row = null;
interface_row = local_dataset.Interfaces.NewInterfacesRow();
string command = "sh run interface " + thisInterface.local_int;
string commandResult = st.ExecCommand(command);
commandResult = commandResult.ToLower();
string[] lines_in_commandresult = commandResult.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
string interface_config = string.Empty;
bool addtoconfig = false;
foreach (var line in lines_in_commandresult)
{
if (line.IndexOf(RevConvInt(thisInterface.local_int)) >= 0) addtoconfig = true;
if (addtoconfig) interface_config = interface_config + line + "\r\n";
}
interface_row.ID = thisInterface.ID;
interface_row.Name = thisInterface.local_int;
interface_row.Running_config = interface_config;
local_dataset.Interfaces.AddInterfacesRow(interface_row);
}
#endregion
#region Collect overall interface status information
if (Options.Default.DisplayConnected && !isASA)
{
Executor.ShowActivity("Checking interface status...");
string[] ifDesc = st.ExecCommand("show interface description").SplitByLine();
foreach (string thisIfDescription in ifDesc.SkipWhile((string s, int i) => i < 1))
{
string[] ifDescrWords = thisIfDescription.SplitBySpace();
string IFName = Common.ConvInt(ifDescrWords[0]);
if (!IFName.StartsWith("vl")) // Don't care vlan interfaces here
{
string IFStatus = string.Format("{0}/{1}", ifDescrWords[1], ifDescrWords[2]);
string IFDescription = string.Join(" ", ifDescrWords.SkipWhile((string s, int i) => i < 3));
var foundIF = from thisIF in local_dataset.Interfaces where thisIF.ID == device_row.ID && thisIF.Name == IFName select thisIF;
if (foundIF.Count() == 1)
{
// Update existing IF data
foundIF.ElementAt(0).Status = IFStatus;
foundIF.ElementAt(0).Description = IFDescription;
}
else
{
// Add as new IF
CDPDataSet.InterfacesRow thisIF = local_dataset.Interfaces.NewInterfacesRow();
thisIF.ID = device_row.ID;
thisIF.Name = IFName;
thisIF.Status = IFStatus;
thisIF.Description = IFDescription;
local_dataset.Interfaces.AddInterfacesRow(thisIF);
}
}
}
}
#endregion
#region Collect VLAN interface information
if (isASA)
{
Executor.ShowActivity("Gathering VLAN information...");
// Contains the L3 information : interface names, interface ip, network, mask
List<string> VLANInfo = new List<string>();
string asaIFs = st.ExecCommand("sh int ip brief");
device_row.L3InterfaceInformation = asaIFs;
foreach (string thisInterface in asaIFs.SplitByLine().SkipWhile(l => l.StartsWith("Interface")))
{
string[] ifWords = thisInterface.SplitBySpace();
string asaIFName = ifWords[0];
string nameIF = "";
string secLevel = "";
string vlanIPAddr = "";
string vlanNetMask = "";
string netaddress = "";
int maskLength = 0;
int vlanID = 0;
string thisIFConfig = st.ExecCommand(string.Format("sh run int {0}", asaIFName));
foreach (string thisConfigLine in thisIFConfig.SplitByLine().Select(s => s.Trim()))
{
if (thisConfigLine.StartsWith("vlan")) int.TryParse(thisConfigLine.SplitBySpace()[1], out vlanID);
else if (thisConfigLine.StartsWith("nameif")) nameIF = thisConfigLine.SplitBySpace()[1];
else if (thisConfigLine.StartsWith("security-level")) secLevel = thisConfigLine.SplitBySpace()[1];
else if (thisConfigLine.StartsWith("ip address"))
{
string[] lineWords = thisConfigLine.SplitBySpace();
vlanIPAddr = lineWords[2];
vlanNetMask = lineWords[3];
maskLength = IPOperations.GetMaskLength(vlanNetMask);
netaddress = IPOperations.GetNetworkAddress(vlanIPAddr, maskLength);
}
}
string networkAddressPrint = "";
if (maskLength > 0) networkAddressPrint = string.Format("{0}/{1}", netaddress, maskLength);
string reportedIFName = string.Format("{0} name: {1} security-level: {2}", asaIFName, nameIF, secLevel);
VLANInfo.Add(string.Join(";", new string[] { vlanID == 0 ? "routed" : vlanID.ToString(), reportedIFName, vlanIPAddr, vlanNetMask, networkAddressPrint }));
#region Add ASA interface to inventory database
string IFStatus = "n/a";
if (ifWords.Length == 6) IFStatus = string.Format("{0}/{1}", ifWords[4], ifWords[5]);
else if (ifWords.Length == 7) IFStatus = string.Format("{0} {1}/{2}", ifWords[4], ifWords[5], ifWords[6]);
var foundIF = from thisIF in local_dataset.Interfaces where thisIF.ID == device_row.ID && thisIF.Name == asaIFName select thisIF;
if (foundIF.Count() == 1)
{
// Update existing IF data
foundIF.ElementAt(0).Status = IFStatus;
foundIF.ElementAt(0).Description = reportedIFName;
}
else
{
// Add as new IF
CDPDataSet.InterfacesRow thisIF = local_dataset.Interfaces.NewInterfacesRow();
thisIF.ID = device_row.ID;
thisIF.Name = asaIFName;
thisIF.Status = IFStatus;
thisIF.Description = reportedIFName;
local_dataset.Interfaces.AddInterfacesRow(thisIF);
}
#endregion
}
device_row.VLANInformation = string.Join(Environment.NewLine, VLANInfo);
}
else
{
Executor.ShowActivity("Gathering VLAN interface information...");
// TODO : for routers, also include "sh ip int brief"
string vlanIFs = st.ExecCommand("sh ip int brief | i [Vv]lan");
device_row.L3InterfaceInformation = vlanIFs;
#region Collect network details for VLANs
// Contains the list of VLAN interface names
List<string> VLANInterfaces = Regex.Matches(vlanIFs, "^Vlan(\\d+)", RegexOptions.Multiline).Cast<Match>().Select(m => m.Value.ToLowerInvariant()).ToList();
// Contains the L3 information : interface names, interface ip, network, mask
List<string> VLANInfo = new List<string>();
string vlans = st.ExecCommand("sh vlan");
bool addLineToOutput = false;
foreach (string line in vlans.SplitByLine())
{
if (line.StartsWith("---"))
{
addLineToOutput = !addLineToOutput;
if (!addLineToOutput) break;
}
else if (addLineToOutput)
{
string[] words = line.SplitBySpace();
int vlanID = -1;
if (int.TryParse(words[0], out vlanID))
{
string vlanName = words[1];
string vlanIPAddr = "";
string vlanNetMask = "";
string netaddress = "";
int maskLength = 0;
// Check if current VLAN has a corresponding VLAN interface definition
if (VLANInterfaces.Contains(string.Format("vlan{0}", vlanID)))
{
string vlanIntConfig = st.ExecCommand(string.Format("sh run int vlan{0}", vlanID));
string ipAddressLine = vlanIntConfig.SplitByLine().FirstOrDefault(l => l.Trim().StartsWith("ip address"));
if (ipAddressLine != null)
{
string[] addr = ipAddressLine.SplitBySpace();
vlanIPAddr = addr[2];
vlanNetMask = addr[3];
maskLength = IPOperations.GetMaskLength(vlanNetMask);
netaddress = IPOperations.GetNetworkAddress(vlanIPAddr, maskLength);
}
else
{
ipAddressLine = vlanIntConfig.SplitByLine().FirstOrDefault(l => l.Trim().StartsWith("no ip address"));
if (ipAddressLine != null)
{
vlanIPAddr = "no ip address";
}
}
}
string networkAddressPrint = "";
if (maskLength > 0) networkAddressPrint = string.Format("{0}/{1}", netaddress, maskLength);
VLANInfo.Add(string.Join(";", new string[] { vlanID.ToString(), vlanName, vlanIPAddr, vlanNetMask, networkAddressPrint }));
}
}
}
device_row.VLANInformation = string.Join(Environment.NewLine, VLANInfo);
#endregion
}
#endregion
result = true;
ActionResult = "Discovery information processing finished successfully.";
if (system_serial == "") ActionResult += "Warning : Could not identify system serial number.";
}
catch (Exception Ex)
{
ActionResult = string.Format("Unexpected processing error : {0} {1}", Ex.Message, Ex.InnerException?.Message);
}
#endregion
}
else if (ConnectionInfo.VendorName.ToLowerInvariant() == "junos")
{
#region JunOS
//
// http://www.juniper.net/documentation/en_US/junos11.1/topics/task/configuration/802-1x-lldp-cli.html
//
ActionResult = "Error processing PGTNetworkDiscovery for JunOS";
string show_ver = string.Empty;
string device_type = "router";
string actual_hostname = string.Empty;
string show_inventory = string.Empty;
string system_serial = string.Empty;
int stackCount = 0;
#region Identify device
show_inventory = st.ExecCommand("show chassis hardware");
// Indicates that we are connected to an ASA, using later for VLAN discovery
bool isASA = show_inventory.IndexOf("Adaptive Security Appliance") >= 0;
// some switches doe no support the "show inventory" command
bool exec_error = show_inventory.ToLowerInvariant().Contains("invalid input detected") || ScriptSettings.FailedCommandPattern.SplitBySemicolon().Any(w => show_inventory.IndexOf(w) >= 0);
if (exec_error)
{
DebugEx.WriteLine(String.Format("CDP2VISIO : switch does not support \"sh inventory\" command, parsing version information"), DebugLevel.Debug);
// try to parse sh_version to get system serial numbers
try
{
system_serial = string.Join(",", show_ver.SplitByLine().Where(l => l.StartsWith("System serial number")).Select(l => l.Split(':')[1].Trim()));
}
catch (Exception Ex)
{
DebugEx.WriteLine(String.Format("CDP2VISIO : error searching serial number in \"sh version\" output : {0}", Ex.InnerExceptionsMessage()), DebugLevel.Debug);
}
}
else
{
// This should return system serial most of the time
try
{
if (stackCount > 0)
{
// if stackCount > 0 the switch supported the "show switch" command. Probably also understands "show module"
string modules = st.ExecCommand("show module");
// some switches who support the "show switch" command may still do not understand "show modules"
exec_error = modules.ToLowerInvariant().Contains("invalid input detected") || ScriptSettings.FailedCommandPattern.SplitBySemicolon().Any(w => modules.IndexOf(w) >= 0);
if (exec_error)
{
DebugEx.WriteLine(String.Format("CDP2VISIO : switch does not support \"sh module\" command, parsing version information"), DebugLevel.Debug);
// try to parse sh_version to get system serial numbers
system_serial = string.Join(",", show_ver.SplitByLine().Where(l => l.StartsWith("System serial number")).Select(l => l.Split(':')[1].Trim()));
}
else
{
// select lines starting with a number. These are assumed the be the switches in stack
var switchList = modules.SplitByLine().Where(l => l.SplitBySpace()[0].Trim('*').IsInt());
// each line contains the serial number in th 4th column
system_serial = string.Join(",", switchList.Select(m => m.SplitBySpace()[3]));
}
}
else system_serial = show_inventory.SplitByLine().First(l => l.StartsWith("PID:")).Split(',')[2].Split(':')[1].Trim();
}
catch (Exception Ex)
{
system_serial = "parsing error";
DebugEx.WriteLine(string.Format("Error parsing serial number : {0}", Ex.InnerExceptionsMessage()), DebugLevel.Error);
}
}
#endregion
#endregion
}
}
return result;
}
public string[] HandledCustomActions()
{
return new string[] { "PGTNetworkDiscovery" };
}
public void HostUnreachable(IScriptExecutorBase Executor, DeviceConnectionInfo ConnectionInfo)
{
}
public string ConvInt(string input_interface)
{
input_interface = input_interface.ToLower();
string conv_int = input_interface;
if (conv_int.IndexOf("fastethernet") >= 0) conv_int = conv_int.Replace("fastethernet", "fa");
if (conv_int.IndexOf("tengigabitethernet") >= 0) conv_int = conv_int.Replace("tengigabitethernet", "tengi");
if (conv_int.IndexOf("gigabitethernet") >= 0) conv_int = conv_int.Replace("gigabitethernet", "gi");
if (conv_int.IndexOf("ethernet") >= 0) conv_int = conv_int.Replace("ethernet", "eth");
if (conv_int.IndexOf("loopback") >= 0) conv_int = conv_int.Replace("loopback", "lo");
return conv_int;
}
public string RevConvInt(string input_interface)
{
input_interface = input_interface.ToLower();
string conv_int = input_interface;
if (conv_int.IndexOf("fa") >= 0) conv_int = conv_int.Replace("fa", "fastethernet");
else if (conv_int.IndexOf("tengi") >= 0) conv_int = conv_int.Replace("tengi", "tengigabitethernet");
else if (conv_int.IndexOf("gi") >= 0) conv_int = conv_int.Replace("gi", "gigabitethernet");
else if (conv_int.IndexOf("eth") >= 0) conv_int = conv_int.Replace("eth", "ethernet");
else if (conv_int.IndexOf("lo") >= 0) conv_int = conv_int.Replace("lo", "loopback");
return conv_int;
}
public void RegisterProvider(ICustomActionHandlerProvider provider)
{
this.cahProvider = provider;
}
public bool IsTerminated()
{
return _terminated;
}
}
public class CDPtoVISIOManager : ICustomMenuHandler
{
private Form AppMainForm;
#region ICustomMenuHandler Members
public ToolStripMenuItem GetMenu()
{
ToolStripMenuItem tsmMainMenu = new ToolStripMenuItem();
#region Menu definition
tsmMainMenu.Image = Resources.Resources.CreateSchema_8259_32;
tsmMainMenu.ImageTransparentColor = System.Drawing.Color.Black;
tsmMainMenu.ImageScaling = ToolStripItemImageScaling.None;
tsmMainMenu.Name = "CDP2VISIOManager.tsmMainMenu";
tsmMainMenu.Text = "CDP Network Discovery";
tsmMainMenu.Click += tsmMainMenu_Click;
#endregion
return tsmMainMenu;
}
void tsmMainMenu_Click(object sender, EventArgs e)
{
CDP2VisioManager frm = new CDP2VisioManager();
frm.MdiParent = AppMainForm;
frm.Show();
}
public void SetMainForm(Form mainForm)
{
this.AppMainForm = mainForm;
}
#endregion
}
}