#!/bin/sh # This script expect a system with resolvconf (openresolv) and iproute2 [ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1 ACTION="$1" IP_CACHE="/var/lib/misc/${interface}.cache" RESOLV_CONF="/run/resolvconf/interfaces/${interface}.conf" NTPFILE="/run/chrony/dhcp-sources.d/${interface}.sources" NAME="/etc/frr/static.d/${interface}-dhcp.conf" NEXT="${NAME}+" [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" [ -n "$subnet" ] || subnet=32 [ -n "$metric" ] || metric=5 # Handle stateful DHCPv6 like DHCPv4 [ -n "$ipv6" ] && ip="$ipv6/128" if [ -z "${IF_WAIT_DELAY}" ]; then IF_WAIT_DELAY=10 fi log() { logger -I $$ -t udhcpc -p user.notice "$*" } wait_for_ipv6_default_route() { log "waiting for IPv6 default route to be installed." while [ $IF_WAIT_DELAY -gt 0 ]; do if ip -6 route list proto dhcp dev $interface | grep -q default; then return fi sleep 1 printf "." : $((IF_WAIT_DELAY -= 1)) done log "Timed out witing for IPv6 default route!" } # RFC3442: If the DHCP server returns both a Classless # Static Routes option and a Router option, the DHCP # client MUST ignore the Router option. set_dhcp_routes() { echo "! Generated by udhcpc" > "$NEXT" if [ -n "$staticroutes" ]; then # format: dest1/mask gw1 ... destn/mask gwn set -- $staticroutes while [ -n "$1" -a -n "$2" ]; do log "adding route $1 via $2 metric $metric tag 100" echo "ip route $1 $2 $metric tag 100" >> "$NEXT" shift 2 done elif [ -n "$router" ] ; then for i in $router ; do echo "ip route 0.0.0.0/0 $i $metric tag 100" >> "$NEXT" done fi # Reduce changes needed by comparing with previous route(s) cmp -s "$NAME" "$NEXT" && return mv "$NEXT" "$NAME" initctl -nbq restart staticd } clr_dhcp_routes() { log "deleting DHCP routes from $interface" [ -f "$NAME" ] || return rm "$NAME" initctl -nbq restart staticd } clr_dhcp_addresses() { addrs=$(ip -j addr show dev $interface \ | jq -c '.[0].addr_info[] | select(.family == "inet") | select(.protocol == "dhcp")') for addr in $addrs; do ip="$(echo "$addr" | jq -r '."local"')" prefix="$(echo "$addr" | jq -r '."prefixlen"')" log "removing $ip/$prefix from $interface" ip addr del "$ip/$prefix" dev "$interface" done } log "action $ACTION" case "$ACTION" in deconfig) clr_dhcp_addresses clr_dhcp_routes /bin/ip link set dev $interface up # drop info from this interface rm -f "$RESOLV_CONF" rm -f "$NTPFILE" if [ -x /usr/sbin/avahi-autoipd ]; then /usr/sbin/avahi-autoipd -c $interface && /usr/sbin/avahi-autoipd -k $interface fi ;; leasefail|nak) if [ -x /usr/sbin/avahi-autoipd ]; then /usr/sbin/avahi-autoipd -c $interface || /usr/sbin/avahi-autoipd -wD $interface --no-chroot fi ;; renew|bound) if [ -x /usr/sbin/avahi-autoipd ]; then /usr/sbin/avahi-autoipd -c $interface && /usr/sbin/avahi-autoipd -k $interface fi if /bin/ip addr add dev $interface $ip/$subnet $BROADCAST proto dhcp; then echo "$ip" > "$IP_CACHE" fi if [ -n "$ipv6" ] ; then wait_for_ipv6_default_route fi set_dhcp_routes # set hostname if given if [ -n "$hostname" ]; then log "setting new hostname: $hostname" hostname "$hostname" sed -i -E "s/^(127\.0\.1\.1\s+).*/\1$hostname/" /etc/hosts fi # drop info from this interface truncate -s 0 "$RESOLV_CONF" # prefer rfc3397 domain search list (option 119) if available if [ -n "$search" ]; then search_list=$search elif [ -n "$domain" ]; then search_list=$domain fi if [ -n "$search_list" ]; then log "adding search $search_list" echo "search $search_list # $interface" >> $RESOLV_CONF fi for i in $dns ; do log "adding dns $i" echo "nameserver $i # $interface" >> $RESOLV_CONF resolvconf -u done if [ -n "$ntpsrv" ]; then truncate -s 0 "$NTPFILE" for srv in $ntpsrv; do log "got NTP server $srv" echo "server $srv iburst" >> "$NTPFILE" done chronyc reload sources >/dev/null fi esac HOOK_DIR="$0.d" for hook in "${HOOK_DIR}/"*; do [ -f "${hook}" -a -x "${hook}" ] || continue "${hook}" "$ACTION" done exit 0