Moving owrt module code from Pyxis Orion

This commit is contained in:
Philippe Caseiro 2018-10-24 10:26:11 +02:00
parent 63b65867d1
commit b27db5fec3
23 changed files with 2625 additions and 0 deletions

82
dhcp_client.go Normal file
View File

@ -0,0 +1,82 @@
package owrt
import (
"bufio"
"fmt"
"regexp"
"strings"
)
// DhcpClient represents a dhcp client ... :)
type DhcpClient struct {
exec Executor
iface string
}
// DhcpResult contains sorted result form AskFroIP
type DhcpResult struct {
CmdRes *CommandResult
IP string
Netmask 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}
//}
func parseDhcpClientOut(out *CommandResult) *DhcpResult {
if out.ReturnCode != 0 {
return &DhcpResult{
out,
"",
"",
}
}
scanner := bufio.NewScanner(strings.NewReader(out.Stdout))
for scanner.Scan() {
line := scanner.Text()
re := regexp.MustCompile(`^udhcpc: ifconfig`)
if re.MatchString(line) {
spl := strings.Split(line, " ")
ip := spl[3]
mask := spl[5]
return &DhcpResult{
out,
ip,
mask,
}
}
}
return nil
}
// AskForIP runs a dhclient ip request with udhcpc
func (dc *DhcpClient) AskForIP() *DhcpResult {
out := dc.exec.Run("udhcpc", "-i", dc.iface)
fmt.Printf("%s\n", out.Stdout)
return parseDhcpClientOut(out)
}

12
dhcp_client_test.go Normal file
View File

@ -0,0 +1,12 @@
package owrt
import "testing"
func TestDhcpClientAskForIP(t *testing.T) {
uexec := createMockExecutor("udhcpc: ifconfig wlan1 192.168.42.20 netmask 255.255.255.0 broadcast +", "", 0)
dhc := NewDhcpClientWithExecutor("wlan1", uexec)
res := dhc.AskForIP()
if res.CmdRes.ReturnCode != 0 {
t.Error("Error in DHCP Client !!")
}
}

54
executor.go Normal file
View File

@ -0,0 +1,54 @@
package owrt
import (
"bytes"
"log"
"os/exec"
"syscall"
)
// Executor interface to describe command runners signature
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 outerr bytes.Buffer
var exitCode int
exe := exec.Command(command, params...)
exe.Stdout = &out
exe.Stderr = &outerr
err := exe.Run()
if err != nil {
// try to get the exit code
if exitError, ok := err.(*exec.ExitError); ok {
ws := exitError.Sys().(syscall.WaitStatus)
exitCode = ws.ExitStatus()
} else {
log.Printf("Could not get exit code for failed program: %v, %v", command, params)
}
} 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: outerr.String(),
ReturnCode: exitCode,
}
}

18
executor_test.go Normal file
View File

@ -0,0 +1,18 @@
package owrt
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)
// }
}

83
network.go Normal file
View File

@ -0,0 +1,83 @@
package owrt
import (
"fmt"
"io/ioutil"
"net"
"strings"
)
// Network provides a representation of network
type Network struct {
exec Executor
}
// NewNetwork return an Network instance to interact with OpenWRT Network components
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" command
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
}
result = append(result, ifaces...)
return result
}
// ListWirelessInterfaces list all wifi cards
// 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
if wifiFile == "" {
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]
if name != "" {
// remove damened whitespaces
name = strings.Replace(name, " ", "", -1)
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 _, name := range ifaceNames {
for _, iface := range ifaces {
if name == iface.Name {
result = append(result, iface)
}
}
}
return result
}

26
network_test.go Normal file
View File

@ -0,0 +1,26 @@
package owrt
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("./testdata/proc_net_wireless.txt")
if len(res) != 0 {
t.Error("The wireless interfaces list is not empty !!")
}
for _, el := range res {
fmt.Printf("[%s]\n", el.Name)
}
}

35
test.go Normal file
View File

@ -0,0 +1,35 @@
package owrt
import (
"log"
"strings"
)
func check(e error) {
if e != nil {
panic(e)
}
}
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,
}
}

4
testdata/proc_net_wireless.txt vendored Normal file
View File

@ -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

View File

@ -0,0 +1 @@
00:25:9c:14:59:6d

24
testdata/uci_show_wireless.txt vendored Normal file
View File

@ -0,0 +1,24 @@
wireless.radio0=wifi-device
wireless.radio0.type='mac80211'
wireless.radio0.channel='36'
wireless.radio0.hwmode='11a'
wireless.radio0.htmode='VHT80'
wireless.radio0.country='DE'
wireless.radio0.path='soc/soc:pcie/pci0000:00/0000:00:01.0/0000:01:00.0'
wireless.default_radio0=wifi-iface
wireless.default_radio0.device='radio0'
wireless.default_radio0.network='lan'
wireless.default_radio0.mode='ap'
wireless.default_radio0.macaddr='5a:ef:68:b5:f5:1a'
wireless.default_radio0.ssid='DonDuSang'
wireless.default_radio0.encryption='psk2'
wireless.default_radio0.key='cadoles;21'
wireless.radio1=wifi-device
wireless.radio1.type='mac80211'
wireless.radio1.hwmode='11g'
wireless.radio1.htmode='HT20'
wireless.radio1.country='FR'
wireless.radio1.path='soc/soc:pcie/pci0000:00/0000:00:02.0/0000:02:00.0'
wireless.radio1.channel='1'
wireless.radio1.legacy_rates='1'
wireless.radio1.disabled='0'

30
testdata/uci_show_wireless_2_cards.txt vendored Normal file
View File

@ -0,0 +1,30 @@
wireless.radio0=wifi-device
wireless.radio0.type='mac80211'
wireless.radio0.channel='36'
wireless.radio0.hwmode='11a'
wireless.radio0.htmode='VHT80'
wireless.radio0.country='DE'
wireless.radio0.path='soc/soc:pcie/pci0000:00/0000:00:01.0/0000:01:00.0'
wireless.default_radio0=wifi-iface
wireless.default_radio0.device='radio0'
wireless.default_radio0.network='lan'
wireless.default_radio0.mode='ap'
wireless.default_radio0.macaddr='5a:ef:68:b5:f5:1a'
wireless.default_radio0.ssid='DonDuSang'
wireless.default_radio0.encryption='psk2'
wireless.default_radio0.key='free_wifi!'
wireless.radio1=wifi-device
wireless.radio1.type='mac80211'
wireless.radio1.hwmode='11g'
wireless.radio1.htmode='HT20'
wireless.radio1.country='FR'
wireless.radio1.path='soc/soc:pcie/pci0000:00/0000:00:02.0/0000:02:00.0'
wireless.radio1.channel='1'
wireless.radio1.legacy_rates='1'
wireless.radio1.disabled='0'
wireless.@wifi-iface[1]=wifi-iface
wireless.@wifi-iface[1].device='radio1'
wireless.@wifi-iface[1].mode='ap'
wireless.@wifi-iface[1].ssid='Pyxis2'
wireless.@wifi-iface[1].encryption='psk2'
wireless.@wifi-iface[1].key='free_wifi!'

