我目前在开发的一款嵌入式产品,运行Linux系统,需要产品支持接入以太网后自动获取IP地址功能,写下此文记录实现的过程。
产品前期调试,为了方便直接通过ifconfig命令设置产品IP为固定IP,例如:
- ifconfig eth0 down
- ifconfig eth0 192.168.1.100
- ifcofnig eth0 up
产品成熟后,需通过DCHP让产品自动获取动态IP地址。
DHCP全称是:动态主机设置协议(英语:Dynamic Host Configuration Protocol,DHCP)它是一个局域网的网络协议,使用 UDP 协议工作,主要有两个用途:
1)用于内部网或网络服务供应商自动分配 IP 地址;
2)给用户用于内部网管理员作为对所有计算机作中央管理的手段。
DHCP分为服务器端和客户端,通常是客户端向服务端申请地址,嵌入式产品上运行的一般是DCHP客户端。
udhcpc是一个面向嵌入式系统的非常小的DHCP客户端,它通常由busybox支持。若文件系统内没有包含这个工具,需在busybox配置选项中开启,并重新编译busybox固件。udhcpc的典型用法举例:
udhcpc -i eth0 -s /etc/udhcpc.script -b
其中,
-i 是指定网卡,我这里只有一个eth0,有多个网卡时需要注意区分;
-s 是指定发生dhcp事件时运行的脚本,默认是/usr/share/udhcpc/default.script这个路径,我这里是将/etc/udhcpc.script软链到了默认路径。
-b 是指定切换到后台指令。
这里运行udhcpc的结果仅仅是从服务端拿到了合法的IP地址而已,还需要将IP、网关、DNS等写入网卡,才能正常使用网络。而这些动作全都由/usr/share/udhcpc/default.script这个脚本实现。这个脚本可以从\busybox-1.1.2\examples\udhcp下获取,将脚本simple.script重命名为default.script,放在开发板上的/usr/share/dhcpc/目录下。
下面是我的default.script,仅供参考:
- #!/bin/sh
-
- # udhcpc script edited by Tim Riker
-
- [ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1
-
- RESOLV_CONF="/etc/resolv.conf"
- [ -e $RESOLV_CONF ] || touch $RESOLV_CONF
- [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
- [ -n "$subnet" ] && NETMASK="netmask $subnet"
-
- case "$1" in
- deconfig)
- /sbin/ifconfig $interface up
- /sbin/ifconfig $interface 0.0.0.0
-
- # drop info from this interface
- # resolv.conf may be a symlink to /tmp/, so take care
- TMPFILE=$(mktemp)
- grep -vE "# $interface\$" $RESOLV_CONF > $TMPFILE
- cat $TMPFILE > $RESOLV_CONF
- rm -f $TMPFILE
-
- if [ -x /usr/sbin/avahi-autoipd ]; then
- /usr/sbin/avahi-autoipd -k $interface
- fi
- ;;
-
- leasefail|nak)
- if [ -x /usr/sbin/avahi-autoipd ]; then
- /usr/sbin/avahi-autoipd -wD $interface --no-chroot
- fi
- ;;
-
- renew|bound)
- if [ -x /usr/sbin/avahi-autoipd ]; then
- /usr/sbin/avahi-autoipd -k $interface
- fi
- /sbin/ifconfig $interface $ip $BROADCAST $NETMASK
-
- if [ -n "$router" ] ; then
- echo "deleting routers"
- while route del default gw 0.0.0.0 dev $interface 2> /dev/null; do
- :
- done
-
- for i in $router ; do
- route add default gw $i dev $interface
- done
- fi
-
- # drop info from this interface
- # resolv.conf may be a symlink to /tmp/, so take care
- TMPFILE=$(mktemp)
- grep -vE "# $interface\$" $RESOLV_CONF > $TMPFILE
- cat $TMPFILE > $RESOLV_CONF
- rm -f $TMPFILE
-
- # prefer rfc3359 domain search list (option 119) if available
- if [ -n "$search" ]; then
- search_list=$search
- elif [ -n "$domain" ]; then
- search_list=$domain
- fi
-
- [ -n "$search_list" ] &&
- echo "search $search_list # $interface" >> $RESOLV_CONF
-
- for i in $dns ; do
- echo adding dns $i
- echo "nameserver $i # $interface" >> $RESOLV_CONF
- done
- ;;
- esac
-
- HOOK_DIR="$0.d"
- for hook in "${HOOK_DIR}/"*; do
- [ -f "${hook}" -a -x "${hook}" ] || continue
- "${hook}" "${@}"
- done
-
- exit 0