97 lines
2.2 KiB
Go
97 lines
2.2 KiB
Go
package networking
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
const deviceFile = "devices.json"
|
|
|
|
type Device struct {
|
|
Name string `json:"name"`
|
|
IP string `json:"ip"`
|
|
Interface string `json:"interface"`
|
|
Icon string `json:"icon"`
|
|
}
|
|
|
|
func GetDevices() map[string]map[string]Device {
|
|
result := make(map[string]map[string]Device)
|
|
devices := make(map[string]Device)
|
|
arpDevices := arpDevices()
|
|
knownDevices := knownDevices()
|
|
for mac, device := range arpDevices {
|
|
if strings.HasPrefix(device.Interface, "macvlan") {
|
|
continue
|
|
}
|
|
if known, ok := knownDevices[mac]; ok {
|
|
devices[mac] = Device{Name: known.Name, IP: device.IP, Interface: device.Interface, Icon: known.Icon}
|
|
} else {
|
|
devices[mac] = device
|
|
}
|
|
}
|
|
for mac, device := range knownDevices {
|
|
if _, ok := devices[mac]; !ok {
|
|
devices[mac] = Device{Name: device.Name, IP: device.IP, Interface: "offline", Icon: device.Icon}
|
|
}
|
|
}
|
|
writeDevices(devices)
|
|
|
|
for mac, device := range devices {
|
|
if strings.HasPrefix(device.Interface, "br") {
|
|
device.Icon = "\uE7B0"
|
|
device.Interface = "bridge"
|
|
}
|
|
if _, ok := result[device.Interface]; !ok {
|
|
result[device.Interface] = make(map[string]Device)
|
|
}
|
|
if device.Icon == "" {
|
|
device.Icon = "\U000F0C8A"
|
|
}
|
|
result[device.Interface][mac] = device
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func writeDevices(devices map[string]Device) {
|
|
marshal, err := json.MarshalIndent(devices, "", " ")
|
|
if err != nil {
|
|
}
|
|
if err := os.WriteFile(deviceFile, marshal, 0644); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func knownDevices() map[string]Device {
|
|
knownDevices := make(map[string]Device)
|
|
file, err := os.ReadFile(deviceFile)
|
|
if err == nil {
|
|
if err := json.Unmarshal(file, &knownDevices); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
return knownDevices
|
|
}
|
|
|
|
func arpDevices() map[string]Device {
|
|
arp := exec.Command("arp", "-a")
|
|
var out bytes.Buffer
|
|
arp.Stdout = &out
|
|
if err := arp.Run(); err != nil {
|
|
panic(err)
|
|
}
|
|
res := out.String()
|
|
lines := strings.Split(res, "\n")
|
|
devices := make(map[string]Device)
|
|
for l := range lines {
|
|
entry := strings.Fields(lines[l])
|
|
if len(entry) > 6 {
|
|
devices[entry[3]] = Device{Name: entry[0], IP: strings.ReplaceAll(strings.ReplaceAll(entry[1], "(", ""), ")", ""), Interface: entry[6]}
|
|
}
|
|
}
|
|
return devices
|
|
}
|