From eae86ee9bd58b7b2447e58bb99bf709afe1b2ac2 Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Tue, 22 Nov 2022 19:09:46 +0100 Subject: [PATCH 1/9] rpcd-mod-luci: reuse infos provided by libiwinfo Don't hardcode bit/name pairs, instead iterate over what's known to the library and use that instead. This automatically adds the missing ad hwmode and HE80+80 htmode - and any future ones. The only difference in the output is the order of the 'hwmodes' array. Signed-off-by: Andre Heider --- libs/rpcd-mod-luci/src/luci.c | 203 ++++++++++++---------------------- 1 file changed, 72 insertions(+), 131 deletions(-) diff --git a/libs/rpcd-mod-luci/src/luci.c b/libs/rpcd-mod-luci/src/luci.c index 4bef961c35..88bc004615 100644 --- a/libs/rpcd-mod-luci/src/luci.c +++ b/libs/rpcd-mod-luci/src/luci.c @@ -76,7 +76,9 @@ struct invoke_context { void *priv; }; -static const char **iw_modenames; +typedef const char * const iw_text_t; +static iw_text_t *iw_modenames, *iw_authnames, *iw_kmgmtnames, + *iw_ciphernames, *iw_htmodenames, *iw_80211names; static struct iwinfo_ops *(*iw_backend)(const char *); static void (*iw_close)(void); @@ -884,6 +886,48 @@ iw_call_num(int (*method)(const char *, int *), const char *dev, blobmsg_add_u32(blob, field, val); } +static void +iw_lower(const char *src, char *dst, size_t len) +{ + size_t i; + + for (i = 0; *src && i < len; i++) + *dst++ = tolower(*src++); + + *dst = 0; +} + +static void +iw_add_bit_array(struct blob_buf *buf, const char *name, uint32_t bits, + iw_text_t values[], size_t len, bool lower, uint32_t zero) +{ + void *c; + size_t i; + char l[128]; + const char *v; + + if (!bits) + bits = zero; + + c = blobmsg_open_array(buf, name); + + for (i = 0; i < len; i++) + if (bits & 1 << i) + { + v = values[i]; + + if (lower) + { + iw_lower(v, l, strlen(values[i])); + v = l; + } + + blobmsg_add_string(buf, NULL, v); + } + + blobmsg_close_array(buf, c); +} + static bool rpc_luci_get_iwinfo(struct blob_buf *buf, const char *devname, bool phy_only) { @@ -895,7 +939,8 @@ static bool rpc_luci_get_iwinfo(struct blob_buf *buf, const char *devname, glob_t paths; int nret, i; - if (!iw_backend || !iw_close || !iw_modenames) { + if (!iw_backend || !iw_close || !iw_modenames || !iw_80211names || + !iw_htmodenames || !iw_authnames || !iw_kmgmtnames || !iw_ciphernames) { if (glob("/usr/lib/libiwinfo.so*", 0, NULL, &paths) != 0) return false; @@ -910,8 +955,14 @@ static bool rpc_luci_get_iwinfo(struct blob_buf *buf, const char *devname, iw_backend = dlsym(iwlib, "iwinfo_backend"); iw_close = dlsym(iwlib, "iwinfo_close"); iw_modenames = dlsym(iwlib, "IWINFO_OPMODE_NAMES"); + iw_80211names = dlsym(iwlib, "IWINFO_80211_NAMES"); + iw_htmodenames = dlsym(iwlib, "IWINFO_HTMODE_NAMES"); + iw_authnames = dlsym(iwlib, "IWINFO_AUTH_NAMES"); + iw_kmgmtnames = dlsym(iwlib, "IWINFO_KMGMT_NAMES"); + iw_ciphernames = dlsym(iwlib, "IWINFO_CIPHER_NAMES"); - if (!iw_backend || !iw_close || !iw_modenames) + if (!iw_backend || !iw_close || !iw_modenames || !iw_80211names || + !iw_htmodenames || !iw_authnames || !iw_kmgmtnames || !iw_ciphernames) return false; } @@ -932,68 +983,13 @@ static bool rpc_luci_get_iwinfo(struct blob_buf *buf, const char *devname, iw_call_num(iw->frequency, devname, buf, "frequency"); iw_call_num(iw->frequency_offset, devname, buf, "frequency_offset"); - if (!iw->hwmodelist(devname, &nret)) { - a = blobmsg_open_array(buf, "hwmodes"); + if (!iw->hwmodelist(devname, &nret)) + iw_add_bit_array(buf, "hwmodes", nret, + iw_80211names, IWINFO_80211_COUNT, true, 0); - if (nret & IWINFO_80211_AX) - blobmsg_add_string(buf, NULL, "ax"); - - if (nret & IWINFO_80211_AC) - blobmsg_add_string(buf, NULL, "ac"); - - if (nret & IWINFO_80211_A) - blobmsg_add_string(buf, NULL, "a"); - - if (nret & IWINFO_80211_B) - blobmsg_add_string(buf, NULL, "b"); - - if (nret & IWINFO_80211_G) - blobmsg_add_string(buf, NULL, "g"); - - if (nret & IWINFO_80211_N) - blobmsg_add_string(buf, NULL, "n"); - - blobmsg_close_array(buf, a); - } - - if (!iw->htmodelist(devname, &nret)) { - a = blobmsg_open_array(buf, "htmodes"); - - if (nret & IWINFO_HTMODE_HT20) - blobmsg_add_string(buf, NULL, "HT20"); - - if (nret & IWINFO_HTMODE_HT40) - blobmsg_add_string(buf, NULL, "HT40"); - - if (nret & IWINFO_HTMODE_VHT20) - blobmsg_add_string(buf, NULL, "VHT20"); - - if (nret & IWINFO_HTMODE_VHT40) - blobmsg_add_string(buf, NULL, "VHT40"); - - if (nret & IWINFO_HTMODE_VHT80) - blobmsg_add_string(buf, NULL, "VHT80"); - - if (nret & IWINFO_HTMODE_VHT80_80) - blobmsg_add_string(buf, NULL, "VHT80+80"); - - if (nret & IWINFO_HTMODE_VHT160) - blobmsg_add_string(buf, NULL, "VHT160"); - - if (nret & IWINFO_HTMODE_HE20) - blobmsg_add_string(buf, NULL, "HE20"); - - if (nret & IWINFO_HTMODE_HE40) - blobmsg_add_string(buf, NULL, "HE40"); - - if (nret & IWINFO_HTMODE_HE80) - blobmsg_add_string(buf, NULL, "HE80"); - - if (nret & IWINFO_HTMODE_HE160) - blobmsg_add_string(buf, NULL, "HE160"); - - blobmsg_close_array(buf, a); - } + if (!iw->htmodelist(devname, &nret)) + iw_add_bit_array(buf, "htmodes", nret & ~IWINFO_HTMODE_NOHT, + iw_htmodenames, IWINFO_HTMODE_COUNT, false, 0); if (!iw->hardware_id(devname, (char *)&ids)) { o2 = blobmsg_open_table(buf, "hardware"); @@ -1028,17 +1024,10 @@ static bool rpc_luci_get_iwinfo(struct blob_buf *buf, const char *devname, if (crypto.enabled) { if (!crypto.wpa_version) { - a = blobmsg_open_array(buf, "wep"); - - if (crypto.auth_algs & IWINFO_AUTH_OPEN) - blobmsg_add_string(buf, NULL, "open"); - - if (crypto.auth_algs & IWINFO_AUTH_SHARED) - blobmsg_add_string(buf, NULL, "shared"); - - blobmsg_close_array(buf, a); - } - else { + iw_add_bit_array(buf, "wep", crypto.auth_algs, + iw_authnames, IWINFO_AUTH_COUNT, + true, 0); + } else { a = blobmsg_open_array(buf, "wpa"); for (nret = 1; nret <= 3; nret++) @@ -1047,64 +1036,16 @@ static bool rpc_luci_get_iwinfo(struct blob_buf *buf, const char *devname, blobmsg_close_array(buf, a); - a = blobmsg_open_array(buf, "authentication"); - - if (crypto.auth_suites & IWINFO_KMGMT_PSK) - blobmsg_add_string(buf, NULL, "psk"); - - if (crypto.auth_suites & IWINFO_KMGMT_8021x) - blobmsg_add_string(buf, NULL, "802.1x"); - - if (crypto.auth_suites & IWINFO_KMGMT_SAE) - blobmsg_add_string(buf, NULL, "sae"); - - if (crypto.auth_suites & IWINFO_KMGMT_OWE) - blobmsg_add_string(buf, NULL, "owe"); - - if (!crypto.auth_suites || - (crypto.auth_suites & IWINFO_KMGMT_NONE)) - blobmsg_add_string(buf, NULL, "none"); - - blobmsg_close_array(buf, a); + iw_add_bit_array(buf, "authentication", + crypto.auth_suites, + iw_kmgmtnames, IWINFO_KMGMT_COUNT, + true, IWINFO_KMGMT_NONE); } - a = blobmsg_open_array(buf, "ciphers"); - nret = crypto.pair_ciphers | crypto.group_ciphers; - - if (nret & IWINFO_CIPHER_WEP40) - blobmsg_add_string(buf, NULL, "wep-40"); - - if (nret & IWINFO_CIPHER_WEP104) - blobmsg_add_string(buf, NULL, "wep-104"); - - if (nret & IWINFO_CIPHER_TKIP) - blobmsg_add_string(buf, NULL, "tkip"); - - if (nret & IWINFO_CIPHER_CCMP) - blobmsg_add_string(buf, NULL, "ccmp"); - - if (nret & IWINFO_CIPHER_CCMP256) - blobmsg_add_string(buf, NULL, "ccmp-256"); - - if (nret & IWINFO_CIPHER_GCMP) - blobmsg_add_string(buf, NULL, "gcmp"); - - if (nret & IWINFO_CIPHER_GCMP256) - blobmsg_add_string(buf, NULL, "gcmp-256"); - - if (nret & IWINFO_CIPHER_WRAP) - blobmsg_add_string(buf, NULL, "wrap"); - - if (nret & IWINFO_CIPHER_AESOCB) - blobmsg_add_string(buf, NULL, "aes-ocb"); - - if (nret & IWINFO_CIPHER_CKIP) - blobmsg_add_string(buf, NULL, "ckip"); - - if (!nret || (nret & IWINFO_CIPHER_NONE)) - blobmsg_add_string(buf, NULL, "none"); - - blobmsg_close_array(buf, a); + iw_add_bit_array(buf, "ciphers", + crypto.pair_ciphers | crypto.group_ciphers, + iw_ciphernames, IWINFO_CIPHER_COUNT, + true, IWINFO_CIPHER_NONE); } blobmsg_close_table(buf, o2); From ed2ee96e4404f603539a19c2c6857a69173d15e3 Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Wed, 23 Nov 2022 12:23:08 +0100 Subject: [PATCH 2/9] rpcd-mod-luci: add "hwmodes_text" to the iwinfo info output This is a preformatted string like "ac/ax/b/g/n" for presentation. Signed-off-by: Andre Heider --- libs/rpcd-mod-luci/src/luci.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libs/rpcd-mod-luci/src/luci.c b/libs/rpcd-mod-luci/src/luci.c index 88bc004615..422555453d 100644 --- a/libs/rpcd-mod-luci/src/luci.c +++ b/libs/rpcd-mod-luci/src/luci.c @@ -81,6 +81,7 @@ static iw_text_t *iw_modenames, *iw_authnames, *iw_kmgmtnames, *iw_ciphernames, *iw_htmodenames, *iw_80211names; static struct iwinfo_ops *(*iw_backend)(const char *); static void (*iw_close)(void); +static size_t (*iw_format_hwmodes)(int, char *, size_t); static void invoke_data_cb(struct ubus_request *req, int type, struct blob_attr *msg) @@ -938,8 +939,9 @@ static bool rpc_luci_get_iwinfo(struct blob_buf *buf, const char *devname, void *o, *o2, *a; glob_t paths; int nret, i; + char text[32]; - if (!iw_backend || !iw_close || !iw_modenames || !iw_80211names || + if (!iw_backend || !iw_close || !iw_format_hwmodes || !iw_modenames || !iw_80211names || !iw_htmodenames || !iw_authnames || !iw_kmgmtnames || !iw_ciphernames) { if (glob("/usr/lib/libiwinfo.so*", 0, NULL, &paths) != 0) return false; @@ -954,6 +956,7 @@ static bool rpc_luci_get_iwinfo(struct blob_buf *buf, const char *devname, iw_backend = dlsym(iwlib, "iwinfo_backend"); iw_close = dlsym(iwlib, "iwinfo_close"); + iw_format_hwmodes = dlsym(iwlib, "iwinfo_format_hwmodes"); iw_modenames = dlsym(iwlib, "IWINFO_OPMODE_NAMES"); iw_80211names = dlsym(iwlib, "IWINFO_80211_NAMES"); iw_htmodenames = dlsym(iwlib, "IWINFO_HTMODE_NAMES"); @@ -961,7 +964,7 @@ static bool rpc_luci_get_iwinfo(struct blob_buf *buf, const char *devname, iw_kmgmtnames = dlsym(iwlib, "IWINFO_KMGMT_NAMES"); iw_ciphernames = dlsym(iwlib, "IWINFO_CIPHER_NAMES"); - if (!iw_backend || !iw_close || !iw_modenames || !iw_80211names || + if (!iw_backend || !iw_close || !iw_format_hwmodes || !iw_modenames || !iw_80211names || !iw_htmodenames || !iw_authnames || !iw_kmgmtnames || !iw_ciphernames) return false; } @@ -983,10 +986,14 @@ static bool rpc_luci_get_iwinfo(struct blob_buf *buf, const char *devname, iw_call_num(iw->frequency, devname, buf, "frequency"); iw_call_num(iw->frequency_offset, devname, buf, "frequency_offset"); - if (!iw->hwmodelist(devname, &nret)) + if (!iw->hwmodelist(devname, &nret)) { iw_add_bit_array(buf, "hwmodes", nret, iw_80211names, IWINFO_80211_COUNT, true, 0); + if (iw_format_hwmodes(nret, text, sizeof(text)) > 0) + blobmsg_add_string(buf, "hwmodes_text", text); + } + if (!iw->htmodelist(devname, &nret)) iw_add_bit_array(buf, "htmodes", nret & ~IWINFO_HTMODE_NOHT, iw_htmodenames, IWINFO_HTMODE_COUNT, false, 0); From eb93ea0ac244397aaba57a9c9db7414c518c7693 Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Mon, 23 Jan 2023 14:44:19 +0100 Subject: [PATCH 3/9] rpcd-mod-luci: bump version Signed-off-by: Andre Heider --- libs/rpcd-mod-luci/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/rpcd-mod-luci/Makefile b/libs/rpcd-mod-luci/Makefile index ee3bc00746..ece32a4cc9 100644 --- a/libs/rpcd-mod-luci/Makefile +++ b/libs/rpcd-mod-luci/Makefile @@ -7,8 +7,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=rpcd-mod-luci -PKG_VERSION:=20210614 -PKG_RELEASE:=2 +PKG_VERSION:=20230123 +PKG_RELEASE:=1 PKG_MAINTAINER:=Jo-Philipp Wich PKG_LICENSE:=Apache-2.0 From d53ea72a88a2f9fb7ddee66eea562838f2d5c9f0 Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Tue, 22 Nov 2022 20:10:07 +0100 Subject: [PATCH 4/9] luci-base: use "hwmodes_text" to describe wireless radios This is a preformatted string like "ac/ax/b/g/n" for presentation. Signed-off-by: Andre Heider --- modules/luci-base/htdocs/luci-static/resources/network.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/luci-base/htdocs/luci-static/resources/network.js b/modules/luci-base/htdocs/luci-static/resources/network.js index e0013c8ec0..2568017c26 100644 --- a/modules/luci-base/htdocs/luci-static/resources/network.js +++ b/modules/luci-base/htdocs/luci-static/resources/network.js @@ -3396,13 +3396,14 @@ WifiDevice = baseclass.extend(/** @lends LuCI.network.WifiDevice.prototype */ { getI18n: function() { var hw = this.ubus('dev', 'iwinfo', 'hardware'), type = L.isObject(hw) ? hw.name : null; + var modes = this.ubus('dev', 'iwinfo', 'hwmodes_text'); if (this.ubus('dev', 'iwinfo', 'type') == 'wl') type = 'Broadcom'; - return '%s 802.11%s Wireless Controller (%s)'.format( + return '%s %s Wireless Controller (%s)'.format( type || 'Generic', - this.getHWModes().sort(L.naturalCompare).join(''), + modes ? '802.11' + modes : 'unknown', this.getName()); }, From 6914468e569b458ab0915482578375f884dd193e Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Sat, 26 Nov 2022 13:10:39 +0100 Subject: [PATCH 5/9] luci-base: remove the hostapd 11n feature flag This feature flag doesn't exist anymore, see this commit on the main repo: 7c63295bf4 "treewide: remove DRIVER_11N_SUPPORT" Signed-off-by: Andre Heider --- modules/luci-base/root/usr/share/rpcd/ucode/luci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/luci-base/root/usr/share/rpcd/ucode/luci b/modules/luci-base/root/usr/share/rpcd/ucode/luci index a30e276b80..8b892dbb91 100644 --- a/modules/luci-base/root/usr/share/rpcd/ucode/luci +++ b/modules/luci-base/root/usr/share/rpcd/ucode/luci @@ -208,7 +208,7 @@ const methods = { relayd: access('/usr/sbin/relayd') == true, }; - const wifi_features = [ 'eap', '11n', '11ac', '11r', 'acs', 'sae', 'owe', 'suiteb192', 'wep', 'wps' ]; + const wifi_features = [ 'eap', '11ac', '11r', 'acs', 'sae', 'owe', 'suiteb192', 'wep', 'wps' ]; if (access('/usr/sbin/hostapd')) { result.hostapd = { cli: access('/usr/sbin/hostapd_cli') == true }; From 05f2901ffb4e4972999d9587a03e532863320f22 Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Sat, 26 Nov 2022 13:25:42 +0100 Subject: [PATCH 6/9] luci-base: add a hostapd 11ax feature flag Required for luci to check if it can acually offer that mode. Signed-off-by: Andre Heider --- modules/luci-base/root/usr/share/rpcd/ucode/luci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/luci-base/root/usr/share/rpcd/ucode/luci b/modules/luci-base/root/usr/share/rpcd/ucode/luci index 8b892dbb91..f4d204cf22 100644 --- a/modules/luci-base/root/usr/share/rpcd/ucode/luci +++ b/modules/luci-base/root/usr/share/rpcd/ucode/luci @@ -208,7 +208,7 @@ const methods = { relayd: access('/usr/sbin/relayd') == true, }; - const wifi_features = [ 'eap', '11ac', '11r', 'acs', 'sae', 'owe', 'suiteb192', 'wep', 'wps' ]; + const wifi_features = [ 'eap', '11ac', '11ax', '11r', 'acs', 'sae', 'owe', 'suiteb192', 'wep', 'wps' ]; if (access('/usr/sbin/hostapd')) { result.hostapd = { cli: access('/usr/sbin/hostapd_cli') == true }; From eead21c5abff36839d5b9922eb06b61ffb44d77c Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Sat, 26 Nov 2022 13:30:26 +0100 Subject: [PATCH 7/9] luci-mod-network: don't offer unsupported wireless hwmodes This prevents offering e.g. 'Legacy' on ac/n only radios or ax if hostapd wasn't compiled with ax support. Signed-off-by: Andre Heider --- .../htdocs/luci-static/resources/view/network/wireless.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js index bdeaecf8a9..e9b0fa4160 100644 --- a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js +++ b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js @@ -343,10 +343,10 @@ var CBIWifiFrequencyValue = form.Value.extend({ .reduce(function(o, v) { o[v] = true; return o }, {}); this.modes = [ - '', 'Legacy', true, + '', 'Legacy', hwmodelist.a || hwmodelist.b || hwmodelist.g, 'n', 'N', hwmodelist.n, - 'ac', 'AC', hwmodelist.ac, - 'ax', 'AX', hwmodelist.ax + 'ac', 'AC', L.hasSystemFeature('hostapd', '11ac') && hwmodelist.ac, + 'ax', 'AX', L.hasSystemFeature('hostapd', '11ax') && hwmodelist.ax ]; var htmodelist = L.toArray(data[0] ? data[0].getHTModes() : null) From abad257fbbe75b67f9507a96f73ac4772d73c248 Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Thu, 17 Nov 2022 21:52:26 +0100 Subject: [PATCH 8/9] luci-mod-network: enable configuring wifi ax networks on the 6G band Tested on a MT7921 device. Signed-off-by: Andre Heider --- .../htdocs/luci-static/resources/view/network/wireless.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js index e9b0fa4160..3c6f51afeb 100644 --- a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js +++ b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js @@ -314,7 +314,7 @@ var CBIWifiFrequencyValue = form.Value.extend({ this.channels = { '2g': L.hasSystemFeature('hostapd', 'acs') ? [ 'auto', 'auto', true ] : [], '5g': L.hasSystemFeature('hostapd', 'acs') ? [ 'auto', 'auto', true ] : [], - '6g': [], + '6g': L.hasSystemFeature('hostapd', 'acs') ? [ 'auto', 'auto', true ] : [], '60g': [] }; @@ -387,7 +387,8 @@ var CBIWifiFrequencyValue = form.Value.extend({ ], 'ax': [ '2g', '2.4 GHz', this.channels['2g'].length > 3, - '5g', '5 GHz', this.channels['5g'].length > 3 + '5g', '5 GHz', this.channels['5g'].length > 3, + '6g', '6 GHz', this.channels['6g'].length > 3 ] }; }, this)); From 01c5a63934392ab66c66c594fbd93a796e36d6e6 Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Wed, 23 Nov 2022 13:29:22 +0100 Subject: [PATCH 9/9] luci-mod-network: use "band" from iwinfo freqlist Instead of mapping it by frequency. Signed-off-by: Andre Heider --- .../luci-static/resources/view/network/wireless.js | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js index 3c6f51afeb..a2b0c84ce2 100644 --- a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js +++ b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js @@ -319,19 +319,11 @@ var CBIWifiFrequencyValue = form.Value.extend({ }; for (var i = 0; i < data[1].length; i++) { - var band; - - if (data[1][i].mhz >= 2412 && data[1][i].mhz <= 2484) - band = '2g'; - else if (data[1][i].mhz >= 5160 && data[1][i].mhz <= 5885) - band = '5g'; - else if (data[1][i].mhz >= 5925 && data[1][i].mhz <= 7125) - band = '6g'; - else if (data[1][i].mhz >= 58320 && data[1][i].mhz <= 69120) - band = '60g'; - else + if (!data[1][i].band) continue; + var band = '%dg'.format(data[1][i].band); + this.channels[band].push( data[1][i].channel, '%d (%d Mhz)'.format(data[1][i].channel, data[1][i].mhz),