Light-Weight DHCP Client
BusyBox 這套超強瑞士刀套件在嵌入式系統中幾乎可以說是必備,裡面也不乏網路 service 與 application。前陣子 review code 剛好看到 DHCP client 相關程式,就順便記錄 busybox 內建的 udhcpc 的用法吧!
DHCP(Dynamic Host Configuration Protocol) 在一般的區域網路是相當常見的服務,目的就是方便管理區域網路內的裝置,當一台 PC 連上區域網路時可向 DHCP Server 自動獲取可用 IP 位址,並且取得 subnet mask,gateway,DNS等資訊。技術細節可以參考 wiki 或其他網站,在此就不多說明了。前述所說 PC 在此架構之下就是 DHCP Client,需要 DHCP Server 來配發 IP 位址。而如何使用 busybox 內建的 DHCP Client (udhcpc) 向 DHCP Server 取得 IP呢?先來看一下 BusyBox 的 Command help:
udhcpc [-Cfbnqtvo] [-c CID] [-V VCLS] [-H HOSTNAME] [-i INTERFACE] [-p pidfile] [-r IP] [-s script] [-O dhcp-option]... -V,--vendorclass=CLASSID Vendor class identifier -i,--interface=INTERFACE Interface to use (default eth0) -H,-h,--hostname=HOSTNAME Client hostname -c,--clientid=CLIENTID Client identifier -C,--clientid-none Suppress default client identifier -p,--pidfile=file Create pidfile -r,--request=IP IP address to request -s,--script=file Run file at DHCP events (default /usr/share/udhcpc/default.script) -t,--retries=N Send up to N request packets -T,--timeout=N Try to get a lease for N seconds (default 3) -A,--tryagain=N Wait N seconds (default 20) after failure -O,--request-option=OPT Request DHCP option OPT (cumulative) -o,--no-default-options Do not request any options (unless -O is also given) -f,--foreground Run in foreground -b,--background Background if lease is not immediately obtained -S,--syslog Log to syslog too -n,--now Exit with failure if lease is not immediately obtained -q,--quit Quit after obtaining lease -R,--release Release IP on quit -a,--arping Use arping to validate offered address
忽然看到一長串說明訊息可別嚇到了,只要理解其作用挑選要使用的參數即可。
若不帶入任何參數,直接執行 udhcpc 可能會出現以下訊息
# udhcpc
udhcpc: ioctl 0x8933 failed: No such device
在預設的情況下,udhcpc 會對 eth0 界面發送封包,如果該界面不存在,則會出現此錯誤訊息。因次我們需要帶入特定界面(-i interface),同時希望把訊息也存入到 syslog 裡(-S),並且把 pid 寫入到特定檔案(-p file)。因此可以將命令改為:
# udhcpc -i eth1 -S -p /var/run/udhcpc.pid
udhcpc (v1.12.1) started
udhcpc: exec /usr/share/udhcpc/default.script: No such file or directory
Sending select for 192.168.4.50...
Lease of 192.168.4.50 obtained, lease time 120
udhcpc: exec /usr/share/udhcpc/default.script: No such file or directory
udhcpc 順利啟動了,也有出現在 process list (ps command)中,但是卻出現 udhcpc: exec /usr/share/udhcpc/default.script: No such file or directory 這個錯誤訊息,而且 ifconfig 中的 eth1 界面 IP 並沒有置換為得到的 192.168.4.50 IP,這又是為什麼?
你需要的只是 udhcpc script
當 udhcpc 取得了 IP 位址之後,會執行 script 並把從 DHCP server 得到的資訊帶入該 script 執行。因此上面才會出現找不到預設 script /usr/share/udhcpc/default.script 的錯誤訊息。而這個 script 的內容又該如何撰寫呢,我們可以直接拿 buildroot 的 udhcpc script 來參考:
#!/bin/sh # udhcpc script edited by Tim Riker <Tim@Rikers.org> [ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1 RESOLV_CONF="/etc/resolv.conf" [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" [ -n "$subnet" ] && NETMASK="netmask $subnet" case "$1" in deconfig) /sbin/ifconfig $interface 0.0.0.0 ;; renew|bound) /sbin/ifconfig $interface $ip $BROADCAST $NETMASK if [ -n "$router" ] ; then echo "deleting routers" while route del default gw 0.0.0.0 dev $interface ; do : done for i in $router ; do route add default gw $i dev $interface done fi echo -n > $RESOLV_CONF [ -n "$domain" ] && echo search $domain >> $RESOLV_CONF for i in $dns ; do echo adding dns $i echo nameserver $i >> $RESOLV_CONF done ;; esac exit 0
當 udhcpc 取得 IP 時,就會執行這個 script 並帶入參數
bound – 程式啟動後第一次向 DHCP Server 取得設定
renew – 更新 DHCP lease (租約)
deconfig – 釋放租約
與部份環境變數(會因 DHCP Server 的設定而有所不同)
$router – gateway 位址
$interface – 界面名稱
$ip – 配發到的 IP 位址
$subnet – 子網域遮罩
$broadcast – 廣播封包位置
$metric – metric 值
$dns – DNS Server 可能會包含不只一個
$domain – 網域名稱
聰明的你應該已經注意到,上面的 script 不過也就是把這些參數套用到實際的設定而已!了解此運作方式,要修改 script 符合實際的應用環境,也只是輕而易舉啦!把該 sctipt 存放到 /etc/udhcpc.sh(看個人習慣),重新執行命令即可!
# udhcpc -i eth1 -p /var/run/udhcpc.pid -S -s /etc/udhcpc.sh udhcpc (v1.12.1) started Sending select for 192.168.4.50... Lease of 192.168.4.50 obtained, lease time 120 deleting routers route: adding dns 192.168.5.2
再次使用 ifconfig 檢查即可發現 IP 位址已經被更新了!
Renew/Release Current Lease
如果 DHCP Server 的設定改變了,或是想要更新裝置上的網路設定,難道就必須把 udhcpc 給殺(kill)掉重新啟動嗎?這倒是不必了!只要發送 signal 通知 udhcpc 就可以了!
更新 DHCP 租約(renew DHCP lease):
# kill -SIGUSR1 `cat /var/run/udhcpc.pid `
釋放 DHCP 租約(release current release):
# kill -SIGUSR2 `cat /var/run/udhcpc.pid `