Android 4.4 DHCP启动过程

一、启动DHCP服务java

public boolean reconnect() {
        if (mLinkUp) {
            mTeardownRequested.set(false);
            runDhcp();
        }
        return mLinkUp;
    }android

   

    private void runDhcp() {
        Thread dhcpThread = new Thread(new Runnable() {
            public void run() {
                DhcpResults dhcpResults = new DhcpResults();
                if (!NetworkUtils.runDhcp(mIface, dhcpResults)) { 服务器

                    // 若是启动DHCP服务失败,则什么都不作退出
                    Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
                    return;
                }网络

                // 若是启动DHCP服务成功,则设置对应的链接状态,并通知其余网络服务模块更新状态
                mLinkProperties = dhcpResults.linkProperties;dom

                mNetworkInfo.setIsAvailable(true);
                mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);
                Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
                msg.sendToTarget();
            }
        });
        dhcpThread.start();
    }ui

2、DHCP启动过程调试

1. JNI层接口server

    Java层调用的NetworkUtils.runDhcp(mIface, dhcpResults)接口,在android_net_Netutils.cpp中定义dns

        static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
        {
            return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);
        }接口

 

        static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz,

                                                         jstring ifname, jobject dhcpResults, bool renew)
        {

            ....

            if (renew) {
                result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength,
                dns, server, &lease, vendorInfo, domains, mtu);
            } else {
                result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,
                dns, server, &lease, vendorInfo, domains, mtu);
            }

            // 下面一段是将获取到的ip地址字段存储到JNI变量中供java层获取,此处省略

            ....

        }

 

2. DHCP客户端(libnetutils)

    dhcp_do_request接口定义在dhcp_utils.c中,该接口主要作了如下几个工做:

    a. 启动DHCP服务,并等待直至DHCP准备OK

        property_set(ctrl_prop, daemon_cmd);

        wait_for_property(daemon_prop_name, desired_status, 10)

    b. 等待DHCP服务端返回一个结果

        wait_for_property(result_prop_name, NULL, 30)

    c. 若是DHCP返回的结果状态值为OK,则从DHCP服务端设置的全局属性中读取ip地址、网关等信息

        fill_ip_info(interface, ipaddr, gateway, prefixLength, dns, server, lease, vendorInfo, domain, mtu)

 

