95 lines
1.9 KiB
Go
95 lines
1.9 KiB
Go
package wol
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
)
|
|
|
|
func WakeUpRepeat(macAddr, broadcastIP, bcastInterface string, port, repeat int) {
|
|
i := 0
|
|
for {
|
|
WakeUp(macAddr, broadcastIP, bcastInterface, port)
|
|
i++
|
|
if i >= repeat {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func WakeUp(macAddr, broadcastIP, bcastInterface string, port int) error {
|
|
var localAddr *net.UDPAddr
|
|
var err error
|
|
if bcastInterface != "" {
|
|
localAddr, err = ipFromInterface(bcastInterface)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
bcastAddr := fmt.Sprintf("%s:%d", broadcastIP, port)
|
|
udpAddr, err := net.ResolveUDPAddr("udp", bcastAddr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Build the magic packet.
|
|
mp, err := New(macAddr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
bs, err := mp.Marshal()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
conn, err := net.DialUDP("udp", localAddr, udpAddr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer conn.Close()
|
|
|
|
//fmt.Printf("Attempting to send a magic packet to MAC %s\n", macAddr)
|
|
//fmt.Printf("... Broadcasting to: %s\n", bcastAddr)
|
|
n, err := conn.Write(bs)
|
|
if err == nil && n != 102 {
|
|
err = fmt.Errorf("magic packet sent was %d bytes (expected 102 bytes sent)", n)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
//fmt.Printf("Magic packet sent successfully to %s\n", macAddr)
|
|
return nil
|
|
|
|
}
|
|
|
|
// ipFromInterface returns a `*net.UDPAddr` from a network interface name.
|
|
func ipFromInterface(iface string) (*net.UDPAddr, error) {
|
|
ief, err := net.InterfaceByName(iface)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
addrs, err := ief.Addrs()
|
|
if err == nil && len(addrs) <= 0 {
|
|
err = fmt.Errorf("no address associated with interface %s", iface)
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Validate that one of the addrs is a valid network IP address.
|
|
for _, addr := range addrs {
|
|
switch ip := addr.(type) {
|
|
case *net.IPNet:
|
|
if !ip.IP.IsLoopback() && ip.IP.To4() != nil {
|
|
return &net.UDPAddr{
|
|
IP: ip.IP,
|
|
}, nil
|
|
}
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("no address associated with interface %s", iface)
|
|
}
|