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) }