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; |
||||
0 ignored issues
–
show
Unused Code
introduced
by
![]() |
|||||
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
It seems like
$match can also be of type array ; however, parameter $needle of mb_strpos() 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
![]() |
|||||
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); |
||||
0 ignored issues
–
show
sleep(1) is not reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||||
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); |
||||
0 ignored issues
–
show
|
|||||
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) { |
||||
0 ignored issues
–
show
|
|||||
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); |
||||
0 ignored issues
–
show
|
|||||
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"); |
||||
0 ignored issues
–
show
|
|||||
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; |
||||
0 ignored issues
–
show
|
|||||
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 |