From 02b749a4c419da734b4467bc1214db25b232979a Mon Sep 17 00:00:00 2001 From: nikk gitanes Date: Mon, 13 Sep 2021 02:39:45 +0300 Subject: [PATCH] add some iface fun and don't start dlna on loopback and tunnels --- server/dlna/dlna.go | 10 +- server/dlna/list.go | 4 +- server/utils/net_interface_filter.go | 38 +++++++ .../utils/net_interface_filter_nix_darwin.go | 29 +++++ server/utils/net_interface_filter_win.go | 105 ++++++++++++++++++ 5 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 server/utils/net_interface_filter.go create mode 100644 server/utils/net_interface_filter_nix_darwin.go create mode 100644 server/utils/net_interface_filter_win.go diff --git a/server/dlna/dlna.go b/server/dlna/dlna.go index a8763f8..dfef97c 100644 --- a/server/dlna/dlna.go +++ b/server/dlna/dlna.go @@ -12,6 +12,7 @@ import ( "github.com/anacrolix/dms/dlna/dms" "server/log" + "server/utils" "server/web/pages/template" ) @@ -21,11 +22,16 @@ func Start() { dmsServer = &dms.Server{ Interfaces: func() (ifs []net.Interface) { var err error - ifs, err = net.Interfaces() + ifaces, err := net.Interfaces() if err != nil { log.TLogln(err) os.Exit(1) } + for _, element := range ifaces { + if element.Flags&net.FlagLoopback == 0 && element.Flags&net.FlagUp == net.FlagUp && element.Flags&net.FlagMulticast == net.FlagMulticast && utils.IsPhysicalInterface(element.HardwareAddr.String()) { + ifs = append(ifs, element) + } + } return }(), HTTPConn: func() net.Listener { @@ -159,7 +165,7 @@ func getDefaultFriendlyName() string { var list []string for _, i := range ifaces { addrs, _ := i.Addrs() - if i.Flags&net.FlagUp == net.FlagUp { + if i.Flags&net.FlagLoopback == 0 && i.Flags&net.FlagUp == net.FlagUp && i.Flags&net.FlagMulticast == net.FlagMulticast && utils.IsPhysicalInterface(i.HardwareAddr.String()) { for _, addr := range addrs { var ip net.IP switch v := addr.(type) { diff --git a/server/dlna/list.go b/server/dlna/list.go index 4e1922f..28fc268 100644 --- a/server/dlna/list.go +++ b/server/dlna/list.go @@ -115,7 +115,7 @@ func getTorrent(path, host string) (ret []interface{}) { func getTorrentMeta(path, host string) (ret interface{}) { - if path=="/" { + if path == "/" { rootObj := upnpav.Object{ ID: "0", ParentID: "-1", @@ -143,7 +143,7 @@ func getTorrentMeta(path, host string) (ret interface{}) { meta := upnpav.Container{Object: trObj} return meta } - + // find torrent without load torrs := torr.ListTorrent() var torr *torr.Torrent diff --git a/server/utils/net_interface_filter.go b/server/utils/net_interface_filter.go new file mode 100644 index 0000000..23bdb7b --- /dev/null +++ b/server/utils/net_interface_filter.go @@ -0,0 +1,38 @@ +package utils + +import ( + "strings" +) + +type PhysicalInterface struct { + MACAddress string + Name string + FriendlyName string +} + +// Mac Address parts to look for, and identify non physical devices. There may be more, update me! +var macAddrPartsToFilter []string = []string{ + "00:03:FF", // Microsoft Hyper-V, Virtual Server, Virtual PC + "0A:00:27", // VirtualBox + "00:00:00:00:00", // Teredo Tunneling Pseudo-Interface + "00:50:56", // VMware ESX 3, Server, Workstation, Player + "00:1C:14", // VMware ESX 3, Server, Workstation, Player + "00:0C:29", // VMware ESX 3, Server, Workstation, Player + "00:05:69", // VMware ESX 3, Server, Workstation, Player + "00:1C:42", // Microsoft Hyper-V, Virtual Server, Virtual PC + "00:0F:4B", // Virtual Iron 4 + "00:16:3E", // Red Hat Xen, Oracle VM, XenSource, Novell Xen + "08:00:27", // Sun xVM VirtualBox + "7A:79", // Hamachi +} + +// Filters the possible physical interface address by comparing it to known popular VM Software adresses +// and Teredo Tunneling Pseudo-Interface. +func IsPhysicalInterface(addr string) bool { + for _, macPart := range macAddrPartsToFilter { + if strings.HasPrefix(strings.ToLower(addr), strings.ToLower(macPart)) { + return false + } + } + return true +} diff --git a/server/utils/net_interface_filter_nix_darwin.go b/server/utils/net_interface_filter_nix_darwin.go new file mode 100644 index 0000000..5777510 --- /dev/null +++ b/server/utils/net_interface_filter_nix_darwin.go @@ -0,0 +1,29 @@ +//go:build linux || darwin +// +build linux darwin + +package utils + +import ( + "fmt" + "net" +) + +// Gets all physical interfaces based on filter results, ignoring all VM, Loopback and Tunnel interfaces. +func GetAllPhysicalInterfaces() []PhysicalInterface { + ifaces, err := net.Interfaces() + + if err != nil { + fmt.Println(err) + return nil + } + + var outInterfaces []PhysicalInterface + + for _, element := range ifaces { + if element.Flags&net.FlagLoopback == 0 && element.Flags&net.FlagUp == 1 && isPhysicalInterface(element.HardwareAddr.String()) { + outInterfaces = append(outInterfaces, PhysicalInterface{MACAddress: element.HardwareAddr.String(), Name: element.Name, FriendlyName: element.Name}) + } + } + + return outInterfaces +} diff --git a/server/utils/net_interface_filter_win.go b/server/utils/net_interface_filter_win.go new file mode 100644 index 0000000..0620d59 --- /dev/null +++ b/server/utils/net_interface_filter_win.go @@ -0,0 +1,105 @@ +//go:build windows +// +build windows + +package utils + +import ( + "os" + "syscall" + "unicode/utf16" + "unsafe" + + "golang.org/x/sys/windows" +) + +const ( + IfOperStatusUp = 1 + IF_TYPE_SOFTWARE_LOOPBACK = 24 + IF_TYPE_TUNNEL = 131 +) + +const hexDigit = "0123456789abcdef" + +func adapterAddresses() ([]*windows.IpAdapterAddresses, error) { + var b []byte + l := uint32(15000) // recommended initial size + for { + b = make([]byte, l) + err := windows.GetAdaptersAddresses(syscall.AF_UNSPEC, windows.GAA_FLAG_INCLUDE_PREFIX, 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &l) + if err == nil { + if l == 0 { + return nil, nil + } + break + } + if err.(syscall.Errno) != syscall.ERROR_BUFFER_OVERFLOW { + return nil, os.NewSyscallError("getadaptersaddresses", err) + } + if l <= uint32(len(b)) { + return nil, os.NewSyscallError("getadaptersaddresses", err) + } + } + var aas []*windows.IpAdapterAddresses + for aa := (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])); aa != nil; aa = aa.Next { + aas = append(aas, aa) + } + return aas, nil +} + +func bytePtrToString(p *uint8) string { + a := (*[10000]uint8)(unsafe.Pointer(p)) + i := 0 + for a[i] != 0 { + i++ + } + return string(a[:i]) +} + +func physicalAddrToString(physAddr [8]byte) string { + if len(physAddr) == 0 { + return "" + } + buf := make([]byte, 0, len(physAddr)*3-1) + for i, b := range physAddr { + if i > 0 { + buf = append(buf, ':') + } + buf = append(buf, hexDigit[b>>4]) + buf = append(buf, hexDigit[b&0xF]) + } + return string(buf) +} + +func cStringToString(cs *uint16) (s string) { + if cs != nil { + us := make([]uint16, 0, 256) + for p := uintptr(unsafe.Pointer(cs)); ; p += 2 { + u := *(*uint16)(unsafe.Pointer(p)) + if u == 0 { + return string(utf16.Decode(us)) + } + us = append(us, u) + } + } + return "" +} + +// Gets all physical interfaces based on filter results, ignoring all VM, Loopback and Tunnel interfaces. +func GetAllPhysicalInterfaces() []PhysicalInterface { + aa, _ := adapterAddresses() + + var outInterfaces []PhysicalInterface + + for _, pa := range aa { + mac := physicalAddrToString(pa.PhysicalAddress) + name := "\\Device\\NPF_" + bytePtrToString(pa.AdapterName) + + if pa.IfType != uint32(IF_TYPE_SOFTWARE_LOOPBACK) && pa.IfType != uint32(IF_TYPE_TUNNEL) && + pa.OperStatus == uint32(IfOperStatusUp) && IsPhysicalInterface(mac) { + + outInterfaces = append(outInterfaces, PhysicalInterface{MACAddress: mac, Name: name, FriendlyName: cStringToString(pa.FriendlyName)}) + } + } + + return outInterfaces +}