repeater/internal/wifi/wpasupplicant/bss.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
}