| #!/bin/sh |
| # dhcpcd client configuration script |
| |
| # Handy variables and functions for our hooks to use |
| if [ "$reason" = ROUTERADVERT ]; then |
| ifsuffix=":ra" |
| else |
| ifsuffix= |
| fi |
| ifname="$interface$ifsuffix" |
| |
| from=from |
| signature_base="# Generated by dhcpcd" |
| signature="$signature_base $from $ifname" |
| signature_base_end="# End of dhcpcd" |
| signature_end="$signature_base_end $from $ifname" |
| state_dir=/var/run/dhcpcd |
| |
| # Ensure that all arguments are unique |
| uniqify() |
| { |
| local result= i= |
| for i do |
| case " $result " in |
| *" $i "*);; |
| *) result="$result $i";; |
| esac |
| done |
| echo "${result# *}" |
| } |
| |
| # List interface config files in a directory. |
| # If dhcpcd is running as a single instance then it will have a list of |
| # interfaces in the preferred order. |
| # Otherwise we just use what we have. |
| list_interfaces() |
| { |
| local i= x= ifaces= |
| for i in $interface_order; do |
| [ -e "$1/$i" ] && ifaces="$ifaces${ifaces:+ }$i" |
| done |
| for x in "$1"/*; do |
| [ -e "$x" ] || continue |
| for i in $interface_order; do |
| if [ $i = "${x##*/}" ]; then |
| unset x |
| break |
| fi |
| done |
| [ -n "$x" ] && ifaces="$ifaces${ifaces:+ }${x##*/}" |
| done |
| echo "$ifaces" |
| } |
| |
| # We normally use sed to extract values using a key from a list of files |
| # but sed may not always be available at the time. |
| key_get_value() |
| { |
| local key="$1" value= x= line= |
| |
| shift |
| if type sed >/dev/null 2>&1; then |
| sed -n "s/^$key//p" $@ |
| else |
| for x do |
| while read line; do |
| case "$line" in |
| "$key"*) echo "${line##$key}";; |
| esac |
| done < "$x" |
| done |
| fi |
| } |
| |
| # We normally use sed to remove markers from a configuration file |
| # but sed may not always be available at the time. |
| remove_markers() |
| { |
| local m1="$1" m2="$2" x= line= in_marker=0 |
| |
| shift; shift |
| if type sed >/dev/null 2>&1; then |
| sed "/^$m1/,/^$m2/d" $@ |
| else |
| for x do |
| while read line; do |
| case "$line" in |
| "$m1"*) in_marker=1;; |
| "$m2"*) in_marker=0;; |
| *) [ $in_marker = 0 ] && echo "$line";; |
| esac |
| done < "$x" |
| done |
| fi |
| } |
| |
| # Compare two files. |
| # If different, replace first with second otherwise remove second. |
| change_file() |
| { |
| if [ -e "$1" ]; then |
| if type cmp >/dev/null 2>&1; then |
| cmp -s "$1" "$2" |
| elif type diff >/dev/null 2>&1; then |
| diff -q "$1" "$2" >/dev/null |
| else |
| # Hopefully we're only working on small text files ... |
| [ "$(cat "$1")" = "$(cat "$2")" ] |
| fi |
| if [ $? -eq 0 ]; then |
| rm -f "$2" |
| return 1 |
| fi |
| fi |
| cat "$2" > "$1" |
| rm -f "$2" |
| return 0 |
| } |
| |
| # Save a config file |
| save_conf() |
| { |
| if [ -f "$1" ]; then |
| rm -f "$1-pre.$interface" |
| cat "$1" > "$1-pre.$interface" |
| fi |
| } |
| |
| # Restore a config file |
| restore_conf() |
| { |
| [ -f "$1-pre.$interface" ] || return 1 |
| cat "$1-pre.$interface" > "$1" |
| rm -f "$1-pre.$interface" |
| } |
| |
| # Write a syslog entry |
| syslog() |
| { |
| local lvl="$1" |
| |
| [ -n "$lvl" ] && shift |
| if [ -n "$*" ]; then |
| if type logger >/dev/null 2>&1; then |
| logger -t dhcpcd -p daemon."$lvl" -is "$interface: $*" |
| fi |
| fi |
| } |
| |
| # Check for a valid domain name as per RFC1123 with the exception of |
| # allowing - and _ as they seem to be widely used. |
| valid_domainname() |
| { |
| local name="$1" label |
| |
| [ -z "$name" -o ${#name} -gt 255 ] && return 1 |
| |
| while [ -n "$name" ]; do |
| label="${name%%.*}" |
| [ -z "$label" -o ${#label} -gt 63 ] && return 1 |
| case "$label" in |
| -*|_*|*-|*_) return 1;; |
| *[![:alnum:]-_]*) return 1;; |
| esac |
| [ "$name" = "${name#*.}" ] && break |
| name="${name#*.}" |
| done |
| return 0 |
| } |
| |
| valid_domainname_list() |
| { |
| local name |
| |
| for name do |
| valid_domainname "$name" || return $? |
| done |
| return 0 |
| } |
| |
| # Check for a valid path |
| valid_path() |
| { |
| case "$@" in |
| *[![:alnum:]#%+-_:\.,@~\\/\[\]=\ ]*) return 1;; |
| esac |
| return 0 |
| } |
| |
| # Check a system service exists |
| service_exists() |
| { |
| @SERVICEEXISTS@ |
| } |
| |
| # Send a command to a system service |
| service_cmd() |
| { |
| @SERVICECMD@ |
| } |
| |
| # Send a command to a system service if it is running |
| service_status() |
| { |
| @SERVICESTATUS@ |
| } |
| |
| # Handy macros for our hooks |
| service_command() |
| { |
| service_exists $1 && service_cmd $1 $2 |
| } |
| service_condcommand() |
| { |
| service_exists $1 && service_status $1 && service_cmd $1 $2 |
| } |
| |
| # We source each script into this one so that scripts run earlier can |
| # remove variables from the environment so later scripts don't see them. |
| # Thus, the user can create their dhcpcd.enter/exit-hook script to configure |
| # /etc/resolv.conf how they want and stop the system scripts ever updating it. |
| for hook in \ |
| @SYSCONFDIR@/dhcpcd.enter-hook \ |
| @HOOKDIR@/* \ |
| @SYSCONFDIR@/dhcpcd.exit-hook |
| do |
| for skip in $skip_hooks; do |
| case "$hook" in |
| */"$skip") continue 2;; |
| */[0-9][0-9]"-$skip") continue 2;; |
| */[0-9][0-9]"-$skip.sh") continue 2;; |
| esac |
| done |
| if [ -f "$hook" ]; then |
| . "$hook" |
| fi |
| done |