github.com/telepresenceio/telepresence/v2@v2.20.0-pro.6.0.20240517030216-236ea954e789/pkg/client/rootd/dbus/resolved.go (about) 1 //go:build linux 2 // +build linux 3 4 package dbus 5 6 import ( 7 "context" 8 "errors" 9 "fmt" 10 "net" 11 "strings" 12 13 "github.com/godbus/dbus/v5" 14 "golang.org/x/sys/unix" 15 16 "github.com/datawire/dlib/dlog" 17 ) 18 19 type ( 20 // A resolvedLinkAddress is the type of the array members of the argument to the SetLinkDNS DBus call. It consists 21 // of an address family (either AF_INET or AF_INET6), followed by a 4-byte or 16-byte array with the raw address data. 22 resolvedLinkAddress struct { 23 Dialect int32 24 IP net.IP 25 } 26 27 // A resolvedDomain is the type of the array members of the argument to the SetLinkDomains DBus call. It is a domain 28 // name string and a parameter identifying whether to include that domain in the search path, or only to be used for 29 // deciding which DNS server to route a given request to. 30 resolvedDomain struct { 31 Name string 32 RoutingOnly bool 33 } 34 ) 35 36 func withDBus(c context.Context, f func(*dbus.Conn) error) error { 37 conn, err := dbus.ConnectSystemBus() 38 if err != nil { 39 err = fmt.Errorf("failed to connect to system bus: %w", err) 40 dlog.Error(c, err) 41 return err 42 } 43 defer conn.Close() 44 return f(conn) 45 } 46 47 func IsResolveDRunning(c context.Context) bool { 48 err := withDBus(c, func(conn *dbus.Conn) error { 49 var names []string 50 if err := conn.BusObject().CallWithContext(c, "org.freedesktop.DBus.ListNames", 0).Store(&names); err != nil { 51 return err 52 } 53 for _, name := range names { 54 if name == "org.freedesktop.resolve1" { 55 return nil 56 } 57 } 58 return errors.New("not found") 59 }) 60 return err == nil 61 } 62 63 func SetLinkDNS(c context.Context, networkIndex int, ips ...net.IP) error { 64 return withDBus(c, func(conn *dbus.Conn) error { 65 addrs := make([]resolvedLinkAddress, len(ips)) 66 for i, ip := range ips { 67 addr := &addrs[i] 68 switch len(ip) { 69 case 4: 70 addr.Dialect = unix.AF_INET 71 case 16: 72 addr.Dialect = unix.AF_INET6 73 default: 74 return errors.New("illegal IP (not AF_INET or AF_INET6") 75 } 76 addr.IP = ip 77 } 78 return conn.Object("org.freedesktop.resolve1", "/org/freedesktop/resolve1").CallWithContext( 79 c, "org.freedesktop.resolve1.Manager.SetLinkDNS", 0, int32(networkIndex), addrs).Err 80 }) 81 } 82 83 func SetLinkDomains(c context.Context, networkIndex int, domains ...string) error { 84 return withDBus(c, func(conn *dbus.Conn) error { 85 dds := make([]resolvedDomain, 0, len(domains)) 86 for _, domain := range domains { 87 if domain == "" { 88 continue 89 } 90 routing := false 91 if strings.HasPrefix(domain, "~") { 92 domain = domain[1:] 93 routing = true 94 } 95 dds = append(dds, resolvedDomain{Name: domain, RoutingOnly: routing}) 96 } 97 return conn.Object("org.freedesktop.resolve1", "/org/freedesktop/resolve1").CallWithContext( 98 c, "org.freedesktop.resolve1.Manager.SetLinkDomains", 0, int32(networkIndex), dds).Err 99 }) 100 } 101 102 func RevertLink(c context.Context, networkIndex int) error { 103 return withDBus(c, func(conn *dbus.Conn) error { 104 return conn.Object("org.freedesktop.resolve1", "/org/freedesktop/resolve1").CallWithContext( 105 c, "org.freedesktop.resolve1.Manager.RevertLink", 0, int32(networkIndex)).Err 106 }) 107 }