package wpasupplicant import ( "fmt" "strings" "github.com/godbus/dbus/v5" ) // D-Bus interactions with the fi.w1.wpa_supplicant1 name must never trigger // service activation. repeater is the sole launcher of the daemon (via // `service wpa_supplicant start` in the app layer); if a call reached the bus // name while the daemon was down — a startup race, or a stray call in // Ethernet-uplink mode — the bus would auto-activate it from its .service // file, spawning `wpa_supplicant -u` and bypassing repeater's own launch. // // godbus only suppresses activation when FlagNoAutoStart is set on the message // (msg.Flags = flags & (FlagNoAutoStart | FlagNoReplyExpected)); the default // flag value of 0 leaves activation enabled. The helpers below set the flag on // every method call and property access. A leaked call then fails cleanly with // a ServiceUnknown error instead of resurrecting the daemon. // callNoAutoStart performs a method call with D-Bus auto-activation disabled. func callNoAutoStart(obj dbus.BusObject, method string, args ...interface{}) *dbus.Call { return obj.Call(method, dbus.FlagNoAutoStart, args...) } // getPropNoAutoStart reads a property (interface.member notation) with // auto-activation disabled. It mirrors dbus.Object.GetProperty, which // otherwise issues Properties.Get with the activation-enabling flag 0. func getPropNoAutoStart(obj dbus.BusObject, p string) (dbus.Variant, error) { var result dbus.Variant iface, prop, err := splitProperty(p) if err != nil { return result, err } err = obj.Call("org.freedesktop.DBus.Properties.Get", dbus.FlagNoAutoStart, iface, prop).Store(&result) return result, err } // setPropNoAutoStart writes a property with auto-activation disabled. The value // is passed through as-is, so callers wrap it in a dbus.Variant just as they // would for dbus.Object.SetProperty. func setPropNoAutoStart(obj dbus.BusObject, p string, v interface{}) error { iface, prop, err := splitProperty(p) if err != nil { return err } return obj.Call("org.freedesktop.DBus.Properties.Set", dbus.FlagNoAutoStart, iface, prop, v).Err } // splitProperty splits an "interface.member" property name into its interface // and member parts, matching godbus's own parsing. func splitProperty(p string) (iface, prop string, err error) { idx := strings.LastIndex(p, ".") if idx == -1 || idx+1 == len(p) { return "", "", fmt.Errorf("dbus: invalid property %s", p) } return p[:idx], p[idx+1:], nil }