Im Netzwerk angemeldete Computer.

Alle Fragen zur Netzwerkkommunikation
Benutzeravatar
Garfield
Beiträge: 172
Registriert: Do 5. Jun 2008, 22:07
OS, Lazarus, FPC: Ubuntu 22.04 LTS (Laz 3.0 FPC3.2.2)
CPU-Target: 64Bit
Wohnort: Aken

Im Netzwerk angemeldete Computer.

Beitrag von Garfield »

Ich möchte unter Windows 10 die im Netzwerk angemeldeten Geräte mit ihrer IP auflisten. Dazu sollen dann ggfs noch MAC, Name und Verbindungsart (WLAN/LAN) kommen.

In Lazarus existiert die Unit NetworkFunctions, welche aus der Delphipraxis stammen dürfte. Die procedure GetComputerList(List: TStrings) wurde dabei etwas abgeändert, um compilieren zu können. Diese Procedure bringt jedoch keine Ergebnisse. Eine ähnliche Routine von Angus Johnson habe ich etwas angepasst ebenfalls getestet:

Code: Alles auswählen

procedure GetNetworkedDrives(strings: TStrings);
 
  procedure EnumNetworkDrives(pnr : PNetResource);
  var
    hEnum: THandle;
    i, enumRes, count, BufferSize: DWORD;
    buffer: pointer;
  begin
    BufferSize := $4000; //ie: use a 16kb buffer
    buffer := nil//just in case memory allocation fails
    if WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, pnr, hEnum) = ERROR_SUCCESS
    then try
      GetMem(buffer, BufferSize);
      repeat
        count := dword(-1); //ie: get as many items possible
        enumRes := WNetEnumResource(hEnum, count, buffer, BufferSize);
 
        //break if either no more items found or an error occurs...
        if (enumRes = ERROR_SUCCESS)
        then begin
          pnr := buffer; //reuse the pnr pointer
          for i := 1 to count do
          begin
            if (pnr^.dwDisplayType = RESOURCEDISPLAYTYPE_DOMAIN or RESOURCEDISPLAYTYPE_SERVER) and (pnr^.dwType = RESOURCETYPE_DISK)
            then strings.Add(pnr^.lpRemoteName);
            //recursive function call...
            if (pnr^.dwUsage and RESOURCEUSAGE_CONTAINER) > 0
            then EnumNetworkDrives(pnr);
            inc(Pointer(pnr),sizeof(TNetResource));
          end;
        end;
      until enumRes <> ERROR_SUCCESS;
    finally
      FreeMem(buffer);
      WNetCloseEnum(hEnum);
    end;
  end;
 
begin
  if strings = nil then exit;
  //simply call the nested recursive function
  //passing nil to starting at the network root ...
  EnumNetworkDrives(nil);
end


Auch damit erhalte ich nicht das gewünschte Ergebnis.

Der erste Aufruf von WNetEnumResource ergibt drei Einträge (siehe Bild). Die rekursiven Aufrufe von WNetEnumResource ergeben jeweils 0 (NO_ERROR) mit 0 Einträgen oer 259 (ERROR_NO_MORE_ITEMS).

YANA gibt mir nur Host-IP, Hostnamen und DHCP-Server-IP zurück.

LuckiePing funktioniert leider nicht. Thread Ping von pacman1986 funktioniert, ist jedoch ohne Source und Angabe der Funktionsweise.

Trotz etlicher Stunden suchen und testen habe ich bisher nichts brauchbares für Lazarus gefunden. Auch die Funktion Ping auf Fritzbox und Druckers ergaben False, während Ping in der Konsole funktioniert.

Kann jemand helfen oder ist Lazarus in der Beziehung unbrauchbar?
Dateianhänge
pnr.png
Gruß Garfield

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Im Netzwerk angemeldete Computer.

Beitrag von af0815 »

Mit Wireshark mal mitprotokollieren was da gesendet wird.

Lazarus ist schon brauchbar, das Geheimnis ist nur, wie mache ich das richtig. Man kann ja einen sog. Ping in den verschiedensten Varianten machen, wenn man halt nicht exakt an die RFC's hält. Was heisst hier Ping eigentlich, ich sende etwas und bewerte die Antwort. Ich kann aber auch je nach BS, bekannte Ports nehmen und eine Antwort anfordern, das ist zwar nicht nach RFC, liefert aber oft bessere Ergebnisse.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
Garfield
Beiträge: 172
Registriert: Do 5. Jun 2008, 22:07
OS, Lazarus, FPC: Ubuntu 22.04 LTS (Laz 3.0 FPC3.2.2)
CPU-Target: 64Bit
Wohnort: Aken

