BusyBox 應用 – udhcpc

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 `

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *


2 + 一 =