diff --git a/doc/API/Switching.md b/doc/API/Switching.md index 3d0259110b..7c76e090c6 100644 --- a/doc/API/Switching.md +++ b/doc/API/Switching.md @@ -234,3 +234,46 @@ Output: "count": 100 } ``` + + +### `list_fdb_detail` + +Get a list of all ports FDB with human readable device and interface names. + +Route: `/api/v0/resources/fdb/:mac/detail` + + - mac is the specific MAC address you would like to query + +Input: + +- + +Example: +```curl +curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms.org/api/v0/resources/fdb/1aaa2bbb3ccc/detail +``` + +Output: +```json +{ + 'count': 7, + 'mac': '9c:93:aa:bb:cc:dd', + 'mac_oui': 'Xerox Corporation', + 'ports_fdb': [ + { + 'hostname': 'hq-core1', + 'ifName': 'ae10', + 'last_seen': '2 hours ago', + 'updated_at': '2023-05-17 03:19:15' + }, + { + 'hostname': 'hq-sw1', + 'ifName': 'ge-0/0/0', + 'last_seen': '3 hours ago', + 'updated_at': '2023-05-17 02:02:06' + }, + ... + ], + 'status': 'ok' +} +``` diff --git a/includes/html/api_functions.inc.php b/includes/html/api_functions.inc.php index d3dd3070fc..ede6cd89a7 100644 --- a/includes/html/api_functions.inc.php +++ b/includes/html/api_functions.inc.php @@ -2424,12 +2424,51 @@ function list_fdb(Illuminate\Http\Request $request) ->get(); if ($fdb->isEmpty()) { - return api_error(404, 'Fdb do not exist'); + return api_error(404, 'Fdb entry does not exist'); } return api_success($fdb, 'ports_fdb'); } +function list_fdb_detail(Illuminate\Http\Request $request) +{ + $macAddress = Rewrite::macToHex((string) $request->route('mac')); + + $rules = [ + 'macAddress' => 'required|string|regex:/^[0-9a-fA-F]{12}$/', + ]; + + $validate = Validator::make(['macAddress' => $macAddress], $rules); + if ($validate->fails()) { + return api_error(422, $validate->messages()); + } + + $extras = ['mac' => Rewrite::readableMac($macAddress), 'mac_oui' => Rewrite::readableOUI($macAddress)]; + + $fdb = PortsFdb::hasAccess(Auth::user()) + ->when(! empty($macAddress), function (Builder $query) use ($macAddress) { + return $query->leftJoin('ports', 'ports_fdb.port_id', 'ports.port_id') + ->leftJoin('devices', 'ports_fdb.device_id', 'devices.device_id') + ->where('mac_address', $macAddress) + ->orderBy('ports_fdb.updated_at', 'desc') + ->select('devices.hostname', 'ports.ifName', 'ports_fdb.updated_at'); + }) + ->limit(1000)->get(); + + if (count($fdb) == 0) { + return api_error(404, 'Fdb entry does not exist'); + } + + foreach ($fdb as $i => $fdb_entry) { + if ($fdb_entry['updated_at']) { + $fdb[$i]['last_seen'] = $fdb_entry['updated_at']->diffForHumans(); + $fdb[$i]['updated_at'] = $fdb_entry['updated_at']->toDateTimeString(); + } + } + + return api_success($fdb, 'ports_fdb', null, 200, count($fdb), $extras); +} + function list_sensors() { $sensors = Sensor::hasAccess(Auth::user())->get(); diff --git a/routes/api.php b/routes/api.php index 67fa67727d..066be796c7 100644 --- a/routes/api.php +++ b/routes/api.php @@ -152,6 +152,7 @@ Route::prefix('v0')->namespace('\App\Api\Controllers')->group(function () { Route::prefix('resources')->group(function () { Route::get('fdb', 'LegacyApiController@list_fdb')->name('list_fdb'); Route::get('fdb/{mac}', 'LegacyApiController@list_fdb')->name('list_fdb_mac'); + Route::get('fdb/{mac}/detail', 'LegacyApiController@list_fdb_detail')->name('list_fdb_detail'); Route::get('links', 'LegacyApiController@list_links')->name('list_links'); Route::get('sensors', 'LegacyApiController@list_sensors')->name('list_sensors'); Route::get('vlans', 'LegacyApiController@list_vlans')->name('list_vlans');