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.

330 lines
9.2 KiB

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