android DHCP流程【转】

摘要:
)[+]1.问题的背景最近遇到了一个问题。在项目中,无论是静态还是DHCP,都无法成功修改DNS。setpropdhcp.${intf}.dns${dnsvalue}203.82.48.3setpropdhcp.${int f}.dns${standydnsvalue}203.8 2.48.4#Setnet.<iface>.dnsN属性,包含DHCP服务器提供的#dns服务器地址。如果[[$interface==p2p*]]theintf=p2pelseintf=$interface=set_nns_props(){case“${new_domain_name_servers}”in“”)return0;;e账户=1234年;dosetpropdhcp.${intf}。dns${i}“”donecount=1fornsaddrin${new_domain_name_servers};dosetpropdhcp.${intf}.dns${count}${dnsaddr}count=$donednsvalue=1standdydnsvalue=2setpropdhcp.${intf}.dns${dsvalue}203.82.48.3setpropdhcp.${int f}.dns${{standydnsvalue}203.82.48.4 separator=“”if[-z“$new_domain_name”];thensearator=“”elseif[-z“$new_domain_search”];thensepher=“”fifisetpropdhcp.${interface}。域“${new_domain_name}$separator${new _domain_search}”}unset_dns_props(){foriin1234;dosetpropdhcp.${intf}.dns${i}“”donesetpropdhcp.${interface}。域“”}case“${reason}”inBOUND|INFORM|REBIND|REBOUT|RENEW|TIMEOUT)集合_ dns_props;;到期|失败|IPV4LL |释放|停止)未设置dns_道具;;Esac1234567891011121314151617181920212223242526272829303132333436373839394404142434464748495051525354555657此脚本有何用途?这是因为在Android中,DHCP分为两部分,一部分是DHCPClient端,另一部分是服务器端。这个过程并不困难。通常,runDhcp函数将在最后调用。其JNI位于frameworksasecorejniandroid_net_NetUtils中。cpp_net_utils_runDhcpCommon中的Androidstaticvoidfill_ ip_ info{property_get;property_get-;property-get;property.get;propty_get;属性-get;属性获取;属性获取123456789101112 DHCP真正起作用的是谁?这是dhcpd守护程序。该过程根据init.svc.dhcpcd进行控制。

本文转载自: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等,这种报文的应用非常少见。

免责声明:文章转载自《android DHCP流程【转】》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇WCF入门教程(一)简介IDEA禁止更新下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

AJAX全套

概述  对于WEB应用程序:用户浏览器发送请求,服务器接收并处理请求,然后返回结果,往往返回就是字符串(HTML),浏览器将字符串(HTML)渲染并显示浏览器上。 AJAX类似于偷偷像后台发送数据。 1、传统的Web应用 一个简单操作需要重新加载全局数据 2、AJAX AJAX,Asynchronous JavaScript and XML (异步的Ja...

使用sqlmap中tamper脚本绕过waf

使用sqlmap中tamper脚本绕过waf 刘海哥 · 2015/02/02 11:26 0x00 背景 sqlmap中的tamper脚本来对目标进行更高效的攻击。 由于乌云知识库少了sqlmap-tamper 收集一下,方便学习。 根据sqlmap中的tamper脚本可以学习过绕过一些技巧。 我收集在找相关的案例作为可分析什么环境使用什么tamp...

教会你Linux Shell自动交互的三种方法

你了解Linux系统么?你是Linux系统的应用者么?如果你要学习linux,你可能会遇到Linux Shell自动交互问题,这里将介绍Linux Shell自动交互的解决方法,在这里拿出来和大家分享一下。 一、背景 shell脚本在处理自动循环或大的任务方面可节省大量的时间,通过创建一个处理任务的命令清单,使用变量、条件、算术和循环等方法快速创建脚本以完...

PHP CLI模式开发

PHP CLI模式开发不需要任何一种Web服务器(包括Apache或MS IIS等),这样,CLI可以运行在各种场合。有两种方法可以运行PHP CLI脚本。 第一种方法是使用 # php /path/to/yourFile.php 调用PHP CLI解释器,并给脚本传递参数。这种方法要指定php解释器的路径。第二种方法是首先运行chmod +x <要...

浏览器窗口关闭事件的监听搜集

转自:http://www.2cto.com/kf/201108/100769.html 方式一:(适用与IE浏览器,而且刷新不提示,只在点击浏览器关闭按钮的时候提示)<script type="text/javascript">window.onbeforeunload=onclose;function onclose(){if(event....

(转)高性能JavaScript:加载和运行(动态加载JS代码)

浏览器是如何加载JS的 当浏览器遇到一个<script>标签时,浏览器首先根据标签src属性下载JavaScript代码,然后运行JavaScript代码,继而继续解析和翻译页面。如果需要加载的js文件很多很大,则会让人感觉页面加载很慢,影响页面的交互。浏览器在遇到<body>之前,不会渲染页面的任何部分,如果此时<head...