31
testdata/wifi_cells_output_1.txt vendored Normal file
View File

@ -0,0 +1,31 @@
BSS 7c:26:64:66:cc:44(on wlan1)
TSF: 85238642066 usec (0d, 23:40:38)
freq: 2412
beacon interval: 100 TUs
capability: ESS (0x0431)
signal: -63.00 dBm
last seen: 1500 ms ago
Information elements from Probe Response frame:
SSID: Livebox-32c8
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT TX/RX MCS rate indexes supported: 0-23
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
RSN: * Version: 1
* Group cipher: TKIP
* Pairwise ciphers: CCMP TKIP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)

88
testdata/wifi_cells_output_3.txt vendored Normal file
View File

@ -0,0 +1,88 @@
BSS 74:3e:2b:08:41:1c(on wlan1)
TSF: 85238642066 usec (0d, 23:40:38)
freq: 2412
beacon interval: 100 TUs
capability: ESS (0x0431)
signal: -63.00 dBm
last seen: 1500 ms ago
Information elements from Probe Response frame:
SSID: PyxisWifi
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT TX/RX MCS rate indexes supported: 0-23
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
RSN: * Version: 1
* Group cipher: TKIP
* Pairwise ciphers: CCMP TKIP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
BSS 7e:26:64:66:cc:44(on wlan1)
TSF: 85238646001 usec (0d, 23:40:38)
freq: 2412
beacon interval: 100 TUs
capability: ESS (0x0421)
signal: -66.00 dBm
last seen: 1500 ms ago
Information elements from Probe Response frame:
SSID: orange
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT TX/RX MCS rate indexes supported: 0-23
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS 20:47:da:b7:0e:5c(on wlan1)
TSF: 2161066518436 usec (25d, 00:17:46)
freq: 2412
beacon interval: 100 TUs
capability: ESS (0x0431)
signal: -58.00 dBm
last seen: 1640 ms ago
Information elements from Probe Response frame:
SSID: Livebox-596a
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT TX/RX MCS rate indexes supported: 0-23
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
RSN: * Version: 1
* Group cipher: TKIP
* Pairwise ciphers: CCMP TKIP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)

1152
testdata/wifi_cells_output_large.txt vendored Normal file
View File

