mirror of
https://github.com/safing/portmaster
synced 2025-09-01 10:09:11 +00:00
216 lines
7.2 KiB
Go
216 lines
7.2 KiB
Go
// +build !server
|
|
|
|
package netenv
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"sync"
|
|
|
|
"github.com/godbus/dbus"
|
|
)
|
|
|
|
var (
|
|
dbusConn *dbus.Conn
|
|
dbusConnLock sync.Mutex
|
|
)
|
|
|
|
func getNameserversFromDbus() ([]Nameserver, error) { //nolint:gocognit // TODO
|
|
// cmdline tool for exploring: gdbus introspect --system --dest org.freedesktop.NetworkManager --object-path /org/freedesktop/NetworkManager
|
|
|
|
var nameservers []Nameserver
|
|
var err error
|
|
|
|
dbusConnLock.Lock()
|
|
defer dbusConnLock.Unlock()
|
|
|
|
if dbusConn == nil {
|
|
dbusConn, err = dbus.SystemBus()
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
primaryConnectionVariant, err := getNetworkManagerProperty(dbusConn, dbus.ObjectPath("/org/freedesktop/NetworkManager"), "org.freedesktop.NetworkManager.PrimaryConnection")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
primaryConnection, ok := primaryConnectionVariant.Value().(dbus.ObjectPath)
|
|
if !ok {
|
|
return nil, errors.New("dbus: could not assert type of /org/freedesktop/NetworkManager:org.freedesktop.NetworkManager.PrimaryConnection")
|
|
}
|
|
|
|
activeConnectionsVariant, err := getNetworkManagerProperty(dbusConn, dbus.ObjectPath("/org/freedesktop/NetworkManager"), "org.freedesktop.NetworkManager.ActiveConnections")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
activeConnections, ok := activeConnectionsVariant.Value().([]dbus.ObjectPath)
|
|
if !ok {
|
|
return nil, errors.New("dbus: could not assert type of /org/freedesktop/NetworkManager:org.freedesktop.NetworkManager.ActiveConnections")
|
|
}
|
|
|
|
sortedConnections := []dbus.ObjectPath{primaryConnection}
|
|
for _, activeConnection := range activeConnections {
|
|
if !objectPathInSlice(activeConnection, sortedConnections) {
|
|
sortedConnections = append(sortedConnections, activeConnection)
|
|
}
|
|
}
|
|
|
|
for _, activeConnection := range sortedConnections {
|
|
|
|
ip4ConfigVariant, err := getNetworkManagerProperty(dbusConn, activeConnection, "org.freedesktop.NetworkManager.Connection.Active.Ip4Config")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ip4Config, ok := ip4ConfigVariant.Value().(dbus.ObjectPath)
|
|
if !ok {
|
|
return nil, fmt.Errorf("dbus: could not assert type of %s:org.freedesktop.NetworkManager.Connection.Active.Ip4Config", activeConnection)
|
|
}
|
|
|
|
nameserverIP4sVariant, err := getNetworkManagerProperty(dbusConn, ip4Config, "org.freedesktop.NetworkManager.IP4Config.Nameservers")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
nameserverIP4s, ok := nameserverIP4sVariant.Value().([]uint32)
|
|
if !ok {
|
|
return nil, fmt.Errorf("dbus: could not assert type of %s:org.freedesktop.NetworkManager.IP4Config.Nameservers", ip4Config)
|
|
}
|
|
|
|
nameserverDomainsVariant, err := getNetworkManagerProperty(dbusConn, ip4Config, "org.freedesktop.NetworkManager.IP4Config.Domains")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
nameserverDomains, ok := nameserverDomainsVariant.Value().([]string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("dbus: could not assert type of %s:org.freedesktop.NetworkManager.IP4Config.Domains", ip4Config)
|
|
}
|
|
|
|
nameserverSearchesVariant, err := getNetworkManagerProperty(dbusConn, ip4Config, "org.freedesktop.NetworkManager.IP4Config.Searches")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
nameserverSearches, ok := nameserverSearchesVariant.Value().([]string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("dbus: could not assert type of %s:org.freedesktop.NetworkManager.IP4Config.Searches", ip4Config)
|
|
}
|
|
|
|
for _, ip := range nameserverIP4s {
|
|
a := uint8(ip / 16777216)
|
|
b := uint8((ip % 16777216) / 65536)
|
|
c := uint8((ip % 65536) / 256)
|
|
d := uint8(ip % 256)
|
|
nameservers = append(nameservers, Nameserver{
|
|
IP: net.IPv4(d, c, b, a),
|
|
Search: append(nameserverDomains, nameserverSearches...),
|
|
})
|
|
}
|
|
|
|
ip6ConfigVariant, err := getNetworkManagerProperty(dbusConn, activeConnection, "org.freedesktop.NetworkManager.Connection.Active.Ip6Config")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ip6Config, ok := ip6ConfigVariant.Value().(dbus.ObjectPath)
|
|
if !ok {
|
|
return nil, fmt.Errorf("dbus: could not assert type of %s:org.freedesktop.NetworkManager.Connection.Active.Ip6Config", activeConnection)
|
|
}
|
|
|
|
nameserverIP6sVariant, err := getNetworkManagerProperty(dbusConn, ip6Config, "org.freedesktop.NetworkManager.IP6Config.Nameservers")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
nameserverIP6s, ok := nameserverIP6sVariant.Value().([][]byte)
|
|
if !ok {
|
|
return nil, fmt.Errorf("dbus: could not assert type of %s:org.freedesktop.NetworkManager.IP6Config.Nameservers", ip6Config)
|
|
}
|
|
|
|
nameserverDomainsVariant, err = getNetworkManagerProperty(dbusConn, ip6Config, "org.freedesktop.NetworkManager.IP6Config.Domains")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
nameserverDomains, ok = nameserverDomainsVariant.Value().([]string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("dbus: could not assert type of %s:org.freedesktop.NetworkManager.IP6Config.Domains", ip6Config)
|
|
}
|
|
|
|
nameserverSearchesVariant, err = getNetworkManagerProperty(dbusConn, ip6Config, "org.freedesktop.NetworkManager.IP6Config.Searches")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
nameserverSearches, ok = nameserverSearchesVariant.Value().([]string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("dbus: could not assert type of %s:org.freedesktop.NetworkManager.IP6Config.Searches", ip6Config)
|
|
}
|
|
|
|
for _, ip := range nameserverIP6s {
|
|
if len(ip) != 16 {
|
|
return nil, fmt.Errorf("dbus: query returned IPv6 address (%s) with invalid length", ip)
|
|
}
|
|
nameservers = append(nameservers, Nameserver{
|
|
IP: net.IP(ip),
|
|
Search: append(nameserverDomains, nameserverSearches...),
|
|
})
|
|
}
|
|
}
|
|
|
|
return nameservers, nil
|
|
}
|
|
|
|
func getConnectivityStateFromDbus() (OnlineStatus, error) {
|
|
var err error
|
|
|
|
dbusConnLock.Lock()
|
|
defer dbusConnLock.Unlock()
|
|
|
|
if dbusConn == nil {
|
|
dbusConn, err = dbus.SystemBus()
|
|
}
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
connectivityStateVariant, err := getNetworkManagerProperty(dbusConn, dbus.ObjectPath("/org/freedesktop/NetworkManager"), "org.freedesktop.NetworkManager.Connectivity")
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
connectivityState, ok := connectivityStateVariant.Value().(uint32)
|
|
if !ok {
|
|
return 0, errors.New("dbus: could not assert type of /org/freedesktop/NetworkManager:org.freedesktop.NetworkManager.Connectivity")
|
|
}
|
|
|
|
// NMConnectivityState
|
|
// NM_CONNECTIVITY_UNKNOWN = 0 Network connectivity is unknown.
|
|
// NM_CONNECTIVITY_NONE = 1 The host is not connected to any network.
|
|
// NM_CONNECTIVITY_PORTAL = 2 The host is behind a captive portal and cannot reach the full Internet.
|
|
// NM_CONNECTIVITY_LIMITED = 3 The host is connected to a network, but does not appear to be able to reach the full Internet.
|
|
// NM_CONNECTIVITY_FULL = 4 The host is connected to a network, and appears to be able to reach the full Internet.
|
|
|
|
switch connectivityState {
|
|
case 0:
|
|
return StatusUnknown, nil
|
|
case 1:
|
|
return StatusOffline, nil
|
|
case 2:
|
|
return StatusPortal, nil
|
|
case 3:
|
|
return StatusLimited, nil
|
|
case 4:
|
|
return StatusOnline, nil
|
|
}
|
|
|
|
return StatusUnknown, nil
|
|
}
|
|
|
|
func getNetworkManagerProperty(conn *dbus.Conn, objectPath dbus.ObjectPath, property string) (dbus.Variant, error) {
|
|
object := conn.Object("org.freedesktop.NetworkManager", objectPath)
|
|
return object.GetProperty(property)
|
|
}
|
|
|
|
func objectPathInSlice(a dbus.ObjectPath, list []dbus.ObjectPath) bool {
|
|
for _, b := range list {
|
|
if string(b) == string(a) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|