Re: Im Netzwerk angemeldete Computer.

Beitrag von Garfield »

Danke. Dann muss ich mich mal mit Wireshark beschäftigen. Vielleicht bringt es auch was wieder ein Delphi zu installieren und damit zu vergleichen.

Das Ping sieht so aus:

Code: Alles auswählen

function Ping(IP:string; TimeOut:Cardinal):Boolean;
  var hICMP : DWORD;
      pierWork : PICMP_ECHO_REPLY;
      dwSize : DWORD;
      Class1,Class2,Class3,Class4 : String;
      i,j : Byte;
begin
  Result:=False;
  j:=1;
  for i:=1 to Length(IP) do begin
    if IP[i]<>'.' then begin
      case j of
        1: Class1:=Class1+IP[i];
        2: Class2:=Class2+IP[i];
        3: Class3:=Class3+IP[i];
        4: Class4:=Class4+IP[i];
      end;
    end else
      Inc(j);
  end;
  hICMP := IcmpCreateFile;
  if hICMP = INVALID_HANDLE_VALUE then exit;
  try
    dwSize := SizeOf(ICMP_ECHO_REPLY)+8;
    pierWork := AllocMem(dwSize);
    try
      if IcmpSendEcho(hICMP,MAKELONG(MAKEWORD(StrToInt(Class1), StrToInt(Class2)),MAKEWORD(StrToInt(Class3), StrToInt(Class4))),nil,0,nil,pierWork,dwSize,TimeOut) = 0 then
        Result:=False
      else
        Result:=True;
    finally
      FreeMem(pierWork,dwSize);
    end;
  finally
    IcmpCloseHandle(hIcmp);
  end;
end;                       


Da wird nichts gesendet. Die zu sendenden Daten sind nil und die Größe 0.

IcmpCreateFile
IcmpSendEcho
IcmpCloseHandle
Gruß Garfield

creed steiger
Beiträge: 957
Registriert: Mo 11. Sep 2006, 22:56

Re: Im Netzwerk angemeldete Computer.

Beitrag von creed steiger »

schau mal den Ping von Synapse an

http://synapse.ararat.cz/doc/help/pingsend.html

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Im Netzwerk angemeldete Computer.

Beitrag von mschnell »

Garfield hat geschrieben:Ich möchte unter Windows 10 die im Netzwerk angemeldeten Geräte mit ihrer IP auflisten.

Was meinst Du denn mit "Netzwerk angemeldeten Geräte"
Ein Endgerät kann sich bei einem "Server" diverser Art "anmelden", aber nicht in einem "Netzwerk". Es kann sich bei mehreren zugreifbaren Servern bei einigen anmelden und bei anderen nicht, oder auch mit Servern Servern kommunizieren ohne sich auf irgend eine Art "abzumelden".

Unter "im Netzwerk anmelden" könnte man am ehesten "eine Adresse via DHCP beziehen" verstehen. Aber auch hier können Computer oder embedded Geräte das Netzwerk benutzen, ohne vorher mit dem DHCP Server kommuniziert zu haben.

-Michael

Benutzeravatar
W126
Lazarusforum e. V.
Beiträge: 53
Registriert: Mo 27. Jul 2015, 11:19
OS, Lazarus, FPC: Linux
CPU-Target: Xeon Silver x64
Wohnort: Hofheim am Taunus

Re: Im Netzwerk angemeldete Computer.

Beitrag von W126 »

Na komm.... er möchte alle aktiven Geräte im Netz finden. So wie es Advances IP Scanner macht. (www.advanced-ip-scanner.com/de)

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Im Netzwerk angemeldete Computer.

Beitrag von mschnell »

Wie soll denn das gehen ?

Klar kann man - in einem Ethernet - die ARP-Bradcasts (zur IP-Adressen/MAC-Adressen-Zuordnung) tracen, und so nach einiger Zeit mit etwas Glück die meisten im lokalen Netzwerk-Zweig eingeschalteten Geräte finden (was anderes als Broadcasts ist ja hinter einem Switch nicht mehr da).

Wenn aber das "Netzwerk" aus mehreren mit Routern gekoppelten Zweigen besteht (z.B. WLAN), klappt das auch nicht mehr.

Ein Ping-Test mit allen möglichen IP-Adressen aller Netzwerk-Zweige wäre denkbar, dauert aber lange und man muss die IP-Adressen (und Masken) aller Netzwerk-Zweige kennen.

(Um alles noch zu vrschlimmern kann ein Gerät auch mit zwei IP-Adressen gleichzeitig in einem "Netz" aktiv sein (z.B parallel per Kabel und WLAN) ) .

-Michael

creed steiger
Beiträge: 957
Registriert: Mo 11. Sep 2006, 22:56

Re: Im Netzwerk angemeldete Computer.

Beitrag von creed steiger »

Naja 2 Möglichkeiten:

Brute Force Ping übers Netzwerk (dauert lang)
oder
UDP Broadcast (was nicht in andere Subnetze kommt)

Beides mit Synapse locker zu realisieren.

Geräte die Ping blocken und ähnliches mal ausgeklammert.

100% Erkennung sind eh nur im "normalen" LAN zu erreichen, was für den Hausgebrauch ja auch ausreicht.

Benutzeravatar
Garfield
Beiträge: 172
Registriert: Do 5. Jun 2008, 22:07
OS, Lazarus, FPC: Ubuntu 22.04 LTS (Laz 3.0 FPC3.2.2)
CPU-Target: 64Bit
Wohnort: Aken

Re: Im Netzwerk angemeldete Computer.

Beitrag von Garfield »

mschnell hat geschrieben:
Garfield hat geschrieben:Ich möchte unter Windows 10 die im Netzwerk angemeldeten Geräte mit ihrer IP auflisten.

Was meinst Du denn mit "Netzwerk angemeldeten Geräte"

Ich meine eine Liste wie in der Fritzbox unter Netzwerk bzw Funknetzwerk oder in der Android-App Fing. Konkret geht es darum, dass eine Kamera gefunden werden soll, um von dieser Dateien herunter zu laden.

Habe eine eigene Ping-Routine versucht:

Code: Alles auswählen

type
  ip_option_information = packed record
    Ttl         : UCHAR;
    Tos         : UCHAR;
    Flags       : UCHAR;
    OptionsSize : UCHAR;
    OptionsData : PUCHAR;
  end;
  PIP_OPTION_INFORMATION = ^IP_OPTION_INFORMATION;
 
  icmp_echo_reply = packed record
    Address       : TInAddr;
    Status        : ULONG;
    RoundTripTime : ULONG;
    DataSize      : USHORT;
    Reserved      : USHORT;
    Data          : PVOID;
    Options       : ip_option_information;
  end;
  PICMP_ECHO_REPLY = ^ICMP_ECHO_REPLY;
 
const
  // Konstanten für den Status
  IP_SUCCESS               =     0;
  IP_BUF_TOO_SMALL         = 11001;
  IP_DEST_NET_UNREACHABLE  = 11002;
  IP_DEST_HOST_UNREACHABLE = 11003;
  IP_DEST_PROT_UNREACHABLE = 11004;
  IP_DEST_PORT_UNREACHABLE = 11005;
  IP_NO_RESOURCES          = 11006;
  IP_BAD_OPTION            = 11007;
  IP_HW_ERROR              = 11008;
  IP_PACKET_TOO_BIG        = 11009;
  IP_REQ_TIMED_OUT         = 11010;
  IP_BAD_REQ               = 11011;
  IP_BAD_ROUTE             = 11012;
  IP_TTL_EXPIRED_TRANSIT   = 11013;
  IP_TTL_EXPIRED_REASSEM   = 11014;
  IP_PARAM_PROBLEM         = 11015;
  IP_SOURCE_QUENCH         = 11016;
  IP_OPTION_TOO_BIG        = 11017;
  IP_BAD_DESTINATION       = 11018;
  IP_GENERAL_FAILURE       = 11050;
 
function IcmpCreateFile : THANDLE; stdcall; external 'icmp.dll';
function IcmpCloseHandle(const IcmpHandle : THANDLE) : LongBool; stdcall; external 'icmp.dll';
function IcmpSendEcho(const IcmpHandle : DWORD; const DestinationAddress : TInAddr; const RequestData : Pointer; const RequestSize : WORD; const RequestOptions : PIP_OPTION_INFORMATION; const ReplyBuffer : Pointer; const ReplySize : DWORD; const TimeOut : DWORD) : DWORD; stdcall; external 'icmp.dll';
// Iphlpapi.dll on Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP;
// Icmp.dll on Windows 2000 Server and Windows 2000 Professional
 
