1#!/bin/sh
2# dhcpcd client configuration script 
3
4# Handy variables and functions for our hooks to use
5if [ "$reason" = ROUTERADVERT ]; then
6	ifsuffix=":ra"
7else
8	ifsuffix=
9fi
10ifname="$interface$ifsuffix"
11
12from=from
13signature_base="# Generated by dhcpcd"
14signature="$signature_base $from $ifname"
15signature_base_end="# End of dhcpcd"
16signature_end="$signature_base_end $from $ifname"
17state_dir=/var/run/dhcpcd
18
19# Ensure that all arguments are unique
20uniqify()
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.
36list_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.
57key_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.
77remove_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.
99change_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
121save_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
130restore_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
138syslog()
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.
152valid_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
171valid_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
182valid_path()
183{
184	case "$@" in
185	*[![:alnum:]#%+-_:\.,@~\\/\[\]=\ ]*) return 1;;
186	esac
187	return 0
188}
189
190# Check a system service exists 
191service_exists()
192{
193	@SERVICEEXISTS@
194}
195
196# Send a command to a system service
197service_cmd()
198{
199	@SERVICECMD@
200}
201
202# Send a command to a system service if it is running
203service_status()
204{
205	@SERVICESTATUS@
206}
207
208# Handy macros for our hooks
209service_command()
210{
211	service_exists $1 && service_cmd $1 $2
212}
213service_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.
222for hook in \
223	@SYSCONFDIR@/dhcpcd.enter-hook \
224	@HOOKDIR@/* \
225	@SYSCONFDIR@/dhcpcd.exit-hook
226do
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
237done
238