-
Notifications
You must be signed in to change notification settings - Fork 37
/
main.go
88 lines (76 loc) · 2.34 KB
/
main.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
package main
import (
"flag"
"fmt"
"log"
"net"
"net/http"
_ "net/http/pprof"
"time"
"github.com/google/gopacket"
"github.com/google/gopacket/pcap"
)
func main() {
// Read config file and generate mDNS forwarding maps
configPath := flag.String("config", "", "Config file in TOML format")
debug := flag.Bool("debug", false, "Enable pprof server on /debug/pprof/")
flag.Parse()
// Start debug server
if *debug {
go debugServer(6060)
}
cfg, err := readConfig(*configPath)
if err != nil {
log.Fatalf("Could not read configuration: %v", err)
}
poolsMap := mapByPool(cfg.Devices)
// Get a handle on the network interface
rawTraffic, err := pcap.OpenLive(cfg.NetInterface, 65536, true, time.Second)
if err != nil {
log.Fatalf("Could not find network interface: %v", cfg.NetInterface)
}
// Get the local MAC address, to filter out Bonjour packet generated locally
intf, err := net.InterfaceByName(cfg.NetInterface)
if err != nil {
log.Fatal(err)
}
brMACAddress := intf.HardwareAddr
// Filter tagged bonjour traffic
filterTemplate := "not (ether src %s) and vlan and dst net (224.0.0.251 or ff02::fb) and udp dst port 5353"
err = rawTraffic.SetBPFFilter(fmt.Sprintf(filterTemplate, brMACAddress))
if err != nil {
log.Fatalf("Could not apply filter on network interface: %v", err)
}
// Get a channel of Bonjour packets to process
decoder := gopacket.DecodersByLayerName["Ethernet"]
source := gopacket.NewPacketSource(rawTraffic, decoder)
bonjourPackets := parsePacketsLazily(source)
// Process Bonjours packets
for bonjourPacket := range bonjourPackets {
fmt.Println(bonjourPacket.packet.String())
// Forward the mDNS query or response to appropriate VLANs
if bonjourPacket.isDNSQuery {
tags, ok := poolsMap[*bonjourPacket.vlanTag]
if !ok {
continue
}
for _, tag := range tags {
sendBonjourPacket(rawTraffic, &bonjourPacket, tag, brMACAddress)
}
} else {
device, ok := cfg.Devices[macAddress(bonjourPacket.srcMAC.String())]
if !ok {
continue
}
for _, tag := range device.SharedPools {
sendBonjourPacket(rawTraffic, &bonjourPacket, tag, brMACAddress)
}
}
}
}
func debugServer(port int) {
err := http.ListenAndServe(fmt.Sprintf("localhost:%d", port), nil)
if err != nil {
log.Fatalf("The application was started with -debug flag but could not listen on port %v: \n %s", port, err)
}
}