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在 
frameworks\base\core\jni\android_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流程【转】的更多相关文章
- [Android Pro]   Android 打包流程
		Android 打包流程: 官网地址:http://developer.android.com/tools/building/index.html 具体的打包步骤如下: 1:生成R.java类文件:E ... 
- Android绘制流程
		一.前言 1.1.C++界面库 MFC.WTL.DuiLib.QT.Skia.OpenGL.Android里面的画图分为2D和3D两种: 2D是由Skia 来实现的,3D部分是由OpenGL实现的. ... 
- Android系统启动流程(一)解析init进程启动过程
		整体流程大致如下: 1.init简介 init进程是Android系统中用户空间的第一个进程,作为第一个进程,它被赋予了很多极其重要的工作职责,比如创建zygote(孵化器)和属性服务等.in ... 
- Android系统启动流程(四)Launcher启动过程与系统启动流程
		此前的文章我们学习了init进程.Zygote进程和SyetemServer进程的启动过程,这一篇文章我们就来学习Android系统启动流程的最后一步:Launcher的启动流程,并结合本系列的前三篇 ... 
- 【转】android SystemUI 流程分析
		android4 SystemUI 流程分析 什么是SystemUI? 对于Phone来说SystemUI指的是:StatusBar(状态栏).NavigationBar(导航栏).而对于Tablet ... 
- 【乘风破浪】Android系统启动流程整理
		前言 对于一个Android应用层开发者来说,了解Android系统的启动流程对理解Android系统有很大的帮助.这其中包含了大量的细节,而且前面很多步骤包含了C/C++实现的native层逻辑,作 ... 
- android 启动流程 相关 杂项记录
		Android原生流程 Init进程 主要流程及分支梳理 ueventd_main()watchdogd_main()主要流程a) 公共部分 增加PATH 环境变量初始化内核日志,打开/dev/kms ... 
- Android 启动流程分析
		原文:https://www.jianshu.com/p/a5532ecc8377 作者曾经在高通的Android性能组工作,主要工作是优化Android Application的启动时间. APP基 ... 
- android 待机流程
		以下分析基于android2.2的google源码.  开机启动时,首先执行PhoneWindowManager.systemReady()(这之前的流程不分析).调用KeyguardViewMed ... 
随机推荐
- Codeforces 919 A. Supermarket
			这场cf有点意思,hack场,C题等于1的特判hack很多人(我hack成功3个人,上分了,哈哈哈,咳咳...) D题好像是树形dp,E题好像是中国剩余定理,F题好像还是dp,具体的不清楚,最近dp的 ... 
- (2)Unity3d菜单
			1.文件菜单 2.编辑菜单 Frame Selected 焦点选择和双击Hierarchy中的元素一样的功能 Lock View to Selected 选中对象再点击此按钮,在场景视图中移动此对象 ... 
- 洛谷——P1144 最短路计数
			P1144 最短路计数 题目描述 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. 输入输出格式 输入格式: 输入第一行包含2个正整数N,M,为图的顶 ... 
- 链表的排序 时间复杂度O(nlogn)
			思路:用归并排序.对一个链表采用递归进行二等分,直到每个部分有序,然后对其进行合并.其实就是两步,先分解,然后合并有序链表. 代码: //对链表采用递归排序 class Solution { publ ... 
- 1005 Spell It Right
			1005 Spell It Right Given a non-negative integer N, your task is to compute the sum of all the dig ... 
- 【转载】Java NIO学习
			这篇文章介绍了NIO的基本概念: http://www.iteye.com/magazines/132-Java-NIO Java NIO提供了与标准IO不同的IO工作方式: Channels and ... 
- C#文件路径操作总结【转】
			http://www.cnblogs.com/zhoufoxcn/archive/2006/10/24/2515874.html 一.获取当前文件的路径 1. System.Diagnostics ... 
- python 工具mouse_find 鼠标定位
			import os,time import pyautogui as pag try: while True: print ("Press Ctrl-C to end") x,y ... 
- 利用反射快速给Model实体赋值  使用 Task 简化异步编程  Guid ToString 格式知多少?(GUID 格式)  Parallel Programming-实现并行操作的流水线(生产者、消费者)  c# 无损高质量压缩图片代码  8种主要排序算法的C#实现 (一)  8种主要排序算法的C#实现 (二)
			试想这样一个业务需求:有一张合同表,由于合同涉及内容比较多所以此表比较庞大,大概有120多个字段.现在合同每一次变更时都需要对合同原始信息进行归档一次,版本号依次递增.那么我们就要新建一张合同历史表, ... 
- 怎样在C语言里实现“面向对象编程”
			有人觉得面向对象是C++/Java这样的高级语言的专利,实际不是这样.面向对象作为一种设计方法.是不限制语言的.仅仅能说,用C++/Java这样的语法来实现面向对象会更easy.更自然一些. 在本节中 ... 
