zoukankan      html  css  js  c++  java
  • DHCP与Option基本概念启蒙

    2020-06-04

    关键字:Option60、新增Option、插入一个Option


    1、DHCP是什么?

    DHCP 全称 Dynamic Host Configuration Protocol,动态主机配置协议。

    说人话就是用于路由器给各个电脑、手机、网络设备分配各种地址以使设备能访问网络用的,同时它还兼有管理某一局域网内设备的功能。

    DHCP 的前身是 BOOTP,即 Bootstrap Protocol。

    DHCP 是一种基于 UDP 协议的局域网通讯协议。

    2、Option是什么?

    DHCP 协议其实就是一段字节流,不同位置的字节数据代表着不同的含义。它大体上可以分成以下两个组成部分:

    1、正文部分

    2、附加选项部分

    正文部分就是一个DHCP包中必不可少的数据。

    附加选项是可选的,即 Option。通常会根据实际的场景需求来决定是否添加。Option部分是直接插在DHCP包的末尾的,它仍旧属于DHCP包。

    Option 的作用就是用以扩展 DHCP 的功能的。因为 DHCP 协议除了简单的分配地址外还要实现管理设备的功能,而不同应用场景往往又会催生出不同的需求,为了满足这些客制化的需求,就需要这种可以由用户自定义内容的“Option”可选项了。

    Option 的格式简单,大体可以分成三个组成部分:

    1、Option代码

    1个字节。

    2、内容长度

    1个字节。

    3、内容

    内容长度个字节。

    其格式如下图所示:

     

    因为 Option 代码就是用来区分不同用途的标识符。因为它占 1 个字节,因此 Option 总共有 256 种(0 ~ 255,事实上只有 254 种可以使用的值,因为 0 和 255 是保留值)

     

    在一个 DHCP 包中可以插入多个 Option 字段。例如,我们以一个 携带了 Option 字段的 DHCP 报文为例,其 Option 数量与位置如下图所示:

    Option 代码的值从 0 ~ 255 都代表了不同的含义,或者说代表了不同的控制类型。每一个代码的详细说明请各位同学自行参阅相关文档,这里给出文档链接如下:

    https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xml

    3、Option60

    Option60 就是指 Option 的代码为 0x3c 的字段值。它通常用于携带设备标识符信息以供 DHCP 服务器鉴权使用。从理论上来说,任何设备都可以接入到 DHCP 服务器并请求获得相应资源。但如果我们的 DHCP 所提供的这种服务是被“商业化”了的,那当然就需要这种鉴权机制了。鉴权不通过,我 DHCP 服务器就可以忽略掉这个设备的服务请求。这种鉴权,通常就是交由 Option60 来实现的。

    Option60 的格式如下图所示:

    Option60 的配置在 Android4.4 中们于如下代码文件:

    .frameworksasecorejavaandroid
    etEthernetDataTracker.java

    在系统起来以后开始 DHCP 获取 DHCP 时会调用 runDhcp() 方法:

    private void runDhcp()

    然后会在这里读取是否有开启 Option60 的标志以及要携带的数据信息。 Option60 的开启标志与数据信息通常可以在设置APK中设定。因为 Option60 常用于鉴权,因为有些设备是往 Option60 中填写一个通行证信息,并会做适当的加密操作。

    runDhcp() 方法中随后会通过 NetworkUtils.runDhcpPlus() 方法来将相应参数传递下去。这个方法是一个 native 方法,它的最终实现位于:

    .frameworksasecorejniandroid_net_NetUtils.cpp
        static jboolean android_net_utils_runDhcpCommon(...)

    随后又会调用 dhcp_do_request() 函数继续传递参数,如下图所示:

    随后就到以下代码中了:

    .systemcorelibnetutilsdhcp_utils.c

    这个 dhcp_do_request() 函数所做的事情,基本就是:根据参数组装启动 dhcpcd 服务的命令以及将参数信息写到系统属性中去。如下图所示:

    再然后就是 dhcpcd 服务登场了。dhcpcd 服务代码目录如下:

    ./external/dhcpcd/

    dhcpcd 服务在爬起来以后就会跑以下代码的 main() 函数:

    .externaldhcpcddhcpcd.c
        int main(int argc, char **argv)

    然后在如下图所示的函数中解析有哪些 Option 是要添加组装要携带的信息的:

     

    .externaldhcpcdif-options.c

    这里还是以 Option60 为例,它在 parse_option() 中的解析如下图所示:

    再接下来就到真正的发送 DHCP 数据报文的时候了。这个操作于 dhcp.c 代码中实现:

    .oxexternaldhcpcddhcp.c
      ssize_t make_message(struct dhcp_message **message, const struct interface *iface, uint8_t type)

    关于 Option60 的组装如下图所示。

    这个指针 p 就是记录 DHCP 报文字节流用的了。

    再往下就是将报文送到网卡驱动发送出去了。

    4、如何在DHCP网络包中插入一个新的Option?

    在 Android 系统中一般都会有 Option60 的完整实现,用户只需在设置APK中设置相应信息即可自动实现 Option60 的字段携带。

    但如何新增一个系统尚不支持的字段呢?

    其实也很简单。

    前面第 3 节介绍的 Option60 的调用组装流程照着来一次就行的了。这里就以新增一个 Option156 来简单说说如何在 DHCP 中插入一个新的 Option字段。

    首先的是应用层将相应信息传递下来的流程。这个就不多说了,同学根据自己的实际需求实现就好。

    然后我们可以关注 EthernetDataTracker.java 中的 runDhcp() 方法。可以依照 Option60 的做法将 Option156 的信息传递到这里来。如下图所示:

    然后,笔者为了偷懒,就直接将 Option156 的信息在这里写到系统属性中去了。这种做法不太好,因为按照常,我们应该将 Option156 的信息一步步传到 C 代码层,根据参数来组装启动 dhcpcd 服务的参数的。

    但笔者偷懒了。

    就这样吧。

    再然后就到 if-option.h 中去新增用于保存 Option156 信息的结构体变量:

    .externaldhcpcdif-options.h

    接下来是去 if-options.c 中解析 Option156 的信息,并将它拷贝到结构体中。直接复制 Option60 的做法来就行了:

    .externaldhcpcdif-options.c

    最后去到 dhcp.c 的 make_message() 函数中完成最后的拼装:

    .externaldhcpcddhcp.c

    如此,开机时抓一个 DHCP 的网络包,就可以发现笔者新增的 Option156 字段信息了,如下图所示:

    上图网络包 wireshark 提示了笔者添加的 Option156 值错误的警告。它的意思是说 Option156 这个字段的“内容”的长度只允许是 1。但笔者在这里给它携带了一个长度为 19 个字节的字符串。因为违反了规范,所以 wireshark 给出了警告。但这其实并不重要。只要你的 DHCP 服务器能解析出来,就没有问题。


    参考资料:

      http://www.360doc.com/content/15/1130/09/8335678_516871788.shtml

      https://blog.csdn.net/zzd_zzd/article/details/88372014

      https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xml

      https://tools.ietf.org/rfc/rfc6926.txt

  • 相关阅读:
    勿忘心安
    设△ABC的内角A,B,C,所对的边分别为a,b,c,且acosB-bcosA=3/5c,则tan(A-B)的最大值为
    P1011 车站
    第一天
    P1134 阶乘问题
    P3152 正整数序列
    某数论
    DO YOU WANNA BUILD A SNOW MAN ?
    luogu P1579 哥德巴赫猜想(升级版)
    紫书 习题 10-25 UVa 1575 (有重复元素的全排列+暴搜)
  • 原文地址:https://www.cnblogs.com/chorm590/p/13038284.html
Copyright © 2011-2022 走看看