174 lines
4.2 KiB
Go
174 lines
4.2 KiB
Go
package wpasupplicant
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/godbus/dbus/v5"
|
|
)
|
|
|
|
// BSS represents a wpa_supplicant BSS (Basic Service Set) object
|
|
type BSS struct {
|
|
path dbus.ObjectPath
|
|
conn *dbus.Conn
|
|
obj dbus.BusObject
|
|
}
|
|
|
|
// BSSProperties holds the properties of a BSS
|
|
type BSSProperties struct {
|
|
SSID []byte
|
|
BSSID []byte
|
|
Signal int16 // Signal strength in dBm
|
|
Frequency uint32 // Frequency in MHz
|
|
Privacy bool // Whether encryption is enabled
|
|
RSN map[string]dbus.Variant
|
|
WPA map[string]dbus.Variant
|
|
}
|
|
|
|
// NewBSS creates a new BSS instance
|
|
func NewBSS(conn *dbus.Conn, path dbus.ObjectPath) *BSS {
|
|
return &BSS{
|
|
path: path,
|
|
conn: conn,
|
|
obj: conn.Object(Service, path),
|
|
}
|
|
}
|
|
|
|
// GetProperties returns all properties of the BSS
|
|
func (b *BSS) GetProperties() (*BSSProperties, error) {
|
|
props := &BSSProperties{}
|
|
|
|
// Get SSID
|
|
if ssidProp, err := b.obj.GetProperty(BSSInterface + ".SSID"); err == nil {
|
|
if ssid, ok := ssidProp.Value().([]byte); ok {
|
|
props.SSID = ssid
|
|
}
|
|
}
|
|
|
|
// Get BSSID
|
|
if bssidProp, err := b.obj.GetProperty(BSSInterface + ".BSSID"); err == nil {
|
|
if bssid, ok := bssidProp.Value().([]byte); ok {
|
|
props.BSSID = bssid
|
|
}
|
|
}
|
|
|
|
// Get Signal
|
|
if signalProp, err := b.obj.GetProperty(BSSInterface + ".Signal"); err == nil {
|
|
if signal, ok := signalProp.Value().(int16); ok {
|
|
props.Signal = signal
|
|
}
|
|
}
|
|
|
|
// Get Frequency
|
|
if freqProp, err := b.obj.GetProperty(BSSInterface + ".Frequency"); err == nil {
|
|
if freq, ok := freqProp.Value().(uint16); ok {
|
|
props.Frequency = uint32(freq)
|
|
}
|
|
}
|
|
|
|
// Get Privacy
|
|
if privacyProp, err := b.obj.GetProperty(BSSInterface + ".Privacy"); err == nil {
|
|
if privacy, ok := privacyProp.Value().(bool); ok {
|
|
props.Privacy = privacy
|
|
}
|
|
}
|
|
|
|
// Get RSN (WPA2) information
|
|
if rsnProp, err := b.obj.GetProperty(BSSInterface + ".RSN"); err == nil {
|
|
if rsn, ok := rsnProp.Value().(map[string]dbus.Variant); ok {
|
|
props.RSN = rsn
|
|
}
|
|
}
|
|
|
|
// Get WPA information
|
|
if wpaProp, err := b.obj.GetProperty(BSSInterface + ".WPA"); err == nil {
|
|
if wpa, ok := wpaProp.Value().(map[string]dbus.Variant); ok {
|
|
props.WPA = wpa
|
|
}
|
|
}
|
|
|
|
return props, nil
|
|
}
|
|
|
|
// GetSSIDString returns the SSID as a string
|
|
func (b *BSS) GetSSIDString() (string, error) {
|
|
prop, err := b.obj.GetProperty(BSSInterface + ".SSID")
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to get SSID property: %v", err)
|
|
}
|
|
|
|
ssid, ok := prop.Value().([]byte)
|
|
if !ok {
|
|
return "", fmt.Errorf("SSID property is not a byte array")
|
|
}
|
|
|
|
return string(ssid), nil
|
|
}
|
|
|
|
// GetBSSIDString returns the BSSID as a formatted MAC address string
|
|
func (b *BSS) GetBSSIDString() (string, error) {
|
|
prop, err := b.obj.GetProperty(BSSInterface + ".BSSID")
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to get BSSID property: %v", err)
|
|
}
|
|
|
|
bssid, ok := prop.Value().([]byte)
|
|
if !ok || len(bssid) != 6 {
|
|
return "", fmt.Errorf("BSSID property is not a valid MAC address")
|
|
}
|
|
|
|
return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x",
|
|
bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]), nil
|
|
}
|
|
|
|
// GetSignal returns the signal strength in dBm
|
|
func (b *BSS) GetSignal() (int16, error) {
|
|
prop, err := b.obj.GetProperty(BSSInterface + ".Signal")
|
|
if err != nil {
|
|
return 0, fmt.Errorf("failed to get Signal property: %v", err)
|
|
}
|
|
|
|
signal, ok := prop.Value().(int16)
|
|
if !ok {
|
|
return 0, fmt.Errorf("Signal property is not an int16")
|
|
}
|
|
|
|
return signal, nil
|
|
}
|
|
|
|
// DetermineSecurityType determines the security type based on BSS properties
|
|
func (p *BSSProperties) DetermineSecurityType() string {
|
|
// Check for WPA2 (RSN) - need to check if KeyMgmt has actual values
|
|
if hasKeyManagement(p.RSN) {
|
|
return "psk"
|
|
}
|
|
|
|
// Check for WPA
|
|
if hasKeyManagement(p.WPA) {
|
|
return "psk"
|
|
}
|
|
|
|
// Check for WEP (privacy but no WPA/RSN)
|
|
if p.Privacy {
|
|
return "wep"
|
|
}
|
|
|
|
// Open network
|
|
return "open"
|
|
}
|
|
|
|
// hasKeyManagement checks if a WPA/RSN map contains actual key management methods
|
|
func hasKeyManagement(secMap map[string]dbus.Variant) bool {
|
|
if len(secMap) == 0 {
|
|
return false
|
|
}
|
|
|
|
// Check if KeyMgmt field exists and has values
|
|
if keyMgmtVariant, ok := secMap["KeyMgmt"]; ok {
|
|
// KeyMgmt is an array of strings
|
|
if keyMgmt, ok := keyMgmtVariant.Value().([]string); ok {
|
|
return len(keyMgmt) > 0
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|