- 取得連結
- X
- 以電子郵件傳送
- 其他應用程式
程式語言:Go
功能:建立魔法封包
由於只要資料是以上格式即可,因此可以作為任何網絡和傳輸層協議發送
通常做法為 UDP 發送到端口 0, 7, 9 之一
TCP 不太適合,因目標通常為待機狀態,無法進行 Handshake 的動作
github.com/linde12/gowol
github.com/ghthor/gowol
github.com/sabhiram/go-wol
- Package:
- "bytes"
- "encoding/binary"
- "fmt"
- "log"
- "net"
- "regexp"
- "github.com/pkg/errors"
功能:建立魔法封包
格式說明
魔術封包 包含 6 bytes 的 0xFF 與 16 次重複的 MAC 地址由於只要資料是以上格式即可,因此可以作為任何網絡和傳輸層協議發送
通常做法為 UDP 發送到端口 0, 7, 9 之一
TCP 不太適合,因目標通常為待機狀態,無法進行 Handshake 的動作
程式碼
magicPacket.go
magicPacket_test.go
package magicPacket
////////////////////////////////////////////////////////////////////////////////
import (
"bytes"
"encoding/binary"
"fmt"
"log"
"net"
"regexp"
"github.com/pkg/errors"
)
////////////////////////////////////////////////////////////////////////////////
var (
delims = ":-"
reMAC = regexp.MustCompile(`^([0-9a-fA-F]{2}[` + delims + `]){5}([0-9a-fA-F]{2})$`)
)
////////////////////////////////////////////////////////////////////////////////
// MACAddress represents a 6 byte network mac address.
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
}
// New returns a magic packet based on a mac address string.
func New(mac string) (*MagicPacket, error) {
var packet MagicPacket
var macAddr MACAddress
hwAddr, err := net.ParseMAC(mac)
if err != nil {
return nil, errors.Wrap(err, "net.ParseMAC")
}
// We only support 6 byte MAC addresses since it is much harder to use the
// binary.Write(...) interface when the size of the MagicPacket is dynamic.
if !reMAC.MatchString(mac) {
return nil, errors.Errorf("%s is not a IEEE 802 MAC-48 address", mac)
}
// 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
}
// Marshal serializes the magic packet structure into a 102 byte slice.
func (mp *MagicPacket) marshal() ([]byte, error) {
var buf bytes.Buffer
if err := binary.Write(&buf, binary.BigEndian, mp); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Send MagicPacket by UDP
func (mp *MagicPacket) SendUDP(ip string, port int) error {
bcastAddr := fmt.Sprintf("%s:%d", ip, port)
udpAddr, err := net.ResolveUDPAddr("udp", bcastAddr)
if err != nil {
return errors.Wrap(err, "net.ResolveUDPAddr")
}
conn, err := net.DialUDP("udp", nil, udpAddr)
if err != nil {
return errors.Wrap(err, "net.DialUDP")
}
defer conn.Close()
log.Printf("Attempting to send a magic packet to MAC %x\n", mp.payload[0])
log.Printf("... Broadcasting to: %s\n", bcastAddr)
bs, err := mp.marshal()
if err != nil {
return errors.Wrap(err, "mp.marshal")
}
_, err = conn.Write(bs)
return errors.Wrap(err, "conn.Write")
}
magicPacket_test.go
package magicPacket
import (
"testing"
)
func TestSendUDP(t *testing.T) {
mp, err := New("11:22:33:44:55:66")
if err != nil {
t.Error(err)
}
err = mp.SendUDP("192.168.1.255", 9)
if err != nil {
t.Error(err)
}
}
參考
Wake-on-LANgithub.com/linde12/gowol
github.com/ghthor/gowol
github.com/sabhiram/go-wol
留言
張貼留言