[udhcpc] busybox udhcpc 功能討論

其實 busybox udhcpc 可以實現許多很實用的功能,例如

  • 定時更新 IP 與租約
  • 背景執行 (與 linux 背警執行的 & 不同,要看其他 option 來做變化)
  • 立即取得租約
  • 可以控制 udhcpc 本身 process 的運作

我們可以先看 busybox 的 udhcpc help options

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
[root@cMT-3E8D /root]# udhcpc --help
BusyBox v1.20.2 (2014-05-26 18:14:32 CST) multi-call binary.

Usage: udhcpc [-fbnqvoCRB] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]
[-V VENDOR] [-x OPT:VAL]... [-O OPT]...

-i,--interface IFACE Interface to use (default eth0)
-p,--pidfile FILE Create pidfile
-s,--script PROG Run PROG at DHCP events (default /usr/share/udhcpc/default.script)
-B,--broadcast Request broadcast replies
-t,--retries N Send up to N discover packets
-T,--timeout N Pause between packets (default 3 seconds)
-A,--tryagain N Wait N seconds after failure (default 20)
-f,--foreground Run in foreground
-b,--background Background if lease is not obtained
-n,--now Exit if lease is not obtained
-q,--quit Exit after obtaining lease
-R,--release Release IP on exit
-S,--syslog Log to syslog too
-a,--arping Use arping to validate offered address
-O,--request-option OPT Request option OPT from server (cumulative)
-o,--no-default-options Don't request any options (unless -O is given)
-r,--request IP Request this IP address
-x OPT:VAL Include option OPT in sent packets (cumulative)
Examples of string, numeric, and hex byte opts:
-x hostname:bbox - option 12
-x lease:3600 - option 51 (lease time)
-x 0x3d:0100BEEFC0FFEE - option 61 (client id)
-F,--fqdn NAME Ask server to update DNS mapping for NAME
-V,--vendorclass VENDOR Vendor identifier (default 'udhcp VERSION')
-C,--clientid-none Don't send MAC as client identifier
-v Verbose
Signals:
USR1 Renew lease
USR2 Release lease

我們針對這幾個選項做討論好了,其他的可以去看 udhcpc 的 man page 獲得更多的訊息與使用方式

  • -i IFACE: 選定 udhcpc 所要使用的網路介面
    • usage: udhcpc -i wlan0 (假設是使用 wifi 介面)
    • 可以針對不同的網路介面去取得 dhcp server 所配給的 ip address
  • -p PIDFILE: 當 udhcpc 執行後有保留其 process 的時候,建立 udhcpc pid file
    • usage: udhcpc -i eth0 -p /var/run/udhcpc-eth0.pid
    • 可以保存其 pid file 並透過 pid 相關的控制指令去控制其 pid file,例如 kill 指令 (kill 不單單是可以殺掉 process 也可以傳輸 signal)
  • -s SCRIPT_PATH: 可以使用特定的 udhcpc 腳本
    • usage: udhcpc -i eth0 -s /etc/udhcpc_special.script
    • 因為有時候會針對不同的介面去跑不同的腳本,而腳本的討論會在這個文章中做說明(等更新時連結會附上)
    • 預設的腳本路徑是 /usr/share/udhcpc/default.script 當沒有這個檔案應該沒辦法跑 udhcpc,所以這個腳本一定要有,不帶參數的時候就是跑這個腳本
  • -t RETRY_NUM: 指定取得 dhcp reply 的次數
    • usage: udhcpc -i eth0 -t 3
    • RETRY_NUM 表示當 udhcpc 要不到 dhcp reply 的時候還會執行的次數 (實際上是 RETRY_NUM-1)
    • 當成功要到 ip address 就不會再發送後續次數的封包
  • -T TIMEOUT: 設定 dhcp reply 回覆的等待時間
    • 預設是三秒
    • 如果三秒等待不到 reply packet 就會進入後續動作 (若有 -q 就離開,有 -t 3 就會繼續發 request 封包)
  • -A AFTER_N_SECS: 若 dhcp 失敗後,等待 AFTER_N_SECS 後再執行一次相同動作
    • usage: udhcpc -i eth0 -A 60,表示失敗後等待 60 s 再次執行 udhcpc -i eth0 -A 60
    • -A 通常要配 -b 或是 -p,在背景執行時失敗後會重新執行 udhcpc
    • 這個跟 -t RETRY_NUM 不一樣,-A 是當程式真的認為已經進入了 dhcp failure 的狀態的時候會等待一段時間後再執行 udhcpc,而 -t 次數都結束且都沒有要到 ip address 的時候才會認定是 dhcp failure
    • 預設是 20 s
  • -f/-b: process 執行的位置 foreground / background
    • usage: udhcpc -i eth0 -f / udhcpc -i eth0 -b
    • -b 比較特殊,-b 是當封包沒有要到的時候會自動進入背景,此時 process 不會消失,可以使用 kill() 傳送 signal 給 udhcpc process
  • -n: 當沒有要到 ip address 的時候離開 process
    • usage: udhcpc -i eth0 -n
    • -b-n 不要同時存在,一個是沒要到會進入背景執行,另一個是沒要到會刪掉 process,如果兩個同時存在時,我試過 -n 的 priority 比較高,-b 沒有意義
  • -q: 當要到 ip address 的時候離開
    • usage: uchcpc -i eth0 -q
    • 這個在一些特殊的地方會用到,通常當你要到 ip address 之後不會想要針對 process 進行處置的時候可以用此 option
    • 若你只是想要從網域中發送 dhcp 封包並且獲得一個合理的回覆,但並不會想要對此封包做任何處置用這個指令也很適合
  • -R: 當 process 被殺掉的時候執行 release request
    • usage: udhcpc -i eth0 -R
    • 這個算是蠻重要的一環,但也相對要小心使用,因為這樣才可以保證網域內的網路分配是可以循環使用的,不然通常沒有加上 -R 的 udhcpc 離開時,dhcp server 並不知道,導致此 ip address 一直被這個 mac 所佔用,要等到 86400 秒租約過期後才會釋出

