其實 busybox udhcpc 可以實現許多很實用的功能,例如
我們可以先看 busybox 的 udhcpc help options1
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
- usage:
-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)
- usage:
-s SCRIPT_PATH
: 可以使用特定的 udhcpc 腳本- usage:
udhcpc -i eth0 -s /etc/udhcpc_special.script
- 因為有時候會針對不同的介面去跑不同的腳本,而腳本的討論會在這個文章中做說明(等更新時連結會附上)
- 預設的腳本路徑是
/usr/share/udhcpc/default.script
當沒有這個檔案應該沒辦法跑 udhcpc,所以這個腳本一定要有,不帶參數的時候就是跑這個腳本
- usage:
-t RETRY_NUM
: 指定取得 dhcp reply 的次數- usage:
udhcpc -i eth0 -t 3
RETRY_NUM
表示當 udhcpc 要不到 dhcp reply 的時候還會執行的次數 (實際上是RETRY_NUM-1
)- 當成功要到 ip address 就不會再發送後續次數的封包
- usage:
-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
- usage:
-f/-b
: process 執行的位置 foreground / background- usage:
udhcpc -i eth0 -f
/udhcpc -i eth0 -b
-b
比較特殊,-b
是當封包沒有要到的時候會自動進入背景,此時 process 不會消失,可以使用kill()
傳送 signal 給 udhcpc process
- usage:
-n
: 當沒有要到 ip address 的時候離開 process- usage:
udhcpc -i eth0 -n
-b
與-n
不要同時存在,一個是沒要到會進入背景執行,另一個是沒要到會刪掉 process,如果兩個同時存在時,我試過-n
的 priority 比較高,-b
沒有意義
- usage:
-q
: 當要到 ip address 的時候離開- usage:
uchcpc -i eth0 -q
- 這個在一些特殊的地方會用到,通常當你要到 ip address 之後不會想要針對 process 進行處置的時候可以用此 option
- 若你只是想要從網域中發送 dhcp 封包並且獲得一個合理的回覆,但並不會想要對此封包做任何處置用這個指令也很適合
- usage:
-R
: 當 process 被殺掉的時候執行 release request- usage:
udhcpc -i eth0 -R
- 這個算是蠻重要的一環,但也相對要小心使用,因為這樣才可以保證網域內的網路分配是可以循環使用的,不然通常沒有加上
-R
的 udhcpc 離開時,dhcp server 並不知道,導致此 ip address 一直被這個 mac 所佔用,要等到 86400 秒租約過期後才會釋出
- usage:
關於 udhcpc signal 的討論 (SIGUSR1/SIGUSR2
)
- 關於狀態機的討論,請看這個文章(等更新後會附上)
SIGUSR1 (10)
: 目的是強制執行 renew 狀態,狀態機會跳到RENEW_REQUESTED
,但是等同於RENEW
狀態,之後自動進入REBINDING
狀態並且發送DHCPREQUEST
packet
之後會運行timeout >> 1
直到timeout <=0
為止,總共花了約 50s 才發生 timeout 回到 INIT 狀態並且 script run deconfigSIGYSR2 (12)
: 目的是強制 release 現在的 lease,並將狀態強制進到RELEASED
狀態,此狀態在 udhcpc source code並沒有任何功能,就是一個 idle status,但是如果收到SIGUSR1
的訊號時,就會立即將狀態回到INIT
狀態
由以上的討論,如果要將 udhcpc 設成 daemon 的話,最好的方式就是執行1
2
3pid = 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 的指令直接說明,以下是我在公司工作時被要求需要達到的網路功能
- 希望網路要到的時候會產生一個 pid file:
/var/run/udhcpc-<IFACE>.pid
- 希望可以發送三次 udhcpc 的 requeset 封包 (實驗過後覺得發送三次最適當)
- 希望沒有要到的時候可以每 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 的結構與設計方式