@ -0,0 +1,1152 @@
BSS 7c:26:64:66:cc:44(on wlan1)
TSF: 85238642066 usec (0d, 23:40:38)
freq: 2412
beacon interval: 100 TUs
capability: ESS (0x0431)
signal: -63.00 dBm
last seen: 1500 ms ago
Information elements from Probe Response frame:
SSID: Livebox-32c8
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT TX/RX MCS rate indexes supported: 0-23
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
RSN: * Version: 1
* Group cipher: TKIP
* Pairwise ciphers: CCMP TKIP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
BSS 7e:26:64:66:cc:44(on wlan1)
TSF: 85238646001 usec (0d, 23:40:38)
freq: 2412
beacon interval: 100 TUs
capability: ESS (0x0421)
signal: -66.00 dBm
last seen: 1500 ms ago
Information elements from Probe Response frame:
SSID: orange
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT TX/RX MCS rate indexes supported: 0-23
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS ac:84:c9:2f:59:6e(on wlan1)
TSF: 2161066518436 usec (25d, 00:17:46)
freq: 2412
beacon interval: 100 TUs
capability: ESS (0x0431)
signal: -58.00 dBm
last seen: 1640 ms ago
Information elements from Probe Response frame:
SSID: Livebox-596a
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT TX/RX MCS rate indexes supported: 0-23
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
RSN: * Version: 1
* Group cipher: TKIP
* Pairwise ciphers: CCMP TKIP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
BSS b0:39:56:d8:38:ed(on wlan1)
TSF: 1037415177423 usec (12d, 00:10:15)
freq: 2422
beacon interval: 100 TUs
capability: ESS (0x0c11)
signal: -51.00 dBm
last seen: 1220 ms ago
Information elements from Probe Response frame:
SSID: Frate Dijon EXT
HT capabilities:
Capabilities: 0x11ee
HT20/HT40
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 4 usec (0x05)
HT RX MCS rate indexes supported: 0-15, 32
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 3
* secondary channel offset: no secondary
* STA channel width: 20 MHz
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
BSS 40:5a:9b:ed:ba:f0(on wlan1)
TSF: 3568958658654 usec (41d, 07:22:38)
freq: 2437
beacon interval: 100 TUs
capability: ESS (0x0431)
signal: -46.00 dBm
last seen: 740 ms ago
Information elements from Probe Response frame:
SSID: Cadoles
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT TX/RX MCS rate indexes supported: 0-15
HT operation:
* primary channel: 6
* secondary channel offset: no secondary
* STA channel width: 20 MHz
RSN: * Version: 1
* Group cipher: TKIP
* Pairwise ciphers: CCMP TKIP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
BSS 00:a6:ca:10:df:01(on wlan1)
TSF: 1018905678733 usec (11d, 19:01:45)
freq: 2437
beacon interval: 102 TUs
capability: ESS (0x1431)
signal: -80.00 dBm
last seen: 820 ms ago
Information elements from Probe Response frame:
SSID: EFF-Mobility
HT capabilities:
Capabilities: 0x19ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 4-PTKSA-RC 4-GTKSA-RC (0x0028)
HT operation:
* primary channel: 6
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS a0:04:60:b2:8a:c8(on wlan1)
TSF: 23484334090837 usec (271d, 19:25:34)
freq: 2472
beacon interval: 100 TUs
capability: ESS (0x0411)
signal: -44.00 dBm
last seen: 40 ms ago
Information elements from Probe Response frame:
SSID: Cadoles Formations (N)
HT capabilities:
Capabilities: 0x11ec
HT20
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 4 usec (0x05)
HT RX MCS rate indexes supported: 0-15, 32
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 13
* secondary channel offset: no secondary
* STA channel width: 20 MHz
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
BSS bc:f6:85:fe:6d:46(on wlan1)
TSF: 5185428505884 usec (60d, 00:23:48)
freq: 2467
beacon interval: 100 TUs
capability: ESS (0x0c11)
signal: -76.00 dBm
last seen: 30 ms ago
Information elements from Probe Response frame:
SSID: Dlink
HT capabilities:
Capabilities: 0x11ee
HT20/HT40
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 2 usec (0x04)
HT RX MCS rate indexes supported: 0-15, 32
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 12
* secondary channel offset: no secondary
* STA channel width: 20 MHz
Secondary Channel Offset: no secondary (0)
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
BSS 90:4d:4a:f7:b9:71(on wlan1)
TSF: 4721041865203 usec (54d, 15:24:01)
freq: 2462
beacon interval: 100 TUs
capability: ESS (0x0001)
signal: -82.00 dBm
last seen: 300 ms ago
Information elements from Probe Response frame:
SSID: orange
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 4 usec (0x05)
HT Max RX data rate: 384 Mbps
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 11
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS e4:9e:12:8b:ef:73(on wlan1)
TSF: 7952485362135 usec (92d, 01:01:25)
freq: 2452
beacon interval: 96 TUs
capability: ESS (0x0411)
signal: -80.00 dBm
last seen: 430 ms ago
Information elements from Probe Response frame:
SSID: Freebox-8BEF72
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c)
HT capabilities:
Capabilities: 0xec
HT20
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
TX STBC
No RX STBC
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: No restriction (0x00)
HT TX/RX MCS rate indexes supported: 0-23, 32
HT operation:
* primary channel: 9
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS 90:4d:4a:f7:b9:70(on wlan1)
TSF: 4721041856992 usec (54d, 15:24:01)
freq: 2462
beacon interval: 100 TUs
capability: ESS (0x0011)
signal: -78.00 dBm
last seen: 310 ms ago
Information elements from Probe Response frame:
SSID: Livebox-B970
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c)
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 4 usec (0x05)
HT Max RX data rate: 384 Mbps
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 11
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS 3c:52:82:fc:5e:21(on wlan1)
TSF: 6735883434375 usec (77d, 23:04:43)
freq: 2437
beacon interval: 100 TUs
capability: ESS (0x0511)
signal: -79.00 dBm
last seen: 970 ms ago
Information elements from Probe Response frame:
SSID: DIRECT-20-HP DeskJet 3630 series
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c)
HT capabilities:
Capabilities: 0x20
HT20
Static SM Power Save
RX HT20 SGI
No RX STBC
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 32767 bytes (exponent: 0x002)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-7
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 6
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS 00:a6:ca:10:df:02(on wlan1)
TSF: 1018894510847 usec (11d, 19:01:34)
freq: 2437
beacon interval: 102 TUs
capability: ESS (0x1421)
signal: -73.00 dBm
last seen: 1040 ms ago
Information elements from Probe Response frame:
SSID: Keo-HotSpot
HT capabilities:
Capabilities: 0x19ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 6
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS a2:17:33:9f:4d:81(on wlan1)
TSF: 3050426691569 usec (35d, 07:20:26)
freq: 2462
beacon interval: 100 TUs
capability: ESS (0x0401)
signal: -82.00 dBm
last seen: 310 ms ago
Information elements from Probe Response frame:
SSID: SFR WiFi FON
BSS ac:84:c9:1d:c6:7c(on wlan1)
TSF: 2491424200041 usec (28d, 20:03:44)
freq: 2412
beacon interval: 100 TUs
capability: ESS (0x0431)
signal: -80.00 dBm
last seen: 1480 ms ago
Information elements from Probe Response frame:
SSID: Frate Djon
RSN: * Version: 1
* Group cipher: TKIP
* Pairwise ciphers: CCMP TKIP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
BSS 78:81:02:5e:b7:15(on wlan1)
TSF: 4786879928619 usec (55d, 09:41:19)
freq: 2437
beacon interval: 100 TUs
capability: ESS (0x0401)
signal: -83.00 dBm
last seen: 950 ms ago
Information elements from Probe Response frame:
SSID: orange
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 4 usec (0x05)
HT Max RX data rate: 384 Mbps
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 6
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS 00:a6:ca:10:df:00(on wlan1)
TSF: 1018905280864 usec (11d, 19:01:45)
freq: 2437
beacon interval: 102 TUs
capability: ESS (0x1431)
signal: -76.00 dBm
last seen: 1170 ms ago
Information elements from Probe Response frame:
SSID: \x00
HT capabilities:
Capabilities: 0x19ac
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: IEEE 802.1X
* Capabilities: 4-PTKSA-RC 4-GTKSA-RC (0x0028)
HT operation:
* primary channel: 6
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS a0:1b:29:be:98:26(on wlan1)
TSF: 2931892990829 usec (33d, 22:24:52)
freq: 2437
beacon interval: 100 TUs
capability: ESS (0x0431)
signal: -64.00 dBm
last seen: 970 ms ago
Information elements from Probe Response frame:
SSID: Livebox-9822
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT TX/RX MCS rate indexes supported: 0-15
HT operation:
* primary channel: 6
* secondary channel offset: no secondary
* STA channel width: 20 MHz
RSN: * Version: 1
* Group cipher: TKIP
* Pairwise ciphers: CCMP TKIP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
BSS 40:4a:03:05:d2:68(on wlan1)
TSF: 57377785 usec (0d, 00:00:57)
freq: 2462
beacon interval: 100 TUs
capability: ESS (0x0431)
signal: -76.00 dBm
last seen: 240 ms ago
Information elements from Probe Response frame:
SSID: ZyXEL
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
HT capabilities:
Capabilities: 0x104e
HT20/HT40
SM Power Save disabled
RX HT40 SGI
No RX STBC
Max AMSDU length: 3839 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-15
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 11
* secondary channel offset: below
* STA channel width: any
BSS f4:ca:e5:98:3b:de(on wlan1)
TSF: 502449932512 usec (5d, 19:34:09)
freq: 2462
beacon interval: 96 TUs
capability: ESS (0x0411)
signal: -86.00 dBm
last seen: 11400 ms ago
Information elements from Probe Response frame:
SSID: FreeWifi_secure
RSN: * Version: 1
* Group cipher: TKIP
* Pairwise ciphers: CCMP TKIP
* Authentication suites: IEEE 802.1X
* Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c)
HT capabilities:
Capabilities: 0x6c
HT20
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
No RX STBC
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: No restriction (0x00)
HT TX/RX MCS rate indexes supported: 0-23, 32
HT operation:
* primary channel: 11
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS 00:17:33:9f:4d:80(on wlan1)
TSF: 3050426716298 usec (35d, 07:20:26)
freq: 2462
beacon interval: 100 TUs
capability: ESS (0x0411)
signal: -79.00 dBm
last seen: 290 ms ago
Information elements from Probe Response frame:
SSID: NEUF_4D7C
BSS a2:17:33:9f:4d:83(on wlan1)
TSF: 3050426718113 usec (35d, 07:20:26)
freq: 2462
beacon interval: 100 TUs
capability: ESS (0x0411)
signal: -80.00 dBm
last seen: 290 ms ago
Information elements from Probe Response frame:
SSID: SFR WiFi Mobile
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: IEEE 802.1X
* Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c)
BSS 30:7c:b2:d1:0b:0d(on wlan1)
TSF: 1059959180138 usec (12d, 06:25:59)
freq: 2462
beacon interval: 100 TUs
capability: ESS (0x0431)
signal: -80.00 dBm
last seen: 11200 ms ago
Information elements from Probe Response frame:
SSID: Livebox-0b09
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT TX/RX MCS rate indexes supported: 0-15
HT operation:
* primary channel: 11
* secondary channel offset: no secondary
* STA channel width: 20 MHz
RSN: * Version: 1
* Group cipher: TKIP
* Pairwise ciphers: CCMP TKIP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
BSS 68:a3:78:0d:b6:51(on wlan1)
TSF: 136373797215 usec (1d, 13:52:53)
freq: 2462
beacon interval: 96 TUs
capability: ESS (0x0411)
signal: -88.00 dBm
last seen: 11230 ms ago
Information elements from Probe Response frame:
SSID: Freebox-0DB650
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c)
HT capabilities:
Capabilities: 0xec
HT20
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
TX STBC
No RX STBC
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: No restriction (0x00)
HT TX/RX MCS rate indexes supported: 0-23, 32
HT operation:
* primary channel: 11
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS 68:15:90:36:63:60(on wlan1)
TSF: 308936601984 usec (3d, 13:48:56)
freq: 2412
beacon interval: 100 TUs
capability: ESS (0x0431)
signal: -88.00 dBm
last seen: 12650 ms ago
Information elements from Probe Response frame:
SSID: Livebox-6360
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-15
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
RSN: * Version: 1
* Group cipher: TKIP
* Pairwise ciphers: CCMP TKIP
* Authentication suites: PSK
* Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c)
BSS 0c:8d:db:c4:a0:34(on wlan1)
TSF: 372485216298 usec (4d, 07:28:05)
freq: 2412
beacon interval: 100 TUs
capability: ESS (0x1431)
signal: -56.00 dBm
last seen: 1540 ms ago
Information elements from Probe Response frame:
SSID: pfPauvres
RSN: * Version: 1
* Group cipher: TKIP
* Pairwise ciphers: CCMP TKIP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
HT capabilities:
Capabilities: 0x9ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 7935 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: No restriction (0x00)
HT TX/RX MCS rate indexes supported: 0-15
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
VHT capabilities:
VHT Capabilities (0x338959b2):
Max MPDU length: 11454
Supported Channel Width: neither 160 nor 80+80
RX LDPC
short GI (80 MHz)
TX STBC
SU Beamformer
SU Beamformee
MU Beamformer
RX antenna pattern consistency
TX antenna pattern consistency
VHT RX MCS set:
1 streams: MCS 0-9
2 streams: MCS 0-9
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
VHT RX highest supported: 0 Mbps
VHT TX MCS set:
1 streams: MCS 0-9
2 streams: MCS 0-9
3 streams: not supported
4 streams: not supported
5 streams: not supported
6 streams: not supported
7 streams: not supported
8 streams: not supported
VHT TX highest supported: 0 Mbps
VHT operation:
* channel width: 0 (20 or 40 MHz)
* center freq segment 1: 0
* center freq segment 2: 0
* VHT basic MCS set: 0xfffc
BSS ac:3b:77:6a:24:e0(on wlan1)
TSF: 741652789170 usec (8d, 14:00:52)
freq: 2412
beacon interval: 100 TUs
capability: ESS (0x0411)
signal: -87.00 dBm
last seen: 1700 ms ago
Information elements from Probe Response frame:
SSID: Grosorboul
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c)
HT capabilities:
Capabilities: 0x18fc
HT20
SM Power Save disabled
RX Greenfield
RX HT20 SGI
RX HT40 SGI
TX STBC
No RX STBC
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-15
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 1
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS 68:a3:78:6e:d9:24(on wlan1)
TSF: 85494694239 usec (0d, 23:44:54)
freq: 2422
beacon interval: 96 TUs
capability: ESS (0x0401)
signal: -87.00 dBm
last seen: 1340 ms ago
Information elements from Probe Response frame:
SSID: FreeWifi
HT capabilities:
Capabilities: 0xec
HT20
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
TX STBC
No RX STBC
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: No restriction (0x00)
HT TX/RX MCS rate indexes supported: 0-23, 32
HT operation:
* primary channel: 3
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS 14:0c:76:79:c0:d9(on wlan1)
TSF: 572290498911 usec (6d, 14:58:10)
freq: 2427
beacon interval: 96 TUs
capability: ESS (0x0411)
signal: -86.00 dBm
last seen: 1300 ms ago
Information elements from Probe Response frame:
SSID: freebox_ZFSFUA
HT capabilities:
Capabilities: 0x6c
HT20
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
No RX STBC
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: No restriction (0x00)
HT TX/RX MCS rate indexes supported: 0-23, 32
HT operation:
* primary channel: 4
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS 78:81:02:5e:b7:14(on wlan1)
TSF: 4786879917067 usec (55d, 09:41:19)
freq: 2437
beacon interval: 100 TUs
capability: ESS (0x0411)
signal: -84.00 dBm
last seen: 960 ms ago
SSID: Livebox-B714
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c)
HT capabilities:
Capabilities: 0x1ad
RX LDPC
HT20
SM Power Save disabled
RX HT20 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 4 usec (0x05)
HT Max RX data rate: 384 Mbps
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 6
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS d6:38:9c:67:00:7a(on wlan1)
TSF: 52271652256 usec (0d, 14:31:11)
freq: 2442
beacon interval: 100 TUs
capability: ESS (0x0411)
signal: -75.00 dBm
last seen: 680 ms ago
Information elements from Probe Response frame:
SSID: \xc5\xa4\xc3\xa3h\xc3\xae\xc5\x99
HT capabilities:
Capabilities: 0x130
HT20
Static SM Power Save
RX Greenfield
RX HT20 SGI
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: No restriction (0x00)
HT TX/RX MCS rate indexes supported: 0-7
HT operation:
* primary channel: 7
* secondary channel offset: no secondary
* STA channel width: 20 MHz
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c)
BSS 00:19:70:4f:de:f2(on wlan1)
TSF: 223832269184 usec (2d, 14:10:32)
freq: 2462
beacon interval: 100 TUs
capability: ESS (0x0431)
signal: -86.00 dBm
last seen: 11260 ms ago
Information elements from Probe Response frame:
SSID: Livebox-45cc
RSN: * Version: 1
* Group cipher: TKIP
* Pairwise ciphers: CCMP TKIP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
HT capabilities:
Capabilities: 0x100c
HT20
SM Power Save disabled
No RX STBC
Max AMSDU length: 3839 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-15
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 11
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS 6c:38:a1:62:1b:28(on wlan1)
TSF: 2704292761929 usec (31d, 07:11:32)
freq: 2412
beacon interval: 100 TUs
capability: ESS (0x0c11)
signal: -86.00 dBm
last seen: 1660 ms ago
Information elements from Probe Response frame:
SSID: Bbox-1B7889A9
HT capabilities:
Capabilities: 0x1ec
HT20
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
TX STBC
RX STBC 1-stream
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: No restriction (0x00)
HT RX MCS rate indexes supported: 0-23
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 1
* secondary channel offset: above
* STA channel width: 20 MHz
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
BSS 68:a3:78:6e:d9:25(on wlan1)
TSF: 85494497631 usec (0d, 23:44:54)
freq: 2422
beacon interval: 96 TUs
capability: ESS (0x0411)
signal: -85.00 dBm
last seen: 1500 ms ago
Information elements from Probe Response frame:
SSID: FreeWifi_secure
RSN: * Version: 1
* Group cipher: TKIP
* Pairwise ciphers: CCMP TKIP
* Authentication suites: IEEE 802.1X
* Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c)
HT capabilities:
Capabilities: 0xec
HT20
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
TX STBC
No RX STBC
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: No restriction (0x00)
HT TX/RX MCS rate indexes supported: 0-23, 32
HT operation:
* primary channel: 3
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS 56:62:21:de:de:70(on wlan1)
TSF: 5762545254750 usec (66d, 16:42:25)
freq: 2422
beacon interval: 100 TUs
capability: ESS (0x0411)
signal: -88.00 dBm
last seen: 1430 ms ago
Information elements from Probe Response frame:
SSID: FREEBOX_JOSIANNE_46
HT capabilities:
Capabilities: 0x106e
HT20/HT40
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
No RX STBC
Max AMSDU length: 3839 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 4 usec (0x05)
HT RX MCS rate indexes supported: 0-15, 32
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 3
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS 56:62:21:de:de:71(on wlan1)
TSF: 5762545257087 usec (66d, 16:42:25)
freq: 2422
beacon interval: 100 TUs
capability: ESS (0x0411)
signal: -86.00 dBm
last seen: 1430 ms ago
Information elements from Probe Response frame:
SSID:
HT capabilities:
Capabilities: 0x106e
HT20/HT40
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
No RX STBC
Max AMSDU length: 3839 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 4 usec (0x05)
HT RX MCS rate indexes supported: 0-15, 32
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 3
* secondary channel offset: no secondary
* STA channel width: 20 MHz
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
BSS 68:a3:78:6e:d9:23(on wlan1)
TSF: 85494792543 usec (0d, 23:44:54)
freq: 2422
beacon interval: 96 TUs
capability: ESS (0x0411)
signal: -86.00 dBm
last seen: 1270 ms ago
Information elements from Probe Response frame:
SSID: Freebox-6ED922
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: PSK
* Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c)
HT capabilities:
Capabilities: 0xec
HT20
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
TX STBC
No RX STBC
Max AMSDU length: 3839 bytes
No DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: No restriction (0x00)
HT TX/RX MCS rate indexes supported: 0-23, 32
HT operation:
* primary channel: 3
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS 44:ce:7d:20:5c:a4(on wlan1)
TSF: 2322036531897 usec (26d, 21:00:36)
freq: 2437
beacon interval: 100 TUs
capability: ESS (0x0411)
signal: -82.00 dBm
last seen: 1030 ms ago
Information elements from Probe Response frame:
SSID: SFR_5CA0
HT capabilities:
Capabilities: 0x18ec
HT20
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
TX STBC
No RX STBC
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-15
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 6
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS d2:ce:7d:20:5c:a7(on wlan1)
TSF: 2322036535330 usec (26d, 21:00:36)
freq: 2437
beacon interval: 100 TUs
capability: ESS (0x0411)
signal: -87.00 dBm
last seen: 1030 ms ago
Information elements from Probe Response frame:
SSID: SFR WiFi Mobile
RSN: * Version: 1
* Group cipher: CCMP
* Pairwise ciphers: CCMP
* Authentication suites: IEEE 802.1X
* Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c)
HT capabilities:
Capabilities: 0x18ec
HT20
SM Power Save disabled
RX HT20 SGI
RX HT40 SGI
TX STBC
No RX STBC
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 8 usec (0x06)
HT RX MCS rate indexes supported: 0-15
HT TX MCS rate indexes are undefined
HT operation:
* primary channel: 6
* secondary channel offset: no secondary
* STA channel width: 20 MHz
BSS 00:22:6b:86:5b:71(on wlan1)
TSF: 13910494312595 usec (161d, 00:01:34)
freq: 2462
beacon interval: 100 TUs
capability: ESS (0x0411)
signal: -88.00 dBm
last seen: 350 ms ago
Information elements from Probe Response frame:
SSID: linksys
RSN: * Version: 1
* Group cipher: TKIP
* Pairwise ciphers: CCMP TKIP
* Authentication suites: PSK
* Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)

