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 中們於如下代碼文件:

.\frameworks\base\core\java\android\net\EthernetDataTracker.java

在系統起來以后開始 DHCP 獲取 DHCP 時會調用 runDhcp() 方法:

private void runDhcp()

然后會在這里讀取是否有開啟 Option60 的標志以及要攜帶的數據信息。 Option60 的開啟標志與數據信息通常可以在設置APK中設定。因為 Option60 常用於鑒權,因為有些設備是往 Option60 中填寫一個通行證信息,並會做適當的加密操作。

 

runDhcp() 方法中隨后會通過 NetworkUtils.runDhcpPlus() 方法來將相應參數傳遞下去。這個方法是一個 native 方法,它的最終實現位於:

.\frameworks\base\core\jni\android_net_NetUtils.cpp
    static jboolean android_net_utils_runDhcpCommon(...)

隨后又會調用 dhcp_do_request() 函數繼續傳遞參數,如下圖所示:

 

 

隨后就到以下代碼中了:

.\system\core\libnetutils\dhcp_utils.c

 

這個 dhcp_do_request() 函數所做的事情,基本就是:根據參數組裝啟動 dhcpcd 服務的命令以及將參數信息寫到系統屬性中去。如下圖所示:

 

再然后就是 dhcpcd 服務登場了。dhcpcd 服務代碼目錄如下:

./external/dhcpcd/

 

dhcpcd 服務在爬起來以后就會跑以下代碼的 main() 函數:

.\external\dhcpcd\dhcpcd.c
    int main(int argc, char **argv)

然后在如下圖所示的函數中解析有哪些 Option 是要添加組裝要攜帶的信息的:

 

 

.\external\dhcpcd\if-options.c

 

 

這里還是以 Option60 為例,它在 parse_option() 中的解析如下圖所示:

 

 

再接下來就到真正的發送 DHCP 數據報文的時候了。這個操作於 dhcp.c 代碼中實現:

.\box\external\dhcpcd\dhcp.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 信息的結構體變量:

.\external\dhcpcd\if-options.h

 

 

接下來是去 if-options.c 中解析 Option156 的信息,並將它拷貝到結構體中。直接復制 Option60 的做法來就行了:

.\external\dhcpcd\if-options.c

 

 

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

.\external\dhcpcd\dhcp.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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM