#!/bin/sh # A simple wrapper around udhcpc so that we are able to dynamically specify # which options it should ask for. # note: ifupdown does not allow VERBOSITY through. can be set in OPTS_FILE. VERBOSITY="${VERBOSITY:-0}" . ${CIRROS_SHLIB:=/lib/cirros/shlib} || { echo "failed to read ${CIRROS_SHLIB}" 1>&2; exit 1; } set -f # ensure PATH has /sbin in it. path_has /sbin || PATH="$PATH:/sbin" OPTS_FILE="/etc/default/udhcpc" RESOLV_CONF="/etc/resolv.conf" apply_static_routes() { # routes are pairs of network and gateway # 169.254.169.254/32 10.65.0.128 local net="" router="" err=0 while [ $# -ne 0 ]; do net="$1" router="$2" [ -n "$net" ] || continue debug 1 "adding net $net with router $router" route add -net "$net" gw "$router" || { error "WARN: failed: route add -net \"$net\" gw \"$router\"" err=$(($err+1)); } shift 2 || { error "apply_static_routes: failed shift 2. odd number of args?" return 1; } done return $err } readconfig() { [ ! -f "$OPTS_FILE" ] || . "$OPTS_FILE" || { error "failed to read $OPTS_FILE"; return 1; } # these are expected to be set. OPTIONS=${OPTIONS:-staticroutes mtu} TIMEOUT=${TIMEOUT:-60} MTU=${MTU:-1500} } up() { [ $# -ge 1 ] || { error "$0 up: must provide interface"; return 1; } local iface="$1" opts="" hostname="" readconfig || return hostname=$(hostname 2>/dev/null) # Gather all options and start udhcpc. for opt in $OPTIONS; do opts="-O $opt $opts" done debug 1 "Starting udhcpc on $iface, asking for options {$OPTIONS}" udhcpc -p "/var/run/udhcpc.${iface}.pid" -R -n \ ${TIMEOUT:+-T "${TIMEOUT}"} -i "$iface" -s "$0" \ $opts ${hostname:+-x "hostname:${hostname}"} } down() { local iface="$1" pidfile="" pid="" [ $# -ge 1 ] || { error "$0 down: must provide interface"; return 1; } pidfile="/var/run/udhcpc.$iface.pid" [ -f "$pidfile" ] || { error "$iface: no pidfile"; return 1; } read pid < "$pidfile" || { error "failed to read pid from '$pidfile' for '$iface'"; return 1; } kill $pid >/dev/null return } renew_bound() { local flags="" mode="$1" i="" shift; [ -n "$interface" ] || { error "$0 $mode: 'interface' not provided"; return 1; } [ -n "$ip" ] || { error "$0 $mode: 'ip' not set in environment"; return 1; } readconfig || return [ -n "$broadcast" ] && flags="${flags}broadcast $broadcast " [ -n "$subnet" ] && flags="${flags}netmask $subnet " flags="${flags}mtu ${mtu:-${MTU}} " flags=${flags% } debug 1 "ifconfig $interface $ip $flags" ifconfig $interface $ip $flags || { error "$0 $mode: failed: 'ifconfig $interface $ip $flags'"; return 1; } if [ -n "$router" ] ; then local out="" ret="" debug 2 "deleting routers" while :; do out=$(route del default gw 0.0.0.0 dev $interface 2>&1) ret=$? [ $ret -eq 0 ] && break case "$out" in *SIOCDELRT*[Nn]o\ such\ process*) break;; esac error "deleting routes failed: $out" 1>&2 done for i in $router; do debug 1 "route add default gw $i dev $interface" route add default gw $i dev $interface done fi local msg="configuring $RESOLV_CONF for $interface. domain=$domain" msg="$msg nameservers: $dns" debug 1 "$msg" { [ -n "$domain" ] && echo "search $domain" for i in $dns ; do echo nameserver $i done } > "$RESOLV_CONF" apply_static_routes $staticroutes } case "$1" in up) shift up "$@" ;; down) shift; down "$@" ;; deconfig) ifconfig $interface 0.0.0.0 ;; renew|bound) renew_bound "$@"; ;; *) error "Usage: $0 " exit 1 ;; esac exit # vi: ts=4 noexpandtab syntax=sh