122
uci.go Normal file
View File

@ -0,0 +1,122 @@
package owrt
import (
"fmt"
"time"
)
// Action is the result of an UCI action output and return code
type Action struct {
*CommandResult
Command string
}
// UCI "Object"
type UCI struct {
exec Executor
Wireless *UCIWirelessConf
}
// NewUCI return an UCI instance to interact with UCI
func NewUCI() *UCI {
exec := &localExecutor{}
wireless := &UCIWirelessConf{}
return &UCI{exec, wireless}
}
// 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 {
wireless := &UCIWirelessConf{}
return &UCI{exec, wireless}
}
// uciRun, private method to run the UCI command
func (u *UCI) uciRun(param ...string) *Action {
cmd := "/sbin/uci"
res := u.exec.Run(cmd, param...)
return &Action{res, fmt.Sprintf("%s %s", cmd, param)}
}
// Add add an entry to UCI configuration, specify the Module and the value
func (u *UCI) Add(module string, name string) *Action {
cmd := "uci add"
commandRes := u.exec.Run(cmd, module, name)
return &Action{commandRes, fmt.Sprintf("%s %s %s", cmd, module, name)}
}
// Delete delete an entry from UCI configuration specify the entry name
func (u *UCI) Delete(entry string) *Action {
return u.uciRun("delete", entry)
}
// 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))
}
// Commit the recent actions to UCI
func (u *UCI) Commit() *Action {
res := u.uciRun("commit")
return res
}
// Reload reload uci configuration
func (u *UCI) Reload() *Action {
cmdResult := u.exec.Run("reload_config")
time.Sleep(5 * time.Second)
return &Action{cmdResult, "reload_config"}
}
// Show returns the output of uci show command
func (u *UCI) Show(target string) *Action {
cmdRes := u.uciRun("show", target)
return cmdRes
}
// AddWireless Create a new Wireless entry in UCI configuration
func (u *UCI) AddWireless() *Action {
res := u.uciRun("add", "wireless", "wifi-iface")
return res
}
// LoadWirelessConf scan UCI configuration and loads saved Wireless configuration
func (u *UCI) LoadWirelessConf() {
u.Wireless = NewUCIWirelessConf(u)
u.Wireless.Load()
}
// GetWifiIface returns the wifi Interface by Index
func (u *UCI) GetWifiIface(idx int) *UCIWirelessInterface {
ifaces := u.Wireless.Interfaces
if len(ifaces) < idx {
return nil
}
return ifaces[idx]
}
// GetWifiIfaceByName returns the wifi Interface by Index
func (u *UCI) GetWifiIfaceByName(name string) *UCIWirelessInterface {
ifaces := u.Wireless.Interfaces
if len(ifaces) <= 0 {
return nil
}
for _, ifa := range ifaces {
if ifa.Name == name {
return ifa
}
}
return nil
}
// GetWifiIfaces wifi interfaces in configuration
func (u *UCI) GetWifiIfaces() []*UCIWirelessInterface {
return u.Wireless.Interfaces
}
// GetWifiDevices returns the wifi devices in configuration
func (u *UCI) GetWifiDevices() []map[string]string {
return u.Wireless.Devices
}

