温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

怎么解决OpenWrt无线搜索错误bug

发布时间:2021-12-06 16:28:44 来源:亿速云 阅读:269 作者:柒染 栏目:互联网科技

本篇文章为大家展示了怎么解决OpenWrt无线搜索错误bug,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

    TP-LINK 841n路由更新openwrt系统到Barrier Breaker r41988,“网络”-->“无线”-->“搜索”这个功能就不能用了,trunk版的也有这个问题。其实今年4、5月份玩HG255D路由就有这个问题,但当时的源码编译给TP-LINK 841n却没有这个问题。对这样的问题,确实比较头大,花了两天时间终于找到bug所在(只解决wr841n的,我的hg255d出问题了)。

    无线搜索bug截图(注意device参数radio0):

怎么解决OpenWrt无线搜索错误bug

一番搜索后发现此页面的源码在系统的/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>

进一步的测试发现,在调用function scanlist(times)异常导致生成的网页不完整,浏览器就会看到那段错误信息。而此函数又是在调用iw.scanlist发生异常。由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系统下一个是可执行文件/usr/bin/iwinfo,另一个是动态链接库文件/usr/lib/libiwinfo.so。于是拷贝之前系统(可以用搜索功能)的iwinfo、libiwinfo.so文件到有问题的路由的/tmp目录下,shell切换到/tmp目录,执行export LD_LIBRARY_PATH=.

然后再执行./iwinfo radio0 scan,发现搜索无线接入点正常,看来出来就出在iwinfo、libiwinfo.so上。直接删除/tmp目录下的libiwinfo.so后再./iwinfo radio0 scan,问题又出现了。由此推断出问题应该在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中实现,刚开始我也不知道841n下是用哪种,索性在makefile文件里写些调试输出语句。然后make package/network/utils/iwinfo/compile V=s重新编译iwinfo,发现用的是nl80211,也就是说要改的代码在./src/iwinfo_nl80211.c。经过一系列的调试最终发现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函数修改如下 static char * nl80211_phy2ifname(const char *ifname) {	int fd, ifidx = -1, cifidx = -1, phyidx = -1;	char buffer[64];	static char nif[IFNAMSIZ] = { 0 };//注意静态变量	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函数用静态变量方式返回,而更倾向于用函数参数的方式,例如声明成static char * nl80211_phy2ifname(const char *ifname, char *out)。

上述内容就是怎么解决OpenWrt无线搜索错误bug,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI