问题背景:

        在大屏设备中,点击网络信息栏,分为五行显示栏,每行各自显示如是否动态获取网络,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的地址信息进行显示,。

 

 

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