100
uci_test.go Normal file
View File

@ -0,0 +1,100 @@
package owrt
import (
"fmt"
"testing"
)
func TestUCIAdd(t *testing.T) {
exec := createMockExecutor("", "", 0)
uci := NewUCIWithExecutor(exec)
res := uci.Add("wireless", "test")
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 TestUCIAddFailed(t *testing.T) {
exec := createMockExecutor("", "BigError", 3)
uci := NewUCIWithExecutor(exec)
res := uci.Add("wireless", "test")
if res.ReturnCode != 3 {
t.Error("Bad Return Code !")
}
}
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 ...")
}
}

179
uci_wireless_conf.go Normal file
View File

@ -0,0 +1,179 @@
package owrt
import (
"fmt"
"regexp"
"strconv"
"strings"
)
// UCIWirelessConf is the representation of UCI Wireless Configuration
type UCIWirelessConf struct {
uciClient *UCI
Devices []map[string]string
DefaultInterface map[string]string
Interfaces []*UCIWirelessInterface
}
// NewUCIWirelessConf builds a new UCIWirelessConf instance
func NewUCIWirelessConf(uci *UCI) *UCIWirelessConf {
return &UCIWirelessConf{
uciClient: uci,
Devices: []map[string]string{}, //, 10),
DefaultInterface: map[string]string{},
Interfaces: []*UCIWirelessInterface{}, //, 10),
}
}
// parse wireless.default_radio[0-9] section of UCI Configuration
func (wc *UCIWirelessConf) parseDefaultInterface(lines []string) int {
matches := map[string]string{
"Name": "default_radio0=",
"Type": "default_radio0.type=",
"Channel": "default_radio0.channel=",
"Hwmode": "default_radio0.hwmode=",
"Htmode": "default_radio0.htmode=",
"Country": "default_radio0.country=",
"Path": "default_radio0.path=",
}
for _, line := range lines {
for key, value := range matches {
if strings.Contains(line, value) {
wc.DefaultInterface[key] = strings.Split(line, "=")[1]
}
}
}
return 0
}
func (wc *UCIWirelessConf) parseInterfaces(lines []string) int {
matches := map[string]*regexp.Regexp{
"Name": regexp.MustCompile(`@wifi-iface\[[0-9]\]=`),
"Device": regexp.MustCompile(`@wifi-iface\[[0-9]\].device=`),
"Mode": regexp.MustCompile(`@wifi-iface\[[0-9]\].mode=`),
"Ssid": regexp.MustCompile(`@wifi-iface\[[0-9]\].ssid=`),
"Encryption": regexp.MustCompile(`@wifi-iface\[[0-9]\].encryption=`),
"Key": regexp.MustCompile(`@wifi-iface\[[0-9]\].key=`),
}
for _, li := range lines {
var idx int
sIdx := strings.Split(li, "[")[1]
sIdx = strings.Split(sIdx, "]")[0]
if s, err := strconv.ParseInt(sIdx, 10, 32); err == nil {
idx = int(s)
}
if idx >= len(wc.Interfaces) {
for i := 0; i <= idx; i++ {
wc.Interfaces = append(wc.Interfaces, NewUCIWirelessInterface())
}
}
if wc.Interfaces[idx] == nil {
wc.Interfaces[idx] = NewUCIWirelessInterface()
wc.Interfaces[idx].Index = idx
}
for key, expr := range matches {
if expr.MatchString(li) {
value := strings.Split(li, "=")[1]
if key == "Name" {
wc.Interfaces[idx].Name = value
}
if key == "Device" {
wc.Interfaces[idx].Device = value
//FIXME
//dev := fmt.Sprintf("wireless.%s", value)
//path := wc.uciClient.Show(dev)
//wc.Interfaces[idx].DevicePath = strings.Split(path.Stdout, "=")[1]
}
if key == "Mode" {
wc.Interfaces[idx].Mode = value
}
if key == "Ssid" {
wc.Interfaces[idx].Ssid = value
}
if key == "Encryption" {
wc.Interfaces[idx].Encryption = value
}
if key == "Key" {
wc.Interfaces[idx].Key = value
}
}
}
}
return 0
}
func (wc *UCIWirelessConf) parseDevicesConf(lines []string) int {
matches := map[string]string{
"Name": "radio[0-9]=",
"Type": "radio[0-9].type=",
"Channel": "radio[0-9].channel=",
"Hwmode": "radio[0-9].hwmode=",
"Htmode": "radio[0-9].htmode=",
"Country": "radio[0-9].country=",
"Path": "radio[0-9].path=",
}
for _, line := range lines {
var idx int
re := regexp.MustCompile("[0-9]")
rIdx := re.FindString(line)
if s, err := strconv.ParseInt(rIdx, 10, 32); err == nil {
idx = int(s)
}
if len(wc.Devices) == 0 {
wc.Devices = append(wc.Devices, make(map[string]string))
}
if idx >= len(wc.Devices) {
for i := 0; i < idx; i++ {
wc.Devices = append(wc.Devices, make(map[string]string))
}
}
if wc.Devices[idx] == nil {
wc.Devices[idx] = make(map[string]string)
}
for key, expr := range matches {
re := regexp.MustCompile(expr)
if re.MatchString(line) {
value := strings.Split(line, "=")[1]
value = strings.Trim(value, "'")
if key == "Name" {
wc.Devices[idx]["Device"] = fmt.Sprintf("radio%d", idx)
}
wc.Devices[idx][key] = value
}
}
}
return 0
}
func grep(lines string, pattern string) []string {
var res []string
for _, line := range strings.Split(strings.TrimSuffix(lines, "\n"), "\n") {
re := regexp.MustCompile(pattern)
if re.MatchString(line) {
res = append(res, line)
}
}
return res
}
// Load return the Wireless Configuration
func (wc *UCIWirelessConf) Load() *UCIWirelessConf {
conf := wc.uciClient.Show("wireless")
wc.parseDevicesConf(grep(conf.Stdout, "wireless.radio"))
wc.parseDefaultInterface(grep(conf.Stdout, "wireless.default_radio0"))
wc.parseInterfaces(grep(conf.Stdout, "wireless.@wifi-iface"))
return wc
}

