Module/Modul: WoL/WakeonLAN sendMagicPacket [WIN/LIN]

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Imhotheb
Beiträge: 192
Registriert: 10.10.2014 13:14
Computerausstattung: Intel 8086, 640 KB RAM, Hercules Video Adapter, 2 x 5 1/4" 360kb Floppy, MS-DOS 3
Wohnort: Wolfenbüttel

Module/Modul: WoL/WakeonLAN sendMagicPacket [WIN/LIN]

Beitrag von Imhotheb »

Hallo Zusammen,

hier ein Modul um ein MagicPacket zu versenden.
Damit kann man Rechner/PCs über das Netzwerk aufwecken.

Zum testen habe ich folgendes Programm (Windows) benutzt:
WoL-Sniffer ... auch WireShark macht hier seine Dienste (Linux und Windows)
Einfach auf einem beliebigen Rechner im Netzwerk starten und sehen ob ein Paket empfangen wird.
Oder einen Computer aus dem Netzwerk mit dem Modul aufwecken :wink:

Bei der Linux-Umsetzung hatte ich mir ein paar C-Codes angesehen und versucht das beste daraus zu machen ... war aber mehr Trial & Fail als Können.

Fragen/Anmerkungen ... Kritik oder Verbesserungsvorschläge? Immer her damit.

EDIT: Funktioniert nur mit IPv4 !!

Genauere Beschreibung im Code:

Code: Alles auswählen

; ==================================================
;|                 WakeOnLan - Module               |
;|==================================================|
;| Version: V1.1                Created: 02.04.2015 |
;| Type: PB-Include (Module)                        |
;| Author: Imhotheb (Andreas Wenzl)                 |
;| Compiler: PB5.31 32/64 [Win/Lin]                 |
;| Description: send MagicPacket                    |
; ==================================================
;
; WakeOnLan-Modul V1.1 - 02.04.2015
; ------------------------------------------------------------------
;
; V1.1  - kleiner Bugfix / Kommentare überarbeitet
; V1.0  - erste Version
;
; ein MagicPacket (WoL-Paket) versenden um damit einen Rechner aufzuwecken
;
; Getestet mit PB 5.31 x86/x86 unter Win7 32Bit/64Bit und XUbuntu 14.10 amd64/i386
;
; InitNetwork() wird benötigt
; 
; Linux: Broadcast muss 255.255.255.255, die lokale Broadcast Addresse oder eine direkte IP sein
; Win: für Broadcast ist alles außer 255.255.255.255 zulässig
;
;
; Aufruf:
; WoL::sendMagicPacket("MacAddresse", "Broadcast oder IP", Portnummer)
; MacAddresse als String übergeben z.B. "AA:BB:CC:DD:EE:FF"
; Broadcast als String übergeben Standart = "10.255.255.255"
; Port als Nummer übergeben. Für WoL wird in der Regel 0, 7 und 9 verwendet.
;
; Rückgabewerte: Erfolgreich: #True / Fehlgeschlagen: #False
;
; Hinweise:
; Man kann eine BroadcastAddresse auch im Router/Gateway freigeben und dann sehr einfach
; aus der "Ferne" sein ganzes Netzwerk aufwecken.
; Jedoch sollte aber Nutzen / Risiko abgewogen und andere Ports verwendet werden
; Bei einer direkten Addresse muss der Switch/Hub die Mac intern gespeichert haben, was aber
; i.d.R. kein Problem sein sollte
;
; ------------------------------------------------------------------

DeclareModule WoL
  Declare sendMagicPacket(Mac.s, Broadcast.s = "10.255.255.255", Port = 9)
EndDeclareModule

