123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- package main
- import (
- "bytes"
- "encoding/binary"
- "errors"
- "fmt"
- "net"
- "regexp"
- )
- /* A complete go sending a WOL packet
- This is from
- https://sabhiram.com/development/2015/02/16/sending_wol_packets_with_golang.html
- */
- // A MacAddress is 6 bytes in a row
- type MacAddress [6]byte
- // A MagicPacket is constituted of 6 bytes of 0xFF followed by
- // 16 groups of the destination MAC address.
- type MagicPacket struct {
- header [6]byte
- payload [16]MacAddress
- }
- // Define globals for MacAddress parsing
- var (
- delims = ":-"
- re_MAC = regexp.MustCompile(`^([0-9a-fA-F]{2}[` + delims + `]){5}([0-9a-fA-F]{2})$`)
- )
- // This function accepts a MAC Address string, and returns a pointer to
- // a MagicPacket object. A Magic Packet is a broadcast frame which
- // contains 6 bytes of 0xFF followed by 16 repetitions of a given mac address.
- func NewMagicPacket(mac string) (*MagicPacket, error) {
- var packet MagicPacket
- var macAddr MacAddress
- // We only support 6 byte MAC addresses
- if !re_MAC.MatchString(mac) {
- return nil, errors.New("MAC address " + mac + " is not valid.")
- }
- hwAddr, err := net.ParseMAC(mac)
- if err != nil {
- return nil, err
- }
- // Copy bytes from the returned HardwareAddr -> a fixed size MACAddress
- for idx := range macAddr {
- macAddr[idx] = hwAddr[idx]
- }
- // Setup the header which is 6 repetitions of 0xFF
- for idx := range packet.header {
- packet.header[idx] = 0xFF
- }
- // Setup the payload which is 16 repetitions of the MAC addr
- for idx := range packet.payload {
- packet.payload[idx] = macAddr
- }
- return &packet, nil
- }
- // This function accepts a MAC address string, and s
- // Function to send a magic packet to a given mac address
- func SendMagicPacket(tvip, macAddr string) error {
- magicPacket, err := NewMagicPacket(macAddr)
- if err != nil {
- return err
- }
- // Fill our byte buffer with the bytes in our MagicPacket
- var buf bytes.Buffer
- binary.Write(&buf, binary.BigEndian, magicPacket)
- // Get a UDPAddr to send the broadcast to
- udpAddr, err := net.ResolveUDPAddr("udp", tvip)
- if err != nil {
- fmt.Printf("Unable to get a UDP address for %s\n", tvip)
- return err
- }
- // Open a UDP connection, and defer its cleanup
- connection, err := net.DialUDP("udp", nil, udpAddr)
- if err != nil {
- fmt.Printf("Unable to dial UDP address for %s\n", tvip)
- return err
- }
- defer connection.Close()
- // Write the bytes of the MagicPacket to the connection
- var neededBytes int = buf.Len()
- bytesWritten, err := connection.Write(buf.Bytes())
- if err != nil {
- fmt.Printf("Unable to write packet to connection\n")
- return err
- } else if bytesWritten != neededBytes {
- fmt.Printf("Warning: %d bytes written, %d expected!\n", bytesWritten, neededBytes)
- }
- return nil
- }
|