30
uci_wireless_conf_test.go Normal file
View File

@ -0,0 +1,30 @@
package owrt
import (
"io/ioutil"
"testing"
)
func TestUCIGetWirelessConf(t *testing.T) {
config, err := ioutil.ReadFile("./testdata/uci_show_wireless.txt")
if err != nil {
t.Fatal(err)
}
exec := createMockExecutor(string(config), "", 0)
uci := NewUCIWithExecutor(exec)
uci.LoadWirelessConf()
if g, e := uci.Wireless.DefaultInterface["Name"], "wifi-iface"; g != e {
t.Fatalf("DefaultDevice.Name is expected to be [%s] and we have [%s]", e, g)
}
config, err = ioutil.ReadFile("./testdata/uci_show_wireless_2_cards.txt")
if err != nil {
t.Fatal(err)
}
exec = createMockExecutor(string(config), "", 0)
uci = NewUCIWithExecutor(exec)
uci.LoadWirelessConf()
if g, e := uci.Wireless.Interfaces[1].Name, "wifi-iface"; g != e {
t.Fatalf("DefaultDevice.Name is expected to be [%s] and we have [%s]", e, g)
}
}

209
uci_wireless_interface.go Normal file
View File

@ -0,0 +1,209 @@
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)
}

View File

@ -0,0 +1,131 @@
package owrt
import (
"testing"
)
const (
ifaceName = "Test"
ifaceNetwork = "Pyxis"
ifaceSysDevName = "wlanX"
ifaceEnc = "psk"
ifaceSSID = "PyxisWifi"
ifaceKey = "qsmdflkjqslmdfkjqslmfkdj"
ifaceDevice = "radioX"
ifaceMode = "ap"
ifaceBssid = "00:00:00:00:00"
)
func TestGetSysDevName(t *testing.T) {
iface := NewUCIWirelessInterface()
iface.Name = ifaceName
iface.Index = 1
iface.Device = ifaceDevice
iface.DevicePath = "soc/soc:pcie/pci0000:00/0000:00:02.0/0000:02:00.0"
iface.Mode = ifaceMode
iface.Ssid = ifaceSSID
iface.Bssid = ifaceBssid
iface.Network = ifaceNetwork
iface.Encryption = ifaceEnc
iface.Key = ifaceKey
if g, e := iface.GetSysDevName("testdata/sys/"), "wlan1"; g != e {
t.Fatalf("UCIWirelessInterface.GetDeviceSysName() failed ! Got: %s Expect: %s", g, e)
}
iface.SysDevName = "wlanX"
if g, e := iface.GetSysDevName("testdata/sys/"), "wlanX"; g != e {
t.Fatalf("UCIWirelessInterface.GetDeviceSysName() failed ! Got: %s Expect: %s", g, e)
}
}
func TestCreate(t *testing.T) {
exec := createMockExecutor("", "", 0)
uci := NewUCIWithExecutor(exec)
iface := NewUCIWirelessInterface()
iface.Name = ifaceName
iface.Device = ifaceDevice
iface.Mode = ifaceMode
iface.Ssid = ifaceSSID
iface.Bssid = ifaceBssid
iface.Network = ifaceNetwork
iface.Encryption = ifaceEnc
iface.Key = ifaceKey
if iface.Create(uci).ReturnCode != 0 {
t.Fatalf("UCIWirelessInterface.Create() failed !")
}
}
func TestUpdate(t *testing.T) {
exec := createMockExecutor("", "", 0)
uci := NewUCIWithExecutor(exec)
iface := NewUCIWirelessInterface()
iface.Name = ifaceName
iface.Index = 1
iface.Device = ifaceDevice
iface.SysDevName = ifaceSysDevName
iface.Mode = ifaceMode
iface.Ssid = ifaceSSID
iface.Bssid = ifaceBssid
iface.Network = ifaceNetwork
iface.Encryption = ifaceEnc
iface.Key = ifaceKey
if iface.Create(uci).ReturnCode != 0 {
t.Fatalf("UCIWirelessInterface.Create() failed !")
}
iface.Name = "Tutu"
if iface.Update(uci).ReturnCode != 0 {
t.Fatalf("UCIWirelessInterface.Update() failed !")
}
}
func TestDelete(t *testing.T) {
exec := createMockExecutor("", "", 0)
uci := NewUCIWithExecutor(exec)
iface := NewUCIWirelessInterface()
iface.Name = ifaceName
iface.Index = 1
iface.Device = ifaceDevice
iface.SysDevName = ifaceSysDevName
iface.Mode = ifaceMode
iface.Ssid = ifaceSSID
iface.Bssid = ifaceBssid
iface.Network = ifaceNetwork
iface.Encryption = ifaceEnc
iface.Key = ifaceKey
if iface.Delete(uci).ReturnCode != 0 {
t.Fatalf("UCIWirelessInterface.Delete() failed !")
}
}
func TestConnect(t *testing.T) {
exec := createMockExecutor("", "", 0)
uci := NewUCIWithExecutor(exec)
iface := NewUCIWirelessInterface()
iface.Name = ifaceName
iface.Index = 1
iface.Device = ifaceDevice
iface.SysDevName = ifaceSysDevName
iface.Mode = ifaceMode
iface.Ssid = ifaceSSID
iface.Bssid = ifaceBssid
iface.Network = ifaceNetwork
iface.Encryption = ifaceEnc
iface.Key = ifaceKey
wifiCell := NewWifiCell("PyxisWifi", "01:01:01:01:01", "psk")
if iface.Connect(uci, wifiCell, "Toto").ReturnCode != 0 {
t.Fatalf("UCIWirelessInterface.Delete() failed !")
}
}

17
wifi_cell.go Normal file
View File

@ -0,0 +1,17 @@
package owrt
// WifiCell reprensents wifi network Cell
type WifiCell struct {
Ssid string
MacAddress string
Encryption string
}
// NewWifiCell returns a new WifiCell object
func NewWifiCell(ssid string, mac string, encrypt string) *WifiCell {
return &WifiCell{
Ssid: ssid,
MacAddress: mac,
Encryption: encrypt,
}
}

126
wifi_scanner.go Normal file
View File

@ -0,0 +1,126 @@
package owrt
import (
"regexp"
"strings"
"time"
)
// NONE contains the string for "none"
const NONE = "none"
// WifiScanner gives access to al OpenWRT Wifi Scan operations
type WifiScanner struct {
exec Executor
iface string
Cells []*WifiCell
}
// NewWifiScanner return an UCI instance to interact with UCI
func NewWifiScanner(wIface string) *WifiScanner {
exec := &localExecutor{}
iface := wIface
Cells := []*WifiCell{}
return &WifiScanner{exec, iface, Cells}
}
// 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) *WifiScanner {
return &WifiScanner{exec, wIface, nil}
}
func (w *WifiScanner) getEncryption(line string) string {
var enc string
if strings.Contains(line, "PSK") {
enc = "psk2"
} else if strings.Contains(line, NONE) {
enc = NONE
} else {
enc = "unkn"
}
return enc
}
func (w *WifiScanner) parseWifiCells(stdout string) int {
mac, ssid, enc := "", "", ""
encOff := false
macExpr := `([0-9a-fA-F][0-9a-fA-F]:){5}([0-9a-fA-F][0-9a-fA-F])`
for _, line := range strings.Split(strings.TrimSuffix(stdout, "\n"), "\n") {
expr := regexp.MustCompile("^BSS")
if expr.MatchString(line) {
if len(mac) != 0 && len(ssid) != 0 && len(enc) == 0 {
enc = NONE
cell := NewWifiCell(ssid, mac, enc)
w.Cells = append(w.Cells, cell)
ssid, enc = "", ""
}
macRegexp := regexp.MustCompile(macExpr)
mac = macRegexp.FindString(line)
}
if strings.Contains(line, "SSID:") {
ssid = strings.Split(line, " ")[1]
ssid = strings.Trim(ssid, "\"")
//ssid = strings.Trim(ssid, " ")
if ssid == "" {
ssid = " "
}
}
if strings.Contains(line, "Encryption key:off") {
encOff = true
}
if strings.Contains(line, "Authentication suites") {
enc = w.getEncryption(line)
}
if len(mac) > 0 && len(ssid) > 0 && (len(enc) > 0 || encOff) {
if encOff {
enc = NONE
encOff = false
}
cell := NewWifiCell(ssid, mac, enc)
w.Cells = append(w.Cells, cell)
ssid, mac, enc = "", "", ""
}
}
return 0
}
// GetWifiCells retrieves all available wifi cells for a card !
func (w *WifiScanner) GetWifiCells() int {
var res *CommandResult
for try := 0; try != 20; try++ {
res = w.exec.Run("iw", w.iface, "scan")
if res.ReturnCode == 0 {
parsing := w.parseWifiCells(res.Stdout)
if parsing == 0 {
if len(w.Cells) == 0 {
return 242
}
}
return parsing
}
time.Sleep(time.Second * 2)
}
return res.ReturnCode
}
// GetCell retreives an WifiCell by SSID provided in parameter
func (w *WifiScanner) GetCell(ssid string) *WifiCell {
for _, v := range w.Cells {
if v.Ssid == ssid {
return v
}
}
return nil
}
// Scan retreives a list of available wifi cells
func (w *WifiScanner) Scan() []*WifiCell {
_ = w.GetWifiCells()
return w.Cells
}

