-
Notifications
You must be signed in to change notification settings - Fork 0
/
watch.go
80 lines (71 loc) · 2.05 KB
/
watch.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
package dash
import (
"net"
"time"
"github.com/google/gopacket/pcap"
"github.com/google/gopacket/layers"
"github.com/google/gopacket"
"bytes"
)
type ButtonEvent struct {
MacAddress string
}
func WatchButton(iface *net.Interface, macAddress string) *chan ButtonEvent {
// Start up a goroutine to read in packet data.
var buttonEventChannel = make(chan ButtonEvent)
go prepareWatch(iface, macAddress, buttonEventChannel)
return &buttonEventChannel
}
func prepareWatch(iface *net.Interface, macAddress string, buttonEventChannel chan ButtonEvent) {
var event = ButtonEvent{
MacAddress: macAddress,
}
for {
// Open up a pcap handle for packet reads/writes.
pcapHandle, err := pcap.OpenLive(iface.Name, 65536, true, 200*time.Millisecond)
if err != nil {
panic(err)
}
watchForButton(pcapHandle, macAddress)
buttonEventChannel <- event
pcapHandle.Close()
}
}
var lastPushed = time.Time{}
// watchForButton watches a handle for incoming ARP responses we might care about, and prints them.
//
// watchForButton loops until 'stop' is closed.
func watchForButton(handle *pcap.Handle, macAddress string) {
src := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
in := src.Packets()
for {
var packet gopacket.Packet
select {
case packet = <-in:
arpLayer := packet.Layer(layers.LayerTypeARP)
if arpLayer == nil {
continue
}
arp := arpLayer.(*layers.ARP)
if arp.Operation == layers.ARPRequest {
//log.Printf("ARP request")
//log.Printf("IP %v Dst %v Src %v", net.IP(arp.SourceProtAddress), net.HardwareAddr(arp.DstHwAddress), net.HardwareAddr(arp.SourceHwAddress))
if addressEquals("00:00:00:00:00:00", arp.DstHwAddress) && addressEquals(macAddress, arp.SourceHwAddress) {
//log.Print("--> Received ARP request")
var now = time.Now()
if now.Sub(lastPushed).Seconds() > 5 {
lastPushed = now
return
}
}
}
}
}
}
func addressEquals(mac string, addr []byte) bool {
macParsed, error := net.ParseMAC(mac)
if error != nil {
return false
}
return bytes.Equal(macParsed, addr)
}