有线网络自动获取的网络信息显示错误问题分析
问题背景:
在大屏设备中,点击网络信息栏,分为五行显示栏,每行各自显示如是否动态获取网络,ip地址,子网掩码,网关地址,DNS服务器等信息。
问题现象&描述:
正常应该能够看到ip地址等信息,出现问题后,实际情况是在ip地址栏,显示乱码,不是正确的ip地址信息。
测试方法:
1、在设置-网络中,手动配置有线网路信息。
2、退出有线网络,再进入有线网络
3、多次进行手动/自动来回切换
4、即可出现自动获取的网络信息错误,在ip地址信息栏显示乱码。

定位过程&根因分析:
ip地址信息乱码,首先查看日志,排查是否是dhcp服务未能正确获取ip地址。

查看日志,发现dhcp服务正常启动,且成功获取了ip信息分配给了网口eth0。
此时怀疑是应用层调用底层接口获取ip地址后处理字符串错误导致此问题。
随后找应用开发人员确认,ip信息是由底层直接传输上来,他们只做显示。
问题确认由底层出现,只能添加打印,直接将底层获取的ip信息在日志中打印出来,看问题出现在哪里。
void EthernetDhcpController::OnDhcpSuccess(const std::string &iface, DhcpResult *result)
{
if (cbObject_ == nullptr || result == nullptr) {
NETMGR_EXT_LOG_E("cbObject_ or result is nullptr!");
return;
}
NETMGR_EXT_LOG_I("OnDhcpSuccess, iface[%{public}s]", iface.c_str());
// 输出 result 的各个值
NETMGR_EXT_LOG_I("@lfq@ dhcpResult.ipAddr : [%s]", result->strOptClientId);
NETMGR_EXT_LOG_I("@lfq@ dhcpResult.gateWay: [%s]", result->strOptRouter1);
NETMGR_EXT_LOG_I("@lfq@ dhcpResult.route1: [%s]", result->strOptRouter1);
NETMGR_EXT_LOG_I("@lfq@ dhcpResult.subNet: [%s]", result->strOptSubnet);
NETMGR_EXT_LOG_I("@lfq@ dhcpResult.route2: [%s]", result->strOptRouter2);
NETMGR_EXT_LOG_I("@lfq@ dhcpResult.dns1: [%s]", result->strOptDns1);
NETMGR_EXT_LOG_I("@lfq@ dhcpResult.dns2: [%s]", result->strOptDns2);
EthernetDhcpCallback::DhcpResult dhcpResult;
dhcpResult.iface = iface;
dhcpResult.ipAddr = result->strOptClientId;
dhcpResult.gateWay = result->strOptRouter1;
dhcpResult.subNet = result->strOptSubnet;
dhcpResult.route1 = result->strOptRouter1;
dhcpResult.route2 = result->strOptRouter2;
dhcpResult.dns1 = result->strOptDns1;
dhcpResult.dns2 = result->strOptDns2;
cbObject_->OnDhcpSuccess(dhcpResult);
}
找到EthernetDhcpController::OnDhcpSuccess函数,添加日志打印ip等信息。


添加日志后显示底层成功获取了两个ip地址,一个是ipv4地址,一个是ipv6地址。那么此接口获取ip地址是正确的,没有问题。继续往下追代码。
std::string AccumulateNetAddress(const std::vector<INetAddr> &netAddrList)
{
return std::accumulate(
netAddrList.begin(), netAddrList.end(), std::string(), [](const std::string &addr, const INetAddr &iter) {
NETMANAGER_EXT_LOGE("@lfq@ 拼接ip地址: %{public}s", (addr.empty() ? (addr + iter.address_) : (addr + DEFAULT_SEPARATOR + iter.address_)).c_str());
return addr.empty() ? (addr + iter.address_) : (addr + DEFAULT_SEPARATOR + iter.address_);
});
}
napi_value GetIfaceConfigCallback(GetIfaceConfigContext *context)
{
napi_value interfaceConfiguration = NapiUtils::CreateObject(context->GetEnv());
NapiUtils::SetInt32Property(context->GetEnv(), interfaceConfiguration, MODE, context->config_->mode_);
NETMANAGER_EXT_LOGE("@lfq@ GetIfaceConfigCallback 拼接IP_ADDR");
for (const auto& ipAddr : context->config_->ipStatic_.ipAddrList_) {
NETMANAGER_EXT_LOGE("@lfq@ IP 地址: %{public}s\n", ipAddr.address_.c_str());
}
std::string ipAddresses = AccumulateNetAddress(context->config_->ipStatic_.ipAddrList_);
NapiUtils::SetStringPropertyUtf8(context->GetEnv(), interfaceConfiguration, IP_ADDR, ipAddresses);
NETMANAGER_EXT_LOGE("@lfq@ GetIfaceConfigCallback 拼接ROUTE");
std::string routeAddresses = AccumulateNetAddress(context->config_->ipStatic_.routeList_);
NapiUtils::SetStringPropertyUtf8(context->GetEnv(), interfaceConfiguration, ROUTE, routeAddresses);
NETMANAGER_EXT_LOGE("@lfq@ GetIfaceConfigCallback 拼接GATEWAY");
for (const auto& gateway : context->config_->ipStatic_.gatewayList_) {
NETMANAGER_EXT_LOGE("@lfq@ 网关地址: %{public}s\n", gateway.address_.c_str());
}
std::string gatewayAddresses = AccumulateNetAddress(context->config_->ipStatic_.gatewayList_);
NapiUtils::SetStringPropertyUtf8(context->GetEnv(), interfaceConfiguration, GATEWAY, gatewayAddresses);
NETMANAGER_EXT_LOGE("@lfq@ GetIfaceConfigCallback 拼接NET_MASK");
std::string maskAddresses = AccumulateNetAddress(context->config_->ipStatic_.netMaskList_);
NapiUtils::SetStringPropertyUtf8(context->GetEnv(), interfaceConfiguration, NET_MASK, maskAddresses);
NETMANAGER_EXT_LOGE("@lfq@ GetIfaceConfigCallback 拼接DNS_SERVERS");
std::string dnsServers = AccumulateNetAddress(context->config_->ipStatic_.dnsServers_);
NapiUtils::SetStringPropertyUtf8(context->GetEnv(), interfaceConfiguration, DNS_SERVERS, dnsServers);
NapiUtils::SetStringPropertyUtf8(context->GetEnv(), interfaceConfiguration, DOMAIN,
context->config_->ipStatic_.domain_);
return interfaceConfiguration;
}
发现后续将dhcp获取的ipv4地址与ipv6地址进行了拼接然后传输到应用层了。添加日志打印也证实了这一点。

从添加的日志看,确实是底层将获取到的ipv4地址与ipv6地址拼接后上传到应用层。
结论:
从业务逻辑上来讲,这样做是对的,因为dhcp服务支持ipv6功能,那么获取到ipv6的地址是正常的。有线网络的接口没有区分ipv4与ipv6,应用调用的有线网络接口获取ip地址信息,在环境支持和设备支持的情况下,获取到了ipv6地址,就会将ipv4与ipv6信息一同上传,那么应用在根据自己的场景,若需要显示ipv4信息就从结果中提取ipv4的地址信息进行显示,若需要显示ipv6信息就从结果中提取ipv6的地址信息进行显示,。
更多推荐
所有评论(0)