71
wifi_scanner_test.go Normal file
View File

@ -0,0 +1,71 @@
package owrt
import (
"fmt"
"io/ioutil"
"testing"
)
// Test GestWifiCells method with 3 Cells
func TestGetWifiCells(t *testing.T) {
cellList, err := ioutil.ReadFile("testdata/wifi_cells_output_3.txt")
if err != nil {
t.Fatal(err)
}
exec := createMockExecutor(string(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].MacAddress, "74:3e:2b:08:41:1c"; 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[1].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[2].Encryption, "psk2"; g != e {
t.Errorf("The last Cell have a bad Encryption!\n %s is expected and we have %s", e, g)
}
if g, e := wifi.Cells[2].MacAddress, "20:47:da:b7:0e:5c"; 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, err := ioutil.ReadFile("testdata/wifi_cells_output_large.txt")
if err != nil {
t.Fatal(err)
}
exec := createMockExecutor(string(cellList), "", 0)
wifi := NewWifiWithExecutor(exec, "wlan1")
_ = wifi.GetWifiCells()
if len(wifi.Cells) != 40 {
fmt.Printf("Size of wifi.Cells is %d and not 40 !!!\n", len(wifi.Cells))
t.Error("Cell list is empty ... This can not append !! Fix your code Dummy !")
}
}