Module WoL
  EnableExplicit
 
  Structure MacAddress
    Byte.b[6]
  EndStructure
 
  Structure MagicPacket
    Header.b[6]
    Mac.MacAddress[16]
  EndStructure
   
  Structure MacAddress_Stringfields
    Byte1.s{2}
    Seperator1.s{1}
    Byte2.s{2}
    Seperator2.s{1}
    Byte3.s{2}
    Seperator3.s{1}
    Byte4.s{2}
    Seperator4.s{1}
    Byte5.s{2}
    Seperator5.s{1}
    Byte6.s{2}
  EndStructure
 
  Structure MacAddress_String
    StructureUnion
      Stringfields.MacAddress_Stringfields
      Mac.s{17}
    EndStructureUnion
  EndStructure
 
  ; Konstanten und Strukturen für Linux / sendMagicPacket()
  CompilerIf #PB_Compiler_OS = #PB_OS_Linux
    Structure sockaddr_in Align #PB_Structure_AlignC
      IP_Family.u
      Port.u
      Addr.l
      Zero.a[8]
    EndStructure     
    #IP_Family = 2      ;IPv4
    #Socket_DGRAM = 2     ;UDP
    #SO_Broadcast = 6 ;??
    #SOL_SOCKET = 1   ;??
    #FIONBIO = $5421
    #Invalid_Socket = -1
  CompilerEndIf
 
 
 
  ; MacAddress & MagicPacket
  ; ----------------------
 
  ; *dest = Zeiger mit einer MacAddress-Struktur
  ; Mac.s = MacAddress als String (z.B. 11:22:33:44:55:66 oder 11-22-33-44-55-66)
  Procedure createMacAdress(*Dest.MacAddress, Mac.s)
    Protected Mac_String.MacAddress_String
    Mac_String\Mac = Mac
   
    ; man könnte hier sicherlich auch StringField() benutzen,
    ; aber so können die Trennzeichen beliebig gewählt werden
    *dest\Byte[0] = Val("$" + Mac_String\Stringfields\Byte1)
    *dest\Byte[1] = Val("$" + Mac_String\Stringfields\Byte2)
    *dest\Byte[2] = Val("$" + Mac_String\Stringfields\Byte3)
    *dest\Byte[3] = Val("$" + Mac_String\Stringfields\Byte4)
    *dest\Byte[4] = Val("$" + Mac_String\Stringfields\Byte5)
    *dest\Byte[5] = Val("$" + Mac_String\Stringfields\Byte6)
   
    ProcedureReturn #True
  EndProcedure
 
  ; *dest = Zeiger mit einer MacAddress-Struktur
  ; Mac.s = MacAddress als String (z.B. 11:22:33:44:55:66 oder 11-22-33-44-55-66)
  Procedure createMagicPacket(*Dest.MagicPacket, Mac.s)
    Protected i.b, j.b
    Protected MacAddress.MacAddress
   
    createMacAdress(@MacAddress, Mac)
   
    For i = 0 To 5              ; Header erstellen ($FFFFFFFFFFFF)
      *Dest\Header[i] = $FF
    Next
    For i = 0 To 15             ; erstelle 16 x Mac
      For j = 0 To 5
        *Dest\Mac[i]\Byte[j] = MacAddress\Byte[j]
      Next j
    Next i
   
    ProcedureReturn #True 
  EndProcedure
 
 
  ; BENÖTIGT: InitNetwork()
  ; Linux: Broadcast muss 255.255.255.255, die lokale Broadcast Addresse oder eine direkte IP sein
  ; Win: für Broadcast ist alles außer 255.255.255.255 zulässig
  Procedure sendMagicPacket(Mac.s, Broadcast.s = "10.255.255.255", Port = 9)
    Protected MagicPacket.MagicPacket
    createMagicPacket(@MagicPacket, Mac)
   
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected cID                 ; ConnectionID
        Protected sendBytes.w
        Protected BufferLength = SizeOf(MagicPacket)
       
        cID = OpenNetworkConnection(Broadcast, Port, #PB_Network_UDP)
        If cID
          sendBytes = SendNetworkData(cID, @MagicPacket, BufferLength)
          If sendBytes = -1
            Debug "WOL::sendMagicPacket(): keine Daten übertragen" ; TODO Debug wenn nicht gewünscht entfernen/ändern
            CloseNetworkConnection(cID)
            ProcedureReturn #False
          ElseIf sendBytes = BufferLength
            CloseNetworkConnection(cID)
            ProcedureReturn #True
          Else
            Debug "WoL::sendMagicPacket(): Puffer / übertragene Daten unterschiedlich: " +
                  Str(sendBytes) + "/" + Str(BufferLength) ; TODO Debug wenn nicht gewünscht entfernen/ändern
             ProcedureReturn #False
          EndIf
        Else
          Debug "WoL::sendMagicPacket(): Kann Netzwrkverbindung nicht herstellen" ; TODO Debug wenn nicht gewünscht entfernen/ändern
          ProcedureReturn #False
        EndIf
        ProcedureReturn #True
       
      CompilerCase #PB_OS_Linux
        Protected TxAddr.sockaddr_in  ; Structur-Zeiger für Socket-Erstellung
        Protected Socket.i
        Protected argp.l      ; Zeiger für Parameterübergabe
        Protected Addr_Broadcast  ; wir brauchen eine numerische IP
        Addr_Broadcast = MakeIPAddress(Val(StringField(Broadcast, 1, ".")),Val(StringField(Broadcast, 2, ".")),
                                       Val(StringField(Broadcast, 3, ".")), Val(StringField(Broadcast, 4, ".")))
       
        ; Socket erstellen
        Socket = socket_(#IP_Family, #Socket_DGRAM, 0)
        If Socket = #Invalid_Socket
          Debug "SocketFehler" ; TODO Debug wenn nicht gewünscht entfernen/ändern
          ProcedureReturn #False
        EndIf
       
        ; Blocking abschalten
        argp = 1
        ioctl_(Socket, #FIONBIO, @argp)
       
        ; Broadcasts erlauben
        argp = Addr_Broadcast ; oder $FFFFFFFF
        setsockopt_(Socket, #SOL_SOCKET, #SO_BROADCAST, @argp, 4)
       
        ; Daten-Zeiger erzeugen
        TxAddr\IP_Family = #IP_Family
        TxAddr\Port = htons_(Port)   ;PortNr.
        TxAddr\Addr = Addr_Broadcast
       
        ;senden
        sendto_(Socket, @MagicPacket, SizeOf(MagicPacket) , 0, @TxAddr, SizeOf(sockaddr_in))
       
        ;schließen
        close_(Socket)
        ProcedureReturn #True
       
    CompilerEndSelect
   
    ProcedureReturn #False
  EndProcedure 
EndModule

CompilerIf #PB_Compiler_IsMainFile
 
  ; Netzwerk MUSS initialisiert sein:
  InitNetwork()
 
  WoL::sendMagicPacket("AA:BB:CC:DD:EE:FF", "127.255.255.255", 9)
  
  UseModule WoL
  sendMagicPacket("AA:BB:CC:DD:EE:FF", "127.255.255.255", 9)
  
CompilerEndIf
weil einfach einfach einfach ist ... mach' ich es anders
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Module/Modul: WoL/WakeonLAN sendMagicPacket [WIN/LIN]

Beitrag von GPI »

Die Windows-Version wollte bei mir nicht funktionieren. Ich hab den Part von durch den von hier http://forums.purebasic.com/english/vie ... p?p=221986 ersetzt und die Routinen Unicode-tauglich gemacht.

https://github.com/GPIforGit/PureBasic- ... eOnLan.pbi
Zuletzt geändert von GPI am 20.12.2015 00:14, insgesamt 1-mal geändert.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Module/Modul: WoL/WakeonLAN sendMagicPacket [WIN/LIN]

Beitrag von ts-soft »

@Imhotheb

InitNetwork() darfste ruhig in das Module packen, es wird immer nur einmal ausgeführt. Das gilt für alle "Init" Funktionen, seid
die Module eingeführt wurden.

Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Imhotheb
Beiträge: 192
Registriert: 10.10.2014 13:14
Computerausstattung: Intel 8086, 640 KB RAM, Hercules Video Adapter, 2 x 5 1/4" 360kb Floppy, MS-DOS 3
Wohnort: Wolfenbüttel

Re: Module/Modul: WoL/WakeonLAN sendMagicPacket [WIN/LIN]

Beitrag von Imhotheb »

@GPI: Hatte die "alte" Windows-Version nochmal getestet ... funtktionierte bei mir auch noch in PB 5.40 / Win10 64 ... aber danke für die Anpassung

@ts-soft: Danke für die Info ... hatte da mal einen Beitrag gelesen, in dem stand das es zu Problemen führen kann ... aber scheint wohl schon einige Zeit her zu sein :lol:

Und weil ich gerade mal hier bin ... wie machen wir das jetzt mit zukünftigen Updates ... über Forum, also hier ... oder über GitHub ? ... oder beides? :roll:
weil einfach einfach einfach ist ... mach' ich es anders
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Module/Modul: WoL/WakeonLAN sendMagicPacket [WIN/LIN]

Beitrag von GPI »

Imhotheb hat geschrieben:@GPI: Hatte die "alte" Windows-Version nochmal getestet ... funtktionierte bei mir auch noch in PB 5.40 / Win10 64 ... aber danke für die Anpassung
Meine Diskstation ist nicht aufgewacht. Möglich das es wegen den Weg PC-Switch-Router-Diskstation und der statischen IP nicht geklappt hat. Zudem geht jetzt bei Windows auch die Adresse 255.255.255.255.
Und weil ich gerade mal hier bin ... wie machen wir das jetzt mit zukünftigen Updates ... über Forum, also hier ... oder über GitHub ? ... oder beides? :roll:
Über mithilfe bei Github würde ich mich immer freuen. Ansonsten hier posten, ich sammle das dann ein und übertrags :)

Toll wäre es, wenn noch jemand eine MAC-Version postet, dann hätten wir alle drei.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
Imhotheb
Beiträge: 192
Registriert: 10.10.2014 13:14
Computerausstattung: Intel 8086, 640 KB RAM, Hercules Video Adapter, 2 x 5 1/4" 360kb Floppy, MS-DOS 3
Wohnort: Wolfenbüttel

Re: Module/Modul: WoL/WakeonLAN sendMagicPacket [WIN/LIN]

Beitrag von Imhotheb »

GPI hat geschrieben:Meine Diskstation ist nicht aufgewacht. Möglich das es wegen den Weg PC-Switch-Router-Diskstation und der statischen IP nicht geklappt hat.
Das Problem hatte ich auch mit ein paar "Desktop-Switches" ... manche scheinen einen recht kleinen Speicher zu besitzen oder den Cache zu schnell zu leeren.
weil einfach einfach einfach ist ... mach' ich es anders
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Module/Modul: WoL/WakeonLAN sendMagicPacket [WIN/LIN]

Beitrag von GPI »

Imhotheb hat geschrieben:
GPI hat geschrieben:Meine Diskstation ist nicht aufgewacht. Möglich das es wegen den Weg PC-Switch-Router-Diskstation und der statischen IP nicht geklappt hat.
Das Problem hatte ich auch mit ein paar "Desktop-Switches" ... manche scheinen einen recht kleinen Speicher zu besitzen oder den Cache zu schnell zu leeren.
Äh, das glaub ich jetzt weniger, es ist ein 24fach Switch mit 8000 Mac-Adressen-Speicher. Das sollte überhaupt kein Problem darstellen. Wenns der nicht packt, dann schaffts keiner. Ich hab da eher den Router in verdacht, über den noch alles geht. Das ist zwar ein FritzBox und die sollten sowas können, aber dort ist halt DHCP konfiguriert, die Diskstation hat aber eine Statische IP, die von der vorgeschlagenen abweicht. Ich schätze mal, da liegt der Hund begraben. Das Problem lös ich jetzt mit der Broadcastadresse 255.255.255.255. Das kommt dann an.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
Imhotheb
Beiträge: 192
Registriert: 10.10.2014 13:14
Computerausstattung: Intel 8086, 640 KB RAM, Hercules Video Adapter, 2 x 5 1/4" 360kb Floppy, MS-DOS 3
Wohnort: Wolfenbüttel

Re: Module/Modul: WoL/WakeonLAN sendMagicPacket [WIN/LIN]

Beitrag von Imhotheb »

GPI hat geschrieben: ... es ist ein 24fach Switch mit 8000 Mac-Adressen-Speicher ...
Muss ich zustimmen, liegt wohl nicht am Switch :lol:
Hauptsache es funktioniert jetzt
weil einfach einfach einfach ist ... mach' ich es anders
Antworten