Source code pulled from OpenBSD for OpenNTPD. The place to contribute to this code is via the OpenBSD CVS tree.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

331 lines
9.3 KiB

  1. #!/bin/sh -
  2. #
  3. # $OpenBSD: netstart,v 1.202 2020/01/15 00:19:40 kn Exp $
  4. # Turn off Strict Bourne shell mode.
  5. set +o sh
  6. # Show usage of the netstart script and exit.
  7. usage() {
  8. print -u2 "usage: ${0##*/} [[-n] interface ...]"
  9. exit 1
  10. }
  11. # Echo file $1 to stdout. Skip comment lines and delete everything
  12. # after the first '#' from other lines. Strip leading and trailing
  13. # whitespace if IFS is set.
  14. # Usage: stripcom /path/to/file
  15. stripcom() {
  16. local _file=$1 _line
  17. [[ -f $_file ]] || return
  18. while read _line; do
  19. [[ -n ${_line%%#*} ]] && print -r -- "$_line"
  20. done <$_file
  21. }
  22. # Parse and "unpack" a hostname.if(5) line given as positional parameters.
  23. # Fill the _cmds array with the resulting interface configuration commands.
  24. parse_hn_line() {
  25. local _af=0 _name=1 _mask=2 _bc=3 _prefix=2 _c _cmd _prev _daddr
  26. set -A _c -- "$@"
  27. set -o noglob
  28. case ${_c[_af]} in
  29. ''|*([[:blank:]])'#'*)
  30. return
  31. ;;
  32. inet) ((${#_c[*]} > 1)) || return
  33. [[ ${_c[_name]} == alias ]] && _mask=3 _bc=4
  34. [[ -n ${_c[_mask]} ]] && _c[_mask]="netmask ${_c[_mask]}"
  35. if [[ -n ${_c[_bc]} ]]; then
  36. _c[_bc]="broadcast ${_c[_bc]}"
  37. [[ ${_c[_bc]} == *NONE ]] && _c[_bc]=
  38. fi
  39. _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}"
  40. ;;
  41. inet6) ((${#_c[*]} > 1)) || return
  42. if [[ ${_c[_name]} == autoconf ]]; then
  43. _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}"
  44. V6_AUTOCONF=true
  45. return
  46. fi
  47. [[ ${_c[_name]} == alias ]] && _prefix=3
  48. [[ -n ${_c[_prefix]} ]] && _c[_prefix]="prefixlen ${_c[_prefix]}"
  49. _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}"
  50. ;;
  51. dest) ((${#_c[*]} == 2)) && _daddr=${_c[1]} || return
  52. _prev=$((${#_cmds[*]} - 1))
  53. ((_prev >= 0)) || return
  54. set -A _c -- ${_cmds[_prev]}
  55. _name=3
  56. [[ ${_c[_name]} == alias ]] && _name=4
  57. _c[_name]="${_c[_name]} $_daddr"
  58. _cmds[$_prev]="${_c[@]}"
  59. ;;
  60. dhcp) _c[0]=
  61. _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]} up;dhclient $_if"
  62. V4_DHCPCONF=true
  63. ;;
  64. '!'*) _cmd=$(print -- "${_c[@]}" | sed 's/\$if/'$_if'/g')
  65. _cmds[${#_cmds[*]}]="${_cmd#!}"
  66. ;;
  67. *) _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}"
  68. ;;
  69. esac
  70. unset _c
  71. set +o noglob
  72. }
  73. # Create interface $1 if it does not yet exist.
  74. # Usage: ifcreate if1
  75. ifcreate() {
  76. local _if=$1
  77. { ifconfig $_if || ifconfig $_if create; } >/dev/null 2>&1
  78. }
  79. # Create interfaces for network pseudo-devices referred to by hostname.if files.
  80. # Usage: vifscreate
  81. vifscreate() {
  82. local _vif _hn _if
  83. for _vif in $(ifconfig -C); do
  84. for _hn in /etc/hostname.${_vif}+([[:digit:]]); do
  85. [[ -f $_hn ]] || continue
  86. _if=${_hn#/etc/hostname.}
  87. if ! ifcreate $_if; then
  88. print -u2 "${0##*/}: create for '$_if' failed."
  89. fi
  90. done
  91. done
  92. }
  93. # Start a single interface.
  94. # Usage: ifstart if1
  95. ifstart() {
  96. local _if=$1 _hn=/etc/hostname.$1 _cmds _i=0 _line _stat
  97. set -A _cmds
  98. # Interface names must be alphanumeric only. We check to avoid
  99. # configuring backup or temp files, and to catch the "*" case.
  100. [[ $_if != +([[:alpha:]])+([[:digit:]]) ]] && return
  101. if [[ ! -f $_hn ]]; then
  102. print -u2 "${0##*/}: $_hn: No such file or directory."
  103. return
  104. fi
  105. # Not using stat(1), we can't rely on having /usr yet.
  106. set -A _stat -- $(ls -nL $_hn)
  107. if [[ "${_stat[0]}${_stat[2]}${_stat[3]}" != *---00 ]]; then
  108. print -u2 "WARNING: $_hn is insecure, fixing permissions."
  109. chmod -LR o-rwx $_hn
  110. chown -LR root:wheel $_hn
  111. fi
  112. # Check for ifconfig'able interface, except if -n option is specified.
  113. if ! $PRINT_ONLY; then
  114. ifcreate $_if || return
  115. fi
  116. # Parse the hostname.if(5) file and fill _cmds array with interface
  117. # configuration commands.
  118. set -o noglob
  119. while IFS= read -- _line; do
  120. parse_hn_line $_line
  121. done <$_hn
  122. # Apply the interface configuration commands stored in _cmds array.
  123. while ((_i < ${#_cmds[*]})); do
  124. if $PRINT_ONLY; then
  125. print -r -- "${_cmds[_i]}"
  126. else
  127. eval "${_cmds[_i]}"
  128. fi
  129. ((_i++))
  130. done
  131. unset _cmds
  132. set +o noglob
  133. }
  134. # Start multiple interfaces by driver name.
  135. # Usage: ifmstart "em iwm" "trunk vlan"
  136. # Start "$1" interfaces in order or all interfaces if empty.
  137. # Don't start "$2" interfaces. "$2" is optional.
  138. ifmstart() {
  139. local _sifs=$1 _xifs=$2 _hn _if _sif _xif
  140. for _sif in ${_sifs:-ALL}; do
  141. for _hn in /etc/hostname.+([[:alpha:]])+([[:digit:]]); do
  142. [[ -f $_hn ]] || continue
  143. _if=${_hn#/etc/hostname.}
  144. # Skip unwanted ifs.
  145. for _xif in $_xifs; do
  146. [[ $_xif == ${_if%%[0-9]*} ]] && continue 2
  147. done
  148. # Start wanted ifs.
  149. [[ $_sif == @(ALL|${_if%%[0-9]*}) ]] && ifstart $_if
  150. done
  151. done
  152. }
  153. # Parse /etc/mygate and add default routes for IPv4 and IPv6.
  154. # Usage: defaultroute
  155. defaultroute() {
  156. local _cmd;
  157. ! $V4_DHCPCONF && stripcom /etc/mygate |
  158. while read gw; do
  159. [[ $gw == @(*:*) ]] && continue
  160. _cmd="route -qn add -host default $gw"
  161. if $PRINT_ONLY; then
  162. print -r -- "$_cmd" && break
  163. else
  164. $_cmd && break
  165. fi
  166. done
  167. ! $V6_AUTOCONF && stripcom /etc/mygate |
  168. while read gw; do
  169. [[ $gw == !(*:*) ]] && continue
  170. _cmd="route -qn add -host -inet6 default $gw"
  171. if $PRINT_ONLY; then
  172. print -r -- "$_cmd" && break
  173. else
  174. $_cmd && break
  175. fi
  176. done
  177. }
  178. # Make sure the invoking user has the right privileges. Check for presence of
  179. # id(1) to avoid problems with diskless setups.
  180. if [[ -x /usr/bin/id ]] && (($(id -u) != 0)); then
  181. echo "${0##*/}: need root privileges"
  182. exit 1
  183. fi
  184. # Get network related vars from rc.conf using the parsing routine from rc.subr.
  185. FUNCS_ONLY=1 . /etc/rc.d/rc.subr
  186. _rc_parse_conf
  187. PRINT_ONLY=false
  188. V4_DHCPCONF=false
  189. V6_AUTOCONF=false
  190. while getopts ":n" opt; do
  191. case $opt in
  192. n) PRINT_ONLY=true;;
  193. *) usage;;
  194. esac
  195. done
  196. shift $((OPTIND-1))
  197. # Option -n is only supported if interface names are specified as parameters.
  198. $PRINT_ONLY && (($# == 0)) && usage
  199. # Load key material for the generation of IPv6 Semantically Opaque Interface
  200. # Identifiers (SOII) used for link local and SLAAC addresses.
  201. $PRINT_ONLY || [[ ! -f /etc/soii.key ]] ||
  202. sysctl -q "net.inet6.ip6.soiikey=$(</etc/soii.key)"
  203. # If we were invoked with a list of interface names, just reconfigure these
  204. # interfaces (or bridges), add default routes and return.
  205. if (($# > 0)); then
  206. for _if; do ifstart $_if; done
  207. defaultroute
  208. return
  209. fi
  210. # Otherwise, process with the complete network initialization.
  211. # /etc/myname contains my symbolic name.
  212. [[ -f /etc/myname ]] && hostname "$(stripcom /etc/myname)"
  213. # Set the address for the loopback interface. Bringing the interface up,
  214. # automatically invokes the IPv6 address ::1.
  215. ifconfig lo0 inet 127.0.0.1/8
  216. # IPv6 configuration.
  217. if ifconfig lo0 inet6 >/dev/null 2>&1; then
  218. ip6kernel=YES
  219. # Disallow link-local unicast dest without outgoing scope identifiers.
  220. route -qn add -inet6 fe80:: -prefixlen 10 ::1 -reject
  221. # Disallow site-local unicast dest without outgoing scope identifiers.
  222. # If you configure site-locals without scope id (it is permissible
  223. # config for routers that are not on scope boundary), you may want
  224. # to comment the line out.
  225. route -qn add -inet6 fec0:: -prefixlen 10 ::1 -reject
  226. # Disallow "internal" addresses to appear on the wire.
  227. route -qn add -inet6 ::ffff:0.0.0.0 -prefixlen 96 ::1 -reject
  228. # Disallow packets to malicious 6to4 prefix.
  229. route -qn add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
  230. route -qn add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
  231. route -qn add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
  232. route -qn add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
  233. # Disallow packets without scope identifier.
  234. route -qn add -inet6 ff01:: -prefixlen 16 ::1 -reject
  235. route -qn add -inet6 ff02:: -prefixlen 16 ::1 -reject
  236. # Completely disallow packets to IPv4 compatible prefix.
  237. #
  238. # This may conflict with RFC1933 under following circumstances:
  239. # (1) An IPv6-only KAME node tries to originate packets to IPv4
  240. # compatible destination. The KAME node has no IPv4 compatible
  241. # support. Under RFC1933, it should transmit native IPv6
  242. # packets toward IPv4 compatible destination, hoping it would
  243. # reach a router that forwards the packet toward auto-tunnel
  244. # interface.
  245. # (2) An IPv6-only node originates a packet to an IPv4 compatible
  246. # destination. A KAME node is acting as an IPv6 router, and
  247. # asked to forward it.
  248. #
  249. # Due to rare use of IPv4 compatible addresses, and security issues
  250. # with it, we disable it by default.
  251. route -qn add -inet6 ::0.0.0.0 -prefixlen 96 ::1 -reject
  252. else
  253. ip6kernel=NO
  254. fi
  255. # Create all the pseudo interfaces up front.
  256. vifscreate
  257. # Configure all the non-loopback interfaces which we know about, but
  258. # do not start interfaces which must be delayed. Refer to hostname.if(5)
  259. ifmstart "" "aggr trunk svlan vlan carp pppoe tun tap gif etherip gre egre mobileip pflow"
  260. # The aggr and trunk interfaces need to come up first in this list.
  261. # The (s)vlan interfaces need to come up after trunk.
  262. # Configure all the carp interfaces which we know about before default route.
  263. ifmstart "aggr trunk svlan vlan carp pppoe"
  264. # Set default routes for IPv4 and IPv6.
  265. defaultroute
  266. # Multicast routing.
  267. if [[ $multicast != YES ]]; then
  268. route -qn delete 224.0.0.0/4 >/dev/null 2>&1
  269. route -qn add -net 224.0.0.0/4 -interface 127.0.0.1 -reject >/dev/null
  270. fi
  271. # Reject 127/8 other than 127.0.0.1.
  272. route -qn add -net 127 127.0.0.1 -reject >/dev/null
  273. # Configure interfaces that rely on routing
  274. ifmstart "tun tap gif etherip gre egre mobileip pflow"
  275. if [[ $ip6kernel == YES ]]; then
  276. # Ensure IPv6 Duplicate Address Detection (DAD) is completed.
  277. count=0
  278. while ((count++ < 10 && $(sysctl -n net.inet6.ip6.dad_pending) != 0)); do
  279. sleep 1
  280. done
  281. fi