This repository has been archived by the owner on Jan 9, 2021. It is now read-only.
/
sniffer.go
125 lines (105 loc) · 2.56 KB
/
sniffer.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package main
import (
"fmt"
"log"
"net"
"sync"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
)
//type fn func(string)
var DashMacs = map[string]func(){}
var State = map[string]bool{}
func SnifferStart() {
// Get a list of all interfaces.
ifaces, err := net.Interfaces()
if err != nil {
panic(err)
}
var wg sync.WaitGroup
for _, iface := range ifaces {
wg.Add(1)
// Start up a scan on each interface.
go func(iface net.Interface) {
defer wg.Done()
if err := scan(&iface); err != nil {
log.Printf("interface %v: %v", iface.Name, err)
}
}(iface)
}
wg.Wait()
}
func scan(iface *net.Interface) error {
// We just look for IPv4 addresses, so try to find if the interface has one.
var addr *net.IPNet
if addrs, err := iface.Addrs(); err != nil {
return err
} else {
for _, a := range addrs {
if ipnet, ok := a.(*net.IPNet); ok {
if ip4 := ipnet.IP.To4(); ip4 != nil {
addr = &net.IPNet{
IP: ip4,
Mask: ipnet.Mask[len(ipnet.Mask)-4:],
}
break
}
}
}
}
// Sanity-check that the interface has a good address.
if addr == nil {
return fmt.Errorf("no good IP network found")
} else if addr.IP[0] == 127 {
return fmt.Errorf("skipping localhost")
} else if addr.Mask[0] != 0xff || addr.Mask[1] != 0xff {
return fmt.Errorf("mask means network is too large")
}
log.Printf("Using network range %v for interface %v", addr, iface.Name)
// Open up a pcap handle for packet reads/writes.
handle, err := pcap.OpenLive(iface.Name, 65536, true, pcap.BlockForever)
if err != nil {
return err
}
defer handle.Close()
stop := make(chan struct{})
readARP(handle, iface, stop)
defer close(stop)
return err
}
func readARP(handle *pcap.Handle, iface *net.Interface, stop chan struct{}) {
src := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
in := src.Packets()
for {
var packet gopacket.Packet
select {
case <-stop:
return
case packet = <-in:
arpLayer := packet.Layer(layers.LayerTypeARP)
if arpLayer == nil {
continue
}
arp := arpLayer.(*layers.ARP)
if !net.IP(arp.SourceProtAddress).Equal(net.ParseIP("0.0.0.0")) {
continue
}
found := false
for mac, fn := range DashMacs {
if net.HardwareAddr(arp.SourceHwAddress).String() == mac {
if !State[mac] {
log.Printf("Click sniffed for %v", mac)
State[mac] = true
fn()
State[mac] = false
}
found = true
}
}
if !found {
log.Printf("FOUND UNKNOWN MAC: %v", net.HardwareAddr(arp.SourceHwAddress))
}
}
}
}