Home | History | Annotate | Download | only in dhcpcd
      1 #!/bin/sh
      2 # dhcpcd client configuration script 
      3 
      4 # Handy variables and functions for our hooks to use
      5 if [ "$reason" = ROUTERADVERT ]; then
      6 	ifsuffix=":ra"
      7 else
      8 	ifsuffix=
      9 fi
     10 ifname="$interface$ifsuffix"
     11 
     12 from=from
     13 signature_base="# Generated by dhcpcd"
     14 signature="$signature_base $from $ifname"
     15 signature_base_end="# End of dhcpcd"
     16 signature_end="$signature_base_end $from $ifname"
     17 state_dir=/var/run/dhcpcd
     18 
     19 # Ensure that all arguments are unique
     20 uniqify()
     21 {
     22 	local result= i=
     23 	for i do
     24 		case " $result " in
     25 			*" $i "*);;
     26 			*) result="$result $i";;
     27 		esac
     28 	done
     29 	echo "${result# *}"
     30 }
     31 
     32 # List interface config files in a directory.
     33 # If dhcpcd is running as a single instance then it will have a list of
     34 # interfaces in the preferred order.
     35 # Otherwise we just use what we have.
     36 list_interfaces()
     37 {
     38 	local i= x= ifaces=
     39 	for i in $interface_order; do
     40 		[ -e "$1/$i" ] && ifaces="$ifaces${ifaces:+ }$i"
     41 	done
     42 	for x in "$1"/*; do
     43 		[ -e "$x" ] || continue
     44 		for i in $interface_order; do
     45 			if [ $i = "${x##*/}" ]; then
     46 				unset x
     47 				break
     48 			fi
     49 		done
     50 		[ -n "$x" ] && ifaces="$ifaces${ifaces:+ }${x##*/}"
     51 	done
     52 	echo "$ifaces"
     53 }
     54 
     55 # We normally use sed to extract values using a key from a list of files
     56 # but sed may not always be available at the time.
     57 key_get_value()
     58 {
     59 	local key="$1" value= x= line=
     60 
     61 	shift
     62 	if type sed >/dev/null 2>&1; then
     63 		sed -n "s/^$key//p" $@
     64 	else
     65 		for x do
     66 			while read line; do
     67 				case "$line" in
     68 				"$key"*) echo "${line##$key}";;
     69 				esac
     70 			done < "$x"
     71 		done
     72 	fi
     73 }
     74 
     75 # We normally use sed to remove markers from a configuration file
     76 # but sed may not always be available at the time.
     77 remove_markers()
     78 {
     79 	local m1="$1" m2="$2" x= line= in_marker=0
     80 
     81 	shift; shift
     82 	if type sed >/dev/null 2>&1; then
     83 		sed "/^$m1/,/^$m2/d" $@
     84 	else
     85 		for x do
     86 			while read line; do
     87 				case "$line" in
     88 				"$m1"*) in_marker=1;;
     89 				"$m2"*) in_marker=0;;
     90 				*) [ $in_marker = 0 ] && echo "$line";;
     91 				esac
     92 			done < "$x"
     93 		done
     94 	fi
     95 }
     96 
     97 # Compare two files.
     98 # If different, replace first with second otherwise remove second.
     99 change_file()
    100 {
    101 	if [ -e "$1" ]; then
    102 		if type cmp >/dev/null 2>&1; then
    103 			cmp -s "$1" "$2"
    104 		elif type diff >/dev/null 2>&1; then
    105 			diff -q "$1" "$2" >/dev/null
    106 		else
    107 			# Hopefully we're only working on small text files ...
    108 			[ "$(cat "$1")" = "$(cat "$2")" ]
    109 		fi
    110 		if [ $? -eq 0 ]; then
    111 			rm -f "$2"
    112 			return 1
    113 		fi
    114 	fi
    115 	cat "$2" > "$1"
    116 	rm -f "$2"
    117 	return 0
    118 }
    119 
    120 # Save a config file
    121 save_conf()
    122 {
    123 	if [ -f "$1" ]; then
    124 		rm -f "$1-pre.$interface"
    125 		cat "$1" > "$1-pre.$interface"
    126 	fi
    127 }
    128 
    129 # Restore a config file
    130 restore_conf()
    131 {
    132 	[ -f "$1-pre.$interface" ] || return 1
    133 	cat "$1-pre.$interface" > "$1"
    134 	rm -f "$1-pre.$interface"
    135 }
    136 
    137 # Write a syslog entry
    138 syslog()
    139 {
    140 	local lvl="$1"
    141 
    142 	[ -n "$lvl" ] && shift
    143 	if [ -n "$*" ]; then
    144 		if type logger >/dev/null 2>&1; then
    145 			logger -t dhcpcd -p daemon."$lvl" -is "$interface: $*"
    146 		fi
    147 	fi
    148 }
    149 
    150 # Check for a valid domain name as per RFC1123 with the exception of
    151 # allowing - and _ as they seem to be widely used.
    152 valid_domainname()
    153 {
    154 	local name="$1" label
    155 
    156 	[ -z "$name" -o ${#name} -gt 255 ] && return 1
    157 	
    158 	while [ -n "$name" ]; do
    159 		label="${name%%.*}"
    160 		[ -z "$label" -o ${#label} -gt 63 ] && return 1
    161 		case "$label" in
    162 		-*|_*|*-|*_)		return 1;;
    163 		*[![:alnum:]-_]*)	return 1;;
    164 		esac
    165 		[ "$name" = "${name#*.}" ] && break
    166 		name="${name#*.}"
    167 	done
    168 	return 0	
    169 }
    170 
    171 valid_domainname_list()
    172 {
    173 	local name
    174 
    175 	for name do
    176 		valid_domainname "$name" || return $?
    177 	done
    178 	return 0
    179 }
    180 
    181 # Check for a valid path
    182 valid_path()
    183 {
    184 	case "$@" in
    185 	*[![:alnum:]#%+-_:\.,@~\\/\[\]=\ ]*) return 1;;
    186 	esac
    187 	return 0
    188 }
    189 
    190 # Check a system service exists 
    191 service_exists()
    192 {
    193 	@SERVICEEXISTS@
    194 }
    195 
    196 # Send a command to a system service
    197 service_cmd()
    198 {
    199 	@SERVICECMD@
    200 }
    201 
    202 # Send a command to a system service if it is running
    203 service_status()
    204 {
    205 	@SERVICESTATUS@
    206 }
    207 
    208 # Handy macros for our hooks
    209 service_command()
    210 {
    211 	service_exists $1 && service_cmd $1 $2
    212 }
    213 service_condcommand()
    214 {
    215 	service_exists $1 && service_status $1 && service_cmd $1 $2
    216 }
    217 
    218 # We source each script into this one so that scripts run earlier can
    219 # remove variables from the environment so later scripts don't see them.
    220 # Thus, the user can create their dhcpcd.enter/exit-hook script to configure
    221 # /etc/resolv.conf how they want and stop the system scripts ever updating it.
    222 for hook in \
    223 	@SYSCONFDIR@/dhcpcd.enter-hook \
    224 	@HOOKDIR@/* \
    225 	@SYSCONFDIR@/dhcpcd.exit-hook
    226 do
    227 	for skip in $skip_hooks; do
    228 		case "$hook" in
    229 			*/"$skip")			continue 2;;
    230 			*/[0-9][0-9]"-$skip")		continue 2;;
    231 			*/[0-9][0-9]"-$skip.sh")	continue 2;;
    232 		esac
    233 	done
    234 	if [ -f "$hook" ]; then
    235 		. "$hook"
    236 	fi
    237 done
    238