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