diff --git a/.gitignore b/.gitignore index 5d683094c4e71e7bd3deab18a6ebaa8ee20b9475..f37dd8d0c8564a934bdffcc31bc3c8e65febccd0 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,10 @@ tags wifimngr .configured_* .pkgdir +*.html +*.gcda +*.gcov +*.gcno +*.log +*.so +*.xml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1578cf68f53ffe25ff25ccf97b19d2ca8077c7d1..9aa5d16459f791e992f421ac3920743b31ba85c4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,7 +4,52 @@ include: stages: - static_code_analysis - + - unit_test + - functional_test + - api_test + variables: DEBUG: 'TRUE' SOURCE_FOLDER: "." + +run_api_test: + stage: api_test + image: iopsys/code-analysis:0.7 + allow_failure: true + script: + - "./gitlab-ci/setup.sh" + - "./gitlab-ci/functional-api-test.sh" + + artifacts: + when: always + reports: + junit: ./report/tap.xml + paths: + - api-test-coverage.html + - api-test-memory-report.xml + +run_unit_test: + stage: unit_test + image: iopsys/code-analysis:0.7 + allow_failure: true + script: + - "./gitlab-ci/setup.sh" + - "./gitlab-ci/unit-test.sh" + + artifacts: + when: always + paths: + - unit-test-coverage.html + +run_functional_test: + stage: functional_test + image: iopsys/code-analysis:0.7 + allow_failure: true + script: + - "./gitlab-ci/setup.sh" + - "./gitlab-ci/functional-test.sh" + + artifacts: + when: always + paths: + - functional-test-coverage.html diff --git a/Makefile b/Makefile index 338959f786f958c3a1ebaa48408478a18a4e8661..abd25bb19b8c7dbc270ab9e22853b1e5996826d5 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,13 @@ +CC=gcc # gcc || clang PROG = wifimngr OBJS = wifimngr.o wps.o wifimngr_event.o main.o PROG_CFLAGS = $(CFLAGS) -Wall -fstrict-aliasing PROG_LDFLAGS = $(LDFLAGS) -PROG_LIBS = -leasy -lwifi-5 -PROG_LIBS += -luci -lubus -lubox -ljson-c -lblobmsg_json -lnl-genl-3 -lnl-3 +PROG_LIBS = -lwifi-5 +PROG_LIBS += -luci -lubus -lubox -ljson-c -lblobmsg_json -lnl-genl-3 -lnl-3 -lgcov -leasy +GCOV = gcov +CODECOVERAGE_SRC = wifimngr.c %.o: %.c $(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $< @@ -32,5 +35,25 @@ files.md5: wifimngr: $(OBJS) $(CC) $(PROG_LDFLAGS) -o $@ $^ $(PROG_LIBS) +test: CFLAGS += -fPIC +test: ${OBJS} + ${CC} ${LDFLAGS} -shared -o libwifimngr.so ${OBJS} ${LIBS} + +unit-test: coverage + make -C test/cmocka unit-test WIFIMNGR_LIB_DIR=$(PWD) + +functional-test: coverage + make -C test/cmocka functional-test WIFIMNGR_LIB_DIR=$(PWD) + +coverage: CFLAGS += -g -O0 -fprofile-arcs -ftest-coverage +coverage: LDFLAGS += --coverage +coverage: test wifimngr + $(foreach testprog, $(CODECOVERAGE_SRC), $(GCOV) $(testprog);) + clean: - rm -f *.o $(PROG) + rm -f *.o libwifimngr.so $(PROG) + rm -f *.xml *.html + find -name '*.gcda' -exec rm {} -fv \; + find -name '*.gcno' -exec rm {} -fv \; + find -name '*.gcov' -exec rm {} -fv \; + make -C test/cmocka clean diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..876c34decb955233d8a63bb480cee9d74eccd4c1 --- /dev/null +++ b/README.md @@ -0,0 +1,249 @@ +# Wifimngr + +Wifimngr implements the wifi data model, publishing the wifi objects over ubus. +In order to remain agnostic the vendor and underlying wifi modules present +in the system, wifimngr uses the easy-soc-libs libwifi APIs to expose supported +methods with its objects. + +<!--Wifimngr implements the wifi data model. It prepares the wifi objects and--> +<!--publishes them over ubus, the exposed methods are agnostic to the underlying--> +<!--wifi module present in the system. It uses the easy-soc-libs libwifi APIs to--> +<!--present the APIs over ubus.--> + +## Overview + +Wifimngr manages three areas of wifi functionality: +1. WiFi Statistics +2. Access Points +3. Radios +4. WiFi Protected Setup (WPS) + + +### UCI Config + +An example UCI wireless configuration file creating one access point interface, +`test5`: + +````bash +config wifi-device 'test5' + option channel 'auto' + option hwmode 'auto' + option country 'DE' + option band 'a' + option bandwidth '80' + +config wifi-iface + option device 'test5' + option ifname 'test5' + option mode 'ap' + option encryption 'psk2' +```` + +For more info on the UCI wireless configuration see [link](./docs/api/uci.wireless.md) + +### Ubus API + +This is a verbose print of all methods published to ubus on a device with one +access point interface `test5`: + +````bash +'wifi' @f2f72310 + "status":{} +'wifi.ap.test5' @57ac8570 + "status":{} + "stats":{} + "assoclist":{} + "stations":{"sta":"String"} + "disconnect":{"sta":"String"} + "monitor":{"sta":"String","get":"Integer"} + "add_neighbor":{"bssid":"String","channel":"Integer","bssid_info":"String","reg":"Integer","phy":"Integer"} + "del_neighbor":{"bssid":"String"} + "list_neighbor":{"ssid":"String","client":"String"} + "request_neighbor":{"ssid":"String","client":"String"} + "request_transition":{"client":"String","bssid":"Array","timeout":"Integer"} + "add_vendor_ie":{"mgmt":"Integer","oui":"String","data":"String"} + "del_vendor_ie":{"mgmt":"Integer","oui":"String","data":"String"} +'wifi.radio.test5' @e662e933 + "status":{} + "stats":{} + "get":{"param":"String"} + "scan":{"ssid":"String","bssid":"String","channel":"Integer"} + "scanresults":{"bssid":"String"} + "autochannel":{"interval":"Integer","algo":"Integer","scans":"Integer"} +'wifi.wps' @4eb8cbd8 + "start":{"vif":"String","mode":"String","role":"String","pin":"String"} + "stop":{} + "status":{"vif":"String"} + "generate_pin":{} + "validate_pin":{"pin":"String"} + "showpin":{"vif":"String"} + "setpin":{"vif":"String","pin":"String"} +```` + +For more info on the Ubus API see +[function specification](./docs/functionspec.md) or go directly to the generated +[docs](./docs/ubus.splash.md). + +### Wifi Statistics + +The `wifi` object publishes gathered radio and interface statistics. + +``` +'wifi' @f2f72310 + "status":{} +``` + +For info on the `wifi` API see [link](./docs/api/wifi.md#wifi) + +### Access Point + +An object will be published on ubus for each interface operating as an access +point, managing operations and data for wifi clients, neighbor nodes +and interface statistics. + +To parse access point interfaces, wifimngr reads the wireless +configuration file (`/etc/config/wireless`), looking for `wifi-iface` sections, +with the option `mode` specified as `ap`. + +``` +config wifi-iface + option device 'test5' + option ifname 'test5' + option mode 'ap' +``` + +Wifimngr will query libwifi to find available API calls for the driver, in order +to dynamically publish available methods to ubus. + +``` +root@:/opt/work# ubus -v list wifi.ap.test5 +'wifi.ap.test5' @a939a75c + "status":{} + "stats":{} + "assoclist":{} + "stations":{"sta":"String"} + "disconnect":{"sta":"String"} + "monitor":{"sta":"String","get":"Integer"} + "add_neighbor":{"bssid":"String","channel":"Integer","bssid_info":"String","reg":"Integer","phy":"Integer"} + "del_neighbor":{"bssid":"String"} + "list_neighbor":{"ssid":"String","client":"String"} + "request_neighbor":{"ssid":"String","client":"String"} + "request_transition":{"client":"String","bssid":"Array","timeout":"Integer"} + "add_vendor_ie":{"mgmt":"Integer","oui":"String","data":"String"} + "del_vendor_ie":{"mgmt":"Integer","oui":"String","data":"String"} +``` + +For info on the access point API see [link](./docs/api/wifi.ap.md#wifiapname) + +### Radio + +Similarily to access point interfaces, wifimngr will publish one object per +available radio, parsed from the wireless configuration, by `wifi-device` +sections. The methods are added dynamically by quering for supported API calls +from libwifi. + +``` +config wifi-device 'test5' + option channel 'auto' + option hwmode 'auto' + option country 'DE' + option band 'a' + option bandwidth '80' +``` + +The radio object manages radio data and statistics, channel selection and +wifi scan operations. + +``` +root@:/opt/work# ubus -v list wifi.radio.test5 +'wifi.radio.test5' @fa7d185d + "status":{} + "stats":{} + "get":{"param":"String"} + "scan":{"ssid":"String","bssid":"String","channel":"Integer"} + "scanresults":{"bssid":"String"} + "autochannel":{"interval":"Integer","algo":"Integer","scans":"Integer"} +``` +For info on the radio API see [link](./docs/api/wifi.radio.md#wifiradioname) + +### Wifi Protected Setup + +Lastly, wifimngr exposes WPS functionality to ubus. + +The configuration is read from the `/etc/config/wireless`. To enable WPS the +`wps` option has to be set to `1`. + +``` +config wifi-iface + option wps '1' +``` + +To see more configuration options see [link](./docs/api/uci.wireless.md), +under the `wifi-iface` section. + + +``` +root@:/opt/work# ubus -v list wifi.wps +'wifi.wps' @78c52f3b + "start":{"vif":"String","mode":"String","role":"String","pin":"String"} + "stop":{} + "status":{"vif":"String"} + "generate_pin":{} + "validate_pin":{"pin":"String"} + "showpin":{"vif":"String"} + "setpin":{"vif":"String","pin":"String"} +``` + +For info on the WPS API see [link](./docs/api/wifi.wps.md#wifiwps) + + +## Tests + +This section will give a brief overview of the tests for wifimngr, for a more +detailed report see [test specification](./docs/testspec.md) + +To test wifimngr, the scope of the tests has to be clearly defined, as wifimngr +is heavily dependent on libwifi: + +1. Verify linkage between wifimngr and libwifi APIs +2. Verify that the wifi structures are correctly prepared and return data is +used correctly by wifimngr +3. Verify that API calls successfully reach libwifi and if passed input is of +correct format + +As the test environment runs in a ubuntu 16.04 docker environment, with little +possibility to prepare wifi drivers and kernel version, the easy-soc-libs had to +be extended to support APIs to run on a test platform, returning dummy data for +getters, and for setters, logging that the call made with timestamp and +arguments. + +To ensure full coverage, the getters are tested by the ubus-api-validation tool, +using json-schemas to validate accurate output. The setters are tested by cmocka +tests, creating a libwifimngr.so shared library, invoking its ubus API +functions directly, verifying that the call went through, and that the arguments +were passed correctly, by parsing the test log file found at `/tmp/test.log`. +Additionally, the cmocka tests verify that netlink event callbacks are +registered and invoked. + +## Dependencies ## + +To successfully build wifimngr, the following libraries are needed: + +| Dependency | Link | License | +| ----------------- | ---------------------------------------------------------------- | -------------- | +| libuci | https://git.openwrt.org/project/uci.git | LGPL 2.1 | +| libubox | https://git.openwrt.org/project/libubox.git | BSD | +| libubus | https://git.openwrt.org/project/ubus.git | LGPL 2.1 | +| libjson-c | https://s3.amazonaws.com/json-c_releases | MIT | +| libwifi | https://dev.iopsys.eu/iopsys/easy-soc-libs/tree/devel/libwifi | GNU GPL2 | +| libnl3 | | | +| libblobmsg_json | | | +| libnl-genl | | | + +Additionally, in order to build with the tests, the following libraries are needed: + +| Dependency | Link | License | +| ------------------------- | --------------------------------------------------------- | ------------- | +| libjson-schema-validator | https://github.com/pboettch/json-schema-validator | LGPL 2.1 | +| libjson-validator | https://dev.iopsys.eu/iopsys/json-schema-validator | | +| libjson-editor | https://dev.iopsys.eu/iopsys/json-editor | | diff --git a/docs/api/uci.wireless.md b/docs/api/uci.wireless.md new file mode 100644 index 0000000000000000000000000000000000000000..f139af86b4975a126b6a479b6771f9902e1b2170 --- /dev/null +++ b/docs/api/uci.wireless.md @@ -0,0 +1 @@ +<tbody><tr><td colspan="2"><div class="td_head">wireless</div><table style="width:100%"><tbody><tr><td><div class="td_head">section</div></td><td><div class="td_head">description</div></td><td><div class="td_head">multi</div></td><td><div class="td_head">options</div></td></tr><tr><td class="td_row_even"><div class="td_row_even">wifi-device</div></td><td class="td_row_even"><div class="td_row_even">Wifi Device Settings</div></td><td class="td_row_even"><div class="td_row_even">true</div></td><td class="td_row_even"><table style="width:100%"><tbody><tr><td><div class="td_head">name</div></td><td><div class="td_head">type</div></td><td><div class="td_head">required</div></td><td><div class="td_head">default</div></td><td><div class="td_head">description</div></td></tr><tr><td class="td_row_even"><div class="td_row_even">channel</div></td><td class="td_row_even"><div class="td_row_even">integer or “auto”</div></td><td class="td_row_even"><div class="td_row_even">yes</div></td><td class="td_row_even"><div class="td_row_even">auto</div></td><td class="td_row_even"><div class="td_row_even">Specifies the wireless channel to use. “auto” defaults to the lowest available channel.</div></td></tr><tr><td class="td_row_odd"><div class="td_row_odd">hwmode</div></td><td class="td_row_odd"><div class="td_row_odd">string</div></td><td class="td_row_odd"><div class="td_row_odd"> </div></td><td class="td_row_odd"><table style="width:100%"></table></td><td class="td_row_odd"><div class="td_row_odd">Selects the wireless protocol to use, possible values are 11b, 11g, and 11a. Note that 11ng and 11na are not available options.</div></td></tr><tr><td class="td_row_even"><div class="td_row_even">country</div></td><td class="td_row_even"><div class="td_row_even">varies</div></td><td class="td_row_even"><div class="td_row_even"> </div></td><td class="td_row_even"><table style="width:100%"></table></td><td class="td_row_even"><div class="td_row_even">Specifies the country code, affects the available channels and transmission powers. For type broadcom a two letter country code is used (EN or DE). The madwifi driver expects a numeric code.</div></td></tr><tr><td class="td_row_odd"><div class="td_row_odd">band</div></td><td class="td_row_odd"><div class="td_row_odd">string</div></td><td class="td_row_odd"><div class="td_row_odd"> </div></td><td class="td_row_odd"><table style="width:100%"></table></td><td class="td_row_odd"><div class="td_row_odd">Whether radio operates at 2.4GHz or 5GHz.</div></td></tr><tr><td class="td_row_even"><div class="td_row_even">bandwidth</div></td><td class="td_row_even"><div class="td_row_even">integer</div></td><td class="td_row_even"><div class="td_row_even"> </div></td><td class="td_row_even"><div class="td_row_even">80</div></td><td class="td_row_even"><div class="td_row_even">Frequency at which the radio operates.</div></td></tr></tbody></table></td></tr><tr><td class="td_row_odd"><div class="td_row_odd">wifi-iface</div></td><td class="td_row_odd"><div class="td_row_odd">Wifi Interface Settings</div></td><td class="td_row_odd"><div class="td_row_odd">true</div></td><td class="td_row_odd"><table style="width:100%"><tbody><tr><td><div class="td_head">name</div></td><td><div class="td_head">type</div></td><td><div class="td_head">required</div></td><td><div class="td_head">default</div></td><td><div class="td_head">description</div></td></tr><tr><td class="td_row_even"><div class="td_row_even">device</div></td><td class="td_row_even"><div class="td_row_even">string</div></td><td class="td_row_even"><div class="td_row_even">yes</div></td><td class="td_row_even"><div class="td_row_even">(first device id)</div></td><td class="td_row_even"><div class="td_row_even">Specifies the used wireless adapter, must refer to one of the defined wifi-device sections</div></td></tr><tr><td class="td_row_odd"><div class="td_row_odd">ifname</div></td><td class="td_row_odd"><div class="td_row_odd">string</div></td><td class="td_row_odd"><div class="td_row_odd">no</div></td><td class="td_row_odd"><div class="td_row_odd">(driver default)</div></td><td class="td_row_odd"><div class="td_row_odd">Specifies a custom name for the Wi-Fi interface, which is otherwise automatically named.</div></td></tr><tr><td class="td_row_even"><div class="td_row_even">mode</div></td><td class="td_row_even"><div class="td_row_even">string</div></td><td class="td_row_even"><div class="td_row_even">yes</div></td><td class="td_row_even"><div class="td_row_even">ap</div></td><td class="td_row_even"><div class="td_row_even">Selects the operation mode of the wireless network interface controller. Possible values are ap, sta, adhoc, wds, monitor, mesh</div></td></tr><tr><td class="td_row_odd"><div class="td_row_odd">encryption</div></td><td class="td_row_odd"><div class="td_row_odd">string</div></td><td class="td_row_odd"><div class="td_row_odd"> </div></td><td class="td_row_odd"><table style="width:100%"></table></td><td class="td_row_odd"><div class="td_row_odd">Wireless encryption method. Possible values are: none, wep, psk, psk2. For WEP station mode the default is “open system” authentication. Use wep+shared or wep+open to force a specific mode.</div></td></tr></tbody></table></td></tr></tbody></table></td></tr></tbody> \ No newline at end of file diff --git a/docs/api/wifi.ap.md b/docs/api/wifi.ap.md new file mode 100644 index 0000000000000000000000000000000000000000..b16174307f6aec6c2bda2860578c50ca9937fd90 --- /dev/null +++ b/docs/api/wifi.ap.md @@ -0,0 +1,3646 @@ +# wifi.ap.<name> Schema + +``` +https://www.iopsys.eu/wifi.ap.json +``` + +| Custom Properties | Additional Properties | +| ----------------- | --------------------- | +| Forbidden | Forbidden | + +# wifi.ap.<name> + +| List of Methods | +| ----------------------------------------- | +| [add_neighbor](#add_neighbor) | Method | wifi.ap.<name> (this schema) | +| [add_vendor_ie](#add_vendor_ie) | Method | wifi.ap.<name> (this schema) | +| [assoclist](#assoclist) | Method | wifi.ap.<name> (this schema) | +| [del_neighbor](#del_neighbor) | Method | wifi.ap.<name> (this schema) | +| [del_vendor_ie](#del_vendor_ie) | Method | wifi.ap.<name> (this schema) | +| [disconnect](#disconnect) | Method | wifi.ap.<name> (this schema) | +| [list_neighbor](#list_neighbor) | Method | wifi.ap.<name> (this schema) | +| [monitor](#monitor) | Method | wifi.ap.<name> (this schema) | +| [request_neighbor](#request_neighbor) | Method | wifi.ap.<name> (this schema) | +| [request_transition](#request_transition) | Method | wifi.ap.<name> (this schema) | +| [stations](#stations) | Method | wifi.ap.<name> (this schema) | +| [stats](#stats) | Method | wifi.ap.<name> (this schema) | +| [status](#status) | Method | wifi.ap.<name> (this schema) | + +## add_neighbor + +`add_neighbor` + +- type: `Method` + +### add_neighbor Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| ------------ | ------- | ------------ | +| `bssid` | string | **Required** | +| `bssid_info` | string | **Required** | +| `channel` | oneOf | **Required** | +| `phy` | integer | **Required** | +| `reg` | integer | **Required** | + +#### bssid + +##### MAC Address + +`bssid` + +- is **required** +- type: reference + +##### bssid Type + +`string` + +- minimum length: 17 characters +- maximum length: 17 characters All instances must conform to this regular expression (test examples + [here](<https://regexr.com/?expression=%5E(%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%3A)%7B5%7D%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%24>)): + +```regex +^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$ +``` + +#### bssid_info + +`bssid_info` + +- is **required** +- type: `string` + +##### bssid_info Type + +`string` + +#### channel + +`channel` + +- is **required** +- type: complex + +##### channel Type + +**One** of the following _conditions_ need to be fulfilled. + +#### Condition 1 + +`integer` + +- minimum value: `1` +- maximum value: `14` + +#### Condition 2 + +`integer` + +- minimum value: `32` +- maximum value: `200` + +#### phy + +`phy` + +- is **required** +- type: `integer` + +##### phy Type + +`integer` + +- minimum value: `0` + +#### reg + +`reg` + +- is **required** +- type: `integer` + +##### reg Type + +`integer` + +- minimum value: `0` + +### Ubus CLI Example + +``` +ubus call wifi.ap.<name> add_neighbor {"bssid":"7D:AF:d4:61:7D:15","channel":148,"bssid_info":"exercitation pariatur labore","reg":55128803,"phy":5160466} +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": [ + "<SID>", + "wifi.ap.<name>", + "add_neighbor", + { + "bssid": "7D:AF:d4:61:7D:15", + "channel": 148, + "bssid_info": "exercitation pariatur labore", + "reg": 55128803, + "phy": 5160466 + } + ] +} +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Output Example + +```json +{} +``` + +## add_vendor_ie + +`add_vendor_ie` + +- type: `Method` + +### add_vendor_ie Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------- | ------------ | +| `data` | string | **Required** | +| `mgmt` | integer | **Required** | +| `oui` | string | **Required** | + +#### data + +##### Hex String + +`data` + +- is **required** +- type: reference + +##### data Type + +`string` + +All instances must conform to this regular expression (test examples +[here](https://regexr.com/?expression=%5E%5B0-9a-fA-F%5D%2B)): + +```regex +^[0-9a-fA-F]+ +``` + +#### mgmt + +`mgmt` + +- is **required** +- type: `integer` + +##### mgmt Type + +`integer` + +#### oui + +##### Three byte oui + +`oui` + +- is **required** +- type: reference + +##### oui Type + +`string` + +- minimum length: 9 characters +- maximum length: 9 characters All instances must conform to this regular expression (test examples + [here](<https://regexr.com/?expression=%5E(%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D)%7B3%7D%24>)): + +```regex +^([0-9a-fA-F][0-9a-fA-F]){3}$ +``` + +### Ubus CLI Example + +``` +ubus call wifi.ap.<name> add_vendor_ie {"mgmt":-95722701,"oui":"b79aaDC49","data":"aAb9"} +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": ["<SID>", "wifi.ap.<name>", "add_vendor_ie", { "mgmt": -95722701, "oui": "b79aaDC49", "data": "aAb9" }] +} +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Output Example + +```json +{} +``` + +## assoclist + +`assoclist` + +- type: `Method` + +### assoclist Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Ubus CLI Example + +``` +ubus call wifi.ap.<name> assoclist {} +``` + +### JSONRPC Example + +```json +{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["<SID>", "wifi.ap.<name>", "assoclist", {}] } +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| ----------- | ----- | ------------ | +| `assoclist` | array | **Required** | + +#### assoclist + +`assoclist` + +- is **required** +- type: `object[]` + +##### assoclist Type + +Array type: `object[]` + +All items must be of the type: `object` with following properties: + +| Property | Type | Required | +| --------- | ------ | ------------ | +| `macaddr` | string | **Required** | +| `wdev` | string | **Required** | + +#### macaddr + +##### MAC Address + +`macaddr` + +- is **required** +- type: reference + +##### macaddr Type + +`string` + +- minimum length: 17 characters +- maximum length: 17 characters All instances must conform to this regular expression (test examples + [here](<https://regexr.com/?expression=%5E(%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%3A)%7B5%7D%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%24>)): + +```regex +^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$ +``` + +#### wdev + +##### Interface + +`wdev` + +- is **required** +- type: reference + +##### wdev Type + +`string` + +- minimum length: 1 characters +- maximum length: 16 characters + +### Output Example + +```json +{ + "assoclist": [ + { "wdev": "eu ex veniam", "macaddr": "95:BB:cd:F3:d8:6d" }, + { "wdev": "nisi", "macaddr": "65:6C:7b:43:D3:FC" }, + { "wdev": "commodo velit a", "macaddr": "9F:d4:4D:D0:F1:A4" }, + { "wdev": "qui ", "macaddr": "ED:D7:49:aC:c5:10" }, + { "wdev": "in et o", "macaddr": "14:69:A2:AC:f6:49" } + ] +} +``` + +## del_neighbor + +`del_neighbor` + +- type: `Method` + +### del_neighbor Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | ------------ | +| `bssid` | string | **Required** | + +#### bssid + +##### MAC Address + +`bssid` + +- is **required** +- type: reference + +##### bssid Type + +`string` + +- minimum length: 17 characters +- maximum length: 17 characters All instances must conform to this regular expression (test examples + [here](<https://regexr.com/?expression=%5E(%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%3A)%7B5%7D%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%24>)): + +```regex +^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$ +``` + +### Ubus CLI Example + +``` +ubus call wifi.ap.<name> del_neighbor {"bssid":"7E:d5:c5:D2:a8:Bd"} +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": ["<SID>", "wifi.ap.<name>", "del_neighbor", { "bssid": "7E:d5:c5:D2:a8:Bd" }] +} +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Output Example + +```json +{} +``` + +## del_vendor_ie + +`del_vendor_ie` + +- type: `Method` + +### del_vendor_ie Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `intput` | object | Optional | +| `output` | object | Optional | + +#### intput + +`intput` + +- is optional +- type: `object` + +##### intput Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------- | ------------ | +| `data` | string | **Required** | +| `mgmt` | integer | **Required** | +| `oui` | string | **Required** | + +#### data + +##### Hex String + +`data` + +- is **required** +- type: reference + +##### data Type + +`string` + +All instances must conform to this regular expression (test examples +[here](https://regexr.com/?expression=%5E%5B0-9a-fA-F%5D%2B)): + +```regex +^[0-9a-fA-F]+ +``` + +#### mgmt + +`mgmt` + +- is **required** +- type: `integer` + +##### mgmt Type + +`integer` + +#### oui + +##### Three byte oui + +`oui` + +- is **required** +- type: reference + +##### oui Type + +`string` + +- minimum length: 9 characters +- maximum length: 9 characters All instances must conform to this regular expression (test examples + [here](<https://regexr.com/?expression=%5E(%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D)%7B3%7D%24>)): + +```regex +^([0-9a-fA-F][0-9a-fA-F]){3}$ +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Output Example + +```json +{} +``` + +## disconnect + +`disconnect` + +- type: `Method` + +### disconnect Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | ------------ | +| `sta` | string | **Required** | + +#### sta + +##### MAC Address + +`sta` + +- is **required** +- type: reference + +##### sta Type + +`string` + +- minimum length: 17 characters +- maximum length: 17 characters All instances must conform to this regular expression (test examples + [here](<https://regexr.com/?expression=%5E(%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%3A)%7B5%7D%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%24>)): + +```regex +^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$ +``` + +### Ubus CLI Example + +``` +ubus call wifi.ap.<name> disconnect {"sta":"62:Ec:Ff:09:FB:42"} +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": ["<SID>", "wifi.ap.<name>", "disconnect", { "sta": "62:Ec:Ff:09:FB:42" }] +} +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Output Example + +```json +{} +``` + +## list_neighbor + +`list_neighbor` + +- type: `Method` + +### list_neighbor Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `client` | string | Optional | +| `ssid` | string | Optional | + +#### client + +##### MAC Address + +`client` + +- is optional +- type: reference + +##### client Type + +`string` + +- minimum length: 17 characters +- maximum length: 17 characters All instances must conform to this regular expression (test examples + [here](<https://regexr.com/?expression=%5E(%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%3A)%7B5%7D%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%24>)): + +```regex +^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$ +``` + +#### ssid + +##### SSID + +`ssid` + +- is optional +- type: reference + +##### ssid Type + +`string` + +- maximum length: 32 characters + +### Ubus CLI Example + +``` +ubus call wifi.ap.<name> list_neighbor {"ssid":"est commodo c","client":"ed:4F:78:BB:F6:00"} +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": ["<SID>", "wifi.ap.<name>", "list_neighbor", { "ssid": "est commodo c", "client": "ed:4F:78:BB:F6:00" }] +} +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Output Example + +```json +{ "neighbors": "dolore sint" } +``` + +## monitor + +`monitor` + +- type: `Method` + +### monitor Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `intput` | object | Optional | +| `output` | object | Optional | + +#### intput + +`intput` + +- is optional +- type: `object` + +##### intput Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------- | ------------ | +| `get` | integer | Optional | +| `sta` | string | **Required** | + +#### get + +`get` + +- is optional +- type: `integer` + +##### get Type + +`integer` + +#### sta + +##### MAC Address + +`sta` + +- is **required** +- type: reference + +##### sta Type + +`string` + +- minimum length: 17 characters +- maximum length: 17 characters All instances must conform to this regular expression (test examples + [here](<https://regexr.com/?expression=%5E(%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%3A)%7B5%7D%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%24>)): + +```regex +^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$ +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Output Example + +```json +{} +``` + +## request_neighbor + +`request_neighbor` + +- type: `Method` + +### request_neighbor Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | ------------ | +| `client` | string | **Required** | +| `ssid` | string | Optional | + +#### client + +##### MAC Address + +`client` + +- is **required** +- type: reference + +##### client Type + +`string` + +- minimum length: 17 characters +- maximum length: 17 characters All instances must conform to this regular expression (test examples + [here](<https://regexr.com/?expression=%5E(%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%3A)%7B5%7D%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%24>)): + +```regex +^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$ +``` + +#### ssid + +##### SSID + +`ssid` + +- is optional +- type: reference + +##### ssid Type + +`string` + +- maximum length: 32 characters + +### Ubus CLI Example + +``` +ubus call wifi.ap.<name> request_neighbor {"client":"Fc:2A:3f:71:Bb:c4","ssid":"aliqua ut Excepteur"} +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": [ + "<SID>", + "wifi.ap.<name>", + "request_neighbor", + { "client": "Fc:2A:3f:71:Bb:c4", "ssid": "aliqua ut Excepteur" } + ] +} +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Output Example + +```json +{} +``` + +## request_transition + +`request_transition` + +- type: `Method` + +### request_transition Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| --------- | ------- | ------------ | +| `bssid` | array | **Required** | +| `client` | string | **Required** | +| `timeout` | integer | Optional | + +#### bssid + +`bssid` + +- is **required** +- type: reference + +##### bssid Type + +Array type: reference + +All items must be of the type: `string` + +- minimum length: 17 characters +- maximum length: 17 characters All instances must conform to this regular expression (test examples + [here](<https://regexr.com/?expression=%5E(%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%3A)%7B5%7D%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%24>)): + +```regex +^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$ +``` + +#### client + +##### MAC Address + +`client` + +- is **required** +- type: reference + +##### client Type + +`string` + +- minimum length: 17 characters +- maximum length: 17 characters All instances must conform to this regular expression (test examples + [here](<https://regexr.com/?expression=%5E(%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%3A)%7B5%7D%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%24>)): + +```regex +^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$ +``` + +#### timeout + +`timeout` + +- is optional +- type: `integer` + +##### timeout Type + +`integer` + +### Ubus CLI Example + +``` +ubus call wifi.ap.<name> request_transition {"client":"b9:0B:De:Dd:8C:De","bssid":["13:a3:F7:32:cA:a1","68:7f:6f:d1:eb:A0","CB:0D:E8:BD:a7:e0","4F:cA:23:87:bC:96","8b:f8:dc:FD:1A:c7"],"timeout":-38008176} +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": [ + "<SID>", + "wifi.ap.<name>", + "request_transition", + { + "client": "b9:0B:De:Dd:8C:De", + "bssid": [ + "13:a3:F7:32:cA:a1", + "68:7f:6f:d1:eb:A0", + "CB:0D:E8:BD:a7:e0", + "4F:cA:23:87:bC:96", + "8b:f8:dc:FD:1A:c7" + ], + "timeout": -38008176 + } + ] +} +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Output Example + +```json +{} +``` + +## stations + +`stations` + +- type: `Method` + +### stations Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `sta` | string | Optional | + +#### sta + +##### MAC Address + +`sta` + +- is optional +- type: reference + +##### sta Type + +`string` + +- minimum length: 17 characters +- maximum length: 17 characters All instances must conform to this regular expression (test examples + [here](<https://regexr.com/?expression=%5E(%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%3A)%7B5%7D%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%24>)): + +```regex +^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$ +``` + +### Ubus CLI Example + +``` +ubus call wifi.ap.<name> stations {"sta":"bD:a6:8E:e1:B1:0F"} +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": ["<SID>", "wifi.ap.<name>", "stations", { "sta": "bD:a6:8E:e1:B1:0F" }] +} +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| ---------- | ----- | ------------ | +| `stations` | array | **Required** | + +#### stations + +`stations` + +- is **required** +- type: `object[]` + +##### stations Type + +Array type: `object[]` + +All items must be of the type: `object` with following properties: + +| Property | Type | Required | +| ------------------ | ------- | ------------ | +| `airtime` | integer | **Required** | +| `capabilities` | object | **Required** | +| `frequency` | string | **Required** | +| `idle` | integer | **Required** | +| `in_network` | integer | **Required** | +| `macaddr` | string | **Required** | +| `max_rate` | integer | **Required** | +| `rssi` | integer | **Required** | +| `rssi_per_antenna` | array | **Required** | +| `rx_airtime` | integer | **Required** | +| `snr` | integer | **Required** | +| `stats` | object | **Required** | +| `status` | object | **Required** | +| `tx_airtime` | integer | **Required** | +| `wdev` | string | **Required** | + +#### airtime + +`airtime` + +- is **required** +- type: `integer` + +##### airtime Type + +`integer` + +- minimum value: `0` +- maximum value: `100` + +#### capabilities + +`capabilities` + +- is **required** +- type: `object` + +##### capabilities Type + +`object` with following properties: + +| Property | Type | Required | +| ------------ | ------- | ------------ | +| `2040coex` | boolean | **Required** | +| `apsd` | boolean | **Required** | +| `dot11ac` | object | Optional | +| `dot11h` | boolean | **Required** | +| `dot11k` | object | Optional | +| `dot11n` | object | Optional | +| `dot11v_btm` | boolean | **Required** | +| `proxy_arp` | boolean | **Required** | +| `psmp` | boolean | **Required** | +| `shortslot` | boolean | **Required** | +| `wmm` | boolean | **Required** | + +#### 2040coex + +`2040coex` + +- is **required** +- type: `boolean` + +##### 2040coex Type + +`boolean` + +#### apsd + +`apsd` + +- is **required** +- type: `boolean` + +##### apsd Type + +`boolean` + +#### dot11ac + +`dot11ac` + +- is optional +- type: `object` + +##### dot11ac Type + +`object` with following properties: + +| Property | Type | Required | +| ----------------------- | ------- | ------------ | +| `dot11ac_160` | boolean | **Required** | +| `dot11ac_8080` | boolean | **Required** | +| `dot11ac_mpdu_max` | integer | **Required** | +| `dot11ac_mu_beamformee` | boolean | **Required** | +| `dot11ac_mu_beamformer` | boolean | **Required** | +| `dot11ac_rx_ldpc` | boolean | **Required** | +| `dot11ac_rx_stbc_1ss` | boolean | **Required** | +| `dot11ac_rx_stbc_2ss` | boolean | **Required** | +| `dot11ac_rx_stbc_3ss` | boolean | **Required** | +| `dot11ac_rx_stbc_4ss` | boolean | **Required** | +| `dot11ac_sgi160` | boolean | **Required** | +| `dot11ac_sgi80` | boolean | **Required** | +| `dot11ac_su_beamformee` | boolean | **Required** | +| `dot11ac_su_beamformer` | boolean | **Required** | +| `dot11ac_tx_stbc` | boolean | **Required** | + +#### dot11ac_160 + +`dot11ac_160` + +- is **required** +- type: `boolean` + +##### dot11ac_160 Type + +`boolean` + +#### dot11ac_8080 + +`dot11ac_8080` + +- is **required** +- type: `boolean` + +##### dot11ac_8080 Type + +`boolean` + +#### dot11ac_mpdu_max + +`dot11ac_mpdu_max` + +- is **required** +- type: `integer` + +##### dot11ac_mpdu_max Type + +`integer` + +- minimum value: `0` +- maximum value: `65535` + +#### dot11ac_mu_beamformee + +`dot11ac_mu_beamformee` + +- is **required** +- type: `boolean` + +##### dot11ac_mu_beamformee Type + +`boolean` + +#### dot11ac_mu_beamformer + +`dot11ac_mu_beamformer` + +- is **required** +- type: `boolean` + +##### dot11ac_mu_beamformer Type + +`boolean` + +#### dot11ac_rx_ldpc + +`dot11ac_rx_ldpc` + +- is **required** +- type: `boolean` + +##### dot11ac_rx_ldpc Type + +`boolean` + +#### dot11ac_rx_stbc_1ss + +`dot11ac_rx_stbc_1ss` + +- is **required** +- type: `boolean` + +##### dot11ac_rx_stbc_1ss Type + +`boolean` + +#### dot11ac_rx_stbc_2ss + +`dot11ac_rx_stbc_2ss` + +- is **required** +- type: `boolean` + +##### dot11ac_rx_stbc_2ss Type + +`boolean` + +#### dot11ac_rx_stbc_3ss + +`dot11ac_rx_stbc_3ss` + +- is **required** +- type: `boolean` + +##### dot11ac_rx_stbc_3ss Type + +`boolean` + +#### dot11ac_rx_stbc_4ss + +`dot11ac_rx_stbc_4ss` + +- is **required** +- type: `boolean` + +##### dot11ac_rx_stbc_4ss Type + +`boolean` + +#### dot11ac_sgi160 + +`dot11ac_sgi160` + +- is **required** +- type: `boolean` + +##### dot11ac_sgi160 Type + +`boolean` + +#### dot11ac_sgi80 + +`dot11ac_sgi80` + +- is **required** +- type: `boolean` + +##### dot11ac_sgi80 Type + +`boolean` + +#### dot11ac_su_beamformee + +`dot11ac_su_beamformee` + +- is **required** +- type: `boolean` + +##### dot11ac_su_beamformee Type + +`boolean` + +#### dot11ac_su_beamformer + +`dot11ac_su_beamformer` + +- is **required** +- type: `boolean` + +##### dot11ac_su_beamformer Type + +`boolean` + +#### dot11ac_tx_stbc + +`dot11ac_tx_stbc` + +- is **required** +- type: `boolean` + +##### dot11ac_tx_stbc Type + +`boolean` + +#### dot11h + +`dot11h` + +- is **required** +- type: `boolean` + +##### dot11h Type + +`boolean` + +#### dot11k + +`dot11k` + +- is optional +- type: `object` + +##### dot11k Type + +`object` with following properties: + +| Property | Type | Required | +| -------------------- | ------- | ------------ | +| `dot11k_bcn_active` | boolean | **Required** | +| `dot11k_bcn_passive` | boolean | **Required** | +| `dot11k_bcn_table` | boolean | **Required** | +| `dot11k_link_meas` | boolean | **Required** | +| `dot11k_nbr_report` | boolean | **Required** | +| `dot11k_rcpi` | boolean | **Required** | +| `dot11k_rsni` | boolean | **Required** | + +#### dot11k_bcn_active + +`dot11k_bcn_active` + +- is **required** +- type: `boolean` + +##### dot11k_bcn_active Type + +`boolean` + +#### dot11k_bcn_passive + +`dot11k_bcn_passive` + +- is **required** +- type: `boolean` + +##### dot11k_bcn_passive Type + +`boolean` + +#### dot11k_bcn_table + +`dot11k_bcn_table` + +- is **required** +- type: `boolean` + +##### dot11k_bcn_table Type + +`boolean` + +#### dot11k_link_meas + +`dot11k_link_meas` + +- is **required** +- type: `boolean` + +##### dot11k_link_meas Type + +`boolean` + +#### dot11k_nbr_report + +`dot11k_nbr_report` + +- is **required** +- type: `boolean` + +##### dot11k_nbr_report Type + +`boolean` + +#### dot11k_rcpi + +`dot11k_rcpi` + +- is **required** +- type: `boolean` + +##### dot11k_rcpi Type + +`boolean` + +#### dot11k_rsni + +`dot11k_rsni` + +- is **required** +- type: `boolean` + +##### dot11k_rsni Type + +`boolean` + +#### dot11n + +`dot11n` + +- is optional +- type: `object` + +##### dot11n Type + +`object` with following properties: + +| Property | Type | Required | +| ---------------- | ------- | ------------ | +| `dot11n_40` | boolean | **Required** | +| `dot11n_ldpc` | boolean | **Required** | +| `dot11n_ps` | boolean | **Required** | +| `dot11n_rx_stbc` | boolean | **Required** | +| `dot11n_sgi20` | boolean | **Required** | +| `dot11n_sgi40` | boolean | **Required** | +| `dot11n_tx_stbc` | boolean | **Required** | + +#### dot11n_40 + +`dot11n_40` + +- is **required** +- type: `boolean` + +##### dot11n_40 Type + +`boolean` + +#### dot11n_ldpc + +`dot11n_ldpc` + +- is **required** +- type: `boolean` + +##### dot11n_ldpc Type + +`boolean` + +#### dot11n_ps + +`dot11n_ps` + +- is **required** +- type: `boolean` + +##### dot11n_ps Type + +`boolean` + +#### dot11n_rx_stbc + +`dot11n_rx_stbc` + +- is **required** +- type: `boolean` + +##### dot11n_rx_stbc Type + +`boolean` + +#### dot11n_sgi20 + +`dot11n_sgi20` + +- is **required** +- type: `boolean` + +##### dot11n_sgi20 Type + +`boolean` + +#### dot11n_sgi40 + +`dot11n_sgi40` + +- is **required** +- type: `boolean` + +##### dot11n_sgi40 Type + +`boolean` + +#### dot11n_tx_stbc + +`dot11n_tx_stbc` + +- is **required** +- type: `boolean` + +##### dot11n_tx_stbc Type + +`boolean` + +#### dot11v_btm + +`dot11v_btm` + +- is **required** +- type: `boolean` + +##### dot11v_btm Type + +`boolean` + +#### proxy_arp + +`proxy_arp` + +- is **required** +- type: `boolean` + +##### proxy_arp Type + +`boolean` + +#### psmp + +`psmp` + +- is **required** +- type: `boolean` + +##### psmp Type + +`boolean` + +#### shortslot + +`shortslot` + +- is **required** +- type: `boolean` + +##### shortslot Type + +`boolean` + +#### wmm + +`wmm` + +- is **required** +- type: `boolean` + +##### wmm Type + +`boolean` + +#### frequency + +##### WiFi Band + +`frequency` + +- is **required** +- type: reference + +##### frequency Type + +`string` + +The value of this property **must** be equal to one of the [known values below](#stations-known-values). + +##### frequency Known Values + +| Value | +| ----- | +| 2GHz | +| 5GHz | + +#### idle + +`idle` + +- is **required** +- type: `integer` + +##### idle Type + +`integer` + +- minimum value: `0` + +#### in_network + +`in_network` + +- is **required** +- type: `integer` + +##### in_network Type + +`integer` + +- minimum value: `0` + +#### macaddr + +##### MAC Address + +`macaddr` + +- is **required** +- type: reference + +##### macaddr Type + +`string` + +- minimum length: 17 characters +- maximum length: 17 characters All instances must conform to this regular expression (test examples + [here](<https://regexr.com/?expression=%5E(%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%3A)%7B5%7D%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%24>)): + +```regex +^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$ +``` + +#### max_rate + +`max_rate` + +- is **required** +- type: `integer` + +##### max_rate Type + +`integer` + +- minimum value: `0` + +#### rssi + +##### RSSI + +`rssi` + +- is **required** +- type: reference + +##### rssi Type + +`integer` + +- minimum value: `-128` +- maximum value: `0` + +#### rssi_per_antenna + +`rssi_per_antenna` + +- is **required** +- type: reference + +##### rssi_per_antenna Type + +Array type: reference + +All items must be of the type: `integer` + +- minimum value: `-128` +- maximum value: `0` + +#### rx_airtime + +`rx_airtime` + +- is **required** +- type: `integer` + +##### rx_airtime Type + +`integer` + +- minimum value: `0` +- maximum value: `100` + +#### snr + +`snr` + +- is **required** +- type: `integer` + +##### snr Type + +`integer` + +- minimum value: `0` +- maximum value: `100` + +#### stats + +`stats` + +- is **required** +- type: `object` + +##### stats Type + +`object` with following properties: + +| Property | Type | Required | +| --------------------- | ------- | ------------ | +| `rate_of_last_rx_pkt` | integer | **Required** | +| `rate_of_last_tx_pkt` | integer | **Required** | +| `rx_data_bytes` | integer | **Required** | +| `rx_data_pkts` | integer | **Required** | +| `rx_failures` | integer | **Required** | +| `tx_failures` | integer | **Required** | +| `tx_pkts_retries` | integer | **Required** | +| `tx_total_bytes` | integer | **Required** | +| `tx_total_pkts` | integer | **Required** | + +#### rate_of_last_rx_pkt + +`rate_of_last_rx_pkt` + +- is **required** +- type: reference + +##### rate_of_last_rx_pkt Type + +`integer` + +- minimum value: `0` + +#### rate_of_last_tx_pkt + +`rate_of_last_tx_pkt` + +- is **required** +- type: reference + +##### rate_of_last_tx_pkt Type + +`integer` + +- minimum value: `0` + +#### rx_data_bytes + +`rx_data_bytes` + +- is **required** +- type: reference + +##### rx_data_bytes Type + +`integer` + +- minimum value: `0` + +#### rx_data_pkts + +`rx_data_pkts` + +- is **required** +- type: reference + +##### rx_data_pkts Type + +`integer` + +- minimum value: `0` + +#### rx_failures + +`rx_failures` + +- is **required** +- type: reference + +##### rx_failures Type + +`integer` + +- minimum value: `0` + +#### tx_failures + +`tx_failures` + +- is **required** +- type: reference + +##### tx_failures Type + +`integer` + +- minimum value: `0` + +#### tx_pkts_retries + +`tx_pkts_retries` + +- is **required** +- type: reference + +##### tx_pkts_retries Type + +`integer` + +- minimum value: `0` + +#### tx_total_bytes + +`tx_total_bytes` + +- is **required** +- type: reference + +##### tx_total_bytes Type + +`integer` + +- minimum value: `0` + +#### tx_total_pkts + +`tx_total_pkts` + +- is **required** +- type: reference + +##### tx_total_pkts Type + +`integer` + +- minimum value: `0` + +#### status + +`status` + +- is **required** +- type: `object` + +##### status Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------- | ------------ | +| `ps` | boolean | **Required** | +| `wmm` | boolean | **Required** | + +#### ps + +`ps` + +- is **required** +- type: `boolean` + +##### ps Type + +`boolean` + +#### wmm + +`wmm` + +- is **required** +- type: `boolean` + +##### wmm Type + +`boolean` + +#### tx_airtime + +`tx_airtime` + +- is **required** +- type: `integer` + +##### tx_airtime Type + +`integer` + +- minimum value: `0` +- maximum value: `100` + +#### wdev + +##### Interface + +`wdev` + +- is **required** +- type: reference + +##### wdev Type + +`string` + +- minimum length: 1 characters +- maximum length: 16 characters + +### Output Example + +```json +{ + "stations": [ + { + "macaddr": "3A:aC:2c:AA:03:C6", + "wdev": "se", + "frequency": "2GHz", + "rssi": -108, + "snr": 70, + "idle": 90053251, + "in_network": 43328099, + "tx_airtime": 56, + "rx_airtime": 93, + "airtime": 73, + "max_rate": 11517274, + "status": { "wmm": false, "ps": false }, + "capabilities": { + "wmm": false, + "apsd": true, + "shortslot": false, + "dot11h": true, + "2040coex": false, + "psmp": true, + "proxy_arp": true, + "dot11v_btm": true, + "dot11k": { + "dot11k_link_meas": false, + "dot11k_nbr_report": true, + "dot11k_bcn_passive": false, + "dot11k_bcn_active": true, + "dot11k_bcn_table": true, + "dot11k_rcpi": false, + "dot11k_rsni": false + }, + "dot11n": { + "dot11n_ldpc": true, + "dot11n_40": true, + "dot11n_ps": false, + "dot11n_sgi20": true, + "dot11n_sgi40": true, + "dot11n_tx_stbc": false, + "dot11n_rx_stbc": false + }, + "dot11ac": { + "dot11ac_160": false, + "dot11ac_8080": false, + "dot11ac_mpdu_max": 57162, + "dot11ac_sgi80": true, + "dot11ac_sgi160": true, + "dot11ac_rx_ldpc": false, + "dot11ac_tx_stbc": false, + "dot11ac_rx_stbc_1ss": false, + "dot11ac_rx_stbc_2ss": false, + "dot11ac_rx_stbc_3ss": true, + "dot11ac_rx_stbc_4ss": true, + "dot11ac_su_beamformer": false, + "dot11ac_su_beamformee": false, + "dot11ac_mu_beamformer": true, + "dot11ac_mu_beamformee": true + } + }, + "stats": { + "tx_total_pkts": 92281078, + "tx_total_bytes": 6455029, + "tx_failures": 15810512, + "tx_pkts_retries": 80187405, + "rx_data_pkts": 24413834, + "rx_data_bytes": 47228586, + "rx_failures": 10026617, + "rate_of_last_tx_pkt": 50344199, + "rate_of_last_rx_pkt": 60889706 + }, + "rssi_per_antenna": [-58, -46, -33, -104] + }, + { + "macaddr": "5F:BD:b8:31:Ec:Dc", + "wdev": "amet sit", + "frequency": "2GHz", + "rssi": -69, + "snr": 63, + "idle": 24571654, + "in_network": 23076310, + "tx_airtime": 56, + "rx_airtime": 1, + "airtime": 88, + "max_rate": 55820450, + "status": { "wmm": false, "ps": false }, + "capabilities": { + "wmm": false, + "apsd": false, + "shortslot": true, + "dot11h": true, + "2040coex": true, + "psmp": false, + "proxy_arp": true, + "dot11v_btm": true, + "dot11k": { + "dot11k_link_meas": true, + "dot11k_nbr_report": true, + "dot11k_bcn_passive": true, + "dot11k_bcn_active": false, + "dot11k_bcn_table": true, + "dot11k_rcpi": true, + "dot11k_rsni": false + }, + "dot11n": { + "dot11n_ldpc": false, + "dot11n_40": false, + "dot11n_ps": false, + "dot11n_sgi20": true, + "dot11n_sgi40": true, + "dot11n_tx_stbc": false, + "dot11n_rx_stbc": false + }, + "dot11ac": { + "dot11ac_160": false, + "dot11ac_8080": false, + "dot11ac_mpdu_max": 17677, + "dot11ac_sgi80": false, + "dot11ac_sgi160": false, + "dot11ac_rx_ldpc": false, + "dot11ac_tx_stbc": false, + "dot11ac_rx_stbc_1ss": false, + "dot11ac_rx_stbc_2ss": false, + "dot11ac_rx_stbc_3ss": false, + "dot11ac_rx_stbc_4ss": false, + "dot11ac_su_beamformer": false, + "dot11ac_su_beamformee": true, + "dot11ac_mu_beamformer": true, + "dot11ac_mu_beamformee": false + } + }, + "stats": { + "tx_total_pkts": 51507224, + "tx_total_bytes": 33042446, + "tx_failures": 52189830, + "tx_pkts_retries": 80860394, + "rx_data_pkts": 31736684, + "rx_data_bytes": 59698555, + "rx_failures": 42673662, + "rate_of_last_tx_pkt": 86670792, + "rate_of_last_rx_pkt": 81522287 + }, + "rssi_per_antenna": [-110, -101, -83] + }, + { + "macaddr": "27:71:6d:C0:C6:c8", + "wdev": "sit ", + "frequency": "2GHz", + "rssi": -115, + "snr": 3, + "idle": 49139566, + "in_network": 93630997, + "tx_airtime": 25, + "rx_airtime": 22, + "airtime": 45, + "max_rate": 36462522, + "status": { "wmm": true, "ps": false }, + "capabilities": { + "wmm": false, + "apsd": false, + "shortslot": false, + "dot11h": true, + "2040coex": false, + "psmp": true, + "proxy_arp": true, + "dot11v_btm": false, + "dot11k": { + "dot11k_link_meas": true, + "dot11k_nbr_report": true, + "dot11k_bcn_passive": true, + "dot11k_bcn_active": true, + "dot11k_bcn_table": true, + "dot11k_rcpi": false, + "dot11k_rsni": false + }, + "dot11n": { + "dot11n_ldpc": false, + "dot11n_40": true, + "dot11n_ps": true, + "dot11n_sgi20": true, + "dot11n_sgi40": true, + "dot11n_tx_stbc": false, + "dot11n_rx_stbc": false + }, + "dot11ac": { + "dot11ac_160": true, + "dot11ac_8080": false, + "dot11ac_mpdu_max": 54602, + "dot11ac_sgi80": true, + "dot11ac_sgi160": false, + "dot11ac_rx_ldpc": true, + "dot11ac_tx_stbc": false, + "dot11ac_rx_stbc_1ss": false, + "dot11ac_rx_stbc_2ss": true, + "dot11ac_rx_stbc_3ss": false, + "dot11ac_rx_stbc_4ss": false, + "dot11ac_su_beamformer": true, + "dot11ac_su_beamformee": false, + "dot11ac_mu_beamformer": true, + "dot11ac_mu_beamformee": true + } + }, + "stats": { + "tx_total_pkts": 22048245, + "tx_total_bytes": 32320728, + "tx_failures": 9765756, + "tx_pkts_retries": 11753890, + "rx_data_pkts": 96434769, + "rx_data_bytes": 75447112, + "rx_failures": 16276172, + "rate_of_last_tx_pkt": 16186367, + "rate_of_last_rx_pkt": 82849152 + }, + "rssi_per_antenna": [-69, -43, -11] + }, + { + "macaddr": "bB:C8:2B:D4:4c:bF", + "wdev": "s", + "frequency": "2GHz", + "rssi": -30, + "snr": 46, + "idle": 92358887, + "in_network": 24006299, + "tx_airtime": 48, + "rx_airtime": 78, + "airtime": 3, + "max_rate": 51661001, + "status": { "wmm": true, "ps": true }, + "capabilities": { + "wmm": true, + "apsd": true, + "shortslot": true, + "dot11h": false, + "2040coex": true, + "psmp": true, + "proxy_arp": false, + "dot11v_btm": false, + "dot11k": { + "dot11k_link_meas": true, + "dot11k_nbr_report": false, + "dot11k_bcn_passive": true, + "dot11k_bcn_active": true, + "dot11k_bcn_table": false, + "dot11k_rcpi": false, + "dot11k_rsni": false + }, + "dot11n": { + "dot11n_ldpc": false, + "dot11n_40": true, + "dot11n_ps": false, + "dot11n_sgi20": false, + "dot11n_sgi40": true, + "dot11n_tx_stbc": false, + "dot11n_rx_stbc": true + }, + "dot11ac": { + "dot11ac_160": false, + "dot11ac_8080": false, + "dot11ac_mpdu_max": 64314, + "dot11ac_sgi80": true, + "dot11ac_sgi160": false, + "dot11ac_rx_ldpc": true, + "dot11ac_tx_stbc": true, + "dot11ac_rx_stbc_1ss": true, + "dot11ac_rx_stbc_2ss": true, + "dot11ac_rx_stbc_3ss": false, + "dot11ac_rx_stbc_4ss": true, + "dot11ac_su_beamformer": true, + "dot11ac_su_beamformee": true, + "dot11ac_mu_beamformer": true, + "dot11ac_mu_beamformee": false + } + }, + "stats": { + "tx_total_pkts": 32983808, + "tx_total_bytes": 3978506, + "tx_failures": 57206696, + "tx_pkts_retries": 72123612, + "rx_data_pkts": 45529189, + "rx_data_bytes": 48658043, + "rx_failures": 12011487, + "rate_of_last_tx_pkt": 12424747, + "rate_of_last_rx_pkt": 82682244 + }, + "rssi_per_antenna": [-92, -16] + }, + { + "macaddr": "c6:09:c5:A1:4E:5E", + "wdev": "reprehenderit", + "frequency": "2GHz", + "rssi": -73, + "snr": 91, + "idle": 19060476, + "in_network": 4933515, + "tx_airtime": 17, + "rx_airtime": 27, + "airtime": 82, + "max_rate": 60339022, + "status": { "wmm": false, "ps": true }, + "capabilities": { + "wmm": true, + "apsd": false, + "shortslot": true, + "dot11h": false, + "2040coex": true, + "psmp": true, + "proxy_arp": true, + "dot11v_btm": false, + "dot11k": { + "dot11k_link_meas": false, + "dot11k_nbr_report": false, + "dot11k_bcn_passive": false, + "dot11k_bcn_active": true, + "dot11k_bcn_table": true, + "dot11k_rcpi": false, + "dot11k_rsni": true + }, + "dot11n": { + "dot11n_ldpc": false, + "dot11n_40": true, + "dot11n_ps": false, + "dot11n_sgi20": false, + "dot11n_sgi40": false, + "dot11n_tx_stbc": false, + "dot11n_rx_stbc": true + }, + "dot11ac": { + "dot11ac_160": false, + "dot11ac_8080": false, + "dot11ac_mpdu_max": 24826, + "dot11ac_sgi80": false, + "dot11ac_sgi160": false, + "dot11ac_rx_ldpc": true, + "dot11ac_tx_stbc": true, + "dot11ac_rx_stbc_1ss": false, + "dot11ac_rx_stbc_2ss": true, + "dot11ac_rx_stbc_3ss": false, + "dot11ac_rx_stbc_4ss": true, + "dot11ac_su_beamformer": false, + "dot11ac_su_beamformee": false, + "dot11ac_mu_beamformer": false, + "dot11ac_mu_beamformee": true + } + }, + "stats": { + "tx_total_pkts": 40473172, + "tx_total_bytes": 16285086, + "tx_failures": 19423488, + "tx_pkts_retries": 17748565, + "rx_data_pkts": 3840175, + "rx_data_bytes": 84968530, + "rx_failures": 13879729, + "rate_of_last_tx_pkt": 29702903, + "rate_of_last_rx_pkt": 44996704 + }, + "rssi_per_antenna": [-6, -90] + } + ] +} +``` + +## stats + +`stats` + +- type: `Method` + +### stats Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Ubus CLI Example + +``` +ubus call wifi.ap.<name> stats {} +``` + +### JSONRPC Example + +```json +{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["<SID>", "wifi.ap.<name>", "stats", {}] } +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| ------------------------- | ------- | ------------ | +| `ack_fail_packets` | integer | **Required** | +| `aggregate_packets` | integer | **Required** | +| `rx_broadcast_packets` | integer | **Required** | +| `rx_bytes` | integer | **Required** | +| `rx_dropped_packets` | integer | **Required** | +| `rx_error_packets` | integer | **Required** | +| `rx_multicast_packets` | integer | **Required** | +| `rx_packets` | integer | **Required** | +| `rx_unicast_packets` | integer | **Required** | +| `rx_unknown_packets` | integer | **Required** | +| `tx_broadcast_packets` | integer | **Required** | +| `tx_bytes` | integer | **Required** | +| `tx_dropped_packets` | integer | **Required** | +| `tx_error_packets` | integer | **Required** | +| `tx_multi_retry_packets` | integer | **Required** | +| `tx_multicast_packets` | integer | **Required** | +| `tx_packets` | integer | **Required** | +| `tx_retrans_fail_packets` | integer | **Required** | +| `tx_retrans_packets` | integer | **Required** | +| `tx_retry_packets` | integer | **Required** | +| `tx_unicast_packets` | integer | **Required** | + +#### ack_fail_packets + +`ack_fail_packets` + +- is **required** +- type: reference + +##### ack_fail_packets Type + +`integer` + +- minimum value: `0` + +#### aggregate_packets + +`aggregate_packets` + +- is **required** +- type: reference + +##### aggregate_packets Type + +`integer` + +- minimum value: `0` + +#### rx_broadcast_packets + +`rx_broadcast_packets` + +- is **required** +- type: reference + +##### rx_broadcast_packets Type + +`integer` + +- minimum value: `0` + +#### rx_bytes + +`rx_bytes` + +- is **required** +- type: reference + +##### rx_bytes Type + +`integer` + +- minimum value: `0` + +#### rx_dropped_packets + +`rx_dropped_packets` + +- is **required** +- type: reference + +##### rx_dropped_packets Type + +`integer` + +- minimum value: `0` + +#### rx_error_packets + +`rx_error_packets` + +- is **required** +- type: reference + +##### rx_error_packets Type + +`integer` + +- minimum value: `0` + +#### rx_multicast_packets + +`rx_multicast_packets` + +- is **required** +- type: reference + +##### rx_multicast_packets Type + +`integer` + +- minimum value: `0` + +#### rx_packets + +`rx_packets` + +- is **required** +- type: reference + +##### rx_packets Type + +`integer` + +- minimum value: `0` + +#### rx_unicast_packets + +`rx_unicast_packets` + +- is **required** +- type: reference + +##### rx_unicast_packets Type + +`integer` + +- minimum value: `0` + +#### rx_unknown_packets + +`rx_unknown_packets` + +- is **required** +- type: reference + +##### rx_unknown_packets Type + +`integer` + +- minimum value: `0` + +#### tx_broadcast_packets + +`tx_broadcast_packets` + +- is **required** +- type: reference + +##### tx_broadcast_packets Type + +`integer` + +- minimum value: `0` + +#### tx_bytes + +`tx_bytes` + +- is **required** +- type: reference + +##### tx_bytes Type + +`integer` + +- minimum value: `0` + +#### tx_dropped_packets + +`tx_dropped_packets` + +- is **required** +- type: reference + +##### tx_dropped_packets Type + +`integer` + +- minimum value: `0` + +#### tx_error_packets + +`tx_error_packets` + +- is **required** +- type: reference + +##### tx_error_packets Type + +`integer` + +- minimum value: `0` + +#### tx_multi_retry_packets + +`tx_multi_retry_packets` + +- is **required** +- type: reference + +##### tx_multi_retry_packets Type + +`integer` + +- minimum value: `0` + +#### tx_multicast_packets + +`tx_multicast_packets` + +- is **required** +- type: reference + +##### tx_multicast_packets Type + +`integer` + +- minimum value: `0` + +#### tx_packets + +`tx_packets` + +- is **required** +- type: reference + +##### tx_packets Type + +`integer` + +- minimum value: `0` + +#### tx_retrans_fail_packets + +`tx_retrans_fail_packets` + +- is **required** +- type: reference + +##### tx_retrans_fail_packets Type + +`integer` + +- minimum value: `0` + +#### tx_retrans_packets + +`tx_retrans_packets` + +- is **required** +- type: reference + +##### tx_retrans_packets Type + +`integer` + +- minimum value: `0` + +#### tx_retry_packets + +`tx_retry_packets` + +- is **required** +- type: reference + +##### tx_retry_packets Type + +`integer` + +- minimum value: `0` + +#### tx_unicast_packets + +`tx_unicast_packets` + +- is **required** +- type: reference + +##### tx_unicast_packets Type + +`integer` + +- minimum value: `0` + +### Output Example + +```json +{ + "tx_bytes": 45898068, + "tx_packets": 22299868, + "tx_unicast_packets": 68790704, + "tx_multicast_packets": 21953717, + "tx_broadcast_packets": 51292406, + "tx_error_packets": 58416828, + "tx_retrans_packets": 62808550, + "tx_retrans_fail_packets": 54601227, + "tx_retry_packets": 6510836, + "tx_multi_retry_packets": 72654188, + "tx_dropped_packets": 46052254, + "ack_fail_packets": 87486133, + "aggregate_packets": 43478535, + "rx_bytes": 16018837, + "rx_packets": 9027848, + "rx_unicast_packets": 6370715, + "rx_multicast_packets": 58632, + "rx_broadcast_packets": 93325534, + "rx_error_packets": 57998201, + "rx_dropped_packets": 86018793, + "rx_unknown_packets": 49274524 +} +``` + +## status + +`status` + +- type: `Method` + +### status Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Ubus CLI Example + +``` +ubus call wifi.ap.<name> status {} +``` + +### JSONRPC Example + +```json +{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["<SID>", "wifi.ap.<name>", "status", {}] } +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------------- | ------- | ------------ | +| `adm_capacity` | integer | **Required** | +| `bandwidth` | oneOf | **Required** | +| `bssid` | string | **Required** | +| `capabilities` | object | **Required** | +| `encryption` | string | **Required** | +| `hidden` | boolean | **Required** | +| `ifname` | string | **Required** | +| `max_stations` | integer | **Required** | +| `num_stations` | integer | **Required** | +| `ssid` | string | **Required** | +| `standard` | string | **Required** | +| `status` | string | **Required** | +| `utilization` | integer | **Required** | + +#### adm_capacity + +`adm_capacity` + +- is **required** +- type: `integer` + +##### adm_capacity Type + +`integer` + +#### bandwidth + +`bandwidth` + +- is **required** +- type: complex + +##### bandwidth Type + +**One** of the following _conditions_ need to be fulfilled. + +#### Condition 1 + +`integer` + +#### Condition 2 + +`integer` + +#### bssid + +##### MAC Address + +`bssid` + +- is **required** +- type: reference + +##### bssid Type + +`string` + +- minimum length: 17 characters +- maximum length: 17 characters All instances must conform to this regular expression (test examples + [here](<https://regexr.com/?expression=%5E(%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%3A)%7B5%7D%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%24>)): + +```regex +^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$ +``` + +#### capabilities + +`capabilities` + +- is **required** +- type: `object` + +##### capabilities Type + +`object` with following properties: + +| Property | Type | Required | +| ----------- | ------- | ------------ | +| `apsd` | boolean | **Required** | +| `dot11ac` | object | Optional | +| `dot11h` | boolean | **Required** | +| `dot11k` | object | Optional | +| `dot11n` | object | Optional | +| `shortslot` | boolean | **Required** | +| `wmm` | boolean | **Required** | + +#### apsd + +`apsd` + +- is **required** +- type: `boolean` + +##### apsd Type + +`boolean` + +#### dot11ac + +`dot11ac` + +- is optional +- type: `object` + +##### dot11ac Type + +`object` with following properties: + +| Property | Type | Required | +| ----------------------- | ------- | ------------ | +| `dot11ac_160` | boolean | **Required** | +| `dot11ac_8080` | boolean | **Required** | +| `dot11ac_mpdu_max` | integer | **Required** | +| `dot11ac_mu_beamformee` | boolean | **Required** | +| `dot11ac_mu_beamformer` | boolean | **Required** | +| `dot11ac_rx_ldpc` | boolean | **Required** | +| `dot11ac_rx_stbc_1ss` | boolean | **Required** | +| `dot11ac_rx_stbc_2ss` | boolean | **Required** | +| `dot11ac_rx_stbc_3ss` | boolean | **Required** | +| `dot11ac_rx_stbc_4ss` | boolean | **Required** | +| `dot11ac_sgi160` | boolean | **Required** | +| `dot11ac_sgi80` | boolean | **Required** | +| `dot11ac_su_beamformee` | boolean | **Required** | +| `dot11ac_su_beamformer` | boolean | **Required** | +| `dot11ac_tx_stbc` | boolean | **Required** | + +#### dot11ac_160 + +`dot11ac_160` + +- is **required** +- type: `boolean` + +##### dot11ac_160 Type + +`boolean` + +#### dot11ac_8080 + +`dot11ac_8080` + +- is **required** +- type: `boolean` + +##### dot11ac_8080 Type + +`boolean` + +#### dot11ac_mpdu_max + +`dot11ac_mpdu_max` + +- is **required** +- type: `integer` + +##### dot11ac_mpdu_max Type + +`integer` + +- minimum value: `0` +- maximum value: `65535` + +#### dot11ac_mu_beamformee + +`dot11ac_mu_beamformee` + +- is **required** +- type: `boolean` + +##### dot11ac_mu_beamformee Type + +`boolean` + +#### dot11ac_mu_beamformer + +`dot11ac_mu_beamformer` + +- is **required** +- type: `boolean` + +##### dot11ac_mu_beamformer Type + +`boolean` + +#### dot11ac_rx_ldpc + +`dot11ac_rx_ldpc` + +- is **required** +- type: `boolean` + +##### dot11ac_rx_ldpc Type + +`boolean` + +#### dot11ac_rx_stbc_1ss + +`dot11ac_rx_stbc_1ss` + +- is **required** +- type: `boolean` + +##### dot11ac_rx_stbc_1ss Type + +`boolean` + +#### dot11ac_rx_stbc_2ss + +`dot11ac_rx_stbc_2ss` + +- is **required** +- type: `boolean` + +##### dot11ac_rx_stbc_2ss Type + +`boolean` + +#### dot11ac_rx_stbc_3ss + +`dot11ac_rx_stbc_3ss` + +- is **required** +- type: `boolean` + +##### dot11ac_rx_stbc_3ss Type + +`boolean` + +#### dot11ac_rx_stbc_4ss + +`dot11ac_rx_stbc_4ss` + +- is **required** +- type: `boolean` + +##### dot11ac_rx_stbc_4ss Type + +`boolean` + +#### dot11ac_sgi160 + +`dot11ac_sgi160` + +- is **required** +- type: `boolean` + +##### dot11ac_sgi160 Type + +`boolean` + +#### dot11ac_sgi80 + +`dot11ac_sgi80` + +- is **required** +- type: `boolean` + +##### dot11ac_sgi80 Type + +`boolean` + +#### dot11ac_su_beamformee + +`dot11ac_su_beamformee` + +- is **required** +- type: `boolean` + +##### dot11ac_su_beamformee Type + +`boolean` + +#### dot11ac_su_beamformer + +`dot11ac_su_beamformer` + +- is **required** +- type: `boolean` + +##### dot11ac_su_beamformer Type + +`boolean` + +#### dot11ac_tx_stbc + +`dot11ac_tx_stbc` + +- is **required** +- type: `boolean` + +##### dot11ac_tx_stbc Type + +`boolean` + +#### dot11h + +`dot11h` + +- is **required** +- type: `boolean` + +##### dot11h Type + +`boolean` + +#### dot11k + +`dot11k` + +- is optional +- type: `object` + +##### dot11k Type + +`object` with following properties: + +| Property | Type | Required | +| -------------------- | ------- | ------------ | +| `dot11k_bcn_active` | boolean | **Required** | +| `dot11k_bcn_passive` | boolean | **Required** | +| `dot11k_bcn_table` | boolean | **Required** | +| `dot11k_link_meas` | boolean | **Required** | +| `dot11k_nbr_report` | boolean | **Required** | +| `dot11k_rcpi` | boolean | **Required** | +| `dot11k_rsni` | boolean | **Required** | + +#### dot11k_bcn_active + +`dot11k_bcn_active` + +- is **required** +- type: `boolean` + +##### dot11k_bcn_active Type + +`boolean` + +#### dot11k_bcn_passive + +`dot11k_bcn_passive` + +- is **required** +- type: `boolean` + +##### dot11k_bcn_passive Type + +`boolean` + +#### dot11k_bcn_table + +`dot11k_bcn_table` + +- is **required** +- type: `boolean` + +##### dot11k_bcn_table Type + +`boolean` + +#### dot11k_link_meas + +`dot11k_link_meas` + +- is **required** +- type: `boolean` + +##### dot11k_link_meas Type + +`boolean` + +#### dot11k_nbr_report + +`dot11k_nbr_report` + +- is **required** +- type: `boolean` + +##### dot11k_nbr_report Type + +`boolean` + +#### dot11k_rcpi + +`dot11k_rcpi` + +- is **required** +- type: `boolean` + +##### dot11k_rcpi Type + +`boolean` + +#### dot11k_rsni + +`dot11k_rsni` + +- is **required** +- type: `boolean` + +##### dot11k_rsni Type + +`boolean` + +#### dot11n + +`dot11n` + +- is optional +- type: `object` + +##### dot11n Type + +`object` with following properties: + +| Property | Type | Required | +| ---------------- | ------- | ------------ | +| `dot11n_40` | boolean | **Required** | +| `dot11n_ldpc` | boolean | **Required** | +| `dot11n_ps` | boolean | **Required** | +| `dot11n_rx_stbc` | boolean | **Required** | +| `dot11n_sgi20` | boolean | **Required** | +| `dot11n_sgi40` | boolean | **Required** | +| `dot11n_tx_stbc` | boolean | **Required** | + +#### dot11n_40 + +`dot11n_40` + +- is **required** +- type: `boolean` + +##### dot11n_40 Type + +`boolean` + +#### dot11n_ldpc + +`dot11n_ldpc` + +- is **required** +- type: `boolean` + +##### dot11n_ldpc Type + +`boolean` + +#### dot11n_ps + +`dot11n_ps` + +- is **required** +- type: `boolean` + +##### dot11n_ps Type + +`boolean` + +#### dot11n_rx_stbc + +`dot11n_rx_stbc` + +- is **required** +- type: `boolean` + +##### dot11n_rx_stbc Type + +`boolean` + +#### dot11n_sgi20 + +`dot11n_sgi20` + +- is **required** +- type: `boolean` + +##### dot11n_sgi20 Type + +`boolean` + +#### dot11n_sgi40 + +`dot11n_sgi40` + +- is **required** +- type: `boolean` + +##### dot11n_sgi40 Type + +`boolean` + +#### dot11n_tx_stbc + +`dot11n_tx_stbc` + +- is **required** +- type: `boolean` + +##### dot11n_tx_stbc Type + +`boolean` + +#### shortslot + +`shortslot` + +- is **required** +- type: `boolean` + +##### shortslot Type + +`boolean` + +#### wmm + +`wmm` + +- is **required** +- type: `boolean` + +##### wmm Type + +`boolean` + +#### encryption + +`encryption` + +- is **required** +- type: `string` + +##### encryption Type + +`string` + +#### hidden + +`hidden` + +- is **required** +- type: `boolean` + +##### hidden Type + +`boolean` + +#### ifname + +##### Interface + +`ifname` + +- is **required** +- type: reference + +##### ifname Type + +`string` + +- minimum length: 1 characters +- maximum length: 16 characters + +#### max_stations + +##### Number of stations + +`max_stations` + +- is **required** +- type: reference + +##### max_stations Type + +`integer` + +- minimum value: `0` +- maximum value: `2007` + +#### num_stations + +##### Number of stations + +`num_stations` + +- is **required** +- type: reference + +##### num_stations Type + +`integer` + +- minimum value: `0` +- maximum value: `2007` + +#### ssid + +##### SSID + +`ssid` + +- is **required** +- type: reference + +##### ssid Type + +`string` + +- maximum length: 32 characters + +#### standard + +`standard` + +- is **required** +- type: `string` + +##### standard Type + +`string` + +#### status + +`status` + +- is **required** +- type: `string` + +##### status Type + +`string` + +#### utilization + +`utilization` + +- is **required** +- type: `integer` + +##### utilization Type + +`integer` + +- minimum value: `0` +- maximum value: `100` + +### Output Example + +```json +{ + "ifname": "nostrud ", + "status": "cillum culpa ut voluptate fugiat", + "ssid": "dolore aute consequ", + "bssid": "8B:d9:Cb:bD:7e:5b", + "encryption": "proident", + "bandwidth": 20, + "standard": "culpa officia commodo", + "num_stations": 70, + "utilization": 61, + "adm_capacity": 87791482, + "hidden": false, + "max_stations": 125, + "capabilities": { + "wmm": true, + "apsd": true, + "shortslot": false, + "dot11h": false, + "dot11k": { + "dot11k_link_meas": true, + "dot11k_nbr_report": false, + "dot11k_bcn_passive": true, + "dot11k_bcn_active": false, + "dot11k_bcn_table": false, + "dot11k_rcpi": true, + "dot11k_rsni": false + }, + "dot11n": { + "dot11n_ldpc": false, + "dot11n_40": false, + "dot11n_ps": false, + "dot11n_sgi20": false, + "dot11n_sgi40": true, + "dot11n_tx_stbc": true, + "dot11n_rx_stbc": true + }, + "dot11ac": { + "dot11ac_160": false, + "dot11ac_8080": true, + "dot11ac_mpdu_max": 36284, + "dot11ac_sgi80": false, + "dot11ac_sgi160": false, + "dot11ac_rx_ldpc": true, + "dot11ac_tx_stbc": false, + "dot11ac_rx_stbc_1ss": false, + "dot11ac_rx_stbc_2ss": true, + "dot11ac_rx_stbc_3ss": false, + "dot11ac_rx_stbc_4ss": true, + "dot11ac_su_beamformer": true, + "dot11ac_su_beamformee": false, + "dot11ac_mu_beamformer": false, + "dot11ac_mu_beamformee": true + } + } +} +``` diff --git a/docs/api/wifi.md b/docs/api/wifi.md new file mode 100644 index 0000000000000000000000000000000000000000..130d7f010378b33af7b9a807ec62e5844c27447e --- /dev/null +++ b/docs/api/wifi.md @@ -0,0 +1,569 @@ +# wifi Schema + +``` +https://www.iopsys.eu/wifi.json +``` + +| Custom Properties | Additional Properties | +| ----------------- | --------------------- | +| Forbidden | Forbidden | + +# wifi + +| List of Methods | +| ----------------- | +| [status](#status) | Method | wifi (this schema) | + +## status + +`status` + +- type: `Method` + +### status Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Ubus CLI Example + +``` +ubus call wifi status {} +``` + +### JSONRPC Example + +```json +{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["<SID>", "wifi", "status", {}] } +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ----- | ------------ | +| `radios` | array | **Required** | + +#### radios + +`radios` + +- is **required** +- type: `object[]` + +##### radios Type + +Array type: `object[]` + +All items must be of the type: `object` with following properties: + +| Property | Type | Required | +| -------------- | ------- | ------------ | +| `accesspoints` | array | **Required** | +| `backhauls` | array | **Required** | +| `band` | string | **Required** | +| `bandwidth` | integer | **Required** | +| `country` | string | **Required** | +| `isup` | boolean | **Required** | +| `name` | string | **Required** | +| `noise` | integer | **Required** | +| `rate` | integer | **Required** | +| `standard` | string | **Required** | + +#### accesspoints + +`accesspoints` + +- is **required** +- type: reference + +##### accesspoints Type + +Array type: reference + +All items must be of the type: `object` with following properties: + +| Property | Type | Required | +| -------- | ------ | ------------ | +| `bssid` | | **Required** | +| `ifname` | string | **Required** | +| `ssid` | string | **Required** | +| `status` | string | **Required** | + +#### bssid + +`bssid` + +- is **required** +- type: complex + +##### bssid Type + +Unknown type ``. + +```json +{ + "bssid": { + "$ref": "#/definitions/macaddr_t" + }, + "simpletype": "complex" +} +``` + +#### ifname + +`ifname` + +- is **required** +- type: `string` + +##### ifname Type + +`string` + +- minimum length: 1 characters +- maximum length: 16 characters + +#### ssid + +`ssid` + +- is **required** +- type: `string` + +##### ssid Type + +`string` + +- maximum length: 32 characters + +#### status + +`status` + +- is **required** +- type: `string` + +##### status Type + +`string` + +#### backhauls + +`backhauls` + +- is **required** +- type: reference + +##### backhauls Type + +Array type: reference + +All items must be of the type: `object` with following properties: + +| Property | Type | Required | +| -------- | ------ | ------------ | +| `bssid` | | **Required** | +| `ifname` | string | **Required** | +| `ssid` | string | **Required** | +| `status` | string | **Required** | + +#### bssid + +`bssid` + +- is **required** +- type: complex + +##### bssid Type + +Unknown type ``. + +```json +{ + "bssid": { + "$ref": "#/definitions/macaddr_t" + }, + "simpletype": "complex" +} +``` + +#### ifname + +`ifname` + +- is **required** +- type: `string` + +##### ifname Type + +`string` + +- minimum length: 1 characters +- maximum length: 16 characters + +#### ssid + +`ssid` + +- is **required** +- type: `string` + +##### ssid Type + +`string` + +- maximum length: 32 characters + +#### status + +`status` + +- is **required** +- type: `string` + +##### status Type + +`string` + +#### band + +##### WiFi Band + +`band` + +- is **required** +- type: reference + +##### band Type + +`string` + +The value of this property **must** be equal to one of the [known values below](#status-known-values). + +##### band Known Values + +| Value | +| ----- | +| 2GHz | +| 5GHz | + +#### bandwidth + +##### Bandwidth + +`bandwidth` + +- is **required** +- type: reference + +##### bandwidth Type + +`integer` + +The value of this property **must** be equal to one of the [known values below](#status-known-values). + +##### bandwidth Known Values + +| Value | +| ----- | +| 20 | +| 40 | +| 80 | +| 160 | + +#### country + +`country` + +- is **required** +- type: `string` + +##### country Type + +`string` + +- minimum length: 2 characters +- maximum length: 3 characters + +#### isup + +`isup` + +- is **required** +- type: `boolean` + +##### isup Type + +`boolean` + +#### name + +##### Interface + +`name` + +- is **required** +- type: reference + +##### name Type + +`string` + +- minimum length: 1 characters +- maximum length: 16 characters + +#### noise + +##### Noise + +`noise` + +- is **required** +- type: reference + +##### noise Type + +`integer` + +- minimum value: `-127` +- maximum value: `0` + +#### rate + +`rate` + +- is **required** +- type: `integer` + +##### rate Type + +`integer` + +- minimum value: `0` + +#### standard + +`standard` + +- is **required** +- type: `string` + +##### standard Type + +`string` + +### Output Example + +```json +{ + "radios": [ + { + "name": "voluptate rep", + "isup": false, + "standard": "sunt aliqua dolore laboris officia", + "country": "qui", + "band": "5GHz", + "bandwidth": 160, + "noise": -93, + "rate": 52420370, + "accesspoints": [ + { "ifname": "culpa", "status": "esse", "ssid": "Lorem id magna", "bssid": { "bssid": "45:F6:98:d8:E2:dc" } }, + { + "ifname": "adipisicing", + "status": "est id et ut irure", + "ssid": "minim sit mollit", + "bssid": { "bssid": "E9:eE:06:be:13:65" } + }, + { + "ifname": "sit dolo", + "status": "laboris nulla qui", + "ssid": "officia commodo", + "bssid": { "bssid": "2D:F0:4F:EA:0D:eb" } + }, + { + "ifname": "nostru", + "status": "officia dolor ea dolore occaecat", + "ssid": "qui sit ", + "bssid": { "bssid": "58:c8:97:d1:d1:9C" } + }, + { "ifname": "es", "status": "ut sint ipsum Duis ex", "ssid": "ex ", "bssid": { "bssid": "63:Bc:eF:3d:c3:9d" } } + ], + "backhauls": [ + { + "ifname": "labo", + "status": "nostrud ex amet", + "ssid": "dolore in eu", + "bssid": { "bssid": "5e:43:a7:9f:6c:01" } + }, + { + "ifname": "id aliquip", + "status": "esse", + "ssid": "dolor consectetur", + "bssid": { "bssid": "ce:FA:92:fe:df:b4" } + }, + { + "ifname": "i", + "status": "dolore mollit commodo", + "ssid": "minim", + "bssid": { "bssid": "Cf:aC:0A:Ed:b3:A6" } + }, + { + "ifname": "inci", + "status": "consectetur id pariatur", + "ssid": "sed", + "bssid": { "bssid": "d8:aa:D5:23:eC:FD" } + }, + { "ifname": "nisi", "status": "voluptate fugiat", "ssid": "sunt ", "bssid": { "bssid": "DB:B1:Fe:50:Cb:Eb" } } + ], + "channel": 24753590, + "channels": "ad minim eiusmod" + }, + { + "name": "occaecat", + "isup": false, + "standard": "labore in dolor ad", + "country": "ni", + "band": "2GHz", + "bandwidth": 80, + "noise": -106, + "rate": 30910391, + "accesspoints": [ + { + "ifname": "si", + "status": "aute occaecat laboris ut aliqua", + "ssid": "incididunt", + "bssid": { "bssid": "69:68:c5:6c:22:DA" } + }, + { + "ifname": "fugiat ", + "status": "Lorem reprehenderit", + "ssid": "dolore min", + "bssid": { "bssid": "88:8f:87:F9:0C:B7" } + } + ], + "backhauls": [ + { + "ifname": "nisi magna ", + "status": "officia in sed Lorem", + "ssid": "sit dolore ", + "bssid": { "bssid": "9f:F0:aD:3c:BF:af" } + }, + { "ifname": "laborum", "status": "mollit", "ssid": "fugiat", "bssid": { "bssid": "D0:Ba:C5:83:D8:be" } } + ], + "channel": -99539458.64552729, + "channels": -53586837 + }, + { + "name": "dolore qu", + "isup": false, + "standard": "ut commodo", + "country": "pr", + "band": "2GHz", + "bandwidth": 20, + "noise": -87, + "rate": 59230503, + "accesspoints": [ + { + "ifname": "cillum d", + "status": "sit occaecat dolor", + "ssid": "dolor", + "bssid": { "bssid": "De:5b:52:b1:ba:5a" } + }, + { "ifname": "paria", "status": "magna ex", "ssid": "cupidatat ", "bssid": { "bssid": "BA:De:8B:fF:Fc:fC" } } + ], + "backhauls": [ + { + "ifname": "Lorem ut Ut ", + "status": "ut cupidatat dolor in consequat", + "ssid": "ad nostrud commodo in in", + "bssid": { "bssid": "bA:21:C0:F4:d1:E7" } + } + ], + "channel": "dolor do minim", + "channels": 96257304.49025026 + }, + { + "name": "in ut", + "isup": false, + "standard": "et enim in", + "country": "vol", + "band": "5GHz", + "bandwidth": 80, + "noise": -90, + "rate": 66907094, + "accesspoints": [ + { + "ifname": "reprehenderi", + "status": "commodo ex qui nostrud", + "ssid": "", + "bssid": { "bssid": "2E:cA:0b:ff:a3:3D" } + }, + { + "ifname": "aute Exce", + "status": "cillum dolor", + "ssid": "Ut pariatur sun", + "bssid": { "bssid": "FD:06:B5:9c:Ea:39" } + }, + { + "ifname": "officia con", + "status": "sint ullamco in nulla consequat", + "ssid": "dolor dol", + "bssid": { "bssid": "F0:2d:54:D2:b9:FE" } + } + ], + "backhauls": [ + { + "ifname": "est deserunt", + "status": "tempor dolor dolor", + "ssid": "Duis laborum", + "bssid": { "bssid": "a1:Cb:F8:5f:F0:f4" } + }, + { + "ifname": "mo", + "status": "dolor amet esse veniam", + "ssid": "cupidatat", + "bssid": { "bssid": "fa:9F:9a:C4:a2:cF" } + }, + { "ifname": "d", "status": "", "ssid": "c", "bssid": { "bssid": "bc:88:7b:ab:cD:27" } }, + { "ifname": "consequ", "status": "Duis", "ssid": "cupidatat", "bssid": { "bssid": "3A:FF:A7:BA:9A:dc" } }, + { + "ifname": "dolo", + "status": "Lorem quis in aliqua occaecat", + "ssid": "q", + "bssid": { "bssid": "8D:6e:f7:fd:8C:e6" } + } + ], + "channel": "do ea sit labore est", + "channels": -76131712.30140434 + } + ] +} +``` diff --git a/docs/api/wifi.radio.md b/docs/api/wifi.radio.md new file mode 100644 index 0000000000000000000000000000000000000000..2018568dac00d78409d78d01f43bf90981aec098 --- /dev/null +++ b/docs/api/wifi.radio.md @@ -0,0 +1,937 @@ +# wifi.radio.<name> Schema + +``` +https://www.iopsys.eu/wifi.radio.json +``` + +WiFi Radio Object + +| Custom Properties | Additional Properties | +| ----------------- | --------------------- | +| Forbidden | Forbidden | + +# wifi.radio.<name> + +| List of Methods | +| --------------------------- | +| [autochannel](#autochannel) | Method | wifi.radio.<name> (this schema) | +| [get](#get) | Method | wifi.radio.<name> (this schema) | +| [scan](#scan) | Method | wifi.radio.<name> (this schema) | +| [scanresults](#scanresults) | Method | wifi.radio.<name> (this schema) | +| [stats](#stats) | Method | wifi.radio.<name> (this schema) | +| [status](#status) | Method | wifi.radio.<name> (this schema) | + +## autochannel + +`autochannel` + +- type: `Method` + +### autochannel Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| ---------- | ------- | -------- | +| `algo` | integer | Optional | +| `interval` | integer | Optional | +| `scans` | integer | Optional | + +#### algo + +`algo` + +- is optional +- type: `integer` + +##### algo Type + +`integer` + +#### interval + +`interval` + +- is optional +- type: `integer` + +##### interval Type + +`integer` + +#### scans + +`scans` + +- is optional +- type: `integer` + +##### scans Type + +`integer` + +### Ubus CLI Example + +``` +ubus call wifi.radio.<name> autochannel {"interval":-3947445,"algo":-79632421,"scans":-97118460} +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": [ + "<SID>", + "wifi.radio.<name>", + "autochannel", + { "interval": -3947445, "algo": -79632421, "scans": -97118460 } + ] +} +``` + +#### output + +##### wifi.radio.autochannel + +Auto channel selection + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| ------------- | ------- | ------------ | +| `code` | integer | **Required** | +| `new_channel` | oneOf | **Required** | +| `status` | string | **Required** | + +#### code + +`code` + +- is **required** +- type: `integer` + +##### code Type + +`integer` + +#### new_channel + +`new_channel` + +- is **required** +- type: complex + +##### new_channel Type + +**One** of the following _conditions_ need to be fulfilled. + +#### Condition 1 + +`integer` + +- minimum value: `1` +- maximum value: `14` + +#### Condition 2 + +`integer` + +- minimum value: `32` +- maximum value: `200` + +#### status + +`status` + +- is **required** +- type: `string` + +##### status Type + +`string` + +### Output Example + +```json +{ "code": -21368995, "new_channel": 139, "status": "quis se" } +``` + +## get + +`get` + +- type: `Method` + +### get Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `param` | string | Optional | + +#### param + +`param` + +- is optional +- type: `string` + +##### param Type + +`string` + +### Ubus CLI Example + +``` +ubus call wifi.radio.<name> get {"param":"sunt"} +``` + +### JSONRPC Example + +```json +{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["<SID>", "wifi.radio.<name>", "get", { "param": "sunt" }] } +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------- | -------- | +| `status` | integer | Optional | +| `values` | integer | Optional | + +#### status + +`status` + +- is optional +- type: `integer` + +##### status Type + +`integer` + +#### values + +`values` + +- is optional +- type: `integer` + +##### values Type + +`integer` + +### Output Example + +```json +{ "status": -47928223, "values": 80011809 } +``` + +## scan + +`scan` + +- type: `Method` + +### scan Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| --------- | ------ | -------- | +| `bssid` | string | Optional | +| `channel` | oneOf | Optional | +| `ssid` | string | Optional | + +#### bssid + +##### MAC Address + +`bssid` + +- is optional +- type: reference + +##### bssid Type + +`string` + +- minimum length: 17 characters +- maximum length: 17 characters All instances must conform to this regular expression (test examples + [here](<https://regexr.com/?expression=%5E(%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%3A)%7B5%7D%5B0-9a-fA-F%5D%5B0-9a-fA-F%5D%24>)): + +```regex +^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$ +``` + +#### channel + +`channel` + +- is optional +- type: complex + +##### channel Type + +**One** of the following _conditions_ need to be fulfilled. + +#### Condition 1 + +`integer` + +- minimum value: `1` +- maximum value: `14` + +#### Condition 2 + +`integer` + +- minimum value: `32` +- maximum value: `200` + +#### ssid + +##### SSID + +`ssid` + +- is optional +- type: reference + +##### ssid Type + +`string` + +- maximum length: 32 characters + +### Ubus CLI Example + +``` +ubus call wifi.radio.<name> scan {"ssid":"in","bssid":"6B:3B:df:a8:E8:bf","channel":8} +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": ["<SID>", "wifi.radio.<name>", "scan", { "ssid": "in", "bssid": "6B:3B:df:a8:E8:bf", "channel": 8 }] +} +``` + +#### output + +Trigger a scan + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Output Example + +```json +{} +``` + +## scanresults + +`scanresults` + +- type: `Method` + +### scanresults Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Ubus CLI Example + +``` +ubus call wifi.radio.<name> scanresults {} +``` + +### JSONRPC Example + +```json +{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["<SID>", "wifi.radio.<name>", "scanresults", {}] } +``` + +#### output + +Show scan results + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Output Example + +```json +{} +``` + +## stats + +`stats` + +- type: `Method` + +### stats Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Ubus CLI Example + +``` +ubus call wifi.radio.<name> stats {} +``` + +### JSONRPC Example + +```json +{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["<SID>", "wifi.radio.<name>", "stats", {}] } +``` + +#### output + +##### wifi.radio.iface + +Radio statistics + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| ---------------------- | ------- | ------------ | +| `rx_bytes` | integer | **Required** | +| `rx_dropped_packets` | integer | **Required** | +| `rx_error_packets` | integer | **Required** | +| `rx_fcs_error_packets` | integer | **Required** | +| `rx_packets` | integer | **Required** | +| `tx_bytes` | integer | **Required** | +| `tx_dropped_packets` | integer | **Required** | +| `tx_error_packets` | integer | **Required** | +| `tx_packets` | integer | **Required** | + +#### rx_bytes + +`rx_bytes` + +- is **required** +- type: reference + +##### rx_bytes Type + +`integer` + +- minimum value: `0` + +#### rx_dropped_packets + +`rx_dropped_packets` + +- is **required** +- type: reference + +##### rx_dropped_packets Type + +`integer` + +- minimum value: `0` + +#### rx_error_packets + +`rx_error_packets` + +- is **required** +- type: reference + +##### rx_error_packets Type + +`integer` + +- minimum value: `0` + +#### rx_fcs_error_packets + +`rx_fcs_error_packets` + +- is **required** +- type: reference + +##### rx_fcs_error_packets Type + +`integer` + +- minimum value: `0` + +#### rx_packets + +`rx_packets` + +- is **required** +- type: reference + +##### rx_packets Type + +`integer` + +- minimum value: `0` + +#### tx_bytes + +`tx_bytes` + +- is **required** +- type: reference + +##### tx_bytes Type + +`integer` + +- minimum value: `0` + +#### tx_dropped_packets + +`tx_dropped_packets` + +- is **required** +- type: reference + +##### tx_dropped_packets Type + +`integer` + +- minimum value: `0` + +#### tx_error_packets + +`tx_error_packets` + +- is **required** +- type: reference + +##### tx_error_packets Type + +`integer` + +- minimum value: `0` + +#### tx_packets + +`tx_packets` + +- is **required** +- type: reference + +##### tx_packets Type + +`integer` + +- minimum value: `0` + +### Output Example + +```json +{ + "tx_bytes": 62760043, + "tx_packets": 39487100, + "tx_error_packets": 4680682, + "tx_dropped_packets": 45656204, + "rx_bytes": 4906712, + "rx_packets": 27902438, + "rx_error_packets": 94647148, + "rx_dropped_packets": 95313119, + "rx_fcs_error_packets": 55108084 +} +``` + +## status + +`status` + +- type: `Method` + +### status Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Ubus CLI Example + +``` +ubus call wifi.radio.<name> status {} +``` + +### JSONRPC Example + +```json +{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["<SID>", "wifi.radio.<name>", "status", {}] } +``` + +#### output + +##### wifi.radio.iface + +Radio status + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | Default | +| ------------------- | ------- | ------------ | ------- | +| `band` | string | **Required** | | +| `beacon_int` | integer | **Required** | `100` | +| `dtim_period` | integer | **Required** | `1` | +| `frag_threshold` | integer | **Required** | `2346` | +| `isup` | boolean | **Required** | | +| `long_retry_limit` | integer | **Required** | | +| `maxrate` | integer | **Required** | | +| `noise` | integer | **Required** | | +| `radio` | string | **Required** | | +| `rts_threshold` | integer | **Required** | `2347` | +| `short_retry_limit` | integer | **Required** | | + +#### band + +##### WiFi Band + +`band` + +- is **required** +- type: reference + +##### band Type + +`string` + +The value of this property **must** be equal to one of the [known values below](#status-known-values). + +##### band Known Values + +| Value | +| ----- | +| 2GHz | +| 5GHz | + +#### beacon_int + +`beacon_int` + +- is **required** +- type: `integer` +- default: `100` + +##### beacon_int Type + +`integer` + +- minimum value: `1` +- maximum value: `65535` + +#### dtim_period + +`dtim_period` + +- is **required** +- type: `integer` +- default: `1` + +##### dtim_period Type + +`integer` + +- minimum value: `1` +- maximum value: `255` + +#### frag_threshold + +`frag_threshold` + +- is **required** +- type: `integer` +- default: `2346` + +##### frag_threshold Type + +`integer` + +- minimum value: `256` +- maximum value: `65535` + +#### isup + +`isup` + +- is **required** +- type: `boolean` + +##### isup Type + +`boolean` + +#### long_retry_limit + +`long_retry_limit` + +- is **required** +- type: `integer` + +##### long_retry_limit Type + +`integer` + +- minimum value: `1` +- maximum value: `255` + +#### maxrate + +`maxrate` + +- is **required** +- type: `integer` + +##### maxrate Type + +`integer` + +- minimum value: `0` + +#### noise + +##### Noise + +`noise` + +- is **required** +- type: reference + +##### noise Type + +`integer` + +- minimum value: `-127` +- maximum value: `0` + +#### radio + +##### Interface + +`radio` + +- is **required** +- type: reference + +##### radio Type + +`string` + +- minimum length: 1 characters +- maximum length: 16 characters + +#### rts_threshold + +`rts_threshold` + +- is **required** +- type: `integer` +- default: `2347` + +##### rts_threshold Type + +`integer` + +- minimum value: `0` +- maximum value: `65535` + +#### short_retry_limit + +`short_retry_limit` + +- is **required** +- type: `integer` + +##### short_retry_limit Type + +`integer` + +- minimum value: `1` +- maximum value: `255` + +### Output Example + +```json +{ + "radio": "eiusmod sint", + "isup": true, + "band": "5GHz", + "noise": -80, + "maxrate": 69768222, + "beacon_int": 13308, + "dtim_period": 19, + "short_retry_limit": 220, + "long_retry_limit": 139, + "frag_threshold": 4365, + "rts_threshold": 17136, + "channel": false, + "bandwidth": "ex in Lorem pariatur velit" +} +``` diff --git a/docs/api/wifi.wps.md b/docs/api/wifi.wps.md new file mode 100644 index 0000000000000000000000000000000000000000..dfdd2ec9d2c606bd275db430d003c6576b33991f --- /dev/null +++ b/docs/api/wifi.wps.md @@ -0,0 +1,682 @@ +# wifi.wps Schema + +``` +https://www.iopsys.eu/wifi.wps +``` + +| Custom Properties | Additional Properties | +| ----------------- | --------------------- | +| Forbidden | Forbidden | + +# wifi.wps + +| List of Methods | +| ----------------------------- | +| [generate_pin](#generate_pin) | Method | wifi.wps (this schema) | +| [setpin](#setpin) | Method | wifi.wps (this schema) | +| [showpin](#showpin) | Method | wifi.wps (this schema) | +| [start](#start) | Method | wifi.wps (this schema) | +| [status](#status) | Method | wifi.wps (this schema) | +| [stop](#stop) | Method | wifi.wps (this schema) | +| [validate_pin](#validate_pin) | Method | wifi.wps (this schema) | + +## generate_pin + +`generate_pin` + +- type: `Method` + +### generate_pin Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | ------------ | +| `input` | object | Optional | +| `output` | object | **Required** | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Ubus CLI Example + +``` +ubus call wifi.wps generate_pin {} +``` + +### JSONRPC Example + +```json +{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["<SID>", "wifi.wps", "generate_pin", {}] } +``` + +#### output + +`output` + +- is **required** +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | ------------ | +| `pin` | string | **Required** | + +#### pin + +`pin` + +- is **required** +- type: reference + +##### pin Type + +`string` + +- minimum length: 8 characters +- maximum length: 8 characters + +### Output Example + +```json +{ "pin": "deserunt" } +``` + +## setpin + +`setpin` + +- type: `Method` + +### setpin Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | ------------ | +| `pin` | string | **Required** | +| `vif` | string | Optional | + +#### pin + +`pin` + +- is **required** +- type: reference + +##### pin Type + +`string` + +- minimum length: 8 characters +- maximum length: 8 characters + +#### vif + +##### Interface + +`vif` + +- is optional +- type: reference + +##### vif Type + +`string` + +- minimum length: 1 characters +- maximum length: 16 characters + +### Ubus CLI Example + +``` +ubus call wifi.wps setpin {"pin":"adelit e","vif":"in magn"} +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": ["<SID>", "wifi.wps", "setpin", { "pin": "adelit e", "vif": "in magn" }] +} +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Output Example + +```json +{} +``` + +## showpin + +`showpin` + +- type: `Method` + +### showpin Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `vif` | string | Optional | + +#### vif + +##### Interface + +`vif` + +- is optional +- type: reference + +##### vif Type + +`string` + +- minimum length: 1 characters +- maximum length: 16 characters + +### Ubus CLI Example + +``` +ubus call wifi.wps showpin {"vif":"esse qu"} +``` + +### JSONRPC Example + +```json +{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["<SID>", "wifi.wps", "showpin", { "vif": "esse qu" }] } +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | ------------ | +| `pin` | string | **Required** | + +#### pin + +`pin` + +- is **required** +- type: reference + +##### pin Type + +`string` + +- minimum length: 8 characters +- maximum length: 8 characters + +### Output Example + +```json +{ "pin": "Duis qui" } +``` + +## start + +`start` + +- type: `Method` + +### start Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `mode` | string | Optional | +| `pin` | string | Optional | +| `role` | string | Optional | +| `vif` | string | Optional | + +#### mode + +`mode` + +- is optional +- type: `string` + +##### mode Type + +`string` + +#### pin + +`pin` + +- is optional +- type: reference + +##### pin Type + +`string` + +- minimum length: 8 characters +- maximum length: 8 characters + +#### role + +`role` + +- is optional +- type: `enum` + +##### role Type + +`string` + +The value of this property **must** be equal to one of the [known values below](#start-known-values). + +##### role Known Values + +| Value | +| --------- | +| registrar | +| enrollee | + +#### vif + +##### Interface + +`vif` + +- is optional +- type: reference + +##### vif Type + +`string` + +- minimum length: 1 characters +- maximum length: 16 characters + +### Ubus CLI Example + +``` +ubus call wifi.wps start {"vif":"ex commo","mode":"culpa","role":"enrollee","pin":"anim qui"} +``` + +### JSONRPC Example + +```json +{ + "jsonrpc": "2.0", + "id": 0, + "method": "call", + "params": [ + "<SID>", + "wifi.wps", + "start", + { "vif": "ex commo", "mode": "culpa", "role": "enrollee", "pin": "anim qui" } + ] +} +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Output Example + +```json +{} +``` + +## status + +`status` + +- type: `Method` + +### status Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `vif` | string | Optional | + +#### vif + +##### Interface + +`vif` + +- is optional +- type: reference + +##### vif Type + +`string` + +- minimum length: 1 characters +- maximum length: 16 characters + +### Ubus CLI Example + +``` +ubus call wifi.wps status {"vif":"laboru"} +``` + +### JSONRPC Example + +```json +{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["<SID>", "wifi.wps", "status", { "vif": "laboru" }] } +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------- | ------------ | +| `code` | integer | **Required** | +| `status` | string | **Required** | + +#### code + +`code` + +- is **required** +- type: `integer` + +##### code Type + +`integer` + +- minimum value: `0` + +#### status + +`status` + +- is **required** +- type: `string` + +##### status Type + +`string` + +### Output Example + +```json +{ "code": 74811734, "status": "nisi Excepteur irure laboris ad" } +``` + +## stop + +`stop` + +- type: `Method` + +### stop Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Ubus CLI Example + +``` +ubus call wifi.wps stop {} +``` + +### JSONRPC Example + +```json +{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["<SID>", "wifi.wps", "stop", {}] } +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ---- | -------- | +| None | None | None | + +### Output Example + +```json +{} +``` + +## validate_pin + +`validate_pin` + +- type: `Method` + +### validate_pin Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | -------- | +| `input` | object | Optional | +| `output` | object | Optional | + +#### input + +`input` + +- is optional +- type: `object` + +##### input Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------ | ------------ | +| `pin` | string | **Required** | + +#### pin + +`pin` + +- is **required** +- type: reference + +##### pin Type + +`string` + +- minimum length: 8 characters +- maximum length: 8 characters + +### Ubus CLI Example + +``` +ubus call wifi.wps validate_pin {"pin":"ipsum am"} +``` + +### JSONRPC Example + +```json +{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["<SID>", "wifi.wps", "validate_pin", { "pin": "ipsum am" }] } +``` + +#### output + +`output` + +- is optional +- type: `object` + +##### output Type + +`object` with following properties: + +| Property | Type | Required | +| -------- | ------- | ------------ | +| `valid` | boolean | **Required** | + +#### valid + +`valid` + +- is **required** +- type: `boolean` + +##### valid Type + +`boolean` + +### Output Example + +```json +{ "valid": true } +``` diff --git a/docs/functionspec.md b/docs/functionspec.md new file mode 100644 index 0000000000000000000000000000000000000000..4c81d05e00cadff2e35a8b869c99541475a76dd6 --- /dev/null +++ b/docs/functionspec.md @@ -0,0 +1,316 @@ +# Function Specification + +The scope of wifimngr is to expose the libwifi APIs over ubus. + +``` +root@dc667cfd1b01:/builds/iopsys/wifimngr# ubus -v list +'wifi' @0af621bb + "status":{} +'wifi.ap.test5' @45e2e3f3 + "status":{} + "stats":{} + "assoclist":{} + "stations":{"sta":"String"} + "disconnect":{"sta":"String"} + "monitor":{"sta":"String","get":"Integer"} + "add_neighbor":{"bssid":"String","channel":"Integer","bssid_info":"String","reg":"Integer","phy":"Integer"} + "del_neighbor":{"bssid":"String"} + "list_neighbor":{"ssid":"String","client":"String"} + "request_neighbor":{"ssid":"String","client":"String"} + "request_transition":{"client":"String","bssid":"Array","timeout":"Integer"} + "add_vendor_ie":{"mgmt":"Integer","oui":"String","data":"String"} + "del_vendor_ie":{"mgmt":"Integer","oui":"String","data":"String"} +'wifi.radio.test5' @0806532f + "status":{} + "stats":{} + "get":{"param":"String"} + "scan":{"ssid":"String","bssid":"String","channel":"Integer"} + "scanresults":{"bssid":"String"} + "autochannel":{"interval":"Integer","algo":"Integer","scans":"Integer"} +'wifi.wps' @e5b4e9d9 + "start":{"vif":"String","mode":"String","role":"String","pin":"String"} + "stop":{} + "status":{"vif":"String"} + "generate_pin":{} + "validate_pin":{"pin":"String"} + "showpin":{"vif":"String"} + "setpin":{"vif":"String","pin":"String"} +``` + +# Contents +* [wifi](#wifi) +* [wifi.ap.\<name\>](#wifiapname) +* [wifi.radio.\<name\>](#wifiradioname) +* [wifi.wps](#wifiwps) + +## APIs + +Wifimngr publishes four different types objects, `wifi`, `wifi.ap.<name>`, +`wifi.radio.<name>` and `wifi.wps`. + +### wifi + +An object that publishes wifi radio and interface information. + +| Method | Function ID | +| :--- | :--- | +| [status](#status) | 1 | + +#### Methods + +Methods descriptions of the `wifi` object. + +##### status +Exposes wifi radio statistics over ubus. + +* [status documentation](./api/wifi.md#status) + +### wifi.ap.\<name\> +Object for wifi access point interface functionality. One object per access +point interface will be published. +````bash + "status":{} + "stats":{} + "assoclist":{} + "stations":{"sta":"String"} + "disconnect":{"sta":"String"} + "monitor":{"sta":"String","get":"Integer"} + "add_neighbor":{"bssid":"String","channel":"Integer","bssid_info":"String","reg":"Integer","phy":"Integer"} + "del_neighbor":{"bssid":"String"} + "list_neighbor":{"ssid":"String","client":"String"} + "request_neighbor":{"ssid":"String","client":"String"} + "request_transition":{"client":"String","bssid":"Array","timeout":"Integer"} + "add_vendor_ie":{"mgmt":"Integer","oui":"String","data":"String"} + "del_vendor_ie":{"mgmt":"Integer","oui":"String","data":"String"} +```` +| Method |Function ID | +| :--- | :--- | +| [status](#status-1) | 2 | +| [stats](#stats) | 3 | +| [assoclist](#assoclist) | 4 | +| [stations](#stations) | 5 | +| [disconnect](#disconnect) | 6 | +| [monitor](#monitor) | 7 | +| [add_neighbor](#add_neighbor) | 8 | +| [del_neighbor](#del_neighbor) | 9 | +| [list_neighbor](#list_neighbor) | 10 | +| [request_neighbor](#request_neighbor) | 11 | +| [request_transition](#request_transition) | 12 | +| [add_vendor_ie](#add_vendor_ie) | 13 | +| [del_vendor_ie](#del_vendor_ie) | 14 | + +#### Methods + +Method descriptions of the `wifi.ap.<name>` object. + +##### status + +Exposes access point interface statistics over ubus. + +* [status documentation](./api/wifi.ap.md#status) + +##### stats + +Exposes access point interface rx/tx statistics over ubus. + +* [stats documentation](./api/wifi.ap.md#stats) + +##### assoclist + +Exposes connected wireless clients over ubus. + +* [assoclist documentation](./api/wifi.ap.md#assoclist) + +##### stations + +Exposes client wifi client statistics over ubus. + +* [stations documentation](./api/wifi.ap.md#stations) + +##### disconnect + +Issue a deauthenticate to a wireles client. + +* [disconnect documentation](./api/wifi.ap.md#disconnect) + +##### monitor + +Monitor signal strength of unassociated station. + +* [monitor documentation](./api/wifi.ap.md#monitor) + +##### add_neighbor + +Add an access point to the neighbor list. + +* [add_neighbor documentation](./api/wifi.ap.md#add_neighbor) + +##### del_neighbor + +Delete an access point from the neighbor list + +* [del_neighbor documentation](./api/wifi.ap.md#del_neighbor) + +##### list_neighbor + +Prints neighbor access points in the network. + +* [list_neighbor documentation](./api/wifi.ap.md#list_neighbor) + +##### request_neighbor + +Triggers an 11k beacon report from an associated station. + +* [request_neighbor documentation](./api/wifi.ap.md#request_neighbor) + +##### request_transition + +Triggers an 11k beacon report from an associated station. + +* [request_transition documentation](./api/wifi.ap.md#request_transition) + +##### add_vendor_ie + +Appends vendor specific information element to an 802.11 management frame. + +* [add_vendor_ie documentation](./api/wifi.ap.md#add_vendor_ie) + +##### del_vendor_ie + +Remove vendor specific information element from an 802.11 management frame. + +* [del_vendor_ie documentation](./api/wifi.ap.md#del_vendor_ie) + +### wifi.radio.\<name\> + +Object for wifi device functionality. One object per device will be published to +ubus. + +````bash +'wifi.radio.test5' @0806532f + "status":{} + "stats":{} + "get":{"param":"String"} + "scan":{"ssid":"String","bssid":"String","channel":"Integer"} + "scanresults":{"bssid":"String"} + "autochannel":{"interval":"Integer","algo":"Integer","scans":"Integer"} +```` +| Method | Function ID | +| :--- | :--- | +| [status](#status-2) | 15 | +| [stats](#stats-1) | 16 | +| [get](#get) | 17 | +| [scan](#scan) | 18 | +| [scanresults](#scanresults) | 19 | +| [autochannel](#autochannel) | 20 | + +#### Methods + +Method descriptions of the `wifi.radio.<name>` object. + +##### status + +Exposes radio statistics over ubus. + +* [status documentation](./api/wifi.radio.md#status) + +##### stats + +Exposes radio stats over ubus. + +* [stats documentation](./api/wifi.radio.md#stats) + +##### get + +Exposes temperature of the WiFi card. + +* [get documentation](./api/wifi.radio.md#get) + +##### scan + +Scans the radio for broadcasted SSIDs. + +* [scan documentation](./api/wifi.radio.md#scan) + +##### scanresults + +Exposes available SSIDs from a radio scan over ubus. + +* [scanresults documentation](./api/wifi.radio.md#scanresults) + +##### autochannel + +Selects a channel for the radio to operate at. + +* [autochannel documentation](./api/wifi.radio.md#autochannel) + +### wifi.wps + +Object for WiFi Protected Setup functionality. + +````bash + "start":{"vif":"String","mode":"String","role":"String","pin":"String"} + "stop":{} + "status":{"vif":"String"} + "generate_pin":{} + "validate_pin":{"pin":"String"} + "showpin":{"vif":"String"} + "setpin":{"vif":"String","pin":"String"} +```` +| Method | Function ID | +| :--- | :--- | +| [start](#start) | 21 | +| [stop](#stop) | 22 | +| [status](#status-3) | 23 | +| [generate_pin](#generate_pin) | 24 | +| [validate_pin](#show_pin) | 25 | +| [showpin](#validate_pin) | 26 | +| [setpin](#setpin) | 27 | + +#### Methods + +Descriptions of `wifi.wps` methods. + + +##### start + +Initiates WPS functionality, default uses push button configuration (PBC). + +* [start documentation](./api/wifi.wps.md#start) + +##### stop + +Stops any WPS functionality. + +* [stop documentation](./api/wifi.wps.md#stop) + +##### status + +Gives current state of the WPS. + +* [status documentation](./api/wifi.wps.md#status) + +##### generate_pin + +Method generating a valid pin for WPS. + +* [generate_pin documentation](./api/wifi.wps.md#generate_pin) + +##### show_pin + +Shows currently set PIN, if any. + +* [showpin documentation](./api/wifi.wps.md#showpin) + + +##### validate_pin + +Takes a pin input and shows whether it is a valid PIN or not. + +* [validate_pin documentation](./api/wifi.wps.md#validate_pin) + +##### setpin + +Takes a pin input and sets it as the active WPS pin for the device. + +* [setpin documentation](./api/wifi.wps.md#setpin) diff --git a/docs/testspec.md b/docs/testspec.md new file mode 100644 index 0000000000000000000000000000000000000000..7cfc1edfbb64ef37e798b1dc5cf07eba081d5e1f --- /dev/null +++ b/docs/testspec.md @@ -0,0 +1,715 @@ +# Test Specification + +Most of the functionality in wifimngr can be tested via its ubus API. Each +API can be broken down into an individual test case to show full coverage is +achieved. + +# Sections +* [Preqreuisites](#prerequisites) +* [Test Suites](#test-suites) +* [Functional API Tests](#functional-api-tests) +* [Unit Tests](#unit-tests) +* [Functional Tests](#functional-tests) +* [Writing New Tests](#writing-new-tests) + + +## Prerequisites + +The only prerequisite for the wifimngr test suites is that libwifi has to be +built for the TEST platform, a versionprepared to publish dummy data for getter +API, and record setter API to a test logfile at `/tmp/test.log`. + +## Test Suites + +The wifimngr build pipe has three test suites, a functional-api suite, a unit +testi suite and functional test suite. + +### Functional API Tests + +The functional API tests consists of four individual test suites, one per object +Ubus under test. The functional API tests use the Ubus-API-validation +command-line interface tool to invoke a method, programmatically through +libubus, and validates it against the objects json-schema. + +#### wifi + +| Execution ID | Method | Description | Function ID Coverage | +| :--- | :--- | :--- | :--- | +| 1 | status | No argument | [1](./functionspec.md#status) | +| 2 | dummy | Negative Test | | + +#### wifi.ap.\<name\> + +| Execution ID | Method | Description | Function ID Coverage | +| :--- | :--- | :--- | :--- | +| 1 | status | No argument | [2](./functionspec.md#status-1) | +| 2 | stats | No argument | [3](./functionspec.md#stats) | +| 3 | assoclist | No argument | [4](./functionspec.md#assoclist) | +| 4 | stations | No argument | [5](./functionspec.md#stations) | +| 5 | stations | With sta argument | [5](./functionspec.md#stations) | +| 6 | list_neighbor | No argument | [10](./functionspec.md#list_neighbor) | +| 7 | list_neighbor | With client argument | [10](./functionspec.md#list_neighbor) | +| 8 | dummy | Negative Test | | + +#### wifi.radio.\<name\> + +| Execution ID | Method | Description | Function ID Coverage | +| :--- | :--- | :--- | :--- | +| 1 | status | No argument | [15](./functionspec.md#status-2) | +| 2 | stats | No argument | [16](./functionspec.md#stats-1) | +| 3 | scanresults | No argument | [19](./functionspec.md#scanresults) | +| 4 | scanresults | With bssid argument | [19](./functionspec.md#scanresults) | +| 5 | get | No argument | [17](./functionspec.md#get) | +| 6 | autochannel | No argument | [20](./functionspec.md#autochannel) | +| 7 | dummy | Negative Test | | + +#### wifi.wps + +| Execution ID | Method | Description | Function ID Coverage | +| :--- | :--- | :--- | :--- | +| 1 | status | No argument | [23](./functionspec.md#status-3) | +| 2 | status | With vif argument | [23](./functionspec.md#status-3) | +| 3 | generate_pin | No argument | [24](./functionspec.md#generate_pin) | +| 4 | validate_pin | With invalid pin argument | [26](./functionspec.md#validate_pin) | +| 5 | validate_pin | With valid pin argument | [26](./functionspec.md#validate_pin) | +| 6 | showpin | No argument | [25](./functionspec.md#showpin) | +| 7 | showpin | With vif argument | [25](./functionspec.md#showpin) | +| 8 | dummy | Negative Test | | + +### Unit Tests + +The wifimngr unit tests are written in cmocka, invoking the ubus callbacks +directly from the source code, which is compiled into a shared library. +This means mocking the arguments of a cli or libubus invoke in a +`struct blob_attr *`. The results of the call will be logged to the logfile at +`/tmp/test.log`. + +| Execution ID | Method | Test Case Name | Function ID Coverage | +| :--- | :--- | :--- | :--- | +| 1 | disconnect | [test_api_radio_disconnect](#test_api_radio_disconnect) | [6](./functionspec.md#disconnect) | +| 2 | request_transition | [test_api_req_bss_transition](#test_api_req_bss_transition) | [12](./functionspec.md#request_transition)| +| 3 | request_neighbor | [test_api_req_beacon_report](#test_api_req_beacon_report) | [11](./functionspec.md#request_neighbor) | +| 4 | add_neighbor | [test_api_add_nbr](#test_api_add_nbr) | [8](./functionspec.md#add_neighbor) | +| 5 | start | [test_api_wps_start](#test_api_wps_start) | [21](./functionspec.md#start) | +| 6 | stop | [test_api_wps_stop](#test_api_wps_stop) | [22](./functionspec.md#stop) | +| 7 | add_vendor_ie | [test_api_add_vendor_ie](#test_api_add_vendor_ie) | [13](./functionspec.md#add_vendor_ie) | +| 8 | del_vendor_ie | [test_api_del_vendor_ie](#test_api_del_vendor_ie) | [14](./functionspec.md#del_vendor_ie) | +| 9 | del_neighbor | [test_api_del_neighbor](#test_api_del_neighbor) | [9](./functionspec.md#del_neighbor) | +| 10 | monitor | [test_api_monitor_sta](#test_api_monitor_sta) | [7](./functionspec.md#monitor) | +| 11 | scan | [test_api_scan](#test_api_scan) | [18](./functionspec.md#scan) | +| 12 | setpin | [test_set_wps_ap_pin](#test_set_wps_ap_pin) | [27](./functionspec.md#setpin) | +| 13 | autochannel | [test_api_acs](#test_api_acs) | [20](./functionspec.md#autochannel) | + +#### test_api_radio_disconnect + +##### Description + +Tests the wifimngr ubus API callback `sta_disconnect(5)`, publishing the method +[disconnect](./functionspec.md#disconnect). + +##### Test Steps + +Prepare the arguments as: +````bash +{ "sta": "50:31:32:33:34:35" } +```` +Iussing a deauthenticate to a 5GHz client from the libwifi test platform. + +Read the logfile and verify that the `sta` argument, and interface, was +accurately logged. + +##### Test Expected Results + +The expected result is for the log file to have recorded a call to the +disconnect function, through the interface `test5` and with the argument `sta` +as `50:31:32:33:34:35`. + +````bash +[2020-02-04 13:06:12] disconnect: { "ifname": "test5", "sta": "50:31:32:33:34:35" } +```` + +#### test_api_req_bss_transition + +##### Description + +Tests the wifimngr ubus API callback `nbr_transition(5)`, publishing the method +[request_transition](./functionspec.md#request_transition). + +##### Test Steps + +Prepare the arguments as: + +````bash +{ "client": "50:31:32:33:34:35", "bssid": ["22:22:22:22:22:22", "11:11:11:11:11:11" ] } +```` + +Requesting a 5GHz client, `50:31:32:33:34:35`, to transition from bssid +`22:22:22:22:22:22` to bssid `11:11:11:11:11:11`. + +Read the logfile and verify that the interface and arguments were accurately +logged. + +##### Test Expected Results + +The expected result is for the log file to have recorded a call to the +req_bss_transition function, through the interface `test5` and with the argument `client` +as `50:31:32:33:34:35` and an array `bssid` with the entries +`"22:22:22:22:22:22","11:11:11:11:11:11"`. + +````bash +[2020-02-04 13:06:12] req_bss_transition: { "ifname": "test5", "client": "50:31:32:33:34:35", "bssid": ["22:22:22:22:22:22","11:11:11:11:11:11",] } +```` + + +#### test_api_req_beacon_report + +##### Description + +Tests the wifimngr ubus API callback `nbr_request(5)`, publishing the method +[request_neighbor](./functionspec.md#request_neighbor). + +##### Test Steps + +Prepare the arguments as: + +````bash +{ "client": "50:31:32:33:34:35", "ssid": "Test SSID 5GHz" } +```` + +Requesting the client `50:31:32:33:34:35` with the ssid `Test SSID 5GHz` as a +neighbor. + +Read the logfile and verify that the interface and arguments were accurately +logged. + +##### Test Expected Results + +The expected result is for the log file to have recorded a call to the +`nbr_request` function, through the interface `test5` and with the argument +`client` as `50:31:32:33:34:35`. Currently the `ssid` argument is ignored and +not expected to be observed from the log file. + +````bash +[2020-02-04 13:06:12] req_beacon_report: { "ifname": "test5", "client": "50:31:32:33:34:35" } +```` + +#### test_api_add_nbr + +##### Description + +Tests the wifimngr ubus API callback `nbr_add(5)`, publishing the method +[add_neighbor](./functionspec.md#add_neighbor). + +##### Test Steps + +Prepare the arguments as: + +````bash +{ "bssid": "00:11:12:13:14:15", "channel": 36, "bssid_info", "5", "reg": 5, "phy": 5 } +```` + +Requesting the neighbor bssid `00:11:12:13:14:15`, operating at channel 36 on +registry 5 and phy 5 to be added to the neighbor list. + +Read the logfile and verify that the interface and arguments were accurately +logged. + +##### Test Expected Results + +The expected result is for the log file to have recorded a call to the +`add_neighbor` function, through the interface `test5` and with the arguments +`bssid` as `00:11:12:13:14:15`, channel as 36, phy as 5, reg as 5, bssid_info as +"5". + +````bash +[2020-02-04 13:06:12] add_neighbor: { "ifname": "test5", "bssid_info": 5, "reg": 5, "channel": 36, "phy": 5, "bssid": "00:11:12:13:14:15" } +```` + +#### test_api_wps_start + +##### Description + +Tests the wifimngr ubus API callback `wps_start(5)`, publishing the method +[start](./functionspec.md#start) to the `wifi.wps` object. + +##### Test Steps + +The test case has three steps, trying different argument inputs to reach as high +coverage as possible. + +The first part of the test case tests the role registrar, with a pin, allowing +others devices to connect via pin, over the 5GHz interface. + +````bash +{ "vif": "test5", "pin": "24033848", "mode", "pin", "role": "registrar" } +```` + +The second part tests signing up with the role enrollee over the 2.4GHz +interface. + +````bash +{ "vif": "test2", "role": "enrollee" }` +```` + +The third part of the test case tests the mode pbc, allowing other devices to +synchronize over via its own push button configuration, over the 2.4GHz +interface. + +````bash +{ "vif": "test2", "mode": "pbc" }` +```` + +Read the logfile and verify that the interface and arguments were accurately +logged. + +##### Test Expected Results + +The expected result is for the log file to have recorded a call to the +`start_wps` function, showing the arguments accordingly, note that role +`registrar` is represented by 0, and `enrollee` by 1, whereas mode `pin` is +represented by 1 and `pbc` by 0. + + +````bash +[2020-02-04 13:06:12] start_wps: { "ifname": "test5", "pin": "24033848", "role": 4, "mode": 1 } +[2020-02-04 13:06:12] start_wps: { "ifname": "test2", "role": 1, "mode": 0 } +[2020-02-04 13:06:12] start_wps: { "ifname": "test2", "role": 0, "mode": 0 } +```` + +#### test_api_wps_stop + +##### Description + +Tests the wifimngr ubus API callback `wps_stop(5)`, publishing the method +[stop](./functionspec.md#stop) to the `wifi.wps` object. + +##### Test Steps + +Prepare the arguments as: + +````bash +{ "ifname": "test5" } +```` + +Stopping any active WPS activity on the 5GHz interface. + +Read the logfile and verify that the interface and arguments were accurately +logged. + +##### Test Expected Results + +As `wps_stop(5)` will call iterate all available interfaces and invoke the +libwifi API `wifi_stop_wps(1)` for each and every one, we expect to see all +(both) interfaces in the logs along with the function tag `stop_wps`. + +````bash +[2020-02-04 13:06:12] stop_wps: { "ifname": "test2" } +[2020-02-04 13:06:12] stop_wps: { "ifname": "test5" } +```` + +#### test_api_add_vendor_ie + +##### Description + +Tests the wifimngr ubus API callback `vsie_add(5)`, publishing the method +[add_vendor_ie](./functionspec.md#add_vendor_ie) to the `wifi.ap.<name>` object. + +##### Test Steps + +Prepare the arguments: + +````bash +{ "mgmt": 5, "oui": "112233", "data": "dd03efa567" } +```` + +Appending the vendor specific information to the management frame. + +##### Test Expected Results + +The expected result is to observe the function tag `add_vendor_ie` in the logs, +along with the prepared arguments, verifying that they have been parsed +correctly by wifimngr and libwifi. + +````bash +[2020-02-04 13:06:12] add_vendor_ie: { "ifname": "test5", "mgmt": 5, "oui": "112233", "data": "dd03efa567" } +```` + +#### test_api_del_vendor_ie + +##### Description + +Tests the wifimngr ubus API callback `vsie_del(5)`, publishing the method +[del_vendor_ie](./functionspec.md#del_vendor_ie) to the `wifi.ap.<name>` object. + +##### Test Steps + +Prepare the arguments: +````bash +{ "mgmt": 5, "oui": "112233", "data": "dd03efa567" } +```` + +Deleting the vendor specific information from the management frame. + +##### Test Expected Results +The expected result is to observe the function tag `del_vendor_ie` in the logs, +along with the prepared arguments, verifying that they have been parsed +correctly by wifimngr and libwifi. + +````bash +[2020-02-04 13:06:12] del_vendor_ie: { "ifname": "test5", "mgmt": 5, "oui": "112233", "data": "dd03efa567" } +```` + +#### test_api_del_neighbor + +##### Description + +Tests the wifimngr ubus API callback `nbr_del(5)`, publishing the method +[del_neighbor](./functionspec.md#del_neighbor) to the `wifi.ap.<name>` object. + +##### Test Steps + +Prepare the arguments: + +````bash +{ "bssid": "50:10:00:11:22:33" } +```` + +Removing the bssid from the neighbor list. + +##### Test Expected Results + +The expected result is to observe the function tag `del_neighbor` in the test +logs, along with the arguments, verifying that they have been parsed correctly +by wifimngr and libwifi. + +````bash +[2020-02-04 13:06:12] del_neighbor: { "ifname": "test5", "bssid": "50:10:00:11:22:33" } +```` + +#### test_api_monitor_sta + +##### Description + +Tests the wifimngr ubus API callback `sta_monitor(5)`, publishing the method +[monitor](./functionspec.md#monitor) to the `wifi.ap.<name>` object. + +##### Test Steps + +Prepare the arguments: + +````bash +{ "sta": "00:00:00:11:22:33" } +```` + +Starting to monitor the unassociated wireless client with the mac address +`00:00:00:11:22:33`. + +##### Test Expected Results + +The expected result is to observe the function tag `monitor_sta` in the test +logs, along with the 5GHz interface and the argument `sta` as +`00:00:00:11:22:33`. + +````bash +[2020-02-04 13:06:12] monitor_sta: { "ifname": "test5", "sta": "00:00:00:11:22:33" } +```` +#### test_api_scan + +##### Description + +Tests the wifimngr ubus API callback `wl_scan(5)`, publishing the method +[scan](./functionspec.md#scan) to the `wifi.radio.<name>` object. + +##### Test Steps + +Prepare the arguments: + +````bash +{ "ssid": "test", "bssid": "00:00:00:11:22:33", "channel": 36 } +```` + +Scanning the device using the ssid `test`. + +##### Test Expected Results + +The expected result is to observe the function tag `scan` in the test logs, +along with the 5GHz interface and the argument `test5` as +`ssid`, the remaining arguments are ignored as they are currently not +implemented or passed to libwifi. + +````bash +[2020-02-04 13:06:12] scan: { "ifname": "test5", "ssid": "test", "bssid": "00:00:00:00:00:00", "channel": 0, "type": 0 } +```` + +#### test_set_wps_ap_pin + +##### Description + +Tests the wifimngr ubus API callback `wps_set_ap_pin(5)`, publishing the method +[setpin](./functionspec.md#setpin) to the `wifi.wps` object. + +##### Test Steps + +Prepare the arguments: + +````bash +{ "ifname": "test5", "pin": "24033848" } +```` + +Setting the WPS pin of the 5GHz interface to 24033848. + +##### Test Expected Results + +The expected result is to observe the function tag `set_wps_ap_pin` in the test +logs, along with the 5GHz interface and the pin. + +````bash +[2020-02-04 13:06:12] set_wps_ap_pin: { "ifname": "test5", "pin": 24033848 } +```` + +#### test_api_acs + +##### Description + +Tests the wifimngr ubus API callback `wl_autochannel(5)`, publishing the method +[autochannel](./functionspec.md#autochannel) to the `wifi.radio.<name>` object. + +##### Test Steps + +Prepare the arguments: + +````bash +{ "ifname": "test5" } +```` + +Automatically selecting a channel to operate at. Currently no further arguments +are passed as they are ignored programmatically. + +##### Test Expected Results + +The expected result is to observe the function tag `acs` in the test +logs, along with the 5GHz interface. + +````bash +[2020-02-04 13:06:12] acs: { "ifname": "test5" } +```` + +### Functional Tests + +| Serial ID | Test Case Name | +| :--- | :--- | +| 1 | test_api_events | + +#### test_api_events + +##### Description + +Tests the event registration and receive process. Wifimngr will read the file +`/etc/wifi.json` in order to register to netlink events, in this case the +netlink family `easysoc` and the group `notify`. + + +``` +{ + "events" : [ + { + "type": "wifi-event", + "name": "cfg09ac03", + "ifname": "test5", + "family": "easysoc", + "group": [ + "notify" + ] + } + ] +} +``` + +##### Test Steps + +As netlink events are not being published in the docker environment, the test +will verify that a listener thread is created, registrates a listener and calls +the libwifi API for receiving events. + +As in practice the listener thread is intended to listen for events for the +entire lifetime of the process, there is no break condition for the listener +loop. However, in order to get a more accurate memory management report, the +event loop, `int wifimngr_recv_event(2)` is mocked to allow break on the return +code -1. + +``` +int wifimngr_recv_event(const char *ifname, void *handle) +{ + int err; + + for (;;) { + err = wifi_recv_event((char *)ifname, handle); + if (err < 0) + return -1; + } + + return 0; +} +``` + +##### Test Expected Results + +The expected results are that wifimngr will have attempted to register a listner +with the family `easysoc`, the group `notify` under the interface `test5`, and +attempted to receive events under the same interface, read from the test log +file under the function tags `register_event` and `recv_event.` + +````bash +[2020-02-05 09:38:40] register_event: { "ifname": "test5", "family": "easysoc", "group": "notify" } +[2020-02-05 09:38:40] recv_event: { "ifname": "test5" } +```` + +## Writing New Tests + +On the addition of new APIs to wifimngr and libwifi, additional tests should be +written to maintain the coverage and quality of the code. + +### Libwifi + +On a new addition to the libwifi API, the test platform for libwifi has to be +extended. The test platform for libwifi consists of two files, `test.c` and +`test.h`, found under the subdirectory `./libwifi/modules/` under the +[easy-soc-libs](https://dev.iopsys.eu/iopsys/easy-soc-libs) repository. + +The following examples assume the existence of a `struct test`. + +``` +struct test { + unsigned char sta[6]; +} +``` + +#### Getter + +Assume the addition of the new API, `get_client(2)`, taking an interface, +`char *` as first argument, and a `struct test *`, filling the +struct with the mac address of the first client in the interface. + +The first step is to prepare some dummy data in the header file, in this case +a dummy client of the type `struct test`. Two structs with static mac addresses +are to be prepared, one for each test interface, holding static data to +represent a mac address. Additionally, add a macro pointing to the address of +the structs with the dummy data. + +``` +/* 5GHz dummy data */ +const struct test test5_test_data = { + .sta = {"\x66\x55\x44\x33\x22\x11"} +}; + +/* 5GHz "pointer" to dummy data */ +#define test5_test &test5_test_data + +/* 2.4GHz dummy data */ +const struct test test2_test_data = { + .sta = {"\x11\x22\x33\x44\x55\x66"} +}; + +/* 2.4GHz "pointer" to dummy data */ +#define test2_test &test2_test_data +``` + +With the dummy data prepared, the function can be implemented. The test platform +has a set of macros prepared to use when filling variables with dummy data, +ranging from primitive types, buffers, arrays and structs. For this example +the helper macro `GET_TEST_BUF_TYPE(4)` will be used: + +``` +#define TESTDATA(band, attr) test ## band ## _ ## attr + +... + +#define GET_TEST_BUF_TYPE(o, iface, attr, type) \ +({ \ + if (ifname_to_band(iface) == 5) \ + memcpy(o, TESTDATA(5, attr), sizeof(type)); \ + else \ + memcpy(o, TESTDATA(2, attr), sizeof(type)); \ +}) +``` + +The macro will fill the first argument, `o`, wth the data pointed to by the +concatenated variable `test`, `5`, `_` and the `attr` argument, forming +`test5_test`. + +Therefore, implementing our dummy getter, `test_get_client(2)`, becomes simple. + +``` +int get_client(char *ifname, struct test *t) +{ + GET_TEST_BUF_TYPE(t, name, test, struct test); + + return 0; +} +``` + +Lastly, it should be added to the driver, assuming the driver has been updated +with a `get_client` function pointer: + +``` +const struct wifi_driver test_driver = { + .name = "test", + .get_client = test_get_client, + ... +}; +``` + +#### Setter + +In the case of an addition of a new setter to the libwifi API. A log function +is prepared in the test driver, logging a `char *` string to a test log file, +`/tmp/test.log`, `log_test(2)`. The first argument to `log_test(2)` is the +`char *` representing the format, and the second is a `va_list`; all the +arguments of the format. It is important the the format follows the structure + +``` +<FUNCTION_IDENTIFIER>: { <RELEVANT_ARGS> } +``` + +Assume the addition of a `set_client(2)` API call, the function should be +implemented in the test driver, calling `log_test(2)` to be able to verify the +struct usage and library linkage. Let's assume that the exposed Ubus API +takes an argument in the form of a mac address, that would be provded as an +argument, `sta`. + +``` +int test_set_client(char *ifname, struct test *t) +{ + log_test("set_client: { \"ifname\": \"%s\", \"sta\": \"%02x%02x%02x%02x%02x%02x\" }", + ifname, t->sta[0], t->sta[0], t->sta[0], + t->sta[0], t->sta[0], t->sta[0]); + + return 0; +} +``` + +This will log the entry as: + +``` +[2020-02-04 13:06:12] set_client: { "ifname": "test5", "sta": "00:11:22:33:44:55" } +``` + +Which can then be read by the corresponding test case and verified. + +### Writing Tests + +When extending the test cases themselves, getters should be tested via the +Ubus-API-validation tool for in the functional-api-test suite. + +Setters without any external dependencies (i.e. other processes) should be +included in the unit tests (`./test/api_test_wifi_setters.c`), and remaining +setters in the functional-test suite (`./test/function_test_wifi_event.c`). + +For the setter tests, a utility function has been prepared to parse the logfile +for the latest occurrance of a function identifier tag, `poll_test_log(2)`, +utility function have been prepared. The function takes a `FILE *` as first +argument, found in the `struct test_env`, and the function identifier as +second argument, returning the json payload found in the log file, if any. + +For more information on writing test cases see +[Continuous Integration at IOPSYS](https://dev.iopsys.eu/training/iopsyswrt-module-development/blob/master/testing/README.md) diff --git a/docs/ubus.splash.md b/docs/ubus.splash.md new file mode 100644 index 0000000000000000000000000000000000000000..ab638842a12aa805414a7744b5e67e910d05a4c5 --- /dev/null +++ b/docs/ubus.splash.md @@ -0,0 +1,6 @@ +# Ubus Generated APIs + +* [WiFi](./api/wifi.md) +* [Access Point](./api/wifi.ap.md) +* [Radio](./api/wifi.radio.md) +* [WiFi Protected Setup](./api/wifi.wps.md) diff --git a/gitlab-ci/functional-api-test.sh b/gitlab-ci/functional-api-test.sh new file mode 100755 index 0000000000000000000000000000000000000000..07fac0bcd8fda304629c739e49039cc54706ca85 --- /dev/null +++ b/gitlab-ci/functional-api-test.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +echo "preparation script" + +pwd + +make coverage -C ./ +supervisorctl status all +supervisorctl update +sleep 3 +supervisorctl status all + +# run API validation +ubus-api-validator -d ./test/api/json/ > ./api-result.log +supervisorctl stop all +supervisorctl status + +#report part +gcovr -r . --html --html-details -o ./api-test-coverage.html +gcovr -r . +cp /opt/work/memory-report.xml /builds/iopsys/wifimngr/api-test-memory-report.xml +tap-junit --input ./api-result.log --output report + + + diff --git a/gitlab-ci/functional-test.sh b/gitlab-ci/functional-test.sh new file mode 100755 index 0000000000000000000000000000000000000000..8b0829a07e8bdc9266cae69ebda131fe2fbf5922 --- /dev/null +++ b/gitlab-ci/functional-test.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +echo "preparation script" + +pwd + +supervisorctl status all +supervisorctl update +sleep 3 +supervisorctl status all + +make functional-test -C ./ + +supervisorctl stop all +supervisorctl status + +#report part +#GitLab-CI output +gcovr -r . +# Artefact +gcovr -r . --html --html-details -o ./functional-test-coverage.html + diff --git a/gitlab-ci/iopsys-supervisord.conf b/gitlab-ci/iopsys-supervisord.conf new file mode 100644 index 0000000000000000000000000000000000000000..c6749e4ee65eabb9c55d5c76e20ebe2e868f15b0 --- /dev/null +++ b/gitlab-ci/iopsys-supervisord.conf @@ -0,0 +1,5 @@ +[program:ubusd] +command=/bin/bash -c "/usr/sbin/ubusd" + +[program:wifimngr] +command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=memory-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes /builds/iopsys/wifimngr/wifimngr" diff --git a/gitlab-ci/setup.sh b/gitlab-ci/setup.sh new file mode 100755 index 0000000000000000000000000000000000000000..41b5c2c8fcf0370985e6d52e13838fa65333ca45 --- /dev/null +++ b/gitlab-ci/setup.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +echo "preparation script" + +pwd + +cp -r ./test/files/etc/* /etc/ +cp -r ./schemas/ubus/* /usr/share/rpcd/schemas +cp ./gitlab-ci/iopsys-supervisord.conf /etc/supervisor/conf.d/ + +ls /etc/config/ +ls /usr/share/rpcd/schemas/ +ls /etc/supervisor/conf.d/ + diff --git a/gitlab-ci/unit-test.sh b/gitlab-ci/unit-test.sh new file mode 100755 index 0000000000000000000000000000000000000000..9dce6f3782705b9219e0d6eb0ca614738daeb268 --- /dev/null +++ b/gitlab-ci/unit-test.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +echo "preparation script" + +pwd + +make unit-test -C ./ + +#report part +#GitLab-CI output +gcovr -r . +# Artefact +gcovr -r . --html --html-details -o ./unit-test-coverage.html diff --git a/main.c b/main.c index f35a335c137cfb8aacded2c873dda5a8abbf6d79..7366cc6780e6592449f00103a396401bba4ca8cf 100644 --- a/main.c +++ b/main.c @@ -115,7 +115,7 @@ out_exit: return -1; } -static int wifimngr_event_main(const char *evmap_file) +int wifimngr_event_main(const char *evmap_file) { struct json_object *jevs, *jev_array; int evproc = 0; diff --git a/schemas/ubus/definitions/definitions.json b/schemas/ubus/definitions/definitions.json new file mode 100644 index 0000000000000000000000000000000000000000..872f01ccd3559f1bd04c47a5f6586a7ce7dc373d --- /dev/null +++ b/schemas/ubus/definitions/definitions.json @@ -0,0 +1,171 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://www.iopsys.eu/definitions.json", + "definitions": { + "channel_2_t": { + "title": "2.4GHz Channel", + "type": "integer", + "default": "auto", + "minimum": 1, + "maximum": 14 + }, + "channel_5_t": { + "title": "5GHz Channel", + "type": "integer", + "default": "auto", + "minimum": 32, + "maximum": 200 + }, + "channels_2_t": { + "title": "2.4GHz Channels", + "type": "array", + "items": { "$ref": "https://www.iopsys.eu/definitions.json#/definitions/channel_2_t"} + }, + "channels_5_t": { + "title": "5GHz Channels", + "type": "array", + "items": { "$ref": "https://www.iopsys.eu/definitions.json#/definitions/channel_5_t"} + }, + "macaddr_t": { + "title": "MAC Address", + "type": "string", + "minLength": 17, + "maxLength": 17, + "pattern":"^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$" + }, + "nasid_t": { + "title": "MAC Address", + "type": "string", + "minLength": 1, + "maxLength": 48, + "pattern":"^([0-9a-fA-F]){1,48}$" + }, + "iface_t": { + "title": "Interface", + "type": "string", + "minLength": 1, + "maxLength": 16 + }, + "ssid_t": { + "title": "SSID", + "type": "string", + "minLength": 0, + "maxLength": 32 + }, + "nstations_t": { + "title": "Number of stations", + "type": "integer", + "minimum": 0, + "maximum": 2007 + }, + "bandwidth_2_t": { + "title": "Bandwidth", + "type": "integer", + "enum": [ + 20, + 40 + ] + }, + "bandwidth_5_t": { + "title": "Bandwidth", + "type": "integer", + "enum": [ + 20, + 40, + 80, + 160 + ] + }, + "rssi_t": { + "title": "RSSI", + "type": "integer", + "minimum": -128, + "maximum": 0 + }, + "noisepower_t": { + "title": "Noise", + "type": "integer", + "minimum": -127, + "maximum": 0 + }, + "band_t": { + "title": "WiFi Band", + "type": "string", + "enum": ["2.4GHz", "5GHz"] + }, + "standards_2_t": { + "title": "2.4GHz WiFi Standards", + "type": "array", + "items": { + "type": "string", + "enum": ["b", "g", "n", "ax"] + } + }, + "standards_5_t": { + "title": "5GHz WiFi Standards", + "type": "array", + "items": { + "type": "string", + "enum": ["a", "n", "ac", "ax"] + } + }, + "rxtx_t": { + "type": "integer", + "minimum": 0 + }, + "pin_t": { + "type": "string", + "minLength": 8, + "maxLength": 8, + "pattern": "^[0-9]*$" + }, + "bandwidth_t": { + "title": "Bandwidth", + "type": "integer", + "enum": [ + 20, + 40, + 80, + 160 + ] + }, + "aps_t": { + "type": "array", + "items": { + "type": "object", + "required": [ + "ifname", + "status", + "ssid", + "bssid" + ], + "properties": { + "ifname": { + "type": "string", + "minLength": 1, + "maxLength": 16 + }, + "status": { "type": "string" }, + "ssid": { + "type": "string", + "minLength": 0, + "maxLength": 32 + }, + "bssid": { "bssid": { "$ref": "https://www.iopsys.eu/definitions.json#/definitions/macaddr_t" } } + } + } + }, + "oui_t": { + "title": "Three byte oui", + "type": "string", + "minLength": 9, + "maxLength": 9, + "pattern":"^([0-9a-fA-F][0-9a-fA-F]){3}$" + }, + "data_t": { + "title": "Hex String", + "type": "string", + "pattern": "^[0-9a-fA-F]+" + } + } +} diff --git a/schemas/ubus/wifi.ap.json b/schemas/ubus/wifi.ap.json new file mode 100644 index 0000000000000000000000000000000000000000..c05d871578b81084fc30ec89785580c11cd22e1a --- /dev/null +++ b/schemas/ubus/wifi.ap.json @@ -0,0 +1,1192 @@ +{ + "definitions": { + "channel_2_t": { + "title": "2.4GHz Channel", + "type": "integer", + "default": "auto", + "minimum": 1, + "maximum": 14 + }, + "channel_5_t": { + "title": "5GHz Channel", + "type": "integer", + "default": "auto", + "minimum": 32, + "maximum": 200 + }, + "channels_2_t": { + "title": "2.4GHz Channels", + "type": "array", + "items": { "$ref": "#/definitions/channel_2_t"} + }, + "channels_5_t": { + "title": "5GHz Channels", + "type": "array", + "items": { "$ref": "#/definitions/channel_5_t"} + }, + "macaddr_t": { + "title": "MAC Address", + "type": "string", + "minLength": 17, + "maxLength": 17, + "pattern":"^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$" + }, + "nasid_t": { + "title": "MAC Address", + "type": "string", + "minLength": 1, + "maxLength": 48, + "pattern":"^([0-9a-fA-F]){1,48}$" + }, + "iface_t": { + "title": "Interface", + "type": "string", + "minLength": 1, + "maxLength": 16 + }, + "ssid_t": { + "title": "SSID", + "type": "string", + "minLength": 0, + "maxLength": 32 + }, + "nstations_t": { + "title": "Number of stations", + "type": "integer", + "minimum": 0, + "maximum": 2007 + }, + "bandwidth_2_t": { + "title": "Bandwidth", + "type": "integer", + "enum": [ + 20, + 40 + ] + }, + "bandwidth_5_t": { + "title": "Bandwidth", + "type": "integer", + "enum": [ + 20, + 40, + 80, + 160 + ] + }, + "rssi_t": { + "title": "RSSI", + "type": "integer", + "minimum": -128, + "maximum": 0 + }, + "noisepower_t": { + "title": "Noise", + "type": "integer", + "minimum": -127, + "maximum": 0 + }, + "band_t": { + "title": "WiFi Band", + "type": "string", + "enum": ["2GHz", "5GHz"] + }, + "standards_2_t": { + "title": "2.4GHz WiFi Standards", + "type": "array", + "items": { + "type": "string", + "enum": ["b", "g", "n", "ax"] + } + }, + "standards_5_t": { + "title": "5GHz WiFi Standards", + "type": "array", + "items": { + "type": "string", + "enum": ["a", "n", "ac", "ax"] + } + }, + "rxtx_t": { + "type": "integer", + "minimum": 0 + }, + "pin_t": { + "type": "string", + "minLength": 8, + "maxLength": 8, + "pattern": "^[0-9]*$" + }, + "bandwidth_t": { + "title": "Bandwidth", + "type": "integer", + "enum": [ + 20, + 40, + 80, + 160 + ] + }, + "aps_t": { + "type": "array", + "items": { + "type": "object", + "required": [ + "ifname", + "status", + "ssid", + "bssid" + ], + "properties": { + "ifname": { + "type": "string", + "minLength": 1, + "maxLength": 16 + }, + "status": { "type": "string" }, + "ssid": { + "type": "string", + "minLength": 0, + "maxLength": 32 + }, + "bssid": { "bssid": { "$ref": "#/definitions/macaddr_t" } } + } + } + }, + "oui_t": { + "title": "Three byte oui", + "type": "string", + "minLength": 9, + "maxLength": 9, + "pattern":"^([0-9a-fA-F][0-9a-fA-F]){3}$" + }, + "data_t": { + "title": "Hex String", + "type": "string", + "pattern": "^[0-9a-fA-F]+" + } + }, + "title": "wifi.ap.<name>", + "regex": true, + "object": "^wifi\\.ap\\..*", + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://www.iopsys.eu/wifi.ap.json", + "additionalProperties": false, + "properties": { + "add_neighbor": { + "type": "object", + "properties": { + "input": { + "type": "object", + "required": [ + "bssid", + "channel", + "bssid_info", + "reg", + "phy" + ], + "properties": { + "bssid": { + "$ref": "#/definitions/macaddr_t" + }, + "channel": { + "oneOf": [ + { + "$ref": "#/definitions/channel_2_t" + }, + { + "$ref": "#/definitions/channel_5_t" + } + ] + }, + "bssid_info": { + "type": "string" + }, + "reg": { + "type": "integer", + "minimum": 0 + }, + "phy": { + "type": "integer", + "minimum": 0 + } + } + }, + "output": { + "type": "object", + "properties": {} + } + } + }, + "del_neighbor": { + "type": "object", + "properties": { + "input": { + "type": "object", + "required": [ + "bssid" + ], + "properties": { + "bssid": { + "$ref": "#/definitions/macaddr_t" + } + } + }, + "output": { + "type": "object", + "properties": {} + } + } + }, + "request_neighbor": { + "type": "object", + "properties": { + "input": { + "type": "object", + "required": [ + "client" + ], + "properties": { + "ssid": { + "$ref": "#/definitions/ssid_t" + }, + "client": { + "$ref": "#/definitions/macaddr_t" + } + } + }, + "output": { + "type": "object", + "properties": {} + } + } + }, + "request_transition": { + "type": "object", + "properties": { + "input": { + "type": "object", + "required": [ + "client", + "bssid" + ], + "properties": { + "client": { + "$ref": "#/definitions/macaddr_t" + }, + "bssid": { + "type": "array", + "items": { + "$ref": "#/definitions/macaddr_t" + } + }, + "timeout": { + "type": "integer" + } + } + }, + "output": { + "type": "object", + "properties": {} + } + } + }, + "monitor": { + "type": "object", + "properties": { + "intput": { + "type": "object", + "required": [ + "sta" + ], + "properties": { + "sta": { + "$ref": "#/definitions/macaddr_t" + }, + "get": { + "type": "integer" + } + } + }, + "output": { + "type": "object", + "properties": {} + } + } + }, + "add_vendor_ie": { + "type": "object", + "properties": { + "input": { + "type": "object", + "required": [ + "mgmt", + "oui", + "data" + ], + "properties": { + "mgmt": { + "type": "integer" + }, + "oui": { + "$ref": "#/definitions/oui_t" + }, + "data": { + "$ref": "#/definitions/data_t" + } + } + }, + "output": { + "type": "object", + "properties": {} + } + } + }, + "del_vendor_ie": { + "type": "object", + "properties": { + "intput": { + "type": "object", + "required": [ + "mgmt", + "oui", + "data" + ], + "properties": { + "mgmt": { + "type": "integer" + }, + "oui": { + "$ref": "#/definitions/oui_t" + }, + "data": { + "$ref": "#/definitions/data_t" + } + } + }, + "output": { + "type": "object", + "properties": {} + } + } + }, + "disconnect": { + "type": "object", + "properties": { + "input": { + "type": "object", + "required": [ + "sta" + ], + "properties": { + "sta": { + "$ref": "#/definitions/macaddr_t" + } + } + }, + "output": { + "type": "object", + "properties": {} + } + } + }, + "status": { + "type": "object", + "properties": { + "input": { + "type": "object", + "properties": {} + }, + "output": { + "type": "object", + "required": [ + "ifname", + "status", + "ssid", + "bssid", + "encryption", + "bandwidth", + "standard", + "num_stations", + "utilization", + "adm_capacity", + "hidden", + "max_stations", + "capabilities" + ], + "properties": { + "ifname": { + "$ref": "#/definitions/iface_t" + }, + "status": { + "type": "string" + }, + "ssid": { + "$ref": "#/definitions/ssid_t" + }, + "bssid": { + "$ref": "#/definitions/macaddr_t" + }, + "encryption": { + "type": "string" + }, + "bandwidth": { + "oneOf": [ + { + "$ref": "#/definitions/bandwidth_2_t" + }, + { + "$ref": "#/definitions/bandwidth_5_t" + } + ] + }, + "standard": { + "type": "string" + }, + "num_stations": { + "$ref": "#/definitions/nstations_t" + }, + "utilization": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "adm_capacity": { + "type": "integer" + }, + "hidden": { + "type": "boolean" + }, + "max_stations": { + "$ref": "#/definitions/nstations_t" + }, + "capabilities": { + "type": "object", + "required": [ + "wmm", + "apsd", + "shortslot", + "dot11h" + ], + "properties": { + "wmm": { + "type": "boolean" + }, + "apsd": { + "type": "boolean" + }, + "shortslot": { + "type": "boolean" + }, + "dot11h": { + "type": "boolean" + }, + "dot11k": { + "required": [ + "dot11k_link_meas", + "dot11k_nbr_report", + "dot11k_bcn_passive", + "dot11k_bcn_active", + "dot11k_bcn_table", + "dot11k_rcpi", + "dot11k_rsni" + ], + "type": "object", + "properties": { + "dot11k_link_meas": { + "type": "boolean" + }, + "dot11k_nbr_report": { + "type": "boolean" + }, + "dot11k_bcn_passive": { + "type": "boolean" + }, + "dot11k_bcn_active": { + "type": "boolean" + }, + "dot11k_bcn_table": { + "type": "boolean" + }, + "dot11k_rcpi": { + "type": "boolean" + }, + "dot11k_rsni": { + "type": "boolean" + } + } + }, + "dot11n": { + "required": [ + "dot11n_ldpc", + "dot11n_40", + "dot11n_ps", + "dot11n_sgi20", + "dot11n_sgi40", + "dot11n_tx_stbc", + "dot11n_rx_stbc" + ], + "type": "object", + "properties": { + "dot11n_ldpc": { + "type": "boolean" + }, + "dot11n_40": { + "type": "boolean" + }, + "dot11n_ps": { + "type": "boolean" + }, + "dot11n_sgi20": { + "type": "boolean" + }, + "dot11n_sgi40": { + "type": "boolean" + }, + "dot11n_tx_stbc": { + "type": "boolean" + }, + "dot11n_rx_stbc": { + "type": "boolean" + } + } + }, + "dot11ac": { + "required": [ + "dot11ac_160", + "dot11ac_8080", + "dot11ac_mpdu_max", + "dot11ac_sgi80", + "dot11ac_sgi160", + "dot11ac_rx_ldpc", + "dot11ac_tx_stbc", + "dot11ac_rx_stbc_1ss", + "dot11ac_rx_stbc_2ss", + "dot11ac_rx_stbc_3ss", + "dot11ac_rx_stbc_4ss", + "dot11ac_su_beamformer", + "dot11ac_su_beamformee", + "dot11ac_mu_beamformer", + "dot11ac_mu_beamformee" + ], + "type": "object", + "properties": { + "dot11ac_160": { + "type": "boolean" + }, + "dot11ac_8080": { + "type": "boolean" + }, + "dot11ac_mpdu_max": { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "dot11ac_sgi80": { + "type": "boolean" + }, + "dot11ac_sgi160": { + "type": "boolean" + }, + "dot11ac_rx_ldpc": { + "type": "boolean" + }, + "dot11ac_tx_stbc": { + "type": "boolean" + }, + "dot11ac_rx_stbc_1ss": { + "type": "boolean" + }, + "dot11ac_rx_stbc_2ss": { + "type": "boolean" + }, + "dot11ac_rx_stbc_3ss": { + "type": "boolean" + }, + "dot11ac_rx_stbc_4ss": { + "type": "boolean" + }, + "dot11ac_su_beamformer": { + "type": "boolean" + }, + "dot11ac_su_beamformee": { + "type": "boolean" + }, + "dot11ac_mu_beamformer": { + "type": "boolean" + }, + "dot11ac_mu_beamformee": { + "type": "boolean" + } + } + } + } + } + } + } + } + }, + "stats": { + "type": "object", + "properties": { + "input": { + "type": "object", + "properties": {} + }, + "output": { + "type": "object", + "required": [ + "tx_bytes", + "tx_packets", + "tx_unicast_packets", + "tx_multicast_packets", + "tx_broadcast_packets", + "tx_error_packets", + "tx_retrans_packets", + "tx_retrans_fail_packets", + "tx_retry_packets", + "tx_multi_retry_packets", + "tx_dropped_packets", + "ack_fail_packets", + "aggregate_packets", + "rx_bytes", + "rx_packets", + "rx_unicast_packets", + "rx_multicast_packets", + "rx_broadcast_packets", + "rx_error_packets", + "rx_dropped_packets", + "rx_unknown_packets" + ], + "properties": { + "tx_bytes": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_unicast_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_multicast_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_broadcast_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_error_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_retrans_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_retrans_fail_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_retry_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_multi_retry_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_dropped_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "ack_fail_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "aggregate_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_bytes": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_unicast_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_multicast_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_broadcast_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_error_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_dropped_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_unknown_packets": { + "$ref": "#/definitions/rxtx_t" + } + } + } + } + }, + "stations": { + "type": "object", + "properties": { + "input": { + "type": "object", + "properties": { + "sta": { + "$ref": "#/definitions/macaddr_t" + } + } + }, + "output": { + "type": "object", + "required": [ + "stations" + ], + "properties": { + "stations": { + "type": "array", + "items": { + "type": "object", + "required": [ + "macaddr", + "wdev", + "frequency", + "rssi", + "snr", + "idle", + "in_network", + "tx_airtime", + "rx_airtime", + "airtime", + "max_rate", + "status", + "capabilities", + "stats", + "rssi_per_antenna" + ], + "properties": { + "macaddr": { + "$ref": "#/definitions/macaddr_t" + }, + "wdev": { + "$ref": "#/definitions/iface_t" + }, + "frequency": { + "$ref": "#/definitions/band_t" + }, + "rssi": { + "$ref": "#/definitions/rssi_t" + }, + "snr": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "idle": { + "type": "integer", + "minimum": 0 + }, + "in_network": { + "type": "integer", + "minimum": 0 + }, + "tx_airtime": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "rx_airtime": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "airtime": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "max_rate": { + "type": "integer", + "minimum": 0 + }, + "status": { + "type": "object", + "required": [ + "wmm", + "ps" + ], + "properties": { + "wmm": { + "type": "boolean" + }, + "ps": { + "type": "boolean" + } + } + }, + "capabilities": { + "type": "object", + "required": [ + "wmm", + "apsd", + "shortslot", + "dot11h", + "2040coex", + "psmp", + "proxy_arp", + "dot11v_btm" + ], + "properties": { + "wmm": { + "type": "boolean" + }, + "apsd": { + "type": "boolean" + }, + "shortslot": { + "type": "boolean" + }, + "dot11h": { + "type": "boolean" + }, + "dot11k": { + "required": [ + "dot11k_link_meas", + "dot11k_nbr_report", + "dot11k_bcn_passive", + "dot11k_bcn_active", + "dot11k_bcn_table", + "dot11k_rcpi", + "dot11k_rsni" + ], + "type": "object", + "properties": { + "dot11k_link_meas": { + "type": "boolean" + }, + "dot11k_nbr_report": { + "type": "boolean" + }, + "dot11k_bcn_passive": { + "type": "boolean" + }, + "dot11k_bcn_active": { + "type": "boolean" + }, + "dot11k_bcn_table": { + "type": "boolean" + }, + "dot11k_rcpi": { + "type": "boolean" + }, + "dot11k_rsni": { + "type": "boolean" + } + } + }, + "2040coex": { + "type": "boolean" + }, + "psmp": { + "type": "boolean" + }, + "proxy_arp": { + "type": "boolean" + }, + "dot11v_btm": { + "type": "boolean" + }, + "dot11n": { + "required": [ + "dot11n_ldpc", + "dot11n_40", + "dot11n_ps", + "dot11n_sgi20", + "dot11n_sgi40", + "dot11n_tx_stbc", + "dot11n_rx_stbc" + ], + "type": "object", + "properties": { + "dot11n_ldpc": { + "type": "boolean" + }, + "dot11n_40": { + "type": "boolean" + }, + "dot11n_ps": { + "type": "boolean" + }, + "dot11n_sgi20": { + "type": "boolean" + }, + "dot11n_sgi40": { + "type": "boolean" + }, + "dot11n_tx_stbc": { + "type": "boolean" + }, + "dot11n_rx_stbc": { + "type": "boolean" + } + } + }, + "dot11ac": { + "required": [ + "dot11ac_160", + "dot11ac_8080", + "dot11ac_mpdu_max", + "dot11ac_sgi80", + "dot11ac_sgi160", + "dot11ac_rx_ldpc", + "dot11ac_tx_stbc", + "dot11ac_rx_stbc_1ss", + "dot11ac_rx_stbc_2ss", + "dot11ac_rx_stbc_3ss", + "dot11ac_rx_stbc_4ss", + "dot11ac_su_beamformer", + "dot11ac_su_beamformee", + "dot11ac_mu_beamformer", + "dot11ac_mu_beamformee" + ], + "type": "object", + "properties": { + "dot11ac_160": { + "type": "boolean" + }, + "dot11ac_8080": { + "type": "boolean" + }, + "dot11ac_mpdu_max": { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "dot11ac_sgi80": { + "type": "boolean" + }, + "dot11ac_sgi160": { + "type": "boolean" + }, + "dot11ac_rx_ldpc": { + "type": "boolean" + }, + "dot11ac_tx_stbc": { + "type": "boolean" + }, + "dot11ac_rx_stbc_1ss": { + "type": "boolean" + }, + "dot11ac_rx_stbc_2ss": { + "type": "boolean" + }, + "dot11ac_rx_stbc_3ss": { + "type": "boolean" + }, + "dot11ac_rx_stbc_4ss": { + "type": "boolean" + }, + "dot11ac_su_beamformer": { + "type": "boolean" + }, + "dot11ac_su_beamformee": { + "type": "boolean" + }, + "dot11ac_mu_beamformer": { + "type": "boolean" + }, + "dot11ac_mu_beamformee": { + "type": "boolean" + } + } + } + } + }, + "stats": { + "type": "object", + "required": [ + "tx_total_pkts", + "tx_total_bytes", + "tx_failures", + "tx_pkts_retries", + "rx_data_pkts", + "rx_data_bytes", + "rx_failures", + "rate_of_last_tx_pkt", + "rate_of_last_rx_pkt" + ], + "properties": { + "tx_total_pkts": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_total_bytes": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_failures": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_pkts_retries": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_data_pkts": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_data_bytes": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_failures": { + "$ref": "#/definitions/rxtx_t" + }, + "rate_of_last_tx_pkt": { + "$ref": "#/definitions/rxtx_t" + }, + "rate_of_last_rx_pkt": { + "$ref": "#/definitions/rxtx_t" + } + } + }, + "rssi_per_antenna": { + "type": "array", + "items": { + "$ref": "#/definitions/rssi_t" + } + } + } + } + } + } + } + } + }, + "list_neighbor": { + "type": "object", + "properties": { + "input": { + "type": "object", + "properties": { + "ssid": { + "$ref": "#/definitions/ssid_t" + }, + "client": { + "$ref": "#/definitions/macaddr_t" + } + } + }, + "output": { + "type": "object", + "required": [ + "neighbors" + ], + "oneOf": [ + { + "properties": { + "neighbors": { + "type": "array", + "items": { + "type": "object", + "required": [ + "bssid", + "bss_info", + "regulatory", + "channel", + "phy" + ], + "properties": { + "bssid": { + "$ref": "#/definitions/macaddr_t" + }, + "bss_info": { + "type": "integer", + "minimum": 0 + }, + "regulatory": { + "type": "integer", + "minimum": 0 + }, + "channel": { + "oneOf": [ + { + "$ref": "#/definitions/channel_2_t" + }, + { + "$ref": "#/definitions/channel_5_t" + } + ] + }, + "phy": { + "type": "integer", + "minimum": 0, + "maximum": 9 + } + } + } + } + } + }, + { + "properties": { + "neighbors": { + "type": "array", + "items": { + "type": "object", + "required": [ + "bssid", + "rssi", + "rsni" + ], + "properties": { + "bssid": { + "$ref": "#/definitions/macaddr_t" + }, + "rssi": { + "$ref": "#/definitions/rssi_t" + }, + "rsni": { + "type": "integer" + } + } + } + } + } + } + ] + } + } + }, + "assoclist": { + "type": "object", + "properties": { + "input": { + "type": "object", + "properties": {} + }, + "output": { + "type": "object", + "required": [ + "assoclist" + ], + "properties": { + "assoclist": { + "type": "array", + "items": { + "type": "object", + "required": [ + "wdev", + "macaddr" + ], + "properties": { + "wdev": { + "$ref": "#/definitions/iface_t" + }, + "macaddr": { + "$ref": "#/definitions/macaddr_t" + } + } + } + } + } + } + } + } + } +} diff --git a/schemas/ubus/wifi.json b/schemas/ubus/wifi.json new file mode 100644 index 0000000000000000000000000000000000000000..f44aa038cb15b189b21ddd989a6579de73693fc1 --- /dev/null +++ b/schemas/ubus/wifi.json @@ -0,0 +1,276 @@ +{ + "definitions": { + "channel_2_t": { + "title": "2.4GHz Channel", + "type": "integer", + "default": "auto", + "minimum": 1, + "maximum": 14 + }, + "channel_5_t": { + "title": "5GHz Channel", + "type": "integer", + "default": "auto", + "minimum": 32, + "maximum": 200 + }, + "channels_2_t": { + "title": "2.4GHz Channels", + "type": "array", + "items": { "$ref": "#/definitions/channel_2_t"} + }, + "channels_5_t": { + "title": "5GHz Channels", + "type": "array", + "items": { "$ref": "#/definitions/channel_5_t"} + }, + "macaddr_t": { + "title": "MAC Address", + "type": "string", + "minLength": 17, + "maxLength": 17, + "pattern":"^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$" + }, + "nasid_t": { + "title": "MAC Address", + "type": "string", + "minLength": 1, + "maxLength": 48, + "pattern":"^([0-9a-fA-F]){1,48}$" + }, + "iface_t": { + "title": "Interface", + "type": "string", + "minLength": 1, + "maxLength": 16 + }, + "ssid_t": { + "title": "SSID", + "type": "string", + "minLength": 0, + "maxLength": 32 + }, + "nstations_t": { + "title": "Number of stations", + "type": "integer", + "minimum": 0, + "maximum": 2007 + }, + "bandwidth_2_t": { + "title": "Bandwidth", + "type": "integer", + "enum": [ + 20, + 40 + ] + }, + "bandwidth_5_t": { + "title": "Bandwidth", + "type": "integer", + "enum": [ + 20, + 40, + 80, + 160 + ] + }, + "rssi_t": { + "title": "RSSI", + "type": "integer", + "minimum": -128, + "maximum": 0 + }, + "noisepower_t": { + "title": "Noise", + "type": "integer", + "minimum": -127, + "maximum": 0 + }, + "band_t": { + "title": "WiFi Band", + "type": "string", + "enum": ["2GHz", "5GHz"] + }, + "standards_2_t": { + "title": "2.4GHz WiFi Standards", + "type": "array", + "items": { + "type": "string", + "enum": ["b", "g", "n", "ax"] + } + }, + "standards_5_t": { + "title": "5GHz WiFi Standards", + "type": "array", + "items": { + "type": "string", + "enum": ["a", "n", "ac", "ax"] + } + }, + "rxtx_t": { + "type": "integer", + "minimum": 0 + }, + "pin_t": { + "type": "string", + "minLength": 8, + "maxLength": 8, + "pattern": "^[0-9]*$" + }, + "bandwidth_t": { + "title": "Bandwidth", + "type": "integer", + "enum": [ + 20, + 40, + 80, + 160 + ] + }, + "aps_t": { + "type": "array", + "items": { + "type": "object", + "required": [ + "ifname", + "status", + "ssid", + "bssid" + ], + "properties": { + "ifname": { + "type": "string", + "minLength": 1, + "maxLength": 16 + }, + "status": { "type": "string" }, + "ssid": { + "type": "string", + "minLength": 0, + "maxLength": 32 + }, + "bssid": { "bssid": { "$ref": "#/definitions/macaddr_t" } } + } + } + }, + "oui_t": { + "title": "Three byte oui", + "type": "string", + "minLength": 9, + "maxLength": 9, + "pattern":"^([0-9a-fA-F][0-9a-fA-F]){3}$" + }, + "data_t": { + "title": "Hex String", + "type": "string", + "pattern": "^[0-9a-fA-F]+" + } + }, + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://www.iopsys.eu/wifi.json", + "type": "object", + "title": "wifi", + "object": "wifi", + "additionalProperties": false, + "properties": { + "status": { + "type": "object", + "properties": { + "input": { + "type": "object", + "properties": {} + }, + "output": { + "type": "object", + "required": [ + "radios" + ], + "properties": { + "radios": { + "type": "array", + "items": { + "type": "object", + "required": [ + "name", + "isup", + "standard", + "country", + "band", + "channel", + "bandwidth", + "noise", + "rate", + "channels", + "accesspoints", + "backhauls" + ], + "if": { + "properties": { + "band": { + "const": "2GHz" + } + } + }, + "then": { + "properties": { + "channel": { + "$ref": "#/definitions/channel_2_t" + }, + "channels": { + "$ref": "#/definitions/channels_2_t" + } + } + }, + "else": { + "properties": { + "channel": { + "$ref": "#/definitions/channel_5_t" + }, + "channels": { + "$ref": "#/definitions/channels_5_t" + } + } + }, + "properties": { + "name": { + "$ref": "#/definitions/iface_t" + }, + "isup": { + "type": "boolean" + }, + "standard": { + "type": "string" + }, + "country": { + "type": "string", + "minLength": 2, + "maxLength": 3 + }, + "band": { + "$ref": "#/definitions/band_t" + }, + "bandwidth": { + "$ref": "#/definitions/bandwidth_t" + }, + "noise": { + "$ref": "#/definitions/noisepower_t" + }, + "rate": { + "type": "integer", + "minimum": 0 + }, + "accesspoints": { + "$ref": "#/definitions/aps_t" + }, + "backhauls": { + "$ref": "#/definitions/aps_t" + } + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/schemas/ubus/wifi.radio.json b/schemas/ubus/wifi.radio.json new file mode 100644 index 0000000000000000000000000000000000000000..0d0030dab5a96c559b69e1f4dd5200de96f0d165 --- /dev/null +++ b/schemas/ubus/wifi.radio.json @@ -0,0 +1,569 @@ +{ + "definitions": { + "channel_2_t": { + "title": "2.4GHz Channel", + "type": "integer", + "default": "auto", + "minimum": 1, + "maximum": 14 + }, + "channel_5_t": { + "title": "5GHz Channel", + "type": "integer", + "default": "auto", + "minimum": 32, + "maximum": 200 + }, + "channels_2_t": { + "title": "2.4GHz Channels", + "type": "array", + "items": { + "$ref": "#/definitions/channel_2_t" + } + }, + "channels_5_t": { + "title": "5GHz Channels", + "type": "array", + "items": { + "$ref": "#/definitions/channel_5_t" + } + }, + "macaddr_t": { + "title": "MAC Address", + "type": "string", + "minLength": 17, + "maxLength": 17, + "pattern": "^([0-9a-fA-F][0-9a-fA-F]:){5}[0-9a-fA-F][0-9a-fA-F]$" + }, + "nasid_t": { + "title": "MAC Address", + "type": "string", + "minLength": 1, + "maxLength": 48, + "pattern": "^([0-9a-fA-F]){1,48}$" + }, + "iface_t": { + "title": "Interface", + "type": "string", + "minLength": 1, + "maxLength": 16 + }, + "ssid_t": { + "title": "SSID", + "type": "string", + "minLength": 0, + "maxLength": 32 + }, + "nstations_t": { + "title": "Number of stations", + "type": "integer", + "minimum": 0, + "maximum": 2007 + }, + "bandwidth_2_t": { + "title": "Bandwidth", + "type": "integer", + "enum": [ + 20, + 40 + ] + }, + "bandwidth_5_t": { + "title": "Bandwidth", + "type": "integer", + "enum": [ + 20, + 40, + 80, + 160 + ] + }, + "rssi_t": { + "title": "RSSI", + "type": "integer", + "minimum": -128, + "maximum": 0 + }, + "noisepower_t": { + "title": "Noise", + "type": "integer", + "minimum": -127, + "maximum": 0 + }, + "band_t": { + "title": "WiFi Band", + "type": "string", + "enum": [ + "2GHz", + "5GHz" + ] + }, + "standards_2_t": { + "title": "2.4GHz WiFi Standards", + "type": "string", + "enum": [ + "802.11b", + "802.11g", + "802.11n", + "802.11ax" + ] + }, + "standards_5_t": { + "title": "5GHz WiFi Standards", + "type": "string", + "enum": [ + "802.11a", + "802.11n", + "802.11ac", + "802.11ax" + ] + }, + "rxtx_t": { + "type": "integer", + "minimum": 0 + }, + "pin_t": { + "type": "string", + "minLength": 8, + "maxLength": 8, + "pattern": "^[0-9]*$" + }, + "bandwidth_t": { + "title": "Bandwidth", + "type": "integer", + "enum": [ + 20, + 40, + 80, + 160 + ] + }, + "aps_t": { + "type": "array", + "items": { + "type": "object", + "required": [ + "ifname", + "status", + "ssid", + "bssid" + ], + "properties": { + "ifname": { + "type": "string", + "minLength": 1, + "maxLength": 16 + }, + "status": { + "type": "string" + }, + "ssid": { + "type": "string", + "minLength": 0, + "maxLength": 32 + }, + "bssid": { + "bssid": { + "$ref": "#/definitions/macaddr_t" + } + } + } + } + }, + "oui_t": { + "title": "Three byte oui", + "type": "string", + "minLength": 9, + "maxLength": 9, + "pattern": "^([0-9a-fA-F][0-9a-fA-F]){3}$" + }, + "data_t": { + "title": "Hex String", + "type": "string", + "pattern": "^[0-9a-fA-F]+" + }, + "scanresult_t": { + "type": "object", + "required": [ + "standard", + "bandwidth", + "channel", + "ssid", + "bssid", + "encryption", + "band", + "rssi", + "load_stas", + "load_utilization", + "load_available" + ], + "if": { + "properties": { + "band": { + "const": "2GHz" + } + } + }, + "then": { + "properties": { + "standard": { + "$ref": "#/definitions/standards_2_t" + }, + "bandwidth": { + "$ref": "#/definitions/bandwidth_2_t" + }, + "channel": { + "$ref": "#/definitions/channel_2_t" + } + } + }, + "else": { + "properties": { + "standard": { + "$ref": "#/definitions/standards_5_t" + }, + "bandwidth": { + "$ref": "#/definitions/bandwidth_5_t" + }, + "channel": { + "$ref": "#/definitions/channel_5_t" + } + } + }, + "properties": { + "ssid": { + "$ref": "#/definitions/ssid_t" + }, + "bssid": { + "$ref": "#/definitions/macaddr_t" + }, + "encryption": { + "type": "string" + }, + "band": { + "$ref": "#/definitions/band_t" + }, + "rssi": { + "$ref": "#/definitions/rssi_t" + }, + "load_stas": { + "type": "integer", + "minimum": 0 + }, + "load_utilization": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "load_available": { + "type": "integer", + "minimum": 0 + } + } + } + }, + "object": "^wifi\\.radio\\..*", + "regex": true, + "title": "wifi.radio.<name>", + "description": "WiFi Radio Object", + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://www.iopsys.eu/wifi.radio.json", + "additionalProperties": false, + "properties": { + "autochannel": { + "type": "object", + "properties": { + "input": { + "type": "object", + "properties": { + "interval": { + "type": "integer" + }, + "algo": { + "type": "integer" + }, + "scans": { + "type": "integer" + } + } + }, + "output": { + "description": "Auto channel selection", + "type": "object", + "title": "wifi.radio.autochannel", + "required": [ + "code", + "new_channel", + "status" + ], + "properties": { + "code": { + "type": "integer" + }, + "new_channel": { + "oneOf": [ + { + "$ref": "#/definitions/channel_2_t" + }, + { + "$ref": "#/definitions/channel_5_t" + } + ] + }, + "status": { + "type": "string" + } + } + } + } + }, + "scan": { + "type": "object", + "properties": { + "input": { + "type": "object", + "properties": { + "ssid": { + "$ref": "#/definitions/ssid_t" + }, + "bssid": { + "$ref": "#/definitions/macaddr_t" + }, + "channel": { + "oneOf": [ + { + "$ref": "#/definitions/channel_2_t" + }, + { + "$ref": "#/definitions/channel_5_t" + } + ] + } + } + }, + "output": { + "description": "Trigger a scan", + "type": "object", + "properties": {} + } + } + }, + "scanresults": { + "type": "object", + "properties": { + "input": { + "type": "object", + "properties": {} + }, + "output": { + "description": "Show scan results", + "type": "object", + "oneOf": [ + { + "required": [ + "accesspoints" + ], + "properties": { + "accesspoints": { + "type": "array", + "items": { + "$ref": "#/definitions/scanresult_t" + } + } + } + }, + { + "$ref": "#/definitions/scanresult_t" + } + ] + } + } + }, + "stats": { + "type": "object", + "properties": { + "input": { + "type": "object", + "properties": {} + }, + "output": { + "description": "Radio statistics", + "type": "object", + "title": "wifi.radio.iface", + "required": [ + "tx_bytes", + "tx_packets", + "tx_error_packets", + "tx_dropped_packets", + "rx_bytes", + "rx_packets", + "rx_error_packets", + "rx_dropped_packets", + "rx_fcs_error_packets" + ], + "properties": { + "tx_bytes": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_error_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "tx_dropped_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_bytes": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_error_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_dropped_packets": { + "$ref": "#/definitions/rxtx_t" + }, + "rx_fcs_error_packets": { + "$ref": "#/definitions/rxtx_t" + } + } + } + } + }, + "status": { + "type": "object", + "properties": { + "input": { + "type": "object", + "properties": {} + }, + "output": { + "description": "Radio status", + "type": "object", + "title": "wifi.radio.iface", + "required": [ + "radio", + "isup", + "band", + "channel", + "bandwidth", + "noise", + "maxrate", + "beacon_int", + "dtim_period", + "short_retry_limit", + "long_retry_limit", + "frag_threshold", + "rts_threshold" + ], + "if": { + "properties": { + "band": { + "const": "2GHz" + } + } + }, + "then": { + "properties": { + "bandwidth": { + "$ref": "#/definitions/bandwidth_2_t" + }, + "channel": { + "$ref": "#/definitions/channel_2_t" + } + } + }, + "else": { + "properties": { + "bandwidth": { + "$ref": "#/definitions/bandwidth_5_t" + }, + "channel": { + "$ref": "#/definitions/channel_5_t" + } + } + }, + "properties": { + "radio": { + "$ref": "#/definitions/iface_t" + }, + "isup": { + "type": "boolean" + }, + "band": { + "$ref": "#/definitions/band_t" + }, + "noise": { + "$ref": "#/definitions/noisepower_t" + }, + "maxrate": { + "type": "integer", + "minimum": 0 + }, + "beacon_int": { + "type": "integer", + "default": 100, + "minimum": 1, + "maximum": 65535 + }, + "dtim_period": { + "type": "integer", + "default": 1, + "minimum": 1, + "maximum": 255 + }, + "short_retry_limit": { + "type": "integer", + "minimum": 1, + "maximum": 255 + }, + "long_retry_limit": { + "type": "integer", + "minimum": 1, + "maximum": 255 + }, + "frag_threshold": { + "type": "integer", + "default": 2346, + "minimum": 256, + "maximum": 65535 + }, + "rts_threshold": { + "type": "integer", + "default": 2347, + "minimum": 0, + "maximum": 65535 + } + } + } + } + }, + "get": { + "type": "object", + "properties": { + "input": { + "type": "object", + "properties": { + "param": { + "type": "string" + } + } + }, + "output": { + "type": "object", + "properties": { + "status": { + "type": "integer" + }, + "values": { + "type": "integer" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/schemas/uci/wireless.json b/schemas/uci/wireless.json new file mode 100644 index 0000000000000000000000000000000000000000..37a78806c04cf5b969b13d7afba5ac49e2b3d324 --- /dev/null +++ b/schemas/uci/wireless.json @@ -0,0 +1,121 @@ +{ + "wireless": [{ + "section": "wifi-device", + "description": "Wifi Device Settings", + "multi": true, + "options": [{ + "name": "channel", + "type": "integer or “auto”", + "required": "yes", + "default": "auto", + "description": "Specifies the wireless channel to use. “auto” defaults to the lowest available channel." + }, + { + "name": "hwmode", + "default": null, + "description": "Selects the wireless protocol to use, possible values are 11b, 11g, and 11a. Note that 11ng and 11na are not available options.", + "type": "string" + }, + { + "name": "country", + "default": null, + "description": "Specifies the country code, affects the available channels and transmission powers. For type broadcom a two letter country code is used (EN or DE). The madwifi driver expects a numeric code.", + "type": "varies" + }, + { + "name": "band", + "default": null, + "description": "Whether radio operates at 2.4GHz or 5GHz.", + "type": "string" + }, + { + "name": "bandwidth", + "default": "80", + "description": "Frequency at which the radio operates.", + "type": "integer" + } + ] + }, + { + "section": "wifi-iface", + "description": "Wifi Interface Settings", + "multi": true, + "options": [{ + "name": "device", + "type": "string", + "required": "yes", + "default": "(first device id)", + "description": "Specifies the used wireless adapter, must refer to one of the defined wifi-device sections" + }, + { + "name": "ifname", + "type": "string", + "required": "no", + "default": "(driver default)", + "description": "Specifies a custom name for the Wi-Fi interface, which is otherwise automatically named." + }, + { + "name": "mode", + "required": "yes", + "default": "ap", + "description": "Selects the operation mode of the wireless network interface controller. Possible values are ap, sta, adhoc, wds, monitor, mesh", + "type": "string" + }, + { + "name": "encryption", + "default": null, + "description": "Wireless encryption method. Possible values are: none, wep, psk, psk2. For WEP station mode the default is “open system” authentication. Use wep+shared or wep+open to force a specific mode.", + "type": "string" + }, + { + "name": "wps", + "description": "Enable wps_pushbutton and wps_label.", + "type": "boolean", + "default": true + }, + { + "name": "wps_config", + "description": "List of configuration methods. Currentlly supported methods are: push_button.", + "default": null, + "type": "list" + }, + { + "name": "wps_device_name", + "description": "User-friendly description of device; up to 32 octets encoded in UTF-8.", + "type": "string", + "default": "LEDE AP" + }, + { + "name": "wps_device_type", + "description": "Primary device type. Examples: 1-0050F204-1 (Computer / PC), 1-0050F204-2 (Computer / Server), 5-0050F204-1 (Storage / NAS), 6-0050F204-1 (Network Infrastructure / AP)", + "type": "string", + "default": "6-0050F204-1" + }, + { + "name": "wps_label", + "description": "Enable label configuration method.", + "type": "boolean", + "default": true + }, + { + "name": "wps_manufacturer", + "description": "The manufacturer of the device (up to 64 ASCII characters).", + "type": "string", + "default": "lede-project.org" + }, + { + "name": "wps_pushbutton", + "description": "Enable push-button configuration method.", + "type": "boolean", + "default": true + }, + { + "name": "wps_pin", + "description": "The PIN to use with WPS-PIN (only in external registrar mode?)", + "type": "string", + "default": null + } + ] + } + ] +} \ No newline at end of file diff --git a/test/api/json/wifi.ap.validation.json b/test/api/json/wifi.ap.validation.json new file mode 100644 index 0000000000000000000000000000000000000000..ec72478aba0724f37f94a0858e8d9e4c313e177d --- /dev/null +++ b/test/api/json/wifi.ap.validation.json @@ -0,0 +1,46 @@ +{ + "object": "wifi.ap.test5", + "methods": [ + { + "method": "status", + "rc": 0 + }, + { + "method": "stats", + "rc": 0 + }, + { + "method": "assoclist", + "rc": 0 + }, + { + "method": "stations", + "rc": 0 + }, + { + "method": "stations", + "args": { + "sta":"50:31:32:33:34:35" + }, + "rc": 0 + }, + { + "method": "list_neighbor" + }, + { + "method": "list_neighbor", + "args": { + "client": "50:31:32:33:34:35" + }, + "rc": 0 + }, + { + "method": "hello", + "args": { + "bssid": "50:31:32:33:34:35" + }, + "rc": 3 + } + ] +} + diff --git a/test/api/json/wifi.radio.validation.json b/test/api/json/wifi.radio.validation.json new file mode 100644 index 0000000000000000000000000000000000000000..cb51aa9ef8d86a7711f4408c47b12771dda0a0b2 --- /dev/null +++ b/test/api/json/wifi.radio.validation.json @@ -0,0 +1,37 @@ +{ + "object": "wifi.radio.test5", + "methods": [ + { + "method": "status", + "rc": 0 + }, + { + "method": "stats", + "rc": 0 + }, + { + "method": "scanresults", + "rc": 0 + }, + { + "method": "scanresults", + "args": { + "bssid": "00:61:62:63:64:65" + }, + "rc": 0 + }, + { + "method": "get", + "rc": 0 + }, + { + "method": "autochannel", + "rc": 0 + }, + { + "method": "hello", + "rc": 3 + } + ] +} + diff --git a/test/api/json/wifi.validation.json b/test/api/json/wifi.validation.json new file mode 100644 index 0000000000000000000000000000000000000000..4253b5bbcac3c54fe5120559ffa5df6f635e0055 --- /dev/null +++ b/test/api/json/wifi.validation.json @@ -0,0 +1,14 @@ +{ + "object": "wifi", + "methods": [ + { + "method": "status", + "rc": 0 + }, + { + "method": "hello", + "rc": 3 + } + ] +} + diff --git a/test/api/json/wifi.wps.validation.json b/test/api/json/wifi.wps.validation.json new file mode 100644 index 0000000000000000000000000000000000000000..e945fb0fc0b3ed92b1c18baf0d316a1e56f03a3d --- /dev/null +++ b/test/api/json/wifi.wps.validation.json @@ -0,0 +1,49 @@ +{ + "object": "wifi.wps", + "methods": [ + { + "method": "status", + "rc": 0 + }, + { + "method": "status", + "args": { + "vif": "test2" + }, + "rc": 0 + }, + { + "method": "generate_pin", + "rc": 0 + }, + { + "method": "validate_pin", + "args": { + "pin": "1111111" + }, + "rc": 0 + }, + { + "method": "validate_pin", + "args": { + "pin": "37780906" + }, + "rc": 0 + }, + { + "method": "showpin", + "rc": 0 + }, + { + "method": "showpin", + "args": { + "vif": "test2" + }, + "rc": 0 + }, + { + "method": "hello", + "rc": 3 + } + ] +} \ No newline at end of file diff --git a/test/cmocka/Makefile b/test/cmocka/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3b416d8e1aaf975049c16dc413bb4314dc2ef37d --- /dev/null +++ b/test/cmocka/Makefile @@ -0,0 +1,30 @@ +CC = gcc +WIFIMNGR_LIB_DIR ?= $(shell dirname $(PWD)) +WIFIMNGR_LIB = -lwifimngr -L$(WIFIMNGR_LIB_DIR) +CMOCKA_LIB = -l cmocka +LIBS = $(WIFIMNGR_LIB) $(CMOCKA_LIB) -lwifi-5 -pthread -luci -lubus -lubox -ljson-c -lblobmsg_json -lnl-genl-3 -lnl-3 -ljson-validator -ljson-schema-validator -ljson-editor +CFLAGS = -g -Wall -I../.. +LDFLAGS = $(LIBS) -Wl,-rpath=$(WIFIMNGR_LIB_DIR) -I$(WIFIMNGR_LIB_DIR) +UNIT_TESTS = unit_test_wifi +FUNCTIONAL_TESTS = functional_test_wifi +UTILS = test_utils.o + +VALGRIND = valgrind --leak-check=full --show-reachable=no \ + --show-leak-kinds=all --errors-for-leak-kinds=all \ + --error-exitcode=1 --track-origins=yes + +unit_test_wifi: $(UTILS) unit_test_wifi.o + $(CC) -o $@ $^ $(LDFLAGS) + +functional_test_wifi: $(UTILS) functional_test_wifi.o + $(CC) -o $@ $^ $(LDFLAGS) + +unit-test: $(UNIT_TESTS) + $(foreach testprog, $(UNIT_TESTS), sudo $(VALGRIND) ./$(testprog);) + +functional-test: $(FUNCTIONAL_TESTS) + $(foreach testprog, $(FUNCTIONAL_TESTS), sudo $(VALGRIND) ./$(testprog);) + +.PHONY: clean +clean: + rm $(UNIT_TESTS) $(FUNCTIONAL_TESTS) *.o -fv diff --git a/test/cmocka/functional_test_wifi.c b/test/cmocka/functional_test_wifi.c new file mode 100644 index 0000000000000000000000000000000000000000..ae383f809a814c0ad6d84de8a4692933d7ef9e8a --- /dev/null +++ b/test/cmocka/functional_test_wifi.c @@ -0,0 +1,113 @@ +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> + +#include <libubus.h> +#include <libubox/blobmsg_json.h> +#include <libubox/blobmsg.h> + +#include <json-validator.h> +#include <json-c/json.h> +#include <json-editor.h> + +#include <json-c/json_tokener.h> +#include <wifi.h> + +#include "wifimngr.h" +#include "test_utils.h" + +struct test_ctx { + FILE *fp; +}; + +int wifimngr_event_main(const char *evmap_file); + +int wifimngr_recv_event(const char *ifname, void *handle) +{ + int err; + + for (;;) { + err = wifi_recv_event((char *)ifname, handle); + if (err < 0) + return -1; + } + + return 0; +} + + +static void test_api_events(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct json_object *jobj, *tmp; + const char *prefix = "register_event"; + + wifimngr_event_main("/etc/wifi.json"); + + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + tmp = json_object_get_by_string(jobj, "family"); + assert_string_equal(json_object_get_string(tmp), "easysoc"); + + tmp = json_object_get_by_string(jobj, "group"); + assert_string_equal(json_object_get_string(tmp), "notify"); + + json_object_put(jobj); + + prefix = "recv_event"; + + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + json_object_put(jobj); +} + +static int group_setup(void **state) +{ + struct test_ctx *ctx = calloc(1, sizeof(struct test_ctx)); + + if (!ctx) + return -1; + + remove("/tmp/test.log"); + + *state = ctx; + return 0; +} + +static int group_teardown(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + + free(ctx); + remove("/tmp/test.log"); + + /* TODO: fix event poll file */ + //if (ctx->fp) + //fclose(ctx->fp); + return 0; +} + +static int setup(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + + return 0; +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup(test_api_events, setup), + }; + + return cmocka_run_group_tests(tests, group_setup, group_teardown); +} diff --git a/test/cmocka/test_utils.c b/test/cmocka/test_utils.c new file mode 100644 index 0000000000000000000000000000000000000000..92922ac303f39b81e39df119b60ee3db97cc3ad3 --- /dev/null +++ b/test/cmocka/test_utils.c @@ -0,0 +1,70 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <json-c/json.h> + +#include "test_utils.h" + +char *multi_tok(char *input, char *delimiter) +{ + static char *string; + char *end, temp; + + if (input) + string = input; + + if (!string) + return string; + + end = strstr(string, delimiter); + + if (!end) { + char *temp = string; + + string = NULL; + return temp; + } + + temp = string; + + *end = '\0'; + string = end + strlen(delimiter); + + return temp; +} + +/* TODO: how to fix events without fopen and fclose every poll? */ +struct json_object *poll_test_log(FILE *fp, const char *prefix) +{ + char line[256] = {0}; + char msg[256] = {0}; + struct json_object *obj = NULL; + + //if (!fp) { + fp = fopen("/tmp/test.log", "r"); + if (!fp) + return NULL; + //} + + while (fgets(line, 256, fp)) { + char *ptr, *s; + char appended[32]; + + snprintf(appended, sizeof(appended), "%s:", prefix); + + ptr = strstr(line, appended); + if (!ptr) + continue; + + s = multi_tok(ptr, appended); + s = multi_tok(NULL, appended); + strncpy(msg, s, sizeof(msg)); + } + + if (strlen(msg)) + obj = json_tokener_parse(msg); + + fclose(fp); + return obj; +} \ No newline at end of file diff --git a/test/cmocka/test_utils.h b/test/cmocka/test_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..22f4a54bde294e297d2ffc20761c6fcff40a08ce --- /dev/null +++ b/test/cmocka/test_utils.h @@ -0,0 +1,13 @@ +#ifndef TEST_UTILS_H +#define TEST_UTILS_H + +#define FIVE_IFACE "test5" +#define TWO_IFACE "test2" + +#define FIVE_CLIENT "50:31:32:33:34:35" +#define PIN "24033848" + +char *multi_tok(char *input, char *delimiter); +struct json_object *poll_test_log(FILE *fp, const char *prefix); + +#endif \ No newline at end of file diff --git a/test/cmocka/unit_test_wifi.c b/test/cmocka/unit_test_wifi.c new file mode 100644 index 0000000000000000000000000000000000000000..196a3e9fdb0be99e8ee74194c5f21798742dae66 --- /dev/null +++ b/test/cmocka/unit_test_wifi.c @@ -0,0 +1,597 @@ +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> + +#include <libubus.h> +#include <libubox/blobmsg_json.h> +#include <libubox/blobmsg.h> + +#include <json-validator.h> +#include <json-c/json.h> +#include <json-editor.h> + +#include <json-c/json_tokener.h> +#include <wifi.h> + +#include "wifimngr.h" +#include "test_utils.h" + +struct test_ctx { + struct blob_buf bb; + struct ubus_object radio; + struct ubus_object ap; + FILE *fp; +}; + +/* declare wifimngr functions */ +int wl_radio_status(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + + +int wl_radio_get_param(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int sta_disconnect(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int nbr_transition(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int nbr_request(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int nbr_add(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int wps_start(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int wps_stop(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int vsie_add(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *ureq, const char *method, + struct blob_attr *msg); + +int vsie_del(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *ureq, const char *method, + struct blob_attr *msg); + +int nbr_del(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int sta_monitor(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int wl_scan(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int wl_autochannel(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int wps_set_ap_pin(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int wifimngr_event_main(const char *evmap_file); + +/* overload ubus_send_reply to prevent segfault*/ +int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req, + struct blob_attr *msg) +{ + return 0; +} + +static void test_api_radio_disconnect(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->ap; + struct json_object *jobj, *tmp; + const char *prefix = "disconnect"; + + blobmsg_add_string(bb, "sta", FIVE_CLIENT); + + sta_disconnect(NULL, obj, NULL, NULL, bb->head); + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + tmp = json_object_get_by_string(jobj, "sta"); + assert_string_equal(json_object_get_string(tmp), FIVE_CLIENT); + + json_object_put(jobj); + return; +} + +static void test_api_req_bss_transition(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->ap; + struct json_object *jobj, *tmp; + const char *prefix = "req_bss_transition"; + void *arr; + + blobmsg_add_string(bb, "client", FIVE_CLIENT); + arr = blobmsg_open_array(bb, "bssid"); + blobmsg_add_string(bb, "NULL", "22:22:22:22:22:22"); + blobmsg_add_string(bb, "NULL", "11:11:11:11:11:11"); + blobmsg_close_array(bb, arr); + + nbr_transition(NULL, obj, NULL, NULL, bb->head); + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + tmp = json_object_get_by_string(jobj, "client"); + assert_string_equal(json_object_get_string(tmp), FIVE_CLIENT); + + tmp = json_object_get_by_string(jobj, "bssid"); + assert_string_equal(json_object_get_string(tmp), "[ \"22:22:22:22:22:22\", \"11:11:11:11:11:11\" ]"); + + json_object_put(jobj); + return; +} + +static void test_api_req_beacon_report(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->ap; + struct json_object *jobj, *tmp; + const char *prefix = "req_beacon_report"; + + blobmsg_add_string(bb, "client", FIVE_CLIENT); + blobmsg_add_string(bb, "ssid", "Test SSID 5Ghz"); + + nbr_request(NULL, obj, NULL, NULL, bb->head); + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + /* TODO: not implemented? */ + //tmp = json_object_get_by_string(jobj, "ssid"); + //assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + tmp = json_object_get_by_string(jobj, "client"); + assert_string_equal(json_object_get_string(tmp), FIVE_CLIENT); + + json_object_put(jobj); + return; +} + +static void test_api_add_nbr(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->ap; + struct json_object *jobj, *tmp; + const char *prefix = "add_neighbor"; + + blobmsg_add_string(bb, "bssid", "00:11:12:13:14:15"); + blobmsg_add_u32(bb, "channel", 36); + blobmsg_add_string(bb, "bssid_info", "5"); + blobmsg_add_u32(bb, "reg", 5); + blobmsg_add_u32(bb, "phy", 5); + + nbr_add(NULL, obj, NULL, NULL, bb->head); + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + tmp = json_object_get_by_string(jobj, "bssid"); + assert_string_equal(json_object_get_string(tmp), "00:11:12:13:14:15"); + + tmp = json_object_get_by_string(jobj, "channel"); + assert_int_equal(json_object_get_int(tmp), 36); + + tmp = json_object_get_by_string(jobj, "bssid_info"); + assert_int_equal(json_object_get_int(tmp), 5); + + tmp = json_object_get_by_string(jobj, "reg"); + assert_int_equal(json_object_get_int(tmp), 5); + + tmp = json_object_get_by_string(jobj, "phy"); + assert_int_equal(json_object_get_int(tmp), 5); + + json_object_put(jobj); + return; +} + +static void test_api_wps_start(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->ap; + struct json_object *jobj, *tmp; + const char *prefix = "start_wps"; + + /* test pin & registrar */ + blobmsg_add_string(bb, "vif", "test5"); + blobmsg_add_string(bb, "mode", "pin"); + blobmsg_add_string(bb, "role", "registrar"); + blobmsg_add_string(bb, "pin", PIN); + wps_start(NULL, obj, NULL, NULL, bb->head); + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + tmp = json_object_get_by_string(jobj, "role"); + assert_int_equal(json_object_get_int(tmp), WPS_REGISTRAR); + + tmp = json_object_get_by_string(jobj, "mode"); + assert_int_equal(json_object_get_int(tmp), WPS_MODE_PIN); + + tmp = json_object_get_by_string(jobj, "pin"); + assert_int_equal(json_object_get_int64(tmp), strtoul(PIN, NULL, 10)); + + json_object_put(jobj); + + /* test enrollee and iface test2 */ + blob_buf_init(bb, 0); + blobmsg_add_string(bb, "vif", "test2"); + blobmsg_add_string(bb, "role", "enrollee"); + wps_start(NULL, obj, NULL, NULL, bb->head); + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), TWO_IFACE); + + tmp = json_object_get_by_string(jobj, "role"); + assert_int_equal(json_object_get_int(tmp), WPS_ENROLLEE); + + /* test pbc and iface test2 */ + blob_buf_init(bb, 0); + blobmsg_add_string(bb, "vif", "test2"); + blobmsg_add_string(bb, "mode", "pbc"); + wps_start(NULL, obj, NULL, NULL, bb->head); + + json_object_put(jobj); + + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), TWO_IFACE); + + tmp = json_object_get_by_string(jobj, "mode"); + assert_int_equal(json_object_get_int(tmp), WPS_MODE_PBC); + + json_object_put(jobj); + + return; +} + +/* TODO: this test works "by chance" because we are looking for 5ghz, + * how can we fix this? */ +static void test_api_wps_stop(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->ap; + struct json_object *jobj, *tmp; + const char *prefix = "stop_wps"; + + wps_stop(NULL, obj, NULL, NULL, bb->head); + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + json_object_put(jobj); + return; +} + +static void test_api_add_vendor_ie(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->ap; + struct json_object *jobj, *tmp; + const char *prefix = "add_vendor_ie"; + + blobmsg_add_u32(bb, "mgmt", 5); + blobmsg_add_string(bb, "oui", "112233"); + blobmsg_add_string(bb, "data", "efa567"); + vsie_add(NULL, obj, NULL, NULL, bb->head); + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + tmp = json_object_get_by_string(jobj, "oui"); + assert_string_equal(json_object_get_string(tmp), "112233"); + + tmp = json_object_get_by_string(jobj, "data"); + /* hex data, prepend dd+len in hex fmt */ + assert_string_equal(json_object_get_string(tmp), "dd03efa567"); + + json_object_put(jobj); + return; +} + +static void test_api_del_vendor_ie(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->ap; + struct json_object *jobj, *tmp; + const char *prefix = "del_vendor_ie"; + + blobmsg_add_u32(bb, "mgmt", 5); + blobmsg_add_string(bb, "oui", "112233"); + blobmsg_add_string(bb, "data", "efa567"); + vsie_del(NULL, obj, NULL, NULL, bb->head); + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + tmp = json_object_get_by_string(jobj, "oui"); + assert_string_equal(json_object_get_string(tmp), "112233"); + + tmp = json_object_get_by_string(jobj, "data"); + assert_string_equal(json_object_get_string(tmp), "dd03efa567"); // hex data, prepend dd+len in hex fmt + + json_object_put(jobj); + return; +} + +static void test_api_del_neighbor(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->ap; + struct json_object *jobj, *tmp; + const char *prefix = "del_neighbor"; + + blobmsg_add_string(bb, "bssid", "50:10:00:11:22:33"); + nbr_del(NULL, obj, NULL, NULL, bb->head); + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + tmp = json_object_get_by_string(jobj, "bssid"); + assert_string_equal(json_object_get_string(tmp), "50:10:00:11:22:33"); + + json_object_put(jobj); + return; +} + +static void test_api_monitor_sta(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->ap; + struct json_object *jobj, *tmp; + const char *prefix = "monitor_sta"; + + blobmsg_add_string(bb, "sta", "00:00:00:11:22:33"); + sta_monitor(NULL, obj, NULL, NULL, bb->head); + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + tmp = json_object_get_by_string(jobj, "sta"); + assert_string_equal(json_object_get_string(tmp), "00:00:00:11:22:33"); + + json_object_put(jobj); + return; +} + +static void test_api_scan(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->radio; + struct json_object *jobj, *tmp; + const char *prefix = "scan"; + + blobmsg_add_string(bb, "bssid", "00:00:00:11:22:33"); + blobmsg_add_string(bb, "ssid", "test"); + blobmsg_add_u32(bb, "channel", 36); + wl_scan(NULL, obj, NULL, NULL, bb->head); + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + /* TODO: unused? + tmp = json_object_get_by_string(jobj, "bssid"); + assert_string_equal(json_object_get_string(tmp), "00:00:00:11:22:33"); + */ + + tmp = json_object_get_by_string(jobj, "ssid"); + assert_string_equal(json_object_get_string(tmp), "test"); + + /* TODO: unused? + tmp = json_object_get_by_string(jobj, "channel"); + assert_int_equal(json_object_get_int(tmp), 36); + */ + + json_object_put(jobj); + return; +} + +static void test_set_wps_ap_pin(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->ap; + struct json_object *jobj, *tmp; + const char *prefix = "set_wps_ap_pin"; + + blobmsg_add_string(bb, "ifname", FIVE_IFACE); + blobmsg_add_string(bb, "pin", PIN); + wps_set_ap_pin(NULL, obj, NULL, NULL, bb->head); + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + tmp = json_object_get_by_string(jobj, "pin"); + assert_int_equal(json_object_get_int64(tmp), strtoul(PIN, NULL, 10)); + + json_object_put(jobj); + return; +} + +static int group_setup(void **state) +{ + struct test_ctx *ctx = calloc(1, sizeof(struct test_ctx)); + + if (!ctx) + return -1; + + remove("/tmp/test.log"); + + ctx->radio.name = "wifi.radio.test5"; + ctx->ap.name = "wifi.ap.test5"; + + memset(&ctx->bb, 0, sizeof(struct blob_buf)); + + *state = ctx; + return 0; +} + +static void test_api_acs(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->radio; + struct json_object *jobj, *tmp; + const char *prefix = "acs"; + + + blobmsg_add_string(bb, "ifname", FIVE_IFACE); + wl_autochannel(NULL, obj, NULL, NULL, bb->head); + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + json_object_put(jobj); + return; +} + +int wifimngr_recv_event(const char *ifname, void *handle) +{ + int err; + + for (;;) { + err = wifi_recv_event((char *)ifname, handle); + if (err < 0) + return -1; + } + + return 0; +} + +static void test_api_events(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct json_object *jobj, *tmp; + const char *prefix = "register_event"; + + wifimngr_event_main("/etc/wifi.json"); + + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + tmp = json_object_get_by_string(jobj, "family"); + assert_string_equal(json_object_get_string(tmp), "easysoc"); + + tmp = json_object_get_by_string(jobj, "group"); + assert_string_equal(json_object_get_string(tmp), "notify"); + + json_object_put(jobj); + + prefix = "recv_event"; + + jobj = poll_test_log(ctx->fp, prefix); + assert_non_null(jobj); + + tmp = json_object_get_by_string(jobj, "ifname"); + assert_string_equal(json_object_get_string(tmp), FIVE_IFACE); + + json_object_put(jobj); +} + +static int group_teardown(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + + blob_buf_free(&ctx->bb); + free(ctx); + remove("/tmp/test.log"); + + /* TODO: fix event poll file */ + //if (ctx->fp) + //fclose(ctx->fp); + return 0; +} + +static int setup(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + + blob_buf_init(&ctx->bb, 0); + + return 0; +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup(test_api_radio_disconnect, setup), + cmocka_unit_test_setup(test_api_req_bss_transition, setup), + cmocka_unit_test_setup(test_api_req_beacon_report, setup), + cmocka_unit_test_setup(test_api_add_nbr, setup), + cmocka_unit_test_setup(test_api_wps_start, setup), + cmocka_unit_test_setup(test_api_wps_stop, setup), + cmocka_unit_test_setup(test_api_add_vendor_ie, setup), + cmocka_unit_test_setup(test_api_del_vendor_ie, setup), + cmocka_unit_test_setup(test_api_del_neighbor, setup), + cmocka_unit_test_setup(test_api_monitor_sta, setup), + cmocka_unit_test_setup(test_api_scan, setup), + cmocka_unit_test_setup(test_set_wps_ap_pin, setup), + cmocka_unit_test_setup(test_api_acs, setup), + }; + + return cmocka_run_group_tests(tests, group_setup, group_teardown); +} diff --git a/test/files/etc/config/wireless b/test/files/etc/config/wireless new file mode 100644 index 0000000000000000000000000000000000000000..93ad34d8352c25c8717880b9c5c2c3776228b0b7 --- /dev/null +++ b/test/files/etc/config/wireless @@ -0,0 +1,25 @@ +config wifi-device 'test2' + option channel 'auto' + option hwmode 'auto' + option country 'DE' + option band 'a' + option bandwidth '80' + +config wifi-iface + option device 'test2' + option ifname 'test2' + option mode 'ap' + option encryption 'psk2' + +config wifi-device 'test5' + option channel 'auto' + option hwmode 'auto' + option country 'DE' + option band 'a' + option bandwidth '80' + +config wifi-iface + option device 'test5' + option ifname 'test5' + option mode 'ap' + option encryption 'psk2' \ No newline at end of file diff --git a/test/files/etc/wifi.json b/test/files/etc/wifi.json new file mode 100644 index 0000000000000000000000000000000000000000..f4ef67bf78fe8c1450ab34b18d4181bc8613f8ff --- /dev/null +++ b/test/files/etc/wifi.json @@ -0,0 +1,13 @@ +{ + "events" : [ + { + "type": "wifi-event", + "name": "cfg09ac03", + "ifname": "test5", + "family": "easysoc", + "group": [ + "notify" + ] + } + ] +} diff --git a/wifimngr.c b/wifimngr.c index 069c8adcbf01132c6dbbc48ad03e0b123882b20a..ee6bf445d2731eb851a341167bce8a0923f7eff7 100644 --- a/wifimngr.c +++ b/wifimngr.c @@ -374,7 +374,7 @@ static void wl_dump_capabilities(struct blob_buf *bb, struct wifi_caps *caps, ui blobmsg_add_u8(bb, "apsd", wifi_cap_isset(bitmap, WIFI_CAP_APSD) ? true : false); blobmsg_add_u8(bb, "shortslot", wifi_cap_isset(bitmap, WIFI_CAP_SHORT_SLOT) ? true : false); blobmsg_add_u8(bb, "dot11h", wifi_cap_isset(bitmap, WIFI_CAP_SPECTRUM_MGMT) ? true : false); - blobmsg_add_u8(bb, "dot11k", wifi_cap_isset(bitmap, WIFI_CAP_RADIO_MEAS) ? true : false); + //blobmsg_add_u8(bb, "dot11k", wifi_cap_isset(bitmap, WIFI_CAP_RADIO_MEAS) ? true : false); if (!!(caps->valid & WIFI_CAP_EXT_VALID)) { blobmsg_add_u8(bb, "2040coex", wifi_cap_isset(bitmap, WIFI_CAP_2040_COEX) ? true : false); @@ -384,7 +384,9 @@ static void wl_dump_capabilities(struct blob_buf *bb, struct wifi_caps *caps, ui } if (!!(caps->valid & WIFI_CAP_HT_VALID)) { - blobmsg_add_u8(bb, "dot11n", true); + void *n; + + n = blobmsg_open_table(bb, "dot11n"); blobmsg_add_u8(bb, "dot11n_ldpc", wifi_cap_isset(bitmap, WIFI_CAP_HT_LDPC) ? true : false); blobmsg_add_u8(bb, "dot11n_40", wifi_cap_isset(bitmap, WIFI_CAP_2040) ? true : false); blobmsg_add_u8(bb, "dot11n_ps", wifi_cap_isset(bitmap, WIFI_CAP_HT_SMPS) ? true : false); @@ -392,12 +394,15 @@ static void wl_dump_capabilities(struct blob_buf *bb, struct wifi_caps *caps, ui blobmsg_add_u8(bb, "dot11n_sgi40", wifi_cap_isset(bitmap, WIFI_CAP_SGI40) ? true : false); blobmsg_add_u8(bb, "dot11n_tx_stbc", wifi_cap_isset(bitmap, WIFI_CAP_HT_TX_STBC) ? true : false); blobmsg_add_u8(bb, "dot11n_rx_stbc", wifi_cap_isset(bitmap, WIFI_CAP_HT_RX_STBC) ? true : false); - } else { + blobmsg_close_table(bb, n); + }/* else { blobmsg_add_u8(bb, "dot11n", false); - } + }*/ if (!!(caps->valid & WIFI_CAP_VHT_VALID)) { - blobmsg_add_u8(bb, "dot11ac", true); + void *ac; + + ac = blobmsg_open_table(bb, "dot11ac"); blobmsg_add_u8(bb, "dot11ac_160", wifi_cap_isset(bitmap, WIFI_CAP_160) ? true : false); blobmsg_add_u8(bb, "dot11ac_8080", wifi_cap_isset(bitmap, WIFI_CAP_8080) ? true : false); if (wifi_cap_isset(bitmap, WIFI_CAP_VHT_MPDU_11454)) @@ -418,12 +423,15 @@ static void wl_dump_capabilities(struct blob_buf *bb, struct wifi_caps *caps, ui blobmsg_add_u8(bb, "dot11ac_su_beamformee", wifi_cap_isset(bitmap, WIFI_CAP_VHT_SU_BFE) ? true : false); blobmsg_add_u8(bb, "dot11ac_mu_beamformer", wifi_cap_isset(bitmap, WIFI_CAP_VHT_MU_BFR) ? true : false); blobmsg_add_u8(bb, "dot11ac_mu_beamformee", wifi_cap_isset(bitmap, WIFI_CAP_VHT_MU_BFE) ? true : false); - } else { + blobmsg_close_table(bb, ac); + }/* else { blobmsg_add_u8(bb, "dot11ac", false); - } + }*/ if (!!(caps->valid & WIFI_CAP_RM_VALID)) { - blobmsg_add_u8(bb, "dot11k", true); + void *k; + + k = blobmsg_open_table(bb, "dot11k"); blobmsg_add_u8(bb, "dot11k_link_meas", wifi_cap_isset(bitmap, WIFI_CAP_RM_LINK) ? true : false); blobmsg_add_u8(bb, "dot11k_nbr_report", wifi_cap_isset(bitmap, WIFI_CAP_RM_NBR_REPORT) ? true : false); blobmsg_add_u8(bb, "dot11k_bcn_passive", wifi_cap_isset(bitmap, WIFI_CAP_RM_BCN_PASSIVE) ? true : false); @@ -431,6 +439,7 @@ static void wl_dump_capabilities(struct blob_buf *bb, struct wifi_caps *caps, ui blobmsg_add_u8(bb, "dot11k_bcn_table", wifi_cap_isset(bitmap, WIFI_CAP_RM_BCN_TABLE) ? true : false); blobmsg_add_u8(bb, "dot11k_rcpi", wifi_cap_isset(bitmap, WIFI_CAP_RM_RCPI) ? true : false); blobmsg_add_u8(bb, "dot11k_rsni", wifi_cap_isset(bitmap, WIFI_CAP_RM_RSNI) ? true : false); + blobmsg_close_table(bb, k); } /* else blobmsg_add_u8(bb, "dot11k", false); */ @@ -467,7 +476,7 @@ static void wifi_print_radio_diagnostics(struct blob_buf *bb, blobmsg_add_u32(bb, "false_cca_count", d->false_cca_count); } -static int wl_radio_status(struct ubus_context *ctx, struct ubus_object *obj, +int wl_radio_status(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { @@ -485,8 +494,8 @@ static int wl_radio_status(struct ubus_context *ctx, struct ubus_object *obj, void *c; int i; - memset(&bb, 0, sizeof(bb)); + memset(&bb, 0, sizeof(bb)); wldev = ubus_radio_to_ifname(obj); wifi_get_ifstatus(wldev, &ifs); @@ -528,6 +537,7 @@ static int wl_radio_status(struct ubus_context *ctx, struct ubus_object *obj, for (i = 0; i < 32 && radio.supp_rates[i] != 0; i++) { blobmsg_add_u32(&bb, "", radio.supp_rates[i]); } + blobmsg_close_array(&bb, c); c = blobmsg_open_array(&bb, "basic_rates"); for (i = 0; i < 32 && radio.basic_rates[i] != 0; i++) { @@ -960,7 +970,7 @@ static const struct blobmsg_policy wl_scan_policy[__SCAN_MAX] = { /* [SCAN_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_INT32 }, */ }; -static int wl_scan(struct ubus_context *ctx, struct ubus_object *obj, +int wl_scan(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { @@ -1138,7 +1148,7 @@ static const struct blobmsg_policy wl_acs_policy[__ACS_MAX] = { [ACS_NUM_SCANS] = { .name = "scans", .type = BLOBMSG_TYPE_INT32 }, }; -static int wl_autochannel(struct ubus_context *ctx, struct ubus_object *obj, +int wl_autochannel(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { @@ -1261,7 +1271,7 @@ static const struct blobmsg_policy btmreq_policy[__NBR_TRANS_MAX] = { [NBR_TRANS_TIMEOUT] = { .name = "timeout", .type = BLOBMSG_TYPE_INT32 }, }; -static int sta_disconnect(struct ubus_context *ctx, struct ubus_object *obj, +int sta_disconnect(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { @@ -1291,7 +1301,7 @@ static int sta_disconnect(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_OK; } -static int sta_monitor(struct ubus_context *ctx, struct ubus_object *obj, +int sta_monitor(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { @@ -1357,7 +1367,7 @@ static int sta_monitor(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_OK; } -static int nbr_add(struct ubus_context *ctx, struct ubus_object *obj, +int nbr_add(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { @@ -1418,7 +1428,7 @@ static int nbr_add(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_OK; } -static int nbr_del(struct ubus_context *ctx, struct ubus_object *obj, +int nbr_del(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { @@ -1567,7 +1577,7 @@ static int nbr_list(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_OK; } -static int nbr_request(struct ubus_context *ctx, struct ubus_object *obj, +int nbr_request(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { @@ -1593,7 +1603,7 @@ static int nbr_request(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_OK; } -static int nbr_transition(struct ubus_context *ctx, struct ubus_object *obj, +int nbr_transition(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { @@ -1662,7 +1672,7 @@ static const struct blobmsg_policy vsie_policy[__VSIE_MAX] = { [VSIE_DATA] = { .name = "data", .type = BLOBMSG_TYPE_STRING}, }; -static int vsie_add(struct ubus_context *ctx, struct ubus_object *obj, +int vsie_add(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *ureq, const char *method, struct blob_attr *msg) { @@ -1711,13 +1721,15 @@ static int vsie_add(struct ubus_context *ctx, struct ubus_object *obj, data[1] = data_len; req->ie.ie_hdr.len += 2 + data_len; + + if (wifi_add_vendor_ie(ifname, req) != 0) return UBUS_STATUS_UNKNOWN_ERROR; return UBUS_STATUS_OK; } -static int vsie_del(struct ubus_context *ctx, struct ubus_object *obj, +int vsie_del(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *ureq, const char *method, struct blob_attr *msg) { @@ -2038,7 +2050,7 @@ static const struct blobmsg_policy radio_get_param_policy[__GET_MAX] = { [GET_PNAME] = { .name = "param", .type = BLOBMSG_TYPE_STRING }, }; -static int wl_radio_get_param(struct ubus_context *ctx, struct ubus_object *obj, +int wl_radio_get_param(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { @@ -2147,13 +2159,13 @@ static int add_radio_methods(struct ubus_object *radio_obj, //UBUS_METHOD_ADD(radio_methods, n_methods, // UBUS_METHOD_NOARG("temperature", wl_temperature)); - if (libwifi_supports(radioname, "wifi_scan")) { +// if (libwifi_supports(radioname, "wifi_scan")) { UBUS_METHOD_ADD(radio_methods, n_methods, UBUS_METHOD("scan", wl_scan, wl_scan_policy)); UBUS_METHOD_ADD(radio_methods, n_methods, UBUS_METHOD("scanresults", wl_scanresults, wl_scanres_policy)); - } +// } UBUS_METHOD_ADD(radio_methods, n_methods, UBUS_METHOD("autochannel", wl_autochannel, wl_acs_policy)); diff --git a/wps.c b/wps.c index 91494e94772b0890e05a719add4d083d72d88c8d..b851fbc4ada1741012749370670345d95829b820 100644 --- a/wps.c +++ b/wps.c @@ -248,12 +248,15 @@ static int wps_status(struct ubus_context *ctx, struct ubus_object *obj, return 0; } -static int wps_start(struct ubus_context *ctx, struct ubus_object *obj, +int wps_start(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { struct blob_attr *tb[__WPS_START_ATTR_MAX]; - struct wps_param wps; + struct wps_param wps = { + .role = WPS_REGISTRAR, + .mode = WPS_MODE_PBC + }; char ifname[16] = {0}; char role[16] = {0}; char mode[8] = {0}; @@ -288,7 +291,7 @@ static int wps_start(struct ubus_context *ctx, struct ubus_object *obj, strncpy(role, blobmsg_data(tb[WPS_START_ATTR_ROLE]), 10); if (!strcasecmp(role, "registrar")) wps.role = WPS_REGISTRAR; - else if (!strcasecmp(mode, "enrollee")) + else if (!strcasecmp(role, "enrollee")) wps.role = WPS_ENROLLEE; else return UBUS_STATUS_INVALID_ARGUMENT; @@ -354,7 +357,7 @@ static int wps_checkpin(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_OK; } -static int wps_set_ap_pin(struct ubus_context *ctx, struct ubus_object *obj, +int wps_set_ap_pin(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { @@ -414,7 +417,7 @@ static int wps_show_ap_pin(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_OK; } -static int wps_stop(struct ubus_context *ctx, struct ubus_object *obj, +int wps_stop(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) {