package wpasupplicant import ( "fmt" "github.com/godbus/dbus/v5" ) // WPAInterface represents a wpa_supplicant Interface object type WPAInterface struct { path dbus.ObjectPath conn *dbus.Conn obj dbus.BusObject } // NewWPAInterface creates a new WPAInterface instance func NewWPAInterface(conn *dbus.Conn, path dbus.ObjectPath) *WPAInterface { return &WPAInterface{ path: path, conn: conn, obj: conn.Object(Service, path), } } // Scan triggers a network scan func (i *WPAInterface) Scan(scanType string) error { args := map[string]interface{}{ "Type": scanType, // "active" or "passive" } err := i.obj.Call(InterfaceInterface+".Scan", 0, args).Err if err != nil { return fmt.Errorf("scan failed: %v", err) } return nil } // GetBSSs returns a list of BSS (Basic Service Set) object paths func (i *WPAInterface) GetBSSs() ([]dbus.ObjectPath, error) { prop, err := i.obj.GetProperty(InterfaceInterface + ".BSSs") if err != nil { return nil, fmt.Errorf("failed to get BSSs property: %v", err) } bsss, ok := prop.Value().([]dbus.ObjectPath) if !ok { return nil, fmt.Errorf("BSSs property is not an array of ObjectPath") } return bsss, nil } // GetState returns the current connection state func (i *WPAInterface) GetState() (WPAState, error) { prop, err := i.obj.GetProperty(InterfaceInterface + ".State") if err != nil { return "", fmt.Errorf("failed to get State property: %v", err) } state, ok := prop.Value().(string) if !ok { return "", fmt.Errorf("State property is not a string") } return WPAState(state), nil } // GetCurrentBSS returns the currently connected BSS object path func (i *WPAInterface) GetCurrentBSS() (dbus.ObjectPath, error) { prop, err := i.obj.GetProperty(InterfaceInterface + ".CurrentBSS") if err != nil { return "", fmt.Errorf("failed to get CurrentBSS property: %v", err) } bss, ok := prop.Value().(dbus.ObjectPath) if !ok { return "", fmt.Errorf("CurrentBSS property is not an ObjectPath") } return bss, nil } // AddNetwork creates a new network configuration func (i *WPAInterface) AddNetwork(config map[string]interface{}) (dbus.ObjectPath, error) { var networkPath dbus.ObjectPath // Convert config to proper DBus variant format dbusConfig := make(map[string]dbus.Variant) for key, value := range config { dbusConfig[key] = dbus.MakeVariant(value) } err := i.obj.Call(InterfaceInterface+".AddNetwork", 0, dbusConfig).Store(&networkPath) if err != nil { return "", fmt.Errorf("failed to add network: %v", err) } return networkPath, nil } // SelectNetwork connects to a network func (i *WPAInterface) SelectNetwork(networkPath dbus.ObjectPath) error { err := i.obj.Call(InterfaceInterface+".SelectNetwork", 0, networkPath).Err if err != nil { return fmt.Errorf("failed to select network: %v", err) } return nil } // EnableNetwork marks a network configuration as enabled (eligible for auto-connect) func (i *WPAInterface) EnableNetwork(networkPath dbus.ObjectPath) error { netObj := i.conn.Object(Service, networkPath) err := netObj.SetProperty(NetworkInterface+".Enabled", dbus.MakeVariant(true)) if err != nil { return fmt.Errorf("failed to enable network: %v", err) } return nil } // RemoveNetwork removes a network configuration func (i *WPAInterface) RemoveNetwork(networkPath dbus.ObjectPath) error { err := i.obj.Call(InterfaceInterface+".RemoveNetwork", 0, networkPath).Err if err != nil { return fmt.Errorf("failed to remove network: %v", err) } return nil } // GetNetworks returns the object paths of all configured networks func (i *WPAInterface) GetNetworks() ([]dbus.ObjectPath, error) { prop, err := i.obj.GetProperty(InterfaceInterface + ".Networks") if err != nil { return nil, fmt.Errorf("failed to get Networks property: %v", err) } networks, ok := prop.Value().([]dbus.ObjectPath) if !ok { return nil, fmt.Errorf("Networks property is not an array of ObjectPath") } return networks, nil } // Disconnect disconnects from the current network func (i *WPAInterface) Disconnect() error { err := i.obj.Call(InterfaceInterface+".Disconnect", 0).Err if err != nil { return fmt.Errorf("disconnect failed: %v", err) } return nil } // SaveConfig saves the current configuration to the wpa_supplicant config file func (i *WPAInterface) SaveConfig() error { err := i.obj.Call(InterfaceInterface+".SaveConfig", 0).Err if err != nil { return fmt.Errorf("save config failed: %v", err) } return nil } // GetPath returns the D-Bus object path for this interface func (i *WPAInterface) GetPath() dbus.ObjectPath { return i.path } // GetScanning returns whether a scan is currently in progress func (i *WPAInterface) GetScanning() (bool, error) { prop, err := i.obj.GetProperty(InterfaceInterface + ".Scanning") if err != nil { return false, fmt.Errorf("failed to get Scanning property: %v", err) } scanning, ok := prop.Value().(bool) if !ok { return false, fmt.Errorf("Scanning property is not a boolean") } return scanning, nil }