dhcpcd-run-hooks 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. #!/bin/sh
  2. # dhcpcd client configuration script
  3. #
  4. # dhcpcd 6.11.5
  5. # Copyright (c) 2006-2016 Roy Marples
  6. # Compiled in features: INET IPv4LL INET6 DHCPv6 AUTH
  7. #
  8. # Fixed issues:
  9. # - remove logger in syslog func: https://github.com/rancher/os/issues/2684
  10. # Handy variables and functions for our hooks to use
  11. case "$reason" in
  12. ROUTERADVERT)
  13. ifsuffix=".ra";;
  14. INFORM6|BOUND6|RENEW6|REBIND6|REBOOT6|EXPIRE6|RELEASE6|STOP6)
  15. ifsuffix=".dhcp6";;
  16. IPV4LL)
  17. ifsuffix=".ipv4ll";;
  18. *)
  19. ifsuffix=".dhcp";;
  20. esac
  21. ifname="$interface$ifsuffix"
  22. from=from
  23. signature_base="# Generated by dhcpcd"
  24. signature="$signature_base $from $ifname"
  25. signature_base_end="# End of dhcpcd"
  26. signature_end="$signature_base_end $from $ifname"
  27. state_dir=/var/run/dhcpcd
  28. _detected_init=false
  29. : ${if_up:=false}
  30. : ${if_down:=false}
  31. : ${syslog_debug:=false}
  32. # Ensure that all arguments are unique
  33. uniqify()
  34. {
  35. local result= i=
  36. for i do
  37. case " $result " in
  38. *" $i "*);;
  39. *) result="$result $i";;
  40. esac
  41. done
  42. echo "${result# *}"
  43. }
  44. # List interface config files in a directory.
  45. # If dhcpcd is running as a single instance then it will have a list of
  46. # interfaces in the preferred order.
  47. # Otherwise we just use what we have.
  48. list_interfaces()
  49. {
  50. local i= x= ifaces=
  51. for i in $interface_order; do
  52. for x in "$1"/$i.*; do
  53. [ -f "$x" ] && ifaces="$ifaces${ifaces:+ }${x##*/}"
  54. done
  55. done
  56. for x in "$1"/*; do
  57. [ -f "$x" ] && ifaces="$ifaces${ifaces:+ }${x##*/}"
  58. done
  59. uniqify $ifaces
  60. }
  61. # Trim function
  62. trim()
  63. {
  64. local var="$*"
  65. var=${var#"${var%%[![:space:]]*}"}
  66. var=${var%"${var##*[![:space:]]}"}
  67. if [ -z "$var" ]; then
  68. # So it seems our shell doesn't support wctype(3) patterns
  69. # Fall back to sed
  70. var=$(echo "$*" | sed -e 's/^[[:space:]]*//;s/[[:space:]]*$//')
  71. fi
  72. printf %s "$var"
  73. }
  74. # We normally use sed to extract values using a key from a list of files
  75. # but sed may not always be available at the time.
  76. key_get_value()
  77. {
  78. local key="$1" value= x= line=
  79. shift
  80. if type sed >/dev/null 2>&1; then
  81. sed -n "s/^$key//p" $@
  82. else
  83. for x do
  84. while read line; do
  85. case "$line" in
  86. "$key"*) echo "${line##$key}";;
  87. esac
  88. done < "$x"
  89. done
  90. fi
  91. }
  92. # We normally use sed to remove markers from a configuration file
  93. # but sed may not always be available at the time.
  94. remove_markers()
  95. {
  96. local m1="$1" m2="$2" x= line= in_marker=0
  97. shift; shift
  98. if type sed >/dev/null 2>&1; then
  99. sed "/^$m1/,/^$m2/d" $@
  100. else
  101. for x do
  102. while read line; do
  103. case "$line" in
  104. "$m1"*) in_marker=1;;
  105. "$m2"*) in_marker=0;;
  106. *) [ $in_marker = 0 ] && echo "$line";;
  107. esac
  108. done < "$x"
  109. done
  110. fi
  111. }
  112. # Compare two files.
  113. comp_file()
  114. {
  115. [ -e "$1" -a -e "$2" ] || return 1
  116. if type cmp >/dev/null 2>&1; then
  117. cmp -s "$1" "$2"
  118. elif type diff >/dev/null 2>&1; then
  119. diff -q "$1" "$2" >/dev/null
  120. else
  121. # Hopefully we're only working on small text files ...
  122. [ "$(cat "$1")" = "$(cat "$2")" ]
  123. fi
  124. }
  125. # Compare two files.
  126. # If different, replace first with second otherwise remove second.
  127. change_file()
  128. {
  129. if [ -e "$1" ]; then
  130. if comp_file "$1" "$2"; then
  131. rm -f "$2"
  132. return 1
  133. fi
  134. fi
  135. cat "$2" > "$1"
  136. rm -f "$2"
  137. return 0
  138. }
  139. # Compare two files.
  140. # If different, copy or link depending on target type
  141. copy_file()
  142. {
  143. if [ -h "$2" ]; then
  144. [ "$(readlink "$2")" = "$1" ] && return 1
  145. ln -sf "$1" "$2"
  146. else
  147. comp_file "$1" "$2" && return 1
  148. cat "$1" >"$2"
  149. fi
  150. }
  151. # Save a config file
  152. save_conf()
  153. {
  154. if [ -f "$1" ]; then
  155. rm -f "$1-pre.$interface"
  156. cat "$1" > "$1-pre.$interface"
  157. fi
  158. }
  159. # Restore a config file
  160. restore_conf()
  161. {
  162. [ -f "$1-pre.$interface" ] || return 1
  163. cat "$1-pre.$interface" > "$1"
  164. rm -f "$1-pre.$interface"
  165. }
  166. # Write a syslog entry
  167. syslog()
  168. {
  169. local lvl="$1"
  170. if [ "$lvl" = debug ]; then
  171. ${syslog_debug} || return 0
  172. fi
  173. [ -n "$lvl" ] && shift
  174. [ -n "$*" ] || return 0
  175. case "$lvl" in
  176. err|error) echo "$interface: $*" >&2;;
  177. *) echo "$interface: $*";;
  178. esac
  179. }
  180. # Check for a valid domain name as per RFC1123 with the exception of
  181. # allowing - and _ as they seem to be widely used.
  182. valid_domainname()
  183. {
  184. local name="$1" label
  185. [ -z "$name" -o ${#name} -gt 255 ] && return 1
  186. while [ -n "$name" ]; do
  187. label="${name%%.*}"
  188. [ -z "$label" -o ${#label} -gt 63 ] && return 1
  189. case "$label" in
  190. -*|_*|*-|*_) return 1;;
  191. # some sh require - as the first or last character in the class
  192. # when matching it
  193. *[![:alnum:]_-]*) return 1;;
  194. esac
  195. [ "$name" = "${name#*.}" ] && break
  196. name="${name#*.}"
  197. done
  198. return 0
  199. }
  200. valid_domainname_list()
  201. {
  202. local name
  203. for name do
  204. valid_domainname "$name" || return $?
  205. done
  206. return 0
  207. }
  208. # Check for a valid path
  209. valid_path()
  210. {
  211. case "$@" in
  212. *[![:alnum:]#%+-_:\.,@~\\/\[\]=\ ]*) return 1;;
  213. esac
  214. return 0
  215. }
  216. # With the advent of alternative init systems, it's possible to have
  217. # more than one installed. So we need to try and guess what one we're
  218. # using unless overriden by configure.
  219. detect_init()
  220. {
  221. _service_exists=""
  222. _service_cmd=""
  223. _service_status=""
  224. [ -n "$_service_cmd" ] && return 0
  225. if ${_detected_init}; then
  226. [ -n "$_service_cmd" ]
  227. return $?
  228. fi
  229. # Detect the running init system.
  230. # As systemd and OpenRC can be installed on top of legacy init
  231. # systems we try to detect them first.
  232. local status=""
  233. : ${status:=status}
  234. if [ -x /bin/systemctl -a -S /run/systemd/private ]; then
  235. _service_exists="/bin/systemctl --quiet is-enabled \$1.service"
  236. _service_status="/bin/systemctl --quiet is-active \$1.service"
  237. _service_cmd="/bin/systemctl \$2 \$1.service"
  238. elif [ -x /usr/bin/systemctl -a -S /run/systemd/private ]; then
  239. _service_exists="/usr/bin/systemctl --quiet is-enabled \$1.service"
  240. _service_status="/usr/bin/systemctl --quiet is-active \$1.service"
  241. _service_cmd="/usr/bin/systemctl \$2 \$1.service"
  242. elif [ -x /sbin/rc-service -a \
  243. -s /libexec/rc/init.d/softlevel -o -s /run/openrc/softlevel ]
  244. then
  245. _service_exists="/sbin/rc-service -e \$1"
  246. _service_cmd="/sbin/rc-service \$1 -- -D \$2"
  247. elif [ -x /usr/sbin/invoke-rc.d ]; then
  248. _service_exists="/usr/sbin/invoke-rc.d --query --quiet \$1 start >/dev/null 2>&1 || [ \$? = 104 ]"
  249. _service_cmd="/usr/sbin/invoke-rc.d \$1 \$2"
  250. elif [ -x /sbin/service ]; then
  251. _service_exists="/sbin/service \$1 >/dev/null 2>&1"
  252. _service_cmd="/sbin/service \$1 \$2"
  253. elif [ -x /usr/sbin/service ]; then
  254. _service_exists="/usr/sbin/service \$1 $status >/dev/null 2>&1"
  255. _service_cmd="/usr/sbin/service \$1 \$2"
  256. elif [ -x /bin/sv ]; then
  257. _service_exists="/bin/sv status \1 >/dev/null 2>&1"
  258. _service_cmd="/bin/sv \$1 \$2"
  259. elif [ -x /usr/bin/sv ]; then
  260. _service_exists="/usr/bin/sv status \1 >/dev/null 2>&1"
  261. _service_cmd="/usr/bin/sv \$1 \$2"
  262. elif [ -e /etc/slackware-version -a -d /etc/rc.d ]; then
  263. _service_exists="[ -x /etc/rc.d/rc.\$1 ]"
  264. _service_cmd="/etc/rc.d/rc.\$1 \$2"
  265. _service_status="/etc/rc.d/rc.\$1 status >/dev/null 2>&1"
  266. else
  267. for x in /etc/init.d/rc.d /etc/rc.d /etc/init.d; do
  268. if [ -d $x ]; then
  269. _service_exists="[ -x $x/\$1 ]"
  270. _service_cmd="$x/\$1 \$2"
  271. _service_status="$x/\$1 $status >/dev/null 2>&1"
  272. break
  273. fi
  274. done
  275. if [ -e /etc/arch-release ]; then
  276. _service_status="[ -e /var/run/daemons/\$1 ]"
  277. elif [ "$x" = "/etc/rc.d" -a -e /etc/rc.d/rc.subr ]; then
  278. _service_status="$x/\$1 check >/dev/null 2>&1"
  279. fi
  280. fi
  281. _detected_init=true
  282. if [ -z "$_service_cmd" ]; then
  283. syslog err "could not detect a useable init system"
  284. return 1
  285. fi
  286. return 0
  287. }
  288. # Check a system service exists
  289. service_exists()
  290. {
  291. if [ -z "$_service_exists" ]; then
  292. detect_init || return 1
  293. fi
  294. eval $_service_exists
  295. }
  296. # Send a command to a system service
  297. service_cmd()
  298. {
  299. if [ -z "$_service_cmd" ]; then
  300. detect_init || return 1
  301. fi
  302. eval $_service_cmd
  303. }
  304. # Send a command to a system service if it is running
  305. service_status()
  306. {
  307. if [ -z "$_service_cmd" ]; then
  308. detect_init || return 1
  309. fi
  310. if [ -n "$_service_status" ]; then
  311. eval $_service_status
  312. else
  313. service_command $1 status >/dev/null 2>&1
  314. fi
  315. }
  316. # Handy macros for our hooks
  317. service_command()
  318. {
  319. service_exists $1 && service_cmd $1 $2
  320. }
  321. service_condcommand()
  322. {
  323. service_exists $1 && service_status $1 && service_cmd $1 $2
  324. }
  325. # We source each script into this one so that scripts run earlier can
  326. # remove variables from the environment so later scripts don't see them.
  327. # Thus, the user can create their dhcpcd.enter/exit-hook script to configure
  328. # /etc/resolv.conf how they want and stop the system scripts ever updating it.
  329. for hook in \
  330. /etc/dhcpcd.enter-hook \
  331. /lib/dhcpcd/dhcpcd-hooks/* \
  332. /etc/dhcpcd.exit-hook
  333. do
  334. for skip in $skip_hooks; do
  335. case "$hook" in
  336. */*~) continue 2;;
  337. */"$skip") continue 2;;
  338. */[0-9][0-9]"-$skip") continue 2;;
  339. */[0-9][0-9]"-$skip.sh") continue 2;;
  340. esac
  341. done
  342. if [ -f "$hook" ]; then
  343. . "$hook"
  344. fi
  345. done