Android DHCPプロセス


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..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

では、このシナリオは何の役に立つのでしょうか.なぜこのスクリプトはDNSを書くことができますか.これはandroidではDHCPがDHCP Client端子とserver端子の2つの部分に分かれているからです.
2、Dhcpクライアント
クライアント側は、上位アプリからframeworkまでのDHCPリクエストです.このプロセスは難しくありません.一般的にrunDhcp関数が呼び出されます.JNIはframeworksbasecorejniandroid_にあります.net_NetUtils.cppのandroid_net_utils_runDhcpCommon.dhcp_が呼び出されますdo_request関数.ここまでframeworkの部分は終わり、次にsystem/core/libnetutilsに呼び出されます.
dhcp_do_request関数では、[dhcp.eth 0.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);
}

それは誰が本当にDHCPの仕事をしているのか、dhcpdという守護プロセスです.このプロセスはinitに基づいています.svc.dhcpcdで制御されます.このプロセスはこれらの属性を設定し、これらの属性は最後にスクリプトに基づいて設定されます.つまり、上述のスクリプト20-dnsです.confと95-configured.この2つのスクリプトはまた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)           

4、DHCPプロトコル
一つ、ネットワークパケットをフィルタリングするときにフィルタリングすべきはbootpで、dhcpではありませんよ.dhcpメッセージの種類は以下の通りです.
(1)DHCPDISCOVER(0×01)ClientがDHCPプロセスを開始する最初のメッセージである.
(2)DHCPOFFER(0×02)DHCPDISCOVERメッセージに対するサーバの応答.
(3)DHCPREQUEST(0×03)このメッセージは、SlientがDHCPを開始する過程でserverのDHCPOFFERメッセージに対する応答、またはclientがIPアドレスのリース期間を延長する時に発行されるメッセージである.
(4)DHCPDECLINE(0×04)Clientは、サーバーに割り当てられたIPアドレスが使用できないことを発見し、例えばIPアドレスが衝突した場合、このメッセージを発行し、サーバーにIPアドレスの使用を禁止することを通知する.
(5)DHCPACK(0×05)、サーバーはClientのDHCPREQUESTメッセージの確認応答メッセージに対して、Clientはこのメッセージを受け取った後、やっと本当にIPアドレスと関連する配置情報を獲得した;
(6)DHCPNAK(0×06)サーバはClientのDHCPREQUESTメッセージに対する拒絶応答メッセージを受信し、Clientはこのメッセージを受信した後、一般的に新しいDHCPプロセスを再開する.
(7)DHCPRELEASE(0×07)Clientは、サーバが割り当てたIPアドレスのメッセージを自発的に解放し、サーバがこのメッセージを受信すると、このIPアドレスを回収し、他のClientに割り当てることができる.
(8)DHCPINFORM(0×08)ClientはすでにIPアドレスを取得しており、このメッセージを送信するのは、DHCPSERVERからrouteip,DNSIpなどの他のネットワーク構成情報を取得するためだけであり、このようなメッセージの応用は非常に珍しい.