function Ping(aIP: String; aTimeOut: Cardinal; aError: String): Boolean;
var
  hIcmpFile      : THANDLE;
  DestAddr       : TInAddr;
  RequestData    : String;
  RequestOptions : PIP_OPTION_INFORMATION;
  ReplyBuffer    : PICMP_ECHO_REPLY;
  ReplySize      : DWORD;
  dwRetVal       : DWORD;
  bRetVal        : LongBool;
begin
  // Init
  Result := False;
  aError := '';
  // Handle für eine IPv4 ICMP Abfrage öffnen.
  hIcmpFile := IcmpCreateFile;
  if hIcmpFile = INVALID_HANDLE_VALUE
  then begin
    // Kein Handle erhalten.
    aError := 'Kein Handle für die Abfrage erhalten';
  end
  else begin
    try
      // Ping initialisieren
      dwRetVal        := 0;
      DestAddr.S_addr := inet_addr(PChar(aIP));
      RequestData     := 'Data Buffer';
      RequestOptions  := nil;
      ReplySize       := SizeOf(icmp_echo_reply) + SizeOf(RequestData);
      ReplyBuffer     := AllocMem(ReplySize);
      if ReplyBuffer = nil
      then begin
        aError := 'Fehler bei der Reservierung von Speicher';
      end
      else begin
        // Pingen
        try
          dwRetVal := IcmpSendEcho(hIcmpFile, DestAddr, PChar(RequestData), SizeOf(RequestData) + 8, RequestOptions, ReplyBuffer, ReplySize, aTimeOut);
          if (dwRetVal = NO_ERROR) or (dwRetVal >= ERROR_INSUFFICIENT_BUFFER)
          then begin
            aError := SysErrorMessage(GetLastOSError);
            ShowMessage(aError);
          end;
        finally
          FreeMem(ReplyBuffer, ReplySize);
        end;
      end;
    finally
      // Das Handle schliessen.
      bRetVal := IcmpCloseHandle(hIcmpFile);
      if not(bRetVal)
      then aError := 'Das Handle konnte nicht geschlossen werden.';
    end;
  end;
end;                   


Da aError immer leer war, ist die Showmessage drin. Es kommt der Fehler "Fehler aufgrund zu wenigen Ressourcen".

Da sollte ich mal in Synapse reinsehen.
Gruß Garfield

Benutzeravatar
W126
Lazarusforum e. V.
Beiträge: 53
Registriert: Mo 27. Jul 2015, 11:19
OS, Lazarus, FPC: Linux
CPU-Target: Xeon Silver x64
Wohnort: Hofheim am Taunus

Re: Im Netzwerk angemeldete Computer.

Beitrag von W126 »

Mit Deiner Methode bist Du schon auf dem richtigen Weg. Der IP Scanner den ich erwähnt habe arbeitet auch so. Er geht jede IP Adresse durch und fragt einige Ports ab (HTTP, HTTPS, FTP, RDP usw.)
Leider bin ich zur Zeit mit einem Projekt ausgelastet, sonst würde ich gerne helfen.

Jörg

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Im Netzwerk angemeldete Computer.

Beitrag von mschnell »

Garfield hat geschrieben:Ich meine eine Liste wie in der Fritzbox unter Netzwerk bzw Funknetzwerk

Da der DHCP-Server auf der Fritzbox läuft weiß sie, welchen Geräten sie IP-Adressen zugeordnet hat und kann sie listen. Du müsstest sie also nach der Liste fragen. Keine Ahnung wie das sinnvoll geht.

Geräte mit fest eingestellten IP-Adressen sieht die Fritz-Box auch nicht.

-Michael

c18x37
Beiträge: 5
Registriert: Mo 23. Nov 2015, 12:57

Re: Im Netzwerk angemeldete Computer.

Beitrag von c18x37 »

W126 hat geschrieben:Mit Deiner Methode bist Du schon auf dem richtigen Weg. Der IP Scanner den ich erwähnt habe arbeitet auch so. Er geht jede IP Adresse durch und fragt einige Ports ab (HTTP, HTTPS, FTP, RDP usw.)


Jede Adresse durchgehen dauert in größeren Netzen möglicherweise sehr lange.
Hatte mal ein ähnliches Problem in einem 10er Netz.
Habe mich da für einen arp-scan entschieden (hatte auch zufällig einen Linux Server im Netz).

