From b8f0a554c10407a3326801ad12cf0ac98b219493 Mon Sep 17 00:00:00 2001 From: Philippe Caseiro Date: Wed, 19 Sep 2018 14:39:00 +0200 Subject: [PATCH 01/10] Adding begin of openwrt manipulation module --- openwrt/uci.go | 78 ++++++++++++++++++++++++++++++++++++++++++++ openwrt/uci_test.go | 48 +++++++++++++++++++++++++++ openwrt/utils.go | 38 +++++++++++++++++++++ openwrt/wifi_cell.go | 31 ++++++++++++++++++ 4 files changed, 195 insertions(+) create mode 100644 openwrt/uci.go create mode 100644 openwrt/uci_test.go create mode 100644 openwrt/utils.go create mode 100644 openwrt/wifi_cell.go diff --git a/openwrt/uci.go b/openwrt/uci.go new file mode 100644 index 0000000..65f3c0c --- /dev/null +++ b/openwrt/uci.go @@ -0,0 +1,78 @@ +package openwrt + +import ( + "bytes" + "fmt" + "log" + "os/exec" + "time" +) + +// Action is the result of an UCI action output and return code +type Action struct { + output string + errors string + returnCode int +} + +// uciRun, private method to run the UCI command +func uciRun(uciAction string, param string) *Action { + cmd := "uci" + + res := Run(cmd, uciAction, param) + return &Action{ + output: res.stdout, + errors: res.stderr, + returnCode: res.returnCode, + } +} + +// UciAdd add an entry to UCI configuration, specify the Module and the value +func UciAdd(module string, name string) *Action { + actionRes := uciRun("add", fmt.Sprintf("%s %s", module, name)) + return actionRes +} + +// UciDelete delete an entry from UCI configuration specify the entry name +func UciDelete(entry string) *Action { + return uciRun("delete", entry) +} + +// UciSet set a value ton an UCI configuration entry +func UciSet(entry string, value string) *Action { + return uciRun("set", fmt.Sprintf("%s=%s", entry, value)) +} + +// UciCommit the recent actions to UCI +func UciCommit() *Action { + return uciRun("commit", "") +} + +// UciReload reload uci configuration +func UciReload() *Action { + var out bytes.Buffer + var stderr bytes.Buffer + + exe := exec.Command("reload_config") + exe.Stdout = &out + exe.Stderr = &stderr + + err := exe.Run() + if err != nil { + fmt.Println(fmt.Sprint(err) + ": " + stderr.String()) + log.Fatal(err) + } + + time.Sleep(5) + + return &Action{ + output: out.String(), + returnCode: 0, + } +} + +// UciAddWireless Create a new Wireless entry in UCI configuration +func UciAddWireless(name string) int { + res := UciAdd("wireless", name) + return res.returnCode +} diff --git a/openwrt/uci_test.go b/openwrt/uci_test.go new file mode 100644 index 0000000..14ba08f --- /dev/null +++ b/openwrt/uci_test.go @@ -0,0 +1,48 @@ +package openwrt + +import ( + "log" + "strings" + "testing" +) + +var retCode int +var retStdout string +var retStderr string + +type UCI struct { + exec Executor +} + +func (u *UCI) Run(command string, args []string) (stdout string, stderr string, exit int, err error) { + return u.exec.Run(command, args) +} + +func NewUCI(exec Executor) *UCI { + return &UCI{exec} +} + +type Executor interface { + Run(command string, args []string) (stdout string, stderr string, exit int, err error) +} + +type fakeExecutor struct{} + +func (e *fakeExecutor) Run(command string, args []string) (stdout string, stderr string, exit int, err error) { + log.Printf("executing '%s %s'", command, strings.Join(args, " ")) + return "", "", 0, nil +} + +func TestUciAdd(t *testing.T) { + + retCode = 0 + retStdout = "OK" + retStderr = "" + + // Return 0 run ! + res := UciAdd("wireless", "test") + if res.returnCode != 0 { + t.Error(res.errors) + } + +} diff --git a/openwrt/utils.go b/openwrt/utils.go new file mode 100644 index 0000000..e2e5a84 --- /dev/null +++ b/openwrt/utils.go @@ -0,0 +1,38 @@ +package openwrt + +import ( + "bytes" + "fmt" + "log" + "os/exec" +) + +// CommandResult contain all information about a command execution, stdout, stderr +type CommandResult struct { + stdout string + stderr string + returnCode int +} + +// Run executes a system command and returns +func Run(command string, params ...string) *CommandResult { + var out bytes.Buffer + var stderr bytes.Buffer + + exe := exec.Command(command, params...) + exe.Stdout = &out + exe.Stderr = &stderr + + err := exe.Run() + if err != nil { + fmt.Println(fmt.Sprint(err) + ": " + stderr.String()) + log.Fatal(err) + } + + return &CommandResult{ + stdout: out.String(), + stderr: stderr.String(), + // FIXME + returnCode: 0, + } +} diff --git a/openwrt/wifi_cell.go b/openwrt/wifi_cell.go new file mode 100644 index 0000000..15e0ffe --- /dev/null +++ b/openwrt/wifi_cell.go @@ -0,0 +1,31 @@ +package openwrt + +import ( + "fmt" + "strings" +) + +// WifiCell reprensents wifi network Cell +type WifiCell struct { + // The SSID + Ssid string + // The cell mac adress + MacAdress string +} + +// NewWifiCell returns a new WifiCell object +func NewWifiCell(ssid string, mac string) *WifiCell { + return &WifiCell{ + Ssid: ssid, + MacAdress: mac, + } +} + +// GetWifiCells retrieves all availabe wifi cells for a card ! +func GetWifiCells(iface string) { + res := Run("iwinfo", iface, "scan") + for _, line := range strings.Split(strings.TrimSuffix(res.stdout, "\n"), "\n") { + fmt.Println(line) + } + +} From e1f0c686304b8ba8ea3eae9fa7d23b90ff255353 Mon Sep 17 00:00:00 2001 From: William Petit Date: Wed, 19 Sep 2018 15:22:51 +0200 Subject: [PATCH 02/10] Object oriented UCI + Executor interface --- openwrt/executor.go | 37 +++++++++++++++++++++++++++++++++++++ openwrt/test.go | 29 +++++++++++++++++++++++++++++ openwrt/uci.go | 18 ++++++++---------- openwrt/uci_struct.go | 19 +++++++++++++++++++ openwrt/uci_struct_test.go | 11 +++++++++++ openwrt/uci_test.go | 37 ++----------------------------------- openwrt/utils.go | 14 +++++++------- openwrt/wifi_cell.go | 4 ++-- 8 files changed, 115 insertions(+), 54 deletions(-) create mode 100644 openwrt/executor.go create mode 100644 openwrt/test.go create mode 100644 openwrt/uci_struct.go create mode 100644 openwrt/uci_struct_test.go diff --git a/openwrt/executor.go b/openwrt/executor.go new file mode 100644 index 0000000..2c19fb7 --- /dev/null +++ b/openwrt/executor.go @@ -0,0 +1,37 @@ +package openwrt + +import ( + "bytes" + "fmt" + "log" + "os/exec" +) + +type Executor interface { + Run(command string, params ...string) *CommandResult +} + +type localExecutor struct{} + +func (e *localExecutor) Run(command string, params ...string) *CommandResult { + + var out bytes.Buffer + var stderr bytes.Buffer + + exe := exec.Command(command, params...) + exe.Stdout = &out + exe.Stderr = &stderr + + err := exe.Run() + if err != nil { + fmt.Println(fmt.Sprint(err) + ": " + stderr.String()) + log.Fatal(err) + } + + return &CommandResult{ + Stdout: out.String(), + Stderr: stderr.String(), + // FIXME + ReturnCode: 0, + } +} diff --git a/openwrt/test.go b/openwrt/test.go new file mode 100644 index 0000000..77b3e3a --- /dev/null +++ b/openwrt/test.go @@ -0,0 +1,29 @@ +package openwrt + +import ( + "log" + "strings" +) + +func createMockExecutor(stdout string, stderr string, returnCode int) Executor { + return &mockExecutor{ + stdout: stdout, + stderr: stderr, + returnCode: returnCode, + } +} + +type mockExecutor struct { + stdout string + stderr string + returnCode int +} + +func (e *mockExecutor) Run(command string, params ...string) *CommandResult { + log.Printf("executing '%s %s'", command, strings.Join(params, " ")) + return &CommandResult{ + Stderr: e.stderr, + Stdout: e.stdout, + ReturnCode: e.returnCode, + } +} diff --git a/openwrt/uci.go b/openwrt/uci.go index 65f3c0c..d02872f 100644 --- a/openwrt/uci.go +++ b/openwrt/uci.go @@ -10,20 +10,16 @@ import ( // Action is the result of an UCI action output and return code type Action struct { - output string - errors string - returnCode int + *CommandResult } // uciRun, private method to run the UCI command func uciRun(uciAction string, param string) *Action { cmd := "uci" - res := Run(cmd, uciAction, param) + res := run(cmd, uciAction, param) return &Action{ - output: res.stdout, - errors: res.stderr, - returnCode: res.returnCode, + res, } } @@ -66,13 +62,15 @@ func UciReload() *Action { time.Sleep(5) return &Action{ - output: out.String(), - returnCode: 0, + &CommandResult{ + Stdout: out.String(), + ReturnCode: 0, + }, } } // UciAddWireless Create a new Wireless entry in UCI configuration func UciAddWireless(name string) int { res := UciAdd("wireless", name) - return res.returnCode + return res.ReturnCode } diff --git a/openwrt/uci_struct.go b/openwrt/uci_struct.go new file mode 100644 index 0000000..d440ae6 --- /dev/null +++ b/openwrt/uci_struct.go @@ -0,0 +1,19 @@ +package openwrt + +type UCI struct { + exec Executor +} + +func NewUCI() *UCI { + exec := &localExecutor{} + return &UCI{exec} +} + +func NewUCIWithExecutor(exec Executor) *UCI { + return &UCI{exec} +} + +func (u *UCI) Add(module string, name string) *Action { + commandRes := u.exec.Run("uci add", module, name) + return &Action{commandRes} +} diff --git a/openwrt/uci_struct_test.go b/openwrt/uci_struct_test.go new file mode 100644 index 0000000..af25884 --- /dev/null +++ b/openwrt/uci_struct_test.go @@ -0,0 +1,11 @@ +package openwrt + +import ( + "testing" +) + +func TestUCIStruct(t *testing.T) { + exec := createMockExecutor("", "", 1) + uci := NewUCIWithExecutor(exec) + uci.Add("wireless", "test") +} diff --git a/openwrt/uci_test.go b/openwrt/uci_test.go index 14ba08f..927884d 100644 --- a/openwrt/uci_test.go +++ b/openwrt/uci_test.go @@ -1,48 +1,15 @@ package openwrt import ( - "log" - "strings" "testing" ) -var retCode int -var retStdout string -var retStderr string - -type UCI struct { - exec Executor -} - -func (u *UCI) Run(command string, args []string) (stdout string, stderr string, exit int, err error) { - return u.exec.Run(command, args) -} - -func NewUCI(exec Executor) *UCI { - return &UCI{exec} -} - -type Executor interface { - Run(command string, args []string) (stdout string, stderr string, exit int, err error) -} - -type fakeExecutor struct{} - -func (e *fakeExecutor) Run(command string, args []string) (stdout string, stderr string, exit int, err error) { - log.Printf("executing '%s %s'", command, strings.Join(args, " ")) - return "", "", 0, nil -} - func TestUciAdd(t *testing.T) { - retCode = 0 - retStdout = "OK" - retStderr = "" - // Return 0 run ! res := UciAdd("wireless", "test") - if res.returnCode != 0 { - t.Error(res.errors) + if res.ReturnCode != 0 { + t.Error(res.Stderr) } } diff --git a/openwrt/utils.go b/openwrt/utils.go index e2e5a84..6e0dbed 100644 --- a/openwrt/utils.go +++ b/openwrt/utils.go @@ -9,13 +9,13 @@ import ( // CommandResult contain all information about a command execution, stdout, stderr type CommandResult struct { - stdout string - stderr string - returnCode int + Stdout string + Stderr string + ReturnCode int } // Run executes a system command and returns -func Run(command string, params ...string) *CommandResult { +func run(command string, params ...string) *CommandResult { var out bytes.Buffer var stderr bytes.Buffer @@ -30,9 +30,9 @@ func Run(command string, params ...string) *CommandResult { } return &CommandResult{ - stdout: out.String(), - stderr: stderr.String(), + Stdout: out.String(), + Stderr: stderr.String(), // FIXME - returnCode: 0, + ReturnCode: 0, } } diff --git a/openwrt/wifi_cell.go b/openwrt/wifi_cell.go index 15e0ffe..a6ac91f 100644 --- a/openwrt/wifi_cell.go +++ b/openwrt/wifi_cell.go @@ -23,8 +23,8 @@ func NewWifiCell(ssid string, mac string) *WifiCell { // GetWifiCells retrieves all availabe wifi cells for a card ! func GetWifiCells(iface string) { - res := Run("iwinfo", iface, "scan") - for _, line := range strings.Split(strings.TrimSuffix(res.stdout, "\n"), "\n") { + res := run("iwinfo", iface, "scan") + for _, line := range strings.Split(strings.TrimSuffix(res.Stdout, "\n"), "\n") { fmt.Println(line) } From 735bc8d19e3812ddebdd445eeae50bef7f458bee Mon Sep 17 00:00:00 2001 From: Philippe Caseiro Date: Thu, 20 Sep 2018 10:59:11 +0200 Subject: [PATCH 03/10] Adding DHCP Client and new Wifi stack --- openwrt/dhcp_client.go | 38 ++++ openwrt/dhcp_client_test.go | 12 ++ openwrt/executor.go | 1 + openwrt/uci.go | 86 ++++----- openwrt/uci_struct.go | 19 -- openwrt/uci_struct_test.go | 11 -- openwrt/uci_test.go | 88 ++++++++- openwrt/wifi.go | 88 +++++++++ openwrt/wifi_cell.go | 78 ++++++-- openwrt/wifi_cell_test.go | 21 ++ openwrt/wifi_test.go | 370 ++++++++++++++++++++++++++++++++++++ 11 files changed, 715 insertions(+), 97 deletions(-) create mode 100644 openwrt/dhcp_client.go create mode 100644 openwrt/dhcp_client_test.go delete mode 100644 openwrt/uci_struct.go delete mode 100644 openwrt/uci_struct_test.go create mode 100644 openwrt/wifi.go create mode 100644 openwrt/wifi_cell_test.go create mode 100644 openwrt/wifi_test.go diff --git a/openwrt/dhcp_client.go b/openwrt/dhcp_client.go new file mode 100644 index 0000000..40c81f3 --- /dev/null +++ b/openwrt/dhcp_client.go @@ -0,0 +1,38 @@ +package openwrt + +// DhcpClient represents a dhcp client ... :) +type DhcpClient struct { + exec Executor + iface string +} + +// NewDhcpClient return an UCI instance to interact with UCI +func NewDhcpClient(netIface string) *DhcpClient { + exec := &localExecutor{} + iface := netIface + return &DhcpClient{exec, iface} +} + +// NewDhcpClientWithExecutor return an UCI instance to interact with UCI +func NewDhcpClientWithExecutor(netIface string, exe Executor) *DhcpClient { + exec := exe + iface := netIface + return &DhcpClient{exec, iface} +} + +// NewDhcpClient return an UCI instance to interact with UCI +//func NewDhcpClient(netIface string, exe Executor) *DhcpClient { +// var exec Executor +// if exe == nil { +// exec = &localExecutor{} +// } else { +// exec = exe +// } +// iface := netIface +// return &DhcpClient{exec, iface} +//} + +// AskForIP runs a dhclient ip request with udhcpc +func (dc *DhcpClient) AskForIP() *CommandResult { + return dc.exec.Run("udhcpc", "-i", dc.iface) +} diff --git a/openwrt/dhcp_client_test.go b/openwrt/dhcp_client_test.go new file mode 100644 index 0000000..b21ca7e --- /dev/null +++ b/openwrt/dhcp_client_test.go @@ -0,0 +1,12 @@ +package openwrt + +import "testing" + +func TestDhcpClientAskForIP(t *testing.T) { + uexec := createMockExecutor("", "", 0) + dhc := NewDhcpClientWithExecutor("wlan1", uexec) + res := dhc.AskForIP() + if res.ReturnCode != 0 { + t.Error("Error in DHCP Client !!") + } +} diff --git a/openwrt/executor.go b/openwrt/executor.go index 2c19fb7..71d3ae7 100644 --- a/openwrt/executor.go +++ b/openwrt/executor.go @@ -7,6 +7,7 @@ import ( "os/exec" ) +// Executor interface to describe command runners signature type Executor interface { Run(command string, params ...string) *CommandResult } diff --git a/openwrt/uci.go b/openwrt/uci.go index d02872f..c5d7429 100644 --- a/openwrt/uci.go +++ b/openwrt/uci.go @@ -1,10 +1,7 @@ package openwrt import ( - "bytes" "fmt" - "log" - "os/exec" "time" ) @@ -13,64 +10,63 @@ type Action struct { *CommandResult } +// UCI "Object" +type UCI struct { + exec Executor +} + +// NewUCI return an UCI instance to interact with UCI +func NewUCI() *UCI { + exec := &localExecutor{} + return &UCI{exec} +} + +// NewUCIWithExecutor returns a UCI Instance an gives you the ability to provide +// a different command executor than the default one. +func NewUCIWithExecutor(exec Executor) *UCI { + return &UCI{exec} +} + // uciRun, private method to run the UCI command -func uciRun(uciAction string, param string) *Action { +func (u *UCI) uciRun(uciAction string, param string) *Action { cmd := "uci" - res := run(cmd, uciAction, param) - return &Action{ - res, - } + res := u.exec.Run(cmd, uciAction, param) + return &Action{res} } -// UciAdd add an entry to UCI configuration, specify the Module and the value -func UciAdd(module string, name string) *Action { - actionRes := uciRun("add", fmt.Sprintf("%s %s", module, name)) - return actionRes +// Add add an entry to UCI configuration, specify the Module and the value +func (u *UCI) Add(module string, name string) *Action { + commandRes := u.exec.Run("uci add", module, name) + return &Action{commandRes} } -// UciDelete delete an entry from UCI configuration specify the entry name -func UciDelete(entry string) *Action { - return uciRun("delete", entry) +// Delete delete an entry from UCI configuration specify the entry name +func (u *UCI) Delete(entry string) *Action { + return u.uciRun("delete", entry) } -// UciSet set a value ton an UCI configuration entry -func UciSet(entry string, value string) *Action { - return uciRun("set", fmt.Sprintf("%s=%s", entry, value)) +// Set set a value ton an UCI configuration entry +func (u *UCI) Set(entry string, value string) *Action { + return u.uciRun("set", fmt.Sprintf("%s=%s", entry, value)) } -// UciCommit the recent actions to UCI -func UciCommit() *Action { - return uciRun("commit", "") +// Commit the recent actions to UCI +func (u *UCI) Commit() *Action { + return u.uciRun("commit", "") } -// UciReload reload uci configuration -func UciReload() *Action { - var out bytes.Buffer - var stderr bytes.Buffer - - exe := exec.Command("reload_config") - exe.Stdout = &out - exe.Stderr = &stderr - - err := exe.Run() - if err != nil { - fmt.Println(fmt.Sprint(err) + ": " + stderr.String()) - log.Fatal(err) - } +// Reload reload uci configuration +func (u *UCI) Reload() *Action { + cmdResult := u.exec.Run("reload_config") time.Sleep(5) - return &Action{ - &CommandResult{ - Stdout: out.String(), - ReturnCode: 0, - }, - } + return &Action{cmdResult} } -// UciAddWireless Create a new Wireless entry in UCI configuration -func UciAddWireless(name string) int { - res := UciAdd("wireless", name) - return res.ReturnCode +// AddWireless Create a new Wireless entry in UCI configuration +func (u *UCI) AddWireless(name string) *Action { + res := u.Add("wireless", name) + return res } diff --git a/openwrt/uci_struct.go b/openwrt/uci_struct.go deleted file mode 100644 index d440ae6..0000000 --- a/openwrt/uci_struct.go +++ /dev/null @@ -1,19 +0,0 @@ -package openwrt - -type UCI struct { - exec Executor -} - -func NewUCI() *UCI { - exec := &localExecutor{} - return &UCI{exec} -} - -func NewUCIWithExecutor(exec Executor) *UCI { - return &UCI{exec} -} - -func (u *UCI) Add(module string, name string) *Action { - commandRes := u.exec.Run("uci add", module, name) - return &Action{commandRes} -} diff --git a/openwrt/uci_struct_test.go b/openwrt/uci_struct_test.go deleted file mode 100644 index af25884..0000000 --- a/openwrt/uci_struct_test.go +++ /dev/null @@ -1,11 +0,0 @@ -package openwrt - -import ( - "testing" -) - -func TestUCIStruct(t *testing.T) { - exec := createMockExecutor("", "", 1) - uci := NewUCIWithExecutor(exec) - uci.Add("wireless", "test") -} diff --git a/openwrt/uci_test.go b/openwrt/uci_test.go index 927884d..36418af 100644 --- a/openwrt/uci_test.go +++ b/openwrt/uci_test.go @@ -1,15 +1,91 @@ package openwrt import ( + "fmt" "testing" ) -func TestUciAdd(t *testing.T) { - - // Return 0 run ! - res := UciAdd("wireless", "test") +func TestUCIAdd(t *testing.T) { + exec := createMockExecutor("", "", 0) + uci := NewUCIWithExecutor(exec) + res := uci.Add("wireless", "test") if res.ReturnCode != 0 { - t.Error(res.Stderr) + t.Error("Bad Return Code !") + } + if res.Stdout != "" { + fmt.Printf("[%s] - ", res.Stdout) + t.Error("Stdout is not empty ...") + } + if res.Stderr != "" { + fmt.Printf("[%s] - ", res.Stdout) + t.Error("Stderr is not empty ...") + } +} + +func TestUCIDelete(t *testing.T) { + exec := createMockExecutor("", "", 0) + uci := NewUCIWithExecutor(exec) + res := uci.Delete("wireless.@wifi-iface[1]") + if res.ReturnCode != 0 { + t.Error("Bad Return Code !") + } + if res.Stdout != "" { + fmt.Printf("[%s] - ", res.Stdout) + t.Error("Stdout is not empty ...") + } + if res.Stderr != "" { + fmt.Printf("[%s] - ", res.Stdout) + t.Error("Stderr is not empty ...") + } +} + +func TestUCISet(t *testing.T) { + exec := createMockExecutor("", "", 0) + uci := NewUCIWithExecutor(exec) + res := uci.Set("wireless.@wifi-iface[1].network", "OrionNetwork") + if res.ReturnCode != 0 { + t.Error("Bad Return Code !") + } + if res.Stdout != "" { + fmt.Printf("[%s] - ", res.Stdout) + t.Error("Stdout is not empty ...") + } + if res.Stderr != "" { + fmt.Printf("[%s] - ", res.Stdout) + t.Error("Stderr is not empty ...") + } +} + +func TestUCICommit(t *testing.T) { + exec := createMockExecutor("", "", 0) + uci := NewUCIWithExecutor(exec) + res := uci.Commit() + if res.ReturnCode != 0 { + t.Error("Bad Return Code !") + } + if res.Stdout != "" { + fmt.Printf("[%s] - ", res.Stdout) + t.Error("Stdout is not empty ...") + } + if res.Stderr != "" { + fmt.Printf("[%s] - ", res.Stdout) + t.Error("Stderr is not empty ...") + } +} + +func TestUCIReload(t *testing.T) { + exec := createMockExecutor("", "", 0) + uci := NewUCIWithExecutor(exec) + res := uci.Reload() + if res.ReturnCode != 0 { + t.Error("Bad Return Code !") + } + if res.Stdout != "" { + fmt.Printf("[%s] - ", res.Stdout) + t.Error("Stdout is not empty ...") + } + if res.Stderr != "" { + fmt.Printf("[%s] - ", res.Stdout) + t.Error("Stderr is not empty ...") } - } diff --git a/openwrt/wifi.go b/openwrt/wifi.go new file mode 100644 index 0000000..97174d7 --- /dev/null +++ b/openwrt/wifi.go @@ -0,0 +1,88 @@ +package openwrt + +import ( + "log" + "strings" + "time" +) + +// Wifi gives access to al OpenWRT Wifi operations +type Wifi struct { + exec Executor + iface string + Cells []*WifiCell +} + +// NewWifi return an UCI instance to interact with UCI +func NewWifi(wIface string) *Wifi { + exec := &localExecutor{} + iface := wIface + return &Wifi{exec, iface, nil} +} + +// NewWifiWithExecutor returns a Wifi Instance an gives you the ability to provide +// a different command executor than the default one. +func NewWifiWithExecutor(exec Executor, wIface string) *Wifi { + return &Wifi{exec, wIface, nil} +} + +// GetWifiCells retrieves all availabe wifi cells for a card ! +func (w *Wifi) GetWifiCells() int { + res := w.exec.Run("iwinfo", w.iface, "scan") + if res.ReturnCode != 0 { + log.Fatal(res.Stderr) + return res.ReturnCode + } + + for res.Stdout == "Scanning not possible" { + time.Sleep(1) + res := w.exec.Run("iwinfo", w.iface, "scan") + if res.ReturnCode != 0 { + log.Fatal(res.Stderr) + return res.ReturnCode + } + } + + new := false + mac := "" + ssid := "" + enc := "" + for _, line := range strings.Split(strings.TrimSuffix(res.Stdout, "\n"), "\n") { + if strings.HasPrefix(line, "Cell") && new == false { + new = true + mac = strings.Split(line, " ")[4] + } + if strings.Contains(line, "ESSID:") { + ssid = strings.Split(line, " ")[1] + ssid = strings.Trim(ssid, "\"") + } + if strings.Contains(line, "Encryption:") { + if strings.Contains(line, "WPA2 PSK") { + enc = "psk" + } else if strings.Contains(line, "none") { + enc = "none" + } else { + enc = "unkn" + } + } + if len(mac) > 0 && len(ssid) > 0 && len(enc) > 0 { + cell := NewWifiCell(ssid, mac, enc) + w.Cells = append(w.Cells, cell) + ssid = "" + mac = "" + enc = "" + new = false + } + } + return 0 +} + +// GetCell retreives an WifiCell by SSID provided in parameter +func (w *Wifi) GetCell(ssid string) *WifiCell { + for _, v := range w.Cells { + if v.Ssid == ssid { + return v + } + } + return nil +} diff --git a/openwrt/wifi_cell.go b/openwrt/wifi_cell.go index a6ac91f..785c1f5 100644 --- a/openwrt/wifi_cell.go +++ b/openwrt/wifi_cell.go @@ -1,31 +1,77 @@ package openwrt -import ( - "fmt" - "strings" -) +import "time" // WifiCell reprensents wifi network Cell type WifiCell struct { - // The SSID - Ssid string - // The cell mac adress - MacAdress string + Ssid string + MacAdress string + Encryption string } // NewWifiCell returns a new WifiCell object -func NewWifiCell(ssid string, mac string) *WifiCell { +func NewWifiCell(ssid string, mac string, encrypt string) *WifiCell { return &WifiCell{ - Ssid: ssid, - MacAdress: mac, + Ssid: ssid, + MacAdress: mac, + Encryption: encrypt, } } -// GetWifiCells retrieves all availabe wifi cells for a card ! -func GetWifiCells(iface string) { - res := run("iwinfo", iface, "scan") - for _, line := range strings.Split(strings.TrimSuffix(res.Stdout, "\n"), "\n") { - fmt.Println(line) +// Connect to wifi Cell +func (cell *WifiCell) Connect(uci *UCI, secret string) *Action { + delRes := uci.Delete("wireless.@wifi-iface[1]") + if delRes.ReturnCode != 0 { + return delRes + } + addRes := uci.AddWireless("wifi-iface") + if addRes.ReturnCode != 0 { + return addRes } + setRes := uci.Set("wireless.@wifi-iface[1].network", "PyxisNetwork") + if setRes.ReturnCode != 0 { + return setRes + } + + setRes = uci.Set("wireless.@wifi-iface[1].ssid", cell.Ssid) + if setRes.ReturnCode != 0 { + return setRes + } + setRes = uci.Set("wireless.@wifi-iface[1].encryption", "psk2") + if setRes.ReturnCode != 0 { + return setRes + } + setRes = uci.Set("wireless.@wifi-iface[1].device", "radio1") + if setRes.ReturnCode != 0 { + return setRes + } + setRes = uci.Set("wireless.@wifi-iface[1].mode", "sta") + if setRes.ReturnCode != 0 { + return setRes + } + setRes = uci.Set("wireless.@wifi-iface[1].bssid", cell.MacAdress) + if setRes.ReturnCode != 0 { + return setRes + } + setRes = uci.Set("wireless.@wifi-iface[1].key", secret) + if setRes.ReturnCode != 0 { + return setRes + } + setRes = uci.Commit() + if setRes.ReturnCode != 0 { + return setRes + } + setRes = uci.Reload() + if setRes.ReturnCode != 0 { + return setRes + } + time.Sleep(20) + return &Action{ + &CommandResult{ + Stdout: "", + Stderr: "", + ReturnCode: 0, + }, + } } diff --git a/openwrt/wifi_cell_test.go b/openwrt/wifi_cell_test.go new file mode 100644 index 0000000..c54da57 --- /dev/null +++ b/openwrt/wifi_cell_test.go @@ -0,0 +1,21 @@ +package openwrt + +import "testing" + +func TestWifiCellConnection(t *testing.T) { + uexec := createMockExecutor("", "", 0) + uci := NewUCIWithExecutor(uexec) + + cellList := `Cell 40 - Address: 68:A3:78:6E:D9:24 + ESSID: "PyxisWifi" + Mode: Master Channel: 3 + Signal: -90 dBm Quality: 20/70 + Encryption: WPA2 PSK (CCMP)` + + exec := createMockExecutor(cellList, "", 0) + wifi := NewWifiWithExecutor(exec, "wlan1") + _ = wifi.GetWifiCells() + + cell := wifi.GetCell("PyxisWifi") + cell.Connect(uci, "secret") +} diff --git a/openwrt/wifi_test.go b/openwrt/wifi_test.go new file mode 100644 index 0000000..f1e32c7 --- /dev/null +++ b/openwrt/wifi_test.go @@ -0,0 +1,370 @@ +package openwrt + +import ( + "fmt" + "testing" +) + +// Test GestWifiCells method with 3 Cells +func TestGetWifiCells(t *testing.T) { + cellList := `Cell 40 - Address: 68:A3:78:6E:D9:24 + ESSID: "PyxisWifi" + Mode: Master Channel: 3 + Signal: -90 dBm Quality: 20/70 + Encryption: none + +Cell 41 - Address: B0:39:56:92:59:E2 + ESSID: "NET17" + Mode: Master Channel: 4 + Signal: -88 dBm Quality: 22/70 + Encryption: WPA2 PSK (CCMP) + +Cell 42 - Address: 0C:F4:D5:16:AA:18 + ESSID: "DIJON-METROPOLE-WIFI" + Mode: Master Channel: 13 + Signal: -90 dBm Quality: 20/70 + Encryption: none` + + exec := createMockExecutor(cellList, "", 0) + wifi := NewWifiWithExecutor(exec, "wlan1") + _ = wifi.GetWifiCells() + if len(wifi.Cells) != 3 { + fmt.Printf("Size of wifi.Cells is %d and not 3 !!!\n", len(wifi.Cells)) + t.Error("Cell list is empty ... This can not append !! Fix your code Dummy !") + } + if g, e := wifi.Cells[0].Ssid, "PyxisWifi"; g != e { + t.Errorf("The first Cell have a bad SSID !\n %s is expected and we have %s", e, g) + } + + if g, e := wifi.Cells[0].MacAdress, "68:A3:78:6E:D9:24"; g != e { + t.Errorf("The first Cell have a bad MAC !\n %s is expected and we have %s", e, g) + } + + if g, e := wifi.Cells[0].Encryption, "none"; g != e { + t.Errorf("The first Cell have a bad Encryption!\n %s is expected and we have %s", e, g) + } + + if g, e := wifi.Cells[1].Encryption, "psk"; g != e { + t.Errorf("The second Cell have a bad Encryption!\n %s is expected and we have %s", e, g) + } + + if g, e := wifi.Cells[2].MacAdress, "0C:F4:D5:16:AA:18"; g != e { + t.Errorf("The last Cell have a bad MAC !\n %s is expected and we have %s", e, g) + } +} + +// Test GestWifiCells method with empty list +func TestGetWifiCellsEmpty(t *testing.T) { + exec := createMockExecutor("", "", 0) + wifi := NewWifiWithExecutor(exec, "wlan1") + _ = wifi.GetWifiCells() + if len(wifi.Cells) != 0 { + fmt.Printf("Size of wifi.Cells is %d and not 0 !!!\n", len(wifi.Cells)) + t.Error("Cell list is empty ... This can not append !! Fix your code Dummy !") + } +} + +// Test GestWifiCells method with 3 Cells +func TestGetWifiCellsLarge(t *testing.T) { + cellList := `Cell 01 - Address: 0C:8D:DB:C4:A0:34 + ESSID: "pfPauvres" + Mode: Master Channel: 11 + Signal: -50 dBm Quality: 60/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 02 - Address: 40:5A:9B:ED:BA:F0 + ESSID: "Cadoles" + Mode: Master Channel: 6 + Signal: -36 dBm Quality: 70/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 03 - Address: A0:04:60:B2:8A:C8 + ESSID: "Cadoles Formations (N)" + Mode: Master Channel: 13 + Signal: -32 dBm Quality: 70/70 + Encryption: WPA2 PSK (CCMP) + +Cell 04 - Address: B0:39:56:D8:38:ED + ESSID: "Frate Dijon EXT" + Mode: Master Channel: 11 + Signal: -57 dBm Quality: 53/70 + Encryption: WPA2 PSK (CCMP) + +Cell 05 - Address: 00:A6:CA:10:DF:00 + ESSID: unknown + Mode: Master Channel: 6 + Signal: -80 dBm Quality: 30/70 + Encryption: WPA2 802.1X (CCMP) + +Cell 06 - Address: AC:84:C9:2F:59:6E + ESSID: "Livebox-596a" + Mode: Master Channel: 1 + Signal: -62 dBm Quality: 48/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 07 - Address: 00:A6:CA:10:DF:01 + ESSID: "EFF-Mobility" + Mode: Master Channel: 6 + Signal: -74 dBm Quality: 36/70 + Encryption: WPA2 PSK (CCMP) + +Cell 08 - Address: A0:1B:29:BE:98:26 + ESSID: "Livebox-9822" + Mode: Master Channel: 6 + Signal: -81 dBm Quality: 29/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 09 - Address: 7C:26:64:66:CC:44 + ESSID: "Livebox-32c8" + Mode: Master Channel: 1 + Signal: -74 dBm Quality: 36/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 10 - Address: 00:A6:CA:10:DF:02 + ESSID: "Keo-HotSpot" + Mode: Master Channel: 6 + Signal: -79 dBm Quality: 31/70 + Encryption: none + +Cell 11 - Address: 7E:26:64:66:CC:44 + ESSID: "orange" + Mode: Master Channel: 1 + Signal: -73 dBm Quality: 37/70 + Encryption: none + +Cell 12 - Address: 3C:52:82:FC:5E:21 + ESSID: "DIRECT-20-HP DeskJet 3630 series" + Mode: Master Channel: 6 + Signal: -78 dBm Quality: 32/70 + Encryption: WPA2 PSK (CCMP) + +Cell 13 - Address: E4:9E:12:8B:EF:73 + ESSID: "Freebox-8BEF72" + Mode: Master Channel: 9 + Signal: -79 dBm Quality: 31/70 + Encryption: WPA2 PSK (CCMP) + +Cell 14 - Address: 40:4A:03:05:D2:68 + ESSID: "ZyXEL" + Mode: Master Channel: 11 + Signal: -71 dBm Quality: 39/70 + Encryption: WPA2 PSK (CCMP) + +Cell 15 - Address: 5C:C3:07:7E:39:D4 + ESSID: "pfP Xa" + Mode: Master Channel: 1 + Signal: -65 dBm Quality: 45/70 + Encryption: WPA2 PSK (CCMP) + +Cell 16 - Address: AC:84:C9:1D:C6:7C + ESSID: "Frate Djon" + Mode: Master Channel: 1 + Signal: -79 dBm Quality: 31/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 17 - Address: 00:17:33:9F:4D:80 + ESSID: "NEUF_4D7C" + Mode: Master Channel: 11 + Signal: -83 dBm Quality: 27/70 + Encryption: WPA PSK (TKIP, CCMP) + +Cell 18 - Address: A2:17:33:9F:4D:81 + ESSID: "SFR WiFi FON" + Mode: Master Channel: 11 + Signal: -85 dBm Quality: 25/70 + Encryption: none + +Cell 19 - Address: BC:F6:85:FE:6D:46 + ESSID: "Dlink" + Mode: Master Channel: 12 + Signal: -70 dBm Quality: 40/70 + Encryption: WPA2 PSK (CCMP) + +Cell 20 - Address: 30:7C:B2:D1:0B:0D + ESSID: "Livebox-0b09" + Mode: Master Channel: 11 + Signal: -81 dBm Quality: 29/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 21 - Address: A2:17:33:9F:4D:83 + ESSID: "SFR WiFi Mobile" + Mode: Master Channel: 11 + Signal: -85 dBm Quality: 25/70 + Encryption: WPA2 802.1X (CCMP) + +Cell 22 - Address: 90:4D:4A:F7:B9:70 + ESSID: "Livebox-B970" + Mode: Master Channel: 11 + Signal: -84 dBm Quality: 26/70 + Encryption: WPA2 PSK (CCMP) + +Cell 23 - Address: 90:4D:4A:F7:B9:71 + ESSID: "orange" + Mode: Master Channel: 11 + Signal: -89 dBm Quality: 21/70 + Encryption: none + +Cell 24 - Address: 00:22:6B:86:5B:71 + ESSID: "linksys" + Mode: Master Channel: 11 + Signal: -86 dBm Quality: 24/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 25 - Address: 68:A3:78:6E:D9:25 + ESSID: "FreeWifi_secure" + Mode: Master Channel: 3 + Signal: -86 dBm Quality: 24/70 + Encryption: WPA2 802.1X (TKIP, CCMP) + +Cell 26 - Address: 6C:38:A1:62:1B:28 + ESSID: "Bbox-1B7889A9" + Mode: Master Channel: 1 + Signal: -90 dBm Quality: 20/70 + Encryption: mixed WPA/WPA2 PSK (CCMP) + +Cell 27 - Address: 78:81:02:5E:B7:14 + ESSID: "Livebox-B714" + Mode: Master Channel: 6 + Signal: -86 dBm Quality: 24/70 + Encryption: WPA2 PSK (CCMP) + +Cell 28 - Address: F4:CA:E5:98:3B:DC + ESSID: "Freebox-5D2400" + Mode: Master Channel: 11 + Signal: -84 dBm Quality: 26/70 + Encryption: WPA PSK (CCMP) + +Cell 29 - Address: 8C:DC:D4:93:69:17 + ESSID: "HP-Print-17-Photosmart 5520" + Mode: Master Channel: 11 + Signal: -87 dBm Quality: 23/70 + Encryption: none + +Cell 30 - Address: 44:CE:7D:20:5C:A4 + ESSID: "SFR_5CA0" + Mode: Master Channel: 6 + Signal: -86 dBm Quality: 24/70 + Encryption: WPA PSK (TKIP, CCMP) + +Cell 31 - Address: F4:CA:E5:98:3B:DE + ESSID: "FreeWifi_secure" + Mode: Master Channel: 11 + Signal: -72 dBm Quality: 38/70 + Encryption: WPA2 802.1X (TKIP, CCMP) + +Cell 32 - Address: 70:0B:01:C0:B3:E0 + ESSID: "Livebox-B3E0" + Mode: Master Channel: 11 + Signal: -80 dBm Quality: 30/70 + Encryption: WPA2 PSK (CCMP) + +Cell 33 - Address: D2:CE:7D:20:5C:A7 + ESSID: "SFR WiFi Mobile" + Mode: Master Channel: 6 + Signal: -85 dBm Quality: 25/70 + Encryption: WPA2 802.1X (CCMP) + +Cell 34 - Address: 68:A3:78:0D:B6:51 + ESSID: "Freebox-0DB650" + Mode: Master Channel: 1 + Signal: -92 dBm Quality: 18/70 + Encryption: WPA2 PSK (CCMP) + +Cell 35 - Address: F8:AB:05:1D:6A:E0 + ESSID: "Bbox-8CE43C68" + Mode: Master Channel: 6 + Signal: -88 dBm Quality: 22/70 + Encryption: mixed WPA/WPA2 PSK (CCMP) + +Cell 36 - Address: F4:CA:E5:98:3B:DD + ESSID: "FreeWifi" + Mode: Master Channel: 11 + Signal: -87 dBm Quality: 23/70 + Encryption: none + +Cell 37 - Address: 14:0C:76:79:C0:D9 + ESSID: "freebox_ZFSFUA" + Mode: Master Channel: 4 + Signal: -88 dBm Quality: 22/70 + Encryption: WPA PSK (TKIP, CCMP) + +Cell 38 - Address: 68:15:90:36:63:60 + ESSID: "Livebox-6360" + Mode: Master Channel: 1 + Signal: -81 dBm Quality: 29/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 39 - Address: 64:7C:34:29:2B:7C + ESSID: "Bbox-D646CB51" + Mode: Master Channel: 1 + Signal: -90 dBm Quality: 20/70 + Encryption: mixed WPA/WPA2 PSK (CCMP) + +Cell 40 - Address: 68:A3:78:6E:D9:24 + ESSID: "FreeWifi" + Mode: Master Channel: 3 + Signal: -90 dBm Quality: 20/70 + Encryption: none + +Cell 41 - Address: B0:39:56:92:59:E2 + ESSID: "NETGEAR17" + Mode: Master Channel: 4 + Signal: -88 dBm Quality: 22/70 + Encryption: WPA2 PSK (CCMP) + +Cell 42 - Address: 0C:F4:D5:16:AA:18 + ESSID: "DIJON-METROPOLE-WIFI" + Mode: Master Channel: 13 + Signal: -90 dBm Quality: 20/70 + Encryption: none + +Cell 43 - Address: D2:CE:7D:20:5C:A5 + ESSID: "SFR WiFi FON" + Mode: Master Channel: 6 + Signal: -81 dBm Quality: 29/70 + Encryption: none + +Cell 44 - Address: 34:27:92:42:CD:72 + ESSID: "Freebox-42CD71" + Mode: Master Channel: 8 + Signal: -88 dBm Quality: 22/70 + Encryption: WPA2 PSK (CCMP) + +Cell 45 - Address: 72:5D:51:78:4C:87 + ESSID: "SFR WiFi FON" + Mode: Master Channel: 11 + Signal: -87 dBm Quality: 23/70 + Encryption: none + +Cell 46 - Address: 68:A3:78:6E:D9:23 + ESSID: "Freebox-6ED922" + Mode: Master Channel: 3 + Signal: -76 dBm Quality: 34/70 + Encryption: WPA2 PSK (CCMP) + +Cell 47 - Address: 00:19:70:4F:DE:F2 + ESSID: "Livebox-45cc" + Mode: Master Channel: 6 + Signal: -78 dBm Quality: 32/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 48 - Address: AC:84:C9:CC:AE:90 + ESSID: "Livebox-AE90" + Mode: Master Channel: 11 + Signal: -81 dBm Quality: 29/70 + Encryption: WPA2 PSK (CCMP) + +Cell 49 - Address: 00:07:7D:89:81:B0 + ESSID: "orange" + Mode: Master Channel: 6 + Signal: -85 dBm Quality: 25/70 + Encryption: none` + + exec := createMockExecutor(cellList, "", 0) + wifi := NewWifiWithExecutor(exec, "wlan1") + _ = wifi.GetWifiCells() + if len(wifi.Cells) != 49 { + fmt.Printf("Size of wifi.Cells is %d and not 49 !!!\n", len(wifi.Cells)) + t.Error("Cell list is empty ... This can not append !! Fix your code Dummy !") + } +} From b680e256b9e41915fbe2092ebc8583ea94caf5dd Mon Sep 17 00:00:00 2001 From: Philippe Caseiro Date: Thu, 20 Sep 2018 16:43:31 +0200 Subject: [PATCH 04/10] Updating executor to remove old util.go Adding new Network interaction "class" --- openwrt/executor.go | 37 +++++++++++++++++--- openwrt/executor_test.go | 18 ++++++++++ openwrt/network.go | 75 ++++++++++++++++++++++++++++++++++++++++ openwrt/network_test.go | 22 ++++++++++++ openwrt/test.go | 6 ++++ openwrt/utils.go | 38 -------------------- 6 files changed, 154 insertions(+), 42 deletions(-) create mode 100644 openwrt/executor_test.go create mode 100644 openwrt/network.go create mode 100644 openwrt/network_test.go delete mode 100644 openwrt/utils.go diff --git a/openwrt/executor.go b/openwrt/executor.go index 71d3ae7..bdd4275 100644 --- a/openwrt/executor.go +++ b/openwrt/executor.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "os/exec" + "syscall" ) // Executor interface to describe command runners signature @@ -12,12 +13,22 @@ type Executor interface { Run(command string, params ...string) *CommandResult } +// CommandResult contain all information about a command execution, stdout, stderr +type CommandResult struct { + Stdout string + Stderr string + ReturnCode int +} + type localExecutor struct{} func (e *localExecutor) Run(command string, params ...string) *CommandResult { var out bytes.Buffer var stderr bytes.Buffer + var exitCode int + + defaultFailedCode := 255 exe := exec.Command(command, params...) exe.Stdout = &out @@ -25,14 +36,32 @@ func (e *localExecutor) Run(command string, params ...string) *CommandResult { err := exe.Run() if err != nil { + if exitError, ok := err.(*exec.ExitError); ok { + ws := exitError.Sys().(syscall.WaitStatus) + exitCode = ws.ExitStatus() + } else { + // This will happen (in OSX) if `name` is not available in $PATH, + // in this situation, exit code could not be get, and stderr will be + // empty string very likely, so we use the default fail code, and format err + // to string and set to stderr + log.Printf("Could not get exit code for failed program: %v, %v", command, params) + exitCode = defaultFailedCode + } fmt.Println(fmt.Sprint(err) + ": " + stderr.String()) log.Fatal(err) } + if err != nil { + // try to get the exit code + } else { + // success, exitCode should be 0 if go is ok + ws := exe.ProcessState.Sys().(syscall.WaitStatus) + exitCode = ws.ExitStatus() + } + return &CommandResult{ - Stdout: out.String(), - Stderr: stderr.String(), - // FIXME - ReturnCode: 0, + Stdout: out.String(), + Stderr: stderr.String(), + ReturnCode: exitCode, } } diff --git a/openwrt/executor_test.go b/openwrt/executor_test.go new file mode 100644 index 0000000..3909188 --- /dev/null +++ b/openwrt/executor_test.go @@ -0,0 +1,18 @@ +package openwrt + +import ( + "testing" +) + +func TestRun(t *testing.T) { + exec := &localExecutor{} + res := exec.Run("uname", "-a") + if g, e := res.ReturnCode, 0; g != e { + t.Errorf("Run command failed ! Got bad return code [%d], [%d} is expected\n", g, e) + } + + // res = exec.Run("noCommandWithThisNameExists", "-a") + // if g, e := res.ReturnCode, 127; g != e { + // t.Errorf("Run command failed ! Got bad return code [%d], [%d} is expected\n", g, e) + // } +} diff --git a/openwrt/network.go b/openwrt/network.go new file mode 100644 index 0000000..6505d46 --- /dev/null +++ b/openwrt/network.go @@ -0,0 +1,75 @@ +package openwrt + +import ( + "fmt" + "io/ioutil" + "net" + "strings" +) + +// Network provides a representation of network +type Network struct { + exec Executor +} + +// NewNetwork return an UCI instance to interact with UCI +func NewNetwork() *Network { + exec := &localExecutor{} + return &Network{exec} +} + +// NewNetworkWithExecutor return an UCI instance to interact with UCI +func NewNetworkWithExecutor(exe Executor) *Network { + exec := exe + return &Network{exec} +} + +// ListInterfaces list all available interfaces on a system using "ip" commmand +func (n *Network) ListInterfaces() []net.Interface { + var result []net.Interface + ifaces, err := net.Interfaces() + if err != nil { + fmt.Print(fmt.Errorf("error listing network interfacess: %+v", err.Error())) + return nil + } + for _, i := range ifaces { + result = append(result, i) + } + return result +} + +// ListWirelessInterfaces list all wifi cards +func (n *Network) ListWirelessInterfaces() []net.Interface { + var result []net.Interface + var ifaceNames []string + + wifiFile := "/proc/net/wireless" + + wifiFileContent, err := ioutil.ReadFile(wifiFile) + check(err) + + index := 0 + for _, line := range strings.Split(string(wifiFileContent), "\n") { + if index < 2 { + index++ + continue + } else { + name := strings.Split(line, ":")[0] + ifaceNames = append(ifaceNames, name) + } + } + + ifaces, err := net.Interfaces() + if err != nil { + fmt.Print(fmt.Errorf("error listing network interfaces : %+v", err.Error())) + return nil + } + for _, i := range ifaces { + for _, name := range ifaceNames { + if name == i.Name { + result = append(result, i) + } + } + } + return result +} diff --git a/openwrt/network_test.go b/openwrt/network_test.go new file mode 100644 index 0000000..89b6f1a --- /dev/null +++ b/openwrt/network_test.go @@ -0,0 +1,22 @@ +package openwrt + +import ( + "fmt" + "testing" +) + +func TestNetworkListInterfaces(t *testing.T) { + net := NewNetwork() + iface := net.ListInterfaces() + for _, ife := range iface { + fmt.Printf("%s\n", ife.Name) + } +} + +func TestListWirelessInterfaces(t *testing.T) { + net := NewNetwork() + res := net.ListWirelessInterfaces() + for _, el := range res { + fmt.Printf("%s\n", el.Name) + } +} diff --git a/openwrt/test.go b/openwrt/test.go index 77b3e3a..5f7ff9a 100644 --- a/openwrt/test.go +++ b/openwrt/test.go @@ -5,6 +5,12 @@ import ( "strings" ) +func check(e error) { + if e != nil { + panic(e) + } +} + func createMockExecutor(stdout string, stderr string, returnCode int) Executor { return &mockExecutor{ stdout: stdout, diff --git a/openwrt/utils.go b/openwrt/utils.go deleted file mode 100644 index 6e0dbed..0000000 --- a/openwrt/utils.go +++ /dev/null @@ -1,38 +0,0 @@ -package openwrt - -import ( - "bytes" - "fmt" - "log" - "os/exec" -) - -// CommandResult contain all information about a command execution, stdout, stderr -type CommandResult struct { - Stdout string - Stderr string - ReturnCode int -} - -// Run executes a system command and returns -func run(command string, params ...string) *CommandResult { - var out bytes.Buffer - var stderr bytes.Buffer - - exe := exec.Command(command, params...) - exe.Stdout = &out - exe.Stderr = &stderr - - err := exe.Run() - if err != nil { - fmt.Println(fmt.Sprint(err) + ": " + stderr.String()) - log.Fatal(err) - } - - return &CommandResult{ - Stdout: out.String(), - Stderr: stderr.String(), - // FIXME - ReturnCode: 0, - } -} From 3f36175f1ab6240f22b27ccffcb0bebb341ec0d7 Mon Sep 17 00:00:00 2001 From: Philippe Caseiro Date: Thu, 20 Sep 2018 17:09:11 +0200 Subject: [PATCH 05/10] Cleaning test data --- openwrt/testdata/wifi_cells_output_3.txt | 17 + openwrt/testdata/wifi_cells_output_large.txt | 293 +++++++++++++++++ openwrt/wifi_cell.go | 2 +- openwrt/wifi_test.go | 321 +------------------ 4 files changed, 322 insertions(+), 311 deletions(-) create mode 100644 openwrt/testdata/wifi_cells_output_3.txt create mode 100644 openwrt/testdata/wifi_cells_output_large.txt diff --git a/openwrt/testdata/wifi_cells_output_3.txt b/openwrt/testdata/wifi_cells_output_3.txt new file mode 100644 index 0000000..cb9b12e --- /dev/null +++ b/openwrt/testdata/wifi_cells_output_3.txt @@ -0,0 +1,17 @@ +Cell 40 - Address: 68:A3:78:6E:D9:24 + ESSID: "PyxisWifi" + Mode: Master Channel: 3 + Signal: -90 dBm Quality: 20/70 + Encryption: none + +Cell 41 - Address: B0:39:56:92:59:E2 + ESSID: "NET17" + Mode: Master Channel: 4 + Signal: -88 dBm Quality: 22/70 + Encryption: WPA2 PSK (CCMP) + +Cell 42 - Address: 0C:F4:D5:16:AA:18 + ESSID: "DIJON-METROPOLE-WIFI" + Mode: Master Channel: 13 + Signal: -90 dBm Quality: 20/70 + Encryption: none \ No newline at end of file diff --git a/openwrt/testdata/wifi_cells_output_large.txt b/openwrt/testdata/wifi_cells_output_large.txt new file mode 100644 index 0000000..e4ee5ed --- /dev/null +++ b/openwrt/testdata/wifi_cells_output_large.txt @@ -0,0 +1,293 @@ +Cell 01 - Address: 0C:8D:DB:C4:A0:34 + ESSID: "pfPauvres" + Mode: Master Channel: 11 + Signal: -50 dBm Quality: 60/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 02 - Address: 40:5A:9B:ED:BA:F0 + ESSID: "Cadoles" + Mode: Master Channel: 6 + Signal: -36 dBm Quality: 70/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 03 - Address: A0:04:60:B2:8A:C8 + ESSID: "Cadoles Formations (N)" + Mode: Master Channel: 13 + Signal: -32 dBm Quality: 70/70 + Encryption: WPA2 PSK (CCMP) + +Cell 04 - Address: B0:39:56:D8:38:ED + ESSID: "Frate Dijon EXT" + Mode: Master Channel: 11 + Signal: -57 dBm Quality: 53/70 + Encryption: WPA2 PSK (CCMP) + +Cell 05 - Address: 00:A6:CA:10:DF:00 + ESSID: unknown + Mode: Master Channel: 6 + Signal: -80 dBm Quality: 30/70 + Encryption: WPA2 802.1X (CCMP) + +Cell 06 - Address: AC:84:C9:2F:59:6E + ESSID: "Livebox-596a" + Mode: Master Channel: 1 + Signal: -62 dBm Quality: 48/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 07 - Address: 00:A6:CA:10:DF:01 + ESSID: "EFF-Mobility" + Mode: Master Channel: 6 + Signal: -74 dBm Quality: 36/70 + Encryption: WPA2 PSK (CCMP) + +Cell 08 - Address: A0:1B:29:BE:98:26 + ESSID: "Livebox-9822" + Mode: Master Channel: 6 + Signal: -81 dBm Quality: 29/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 09 - Address: 7C:26:64:66:CC:44 + ESSID: "Livebox-32c8" + Mode: Master Channel: 1 + Signal: -74 dBm Quality: 36/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 10 - Address: 00:A6:CA:10:DF:02 + ESSID: "Keo-HotSpot" + Mode: Master Channel: 6 + Signal: -79 dBm Quality: 31/70 + Encryption: none + +Cell 11 - Address: 7E:26:64:66:CC:44 + ESSID: "orange" + Mode: Master Channel: 1 + Signal: -73 dBm Quality: 37/70 + Encryption: none + +Cell 12 - Address: 3C:52:82:FC:5E:21 + ESSID: "DIRECT-20-HP DeskJet 3630 series" + Mode: Master Channel: 6 + Signal: -78 dBm Quality: 32/70 + Encryption: WPA2 PSK (CCMP) + +Cell 13 - Address: E4:9E:12:8B:EF:73 + ESSID: "Freebox-8BEF72" + Mode: Master Channel: 9 + Signal: -79 dBm Quality: 31/70 + Encryption: WPA2 PSK (CCMP) + +Cell 14 - Address: 40:4A:03:05:D2:68 + ESSID: "ZyXEL" + Mode: Master Channel: 11 + Signal: -71 dBm Quality: 39/70 + Encryption: WPA2 PSK (CCMP) + +Cell 15 - Address: 5C:C3:07:7E:39:D4 + ESSID: "pfP Xa" + Mode: Master Channel: 1 + Signal: -65 dBm Quality: 45/70 + Encryption: WPA2 PSK (CCMP) + +Cell 16 - Address: AC:84:C9:1D:C6:7C + ESSID: "Frate Djon" + Mode: Master Channel: 1 + Signal: -79 dBm Quality: 31/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 17 - Address: 00:17:33:9F:4D:80 + ESSID: "NEUF_4D7C" + Mode: Master Channel: 11 + Signal: -83 dBm Quality: 27/70 + Encryption: WPA PSK (TKIP, CCMP) + +Cell 18 - Address: A2:17:33:9F:4D:81 + ESSID: "SFR WiFi FON" + Mode: Master Channel: 11 + Signal: -85 dBm Quality: 25/70 + Encryption: none + +Cell 19 - Address: BC:F6:85:FE:6D:46 + ESSID: "Dlink" + Mode: Master Channel: 12 + Signal: -70 dBm Quality: 40/70 + Encryption: WPA2 PSK (CCMP) + +Cell 20 - Address: 30:7C:B2:D1:0B:0D + ESSID: "Livebox-0b09" + Mode: Master Channel: 11 + Signal: -81 dBm Quality: 29/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 21 - Address: A2:17:33:9F:4D:83 + ESSID: "SFR WiFi Mobile" + Mode: Master Channel: 11 + Signal: -85 dBm Quality: 25/70 + Encryption: WPA2 802.1X (CCMP) + +Cell 22 - Address: 90:4D:4A:F7:B9:70 + ESSID: "Livebox-B970" + Mode: Master Channel: 11 + Signal: -84 dBm Quality: 26/70 + Encryption: WPA2 PSK (CCMP) + +Cell 23 - Address: 90:4D:4A:F7:B9:71 + ESSID: "orange" + Mode: Master Channel: 11 + Signal: -89 dBm Quality: 21/70 + Encryption: none + +Cell 24 - Address: 00:22:6B:86:5B:71 + ESSID: "linksys" + Mode: Master Channel: 11 + Signal: -86 dBm Quality: 24/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 25 - Address: 68:A3:78:6E:D9:25 + ESSID: "FreeWifi_secure" + Mode: Master Channel: 3 + Signal: -86 dBm Quality: 24/70 + Encryption: WPA2 802.1X (TKIP, CCMP) + +Cell 26 - Address: 6C:38:A1:62:1B:28 + ESSID: "Bbox-1B7889A9" + Mode: Master Channel: 1 + Signal: -90 dBm Quality: 20/70 + Encryption: mixed WPA/WPA2 PSK (CCMP) + +Cell 27 - Address: 78:81:02:5E:B7:14 + ESSID: "Livebox-B714" + Mode: Master Channel: 6 + Signal: -86 dBm Quality: 24/70 + Encryption: WPA2 PSK (CCMP) + +Cell 28 - Address: F4:CA:E5:98:3B:DC + ESSID: "Freebox-5D2400" + Mode: Master Channel: 11 + Signal: -84 dBm Quality: 26/70 + Encryption: WPA PSK (CCMP) + +Cell 29 - Address: 8C:DC:D4:93:69:17 + ESSID: "HP-Print-17-Photosmart 5520" + Mode: Master Channel: 11 + Signal: -87 dBm Quality: 23/70 + Encryption: none + +Cell 30 - Address: 44:CE:7D:20:5C:A4 + ESSID: "SFR_5CA0" + Mode: Master Channel: 6 + Signal: -86 dBm Quality: 24/70 + Encryption: WPA PSK (TKIP, CCMP) + +Cell 31 - Address: F4:CA:E5:98:3B:DE + ESSID: "FreeWifi_secure" + Mode: Master Channel: 11 + Signal: -72 dBm Quality: 38/70 + Encryption: WPA2 802.1X (TKIP, CCMP) + +Cell 32 - Address: 70:0B:01:C0:B3:E0 + ESSID: "Livebox-B3E0" + Mode: Master Channel: 11 + Signal: -80 dBm Quality: 30/70 + Encryption: WPA2 PSK (CCMP) + +Cell 33 - Address: D2:CE:7D:20:5C:A7 + ESSID: "SFR WiFi Mobile" + Mode: Master Channel: 6 + Signal: -85 dBm Quality: 25/70 + Encryption: WPA2 802.1X (CCMP) + +Cell 34 - Address: 68:A3:78:0D:B6:51 + ESSID: "Freebox-0DB650" + Mode: Master Channel: 1 + Signal: -92 dBm Quality: 18/70 + Encryption: WPA2 PSK (CCMP) + +Cell 35 - Address: F8:AB:05:1D:6A:E0 + ESSID: "Bbox-8CE43C68" + Mode: Master Channel: 6 + Signal: -88 dBm Quality: 22/70 + Encryption: mixed WPA/WPA2 PSK (CCMP) + +Cell 36 - Address: F4:CA:E5:98:3B:DD + ESSID: "FreeWifi" + Mode: Master Channel: 11 + Signal: -87 dBm Quality: 23/70 + Encryption: none + +Cell 37 - Address: 14:0C:76:79:C0:D9 + ESSID: "freebox_ZFSFUA" + Mode: Master Channel: 4 + Signal: -88 dBm Quality: 22/70 + Encryption: WPA PSK (TKIP, CCMP) + +Cell 38 - Address: 68:15:90:36:63:60 + ESSID: "Livebox-6360" + Mode: Master Channel: 1 + Signal: -81 dBm Quality: 29/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 39 - Address: 64:7C:34:29:2B:7C + ESSID: "Bbox-D646CB51" + Mode: Master Channel: 1 + Signal: -90 dBm Quality: 20/70 + Encryption: mixed WPA/WPA2 PSK (CCMP) + +Cell 40 - Address: 68:A3:78:6E:D9:24 + ESSID: "FreeWifi" + Mode: Master Channel: 3 + Signal: -90 dBm Quality: 20/70 + Encryption: none + +Cell 41 - Address: B0:39:56:92:59:E2 + ESSID: "NETGEAR17" + Mode: Master Channel: 4 + Signal: -88 dBm Quality: 22/70 + Encryption: WPA2 PSK (CCMP) + +Cell 42 - Address: 0C:F4:D5:16:AA:18 + ESSID: "DIJON-METROPOLE-WIFI" + Mode: Master Channel: 13 + Signal: -90 dBm Quality: 20/70 + Encryption: none + +Cell 43 - Address: D2:CE:7D:20:5C:A5 + ESSID: "SFR WiFi FON" + Mode: Master Channel: 6 + Signal: -81 dBm Quality: 29/70 + Encryption: none + +Cell 44 - Address: 34:27:92:42:CD:72 + ESSID: "Freebox-42CD71" + Mode: Master Channel: 8 + Signal: -88 dBm Quality: 22/70 + Encryption: WPA2 PSK (CCMP) + +Cell 45 - Address: 72:5D:51:78:4C:87 + ESSID: "SFR WiFi FON" + Mode: Master Channel: 11 + Signal: -87 dBm Quality: 23/70 + Encryption: none + +Cell 46 - Address: 68:A3:78:6E:D9:23 + ESSID: "Freebox-6ED922" + Mode: Master Channel: 3 + Signal: -76 dBm Quality: 34/70 + Encryption: WPA2 PSK (CCMP) + +Cell 47 - Address: 00:19:70:4F:DE:F2 + ESSID: "Livebox-45cc" + Mode: Master Channel: 6 + Signal: -78 dBm Quality: 32/70 + Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + +Cell 48 - Address: AC:84:C9:CC:AE:90 + ESSID: "Livebox-AE90" + Mode: Master Channel: 11 + Signal: -81 dBm Quality: 29/70 + Encryption: WPA2 PSK (CCMP) + +Cell 49 - Address: 00:07:7D:89:81:B0 + ESSID: "orange" + Mode: Master Channel: 6 + Signal: -85 dBm Quality: 25/70 + Encryption: none \ No newline at end of file diff --git a/openwrt/wifi_cell.go b/openwrt/wifi_cell.go index 785c1f5..ccdfdc3 100644 --- a/openwrt/wifi_cell.go +++ b/openwrt/wifi_cell.go @@ -38,7 +38,7 @@ func (cell *WifiCell) Connect(uci *UCI, secret string) *Action { if setRes.ReturnCode != 0 { return setRes } - setRes = uci.Set("wireless.@wifi-iface[1].encryption", "psk2") + setRes = uci.Set("wireless.@wifi-iface[1].encryption", cell.Encryption) if setRes.ReturnCode != 0 { return setRes } diff --git a/openwrt/wifi_test.go b/openwrt/wifi_test.go index f1e32c7..a168c7f 100644 --- a/openwrt/wifi_test.go +++ b/openwrt/wifi_test.go @@ -2,30 +2,19 @@ package openwrt import ( "fmt" + "io/ioutil" "testing" ) // Test GestWifiCells method with 3 Cells func TestGetWifiCells(t *testing.T) { - cellList := `Cell 40 - Address: 68:A3:78:6E:D9:24 - ESSID: "PyxisWifi" - Mode: Master Channel: 3 - Signal: -90 dBm Quality: 20/70 - Encryption: none -Cell 41 - Address: B0:39:56:92:59:E2 - ESSID: "NET17" - Mode: Master Channel: 4 - Signal: -88 dBm Quality: 22/70 - Encryption: WPA2 PSK (CCMP) + cellList, err := ioutil.ReadFile("testdata/wifi_cells_output_3.txt") + if err != nil { + t.Fatal(err) + } -Cell 42 - Address: 0C:F4:D5:16:AA:18 - ESSID: "DIJON-METROPOLE-WIFI" - Mode: Master Channel: 13 - Signal: -90 dBm Quality: 20/70 - Encryption: none` - - exec := createMockExecutor(cellList, "", 0) + exec := createMockExecutor(string(cellList), "", 0) wifi := NewWifiWithExecutor(exec, "wlan1") _ = wifi.GetWifiCells() if len(wifi.Cells) != 3 { @@ -66,301 +55,13 @@ func TestGetWifiCellsEmpty(t *testing.T) { // Test GestWifiCells method with 3 Cells func TestGetWifiCellsLarge(t *testing.T) { - cellList := `Cell 01 - Address: 0C:8D:DB:C4:A0:34 - ESSID: "pfPauvres" - Mode: Master Channel: 11 - Signal: -50 dBm Quality: 60/70 - Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) -Cell 02 - Address: 40:5A:9B:ED:BA:F0 - ESSID: "Cadoles" - Mode: Master Channel: 6 - Signal: -36 dBm Quality: 70/70 - Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) + cellList, err := ioutil.ReadFile("testdata/wifi_cells_output_large.txt") + if err != nil { + t.Fatal(err) + } -Cell 03 - Address: A0:04:60:B2:8A:C8 - ESSID: "Cadoles Formations (N)" - Mode: Master Channel: 13 - Signal: -32 dBm Quality: 70/70 - Encryption: WPA2 PSK (CCMP) - -Cell 04 - Address: B0:39:56:D8:38:ED - ESSID: "Frate Dijon EXT" - Mode: Master Channel: 11 - Signal: -57 dBm Quality: 53/70 - Encryption: WPA2 PSK (CCMP) - -Cell 05 - Address: 00:A6:CA:10:DF:00 - ESSID: unknown - Mode: Master Channel: 6 - Signal: -80 dBm Quality: 30/70 - Encryption: WPA2 802.1X (CCMP) - -Cell 06 - Address: AC:84:C9:2F:59:6E - ESSID: "Livebox-596a" - Mode: Master Channel: 1 - Signal: -62 dBm Quality: 48/70 - Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) - -Cell 07 - Address: 00:A6:CA:10:DF:01 - ESSID: "EFF-Mobility" - Mode: Master Channel: 6 - Signal: -74 dBm Quality: 36/70 - Encryption: WPA2 PSK (CCMP) - -Cell 08 - Address: A0:1B:29:BE:98:26 - ESSID: "Livebox-9822" - Mode: Master Channel: 6 - Signal: -81 dBm Quality: 29/70 - Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) - -Cell 09 - Address: 7C:26:64:66:CC:44 - ESSID: "Livebox-32c8" - Mode: Master Channel: 1 - Signal: -74 dBm Quality: 36/70 - Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) - -Cell 10 - Address: 00:A6:CA:10:DF:02 - ESSID: "Keo-HotSpot" - Mode: Master Channel: 6 - Signal: -79 dBm Quality: 31/70 - Encryption: none - -Cell 11 - Address: 7E:26:64:66:CC:44 - ESSID: "orange" - Mode: Master Channel: 1 - Signal: -73 dBm Quality: 37/70 - Encryption: none - -Cell 12 - Address: 3C:52:82:FC:5E:21 - ESSID: "DIRECT-20-HP DeskJet 3630 series" - Mode: Master Channel: 6 - Signal: -78 dBm Quality: 32/70 - Encryption: WPA2 PSK (CCMP) - -Cell 13 - Address: E4:9E:12:8B:EF:73 - ESSID: "Freebox-8BEF72" - Mode: Master Channel: 9 - Signal: -79 dBm Quality: 31/70 - Encryption: WPA2 PSK (CCMP) - -Cell 14 - Address: 40:4A:03:05:D2:68 - ESSID: "ZyXEL" - Mode: Master Channel: 11 - Signal: -71 dBm Quality: 39/70 - Encryption: WPA2 PSK (CCMP) - -Cell 15 - Address: 5C:C3:07:7E:39:D4 - ESSID: "pfP Xa" - Mode: Master Channel: 1 - Signal: -65 dBm Quality: 45/70 - Encryption: WPA2 PSK (CCMP) - -Cell 16 - Address: AC:84:C9:1D:C6:7C - ESSID: "Frate Djon" - Mode: Master Channel: 1 - Signal: -79 dBm Quality: 31/70 - Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) - -Cell 17 - Address: 00:17:33:9F:4D:80 - ESSID: "NEUF_4D7C" - Mode: Master Channel: 11 - Signal: -83 dBm Quality: 27/70 - Encryption: WPA PSK (TKIP, CCMP) - -Cell 18 - Address: A2:17:33:9F:4D:81 - ESSID: "SFR WiFi FON" - Mode: Master Channel: 11 - Signal: -85 dBm Quality: 25/70 - Encryption: none - -Cell 19 - Address: BC:F6:85:FE:6D:46 - ESSID: "Dlink" - Mode: Master Channel: 12 - Signal: -70 dBm Quality: 40/70 - Encryption: WPA2 PSK (CCMP) - -Cell 20 - Address: 30:7C:B2:D1:0B:0D - ESSID: "Livebox-0b09" - Mode: Master Channel: 11 - Signal: -81 dBm Quality: 29/70 - Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) - -Cell 21 - Address: A2:17:33:9F:4D:83 - ESSID: "SFR WiFi Mobile" - Mode: Master Channel: 11 - Signal: -85 dBm Quality: 25/70 - Encryption: WPA2 802.1X (CCMP) - -Cell 22 - Address: 90:4D:4A:F7:B9:70 - ESSID: "Livebox-B970" - Mode: Master Channel: 11 - Signal: -84 dBm Quality: 26/70 - Encryption: WPA2 PSK (CCMP) - -Cell 23 - Address: 90:4D:4A:F7:B9:71 - ESSID: "orange" - Mode: Master Channel: 11 - Signal: -89 dBm Quality: 21/70 - Encryption: none - -Cell 24 - Address: 00:22:6B:86:5B:71 - ESSID: "linksys" - Mode: Master Channel: 11 - Signal: -86 dBm Quality: 24/70 - Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) - -Cell 25 - Address: 68:A3:78:6E:D9:25 - ESSID: "FreeWifi_secure" - Mode: Master Channel: 3 - Signal: -86 dBm Quality: 24/70 - Encryption: WPA2 802.1X (TKIP, CCMP) - -Cell 26 - Address: 6C:38:A1:62:1B:28 - ESSID: "Bbox-1B7889A9" - Mode: Master Channel: 1 - Signal: -90 dBm Quality: 20/70 - Encryption: mixed WPA/WPA2 PSK (CCMP) - -Cell 27 - Address: 78:81:02:5E:B7:14 - ESSID: "Livebox-B714" - Mode: Master Channel: 6 - Signal: -86 dBm Quality: 24/70 - Encryption: WPA2 PSK (CCMP) - -Cell 28 - Address: F4:CA:E5:98:3B:DC - ESSID: "Freebox-5D2400" - Mode: Master Channel: 11 - Signal: -84 dBm Quality: 26/70 - Encryption: WPA PSK (CCMP) - -Cell 29 - Address: 8C:DC:D4:93:69:17 - ESSID: "HP-Print-17-Photosmart 5520" - Mode: Master Channel: 11 - Signal: -87 dBm Quality: 23/70 - Encryption: none - -Cell 30 - Address: 44:CE:7D:20:5C:A4 - ESSID: "SFR_5CA0" - Mode: Master Channel: 6 - Signal: -86 dBm Quality: 24/70 - Encryption: WPA PSK (TKIP, CCMP) - -Cell 31 - Address: F4:CA:E5:98:3B:DE - ESSID: "FreeWifi_secure" - Mode: Master Channel: 11 - Signal: -72 dBm Quality: 38/70 - Encryption: WPA2 802.1X (TKIP, CCMP) - -Cell 32 - Address: 70:0B:01:C0:B3:E0 - ESSID: "Livebox-B3E0" - Mode: Master Channel: 11 - Signal: -80 dBm Quality: 30/70 - Encryption: WPA2 PSK (CCMP) - -Cell 33 - Address: D2:CE:7D:20:5C:A7 - ESSID: "SFR WiFi Mobile" - Mode: Master Channel: 6 - Signal: -85 dBm Quality: 25/70 - Encryption: WPA2 802.1X (CCMP) - -Cell 34 - Address: 68:A3:78:0D:B6:51 - ESSID: "Freebox-0DB650" - Mode: Master Channel: 1 - Signal: -92 dBm Quality: 18/70 - Encryption: WPA2 PSK (CCMP) - -Cell 35 - Address: F8:AB:05:1D:6A:E0 - ESSID: "Bbox-8CE43C68" - Mode: Master Channel: 6 - Signal: -88 dBm Quality: 22/70 - Encryption: mixed WPA/WPA2 PSK (CCMP) - -Cell 36 - Address: F4:CA:E5:98:3B:DD - ESSID: "FreeWifi" - Mode: Master Channel: 11 - Signal: -87 dBm Quality: 23/70 - Encryption: none - -Cell 37 - Address: 14:0C:76:79:C0:D9 - ESSID: "freebox_ZFSFUA" - Mode: Master Channel: 4 - Signal: -88 dBm Quality: 22/70 - Encryption: WPA PSK (TKIP, CCMP) - -Cell 38 - Address: 68:15:90:36:63:60 - ESSID: "Livebox-6360" - Mode: Master Channel: 1 - Signal: -81 dBm Quality: 29/70 - Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) - -Cell 39 - Address: 64:7C:34:29:2B:7C - ESSID: "Bbox-D646CB51" - Mode: Master Channel: 1 - Signal: -90 dBm Quality: 20/70 - Encryption: mixed WPA/WPA2 PSK (CCMP) - -Cell 40 - Address: 68:A3:78:6E:D9:24 - ESSID: "FreeWifi" - Mode: Master Channel: 3 - Signal: -90 dBm Quality: 20/70 - Encryption: none - -Cell 41 - Address: B0:39:56:92:59:E2 - ESSID: "NETGEAR17" - Mode: Master Channel: 4 - Signal: -88 dBm Quality: 22/70 - Encryption: WPA2 PSK (CCMP) - -Cell 42 - Address: 0C:F4:D5:16:AA:18 - ESSID: "DIJON-METROPOLE-WIFI" - Mode: Master Channel: 13 - Signal: -90 dBm Quality: 20/70 - Encryption: none - -Cell 43 - Address: D2:CE:7D:20:5C:A5 - ESSID: "SFR WiFi FON" - Mode: Master Channel: 6 - Signal: -81 dBm Quality: 29/70 - Encryption: none - -Cell 44 - Address: 34:27:92:42:CD:72 - ESSID: "Freebox-42CD71" - Mode: Master Channel: 8 - Signal: -88 dBm Quality: 22/70 - Encryption: WPA2 PSK (CCMP) - -Cell 45 - Address: 72:5D:51:78:4C:87 - ESSID: "SFR WiFi FON" - Mode: Master Channel: 11 - Signal: -87 dBm Quality: 23/70 - Encryption: none - -Cell 46 - Address: 68:A3:78:6E:D9:23 - ESSID: "Freebox-6ED922" - Mode: Master Channel: 3 - Signal: -76 dBm Quality: 34/70 - Encryption: WPA2 PSK (CCMP) - -Cell 47 - Address: 00:19:70:4F:DE:F2 - ESSID: "Livebox-45cc" - Mode: Master Channel: 6 - Signal: -78 dBm Quality: 32/70 - Encryption: mixed WPA/WPA2 PSK (TKIP, CCMP) - -Cell 48 - Address: AC:84:C9:CC:AE:90 - ESSID: "Livebox-AE90" - Mode: Master Channel: 11 - Signal: -81 dBm Quality: 29/70 - Encryption: WPA2 PSK (CCMP) - -Cell 49 - Address: 00:07:7D:89:81:B0 - ESSID: "orange" - Mode: Master Channel: 6 - Signal: -85 dBm Quality: 25/70 - Encryption: none` - - exec := createMockExecutor(cellList, "", 0) + exec := createMockExecutor(string(cellList), "", 0) wifi := NewWifiWithExecutor(exec, "wlan1") _ = wifi.GetWifiCells() if len(wifi.Cells) != 49 { From de0255fd03e6d6865dcd5b3ac04a0a1ed414dafd Mon Sep 17 00:00:00 2001 From: Philippe Caseiro Date: Thu, 20 Sep 2018 17:11:21 +0200 Subject: [PATCH 06/10] Cleaning lint issue : openwrt/wifi.go:39::warning: declaration of res shadows declaration at openwrt/wifi.go:31 (vetshadow) --- openwrt/wifi.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openwrt/wifi.go b/openwrt/wifi.go index 97174d7..9507b9f 100644 --- a/openwrt/wifi.go +++ b/openwrt/wifi.go @@ -36,7 +36,7 @@ func (w *Wifi) GetWifiCells() int { for res.Stdout == "Scanning not possible" { time.Sleep(1) - res := w.exec.Run("iwinfo", w.iface, "scan") + res = w.exec.Run("iwinfo", w.iface, "scan") if res.ReturnCode != 0 { log.Fatal(res.Stderr) return res.ReturnCode From ec26c74ae895b08b6013c8981eb7d9cd16e9afd5 Mon Sep 17 00:00:00 2001 From: Philippe Caseiro Date: Thu, 20 Sep 2018 17:34:34 +0200 Subject: [PATCH 07/10] Spliting "complex" methods to please go linter ! --- openwrt/network.go | 4 +--- openwrt/uci.go | 2 +- openwrt/wifi.go | 39 ++++++++++++++++-------------- openwrt/wifi_cell.go | 56 ++++++++++++++++++++++++++++---------------- 4 files changed, 59 insertions(+), 42 deletions(-) diff --git a/openwrt/network.go b/openwrt/network.go index 6505d46..2384829 100644 --- a/openwrt/network.go +++ b/openwrt/network.go @@ -32,9 +32,7 @@ func (n *Network) ListInterfaces() []net.Interface { fmt.Print(fmt.Errorf("error listing network interfacess: %+v", err.Error())) return nil } - for _, i := range ifaces { - result = append(result, i) - } + result = append(result, ifaces...) return result } diff --git a/openwrt/uci.go b/openwrt/uci.go index c5d7429..0613643 100644 --- a/openwrt/uci.go +++ b/openwrt/uci.go @@ -60,7 +60,7 @@ func (u *UCI) Commit() *Action { func (u *UCI) Reload() *Action { cmdResult := u.exec.Run("reload_config") - time.Sleep(5) + time.Sleep(5 * time.Second) return &Action{cmdResult} } diff --git a/openwrt/wifi.go b/openwrt/wifi.go index 9507b9f..d13f5d7 100644 --- a/openwrt/wifi.go +++ b/openwrt/wifi.go @@ -26,28 +26,12 @@ func NewWifiWithExecutor(exec Executor, wIface string) *Wifi { return &Wifi{exec, wIface, nil} } -// GetWifiCells retrieves all availabe wifi cells for a card ! -func (w *Wifi) GetWifiCells() int { - res := w.exec.Run("iwinfo", w.iface, "scan") - if res.ReturnCode != 0 { - log.Fatal(res.Stderr) - return res.ReturnCode - } - - for res.Stdout == "Scanning not possible" { - time.Sleep(1) - res = w.exec.Run("iwinfo", w.iface, "scan") - if res.ReturnCode != 0 { - log.Fatal(res.Stderr) - return res.ReturnCode - } - } - +func (w *Wifi) parseWifiCells(stdout string) int { new := false mac := "" ssid := "" enc := "" - for _, line := range strings.Split(strings.TrimSuffix(res.Stdout, "\n"), "\n") { + for _, line := range strings.Split(strings.TrimSuffix(stdout, "\n"), "\n") { if strings.HasPrefix(line, "Cell") && new == false { new = true mac = strings.Split(line, " ")[4] @@ -77,6 +61,25 @@ func (w *Wifi) GetWifiCells() int { return 0 } +// GetWifiCells retrieves all availabe wifi cells for a card ! +func (w *Wifi) GetWifiCells() int { + res := w.exec.Run("iwinfo", w.iface, "scan") + if res.ReturnCode != 0 { + log.Fatal(res.Stderr) + return res.ReturnCode + } + + for res.Stdout == "Scanning not possible" { + time.Sleep(time.Second) + res = w.exec.Run("iwinfo", w.iface, "scan") + if res.ReturnCode != 0 { + log.Fatal(res.Stderr) + return res.ReturnCode + } + } + return w.parseWifiCells(res.Stdout) +} + // GetCell retreives an WifiCell by SSID provided in parameter func (w *Wifi) GetCell(ssid string) *WifiCell { for _, v := range w.Cells { diff --git a/openwrt/wifi_cell.go b/openwrt/wifi_cell.go index ccdfdc3..3ce823e 100644 --- a/openwrt/wifi_cell.go +++ b/openwrt/wifi_cell.go @@ -18,17 +18,7 @@ func NewWifiCell(ssid string, mac string, encrypt string) *WifiCell { } } -// Connect to wifi Cell -func (cell *WifiCell) Connect(uci *UCI, secret string) *Action { - delRes := uci.Delete("wireless.@wifi-iface[1]") - if delRes.ReturnCode != 0 { - return delRes - } - addRes := uci.AddWireless("wifi-iface") - if addRes.ReturnCode != 0 { - return addRes - } - +func (cell *WifiCell) uciWifiConfigure(uci *UCI, secret string) *Action { setRes := uci.Set("wireless.@wifi-iface[1].network", "PyxisNetwork") if setRes.ReturnCode != 0 { return setRes @@ -58,15 +48,41 @@ func (cell *WifiCell) Connect(uci *UCI, secret string) *Action { if setRes.ReturnCode != 0 { return setRes } - setRes = uci.Commit() - if setRes.ReturnCode != 0 { - return setRes - } - setRes = uci.Reload() - if setRes.ReturnCode != 0 { - return setRes - } - time.Sleep(20) + + return &Action{ + &CommandResult{ + Stdout: "", + Stderr: "", + ReturnCode: 0, + }, + } +} + +// Connect to wifi Cell +func (cell *WifiCell) Connect(uci *UCI, secret string) *Action { + delRes := uci.Delete("wireless.@wifi-iface[1]") + if delRes.ReturnCode != 0 { + return delRes + } + addRes := uci.AddWireless("wifi-iface") + if addRes.ReturnCode != 0 { + return addRes + } + + setRes := cell.uciWifiConfigure(uci, secret) + if setRes.ReturnCode != 0 { + return setRes + } + + setRes = uci.Commit() + if setRes.ReturnCode != 0 { + return setRes + } + setRes = uci.Reload() + if setRes.ReturnCode != 0 { + return setRes + } + time.Sleep(20 * time.Second) return &Action{ &CommandResult{ Stdout: "", From 1dbb62c490ec727fe686b42d1a4649126a937af2 Mon Sep 17 00:00:00 2001 From: William Petit Date: Fri, 21 Sep 2018 14:33:17 +0200 Subject: [PATCH 08/10] Add /proc/net/wireless sample --- openwrt/testdata/proc_net_wireless.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 openwrt/testdata/proc_net_wireless.txt diff --git a/openwrt/testdata/proc_net_wireless.txt b/openwrt/testdata/proc_net_wireless.txt new file mode 100644 index 0000000..5fc603c --- /dev/null +++ b/openwrt/testdata/proc_net_wireless.txt @@ -0,0 +1,4 @@ +Inter-| sta-| Quality | Discarded packets | Missed | WE + face | tus | link level noise | nwid crypt frag retry misc | beacon | 22 + wlan1: 0000 0 0 0 0 0 0 0 0 0 + wlan0: 0000 0 0 0 0 0 0 0 0 0 From b34ccd3dee589e4720b2b9a537b8b75195e31702 Mon Sep 17 00:00:00 2001 From: Philippe Caseiro Date: Fri, 21 Sep 2018 14:36:06 +0200 Subject: [PATCH 09/10] Improving network_test.go ... This way we don't need a real wifi card --- openwrt/network.go | 8 ++++++-- openwrt/network_test.go | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/openwrt/network.go b/openwrt/network.go index 2384829..6ba5d47 100644 --- a/openwrt/network.go +++ b/openwrt/network.go @@ -37,11 +37,15 @@ func (n *Network) ListInterfaces() []net.Interface { } // ListWirelessInterfaces list all wifi cards -func (n *Network) ListWirelessInterfaces() []net.Interface { +// you need to provide the wireless file or "" to use +// Linux default one "/proc/net/wireless" +func (n *Network) ListWirelessInterfaces(wifiFile string) []net.Interface { var result []net.Interface var ifaceNames []string - wifiFile := "/proc/net/wireless" + if wifiFile == "" { + wifiFile = "/proc/net/wireless" + } wifiFileContent, err := ioutil.ReadFile(wifiFile) check(err) diff --git a/openwrt/network_test.go b/openwrt/network_test.go index 89b6f1a..bac8574 100644 --- a/openwrt/network_test.go +++ b/openwrt/network_test.go @@ -15,7 +15,7 @@ func TestNetworkListInterfaces(t *testing.T) { func TestListWirelessInterfaces(t *testing.T) { net := NewNetwork() - res := net.ListWirelessInterfaces() + res := net.ListWirelessInterfaces("./testdata/proc_net_wireless.txt") for _, el := range res { fmt.Printf("%s\n", el.Name) } From 17487dd7a6f4fe2121df40633727ded975b9bbe5 Mon Sep 17 00:00:00 2001 From: Philippe Caseiro Date: Fri, 21 Sep 2018 15:42:48 +0200 Subject: [PATCH 10/10] Spliting complex function parseWifiCells --- openwrt/wifi.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/openwrt/wifi.go b/openwrt/wifi.go index d13f5d7..e930bc5 100644 --- a/openwrt/wifi.go +++ b/openwrt/wifi.go @@ -26,11 +26,19 @@ func NewWifiWithExecutor(exec Executor, wIface string) *Wifi { return &Wifi{exec, wIface, nil} } +func (w *Wifi) getEncryption(line string) string { + enc := "unkn" + if strings.Contains(line, "WPA2 PSK") { + enc = "psk" + } else if strings.Contains(line, "none") { + enc = "none" + } + return enc +} + func (w *Wifi) parseWifiCells(stdout string) int { new := false - mac := "" - ssid := "" - enc := "" + mac, ssid, enc := "", "", "" for _, line := range strings.Split(strings.TrimSuffix(stdout, "\n"), "\n") { if strings.HasPrefix(line, "Cell") && new == false { new = true @@ -41,20 +49,12 @@ func (w *Wifi) parseWifiCells(stdout string) int { ssid = strings.Trim(ssid, "\"") } if strings.Contains(line, "Encryption:") { - if strings.Contains(line, "WPA2 PSK") { - enc = "psk" - } else if strings.Contains(line, "none") { - enc = "none" - } else { - enc = "unkn" - } + enc = w.getEncryption(line) } if len(mac) > 0 && len(ssid) > 0 && len(enc) > 0 { cell := NewWifiCell(ssid, mac, enc) w.Cells = append(w.Cells, cell) - ssid = "" - mac = "" - enc = "" + ssid, mac, enc = "", "", "" new = false } }