關於 udhcpc signal 的討論 (SIGUSR1/SIGUSR2)

  • 關於狀態機的討論,請看這個文章(等更新後會附上)
  • SIGUSR1 (10): 目的是強制執行 renew 狀態,狀態機會跳到 RENEW_REQUESTED,但是等同於 RENEW 狀態,之後自動進入 REBINDING 狀態並且發送 DHCPREQUEST packet
    之後會運行 timeout >> 1 直到 timeout <=0 為止,總共花了約 50s 才發生 timeout 回到 INIT 狀態並且 script run deconfig
  • SIGYSR2 (12): 目的是強制 release 現在的 lease,並將狀態強制進到 RELEASED 狀態,此狀態在 udhcpc source code並沒有任何功能,就是一個 idle status,但是如果收到 SIGUSR1 的訊號時,就會立即將狀態回到 INIT 狀態

由以上的討論,如果要將 udhcpc 設成 daemon 的話,最好的方式就是執行

1
2
3
pid = check_pid("/var/run/udhcpc-eth0.pid");
kill(SIGUSR2, pid); // set udhcpc to release state
kill(SIGUSR1, pid); // set udhcpc to init state and get lease again

實際 udhcpc 指令的使用方式

我們直接用 bash 的指令直接說明,以下是我在公司工作時被要求需要達到的網路功能

  1. 希望網路要到的時候會產生一個 pid file: /var/run/udhcpc-<IFACE>.pid
  2. 希望可以發送三次 udhcpc 的 requeset 封包 (實驗過後覺得發送三次最適當)
  3. 希望沒有要到的時候可以每 60 秒嘗試再要一次 ip address

就以上三點,我們可以直接使用剛剛提到的 option 組合來實現:

1
udhcpc -i <IFACE> -p /var/run/udhcpc-eth0.pid -b -t 3 -A 60

理論上要不到 ip,會進入背景,並且 hang 60 sec 之後才會再丟 3 次 discover 封包,若可以要到的話,就可以直接要到 IP,daemon 還是會存在,若要不到的話,會重新計數 retry 時間,然後 60s 後自動要到 ip address

這篇結束後,我們將會討論 udhcpc 所使用的 script 的結構與設計方式