diff --git a/configs/models/Alcatel-switches.yml b/configs/models/Alcatel-switches.yml index 9df49de..72b41d7 100644 --- a/configs/models/Alcatel-switches.yml +++ b/configs/models/Alcatel-switches.yml @@ -32,4 +32,5 @@ models: net_settings: \SwitcherCore\Modules\General\NetSettings clear_iface_counters: SwitcherCore\Modules\AlcatelSwitch\ClearIfaceCounters supported_modules: \SwitcherCore\Modules\General\SupportedModules - sys_temp: \SwitcherCore\Modules\AlcatelSwitch\SystemTemperatures \ No newline at end of file + sys_temp: \SwitcherCore\Modules\AlcatelSwitch\SystemTemperatures + snooping_info: \SwitcherCore\Modules\AlcatelSwitch\SnoopingInfo \ No newline at end of file diff --git a/configs/models/BDcom.yml b/configs/models/BDcom.yml index 2d8d529..5344290 100644 --- a/configs/models/BDcom.yml +++ b/configs/models/BDcom.yml @@ -62,6 +62,7 @@ models: sfp_diag: \SwitcherCore\Modules\General\SfpDiag sfp_optical: \SwitcherCore\Modules\BDcom\GP3600\SfpOpticalInfo sys_temp: \SwitcherCore\Modules\General\SystemTemperatures + snooping_info: \SwitcherCore\Modules\BDcom\GP3600\SnoopingInfo extra: pon_port_size: 128 console_conn_type: bdcom @@ -116,6 +117,7 @@ models: sfp_diag: \SwitcherCore\Modules\General\SfpDiag sfp_optical: \SwitcherCore\Modules\BDcom\SfpOpticalInfo sys_temp: \SwitcherCore\Modules\General\SystemTemperatures + snooping_info: \SwitcherCore\Modules\BDcom\SnoopingInfo extra: pon_port_size: 64 console_conn_type: bdcom @@ -171,6 +173,7 @@ models: sfp_diag: \SwitcherCore\Modules\General\SfpDiag sfp_optical: \SwitcherCore\Modules\BDcom\SfpOpticalInfo sys_temp: \SwitcherCore\Modules\General\SystemTemperatures + snooping_info: \SwitcherCore\Modules\BDcom\SnoopingInfo extra: pon_port_size: 64 console_conn_type: bdcom @@ -226,6 +229,7 @@ models: sfp_diag: \SwitcherCore\Modules\General\SfpDiag sfp_optical: \SwitcherCore\Modules\BDcom\SfpOpticalInfo sys_temp: \SwitcherCore\Modules\General\SystemTemperatures + snooping_info: \SwitcherCore\Modules\BDcom\SnoopingInfo extra: pon_port_size: 64 console_conn_type: bdcom @@ -281,6 +285,7 @@ models: sfp_diag: \SwitcherCore\Modules\General\SfpDiag sfp_optical: \SwitcherCore\Modules\BDcom\SfpOpticalInfo sys_temp: \SwitcherCore\Modules\General\SystemTemperatures + snooping_info: \SwitcherCore\Modules\BDcom\SnoopingInfo extra: pon_port_size: 64 console_conn_type: bdcom @@ -336,6 +341,7 @@ models: sfp_diag: \SwitcherCore\Modules\General\SfpDiag sfp_optical: \SwitcherCore\Modules\BDcom\SfpOpticalInfo sys_temp: \SwitcherCore\Modules\General\SystemTemperatures + snooping_info: \SwitcherCore\Modules\BDcom\SnoopingInfo extra: pon_port_size: 64 console_conn_type: bdcom @@ -391,6 +397,7 @@ models: sfp_diag: \SwitcherCore\Modules\General\SfpDiag sfp_optical: \SwitcherCore\Modules\BDcom\SfpOpticalInfo sys_temp: \SwitcherCore\Modules\General\SystemTemperatures + snooping_info: \SwitcherCore\Modules\BDcom\SnoopingInfo extra: pon_port_size: 64 console_conn_type: bdcom @@ -447,6 +454,7 @@ models: sfp_diag: \SwitcherCore\Modules\General\SfpDiag sfp_optical: \SwitcherCore\Modules\BDcom\SfpOpticalInfo sys_temp: \SwitcherCore\Modules\General\SystemTemperatures + snooping_info: \SwitcherCore\Modules\BDcom\SnoopingInfo extra: pon_port_size: 64 console_conn_type: bdcom diff --git a/configs/models/C-Data.yml b/configs/models/C-Data.yml index 125b905..d5ab3cc 100755 --- a/configs/models/C-Data.yml +++ b/configs/models/C-Data.yml @@ -38,6 +38,7 @@ models: interface_counters: \SwitcherCore\Modules\CData\FD11XX\InterfaceCounters supported_modules: \SwitcherCore\Modules\General\SupportedModules sys_temp: \SwitcherCore\Modules\General\SystemTemperatures + snooping_info: \SwitcherCore\Modules\CData\FD11XX\SnoopingInfo extra: pon_port_size: 64 pon_type: EPON @@ -96,6 +97,7 @@ models: pon_ports_optical: \SwitcherCore\Modules\CData\FD11XX\PonPortsOptical supported_modules: \SwitcherCore\Modules\General\SupportedModules sys_temp: \SwitcherCore\Modules\General\SystemTemperatures + snooping_info: \SwitcherCore\Modules\CData\FD11XX\SnoopingInfo extra: pon_type: EPON console_conn_type: stels @@ -162,6 +164,7 @@ models: pon_onts_configuration: \SwitcherCore\Modules\CData\PonOntsConfiguration supported_modules: \SwitcherCore\Modules\General\SupportedModules sys_temp: \SwitcherCore\Modules\CData\SystemTemperatures + snooping_info: \SwitcherCore\Modules\CData\SnoopingInfo extra: pon_type: EPON @@ -228,6 +231,7 @@ models: pon_onts_configuration: \SwitcherCore\Modules\CData\PonOntsConfiguration supported_modules: \SwitcherCore\Modules\General\SupportedModules sys_temp: \SwitcherCore\Modules\CData\SystemTemperatures + snooping_info: \SwitcherCore\Modules\CData\SnoopingInfo extra: pon_type: EPON @@ -304,6 +308,7 @@ models: pon_onts_configuration: \SwitcherCore\Modules\CData\PonOntsConfiguration supported_modules: \SwitcherCore\Modules\General\SupportedModules sys_temp: \SwitcherCore\Modules\CData\SystemTemperatures + snooping_info: \SwitcherCore\Modules\CData\SnoopingInfo extra: pon_type: EPON @@ -391,6 +396,7 @@ models: pon_onts_configuration: \SwitcherCore\Modules\CData\FD16xxV3\PonOntsConfiguration supported_modules: \SwitcherCore\Modules\General\SupportedModules sys_temp: \SwitcherCore\Modules\CData\FD16xxV3\SystemTemperatures + snooping_info: \SwitcherCore\Modules\CData\FD16xxV3\SnoopingInfo extra: pon_type: GPON pon_port_size: 128 @@ -429,6 +435,7 @@ models: pon_onts_configuration: \SwitcherCore\Modules\CData\PonOntsConfiguration supported_modules: \SwitcherCore\Modules\General\SupportedModules sys_temp: \SwitcherCore\Modules\CData\SystemTemperatures + snooping_info: \SwitcherCore\Modules\CData\SnoopingInfo extra: pon_type: GPON pon_port_size: 128 @@ -500,6 +507,7 @@ models: pon_onts_configuration: \SwitcherCore\Modules\CData\FD16xxV3\PonOntsConfiguration supported_modules: \SwitcherCore\Modules\General\SupportedModules sys_temp: \SwitcherCore\Modules\CData\FD16xxV3\SystemTemperatures + snooping_info: \SwitcherCore\Modules\CData\FD16xxV3\SnoopingInfo extra: pon_type: GPON pon_port_size: 128 @@ -541,6 +549,7 @@ models: pon_onts_configuration: \SwitcherCore\Modules\CData\PonOntsConfiguration supported_modules: \SwitcherCore\Modules\General\SupportedModules sys_temp: \SwitcherCore\Modules\CData\SystemTemperatures + snooping_info: \SwitcherCore\Modules\CData\SnoopingInfo extra: pon_type: GPON pon_port_size: 128 @@ -613,6 +622,7 @@ models: pon_onts_configuration: \SwitcherCore\Modules\CData\FD16xxV3\PonOntsConfiguration supported_modules: \SwitcherCore\Modules\General\SupportedModules sys_temp: \SwitcherCore\Modules\CData\FD16xxV3\SystemTemperatures + snooping_info: \SwitcherCore\Modules\CData\FD16xxV3\SnoopingInfo extra: pon_type: GPON pon_port_size: 128 @@ -728,6 +738,7 @@ models: sfp_diag: \SwitcherCore\Modules\CData\FD16xxV3\SfpDiag supported_modules: \SwitcherCore\Modules\General\SupportedModules sys_temp: \SwitcherCore\Modules\CData\FD16xxV3\SystemTemperatures + snooping_info: \SwitcherCore\Modules\CData\FD16xxV3\SnoopingInfo extra: pon_type: GPON pon_port_size: 128 @@ -766,6 +777,7 @@ models: pon_onts_configuration: \SwitcherCore\Modules\CData\PonOntsConfiguration supported_modules: \SwitcherCore\Modules\General\SupportedModules sys_temp: \SwitcherCore\Modules\CData\SystemTemperatures + snooping_info: \SwitcherCore\Modules\CData\SnoopingInfo extra: pon_type: GPON pon_port_size: 128 diff --git a/configs/models/Raisecom.yml b/configs/models/Raisecom.yml index ff779b5..038804a 100644 --- a/configs/models/Raisecom.yml +++ b/configs/models/Raisecom.yml @@ -38,6 +38,7 @@ models: clear_iface_counters: \SwitcherCore\Modules\Raisecom\ClearIfaceCounters supported_modules: \SwitcherCore\Modules\General\SupportedModules sys_temp: \SwitcherCore\Modules\General\SystemTemperatures + snooping_info: \SwitcherCore\Modules\Raisecom\SnoopingInfo - name: Raisecom ISCOM key: raisecom_iscom @@ -77,6 +78,7 @@ models: clear_iface_counters: \SwitcherCore\Modules\Raisecom\ClearIfaceCounters supported_modules: \SwitcherCore\Modules\General\SupportedModules sys_temp: \SwitcherCore\Modules\General\SystemTemperatures + snooping_info: \SwitcherCore\Modules\Raisecom\SnoopingInfo - name: Raisecom RAX721 key: raisecom_rax721 @@ -114,6 +116,7 @@ models: multi_console_command: \SwitcherCore\Modules\General\Switches\MultiRawConsoleCommand clear_iface_counters: \SwitcherCore\Modules\Raisecom\ClearIfaceCounters supported_modules: \SwitcherCore\Modules\General\SupportedModules + #snooping_info: \SwitcherCore\Modules\Raisecom\SnoopingInfo - name: Raisecom Default key: raisecom_default @@ -122,6 +125,8 @@ models: inputs: - snmp - console + oids: + - ./oids/raisecom/iscom.yml extra: console_conn_type: raisecom modules: @@ -146,4 +151,5 @@ models: multi_console_command: \SwitcherCore\Modules\General\Switches\MultiRawConsoleCommand clear_iface_counters: \SwitcherCore\Modules\Raisecom\ClearIfaceCounters supported_modules: \SwitcherCore\Modules\General\SupportedModules - sys_temp: \SwitcherCore\Modules\General\SystemTemperatures \ No newline at end of file + sys_temp: \SwitcherCore\Modules\General\SystemTemperatures + snooping_info: \SwitcherCore\Modules\Raisecom\SnoopingInfo \ No newline at end of file diff --git a/configs/models/ZTE-C-series.yml b/configs/models/ZTE-C-series.yml index 56e49e8..34664a7 100755 --- a/configs/models/ZTE-C-series.yml +++ b/configs/models/ZTE-C-series.yml @@ -261,6 +261,7 @@ models: sfp_diag: \SwitcherCore\Modules\General\SfpDiag onu_ip_host: \SwitcherCore\Modules\ZTE\C600Series\OnuIpHost supported_modules: \SwitcherCore\Modules\General\SupportedModules + snooping_info: \SwitcherCore\Modules\ZTE\C600Series\SnoopingInfo extra: console_conn_type: zte diff --git a/configs/modules.yml b/configs/modules.yml index e4873c4..d184585 100755 --- a/configs/modules.yml +++ b/configs/modules.yml @@ -514,6 +514,7 @@ - name: snooping_info descr: Return information about DHCP snooping arguments: + - {name: ip, pattern: '^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$', required: no} - {name: interface, pattern: '.*', required: no} - {name: mac_address, pattern: '.*', required: no} - {name: vlan_id, pattern: '.*', required: no} diff --git a/configs/oids/raisecom/iscom.yml b/configs/oids/raisecom/iscom.yml index 73591a8..0491b0c 100644 --- a/configs/oids/raisecom/iscom.yml +++ b/configs/oids/raisecom/iscom.yml @@ -14,4 +14,11 @@ # .1.3.6.1.4.1.8886.1.18.2.2.1.1.2.{iface_id}.4 - Optical Rx Power. Divide value by 1000 to get in dBm # .1.3.6.1.4.1.8886.1.18.2.2.1.1.2.{iface_id}.5 - Supply Voltage. Divide value by 1000 to get in Volts - - {name: sensors.temperature.cpu, oid: .1.3.6.1.4.1.8886.1.1.4.2.1} \ No newline at end of file + - {name: sensors.temperature.cpu, oid: .1.3.6.1.4.1.8886.1.1.4.2.1} + + # DHCP Snooping: + - {name: dhcpSnooping.bindMac, oid: .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.2} # .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.2.4.10.31.10.7 = Hex-STRING: 90 1B 0E 65 51 36 | Do not know what is '4' before ip addresses + - {name: dhcpSnooping.bindLease, oid: .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.3} # .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.3.4.10.31.10.7 = Gauge32: 540 | remaining lease time in seconds | Do not know what is '4' before ip addresses + - {name: dhcpSnooping.bindVlan, oid: .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.4} # .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.4.4.10.31.10.7 = INTEGER: 31 | Do not know what is '4' before ip addresses + - {name: dhcpSnooping.bindPort, oid: .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.5} # .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.5.4.10.31.10.7 = INTEGER: 2082476041 | Do not know what is '4' before ip addresses + diff --git a/configs/oids/raisecom/iscom2600.yml b/configs/oids/raisecom/iscom2600.yml index 390964c..fbb9139 100644 --- a/configs/oids/raisecom/iscom2600.yml +++ b/configs/oids/raisecom/iscom2600.yml @@ -1,2 +1,9 @@ - {name: if.StatsDuplexStatus, oid: .1.3.6.1.2.1.10.7.2.1.19, access: read , values: {1: Down, 2: Full, 3: Half}} - - {name: sensors.temperature.cpu, oid: .1.3.6.1.4.1.8886.1.1.4.2.1} \ No newline at end of file + - {name: sensors.temperature.cpu, oid: .1.3.6.1.4.1.8886.1.1.4.2.1} + + + # DHCP Snooping (can be wrong): + - {name: dhcpSnooping.bindMac, oid: .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.2} # .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.2.4.10.31.10.7 = Hex-STRING: 90 1B 0E 65 51 36 | Do not know what is '4' before ip addresses + - {name: dhcpSnooping.bindLease, oid: .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.3} # .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.3.4.10.31.10.7 = Gauge32: 540 | remaining lease time in seconds | Do not know what is '4' before ip addresses + - {name: dhcpSnooping.bindVlan, oid: .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.4} # .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.4.4.10.31.10.7 = INTEGER: 31 | Do not know what is '4' before ip addresses + - {name: dhcpSnooping.bindPort, oid: .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.5} # .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.5.4.10.31.10.7 = INTEGER: 2082476041 | Do not know what is '4' before ip addresses \ No newline at end of file diff --git a/configs/oids/raisecom/rax721.yml b/configs/oids/raisecom/rax721.yml index 7b6372f..f72d8df 100644 --- a/configs/oids/raisecom/rax721.yml +++ b/configs/oids/raisecom/rax721.yml @@ -15,4 +15,10 @@ # .1.3.6.1.4.1.8886.60.18.1.2.2.1.1.2.{iface_id}.4 - Optical Rx Power. Divide value by 1000 to get in dBm # .1.3.6.1.4.1.8886.60.18.1.2.2.1.1.2.{iface_id}.5 - Supply Voltage. Divide value by 1000 to get in Volts - - {name: sensors.temperature.cpu, oid: .1.3.6.1.4.1.8886.1.1.4.2.1} \ No newline at end of file + - {name: sensors.temperature.cpu, oid: .1.3.6.1.4.1.8886.1.1.4.2.1} + + # DHCP Snooping (can be wrong): + - {name: dhcpSnooping.bindMac, oid: .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.2} # .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.2.4.10.31.10.7 = Hex-STRING: 90 1B 0E 65 51 36 | Do not know what is '4' before ip addresses + - {name: dhcpSnooping.bindLease, oid: .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.3} # .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.3.4.10.31.10.7 = Gauge32: 540 | remaining lease time in seconds | Do not know what is '4' before ip addresses + - {name: dhcpSnooping.bindVlan, oid: .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.4} # .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.4.4.10.31.10.7 = INTEGER: 31 | Do not know what is '4' before ip addresses + - {name: dhcpSnooping.bindPort, oid: .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.5} # .1.3.6.1.4.1.8886.6.1.23.1.1.5.1.5.4.10.31.10.7 = INTEGER: 2082476041 | Do not know what is '4' before ip addresses \ No newline at end of file diff --git a/src/Modules/AlcatelSwitch/SnoopingInfo.php b/src/Modules/AlcatelSwitch/SnoopingInfo.php new file mode 100644 index 0000000..d9f2c42 --- /dev/null +++ b/src/Modules/AlcatelSwitch/SnoopingInfo.php @@ -0,0 +1,96 @@ +response; + } + + function getPrettyFiltered($filter = [], $fromCache = false) { + $data = $this->getPretty(); + if(count($data) === 0) return []; + if ($filter['interface']) { + $interface = $this->parseInterface($filter['interface']); + $data = array_filter($data, function ($e) use ($interface) { + return $e['interface']['id'] == $interface['id']; + }); + } + if ($filter['mac_address']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['mac_address'] == Helper::formatMac($filter['mac_address']); + }); + } + if ($filter['vlan_id']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['vlan_id'] == $filter['vlan_id']; + }); + } + if ($filter['ip']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['ip'] == $filter['ip']; + }); + } + return array_values($data); + } + + function getPretty() { + return $this->response; + } + + + /** + * @param array $filter + * @return $this|AbstractModule + * @throws Exception + */ + public function run($filter = []) { + $cmd = 'show ip dhcp snooping binding'; + if(isset($filter['interface'])) { + $iface = $this->parseInterface($filter['interface']); + $cmd .= ' ethernet ' . $iface['name']; + } elseif(isset($filter['mac_address'])) { + $mac = strtolower(Helper::formatMac($filter['mac_address'])); + $cmd .= ' mac-address ' . $mac; + } elseif(isset($filter['ip'])) { + $cmd .= ' ip-address ' . $filter['ip']; + } elseif(isset($filter['vlan_id'])) { + $cmd .= ' vlan ' . $filter['vlan_id']; + } + $r = $this->getModule('console_command')->run(['command' => $cmd])->getPretty(); + $r = explode("\n", $r['output']); + + $resp = []; + foreach($r as $line) { + $m = []; + if(preg_match('/^((([0-9a-f]{2}):?){6})\s+((\d{1,3}\.?){4})\s+(\d{1,5})\s+(\w{3,})\s+(\d{1,4})\s+([eg]\d{1,3})/i', trim($line), $m)) { + $resp[] = [ + 'interface' => $this->parseInterface($m[9], 'name'), + 'mac_address' => Helper::formatMac($m[1]), + 'vlan_id' => (int) $m[8], + 'ip' => $m[4], + 'remaining' => (int) $m[6], + '_type' => strtoupper($m[7]), + ]; + } + } + $this->response = $resp; + return $this; + } +} + diff --git a/src/Modules/BDcom/GP3600/SnoopingInfo.php b/src/Modules/BDcom/GP3600/SnoopingInfo.php new file mode 100644 index 0000000..cf74cd4 --- /dev/null +++ b/src/Modules/BDcom/GP3600/SnoopingInfo.php @@ -0,0 +1,91 @@ +response; + } + + function getPrettyFiltered($filter = [], $fromCache = false) { + $data = $this->getPretty(); + if ($filter['interface']) { + $interface = $this->parseInterface($filter['interface']); + $data = array_filter($data, function ($e) use ($interface) { + return $e['interface']['id'] == $interface['id']; + }); + } + if ($filter['mac_address']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['mac_address'] == Helper::formatMac($filter['mac_address']); + }); + } + if ($filter['vlan_id']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['vlan_id'] == $filter['vlan_id']; + }); + } + if ($filter['ip']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['ip'] == $filter['ip']; + }); + } + return array_values($data); + } + + function getPretty() { + return $this->response; + } + + + /** + * @param array $filter + * @return $this|AbstractModule + * @throws Exception + */ + public function run($filter = []) { + $cmd = 'show ip dhcp-relay snooping binding all'; + if(isset($filter['interface'])) { + $iface = $this->parseInterface($filter['interface']); + $cmd .= ' | include "' . $iface['name'] . '"'; + } elseif(isset($filter['mac_address'])) { + $mac = strtolower(Helper::formatMac($filter['mac_address'])); + $cmd .= ' | include "' . $mac . '"'; + } elseif(isset($filter['ip'])) { + $cmd .= ' | include "' . $filter['ip'] . '"'; + } elseif(isset($filter['vlan_id'])) { + $cmd .= ' | include "' . $filter['vlan_id'] . '"'; + } + $r = $this->getModule('console_command')->run(['command' => $cmd])->getPretty(); + $r = explode("\n", $r['output']); + $resp = []; + foreach($r as $line) { + $m = []; + if(preg_match('/^(([0-9a-f]{2}:?){6})\s+((\d{1,3}\.?){4})\s+(\d{1,10})\s+(dhcp_sn|manual)\s+(\d{1,4})\s+((g|tg|epon|gpon|fe)\d{1,3}\/\d{1,3})$/i', trim($line), $m)) { + if(isset($filter['vlan_id']) && $m[7] != $filter['vlan_id']) continue; + $resp[] = [ + 'interface' => $this->parseInterface($m[8]), + 'mac_address' => Helper::formatMac($m[1]), + 'vlan_id' => (int) $m[7], + 'ip' => $m[3], + 'remaining' => (int) $m[5], + '_type' => strtoupper($m[6]), + ]; + } + } + $this->response = $resp; + return $this; + } +} + diff --git a/src/Modules/BDcom/SnoopingInfo.php b/src/Modules/BDcom/SnoopingInfo.php new file mode 100644 index 0000000..0d7aee1 --- /dev/null +++ b/src/Modules/BDcom/SnoopingInfo.php @@ -0,0 +1,91 @@ +response; + } + + function getPrettyFiltered($filter = [], $fromCache = false) { + $data = $this->getPretty(); + if ($filter['interface']) { + $interface = $this->parseInterface($filter['interface']); + $data = array_filter($data, function ($e) use ($interface) { + return $e['interface']['id'] == $interface['id']; + }); + } + if ($filter['mac_address']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['mac_address'] == Helper::formatMac($filter['mac_address']); + }); + } + if ($filter['vlan_id']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['vlan_id'] == $filter['vlan_id']; + }); + } + if ($filter['ip']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['ip'] == $filter['ip']; + }); + } + return array_values($data); + } + + function getPretty() { + return $this->response; + } + + + /** + * @param array $filter + * @return $this|AbstractModule + * @throws Exception + */ + public function run($filter = []) { + $cmd = 'show ip dhcp-relay snooping binding all'; + if(isset($filter['interface'])) { + $iface = $this->parseInterface($filter['interface']); + $cmd .= ' | include "' . $iface['name'] . '"'; + } elseif(isset($filter['mac_address'])) { + $mac = strtolower(Helper::formatMac($filter['mac_address'])); + $cmd .= ' | include "' . $mac . '"'; + } elseif(isset($filter['ip'])) { + $cmd .= ' | include "' . $filter['ip'] . '"'; + } elseif(isset($filter['vlan_id'])) { + $cmd .= ' | include "' . $filter['vlan_id'] . '"'; + } + $r = $this->getModule('console_command')->run(['command' => $cmd])->getPretty(); + $r = explode("\n", $r['output']); + $resp = []; + foreach($r as $line) { + $m = []; + if(preg_match('/^(([0-9a-f]{2}:?){6})\s+((\d{1,3}\.?){4})\s+(\d{1,10})\s+(dhcp_sn|manual)\s+(\d{1,4})\s+((g|tg|epon|gpon|fe)\d{1,3}\/\d{1,3})$/i', trim($line), $m)) { + if(isset($filter['vlan_id']) && $m[7] != $filter['vlan_id']) continue; + $resp[] = [ + 'interface' => $this->parseInterface($m[8]), + 'mac_address' => Helper::formatMac($m[1]), + 'vlan_id' => (int) $m[7], + 'ip' => $m[3], + 'remaining' => (int) $m[5], + '_type' => strtoupper($m[6]), + ]; + } + } + $this->response = $resp; + return $this; + } +} + diff --git a/src/Modules/CData/FD11XX/SnoopingInfo.php b/src/Modules/CData/FD11XX/SnoopingInfo.php new file mode 100644 index 0000000..654cb5c --- /dev/null +++ b/src/Modules/CData/FD11XX/SnoopingInfo.php @@ -0,0 +1,95 @@ +response; + } + + function getPrettyFiltered($filter = [], $fromCache = false) { + $data = $this->getPretty(); + if ($filter['interface']) { + $interface = $this->parseInterface($filter['interface']); + $data = array_filter($data, function ($e) use ($interface) { + return $e['interface']['id'] == $interface['id']; + }); + } + if ($filter['mac_address']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['mac_address'] == Helper::formatMac($filter['mac_address']); + }); + } + if ($filter['vlan_id']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['vlan_id'] == $filter['vlan_id']; + }); + } + if ($filter['ip']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['ip'] == $filter['ip']; + }); + } + return array_values($data); + } + + function getPretty() { + return $this->response; + } + + + /** + * @param array $filter + * @return $this|AbstractModule + * @throws Exception + */ + public function run($filter = []) { + $cmd = 'show dhcp security-table'; + if(isset($filter['interface'])) { + $iface = $this->parseInterface($filter['interface']); + $if_name = $iface['name']; + if(strpos($if_name, 'gpon') !== false) $if_name = str_replace('gpon', 'pon', $if_name); + $cmd .= ' port ' . $if_name; + } elseif(isset($filter['mac_address'])) { + $mac = Helper::formatMac($filter['mac_address']); + $cmd .= ' mac ' . $mac; + } elseif(isset($filter['ip'])) { + $cmd .= ' ' . $filter['ip']; + } elseif(isset($filter['vlan_id'])) { + $cmd .= ' vlan ' . $filter['vlan_id']; + } + $r = $this->getModule('console_command')->run(['command' => $cmd])->getPretty(); + $r = explode("\n", $r['output']); + $resp = []; + + foreach($r as $line) { + $m = []; + if(preg_match('/^(([0-9a-f]{2}:?){6})\s+((\d{1,3}\.?){4})\s+(\d{1,4})\s+((ge|lag|xge|epon|gpon|fe)\s\d{1,3}\/\d{1,3}\/\d{1,3})\s+(\d{1,10})\s+(dynamic|static)\s+(valid|invalid)$/i', trim($line), $m)) { + if(strtoupper($m[10]) === 'INVALID') continue; + $resp[] = [ + 'interface' => $this->parseInterface($m[6]), + 'mac_address' => Helper::formatMac($m[1]), + 'vlan_id' => (int) $m[5], + 'ip' => $m[3], + 'remaining' => (int) $m[8], + '_type' => strtoupper($m[9]), + //'_status' => strtoupper($m[10]), + ]; + } + } + $this->response = $resp; + return $this; + } +} + diff --git a/src/Modules/CData/FD16xxV3/SnoopingInfo.php b/src/Modules/CData/FD16xxV3/SnoopingInfo.php new file mode 100644 index 0000000..70f717d --- /dev/null +++ b/src/Modules/CData/FD16xxV3/SnoopingInfo.php @@ -0,0 +1,95 @@ +response; + } + + function getPrettyFiltered($filter = [], $fromCache = false) { + $data = $this->getPretty(); + if ($filter['interface']) { + $interface = $this->parseInterface($filter['interface']); + $data = array_filter($data, function ($e) use ($interface) { + return $e['interface']['id'] == $interface['id']; + }); + } + if ($filter['mac_address']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['mac_address'] == Helper::formatMac($filter['mac_address']); + }); + } + if ($filter['vlan_id']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['vlan_id'] == $filter['vlan_id']; + }); + } + if ($filter['ip']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['ip'] == $filter['ip']; + }); + } + return array_values($data); + } + + function getPretty() { + return $this->response; + } + + + /** + * @param array $filter + * @return $this|AbstractModule + * @throws Exception + */ + public function run($filter = []) { + $cmd = 'show dhcp security-table'; + if(isset($filter['interface'])) { + $iface = $this->parseInterface($filter['interface']); + $if_name = $iface['name']; + if(strpos($if_name, 'gpon') !== false) $if_name = str_replace('gpon', 'pon', $if_name); + $cmd .= ' port ' . $if_name; + } elseif(isset($filter['mac_address'])) { + $mac = Helper::formatMac($filter['mac_address']); + $cmd .= ' mac ' . $mac; + } elseif(isset($filter['ip'])) { + $cmd .= ' ' . $filter['ip']; + } elseif(isset($filter['vlan_id'])) { + $cmd .= ' vlan ' . $filter['vlan_id']; + } + $r = $this->getModule('console_command')->run(['command' => $cmd])->getPretty(); + $r = explode("\n", $r['output']); + $resp = []; + + foreach($r as $line) { + $m = []; + if(preg_match('/^(([0-9a-f]{2}:?){6})\s+((\d{1,3}\.?){4})\s+(\d{1,4})\s+((ge|lag|xge|epon|gpon|fe)\s\d{1,3}\/\d{1,3}\/\d{1,3})\s+(\d{1,10})\s+(dynamic|static)\s+(valid|invalid)$/i', trim($line), $m)) { + if(strtoupper($m[10]) === 'INVALID') continue; + $resp[] = [ + 'interface' => $this->parseInterface($m[6]), + 'mac_address' => Helper::formatMac($m[1]), + 'vlan_id' => (int) $m[5], + 'ip' => $m[3], + 'remaining' => (int) $m[8], + '_type' => strtoupper($m[9]), + //'_status' => strtoupper($m[10]), + ]; + } + } + $this->response = $resp; + return $this; + } +} + diff --git a/src/Modules/CData/SnoopingInfo.php b/src/Modules/CData/SnoopingInfo.php new file mode 100644 index 0000000..fe0acd7 --- /dev/null +++ b/src/Modules/CData/SnoopingInfo.php @@ -0,0 +1,95 @@ +response; + } + + function getPrettyFiltered($filter = [], $fromCache = false) { + $data = $this->getPretty(); + if ($filter['interface']) { + $interface = $this->parseInterface($filter['interface']); + $data = array_filter($data, function ($e) use ($interface) { + return $e['interface']['id'] == $interface['id']; + }); + } + if ($filter['mac_address']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['mac_address'] == Helper::formatMac($filter['mac_address']); + }); + } + if ($filter['vlan_id']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['vlan_id'] == $filter['vlan_id']; + }); + } + if ($filter['ip']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['ip'] == $filter['ip']; + }); + } + return array_values($data); + } + + function getPretty() { + return $this->response; + } + + + /** + * @param array $filter + * @return $this|AbstractModule + * @throws Exception + */ + public function run($filter = []) { + $cmd = 'show dhcp security-table'; + if(isset($filter['interface'])) { + $iface = $this->parseInterface($filter['interface']); + $if_name = $iface['name']; + if(strpos($if_name, 'gpon') !== false) $if_name = str_replace('gpon', 'pon', $if_name); + $cmd .= ' port ' . $if_name; + } elseif(isset($filter['mac_address'])) { + $mac = Helper::formatMac($filter['mac_address']); + $cmd .= ' mac ' . $mac; + } elseif(isset($filter['ip'])) { + $cmd .= ' ' . $filter['ip']; + } elseif(isset($filter['vlan_id'])) { + $cmd .= ' vlan ' . $filter['vlan_id']; + } + $r = $this->getModule('console_command')->run(['command' => $cmd])->getPretty(); + $r = explode("\n", $r['output']); + $resp = []; + + foreach($r as $line) { + $m = []; + if(preg_match('/^(([0-9a-f]{2}:?){6})\s+((\d{1,3}\.?){4})\s+(\d{1,4})\s+((ge|lag|xge|epon|gpon|fe)\s\d{1,3}\/\d{1,3}\/\d{1,3})\s+(\d{1,10})\s+(dynamic|static)\s+(valid|invalid)$/i', trim($line), $m)) { + if(strtoupper($m[10]) === 'INVALID') continue; + $resp[] = [ + 'interface' => $this->parseInterface($m[6]), + 'mac_address' => Helper::formatMac($m[1]), + 'vlan_id' => (int) $m[5], + 'ip' => $m[3], + 'remaining' => (int) $m[8], + '_type' => strtoupper($m[9]), + //'_status' => strtoupper($m[10]), + ]; + } + } + $this->response = $resp; + return $this; + } +} + diff --git a/src/Modules/Raisecom/SnoopingInfo.php b/src/Modules/Raisecom/SnoopingInfo.php new file mode 100644 index 0000000..1414a70 --- /dev/null +++ b/src/Modules/Raisecom/SnoopingInfo.php @@ -0,0 +1,110 @@ +response; + } + + function getPrettyFiltered($filter = [], $fromCache = false) { + $data = $this->getPretty(); + if(count($data) === 0) return []; + if ($filter['interface']) { + $interface = $this->parseInterface($filter['interface']); + $data = array_filter($data, function ($e) use ($interface) { + return $e['interface']['id'] == $interface['id']; + }); + } + if ($filter['mac_address']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['mac_address'] == Helper::formatMac($filter['mac_address']); + }); + } + if ($filter['vlan_id']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['vlan_id'] == $filter['vlan_id']; + }); + } + return array_values($data); + } + + function getPretty() { + return $this->response; + } + + + /** + * @param array $filter + * @return $this|AbstractModule + * @throws Exception + */ + public function run($filter = []) { + + $oids = []; + $oids[] = $this->oids->getOidByName('dhcpSnooping.bindMac')->getOid(); + $oids[] = $this->oids->getOidByName('dhcpSnooping.bindLease')->getOid(); + $oids[] = $this->oids->getOidByName('dhcpSnooping.bindVlan')->getOid(); + $oids[] = $this->oids->getOidByName('dhcpSnooping.bindPort')->getOid(); + + if(isset($filter['ip'])) { + foreach($oids as $i => $oid) { + $oids[$i] .= ".4.{$filter['ip']}"; + } + } + foreach($oids as $i => $oid) { + $oids[$i] = Oid::init($oid); + } + if(isset($filter['ip'])) { + $res = $this->formatResponse($this->snmp->get($oids)); + } else { + $res = $this->formatResponse($this->snmp->walk($oids)); + } + $resp = []; + try { + foreach($res['dhcpSnooping.bindMac']->fetchAll() as $r) { + $ip = Helper::oid2IP($r->getOid()); + $resp[$ip]['mac_address'] = Helper::formatMac($r->getHexValue()); + } + } catch(SNMPException $e) { + throw new Exception("Specified IP-address hasn't been found"); + } + foreach($res['dhcpSnooping.bindLease']->fetchAll() as $r) { + $ip = Helper::oid2IP($r->getOid()); + $resp[$ip]['remaining'] = $r->getParsedValue(); + } + foreach($res['dhcpSnooping.bindVlan']->fetchAll() as $r) { + $ip = Helper::oid2IP($r->getOid()); + $resp[$ip]['vlan_id'] = $r->getParsedValue(); + } + foreach($res['dhcpSnooping.bindPort']->fetchAll() as $r) { + $ip = Helper::oid2IP($r->getOid()); + $resp[$ip]['interface'] = $this->parseInterface($r->getParsedValue()); + } + $response = []; + foreach($resp as $ip => $val) { + $val['ip'] = $ip; + $response[] = $val; + } + $this->response = $response; + return $this; + } +} + diff --git a/src/Modules/VsolOlts/SnoopingInfo.php b/src/Modules/VsolOlts/SnoopingInfo.php index c42961b..4ba54c8 100644 --- a/src/Modules/VsolOlts/SnoopingInfo.php +++ b/src/Modules/VsolOlts/SnoopingInfo.php @@ -35,7 +35,7 @@ function getPrettyFiltered($filter = [], $fromCache = false) } if ($filter['mac_address']) { $data = array_filter($data, function ($e) use ($filter) { - return $e['mac_address'] == Helper::formatMac($filter['mac']); + return $e['mac_address'] == Helper::formatMac($filter['mac_address']); }); } if ($filter['vlan_id']) { @@ -43,6 +43,11 @@ function getPrettyFiltered($filter = [], $fromCache = false) return $e['vlan_id'] == $filter['vlan_id']; }); } + if ($filter['ip']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['ip'] == $filter['ip']; + }); + } return array_values($data); } @@ -93,10 +98,10 @@ public function loadSnoopTable() { $resp[$id]['ip'] = $response->fetchOne()->getParsedValue(); break; case 'dhcp.snooping.bindingLease': - $resp[$id]['lease_time'] = (int) $response->fetchOne()->getParsedValue(); + $resp[$id]['remaining'] = (int) $response->fetchOne()->getParsedValue(); break; case 'dhcp.snooping.bindingType': - $resp[$id]['type'] = $response->fetchOne()->getParsedValue(); + $resp[$id]['_type'] = $response->fetchOne()->getParsedValue(); break; case 'dhcp.snooping.bindingVlan': $resp[$id]['vlan_id'] = (int)$response->fetchOne()->getParsedValue(); diff --git a/src/Modules/ZTE/C600Series/Fdb.php b/src/Modules/ZTE/C600Series/Fdb.php index 5450a87..5b29df4 100644 --- a/src/Modules/ZTE/C600Series/Fdb.php +++ b/src/Modules/ZTE/C600Series/Fdb.php @@ -5,6 +5,7 @@ use Exception; +use SwitcherCore\Modules\Helper; class Fdb extends ModuleAbstract { @@ -14,6 +15,8 @@ public function run($params = []) if ($params['interface']) { $interface = $this->parseInterface($params['interface']); $data = $this->fdbByInterface($interface); + } elseif($params['vlan_id']) { + $data = $this->fdbByVlan($params['vlan_id']); } else { $interfaces = $this->getModule('pon_ports_list')->run()->getPretty(); foreach ($interfaces as $interface) { @@ -34,6 +37,24 @@ public function getPrettyFiltered($filter = []) return $this->response; } + public function fdbByVlan($vlan_id) { + $command = "show mac vlan $vlan_id"; + $lines = explode("\n", $this->telnet->exec($command)); + $resp = []; + foreach ($lines as $line) { + if(preg_match('/((([0-9a-f]{4})\.?){3})\s+(\d{1,4})\s+(dynamic|static)\s+((\w+)[-_]?(\w+)?[-_]?\d\/\d{1,3}(\/\d{1,3})?([:\.])?(\d{1,3})?(:?(\d)?)).*/i', trim($line), $m)) { + $resp[] = [ + '_virtual_port' => isset($m[13]) ? $m[13] : null, + 'mac_address' => Helper::formatMac($m[1]), + 'vlan_id' => $vlan_id, + 'type' => strtoupper($m[5]), + 'interface' => $this->parseInterface($m[6]), + ]; + } + } + return $resp; + } + function fdbByInterface($interface) { if (!$this->telnet) { diff --git a/src/Modules/ZTE/C600Series/ModuleAbstract.php b/src/Modules/ZTE/C600Series/ModuleAbstract.php index 5863e64..1eceb6a 100644 --- a/src/Modules/ZTE/C600Series/ModuleAbstract.php +++ b/src/Modules/ZTE/C600Series/ModuleAbstract.php @@ -159,7 +159,7 @@ public function parseInterface($name) } $iface = $xidList['names']["{$m[1]}/{$m[2]}/{$m[3]}"]; } - if(is_string($name) && preg_match('/^.*?([0-9])\/([0-9]{1,3})\/([0-9]{1,3}):([0-9]{1,3})$/', $name, $m)) { + if(is_string($name) && preg_match('/^.*?([0-9])\/([0-9]{1,3})\/([0-9]{1,3})[:\.]([0-9]{1,3})/', $name, $m)) { if(!isset($xidList['names']["{$m[1]}/{$m[2]}/{$m[3]}"])) { throw new \Exception("Error parse port with name={$name}, searching key={$m[1]}/{$m[2]}/{$m[3]}"); } diff --git a/src/Modules/ZTE/C600Series/SnoopingInfo.php b/src/Modules/ZTE/C600Series/SnoopingInfo.php new file mode 100644 index 0000000..e2dccfe --- /dev/null +++ b/src/Modules/ZTE/C600Series/SnoopingInfo.php @@ -0,0 +1,178 @@ +response; + } + + function getPrettyFiltered($filter = [], $fromCache = false) { + $data = $this->getPretty(); + if(count($data) === 0) return []; + if ($filter['interface']) { + $interface = $this->parseInterface($filter['interface']); + $data = array_filter($data, function ($e) use ($interface) { + return $e['interface']['id'] == $interface['id']; + }); + } + if ($filter['mac_address']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['mac_address'] == Helper::formatMac($filter['mac_address']); + }); + } + if ($filter['vlan_id']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['vlan_id'] == $filter['vlan_id']; + }); + } + if ($filter['ip']) { + $data = array_filter($data, function ($e) use ($filter) { + return $e['ip'] == $filter['ip']; + }); + } + return array_values($data); + } + + function getPretty() { + return $this->response; + } + + + /** + * @param array $filter + * @return $this|AbstractModule + * @throws Exception + */ + public function run($filter = []) { + if(isset($filter['ip'])) { + $cmd = 'show ip dhcp snooping dynamic ip ' . $filter['ip']; + $r = $this->getModule('console_command')->run(['command' => $cmd])->getPretty(); + $r = explode("\n", $r['output']); + if(count($r) < 2) throw new Exception("SnoopingInfo: {$filter['ip']} not found"); + $resp = []; + foreach($r as $line) { + if(preg_match('/^MAC addr\s+:((([0-9a-f]{4})\.?){3})$/i', trim($line), $m)) { + $resp['mac_address'] = Helper::formatMac($m[1]); + } + if(preg_match('/^IP addr\s+:(((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4})$/i', trim($line), $m)) { + $resp['ip'] = $m[1]; + } + if(preg_match('/^VLAN\s+:(\d{1,4})$/i', trim($line), $m)) { + $resp['vlan_id'] = (int) $m[1]; + } + if(preg_match('/^Interface\s+:((\w+)[-_]?(\w+)?[-_]?\d\/\d{1,3}(\/\d{1,3})?(([:\.])?(\d{1,3})?)?(([:\.])?(\d{1,3})?)?)/i', trim($line), $m)) { + $resp['interface'] = $this->parseInterface($m[1]); + } + if(preg_match('/^Remaining\s+:((\d{1,3}):(\d{2}):(\d{2}))/i', trim($line), $m)) { + $hours = (int) $m[2]; + $minutes = (int) $m[3]; + $seconds = (int) $m[4]; + $resp['remaining'] = $seconds + $minutes * 60 + $hours * 60 * 60; + } + if(preg_match('/^Server IP\s+:(((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4})$/i', trim($line), $m)) { + $resp['_server_ip'] = $m[1]; + } + if(preg_match('/^Gateway IP\s+:(((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4})$/i', trim($line), $m)) { + $resp['_gateway_ip'] = $m[1]; + } + if(preg_match('/^Subnet mask\s+:(((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4})$/i', trim($line), $m)) { + $resp['_subnet_mask'] = $m[1]; + } + } + $this->response = [$resp]; + return $this; + } + + $ifaces_4mac = []; + if(isset($filter['mac_address'])) { + $cmd = 'show mac ' . Helper::formatMac3Blocks($filter['mac_address']); + $r = $this->getModule('console_command')->run(['command' => $cmd])->getPretty(); + $r = explode("\n", $r['output']); + foreach($r as $line) { + if(preg_match('/((([0-9a-f]{4})\.?){3})\s+(\d{1,4})\s+(dynamic|static)\s+((\w+)[-_]?(\w+)?[-_]?\d\/\d{1,3}(\/\d{1,3})?(([:\.])?(\d{1,3})){0,2})/i', trim($line), $m)) { + $ifaces_4mac[$m[6]] = $m[6]; + } + } + } + if(isset($filter['vlan_id'])) { + $cmd = "show mac vlan {$filter['vlan_id']}"; + $r = $this->getModule('console_command')->run(['command' => $cmd])->getPretty(); + $r = explode("\n", $r['output']); + foreach($r as $line) { + if(preg_match('/((([0-9a-f]{4})\.?){3})\s+(\d{1,4})\s+(dynamic|static)\s+((\w+)[-_]?(\w+)?[-_]?\d\/\d{1,3}(\/\d{1,3})?(([:\.])?(\d{1,3})){0,2})/i', trim($line), $m)) { + $ifaces_4mac[$m[6]] = $m[6]; + } + } + } + if(isset($filter['interface'])) { + $iface = $this->parseInterface($filter['interface'])['name']; + // $iface = str_replace(['gpon_onu-', 'epon_onu-'], 'vport-', $iface); + // $iface = str_replace(':', '.', $iface); + // $iface .= ':1'; + $iface = "vport-{$iface['_shelf']}/{$iface['_slot']}/{$iface['_port']}.{$iface['_onu']}:1"; + $ifaces_4mac = [$iface]; + } + + + $out = []; + if(count($ifaces_4mac) > 0) { + foreach($ifaces_4mac as $iface) { + $cmd = "show ip dhcp snooping dynamic port $iface"; + $r = $this->getModule('console_command')->run(['command' => $cmd])->getPretty(); + $r = explode("\n", $r['output']); + $out = array_merge($r, $out); + } + } else { + $cmd = "show ip dhcp snooping dynamic database"; + $r = $this->getModule('console_command')->run(['command' => $cmd])->getPretty(); + $r = explode("\n", $r['output']); + $out = $r; + } + + $resp = []; + $add_next_line = false; + foreach($out as $line) { + if($add_next_line) { + if(preg_match('/^(\/\d{1,3}([:\.]\d{1,3})?([:\.]\d{1,3})?)/', trim($line), $m)) { + $interface .= $m[1]; + $resp[] = [ + 'interface' => $this->parseInterface($interface), + 'mac_address' => $mac, + 'ip' => $ip, + 'vlan_id' => $vlan_id, + 'remaining' => $remaining, + ]; + } + $add_next_line = false; + continue; + } + if(preg_match('/^\d{1,5}\s+(([0-9a-f]{4}\.?){3})\s+(((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4})\s+(\d{1,4})\s+dynamic\s+(\w+[-_]\d\/\d{1,3})\s+(\d{1,3}:\d{2}:\d{2})\s+\d?\s*((\d{1,3}):(\d{2}):(\d{2}))/i', trim($line), $m)) { + $mac = Helper::formatMac($m[1]); + $ip = $m[3]; + $vlan_id = (int) $m[7]; + $interface = $m[8]; + $hours = (int) $m[11]; + $minutes = (int) $m[12]; + $seconds = (int) $m[13]; + $remaining = $seconds + $minutes * 60 + $hours * 60 * 60; + $add_next_line = true; + } + } + + $this->response = $resp; + return $this; + } +} +