if RunCommand('/usr/bin/arp-scan', ['10.0.0.0/8'], s) then ... do something with s

Christoph

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Im Netzwerk angemeldete Computer.

Beitrag von af0815 »

Wenn man sich die ursprüngliche Aufgabe ansieht, so könnte man doch auch die WINS Auflösung von WIndows zu rate ziehen, da die meisten Programme (früher) damit zu recht gekommen sind. Den DHCP Server zu fragen ist nicht direkt möglich (IMHO), eventuell über SNMP, wenn der DHCP mitspielt, siehe dhcp-pool-monitor.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Im Netzwerk angemeldete Computer.

Beitrag von mschnell »

In "ordentlichen" Netzwerken ist der DHCP-Server mit dem DNS verbunden um die über DHCP "angemeldeten" Machinen über ihre Netzwerk-Namen verfügbar zu machen.

Pflicht ist das aber nicht.

-Michael

Benutzeravatar
Garfield
Beiträge: 172
Registriert: Do 5. Jun 2008, 22:07
OS, Lazarus, FPC: Ubuntu 22.04 LTS (Laz 3.0 FPC3.2.2)
CPU-Target: 64Bit
Wohnort: Aken

Re: Im Netzwerk angemeldete Computer.

Beitrag von Garfield »

Ich habe mich für Embarcadero® Delphi 10.1 Berlin Starter registriert. Nach der Installation habe ich mir den Ping dort angesehen und heute diesen Fehler gefunden:

Code: Alles auswählen

function IcmpSendEcho(const IcmpHandle : DWORD; const DestinationAddress : TInAddr; const RequestData : Pointer; const RequestSize : WORD; const RequestOptions : PIP_OPTION_INFORMATION; const ReplyBuffer : Pointer; const ReplySize : DWORD; const TimeOut : DWORD) : DWORD; stdcall; external 'Iphlpapi.dll';

TInAddr ist in Winsock2 wie folgt definiert:

Code: Alles auswählen

  PInAddr = ^TInAddr;
  TInAddr = record
    case integer of
      0: (S_un_b: SunB);
      1: (S_un_w: SunW);
      2: (S_addr: u_long);
    end;
  in_addr = TInAddr;


Bei Microsoft steht auch

Code: Alles auswählen

typedef struct {
  union {
    struct {
      u_char s_b1,s_b2,s_b3,s_b4;
    } S_un_b;
    struct {
      u_short s_w1,s_w2;
    } S_un_w;
    u_long S_addr;
  } S_un;
} IPAddr; 


Wenn ich dann die DestinationAddress als DWord definiere bekomme ich mit dem Aufruf

Code: Alles auswählen

dwRetVal := IcmpSendEcho(hIcmpFile, DestAddr, nil {PChar(RequestData)}, 0 {SizeOf(RequestData)}, nil {RequestOptions}, @ReplyBuffer[0], ReplySize, aTimeOut);

eine sinnvolle Antwort.

@Jörg. Den Scanner hatte ich schon mal gefunden aber leider erst heute ausprobiert. Dein Hinweis auf den Scanner hat mir schon geholfen. Sonst hätte ich mir den noch länger nicht angesehn.

@Michael. Man kann sich an der Fritzbox anmelden und eine entsprechende Anfrage stellen (http://www.fr-an.de/soft/14/bb.htm). Ob fest eingestellte IPs gelistet werden weiß ich nicht. Mir ist im Moment nicht bewußt ob mein Drucker angezeigt wird. Wenn sich Geräte einmal an der Fritzbox angemeldet haben, merkt sich die Fritzbox die MAC und die Bezeichnung und weist ihm immer die selbe IP zu. Die Geräte werden in der Liste auch angezeigt, wenn sie nicht verbunden sind. Das ist bei ARP wohl auch so.

@Christoph. Die Abfrage dürfte gar nicht so lange dauern. Ich glaube in der Entwicklerecke hatte Narses eine Klasse vorgestellt, mit welcher jede mögliche IP in einem eigenen Thread angepingt wurde. Damit sollte der PingScan kaum länger dauern als der Timeout. Im Moment geht es ja nur um ein Heimnetz. Da gibt es doch nicht mehr als 255 Möglichkeiten? (Ich sollte mich mal eingehender mit Netzwerken beschäftigen.)

Von SNMP habe ich auch schon gelesen, aber mich nicht damit beschäftigt.
Gruß Garfield

Antworten