3. DHCP服务端(dhcpcd)

    a. DHCP消息类型

        DHCPDISCOVER

        DHCPOFFER

        DHCPREQUEST

        DHCPDECLINE

        DHCPACK

        DHCPNACK

        DHCPRELEASE

        DHCPINFORM

 

    b. DHCP的四步租约过程

       DHCP租约过程就是DHCP客户机动态获取IP地址的过程。

        ①客户机请求IP(客户机发DHCPDISCOVER广播包)

                   当一个DHCP客户机启动时,会自动将本身的IP地址配置成0.0.0.0,因为使用0.0.0.0不能进行正常通

            信,因此客户机就必须经过DHCP服务器来获取一个合法的地址。因为客户机不知道DHCP服务器的IP地址,

            因此它使用0.0.0.0的地址做为源地址,使用UDP68端口做为源端口,使用255.255.255.255做为目标地址,使

            用UDP67端口做为目的端口来广播请求IP地址信息。广播信息中包含了DHCP客户机的MAC地址和计算机

            名,以便使DHCP服务器能肯定是哪一个客户机发送的请求。

 

        ②服务器响应(服务器发DHCPOFFER广播包)

                   当DHCP服务器接收到客户机请求IP地址的信息时,它就在本身的IP地址池中查找是否有合法的IP地址提

            供给客户机。若是有,DHCP服务器就将此IP地址作上标记,加入到DHCPOFFER的消息中,而后DHCP服务器

            就广播一则包括下列信息的DHCPOFFER消息:

                 DHCP客户机的MAC地址

                   DHCP服务器提供的合法IP地址

                   子网掩码

                   默认网关(路由)

                   租约的期限

                   DHCP服务器的IP地址

            由于DHCP客户机尚未IP地址,因此DHCP服务器使用本身的IP地址做为源地址,使用UDP67端口做为源端

            口,使用255.255.255.255做为目标地址,使用UDP68端口做为目的端口来广播DHCPOFFER信息。

 

        ③客户机选择IP(客户机发DHCPREQUEST广播包)

                 DHCP客户机从接收到的第一个DHCPOFFER消息中选择IP地址,发出IP地址的DHCP服务器将该地址保

            留,这样该地址就不能提供给另外一个DHCP客户机。当客户机从第一个DHCP服务器接收DHCPOFFER并选择IP

            地址后,DHCP租约的第三过程发生。客户机将DHCPREQUEST消息广播到全部的DHCP服务器,代表它接受提

            供的内容。DHCPREQUEST消息包括为该客户机提供IP配置的服务器的服务标识符(IP地址)。DHCP服务器

            查看服务器标识符字段,以肯定它本身是否被选择为指定的客户机提供IP地址,若是那些DHCPOFFER被拒

            绝,则DHCP服务器会取消提供并保留其IP地址以用于下一个IP租约请求。

                   在客户机选择IP的过程当中,虽然客户机选择了IP地址,可是尚未配置IP地址,而在一个网络中可能有几

            个DHCP服务器,因此客户机仍然使用0.0.0.0的地址做为源地址,使用UDP68端口做为源端口,使用

             255.255.255.255做为目标地址,使用UDP67端口做为目的端口来广播DHCPREQUEST信息。

 

        ④服务器肯定租约(服务器发DHCPACK/DHCPNAK广播包)

                 DHCP服务器接收到DHCPREQUEST消息后,以DHCPACK消息的形式向客户机广播成功的确认,该消息包

            含有IP地址的有效租约和其余可能配置的信息。虽然服务器确认了客户机的租约请求,可是客户机尚未收

            到服务器的DHCPACK消息,因此服务器仍然使用本身的IP地址做为源地址,使用UDP67端口做为源端口,使

            用255.255.255.255做为目标地址,使用UDP68端口做为目的端口来广播DHCPACK信息。当客户机收到

           DHCPACK消息时,它就配置了IP地址,完成了TCP/IP的初始化。

                   若是DHCPREQUEST不成功,例如客户机试图租约先前的IP地址,但该IP地址再也不可用,或者由于客户机

            移到其余子网,该IP无效时,DHCP服务器将广播否认确认消息DHCPNAK。当客户机接收到不成功的确认时,

            它将从新开始DHCP租约过程。

                   若是DHCP客户机没法找到DHCP服务器,它将从TCP/IP的B类网段169.254.0.0中挑选一个IP地址做为自

            己的IP地址,继续每隔5分钟尝试与DHCP服务器进行通信,一旦与DHCP服务器取得联系,则客户机放弃自

            动配置的IP地址,而使用DHCP服务器分配的IP地址。

 

    c. DHCP客户机向网络DHCP服务器租约IP地址的流程及实际log

        dhcpcd[1544]: version 5.5.6 starting
        dhcpcd[1544]: get_duid: Permission denied
        dhcpcd[1544]: eth0: using ClientID 01:12:78:e4:0b:44:00
        dhcpcd[1544]: eth0: executing `/system/etc/dhcpcd/dhcpcd-run-hooks', reason PREINIT
        dhcpcd[1544]: eth0: reading lease `/data/misc/dhcp/dhcpcd-eth0.lease'
        dhcpcd[1544]: eth0: rebinding lease of 192.168.4.164
        dhcpcd[1544]: eth0: sending REQUEST (xid 0x440be4), next in 3.54 seconds
        dhcpcd[1544]: eth0: sending REQUEST (xid 0x440be4), next in 7.63 seconds
        dhcpcd[1544]: eth0: NAK: from 192.168.4.1
        dhcpcd[1544]: eth0: executing `/system/etc/dhcpcd/dhcpcd-run-hooks', reason NAK
        dhcpcd[1544]: eth0: broadcasting for a lease
        dhcpcd[1544]: eth0: sending DISCOVER (xid 0x440be4), next in 4.97 seconds
        dhcpcd[1544]: eth0: offered 192.168.4.165 from 192.168.4.1
        dhcpcd[1544]: eth0: sending REQUEST (xid 0x440be4), next in 3.02 seconds
        dhcpcd[1544]: eth0: acknowledged 192.168.4.165 from 192.168.4.1
        dhcpcd[1544]: eth0: leased 192.168.4.165 for 7200 seconds
        dhcpcd[1544]: eth0: adding IP address 192.168.4.165/24
        dhcpcd[1544]: eth0: adding route to 192.168.4.0/24
        dhcpcd[1544]: eth0: adding default route via 192.168.4.1
        dhcpcd[1544]: eth0: writing lease `/data/misc/dhcp/dhcpcd-eth0.lease'
        dhcpcd[1544]: eth0: executing `/system/etc/dhcpcd/dhcpcd-run-hooks', reason BOUND

 

    d. 调试网络的经常使用命令

        (1) netcfg              netcfg   //查看ip状况              netcfg eth0 up dhcp   //经过dhcp 自动获取ip和网关           (2) ifconfig              ifconfig eth0 192.168.8.81 up              ifconfig eth0 192.168.8.81 netmask 255.255.255.0 up           (3) gateway 配置              route add default gw 192.168.0.1 dev eth0           (4) dns 配置              setprop net.dns1 192.168.8.11              setprop net.dns2 147.11.100.30           (5) mac adddr              ifconfig eth0 hw ether 00:AA:BB:33:44:55