您好,登錄后才能下訂單哦!
本篇文章為大家展示了怎么解決OpenWrt無線搜索錯誤bug,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
TP-LINK 841n路由更新openwrt系統(tǒng)到Barrier Breaker r41988,“網絡”-->“無線”-->“搜索”這個功能就不能用了,trunk版的也有這個問題。其實今年4、5月份玩HG255D路由就有這個問題,但當時的源碼編譯給TP-LINK 841n卻沒有這個問題。對這樣的問題,確實比較頭大,花了兩天時間終于找到bug所在(只解決wr841n的,我的hg255d出問題了)。
無線搜索bug截圖(注意device參數(shù)radio0):
一番搜索后發(fā)現(xiàn)此頁面的源碼在系統(tǒng)的/usr/lib/lua/luci/view/admin_network/wifi_join.htm文件里,對應openwrt的源碼路徑為./feeds/luci/modules/admin-full/luasrc/view/admin_network/wifi_join.htm。終于要代碼如下:
<%- local sys = require "luci.sys" local utl = require "luci.util" function guess_wifi_signal(info) local scale = (100 / (info.quality_max or 100) * (info.quality or 0)) local icon if not info.bssid or info.bssid == "00:00:00:00:00:00" then icon = resource .. "/icons/signal-none.png" elseif scale < 15 then icon = resource .. "/icons/signal-0.png" elseif scale < 35 then icon = resource .. "/icons/signal-0-25.png" elseif scale < 55 then icon = resource .. "/icons/signal-25-50.png" elseif scale < 75 then icon = resource .. "/icons/signal-50-75.png" else icon = resource .. "/icons/signal-75-100.png" end return icon end function percent_wifi_signal(info) local qc = info.quality or 0 local qm = info.quality_max or 0 if info.bssid and qc > 0 and qm > 0 then return math.floor((100 / qm) * qc) else return 0 end end function format_wifi_encryption(info) if info.wep == true then return "WEP" elseif info.wpa > 0 then return translatef("<abbr title='Pairwise: %s / Group: %s'>%s - %s</abbr>", table.concat(info.pair_ciphers, ", "), table.concat(info.group_ciphers, ", "), (info.wpa == 3) and translate("mixed WPA/WPA2") or (info.wpa == 2 and "WPA2" or "WPA"), table.concat(info.auth_suites, ", ") ) elseif info.enabled then return "<em>%s</em>" % translate("unknown") else return "<em>%s</em>" % translate("open") end end local dev = luci.http.formvalue("device") local iw = luci.sys.wifi.getiwinfo(dev) if not iw then luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless")) return end function scanlist(times) local i, k, v local l = { } local s = { } for i = 1, times do for k, v in ipairs(iw.scanlist or { }) do if not s[v.bssid] then l[#l+1] = v s[v.bssid] = true end end end return l end -%> <%+header%> <h3><a id="content" name="content"><%:Join Network: Wireless Scan%></a></h3> <div class="cbi-map"> <fieldset class="cbi-section"> <table class="cbi-section-table" > <!-- scan list --> <% for i, net in ipairs(scanlist(3)) do net.encryption = net.encryption or { } %> <tr class="cbi-section-table-row cbi-rowstyle-<%=1 + ((i-1) % 2)%>"> <td class="cbi-value-field" > <abbr title="<%:Signal%>: <%=net.signal%> <%:dB%> / <%:Quality%>: <%=net.quality%>/<%=net.quality_max%>"> <img src="<%=guess_wifi_signal(net)%>" /><br /> <small><%=percent_wifi_signal(net)%>%</small> </abbr> </td> <td class="cbi-value-field" > <big><strong><%=net.ssid and utl.pcdata(net.ssid) or "<em>%s</em>" % translate("hidden")%></strong></big><br /> <strong>Channel:</strong> <%=net.channel%> | <strong>Mode:</strong> <%=net.mode%> | <strong>BSSID:</strong> <%=net.bssid%> | <strong>Encryption:</strong> <%=format_wifi_encryption(net.encryption)%> </td> <td class="cbi-value-field" > <form action="<%=REQUEST_URI%>" method="post"> <input type="hidden" name="device" value="<%=utl.pcdata(dev)%>" /> <input type="hidden" name="join" value="<%=utl.pcdata(net.ssid)%>" /> <input type="hidden" name="mode" value="<%=net.mode%>" /> <input type="hidden" name="bssid" value="<%=net.bssid%>" /> <input type="hidden" name="channel" value="<%=net.channel%>" /> <input type="hidden" name="wep" value="<%=net.encryption.wep and 1 or 0%>" /> <% if net.encryption.wpa then %> <input type="hidden" name="wpa_version" value="<%=net.encryption.wpa%>" /> <% for _, v in ipairs(net.encryption.auth_suites) do %><input type="hidden" name="wpa_suites" value="<%=v%>" /> <% end; for _, v in ipairs(net.encryption.group_ciphers) do %><input type="hidden" name="wpa_group" value="<%=v%>" /> <% end; for _, v in ipairs(net.encryption.pair_ciphers) do %><input type="hidden" name="wpa_pairwise" value="<%=v%>" /> <% end; end %> <input type="hidden" name="clbridge" value="<%=iw.type == "wl" and 1 or 0%>" /> <input class="cbi-button cbi-button-apply" type="submit" value="<%:Join Network%>" /> </form> </td> </tr> <% end %> <!-- /scan list --> </table> </fieldset> </div>
進一步的測試發(fā)現(xiàn),在調用function scanlist(times)異常導致生成的網頁不完整,瀏覽器就會看到那段錯誤信息。而此函數(shù)又是在調用iw.scanlist發(fā)生異常。由local iw = luci.sys.wifi.getiwinfo(dev)找到sys.lua模塊,路徑/usr/lib/lua/luci/sys.lua,對應openwrt源碼位置./feeds/luci/modules/base/luasrc/sys.lua。主要源碼:
--- Get wireless information for given interface. -- @param ifname String containing the interface name -- @return A wrapped iwinfo object instance function wifi.getiwinfo(ifname) local stat, iwinfo = pcall(require, "iwinfo") if ifname then local c = 0 local u = uci.cursor_state() local d, n = ifname:match("^(%w+)%.network(%d+)") if d and n then ifname = d n = tonumber(n) u:foreach("wireless", "wifi-iface", function(s) if s.device == d then c = c + 1 if c == n then ifname = s.ifname or s.device return false end end end) elseif u:get("wireless", ifname) == "wifi-device" then u:foreach("wireless", "wifi-iface", function(s) if s.device == ifname and s.ifname then ifname = s.ifname return false end end) end local t = stat and iwinfo.type(ifname) local x = t and iwinfo[t] or { } return setmetatable({}, { __index = function(t, k) if k == "ifname" then return ifname elseif x[k] then return x[k](ifname) end end }) end end
原來是調用iwinfo命令完成的無線搜索。在openwrt下運行iwinfo命令:
root@OpenWrt:~# iwinfo --help Usage: iwinfo <device> info iwinfo <device> scan iwinfo <device> txpowerlist iwinfo <device> freqlist iwinfo <device> assoclist iwinfo <device> countrylist root@OpenWrt:~# iwinfo radio0 scan Cell 01 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 02 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 03 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 04 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 05 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 06 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 07 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 08 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 09 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 10 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 11 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 12 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 13 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 14 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 15 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 16 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 17 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 18 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 19 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none Cell 20 - Address: 00:00:00:00:00:00 ESSID: unknown Mode: Unknown Channel: unknown Signal: -256 dBm Quality: 0/0 Encryption: none
看看Address、ESSID。。 說明iwinfo根本就無法掃描到無線接入點。而在4、5月份編譯的版本運行此命令沒問題,可以搜索到接入點。iwinfo涉及到兩個文件,在openwrt系統(tǒng)下一個是可執(zhí)行文件/usr/bin/iwinfo,另一個是動態(tài)鏈接庫文件/usr/lib/libiwinfo.so。于是拷貝之前系統(tǒng)(可以用搜索功能)的iwinfo、libiwinfo.so文件到有問題的路由的/tmp目錄下,shell切換到/tmp目錄,執(zhí)行export LD_LIBRARY_PATH=.
然后再執(zhí)行./iwinfo radio0 scan,發(fā)現(xiàn)搜索無線接入點正常,看來出來就出在iwinfo、libiwinfo.so上。直接刪除/tmp目錄下的libiwinfo.so后再./iwinfo radio0 scan,問題又出現(xiàn)了。由此推斷出問題應該在libiwinfo.so里。iwinfo工具源碼在openwrt源碼的./package/network/utils/iwinfo下,注意Makefile文件有如下代碼:
IWINFO_BACKENDS := \ $(if $(CONFIG_PACKAGE_kmod-brcm-wl),wl) \ $(if $(CONFIG_PACKAGE_kmod-brcm-wl-mini),wl) \ $(if $(CONFIG_PACKAGE_kmod-brcm-wl-mimo),wl) \ $(if $(CONFIG_PACKAGE_kmod-madwifi),madwifi) \ $(if $(CONFIG_PACKAGE_kmod-mac80211),nl80211)
在src目錄下的Makefile文件有如下代碼:
ifneq ($(filter wl,$(IWINFO_BACKENDS)),) IWINFO_CFLAGS += -DUSE_WL IWINFO_LIB_OBJ += iwinfo_wl.o endif ifneq ($(filter madwifi,$(IWINFO_BACKENDS)),) IWINFO_CFLAGS += -DUSE_MADWIFI IWINFO_LIB_OBJ += iwinfo_madwifi.o endif ifneq ($(filter nl80211,$(IWINFO_BACKENDS)),) IWINFO_CFLAGS += -DUSE_NL80211 IWINFO_CLI_LDFLAGS += -lnl-tiny IWINFO_LIB_LDFLAGS += -lnl-tiny IWINFO_LIB_OBJ += iwinfo_nl80211.o endif
無線搜索有3中實現(xiàn),剛開始我也不知道841n下是用哪種,索性在makefile文件里寫些調試輸出語句。然后make package/network/utils/iwinfo/compile V=s重新編譯iwinfo,發(fā)現(xiàn)用的是nl80211,也就是說要改的代碼在./src/iwinfo_nl80211.c。經過一系列的調試最終發(fā)現(xiàn)bug所在。解決方案如下:
// iwinfo_cli.c文件 static void print_scanlist(const struct iwinfo_ops *iw, const char *ifname) { int i, x, len=0; //這里len必須初始化為0 char buf[IWINFO_BUFSIZE]; struct iwinfo_scanlist_entry *e; if (iw->scanlist(ifname, buf, &len)) { printf("Scanning not possible\n\n"); return; } else if (len <= 0) { printf("No scan results\n\n"); return; }
// iwinfo_nl80211.c文件nl80211_phy2ifname函數(shù)修改如下 static char * nl80211_phy2ifname(const char *ifname) { int fd, ifidx = -1, cifidx = -1, phyidx = -1; char buffer[64]; static char nif[IFNAMSIZ] = { 0 };//注意靜態(tài)變量 DIR *d; struct dirent *e; char *ret = NULL; //添加 if (!ifname) return NULL; else if (!strncmp(ifname, "phy", 3)) phyidx = atoi(&ifname[3]); else if (!strncmp(ifname, "radio", 5)) phyidx = atoi(&ifname[5]); //當傳進來的ifname=wlan0時,phyidx=-1,后面的memset可能會把ifname清空。 //memset(nif, 0, sizeof(nif)); //注釋掉,因為ifname可能指向nif if (phyidx > -1) { if ((d = opendir("/sys/class/net")) != NULL) { while ((e = readdir(d)) != NULL) { snprintf(buffer, sizeof(buffer), "/sys/class/net/%s/phy80211/index", e->d_name); if (nl80211_readint(buffer) == phyidx) { snprintf(buffer, sizeof(buffer), "/sys/class/net/%s/ifindex", e->d_name); if ((cifidx = nl80211_readint(buffer)) >= 0 && ((ifidx < 0) || (cifidx < ifidx))) { ifidx = cifidx; strncpy(nif, e->d_name, sizeof(nif)); ret = nif ; //添加 break ; //添加 } } } closedir(d); } } return ret ; //修改 }
make package/network/utils/iwinfo/compile V=s 重新編譯iwinfo,傳到路由上測試,iwinfo radio0 scan已經沒問題,可以正常搜索無線了。其實我不喜歡nl80211_phy2ifname函數(shù)用靜態(tài)變量方式返回,而更傾向于用函數(shù)參數(shù)的方式,例如聲明成static char * nl80211_phy2ifname(const char *ifname, char *out)。
上述內容就是怎么解決OpenWrt無線搜索錯誤bug,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業(yè)資訊頻道。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。