SwitchInfoPlugin.pm 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. package Foswiki::Plugins::SwitchInfoPlugin;
  2. use Net::SNMP qw(:snmp ticks_to_time TRANSLATE_NONE);
  3. use Net::Ping;
  4. # Always use strict to enforce variable scoping
  5. use strict;
  6. # $VERSION is referred to by Foswiki, and is the only global variable that
  7. # *must* exist in this package
  8. use vars qw( $VERSION $RELEASE $debug $pluginName );
  9. use Foswiki::Func (); # The plugins API
  10. use Foswiki::Plugins (); # For the API version
  11. # This should always be $Rev: 8713$ so that Foswiki can determine the checked-in
  12. # status of the plugin. It is used by the build automation tools, so
  13. # you should leave it alone.
  14. $VERSION = '$Rev: 8713$';
  15. # This is a free-form string you can use to "name" your own plugin version.
  16. # It is *not* used by the build automation tools, but is reported as part
  17. # of the version number in PLUGINDESCRIPTIONS.
  18. $RELEASE = '1.01';
  19. # Name of this Plugin, only used in this module
  20. $pluginName = 'SwitchInfoPlugin';
  21. =pod
  22. ---++ initPlugin($topic, $web, $user, $installWeb) -> $boolean
  23. * =$topic= - the name of the topic in the current CGI query
  24. * =$web= - the name of the web in the current CGI query
  25. * =$user= - the login name of the user
  26. * =$installWeb= - the name of the web the plugin is installed in
  27. REQUIRED
  28. Called to initialise the plugin. If everything is OK, should return
  29. a non-zero value. On non-fatal failure, should write a message
  30. using Foswiki::Func::writeWarning and return 0. In this case
  31. %FAILEDPLUGINS% will indicate which plugins failed.
  32. In the case of a catastrophic failure that will prevent the whole
  33. installation from working safely, this handler may use 'die', which
  34. will be trapped and reported in the browser.
  35. You may also call =Foswiki::Func::registerTagHandler= here to register
  36. a function to handle tags that have standard Foswiki syntax - for example,
  37. =%MYTAG{"my param" myarg="My Arg"}%. You can also override internal
  38. Foswiki tag handling functions this way, though this practice is unsupported
  39. and highly dangerous!
  40. =cut
  41. sub initPlugin {
  42. my( $topic, $web ) = @_;
  43. # check for Plugins.pm versions
  44. if( $Foswiki::Plugins::VERSION < 1.026 ) {
  45. Foswiki::Func::writeWarning( "Version mismatch between $pluginName and Plugins.pm" );
  46. return 0;
  47. }
  48. # register the _EXAMPLETAG function to handle %EXAMPLETAG{...}%
  49. Foswiki::Func::registerTagHandler( 'SWITCHINFO', \&_SWITCHINFO );
  50. # Plugin correctly initialized
  51. return 1;
  52. }
  53. sub extract_last_digit {
  54. my $base_oid = shift;
  55. my $key = shift;
  56. $key =~s/^$base_oid\.//;
  57. return $key;
  58. }
  59. sub expand_status {
  60. my ($device) = @_;
  61. my $ret ='';
  62. my %ifOperStatus = (
  63. '1','up',
  64. '2','down',
  65. '3','testing',
  66. '4','unknown',
  67. '5','dormant',
  68. '6','notPresent',
  69. '7','lowerLayerDown'
  70. );
  71. foreach my $port (sort {$a <=> $b} keys %$device) {
  72. next if (!$port);
  73. next if (!$device->{$port}->{Index});
  74. if (!$device->{$port}->{Alias}) { $device->{$port}->{Alias}=''; }
  75. if (!$device->{$port}->{Descr}) { $device->{$port}->{Descr}=''; }
  76. if (!$device->{$port}->{AdminStatus}) { $device->{$port}->{AdminStatus}=''; }
  77. if (exists $ifOperStatus{$device->{$port}->{AdminStatus}}) { $device->{$port}->{AdminStatus} = $ifOperStatus{$device->{$port}->{AdminStatus}}; }
  78. if (!$device->{$port}->{OperStatus}) { $device->{$port}->{OperStatus}=''; }
  79. if (exists $ifOperStatus{$device->{$port}->{OperStatus}}) { $device->{$port}->{OperStatus} = $ifOperStatus{$device->{$port}->{OperStatus}}; }
  80. if (!$device->{$port}->{Speed}) { $device->{$port}->{Speed}=0; } else {
  81. my $speed = $device->{$port}->{Speed};
  82. if ($speed eq '10000000') { $device->{$port}->{Speed}='10M'; }
  83. if ($speed eq '100000000') { $device->{$port}->{Speed}='100M'; }
  84. if ($speed eq '1000000000') { $device->{$port}->{Speed}='1G'; }
  85. if ($speed eq '10000000000') { $device->{$port}->{Speed}='10G'; }
  86. if ($speed eq '4294967295') { $device->{$port}->{Speed}='10G'; }
  87. }
  88. if ($device->{$port}->{LastChange} and $device->{$port}->{LastChange}>0 ) {
  89. my $day; my $hour; my $min;
  90. my $value = int($device->{$port}->{LastChange}/100);
  91. $day = int($value/86400);
  92. $hour = int(($value - 86400*$day)/3600);
  93. $min = int (($value - 86400*$day - 3600*$hour)/60);
  94. $device->{$port}->{LastChange} = "$day days $hour:$min";
  95. }
  96. if (!$device->{$port}->{LastChange}) { $device->{$port}->{LastChange}=''; }
  97. if (!$device->{$port}->{Vlan}) { $device->{$port}->{Vlan}='1'; }
  98. if (!$device->{$port}->{POE}) { $device->{$port}->{POE}=''; }
  99. if (!$device->{$port}->{SFP}) { $device->{$port}->{SFP}=''; }
  100. $ret.='| '.$port.' | ';
  101. $ret.=$device->{$port}->{Index}.' | ';
  102. $ret.=$device->{$port}->{Alias}.' | ';
  103. $ret.=$device->{$port}->{Descr}.' | ';
  104. $ret.=$device->{$port}->{AdminStatus}.' | ';
  105. $ret.=$device->{$port}->{OperStatus}.' | ';
  106. $ret.=$device->{$port}->{Speed}.' | ';
  107. $ret.=$device->{$port}->{LastChange}.' | ';
  108. $ret.=$device->{$port}->{Vlan}.' | ';
  109. $ret.=$device->{$port}->{POE}.' | ';
  110. $ret.=$device->{$port}->{SFP}." |\n";
  111. }
  112. return $ret;
  113. };
  114. ##########################################################
  115. sub table_callback {
  116. my ($session, $OID_ifTable, $table) = @_;
  117. my $list = $session->var_bind_list();
  118. if (!defined $list) {
  119. printf "ERROR: %s\n", $session->error();
  120. return;
  121. }
  122. my @names = $session->var_bind_names();
  123. my $next = undef;
  124. while (@names) {
  125. $next = shift @names;
  126. if (!oid_base_match($OID_ifTable, $next)) { return; }
  127. $table->{$next} = $list->{$next};
  128. }
  129. my $result = $session->get_bulk_request( -varbindlist => [ $next ], -maxrepetitions => 10, );
  130. if (!defined $result) { printf "ERROR: %s.\n", $session->error(); }
  131. return;
  132. }
  133. ###########################################################
  134. sub _SWITCHINFO {
  135. my($session, $params, $theTopic, $theWeb) = @_;
  136. ### parameters
  137. my $vendor = $params->{vendor} || '';
  138. my $host = $params->{_DEFAULT} || $params->{host};
  139. ### check host alive
  140. my $p = Net::Ping->new("tcp",1,1);
  141. my $ok= $p->ping($host);
  142. $p->close();
  143. if (!$ok) { return "Switch is not available<BR>"; }
  144. undef($p);
  145. my $port = $params->{port} || 161;
  146. my $timeout = $params->{timeout} || 5;
  147. my $community = $params->{community};
  148. if (!$community) { $community = 'public'; }
  149. my %bridgeOIDS=(
  150. 'Index' =>'.1.3.6.1.2.1.31.1.1.1.1',
  151. 'Alias' =>'.1.3.6.1.2.1.31.1.1.1.18',
  152. 'Descr' =>'.1.3.6.1.2.1.2.2.1.2',
  153. 'Speed' =>'.1.3.6.1.2.1.2.2.1.5',
  154. 'AdminStatus'=>'.1.3.6.1.2.1.2.2.1.7',
  155. 'OperStatus' =>'.1.3.6.1.2.1.2.2.1.8',
  156. 'LastChange' =>'.1.3.6.1.2.1.2.2.1.9',
  157. 'Vlan' =>'.1.3.6.1.2.1.17.7.1.4.5.1.1',
  158. 'PoeAdmin' =>'.1.3.6.1.2.1.105.1.1.1.3.1',
  159. );
  160. my %VendorOIDS = (
  161. "Mikrotik" => {
  162. "Default"=> {
  163. PoeAdmin =>'.1.3.6.1.4.1.14988.1.1.15.1.1.3',
  164. # PoeInt =>'.1.3.6.1.4.1.14988.1.1.15.1.1.1',
  165. # PoeIntName =>'.1.3.6.1.4.1.14988.1.1.15.1.1.2',
  166. PoeVolt =>'.1.3.6.1.4.1.14988.1.1.15.1.1.4',
  167. PoeCurrent =>'.1.3.6.1.4.1.14988.1.1.15.1.1.5',
  168. PoePower =>'.1.3.6.1.4.1.14988.1.1.15.1.1.6',
  169. },
  170. },
  171. "Eltex" => {
  172. "Default" => {
  173. PoePower =>'.1.3.6.1.4.1.89.108.1.1.5.1',
  174. PoeCurrent =>'.1.3.6.1.4.1.89.108.1.1.4.1',
  175. PoeVolt =>'.1.3.6.1.4.1.89.108.1.1.3.1',
  176. SfpStatus =>'.1.3.6.1.4.1.89.90.1.2.1.3',
  177. SfpVendor =>'.1.3.6.1.4.1.35265.1.23.53.1.1.1.5',
  178. SfpSN =>'.1.3.6.1.4.1.35265.1.23.53.1.1.1.6',
  179. SfpFreq =>'.1.3.6.1.4.1.35265.1.23.53.1.1.1.4',
  180. SfpLength =>'.1.3.6.1.4.1.35265.1.23.53.1.1.1.8',
  181. },
  182. },
  183. "Huawei" => {
  184. "Default"=> {
  185. PoeAdmin =>'.1.3.6.1.4.1.2011.5.25.195.3.1.3',
  186. PoePower =>'.1.3.6.1.4.1.2011.5.25.195.3.1.10',
  187. PoeCurrent =>'.1.3.6.1.4.1.4526.11.15.1.1.1.3.1',
  188. PoeVolt =>'.1.3.6.1.4.1.2011.5.25.195.3.1.14',
  189. SfpVendor =>'.1.3.6.1.4.1.2011.5.25.31.1.1.2.1.11',
  190. SfpSpeed =>'.1.3.6.1.4.1.2011.5.25.31.1.1.2.1.2',
  191. SfpVolt =>'.1.3.6.1.4.1.2011.5.25.31.1.1.3.1.6',
  192. SfpOptRx =>'.1.3.6.1.4.1.2011.5.25.31.1.1.3.1.32',
  193. SfpOptTx =>'.1.3.6.1.4.1.2011.5.25.31.1.1.3.1.33',
  194. SfpCurrent =>'.1.3.6.1.4.1.2011.5.25.31.1.1.3.1.31',
  195. SfpRx =>'.1.3.6.1.4.1.2011.5.25.31.1.1.3.1.8',
  196. SfpTx =>'.1.3.6.1.4.1.2011.5.25.31.1.1.3.1.9',
  197. },
  198. },
  199. "Allied Telesis" => {
  200. "Default" => {
  201. PoePower =>'.1.3.6.1.4.1.89.108.1.1.5.1',
  202. PoeCurrent=>'.1.3.6.1.4.1.89.108.1.1.4.1',
  203. PoeVolt =>'.1.3.6.1.4.1.89.108.1.1.3.1',
  204. },
  205. },
  206. "NetGear" => {
  207. "Deafult" =>{
  208. PoeAdmin =>'.1.3.6.1.4.1.4526.11.15.1.1.1.6.1',
  209. PoePower =>'.1.3.6.1.4.1.4526.11.15.1.1.1.2.1',
  210. PoeCurrent =>'.1.3.6.1.4.1.4526.11.15.1.1.1.3.1',
  211. PoeVolt =>'.1.3.6.1.4.1.4526.11.15.1.1.1.4.1',
  212. },
  213. },
  214. "HP" => {
  215. "Default" => {
  216. PoePower =>'.1.3.6.1.4.1.25506.2.14.1.1.4.1',
  217. PoeVolt =>'.1.3.6.1.4.1.25506.2.14.1.1.3.1',
  218. },
  219. },
  220. );
  221. my %DefaultMibs=(
  222. 'Description' => '.1.3.6.1.2.1.1.1.0',
  223. 'Uptime' => '.1.3.6.1.2.1.1.3.0',
  224. 'Name' => '.1.3.6.1.2.1.1.5.0',
  225. );
  226. my $snmp_session;
  227. my $error;
  228. ### open SNMP session
  229. eval {
  230. ($snmp_session, $error) = Net::SNMP->session(
  231. -hostname => $host,
  232. -community => $community,
  233. -nonblocking => 1,
  234. -translate => [-octetstring => 0],
  235. -version => 'snmpv2c',
  236. );
  237. };
  238. if (!defined($snmp_session)) { return "Switch is not available<BR>"; }
  239. $snmp_session->translate([-timeticks]);
  240. my %defaultTable;
  241. my $ret = $snmp_session->get_bulk_request(
  242. -varbindlist => [ '.1.3.6.1.2.1.1' ],
  243. -callback => [ \&table_callback, '.1.3.6.1.2.1.1', \%defaultTable ],
  244. -maxrepetitions => 10,
  245. );
  246. if (!defined $ret) {
  247. $snmp_session->close();
  248. return "Wlc not answer!<BR>";
  249. }
  250. # Now initiate the SNMP message exchange.
  251. snmp_dispatcher();
  252. my %switchTable;
  253. foreach my $key (keys %bridgeOIDS) {
  254. my $bridge_mib = $bridgeOIDS{$key};
  255. my %table;
  256. my $result = $snmp_session->get_bulk_request(
  257. -varbindlist => [ $bridge_mib ],
  258. -callback => [ \&table_callback, $bridge_mib, \%table ],
  259. -maxrepetitions => 10,
  260. );
  261. if (!defined $result) {
  262. printf "ERROR: %s\n", $snmp_session->error();
  263. $snmp_session->close();
  264. exit 1;
  265. }
  266. # Now initiate the SNMP message exchange.
  267. snmp_dispatcher();
  268. $switchTable{$key}=\%table;
  269. }
  270. my %switch_status;
  271. my $poe_found;
  272. my @keys = (keys %bridgeOIDS);
  273. for (my $index=0; $index<scalar(@keys); $index++) {
  274. my $key = $keys[$index];
  275. for my $oid (oid_lex_sort(keys %{$switchTable{$key}})) {
  276. next if (!$oid);
  277. my $num = extract_last_digit($bridgeOIDS{$key},$oid);
  278. my $value = $switchTable{$key}->{$oid};
  279. next if ($key ne "Index" and !exists $switch_status{$num}->{num});
  280. if ($key eq "Index") {
  281. next if ($value=~/^enet0/i);
  282. next if ($value=~/^po(\d)/i);
  283. next if ($value=~/^lo/);
  284. next if ($value=~/^IP/);
  285. next if ($value=~/^Vlan/i);
  286. next if ($value=~/^Null/i);
  287. next if ($value=~/^loop/i);
  288. next if ($value=~/^console/i);
  289. next if ($value=~/^tunnel/i);
  290. next if ($value=~/^MEth/);
  291. next if ($value=~/^bridge/i);
  292. next if ($value=~/^ppp/i);
  293. next if ($value=~/^rtif\(/i);
  294. $switch_status{$num}->{num}=$value;
  295. }
  296. $switch_status{$num}->{$key}=$value;
  297. }
  298. }
  299. #my %ext_walk = %{$VendorOIDS{$vendor}{Default}};
  300. #foreach my $key (keys %ext_walk) {
  301. #my $bridge_mib = $ext_walk{$key};
  302. #my %table;
  303. #my $result = $snmp_session->get_bulk_request(
  304. # -varbindlist => [ $bridge_mib ],
  305. # -callback => [ \&table_callback, $bridge_mib, \%table ],
  306. # -maxrepetitions => 10,
  307. # );
  308. #if (!defined $result) {
  309. # printf "ERROR: %s\n", $snmp_session->error();
  310. # $snmp_session->close();
  311. # exit 1;
  312. # }
  313. ## Now initiate the SNMP message exchange.
  314. #snmp_dispatcher();
  315. #$switchTable{$key}=\%table;
  316. #}
  317. $snmp_session->close();
  318. my $result=$defaultTable{$DefaultMibs{Name}}."\n<br>";
  319. $result.=$defaultTable{$DefaultMibs{Description}}."\n<br>";
  320. my $uptime = int($defaultTable{$DefaultMibs{Uptime}}/100);
  321. my $day; my $hour; my $min;
  322. $day = int($uptime/86400);
  323. $hour = int(($uptime - 86400*$day)/3600);
  324. $min = int (($uptime - 86400*$day - 3600*$hour)/60);
  325. my $s_uptime = "$day days $hour:$min";
  326. $result.= "$s_uptime\n<br>\n";
  327. $result.= "| *Index* | *Port* | *Alias* | *Description* | *Admin state* | *Oper state* | *Speed* | *Last change* | *Vlan* | *Poe* | *Sfp* |\n";
  328. $result.=expand_status(\%switch_status);
  329. return $result;
  330. }
  331. 1;