owrt/uci_wireless_interface.go

210 lines
5.3 KiB
Go

package owrt
import (
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
)
// UCIWirelessInterface is the description of an Wireless interface (cf Openwrt doc) on top of an Wireless Device
type UCIWirelessInterface struct {
Name string
Index int
Device string
DevicePath string
SysDevName string
Mode string
Disabled bool
Ssid string
Bssid string
Network string
Encryption string
Key string
Country string
}
// NewUCIWirelessInterface builds a new UCIWirelessInterface instance
func NewUCIWirelessInterface() *UCIWirelessInterface {
return &UCIWirelessInterface{}
}
// GetSysDevName looks for the system name of Wireless Interface
func (wi *UCIWirelessInterface) GetSysDevName(sysDir string) string {
var found string
if wi.SysDevName != "" {
return wi.SysDevName
}
if sysDir == "" {
sysDir = "/sys/devices/platform"
}
if _, err := os.Stat(sysDir); os.IsNotExist(err) {
return "ERROR123-FILE-DONES-NOT-EXIST"
}
err := filepath.Walk(sysDir, func(path string, f os.FileInfo, _ error) error {
patt := fmt.Sprintf("%s/%s/.*/address", wi.DevicePath, "net")
r, err := regexp.MatchString(patt, path)
if err == nil && r {
res := strings.Split(path, "/")
idx := len(res) - 2
found = res[idx]
}
return nil
})
if err != nil {
return err.Error()
}
wi.SysDevName = found
return found
}
// Create add a new entry for wifi interface in UCI Configuration
func (wi *UCIWirelessInterface) Create(uci *UCI) *Action {
var confPrefix string
addRes := uci.AddWireless()
if addRes.ReturnCode != 0 {
return addRes
}
if wi.Index <= 0 {
confPrefix = fmt.Sprintf("wireless.@wifi-iface[%d]", len(uci.Wireless.Interfaces))
} else {
confPrefix = fmt.Sprintf("wireless.@wifi-iface[%d]", wi.Index)
}
conf := make(map[string][]string)
conf["network"] = append(conf["network"], fmt.Sprintf("%s.network", confPrefix), wi.Network)
conf["ssid"] = append(conf["ssid"], fmt.Sprintf("%s.ssid", confPrefix), wi.Ssid)
conf["enc"] = append(conf["enc"], fmt.Sprintf("%s.encryption", confPrefix), wi.Encryption)
conf["device"] = append(conf["device"], fmt.Sprintf("%s.device", confPrefix), wi.Device)
conf["mode"] = append(conf["mode"], fmt.Sprintf("%s.mode", confPrefix), wi.Mode)
conf["bssid"] = append(conf["bssid"], fmt.Sprintf("%s.bssid", confPrefix), wi.Bssid)
conf["key"] = append(conf["key"], fmt.Sprintf("%s.key", confPrefix), wi.Key)
conf["disabled"] = append(conf["disabled"], fmt.Sprintf("%s.disabled", confPrefix), "0")
conf["country"] = append(conf["country"], fmt.Sprintf("%s.country", confPrefix), wi.Country)
for _, value := range conf {
if value[1] != "" {
result := uci.Set(value[0], value[1])
if result.ReturnCode != 0 {
return result
}
}
}
return &Action{
CommandResult: &CommandResult{
Stdout: "",
Stderr: "",
ReturnCode: 0,
},
}
}
// Save commit and relaod configuration (writes it to files !)
func (wi *UCIWirelessInterface) Save(uci *UCI) *Action {
commitRes := uci.Commit()
if commitRes.ReturnCode != 0 {
return commitRes
}
reload := uci.Reload()
return reload
}
// SysAdd creates the interface in the system using iw command
func (wi *UCIWirelessInterface) SysAdd(uci *UCI) *Action {
cmd := "iw"
opt := "phy"
phydev := fmt.Sprintf("phy%d", wi.Index)
what := "interface"
act := "add"
tpe := "managed"
if wi.SysDevName == "" {
wi.SysDevName = fmt.Sprintf("tmp.radio%d", wi.Index)
}
res := uci.exec.Run(cmd, opt, phydev, what, act, wi.SysDevName, "type", tpe)
return &Action{
CommandResult: res,
Command: fmt.Sprintf("%s %s %s %s %s %s %s %s", cmd, opt, phydev, what, act, wi.SysDevName, "type", tpe),
}
}
// SysDel deletes the interface in the system using iw command
func (wi *UCIWirelessInterface) SysDel(uci *UCI) *Action {
cmd := "iw"
opt := "dev"
act := "del"
if wi.SysDevName == "" {
wi.SysDevName = fmt.Sprintf("tmp.radio%d", wi.Index)
}
res := uci.exec.Run(cmd, opt, wi.SysDevName, act)
return &Action{
CommandResult: res,
Command: fmt.Sprintf("%s %s %s %s", cmd, opt, wi.SysDevName, act),
}
}
// Up brings the interface up in the system using ip command
func (wi *UCIWirelessInterface) Up(uci *UCI) *Action {
cmd := "ip"
opt := "link"
act := "set"
wht := "dev"
res := uci.exec.Run(cmd, opt, act, wht, wi.SysDevName, "up")
return &Action{
CommandResult: res,
}
}
// Delete remove wifi interface from UCI Configuration
func (wi *UCIWirelessInterface) Delete(uci *UCI) *Action {
toDelete := fmt.Sprintf("wireless.@wifi-iface[%d]", wi.Index)
del := uci.Delete(toDelete)
if del.ReturnCode != 0 {
return del
}
return uci.Commit()
}
// Update add a new entry for wifi interface in UCI Configuration
func (wi *UCIWirelessInterface) Update(uci *UCI) *Action {
wi.Delete(uci)
create := wi.Create(uci)
if create.ReturnCode != 0 {
return create
}
return uci.Commit()
}
// Scan starts a scan for wifi networks with this device
func (wi *UCIWirelessInterface) Scan() []*WifiCell {
devName := wi.GetSysDevName("")
wifi := NewWifiScanner(devName)
return wifi.Scan()
}
// Connect updates configuration to connect to the WifiCell
func (wi *UCIWirelessInterface) Connect(uci *UCI, cell *WifiCell, secret string) *Action {
wi.Ssid = cell.Ssid
wi.Bssid = cell.MacAddress
wi.Encryption = cell.Encryption
wi.Mode = "sta"
wi.Key = secret
res := wi.Update(uci)
if res.ReturnCode != 0 {
return res
}
return wi.Save(uci)
}