-- SPDX-License-Identifier: GPL-3.0-or-later ------------------------------------------------------------------------ -- pla-util - A power line adapter utility -- Copyright (C) 2016-2023 John Serock -- -- This file is part of pla-util. -- -- pla-util is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- pla-util is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . ------------------------------------------------------------------------ with Interfaces.C.Strings; package body Packets.Device_Locators is function Create return Basic_Search_Type is Algorithm : Basic_Search_Type; begin return Algorithm; end Create; function Create (Device_Name : String) return Named_Search_Type is Algorithm : Named_Search_Type; Target_Count : Interfaces.C.size_t; begin Interfaces.C.To_C (Item => Device_Name, Target => Algorithm.Network_Device_Name, Count => Target_Count); return Algorithm; end Create; overriding procedure Finalize (Self : in out Device_Locator_Type) is begin if Self.Devices_Access /= null then Pcap.Devices.Free_All_Devices (Network_Devices => Self.Devices_Access); Self.Devices_Access := null; end if; end Finalize; procedure Find (Self : Device_Locator_Type; Device_Name : String; Interface_Name : out Interface_Name_Strings.Bounded_String; Interface_Address : out MAC_Addresses.MAC_Address_Type) is use type Pcap.Devices.Address_Access_Type; Address_Access : Pcap.Devices.Address_Access_Type := null; Device_Access : Pcap.Devices.Interface_Access_Type := null; Search_Algorithm : constant Search_Type'Class := (if Device_Name = "" then Create else Create (Device_Name => Device_Name)); begin Device_Access := Search_Algorithm.Run (Network_Device => Self.Devices_Access); Interface_Name := Interface_Name_Strings.To_Bounded_String (Source => Interfaces.C.Strings.Value (Item => Device_Access.all.Name)); Address_Access := Device_Access.all.Addresses; while Address_Access /= null and then Pcap.Devices.Is_Not_Packet_Address (Socket_Address => Address_Access.all.Socket_Address) loop Address_Access := Address_Access.all.Next; end loop; if Address_Access = null then raise Packet_Error with "MAC address of device " & Interface_Name_Strings.To_String (Source => Interface_Name) & " not found"; end if; Interface_Address := MAC_Addresses.Create_MAC_Address (MAC_Address_Octets => Address_Access.all.Socket_Address.all.SLL_Address (1 .. 6)); end Find; procedure Find_All_Devices (Self : in out Device_Locator_Type) is use type Interfaces.C.int; Error_Buffer : aliased Pcap.Error_Buffer_Type; Return_Code : Interfaces.C.int; begin Return_Code := Pcap.Devices.Find_All_Devices (Network_Devices => Self.Devices_Access, Error_Buffer => Error_Buffer); if Return_Code /= 0 then raise Packet_Error with Interfaces.C.To_Ada (Item => Error_Buffer); end if; if Self.Devices_Access = null then raise Packet_Error with "No devices found"; end if; end Find_All_Devices; pragma Warnings (Off, "formal parameter*is not referenced"); overriding function Run (Self : Basic_Search_Type; Network_Device : Pcap.Devices.Interface_Access_Type) return Pcap.Devices.Interface_Access_Type is pragma Warnings (On, "formal parameter*is not referenced"); Device_Access : Pcap.Devices.Interface_Access_Type := Network_Device; begin while Device_Access /= null and then (Pcap.Devices.Is_Loopback (Network_Device => Device_Access) or else Pcap.Devices.Is_Down (Network_Device => Device_Access) or else Pcap.Devices.Is_Not_Running (Network_Device => Device_Access)) loop Device_Access := Device_Access.all.Next; end loop; if Device_Access = null then raise Packet_Error with "No up and running non-loopback network device found"; end if; return Device_Access; end Run; overriding function Run (Self : Named_Search_Type; Network_Device : Pcap.Devices.Interface_Access_Type) return Pcap.Devices.Interface_Access_Type is Device_Access : Pcap.Devices.Interface_Access_Type := Network_Device; begin while Device_Access /= null and then Interfaces.C.Strings.Value (Item => Device_Access.all.Name) /= Interfaces.C.To_Ada (Item => Self.Network_Device_Name) loop Device_Access := Device_Access.all.Next; end loop; if Device_Access = null then raise Packet_Error with "Device " & Interfaces.C.To_Ada (Item => Self.Network_Device_Name) & " not found"; end if; return Device_Access; end Run; end Packets.Device_Locators;