1 | <?php |
||||
2 | /** |
||||
3 | * CISCO Switch Interface Class |
||||
4 | * Basically this is a wrapper to do and parse things from IOS. |
||||
5 | * Links I might find helpful in improving this class: |
||||
6 | * http://www.networker.gr/index.php/2011/03/parsing-the-cisco-ios-configuration/ |
||||
7 | * http://technologyordie.com/parsing-cisco-show-command-output |
||||
8 | * http://packetpushers.net/rocking-your-show-commands-with-regex/ |
||||
9 | * Based on code from http://www.soucy.org/project/cisco/ |
||||
10 | * |
||||
11 | * @author Joe Huss <[email protected]> |
||||
12 | * @version $Revision: 58 $ |
||||
13 | * @copyright 2019 |
||||
14 | * @package MyAdmin |
||||
15 | * @category Network |
||||
16 | */ |
||||
17 | |||||
18 | /** |
||||
19 | * cisco |
||||
20 | * |
||||
21 | * @access public |
||||
22 | */ |
||||
23 | class cisco |
||||
24 | { |
||||
25 | /** |
||||
26 | * @var bool |
||||
27 | */ |
||||
28 | public $autoconnect = true; // Sets whether or not exec() will automatically connect() if needed |
||||
29 | /** |
||||
30 | * @var int |
||||
31 | */ |
||||
32 | public $min_timeout = 300; // sets a minimum timeout, 0 or false to disable |
||||
33 | /** |
||||
34 | * @var bool |
||||
35 | */ |
||||
36 | public $connected = false; // True/False Whether or not you are currently connected |
||||
37 | /** |
||||
38 | * @var |
||||
39 | */ |
||||
40 | private $_hostname; // SSH Connection Hostname |
||||
41 | /** |
||||
42 | * @var |
||||
43 | */ |
||||
44 | private $_username; // SSH Connection Username |
||||
45 | /** |
||||
46 | * @var |
||||
47 | */ |
||||
48 | private $_password; // SSH Connection Password |
||||
49 | /** |
||||
50 | * @var int |
||||
51 | */ |
||||
52 | private $_port; // SSH Connection Port |
||||
53 | /** |
||||
54 | * @var |
||||
55 | */ |
||||
56 | private $_motd; // MOTD / Message of the day / Banner |
||||
57 | /** |
||||
58 | * @var |
||||
59 | */ |
||||
60 | private $_prompt; // Prompt |
||||
61 | /** |
||||
62 | * @var |
||||
63 | */ |
||||
64 | private $_ssh; // SSH Connection Resource |
||||
65 | /** |
||||
66 | * @var |
||||
67 | */ |
||||
68 | private $_stream; // Data Stream |
||||
69 | /** |
||||
70 | * @var |
||||
71 | */ |
||||
72 | private $_data; // Formatted Response |
||||
73 | /** |
||||
74 | * @var |
||||
75 | */ |
||||
76 | private $_response; // Raw Response |
||||
77 | |||||
78 | /** |
||||
79 | * @param $hostname |
||||
80 | * @param $username |
||||
81 | * @param $password |
||||
82 | * @param int $port |
||||
83 | */ |
||||
84 | public function __construct($hostname, $username, $password, $port = 22) |
||||
85 | { |
||||
86 | $this->_hostname = $hostname; |
||||
87 | $this->_username = $username; |
||||
88 | $this->_password = $password; |
||||
89 | $this->_port = $port; |
||||
90 | if ($this->min_timeout && ini_get('default_socket_timeout') < $this->min_timeout) { |
||||
91 | ini_set('default_socket_timeout', $this->min_timeout); |
||||
92 | } |
||||
93 | } |
||||
94 | |||||
95 | /** |
||||
96 | * @param string $string |
||||
97 | * @param int $index |
||||
98 | * @return string |
||||
99 | */ |
||||
100 | public function _string_shift(&$string, $index = 1) |
||||
101 | { |
||||
102 | $substr = mb_substr($string, 0, $index); |
||||
103 | $string = mb_substr($string, $index); |
||||
104 | return $substr; |
||||
105 | } |
||||
106 | |||||
107 | /** |
||||
108 | * Returns the output of an interactive shell |
||||
109 | * Gathers output from a shell until $pattern is met, Pattern is a regular string |
||||
110 | * unless $regex = true, then it matches it with preg_match as a regular expression. |
||||
111 | * |
||||
112 | * @param $pattern string the string or the pattern to match |
||||
113 | * @param $regex bool Whether or not we are trying to match a regex pattern or just a simple string |
||||
114 | * @return String |
||||
115 | * @access public |
||||
116 | */ |
||||
117 | public function read($pattern = '', $regex = false) |
||||
118 | { |
||||
119 | //usleep(1000); |
||||
120 | $this->_response = ''; |
||||
121 | $match = $pattern; |
||||
122 | $i = 0; |
||||
123 | while (!feof($this->_stream)) { |
||||
124 | if ($regex) { |
||||
125 | preg_match($pattern, $this->_response, $matches); |
||||
126 | //echo 'M:'.print_r($matches, TRUE).'<br>'; |
||||
127 | $match = isset($matches[0]) ? $matches[0] : []; |
||||
128 | } |
||||
129 | $pos = !empty($match) ? mb_strpos($this->_response, $match) : false; |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
130 | //echo ++$i . "POS:".var_export($pos, TRUE).'<br>'; |
||||
131 | if ($pos !== false) { |
||||
132 | //echo "$match Matching $pattern @ $pos <br>"; |
||||
133 | return $this->_string_shift($this->_response, $pos + mb_strlen($match)); |
||||
0 ignored issues
–
show
It seems like
$match can also be of type array ; however, parameter $string of mb_strlen() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
134 | } |
||||
135 | usleep(1000); |
||||
136 | $response = fgets($this->_stream); |
||||
137 | //echo "R$i:$response<br>"; |
||||
138 | if (is_bool($response)) { |
||||
139 | //echo "Return B $response::".$this->_response."<br>"; |
||||
140 | // return $response ? $this->_string_shift($this->_response, mb_strlen($this->_response)) : false; |
||||
141 | } |
||||
142 | $this->_response .= $response; |
||||
143 | } |
||||
144 | echo 'FEOF !!!!<br>'; |
||||
145 | return $this->_response; |
||||
146 | } |
||||
147 | |||||
148 | /** |
||||
149 | * @param string $cmd |
||||
150 | */ |
||||
151 | public function write($cmd) |
||||
152 | { |
||||
153 | fwrite($this->_stream, $cmd); |
||||
154 | } |
||||
155 | |||||
156 | /** |
||||
157 | * @return bool |
||||
158 | */ |
||||
159 | public function connect() |
||||
160 | { |
||||
161 | //echo "Connecting to " . $this->_hostname . "<br>"; |
||||
162 | $this->_ssh = ssh2_connect($this->_hostname, $this->_port); |
||||
163 | if ($this->_ssh === false) { |
||||
164 | return false; |
||||
165 | } |
||||
166 | ssh2_auth_password($this->_ssh, $this->_username, $this->_password); |
||||
167 | $this->_stream = ssh2_shell($this->_ssh); |
||||
168 | $this->connected = true; |
||||
169 | $this->parse_motd_and_prompt(); |
||||
170 | return true; |
||||
171 | } |
||||
172 | |||||
173 | /** |
||||
174 | * |
||||
175 | */ |
||||
176 | public function parse_motd_and_prompt() |
||||
177 | { |
||||
178 | $this->_motd = trim($this->read('/.*[>|#]/', true)); |
||||
179 | $this->write("\n"); |
||||
180 | $this->_prompt = trim($this->read('/.*[>|#]/', true)); |
||||
181 | $length = mb_strlen($this->_prompt); |
||||
182 | if (mb_substr($this->_motd, -$length) == $this->_prompt) { |
||||
183 | $this->_motd = mb_substr($this->_motd, 0, -$length); |
||||
184 | } |
||||
185 | //echo "MOTD:".$this->_motd."<br>"; |
||||
186 | //echo "Prompt:".$this->_prompt.'<br>'; |
||||
187 | return true; |
||||
188 | sleep(1); |
||||
189 | $this->_motd = ''; |
||||
190 | while ($this->_response = fgets($this->_stream)) { |
||||
191 | $this->_motd .= $this->_response; |
||||
192 | } |
||||
193 | $this->_motd = trim($this->_motd); |
||||
194 | fwrite($this->_stream, "\n"); |
||||
195 | $this->_response = stream_get_contents($this->_stream); |
||||
196 | //stream_set_blocking($this->_stream, FALSE); |
||||
197 | $this->_prompt = trim($this->_response); |
||||
198 | /* sleep (1); |
||||
199 | while ($this->_response = fgets($this->_stream)) |
||||
200 | $this->_prompt .= $this->_response; |
||||
201 | $this->_prompt = trim($this->_prompt);*/ |
||||
202 | echo 'MOTD:'.$this->_motd.'<br>'; |
||||
203 | echo 'Prompt:'.$this->_prompt.'<br>'; |
||||
204 | $length = mb_strlen($this->_prompt); |
||||
205 | if (mb_substr($this->_motd, -$length) == $this->_prompt) { |
||||
206 | //echo "Found Prompt<br>"; |
||||
207 | $this->_motd = mb_substr($this->_motd, 0, -$length); |
||||
208 | } |
||||
209 | //echo "MOTD:".$this->_motd . "<br>"; |
||||
210 | echo 'Prompt:'.$this->_prompt.'<br>'; |
||||
211 | /* $this->_stream = ssh2_exec($this->_ssh, "#"); |
||||
212 | stream_set_blocking($this->_stream, TRUE); |
||||
213 | $this->_response = stream_get_contents($this->_stream); |
||||
214 | $this->_data = $this->_response; |
||||
215 | stream_set_blocking($this->_stream, FALSE); |
||||
216 | var_dump($this->_response); |
||||
217 | */ |
||||
218 | } |
||||
219 | |||||
220 | /** |
||||
221 | * @param string $cmd |
||||
222 | * @return string |
||||
223 | */ |
||||
224 | public function exec($cmd) |
||||
225 | { |
||||
226 | if ($this->autoconnect === true && $this->connected === false) { |
||||
227 | $this->connect(); |
||||
228 | } |
||||
229 | if (mb_substr($cmd, -1) != "\n") { |
||||
230 | //error_log("Adding NEWLINE Character To SSH2 Command $cmd", __LINE__, __FILE__); |
||||
231 | $cmd .= "\n"; |
||||
232 | } |
||||
233 | $this->_data = false; |
||||
234 | fwrite($this->_stream, $cmd); |
||||
235 | $this->_response = trim($this->read($this->_prompt)); |
||||
236 | $length = mb_strlen($this->_prompt); |
||||
237 | if (mb_substr($this->_response, -$length) == $this->_prompt) { |
||||
238 | //echo "Found Prompt<br>"; |
||||
239 | $this->_response = mb_substr($this->_response, 0, -$length); |
||||
240 | } |
||||
241 | $this->_data = $this->_response; |
||||
242 | //stream_set_blocking($this->_stream, FALSE); |
||||
243 | //if (mb_strpos($this->_data, '% Invalid input detected') !== FALSE) $this->_data = FALSE; |
||||
244 | return $this->_data; |
||||
245 | } |
||||
246 | |||||
247 | /** |
||||
248 | * @return string |
||||
249 | */ |
||||
250 | public function get_response() |
||||
251 | { |
||||
252 | return $this->_response; |
||||
253 | } |
||||
254 | |||||
255 | /** |
||||
256 | * |
||||
257 | */ |
||||
258 | public function disconnect() |
||||
259 | { |
||||
260 | //ssh2_exec($this->_ssh, 'quit'); |
||||
261 | $this->connected = false; |
||||
262 | } |
||||
263 | |||||
264 | /** |
||||
265 | * |
||||
266 | */ |
||||
267 | public function __destruct() |
||||
268 | { |
||||
269 | if ($this->connected === true) { |
||||
270 | $this->disconnect(); |
||||
271 | } |
||||
272 | } |
||||
273 | |||||
274 | /** |
||||
275 | * @param $int |
||||
276 | * @return string |
||||
277 | */ |
||||
278 | public function show_int_config($int) |
||||
279 | { |
||||
280 | // Enabled Only |
||||
281 | //if (mb_strpos($this->_prompt, '#') === FALSE) |
||||
282 | // die('Error: User must be enabled to use show_int_config()'.PHP_EOL); |
||||
283 | $this->exec('show run int '.$int); |
||||
284 | return $this->show_int_config_parser(); |
||||
285 | } |
||||
286 | |||||
287 | /** |
||||
288 | * @return string |
||||
289 | */ |
||||
290 | public function show_int_config_parser() |
||||
291 | { |
||||
292 | $this->_data = explode("\r\n", $this->_data); |
||||
293 | for ($i = 0; $i < 5; $i++) { |
||||
294 | array_shift($this->_data); |
||||
295 | } |
||||
296 | for ($i = 0; $i < 2; $i++) { |
||||
297 | array_pop($this->_data); |
||||
298 | } |
||||
299 | $this->_data = implode("\n", $this->_data); |
||||
300 | return $this->_data; |
||||
301 | } |
||||
302 | |||||
303 | /** |
||||
304 | * @return array |
||||
305 | */ |
||||
306 | public function show_int_status() |
||||
307 | { |
||||
308 | $result = []; |
||||
309 | $this->exec('show int status'); |
||||
310 | $this->_data = explode("\r\n", $this->_data); |
||||
311 | for ($i = 0; $i < 2; $i++) { |
||||
312 | array_shift($this->_data); |
||||
313 | } |
||||
314 | array_pop($this->_data); |
||||
315 | $pos = mb_strpos($this->_data[0], 'Status'); |
||||
316 | foreach ($this->_data as $entry) { |
||||
317 | $temp = trim($entry); |
||||
318 | if (mb_strlen($temp) > 1 && $temp[2] != 'r' && $temp[0] != '-') { |
||||
319 | $entry = []; |
||||
320 | $entry['interface'] = mb_substr($temp, 0, mb_strpos($temp, ' ')); |
||||
321 | $entry['description'] = trim(mb_substr($temp, mb_strpos($temp, ' ') + 1, $pos - mb_strlen($entry['interface']) - 1)); |
||||
322 | $temp = mb_substr($temp, $pos); |
||||
323 | /** @noinspection PrintfScanfArgumentsInspection */ |
||||
324 | $temp = sscanf($temp, '%s %s %s %s %s %s'); |
||||
325 | $entry['status'] = $temp[0]; |
||||
326 | $entry['vlan'] = $temp[1]; |
||||
327 | $entry['duplex'] = $temp[2]; |
||||
328 | $entry['speed'] = $temp[3]; |
||||
329 | $entry['type'] = trim($temp[4].' '.$temp[5]); |
||||
330 | $result[] = $entry; |
||||
331 | } // if |
||||
332 | } // foreach |
||||
333 | $this->_data = $result; |
||||
334 | return $this->_data; |
||||
335 | } |
||||
336 | |||||
337 | /** |
||||
338 | * @return array |
||||
339 | */ |
||||
340 | public function show_log() |
||||
341 | { |
||||
342 | // Enabled Only |
||||
343 | if (mb_strpos($this->_prompt, '#') === false) { |
||||
344 | die('Error: User must be enabled to use show_log()'.PHP_EOL); |
||||
345 | } |
||||
346 | $result = []; |
||||
347 | $this->exec('sh log | inc %'); |
||||
348 | $this->_data = explode("\r\n", $this->_data); |
||||
349 | array_shift($this->_data); |
||||
350 | array_pop($this->_data); |
||||
351 | foreach ($this->_data as $entry) { |
||||
352 | $temp = trim($entry); |
||||
353 | $entry = []; |
||||
354 | $entry['timestamp'] = mb_substr($temp, 0, mb_strpos($temp, '%') - 2); |
||||
355 | if ($entry['timestamp'][0] == '.' || $entry['timestamp'][0] == '*') { |
||||
356 | $entry['timestamp'] = mb_substr($entry['timestamp'], 1); |
||||
357 | } |
||||
358 | $temp = mb_substr($temp, mb_strpos($temp, '%') + 1); |
||||
359 | $entry['type'] = mb_substr($temp, 0, mb_strpos($temp, ':')); |
||||
360 | $temp = mb_substr($temp, mb_strpos($temp, ':') + 2); |
||||
361 | $entry['message'] = $temp; |
||||
362 | $result[] = $entry; |
||||
363 | } // foreach |
||||
364 | $this->_data = $result; |
||||
365 | return $this->_data; |
||||
366 | } |
||||
367 | |||||
368 | /** |
||||
369 | * @param $int |
||||
370 | * @return array |
||||
371 | */ |
||||
372 | public function show_int($int) |
||||
373 | { |
||||
374 | $result = []; |
||||
375 | $this->exec('show int '.$int); |
||||
376 | $this->_data = explode("\r\n", $this->_data); |
||||
377 | foreach ($this->_data as $entry) { |
||||
378 | $entry = trim($entry); |
||||
379 | if (mb_strpos($entry, 'line protocol') !== false) { |
||||
380 | $result['interface'] = mb_substr($entry, 0, mb_strpos($entry, ' ')); |
||||
381 | if (mb_strpos($entry, 'administratively') !== false) { |
||||
382 | $result['status'] = 'disabled'; |
||||
383 | } elseif (mb_substr($entry, mb_strpos($entry, 'line protocol') + 17, 2) == 'up') { |
||||
384 | $result['status'] = 'connected'; |
||||
385 | } else { |
||||
386 | $result['status'] = 'notconnect'; |
||||
387 | } // if .. else |
||||
388 | } elseif (mb_strpos($entry, 'Description: ') !== false) { |
||||
389 | $entry = explode(':', $entry); |
||||
390 | $result['description'] = trim($entry[1]); |
||||
391 | } elseif (mb_strpos($entry, 'MTU') !== false) { |
||||
392 | $entry = explode(',', $entry); |
||||
393 | $entry[0] = trim($entry[0]); |
||||
394 | $entry[0] = explode(' ', $entry[0]); |
||||
395 | $result['mtu'] = $entry[0][1]; |
||||
396 | $entry[1] = trim($entry[1]); |
||||
397 | $entry[1] = explode(' ', $entry[1]); |
||||
398 | $result['bandwidth'] = $entry[1][1]; |
||||
399 | $entry[2] = trim($entry[2]); |
||||
400 | $entry[2] = explode(' ', $entry[2]); |
||||
401 | $result['dly'] = $entry[2][1]; |
||||
402 | } elseif (mb_strpos($entry, 'duplex') !== false) { |
||||
403 | $entry = explode(',', $entry); |
||||
404 | $entry[0] = trim($entry[0]); |
||||
405 | $entry[0] = explode(' ', $entry[0]); |
||||
406 | $entry[0][0] = explode('-', $entry[0][0]); |
||||
407 | $result['duplex'] = strtolower($entry[0][0][0]); |
||||
408 | $entry[1] = trim($entry[1]); |
||||
409 | if (mb_strpos($entry[1], 'Auto') !== false) { |
||||
410 | $result['speed'] = 'auto'; |
||||
411 | } else { |
||||
412 | $result['speed'] = (int) $entry[1]; |
||||
413 | } // if .. else |
||||
414 | $entry[2] = rtrim($entry[2]); |
||||
415 | $result['type'] = mb_substr($entry[2], mb_strrpos($entry[2], ' ') + 1); |
||||
416 | } elseif (mb_strpos($entry, 'input rate') !== false) { |
||||
417 | $entry = explode(',', $entry); |
||||
418 | $result['in_rate'] = mb_substr($entry[0], mb_strpos($entry[0], 'rate') + 5, mb_strrpos($entry[0], ' ') - (mb_strpos($entry[0], 'rate') + 5)); |
||||
419 | $entry = trim($entry[1]); |
||||
420 | $entry = explode(' ', $entry); |
||||
421 | $result['in_packet_rate'] = $entry[0]; |
||||
422 | } elseif (mb_strpos($entry, 'output rate') !== false) { |
||||
423 | $entry = explode(',', $entry); |
||||
424 | $result['out_rate'] = mb_substr($entry[0], mb_strpos($entry[0], 'rate') + 5, mb_strrpos($entry[0], ' ') - (mb_strpos($entry[0], 'rate') + 5)); |
||||
425 | $entry = trim($entry[1]); |
||||
426 | $entry = explode(' ', $entry); |
||||
427 | $result['out_packet_rate'] = $entry[0]; |
||||
428 | } elseif (mb_strpos($entry, 'packets input') !== false) { |
||||
429 | $entry = explode(',', $entry); |
||||
430 | $entry[0] = trim($entry[0]); |
||||
431 | $entry[0] = explode(' ', $entry[0]); |
||||
432 | $result['in_packet'] = $entry[0][0]; |
||||
433 | $entry[1] = trim($entry[1]); |
||||
434 | $entry[1] = explode(' ', $entry[1]); |
||||
435 | $result['in'] = $entry[1][0]; |
||||
436 | if (count($entry) > 2) { |
||||
437 | $entry[2] = trim($entry[2]); |
||||
438 | $entry[2] = explode(' ', $entry[2]); |
||||
439 | $result['no_buffer'] = $entry[2][0]; |
||||
440 | } // if |
||||
441 | } elseif (mb_strpos($entry, 'Received') !== false) { |
||||
442 | $entry = explode(',', $entry); |
||||
443 | $entry[0] = trim($entry[0]); |
||||
444 | $entry[0] = explode(' ', $entry[0]); |
||||
445 | $result['broadcast'] = $entry[0][1]; |
||||
446 | if (count($entry) > 1) { |
||||
447 | $entry[1] = trim($entry[1]); |
||||
448 | $entry[1] = explode(' ', $entry[1]); |
||||
449 | $result['runt'] = $entry[1][0]; |
||||
450 | $entry[2] = trim($entry[2]); |
||||
451 | $entry[2] = explode(' ', $entry[2]); |
||||
452 | $result['giant'] = $entry[2][0]; |
||||
453 | $entry[3] = trim($entry[3]); |
||||
454 | $entry[3] = explode(' ', $entry[3]); |
||||
455 | $result['throttle'] = $entry[3][0]; |
||||
456 | } // if |
||||
457 | } elseif (mb_strpos($entry, 'CRC') !== false) { |
||||
458 | $entry = explode(',', $entry); |
||||
459 | $entry[0] = trim($entry[0]); |
||||
460 | $entry[0] = explode(' ', $entry[0]); |
||||
461 | $result['in_error'] = $entry[0][0]; |
||||
462 | $entry[1] = trim($entry[1]); |
||||
463 | $entry[1] = explode(' ', $entry[1]); |
||||
464 | $result['crc'] = $entry[1][0]; |
||||
465 | $entry[2] = trim($entry[2]); |
||||
466 | $entry[2] = explode(' ', $entry[2]); |
||||
467 | $result['frame'] = $entry[2][0]; |
||||
468 | $entry[3] = trim($entry[3]); |
||||
469 | $entry[3] = explode(' ', $entry[3]); |
||||
470 | $result['overrun'] = $entry[3][0]; |
||||
471 | $entry[4] = trim($entry[4]); |
||||
472 | $entry[4] = explode(' ', $entry[4]); |
||||
473 | $result['ignored'] = $entry[4][0]; |
||||
474 | } elseif (mb_strpos($entry, 'watchdog') !== false) { |
||||
475 | $entry = explode(',', $entry); |
||||
476 | $entry[0] = trim($entry[0]); |
||||
477 | $entry[0] = explode(' ', $entry[0]); |
||||
478 | $result['watchdog'] = $entry[0][0]; |
||||
479 | $entry[1] = trim($entry[1]); |
||||
480 | $entry[1] = explode(' ', $entry[1]); |
||||
481 | $result['multicast'] = $entry[1][0]; |
||||
482 | if (count($entry) > 2) { |
||||
483 | $entry[2] = trim($entry[2]); |
||||
484 | $entry[2] = explode(' ', $entry[2]); |
||||
485 | $result['pause_in'] = $entry[2][0]; |
||||
486 | } // if |
||||
487 | } elseif (mb_strpos($entry, 'dribble') !== false) { |
||||
488 | $entry = trim($entry); |
||||
489 | $entry = explode(' ', $entry); |
||||
490 | $result['in_dribble'] = $entry[0]; |
||||
491 | } elseif (mb_strpos($entry, 'packets output') !== false) { |
||||
492 | $entry = explode(',', $entry); |
||||
493 | $entry[0] = trim($entry[0]); |
||||
494 | $entry[0] = explode(' ', $entry[0]); |
||||
495 | $result['out_packet'] = $entry[0][0]; |
||||
496 | $entry[1] = trim($entry[1]); |
||||
497 | $entry[1] = explode(' ', $entry[1]); |
||||
498 | $result['out'] = $entry[1][0]; |
||||
499 | $entry[2] = trim($entry[2]); |
||||
500 | $entry[2] = explode(' ', $entry[2]); |
||||
501 | $result['underrun'] = $entry[2][0]; |
||||
502 | } elseif (mb_strpos($entry, 'output errors') !== false) { |
||||
503 | $entry = explode(',', $entry); |
||||
504 | $entry[0] = trim($entry[0]); |
||||
505 | $entry[0] = explode(' ', $entry[0]); |
||||
506 | $result['out_error'] = $entry[0][0]; |
||||
507 | if (count($entry) > 2) { |
||||
508 | $entry[1] = trim($entry[1]); |
||||
509 | $entry[1] = explode(' ', $entry[1]); |
||||
510 | $result['collision'] = $entry[1][0]; |
||||
511 | $entry[2] = trim($entry[2]); |
||||
512 | $entry[2] = explode(' ', $entry[2]); |
||||
513 | $result['reset'] = $entry[2][0]; |
||||
514 | } else { |
||||
515 | $entry[1] = trim($entry[1]); |
||||
516 | $entry[1] = explode(' ', $entry[1]); |
||||
517 | $result['reset'] = $entry[1][0]; |
||||
518 | } // if .. else |
||||
519 | } elseif (mb_strpos($entry, 'babbles') !== false) { |
||||
520 | $entry = explode(',', $entry); |
||||
521 | $entry[0] = trim($entry[0]); |
||||
522 | $entry[0] = explode(' ', $entry[0]); |
||||
523 | $result['babble'] = $entry[0][0]; |
||||
524 | $entry[1] = trim($entry[1]); |
||||
525 | $entry[1] = explode(' ', $entry[1]); |
||||
526 | $result['late_collision'] = $entry[1][0]; |
||||
527 | $entry[2] = trim($entry[2]); |
||||
528 | $entry[2] = explode(' ', $entry[2]); |
||||
529 | $result['deferred'] = $entry[2][0]; |
||||
530 | } elseif (mb_strpos($entry, 'lost carrier') !== false) { |
||||
531 | $entry = explode(',', $entry); |
||||
532 | $entry[0] = trim($entry[0]); |
||||
533 | $entry[0] = explode(' ', $entry[0]); |
||||
534 | $result['lost_carrier'] = $entry[0][0]; |
||||
535 | $entry[1] = trim($entry[1]); |
||||
536 | $entry[1] = explode(' ', $entry[1]); |
||||
537 | $result['no_carrier'] = $entry[1][0]; |
||||
538 | if (count($entry) > 2) { |
||||
539 | $entry[2] = trim($entry[2]); |
||||
540 | $entry[2] = explode(' ', $entry[2]); |
||||
541 | $result['pause_out'] = $entry[2][0]; |
||||
542 | } // if |
||||
543 | } elseif (mb_strpos($entry, 'output buffer failures') !== false) { |
||||
544 | $entry = explode(',', $entry); |
||||
545 | $entry[0] = trim($entry[0]); |
||||
546 | $entry[0] = explode(' ', $entry[0]); |
||||
547 | $result['out_buffer_fail'] = $entry[0][0]; |
||||
548 | $entry[1] = trim($entry[1]); |
||||
549 | $entry[1] = explode(' ', $entry[1]); |
||||
550 | $result['out_buffer_swap'] = $entry[1][0]; |
||||
551 | } // if .. elseif |
||||
552 | } // foreach |
||||
553 | $this->_data = $result; |
||||
554 | return $this->_data; |
||||
555 | } |
||||
556 | |||||
557 | /** |
||||
558 | * @return array |
||||
559 | */ |
||||
560 | public function trunk_ports() |
||||
561 | { |
||||
562 | $result = []; |
||||
563 | $this->exec('show interface status | include trunk'); |
||||
564 | $this->_data = explode("\r\n", $this->_data); |
||||
565 | array_shift($this->_data); |
||||
566 | array_pop($this->_data); |
||||
567 | if (count($this->_data) > 0) { |
||||
568 | foreach ($this->_data as $interface) { |
||||
569 | $interface = explode(' ', $interface); |
||||
570 | $result[] = $interface[0]; |
||||
571 | } // foreach |
||||
572 | } // if |
||||
573 | $this->_data = $result; |
||||
574 | return $this->_data; |
||||
575 | } |
||||
576 | |||||
577 | /** |
||||
578 | * @return array |
||||
579 | */ |
||||
580 | public function vlans() |
||||
581 | { |
||||
582 | $result = []; |
||||
583 | $this->exec('show spanning-tree summary | include ^VLAN'); |
||||
584 | $this->_data = explode("\r\n", $this->_data); |
||||
585 | array_shift($this->_data); |
||||
586 | array_pop($this->_data); |
||||
587 | if (count($this->_data) > 0) { |
||||
588 | foreach ($this->_data as $vlan) { |
||||
589 | $vlan = explode(' ', $vlan); |
||||
590 | $vlan = mb_substr($vlan[0], 4); |
||||
591 | $result[] = (int) $vlan; |
||||
592 | } // foreach |
||||
593 | } // if |
||||
594 | $this->_data = $result; |
||||
595 | return $this->_data; |
||||
596 | } |
||||
597 | |||||
598 | /** |
||||
599 | * @return array |
||||
600 | */ |
||||
601 | public function errdisabled() |
||||
602 | { |
||||
603 | $result = []; |
||||
604 | $this->exec('show int status err'); |
||||
605 | $this->_data = explode("\r\n", $this->_data); |
||||
606 | for ($i = 0; $i < 2; $i++) { |
||||
607 | array_shift($this->_data); |
||||
608 | } |
||||
609 | array_pop($this->_data); |
||||
610 | $pos = mb_strpos($this->_data[0], 'Status'); |
||||
611 | foreach ($this->_data as $entry) { |
||||
612 | $temp = trim($entry); |
||||
613 | if (mb_strlen($temp) > 1 && $temp[2] != 'r') { |
||||
614 | $entry = []; |
||||
615 | $entry['interface'] = mb_substr($temp, 0, mb_strpos($temp, ' ')); |
||||
616 | $entry['description'] = trim(mb_substr($temp, mb_strpos($temp, ' ') + 1, $pos - mb_strlen($entry['interface']) - 1)); |
||||
617 | $temp = mb_substr($temp, $pos); |
||||
618 | /** @noinspection PrintfScanfArgumentsInspection */ |
||||
619 | $temp = sscanf($temp, '%s %s'); |
||||
620 | $entry['status'] = $temp[0]; |
||||
621 | $entry['reason'] = $temp[1]; |
||||
622 | $result[] = $entry; |
||||
623 | } // if |
||||
624 | } // foreach |
||||
625 | $this->_data = $result; |
||||
626 | return $this->_data; |
||||
627 | } |
||||
628 | |||||
629 | /** |
||||
630 | * @return array |
||||
631 | */ |
||||
632 | public function dhcpsnoop_bindings() |
||||
633 | { |
||||
634 | $result = []; |
||||
635 | $this->exec('sh ip dhcp snoop binding | inc dhcp-snooping'); |
||||
636 | $this->_data = explode("\r\n", $this->_data); |
||||
637 | array_shift($this->_data); |
||||
638 | array_pop($this->_data); |
||||
639 | foreach ($this->_data as $entry) { |
||||
640 | /** @noinspection PrintfScanfArgumentsInspection */ |
||||
641 | $temp = sscanf($entry, '%s %s %s %s %s %s'); |
||||
642 | $entry = []; |
||||
643 | $entry['mac_address'] = $temp[0]; |
||||
644 | $entry['mac_address'] = strtolower(str_replace(':', '', $entry['mac_address'])); |
||||
645 | $entry['ip_address'] = $temp[1]; |
||||
646 | $entry['lease'] = $temp[2]; |
||||
647 | $entry['vlan'] = $temp[4]; |
||||
648 | $entry['interface'] = $temp[5]; |
||||
649 | if ($temp[3] == 'dhcp-snooping') { |
||||
650 | $result[] = $entry; |
||||
651 | } |
||||
652 | } |
||||
653 | $this->_data = $result; |
||||
654 | return $this->_data; |
||||
655 | } |
||||
656 | |||||
657 | /** |
||||
658 | * @return array |
||||
659 | */ |
||||
660 | public function mac_address_table() |
||||
661 | { |
||||
662 | $result = []; |
||||
663 | $omit = $this->trunk_ports(); |
||||
664 | $this->exec('show mac address-table | exclude CPU'); |
||||
665 | $this->_data = str_replace(' ', '', $this->_data); |
||||
666 | $this->_data = explode("\r\n", $this->_data); |
||||
667 | for ($i = 0; $i < 6; $i++) { |
||||
668 | array_shift($this->_data); |
||||
669 | } |
||||
670 | for ($i = 0; $i < 2; $i++) { |
||||
671 | array_pop($this->_data); |
||||
672 | } |
||||
673 | foreach ($this->_data as $entry) { |
||||
674 | /** @noinspection PrintfScanfArgumentsInspection */ |
||||
675 | $temp = sscanf($entry, '%s %s %s %s'); |
||||
676 | $entry = []; |
||||
677 | $entry['mac_address'] = $temp[1]; |
||||
678 | $entry['interface'] = $temp[3]; |
||||
679 | if (in_array($entry['interface'], $omit) == false) { |
||||
680 | $result[] = $entry; |
||||
681 | } // if |
||||
682 | } // foreach |
||||
683 | $this->_data = $result; |
||||
684 | return $this->_data; |
||||
685 | } |
||||
686 | |||||
687 | /** |
||||
688 | * @return array |
||||
689 | */ |
||||
690 | public function arp_table() |
||||
691 | { |
||||
692 | $result = []; |
||||
693 | $this->exec('show arp | exc Incomplete'); |
||||
694 | $this->_data = explode("\r\n", $this->_data); |
||||
695 | for ($i = 0; $i < 2; $i++) { |
||||
696 | array_shift($this->_data); |
||||
697 | } |
||||
698 | array_pop($this->_data); |
||||
699 | foreach ($this->_data as $entry) { |
||||
700 | /** @noinspection PrintfScanfArgumentsInspection */ |
||||
701 | $temp = sscanf($entry, '%s %s %s %s %s %s'); |
||||
702 | $entry = []; |
||||
703 | $entry['ip'] = $temp[1]; |
||||
704 | $entry['mac_address'] = $temp[3]; |
||||
705 | if ($temp[2] == '-') { |
||||
706 | $temp[2] = '0'; |
||||
707 | } |
||||
708 | $entry['age'] = $temp[2]; |
||||
709 | $entry['interface'] = $temp[5]; |
||||
710 | if ($entry['ip'] != 'Address' && $entry['mac_address'] != 'Incomplete') { |
||||
711 | $result[] = $entry; |
||||
712 | } // if |
||||
713 | } // foreach |
||||
714 | $this->_data = $result; |
||||
715 | return $this->_data; |
||||
716 | } |
||||
717 | |||||
718 | /** |
||||
719 | * @return array |
||||
720 | */ |
||||
721 | public function ipv6_neighbor_table() |
||||
722 | { |
||||
723 | $result = []; |
||||
724 | $this->exec('show ipv6 neighbors | exc INCMP'); |
||||
725 | $this->_data = explode("\r\n", $this->_data); |
||||
726 | for ($i = 0; $i < 2; $i++) { |
||||
727 | array_shift($this->_data); |
||||
728 | } |
||||
729 | for ($i = 0; $i < 2; $i++) { |
||||
730 | array_pop($this->_data); |
||||
731 | } |
||||
732 | foreach ($this->_data as $entry) { |
||||
733 | /** @noinspection PrintfScanfArgumentsInspection */ |
||||
734 | $temp = sscanf($entry, '%s %s %s %s %s'); |
||||
735 | $entry = []; |
||||
736 | $entry['ipv6'] = $temp[0]; |
||||
737 | $entry['mac_address'] = $temp[2]; |
||||
738 | $entry['age'] = $temp[1]; |
||||
739 | $entry['interface'] = $temp[4]; |
||||
740 | $result[] = $entry; |
||||
741 | } // foreach |
||||
742 | $this->_data = $result; |
||||
743 | return $this->_data; |
||||
744 | } |
||||
745 | |||||
746 | /** |
||||
747 | * @return array |
||||
748 | */ |
||||
749 | public function ipv6_routers() |
||||
750 | { |
||||
751 | $result = []; |
||||
752 | $this->exec('show ipv6 routers'); |
||||
753 | $this->_data = explode("\r\n", $this->_data); |
||||
754 | array_shift($this->_data); |
||||
755 | array_pop($this->_data); |
||||
756 | for ($i = 0, $iMax = count($this->_data); $i < $iMax; $i++) { |
||||
757 | $entry = trim($this->_data[$i]); |
||||
758 | if (mb_substr($entry, 0, 7) == 'Router ') { |
||||
759 | /** @noinspection PrintfScanfArgumentsInspection */ |
||||
760 | $temp = sscanf($entry, '%s %s %s %s'); |
||||
761 | $entry = []; |
||||
762 | $entry['router'] = $temp[1]; |
||||
763 | $entry['interface'] = str_replace(',', '', $temp[3]); |
||||
764 | /** @noinspection PrintfScanfArgumentsInspection */ |
||||
765 | $temp = sscanf(trim($this->_data[$i + 4]), '%s %s %s'); |
||||
766 | $entry['prefix'] = $temp[1]; |
||||
767 | $i += 5; |
||||
768 | $result[] = $entry; |
||||
769 | } // if |
||||
770 | } // for |
||||
771 | $this->_data = $result; |
||||
772 | return $this->_data; |
||||
773 | } |
||||
774 | |||||
775 | /** |
||||
776 | * @param $config |
||||
777 | * @return null|boolean |
||||
778 | */ |
||||
779 | public function configure($config) |
||||
780 | { |
||||
781 | // USE AT OWN RISK: This function will apply configuration statements to a device. |
||||
782 | // Enabled Only |
||||
783 | if (mb_strpos($this->_prompt, '#') === false) { |
||||
784 | die('Error: User must be enabled to use configure()'.PHP_EOL); |
||||
785 | } |
||||
786 | $this->_data = explode("\n", $config); |
||||
787 | $this->_ssh->write("config t\n"); |
||||
788 | $config_prompt = $this->_ssh->read('/.*[>|#]/', NET_SSH2_READ_REGEX); |
||||
0 ignored issues
–
show
|
|||||
789 | $config_prompt = str_replace("\r\n", '', trim($config_prompt)); |
||||
790 | if (mb_strpos($config_prompt, 'config)#') !== false) { |
||||
791 | foreach ($this->_data as $c) { |
||||
792 | $this->_ssh->write($c."\n"); |
||||
793 | } |
||||
794 | $this->_ssh->write("end\n"); |
||||
795 | } |
||||
796 | $result = $this->_ssh->read($this->_prompt); |
||||
797 | $result = explode("\r\n", $result); |
||||
798 | if (count($this->_data) == (count($result) - 2)) { |
||||
799 | return true; |
||||
800 | } else { |
||||
801 | die('Error: Switch rejected configuration: '.PHP_EOL.$config."\n"); |
||||
802 | } |
||||
803 | } |
||||
804 | |||||
805 | /** |
||||
806 | * @return bool |
||||
807 | */ |
||||
808 | public function write_config() |
||||
809 | { |
||||
810 | $this->exec('write'); |
||||
811 | if (mb_strpos($this->_data, '[OK]') !== false) { |
||||
812 | return true; |
||||
813 | } else { |
||||
814 | return false; |
||||
815 | } |
||||
816 | } |
||||
817 | } |
||||
818 | |||||
819 | /** |
||||
820 | * Class cisco_parser |
||||
821 | */ |
||||
822 | class cisco_parser |
||||
823 | { |
||||
824 | /** |
||||
825 | * @param $lines |
||||
826 | * @param integer $x |
||||
827 | * @return int |
||||
828 | */ |
||||
829 | public function get_space_depth($lines, $x) |
||||
830 | { |
||||
831 | if (preg_match('/^(?P<spaces>\s+)*(?P<rest>\S.*)$/', $lines[$x], $matches)) { |
||||
832 | $cdepth = mb_strlen($matches['spaces']); |
||||
833 | } else { |
||||
834 | $cdepth = 0; |
||||
835 | } |
||||
836 | return $cdepth; |
||||
837 | } |
||||
838 | |||||
839 | /** |
||||
840 | * @param $lines |
||||
841 | * @param int $x |
||||
842 | * @param int $depth |
||||
843 | * @return array |
||||
844 | */ |
||||
845 | public function parse_cisco_children($lines, $x = 0, $depth = 0) |
||||
846 | { |
||||
847 | //global $x; |
||||
848 | $data = []; |
||||
849 | $last_command = false; |
||||
850 | for ($xMax = count($lines); $x < $xMax; $x++) { |
||||
851 | $cdepth = $this->get_space_depth($lines, $x); |
||||
852 | $command = ltrim($lines[$x]); |
||||
853 | $arguments = ''; |
||||
854 | $spacepos = mb_strpos($command, ' '); |
||||
855 | if ($spacepos !== false) { |
||||
856 | $arguments = mb_substr($command, $spacepos + 1); |
||||
857 | $command = mb_substr($command, 0, $spacepos); |
||||
858 | //echo "Got C|$command|A|$arguments|<br>"; |
||||
859 | } |
||||
860 | if ($cdepth == $depth) { |
||||
861 | $new_data = ['command' => $command]; |
||||
862 | if ($arguments != '') { |
||||
863 | $new_data['arguments'] = trim($arguments); |
||||
864 | } |
||||
865 | if ($x + 1 < count($lines)) { |
||||
866 | $next_depth = $this->get_space_depth($lines, $x + 1); |
||||
867 | if ($next_depth > $depth) { |
||||
868 | $new_data['children'] = $this->parse_cisco_children($lines, $x + 1, $next_depth); |
||||
869 | while ($this->get_space_depth($lines, $x + 1) > $depth) { |
||||
870 | ++$x; |
||||
871 | } |
||||
872 | } |
||||
873 | } |
||||
874 | $data[] = $new_data; |
||||
875 | } elseif ($cdepth < $depth) { |
||||
876 | return $data; |
||||
877 | } else { |
||||
878 | echo "SHOULD NEVER GET HERE\n"; |
||||
879 | } |
||||
880 | } |
||||
881 | return $data; |
||||
882 | } |
||||
883 | } |
||||
884 |