zoukankan      html  css  js  c++  java
  • android DHCP流程【转】

    本文转载自:http://blog.csdn.net/myvest/article/details/51483647

     

    目录(?)[+]

     

    1、问题背景

    最近遇到一个问题,在一个项目中,无论静态或是DHCP,都无法成功修改DNS。 
    最后发现,是因为/etc/dhcpcd/dhcpcd-hooks/20-dns.conf 这个脚本中,将DNS写死了,如下代码片,每次设置完以后,还去在设置一次。

    setprop dhcp.${intf}.dns${dnsvalue} 203.82.48.3
    setprop dhcp.${intf}.dns${standydnsvalue} 203.82.48.4
    
    # Set net.<iface>.dnsN properties that contain the
    # DNS server addresses given by the DHCP server.
    
    if [[ $interface == p2p* ]]
        then
        intf=p2p
        else
        intf=$interface
    fi
    
    set_dns_props()
    {
        case "${new_domain_name_servers}" in
        "")   return 0;;
        esac
    
        count=1
        for i in 1 2 3 4; do
            setprop dhcp.${intf}.dns${i} ""
        done
    
        count=1
        for dnsaddr in ${new_domain_name_servers}; do
            setprop dhcp.${intf}.dns${count} ${dnsaddr}
            count=$(($count + 1))
        done
    
        dnsvalue=1
        standydnsvalue=2
        setprop dhcp.${intf}.dns${dnsvalue} 203.82.48.3
        setprop dhcp.${intf}.dns${standydnsvalue} 203.82.48.4
    
        separator=" "
        if [ -z "$new_domain_name" ]; then
           separator=""
        else
            if [ -z "$new_domain_search" ]; then
                separator=""
            fi
        fi
        setprop dhcp.${interface}.domain "${new_domain_name}$separator${new_domain_search}"
    }
    
    unset_dns_props()
    {
        for i in 1 2 3 4; do
            setprop dhcp.${intf}.dns${i} ""
        done
    
        setprop dhcp.${interface}.domain ""
    }
    
    case "${reason}" in
    BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT)       set_dns_props;;
    EXPIRE|FAIL|IPV4LL|RELEASE|STOP)                unset_dns_props;;
    esac
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    那么,这个脚本是有什么用处呢?为什么这个脚本可以写死DNS。 
    这是因为android中,DHCP分为两个部分,一个是DHCP Client端,一个是server端。

    2、Dhcp客户端

    client端就是我们从上层APP到framework后发出的DHCP请求。这个流程不难,一般是最后会调用runDhcp函数,其JNI在 
    frameworksasecorejniandroid_net_NetUtils.cpp 
    中的android_net_utils_runDhcpCommon。然后会在调用dhcp_do_request函数。到这里,framework的部分就完了,接下来会调用到system/core/libnetutils中去。

    在dhcp_do_request函数中,当[dhcp.eth0.result]属性变为[ok]时,会调用fill_ip_info函数,这个函数的作用,就是去读取IP信息而已。

    
    static void fill_ip_info(const char *interface, in_addr_t *ipaddr, in_addr_t *gateway, in_addr_t *mask, in_addr_t *dns1, in_addr_t *dns2, in_addr_t *server, uint32_t  *lease)
    {
    
    property_get(“dhcp.eth0. ipaddress”, prop_value,NULL);
    property_get(“dhcp.eth0. gateway”, prop_value,NULL);
    property_get(“dhcp.eth0. mask”, prop_value,NULL);
    property_get(“dhcp.eth0. dns1”, prop_value,NULL);
    property_get(“dhcp.eth0. dns2”, prop_value,NULL);
    property_get(“dhcp.eth0. server”, prop_value,NULL);
    property_get(“dhcp.eth0. leasetime”, prop_value,NULL);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    那是谁去真正做DHCP的工作呢,是dhcpd这个守护进程。这个进程是根据init.svc.dhcpcd来控制的。这个进程会去设置这些属性,这些属性最后都是根据脚本设置的,也就是我们上面提到的脚本20-dns.conf和95-configured。这两个脚本又是通过etc/dhcpcd/dhcpcd-run-hooks调起来的。 
    大概流程如下面:

    3、Dhcp server端

    dhcpcd 调用过程:

    代码在external/dhcpcd下,

    =>main
    # define SYSCONFDIR "/system/etc/dhcpcd"
    #define PACKAGE "dhcpcd"
     # define CONFIG SYSCONFDIR "/" PACKAGE ".conf"
     # define LIBEXECDIR "/system/etc/dhcpcd"
     # define SCRIPT LIBEXECDIR "/" PACKAGE "-run-hooks"
    =>strlcpy(options->script, SCRIPT, sizeof(options->script));//默认的options->script="/system/etc/dhcpcd /dhcpcd-run-hooks"
    =>f = fopen(cf ? cf : CONFIG, "r");//如果没有指定.conf文件,那么使用默认.conf文件
    =>parse_config_line//解析"/system/etc/dhcpcd/dhcpcd.conf"默认配置文件
    =>parse_option
    =>如果在"/system/etc/dhcpcd/dhcpcd.conf"有"script"这个节
    =>那么执行strlcpy(options->script, oarg, sizeof(options->script));直接拷贝
     /*
     {"script", required_argument, NULL, 'c'},
     {"option", required_argument, NULL, 'o'},
    "/system/etc/dhcpcd/dhcpcd.conf"中的部分内容如下:
     ...
    option domain_name_servers, domain_name, domain_search, host_name
     ...
     */
    =>dhcp_run
    =>handle_dhcp_packet
    =>handle_dhcp
    =>bind_dhcp
      reason = "TIMEOUT";reason = "BOUND";reason = "REBIND";reason = "RENEW";
    system/extra/dhcpcd-4.0.0-beta9/configure.c
    => configure(iface, reason, state->new, state->old, &state->lease, options, 1);
    //如果dhcp超时或者dhcp成功,都会调用exec_script来执行脚本,
    //执行setprop dhcp.${interface}.result "failed"或者
    //执行setprop dhcp.${interface}.result "ok"
    =>exec_script(options, iface->name, reason, NULL, old);
    =>然后configure_env通过环境变量将reason传递到脚本中
    int exec_script(const struct options *options, const char *iface, const char *reason,
    const struct dhcp_message *dhcpn, const struct dhcp_message *dhcpo)
    =>pid = fork();
    =>if(pid == 0)execve(options->script, argv, env);//子进程执行脚本,默认"/system/etc/dhcpcd/dhcpcd-run-hooks"
    //dhcpcd-run-hooks脚本会根据level值,决定是否执行system/etc/dhcpcd/dhcpcd-hook/*目录下的相应文件
    //我们的系统在该system/etc/dhcpcd/dhcpcd-hook/*目录下有如下2个文件
    //95-configured
    //20-dns.conf
    =>父进程返回while (waitpid(pid, &status, 0) == -1)等待子进程脚本执行完成
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    4、DHCP协议

    有一点,在过滤网络包的时候,应该过滤的是bootp,而不是dhcp哦,dhcp报文的种类有以下这些:

    (1)DHCPDISCOVER(0×01),此为Client开始DHCP过程的第一个报文;

    (2)DHCPOFFER(0×02),此为Server对DHCPDISCOVER报文的响应;

    (3)DHCPREQUEST(0×03),此报文是Slient开始DHCP过程中对server的DHCPOFFER报文的回应,或者是client续延IP地址租期时发出的报文;

    (4)DHCPDECLINE(0×04),当Client发现Server分配给它的IP地址无法使用,如IP地址冲突时,将发出此报文,通知Server禁止使用IP地址;

    (5)DHCPACK(0×05),Server对Client的DHCPREQUEST报文的确认响应报文,Client收到此报文后,才真正获得了IP地址和相关的配置信息;

    (6)DHCPNAK(0×06),Server对Client的DHCPREQUEST报文的拒绝响应报文,Client收到此报文后,一般会重新开始新的DHCP过程;

    (7)DHCPRELEASE(0×07),Client主动释放server分配给它的IP地址的报文,当Server收到此报文后,就可以回收这个IP地址,能够分配给其他的Client;

    (8)DHCPINFORM(0×08),Client已经获得了IP地址,发送此报文,只是为了从DHCPSERVER处获取其他的一些网络配置信息,如routeip,DNSIp等,这种报文的应用非常少见。

  • 相关阅读:
    学习笔记9(必做)
    团队作业(四):描述设计
    改进ls的实现(课下作业)
    stat命令的实现-mysate(必做)
    反汇编测试
    学习笔记8(必做)
    初次使用git上传代码到码云
    团队作业(三):确定分工
    学习笔记7(必做)
    缓冲区溢出漏洞实验
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/8244600.html
Copyright © 2011-2022 走看看