From 81ddab86afd797decaa47fc1232c4207bffd6fd1 Mon Sep 17 00:00:00 2001 From: Lorenzo Zafra Date: Sat, 24 Jun 2017 21:07:31 -0600 Subject: [PATCH] feature: fdb tables (#6616) * feature: FDB TABLES for ios and timos * Fixed coding style issues * renamed fdb.sql to 191.sql * fixed travisCI issue * FDB table discovery working on IOS * Fixed bug: failing to insert fdb entries into database * Fix phpcbf issue * moved sql schema * rename sql schema * Add (tentative) FDB support for HP Comware switches * build schema * schema changes * run build schema....... * FBD Table discovery working on HP ComWare * FBD Table discovery working on HP ComWare * Add FDB support for HP Comware * Discovery regex fix, tested and works for cisco 3750, 2960, 6509 * Use vlan_id instead of raw vlan. Remove Nokia implementation as vlans are not being discovered for it at the moment. * Use vlan_id instead of vlan. * Add debug messages, comware support * Sorry.. phpunit isnt working for me * Use a file structure instead of if statement per OS * Make inserts to vlan table if entry does not exist. * Rename sql schema file * Use existing context name Improve output and database synchronization Remove chromephp and if ios rename sqlfile add comware back update schema * Delete TIMETRA-CHASSIS-MIB * Delete TIMETRA-FILTER-MIB * change index to bigint to be safe --- html/includes/print-menubar.php | 1 + html/includes/table/fdb-search.inc.php | 94 +++++++++++++++++++ html/pages/device/port.inc.php | 1 + html/pages/device/port/fdb.inc.php | 29 ++++++ html/pages/device/ports.inc.php | 3 +- html/pages/device/ports/fdb.inc.php | 29 ++++++ html/pages/search.inc.php | 1 + html/pages/search/fdb.inc.php | 97 ++++++++++++++++++++ includes/defaults.inc.php | 2 +- includes/discovery/fdb-table.inc.php | 79 ++++++++++++++++ includes/discovery/fdb-table/comware.inc.php | 46 ++++++++++ includes/discovery/fdb-table/ios.inc.php | 61 ++++++++++++ includes/snmp.inc.php | 4 +- misc/db_schema.yaml | 10 ++ sql-schema/196.sql | 2 + 15 files changed, 456 insertions(+), 3 deletions(-) create mode 100644 html/includes/table/fdb-search.inc.php create mode 100644 html/pages/device/port/fdb.inc.php create mode 100644 html/pages/device/ports/fdb.inc.php create mode 100644 html/pages/search/fdb.inc.php create mode 100644 includes/discovery/fdb-table.inc.php create mode 100644 includes/discovery/fdb-table/comware.inc.php create mode 100644 includes/discovery/fdb-table/ios.inc.php create mode 100644 sql-schema/196.sql diff --git a/html/includes/print-menubar.php b/html/includes/print-menubar.php index c093849343..4d7900cabc 100644 --- a/html/includes/print-menubar.php +++ b/html/includes/print-menubar.php @@ -126,6 +126,7 @@ if (dbFetchCell("SELECT 1 from `packages` LIMIT 1")) {
  • IPv6 Address
  • MAC Address
  • ARP Tables
  • +
  • FDB Tables
  • diff --git a/html/includes/table/fdb-search.inc.php b/html/includes/table/fdb-search.inc.php new file mode 100644 index 0000000000..6b248a8e85 --- /dev/null +++ b/html/includes/table/fdb-search.inc.php @@ -0,0 +1,94 @@ + 0 || $entry['ifOutErrors'] > 0) { + $error_img = generate_port_link($entry, "", port_errors); + } else { + $error_img = ''; + } + + $fdb_host = dbFetchRow('SELECT * FROM ports_fdb AS F, ipv4_mac AS M WHERE F.mac_address = ? AND M.mac_address = F.mac_address', array($entry['mac_address'])); + $response[] = array( + 'os' => $entry['os'], + 'mac_address' => formatMac($entry['mac_address']), + 'ipv4_address' => $fdb_host['ipv4_address'], + 'hostname' => generate_device_link($entry), + 'interface' => generate_port_link($entry, makeshortif(fixifname(cleanPort($entry['label'])))).' '.$error_img, + 'vlan' => $entry['vlan_vlan'], + ); + }//end if + + unset($ignore); +}//end foreach + +$output = array( + 'current' => $current, + 'rowCount' => $rowCount, + 'rows' => $response, + 'total' => $total, +); +echo _json_encode($output); diff --git a/html/pages/device/port.inc.php b/html/pages/device/port.inc.php index 0155c7208b..b5693dd8ca 100644 --- a/html/pages/device/port.inc.php +++ b/html/pages/device/port.inc.php @@ -72,6 +72,7 @@ $menu_options['graphs'] = 'Graphs'; $menu_options['realtime'] = 'Real time'; // FIXME CONDITIONAL $menu_options['arp'] = 'ARP Table'; +$menu_options['fdb'] = 'FDB Table'; $menu_options['events'] = 'Eventlog'; $menu_options['notes'] = 'Notes'; diff --git a/html/pages/device/port/fdb.inc.php b/html/pages/device/port/fdb.inc.php new file mode 100644 index 0000000000..4963a7745d --- /dev/null +++ b/html/pages/device/port/fdb.inc.php @@ -0,0 +1,29 @@ + + + + + + + + + + +
    MAC addressIPv4 AddressPortVlan
    + + + diff --git a/html/pages/device/ports.inc.php b/html/pages/device/ports.inc.php index 58c0f6f23e..4110d66cdf 100644 --- a/html/pages/device/ports.inc.php +++ b/html/pages/device/ports.inc.php @@ -23,6 +23,7 @@ print_optionbar_start(); $menu_options['basic'] = 'Basic'; $menu_options['details'] = 'Details'; $menu_options['arp'] = 'ARP Table'; +$menu_options['fdb'] = 'FDB Table'; if (dbFetchCell("SELECT * FROM links AS L, ports AS I WHERE I.device_id = '".$device['device_id']."' AND I.port_id = L.local_port_id")) { $menu_options['neighbours'] = 'Neighbours'; @@ -118,7 +119,7 @@ if ($vars['view'] == 'minigraphs') { } echo ''; -} elseif ($vars['view'] == 'arp' || $vars['view'] == 'adsl' || $vars['view'] == 'neighbours') { +} elseif ($vars['view'] == 'arp' || $vars['view'] == 'adsl' || $vars['view'] == 'neighbours' || $vars['view'] == 'fdb') { include 'ports/'.$vars['view'].'.inc.php'; } else { if ($vars['view'] == 'details') { diff --git a/html/pages/device/ports/fdb.inc.php b/html/pages/device/ports/fdb.inc.php new file mode 100644 index 0000000000..137a60771e --- /dev/null +++ b/html/pages/device/ports/fdb.inc.php @@ -0,0 +1,29 @@ + + + + + + + + + + +
    MAC addressIPv4 AddressPortVlan
    + + + diff --git a/html/pages/search.inc.php b/html/pages/search.inc.php index 65dd16ea5a..1bdd35e509 100644 --- a/html/pages/search.inc.php +++ b/html/pages/search.inc.php @@ -9,6 +9,7 @@ $sections = array( 'ipv6' => 'IPv6 Address', 'mac' => 'MAC Address', 'arp' => 'ARP Table', + 'fdb' => 'FDB Table' ); if (dbFetchCell('SELECT 1 from `packages` LIMIT 1')) { diff --git a/html/pages/search/fdb.inc.php b/html/pages/search/fdb.inc.php new file mode 100644 index 0000000000..06b62e4e26 --- /dev/null +++ b/html/pages/search/fdb.inc.php @@ -0,0 +1,97 @@ +
    +
    + FDB Entries +
    + + + + + + + + + + + + +
    + + diff --git a/includes/defaults.inc.php b/includes/defaults.inc.php index eff0e8a21f..3211944f57 100644 --- a/includes/defaults.inc.php +++ b/includes/defaults.inc.php @@ -783,7 +783,7 @@ $config['discovery_modules']['ntp'] = 1; $config['discovery_modules']['loadbalancers'] = 0; $config['discovery_modules']['mef'] = 0; $config['discovery_modules']['wireless'] = 1; - +$config['discovery_modules']['fdb-table'] = 1; // Enable daily updates $config['update'] = 1; diff --git a/includes/discovery/fdb-table.inc.php b/includes/discovery/fdb-table.inc.php new file mode 100644 index 0000000000..400a15f431 --- /dev/null +++ b/includes/discovery/fdb-table.inc.php @@ -0,0 +1,79 @@ + $mac_address_table) { + echo " {$vlans_by_id[$vlan_id]}: "; + + foreach ($mac_address_table as $mac_address_entry => $entry) { + if ($existing_fdbs[$vlan_id][$mac_address_entry]) { + $new_port = $entry['port_id']; + + if ($existing_fdbs[$vlan_id][$mac_address_entry]['port_id'] != $new_port) { + $port_fdb_id = $existing_fdbs[$vlan_id][$mac_address_entry]['ports_fdb_id']; + $valid_fdb[] = $port_fdb_id; + + dbUpdate( + array('port_id' => $new_port), + 'ports_fdb', + '`ports_fdb_id` = ?', + array($port_fdb_id) + ); + echo 'U'; + } else { + echo '.'; + } + unset($existing_fdbs[$vlan_id][$mac_address_entry]); + } else { + $new_entry = array( + 'port_id' => $entry['port_id'], + 'mac_address' => $mac_address_entry, + 'vlan_id' => $vlan_id, + 'device_id' => $device['device_id'], + ); + + $valid_fdb = dbInsert($new_entry, 'ports_fdb'); + echo '+'; + } + } + + foreach ($existing_fdbs[$vlan_id] as $entry) { + dbDelete('ports_fdb', '`ports_fdb_id` = ?', array($entry['ports_fdb_id'])); + echo '-'; + } + echo PHP_EOL; + } + + unset($existing_fdbs, $ifIndex_dict, $portid_dict, $vlans_dict); +} diff --git a/includes/discovery/fdb-table/comware.inc.php b/includes/discovery/fdb-table/comware.inc.php new file mode 100644 index 0000000000..9fe91405b8 --- /dev/null +++ b/includes/discovery/fdb-table/comware.inc.php @@ -0,0 +1,46 @@ +\w+)\[(?P\d+)]\[(?P[\w:-]+)]\s(?P\d+)~', $fdbPort_entry, $matches); + if (!empty($matches)) { + $port = $matches['port']; + $mac = $matches['mac']; + $vlan = $matches['vlan']; + $vlan_id = $vlans_dict[$vlan]; + echo " $vlan"; + + if (!empty($mac)) { + list($oct_1, $oct_2, $oct_3, $oct_4, $oct_5, $oct_6) = explode(':', $mac); + $mac_address = zeropad($oct_1) . zeropad($oct_2) . zeropad($oct_3) . zeropad($oct_4) . zeropad($oct_5) . zeropad($oct_6); + if (strlen($mac_address) != 12) { + echo 'Mac Address padding failed'; + continue; + } else { + $dot1dBasePort = $port; + $insert[$vlan_id][$mac_address]['port_id'] = $portid_dict[$dot1dBasePort]; + d_echo("vlan $vlan mac $mac_address port ($port) " . $portid_dict[$dot1dBasePort] . PHP_EOL); + } + } // end if on empty mac + } // end if on matches +} // end loop on fdbPort_entry + +echo PHP_EOL; diff --git a/includes/discovery/fdb-table/ios.inc.php b/includes/discovery/fdb-table/ios.inc.php new file mode 100644 index 0000000000..79000ab01e --- /dev/null +++ b/includes/discovery/fdb-table/ios.inc.php @@ -0,0 +1,61 @@ + $vtpdomain) { + echo "VTP Domain $vtpdomain_id {$vtpdomain['managementDomainName']}> "; + foreach ($vlans[$vtpdomain_id] as $vlan_raw => $vlan) { + echo "$vlan_raw "; + if (!array_key_exists($vlan_raw, $vlans_dict)) { + $newvlan_id = dbInsert(array( + 'device_id' => $device['device_id'], + 'vlan_domain' => $vtpdomain_id, + 'vlan_vlan' => $vlan_raw, + 'vlan_name' => $vlan['vtpVlanName'], + 'vlan_type' => $vlan['vtpVlanType'] + ), 'vlans'); + $vlans_dict[$vlan_raw] = $newvlan_id; + } + + if ($vlan['vtpVlanState'] == 'operational') { + $device_vlan = $device; + $device_vlan['context_name'] = $vlan_raw; + $FdbPort_table = snmp_walk($device_vlan, 'dot1dTpFdbPort', '-OqsX', 'BRIDGE-MIB'); + if (empty($FdbPort_table)) { + // If there are no entries for the vlan, continue + unset($device_vlan); + continue; + } + + $dot1dBasePortIfIndex = snmp_walk($device_vlan, 'dot1dBasePortIfIndex', '-OqsX', 'BRIDGE-MIB'); + + foreach (explode("\n", $dot1dBasePortIfIndex) as $dot1dBasePortIfIndex_entry) { + if (!empty($dot1dBasePortIfIndex_entry)) { + preg_match('~dot1dBasePortIfIndex\[(\d+)]\s(\d+)~', $dot1dBasePortIfIndex_entry, $matches); + $portid_dict[$matches[1]] = $ifIndex_dict[$matches[2]]; + } + } + + foreach (explode("\n", $FdbPort_table) as $FdbPort_entry) { + preg_match('~(?P\w+)\[(?P[\w:-]+)]\s(?P\w.*)~', $FdbPort_entry, $matches); + if (! empty($matches)) { + list($oct_1, $oct_2, $oct_3, $oct_4, $oct_5, $oct_6) = explode(':', $matches['mac']); + $mac_address = zeropad($oct_1) . zeropad($oct_2) . zeropad($oct_3) . zeropad($oct_4) . zeropad($oct_5) . zeropad($oct_6); + if (strlen($mac_address) != 12) { + echo 'Mac Address padding failed'; + continue; + } else { + $vlan_id = $vlans_dict[$vlan_raw]; + $dot1dBasePort = $matches['result']; + $insert[$vlan_id][$mac_address]['port_id'] = $portid_dict[$dot1dBasePort]; + d_echo("vlan $vlan_raw - mac $mac_address - port ($port) ".$portid_dict[$dot1dBasePort]."\n"); + } + } + } + + unset($device_vlan); + } //end if operational + } // end for each vlan + echo PHP_EOL; +} // end for each vlan domain diff --git a/includes/snmp.inc.php b/includes/snmp.inc.php index f4382548fd..0d1919a90d 100644 --- a/includes/snmp.inc.php +++ b/includes/snmp.inc.php @@ -666,7 +666,6 @@ function snmp_cache_port_oids($oids, $port, $device, $array, $mib = 0) return $array; }//end snmp_cache_port_oids() - function snmp_gen_auth(&$device) { global $debug, $vdebug; @@ -703,6 +702,9 @@ function snmp_gen_auth(&$device) } elseif ($device['snmpver'] === 'v2c' or $device['snmpver'] === 'v1') { $cmd = " -".$device['snmpver']; $cmd .= " -c '".$device['community']."'"; + if (isset($device['context_name'])) { + $cmd .= '@' . $device['context_name']; + } } else { if ($debug) { print 'DEBUG: '.$device['snmpver']." : Unsupported SNMP Version (shouldn't be possible to get here)\n"; diff --git a/misc/db_schema.yaml b/misc/db_schema.yaml index ac34d9f1f7..f639333efd 100644 --- a/misc/db_schema.yaml +++ b/misc/db_schema.yaml @@ -1126,6 +1126,16 @@ ports_adsl: port_id: { Field: port_id, Type: int(11), 'Null': false, Default: null, Extra: '' } Indexes: interface_id: { Name: interface_id, Columns: [port_id], Unique: true, Type: BTREE } +ports_fdb: + Columns: + device_id: { Field: device_id, Type: 'int(11) unsigned', 'Null': false, Default: null, Extra: '' } + mac_address: { Field: mac_address, Type: varchar(32), 'Null': false, Default: null, Extra: '' } + ports_fdb_id: { Field: ports_fdb_id, Type: bigint(20), 'Null': false, Default: null, Extra: auto_increment } + port_id: { Field: port_id, Type: 'int(11) unsigned', 'Null': false, Default: null, Extra: '' } + vlan_id: { Field: vlan_id, Type: 'int(11) unsigned', 'Null': false, Default: null, Extra: '' } + Indexes: + PRIMARY: { Name: PRIMARY, Columns: [ports_fdb_id], Unique: true, Type: BTREE } + mac_address: { Name: mac_address, Columns: [mac_address], Unique: false, Type: BTREE } ports_perms: Columns: access_level: { Field: access_level, Type: int(11), 'Null': false, Default: null, Extra: '' } diff --git a/sql-schema/196.sql b/sql-schema/196.sql new file mode 100644 index 0000000000..c2626a36e9 --- /dev/null +++ b/sql-schema/196.sql @@ -0,0 +1,2 @@ +CREATE TABLE `ports_fdb` ( `ports_fdb_id` BIGINT(20) PRIMARY KEY NOT NULL AUTO_INCREMENT, `port_id` INT(11) unsigned NOT NULL, `mac_address` VARCHAR(32) NOT NULL, `vlan_id` INT(11) unsigned NOT NULL, `device_id` INT(11) unsigned NOT NULL); +ALTER TABLE `ports_fdb` ADD INDEX ( `mac_address` );