-
Notifications
You must be signed in to change notification settings - Fork 37
/
packet.go
116 lines (94 loc) · 3.02 KB
/
packet.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
package main
import (
"net"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
)
type bonjourPacket struct {
packet gopacket.Packet
srcMAC *net.HardwareAddr
dstMAC *net.HardwareAddr
isIPv6 bool
vlanTag *uint16
isDNSQuery bool
}
func parsePacketsLazily(source *gopacket.PacketSource) chan bonjourPacket {
// Process packets, and forward Bonjour traffic to the returned channel
// Set decoding to Lazy
source.DecodeOptions = gopacket.DecodeOptions{Lazy: true}
packetChan := make(chan bonjourPacket, 100)
go func() {
for packet := range source.Packets() {
tag := parseVLANTag(packet)
// Get source and destination mac addresses
srcMAC, dstMAC := parseEthernetLayer(packet)
// Check IP protocol version
isIPv6 := parseIPLayer(packet)
// Get UDP payload
payload := parseUDPLayer(packet)
isDNSQuery := parseDNSPayload(payload)
// Pass on the packet for its next adventure
packetChan <- bonjourPacket{
packet: packet,
vlanTag: tag,
srcMAC: srcMAC,
dstMAC: dstMAC,
isIPv6: isIPv6,
isDNSQuery: isDNSQuery,
}
}
}()
return packetChan
}
func parseEthernetLayer(packet gopacket.Packet) (srcMAC, dstMAC *net.HardwareAddr) {
if parsedEth := packet.Layer(layers.LayerTypeEthernet); parsedEth != nil {
srcMAC = &parsedEth.(*layers.Ethernet).SrcMAC
dstMAC = &parsedEth.(*layers.Ethernet).DstMAC
}
return
}
func parseVLANTag(packet gopacket.Packet) (tag *uint16) {
if parsedTag := packet.Layer(layers.LayerTypeDot1Q); parsedTag != nil {
tag = &parsedTag.(*layers.Dot1Q).VLANIdentifier
}
return
}
func parseIPLayer(packet gopacket.Packet) (isIPv6 bool) {
if parsedIP := packet.Layer(layers.LayerTypeIPv4); parsedIP != nil {
isIPv6 = false
}
if parsedIP := packet.Layer(layers.LayerTypeIPv6); parsedIP != nil {
isIPv6 = true
}
return
}
func parseUDPLayer(packet gopacket.Packet) (payload []byte) {
if parsedUDP := packet.Layer(layers.LayerTypeUDP); parsedUDP != nil {
payload = parsedUDP.(*layers.UDP).Payload
}
return
}
func parseDNSPayload(payload []byte) (isDNSQuery bool) {
packet := gopacket.NewPacket(payload, layers.LayerTypeDNS, gopacket.Default)
if parsedDNS := packet.Layer(layers.LayerTypeDNS); parsedDNS != nil {
isDNSQuery = !parsedDNS.(*layers.DNS).QR
}
return
}
type packetWriter interface {
WritePacketData([]byte) error
}
func sendBonjourPacket(handle packetWriter, bonjourPacket *bonjourPacket, tag uint16, brMACAddress net.HardwareAddr) {
*bonjourPacket.vlanTag = tag
*bonjourPacket.srcMAC = brMACAddress
// Network devices may set dstMAC to the local MAC address
// Rewrite dstMAC to ensure that it is set to the appropriate multicast MAC address
if bonjourPacket.isIPv6 {
*bonjourPacket.dstMAC = net.HardwareAddr{0x33, 0x33, 0x00, 0x00, 0x00, 0xFB}
} else {
*bonjourPacket.dstMAC = net.HardwareAddr{0x01, 0x00, 0x5E, 0x00, 0x00, 0xFB}
}
buf := gopacket.NewSerializeBuffer()
gopacket.SerializePacket(buf, gopacket.SerializeOptions{}, bonjourPacket.packet)
handle.WritePacketData(buf.Bytes())
}