-
Notifications
You must be signed in to change notification settings - Fork 2
/
magicPacket.go
109 lines (91 loc) · 2.13 KB
/
magicPacket.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package main
import (
"fmt"
"net"
"strconv"
)
/*
魔法包结构:
6字节头 96字节(目标mac * 16) 4-6字节(密码)
FF FF FF FF FF FF 11 22 33 44 55 66 *16 00 00 00 00 00 00
*/
// MagicPacket 魔法包
type MagicPacket struct {
header []byte
payload []byte
password []byte
}
// ParseMagicPacket MAC地址字符串转换为魔法包
func ParseMagicPacket(hardwareAddr string, password ...interface{}) (MagicPacket, error) {
var mp MagicPacket
mp.header = make([]byte, 6)
mp.payload = make([]byte, 96)
mp.password = make([]byte, 6)
// header
for i := 0; i < 6; i++ {
mp.header[i] = 0xff
}
// payload
mac, err := net.ParseMAC(hardwareAddr)
if err != nil {
return MagicPacket{}, err
}
for i := 0; i < 96; i = i + 6 {
copy(mp.payload[i:], mac)
}
// password
if len(password) != 0 {
passwd, err := net.ParseMAC(password[0].(string))
if err != nil {
return MagicPacket{}, fmt.Errorf("invalid password %v", password[0])
}
for i := 0; i < 6; i++ {
mp.password[i] = passwd[i]
}
}
return mp, nil
}
// Unmarshal []byte转换为魔法包
func Unmarshal(mpb []byte) (MagicPacket, error) {
var mp MagicPacket
mp.header = make([]byte, 6)
mp.payload = make([]byte, 96)
mp.password = make([]byte, 6)
if len(mpb) == 108 {
copy(mp.header[:], mpb[:6])
copy(mp.payload[:], mpb[6:102])
copy(mp.password[:], mpb[102:])
} else if len(mpb) == 102 {
copy(mp.header[:], mpb[:6])
copy(mp.payload[:], mpb[6:])
} else {
return mp, fmt.Errorf("invalid magic packet")
}
return mp, nil
}
// Marshal 魔法包转换为[]byte
func (mp MagicPacket) Marshal() []byte {
// 拼接 header payload password
return append(append(mp.header, mp.payload...), mp.password...)
}
// Send 发送魔法包
func (mp MagicPacket) Send(addr string, port int) error {
// 建立udp连接
conn, err := net.Dial("udp", addr+":"+strconv.Itoa(port))
if err != nil {
return err
}
// 函数运行完成关闭连接
defer func(conn net.Conn) {
err := conn.Close()
if err != nil {
panic(err)
}
}(conn)
// 发送数据
_, err = conn.Write(mp.Marshal())
if err != nil {
return err
}
return nil
}