/
mdns.go
100 lines (83 loc) · 2.13 KB
/
mdns.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
package packets
import (
"net"
"strings"
"github.com/evilsocket/islazy/str"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
)
const MDNSPort = 5353
var (
MDNSDestMac = net.HardwareAddr{0x01, 0x00, 0x5e, 0x00, 0x00, 0xfb}
MDNSDestIP = net.ParseIP("224.0.0.251")
)
func MDNSGetMeta(pkt gopacket.Packet) map[string]string {
meta := make(map[string]string)
defer func() {
if r := recover(); r != nil {
meta = nil
}
}()
if ludp := pkt.Layer(layers.LayerTypeUDP); ludp != nil {
if udp := ludp.(*layers.UDP); udp != nil && udp.SrcPort == MDNSPort && udp.DstPort == MDNSPort {
dns := layers.DNS{}
if err := dns.DecodeFromBytes(udp.Payload, gopacket.NilDecodeFeedback); err == nil {
answers := append(dns.Answers, dns.Additionals...)
answers = append(answers, dns.Authorities...)
for _, answer := range answers {
switch answer.Type {
case layers.DNSTypePTR:
case layers.DNSTypeA:
case layers.DNSTypeAAAA:
meta["mdns:hostname"] = string(answer.Name)
case layers.DNSTypeTXT:
for _, raw := range answer.TXTs {
if value := string(raw); strings.Contains(value, "=") {
parts := strings.SplitN(value, "=", 2)
meta["mdns:"+str.Trim(parts[0])] = str.Trim(parts[1])
}
}
}
}
}
}
}
if meta != nil && len(meta) > 0 {
return meta
}
return nil
}
func NewMDNSProbe(from net.IP, from_hw net.HardwareAddr) (error, []byte) {
eth := layers.Ethernet{
SrcMAC: from_hw,
DstMAC: MDNSDestMac,
EthernetType: layers.EthernetTypeIPv4,
}
ip4 := layers.IPv4{
Protocol: layers.IPProtocolUDP,
Version: 4,
TTL: 64,
SrcIP: from,
DstIP: MDNSDestIP,
}
udp := layers.UDP{
SrcPort: layers.UDPPort(12345),
DstPort: layers.UDPPort(MDNSPort),
}
dns := layers.DNS{
ID: 1,
RD: true,
OpCode: layers.DNSOpCodeQuery,
Questions: []layers.DNSQuestion{
{
Name: []byte("_services._dns-sd._udp.local"),
Type: layers.DNSTypePTR,
Class: layers.DNSClassIN,
},
},
}
if err := udp.SetNetworkLayerForChecksum(&ip4); err != nil {
return err, nil
}
return Serialize(ð, &ip4, &udp, &dns)
}