xref: /openbsd/etc/netstart (revision 8222f376)
1df930be7Sderaadt#!/bin/sh -
2df930be7Sderaadt#
3*8222f376Srpe#	$OpenBSD: netstart,v 1.177 2017/04/24 20:31:48 rpe Exp $
45116749bSrpe
55116749bSrpe# Turn off Strict Bourne shell mode.
65116749bSrpeset +o sh
78fc5e153Smillert
8952fbff6Srpe# Echo file $1 to stdout. Skip comment lines and delete everything
9952fbff6Srpe# after the first '#' from other lines. Strip leading and trailing
10952fbff6Srpe# whitespace if IFS is set.
11e57a083bSrpe# Usage: stripcom /path/to/file
128fc5e153Smillertstripcom() {
13e57a083bSrpe	local _file=$1 _line
14e57a083bSrpe
15e57a083bSrpe	[[ -f $_file ]] || return
16e57a083bSrpe
17e57a083bSrpe	while read _line; do
18e57a083bSrpe		[[ -n ${_line%%#*} ]] && print -r -- "$_line"
19e57a083bSrpe	done <$_file
208fc5e153Smillert}
2104e0ac27Smillert
22*8222f376Srpe# Parse and "unpack" a hostname.if(5) line given as positional parameters.
23*8222f376Srpe# Fill the _cmds array with the resulting interface configuration commands.
24*8222f376Srpeparse_hn_line() {
25*8222f376Srpe	local _af=0 _name=1 _mask=2 _bc=3 _prefix=2 _c _cmd _prev _daddr
26*8222f376Srpe	set -A _c -- "$@"
27*8222f376Srpe	set -o noglob
28*8222f376Srpe
29*8222f376Srpe	case ${_c[_af]} in
30*8222f376Srpe	''|*([[:blank:]])'#'*)
31*8222f376Srpe		return
32*8222f376Srpe		;;
33*8222f376Srpe	inet)	((${#_c[*]} > 1)) || return
34*8222f376Srpe		[[ ${_c[_name]} == alias ]] && _mask=3 _bc=4
35*8222f376Srpe		[[ -n ${_c[_mask]} ]] && _c[_mask]="netmask ${_c[_mask]}"
36*8222f376Srpe		if [[ -n ${_c[_bc]} ]]; then
37*8222f376Srpe			_c[_bc]="broadcast ${_c[_bc]}"
38*8222f376Srpe			[[ ${_c[_bc]} == *NONE ]] && _c[_bc]=
39*8222f376Srpe		fi
40*8222f376Srpe		_cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}"
41*8222f376Srpe		;;
42*8222f376Srpe	inet6)	((${#_c[*]} > 1)) || return
43*8222f376Srpe		if [[ ${_c[_name]} == autoconf ]]; then
44*8222f376Srpe			_cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}"
45*8222f376Srpe			rtsolif="$rtsolif $_if"
46*8222f376Srpe			return
47*8222f376Srpe		fi
48*8222f376Srpe		[[ ${_c[_name]} == alias ]] && _prefix=3
49*8222f376Srpe		[[ -n ${_c[_prefix]} ]] && _c[_prefix]="prefixlen ${_c[_prefix]}"
50*8222f376Srpe		_cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}"
51*8222f376Srpe		;;
52*8222f376Srpe	dest)	((${#_c[*]} == 2)) && _daddr=${_c[1]} || return
53*8222f376Srpe		_prev=$((${#_cmds[*]} - 1))
54*8222f376Srpe		((_prev >= 0)) || return
55*8222f376Srpe		set -A _c -- ${_cmds[_prev]}
56*8222f376Srpe		_name=3
57*8222f376Srpe		[[ ${_c[_name]} == alias ]] && _name=4
58*8222f376Srpe		_c[_name]="${_c[_name]} $_daddr"
59*8222f376Srpe		_cmds[$_prev]="${_c[@]}"
60*8222f376Srpe		;;
61*8222f376Srpe	dhcp)	_c[0]=
62*8222f376Srpe		_cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]} down;dhclient $_if"
63*8222f376Srpe		dhcpif="$dhcpif $_if"
64*8222f376Srpe		;;
65*8222f376Srpe	rtsol)	# XXX Support the rtsol keyword for some time to enable a smooth
66*8222f376Srpe		# XXX transition to autoconf.
67*8222f376Srpe		_c[0]=
68*8222f376Srpe		_cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]} up"
69*8222f376Srpe		_cmds[${#_cmds[*]}]="ifconfig $_if inet6 autoconf"
70*8222f376Srpe		rtsolif="$rtsolif $_if"
71*8222f376Srpe		;;
72*8222f376Srpe	'!'*)	_cmd=$(print -- "${_c[@]}" | sed 's/\$if/'$_if'/g')
73*8222f376Srpe		_cmds[${#_cmds[*]}]="${_cmd#!}"
74*8222f376Srpe		;;
75*8222f376Srpe	*)	_cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}"
76*8222f376Srpe		;;
77*8222f376Srpe	esac
78*8222f376Srpe	unset _c
79*8222f376Srpe}
80*8222f376Srpe
81e57a083bSrpe# Start a single interface.
82e57a083bSrpe# Usage: ifstart if1
83dfc209d0Smiodifstart() {
84*8222f376Srpe	local _if=$1 _file=$HN_DIR/hostname.$1 _cmds _i=0 _line _stat
85*8222f376Srpe	set -A _cmds
8624811c97Srpe
87dfc209d0Smiod	# Interface names must be alphanumeric only.  We check to avoid
88dfc209d0Smiod	# configuring backup or temp files, and to catch the "*" case.
89*8222f376Srpe	[[ $_if != +([[:alpha:]])+([[:digit:]]) ]] && return
90dfc209d0Smiod
917178fdf4Srpe	if [[ ! -f $_file ]]; then
927178fdf4Srpe		echo "netstart: $_file: No such file or directory"
9349352c7bStodd		return
9449352c7bStodd	fi
95*8222f376Srpe
96300d0407Srpe	# Not using stat(1), we can't rely on having /usr yet.
977178fdf4Srpe	set -A _stat -- $(ls -nL $_file)
987178fdf4Srpe	if [ "${_stat[0]#???????} ${_stat[2]} ${_stat[3]}" != "--- 0 0" ]; then
997178fdf4Srpe		echo "WARNING: $_file is insecure, fixing permissions"
1007178fdf4Srpe		chmod -LR o-rwx $_file
1017178fdf4Srpe		chown -LR root.wheel $_file
102bc53e65aSderaadt	fi
103dfc209d0Smiod
104*8222f376Srpe	# Check for ifconfig'able interface, except if -n option is specified.
105*8222f376Srpe	if ! $PRINT_ONLY; then
106*8222f376Srpe		(ifconfig $_if || ifconfig $_if create) >/dev/null 2>&1 ||
1072817040cStodd		return
1082817040cStodd	fi
109*8222f376Srpe
110*8222f376Srpe	# Parse the hostname.if(5) file and fill _cmds array with interface
111*8222f376Srpe	# configuration commands.
112*8222f376Srpe	set -o noglob
113*8222f376Srpe	while IFS= read -- _line; do
114*8222f376Srpe		parse_hn_line $_line
1157178fdf4Srpe	done <$_file
116*8222f376Srpe
117*8222f376Srpe	# Apply the interface configuration commands stored in _cmds array.
118*8222f376Srpe	while ((_i < ${#_cmds[*]})); do
119*8222f376Srpe		if $PRINT_ONLY; then
120*8222f376Srpe			print -r -- "${_cmds[_i]}"
121*8222f376Srpe		else
122*8222f376Srpe			eval "${_cmds[_i]}"
123*8222f376Srpe		fi
124*8222f376Srpe		((_i++))
125*8222f376Srpe	done
126*8222f376Srpe	unset _cmds
127dfc209d0Smiod}
128dfc209d0Smiod
129dde523b1Srpe# Start multiple interfaces by driver name.
130dde523b1Srpe# Usage: ifmstart "em iwm" "trunk vlan"
131300d0407Srpe#   Start "$1" interfaces in order or all interfaces if empty.
132dde523b1Srpe#   Don't start "$2" interfaces. "$2" is optional.
1339ac6b043Stoddifmstart() {
134dde523b1Srpe	local _sifs=$1 _xifs=$2 _hn _if _sif _xif
135dde523b1Srpe
136dde523b1Srpe	for _sif in ${_sifs:-ALL}; do
137dde523b1Srpe		for _hn in /etc/hostname.*; do
138dde523b1Srpe			_if=${_hn#/etc/hostname.}
139dde523b1Srpe			[[ $_if == '*' ]] && continue
1409ac6b043Stodd
141300d0407Srpe			# Skip unwanted ifs.
142dde523b1Srpe			for _xif in $_xifs; do
143dde523b1Srpe				[[ $_xif == ${_if%%[0-9]*} ]] && continue 2
1449ac6b043Stodd			done
1459ac6b043Stodd
146300d0407Srpe			# Start wanted ifs.
147dde523b1Srpe			[[ $_sif == @(ALL|${_if%%[0-9]*}) ]] && ifstart $_if
1489ac6b043Stodd		done
1499ac6b043Stodd	done
1509ac6b043Stodd}
1519ac6b043Stodd
15293230e63Srpe# IPv6 autoconf the interfaces in the $rtsolif list.
15393230e63Srpe# Usage: ifv6autoconf
15493230e63Srpeifv6autoconf() {
15593230e63Srpe	local _if
15693230e63Srpe
1576125fd66Ssthen	# $ip6kernel will not have been set if we were invoked with a
1586125fd66Ssthen	# list of interface names
15993230e63Srpe	ifconfig lo0 inet6 >/dev/null 2>&1 || return 0
16093230e63Srpe
16193230e63Srpe	for _if in $rtsolif; do
16293230e63Srpe		ifconfig $_if inet6 autoconf
1636125fd66Ssthen	done
1646125fd66Ssthen}
1656125fd66Ssthen
16605102370Smpi# Parse /etc/mygate and add default routes for IPv4 and IPv6
16705102370Smpi# Usage: defaultroute
16805102370Smpidefaultroute() {
16905102370Smpi	[[ -z $dhcpif ]] && stripcom /etc/mygate | while read gw; do
17005102370Smpi			[[ $gw == @(*:*) ]] && continue
17105102370Smpi			route -qn delete default >/dev/null 2>&1
17205102370Smpi			route -qn add -host default $gw && break
17305102370Smpi	done
17405102370Smpi	[[ -z $rtsolif ]] && stripcom /etc/mygate | while read gw; do
17505102370Smpi			[[ $gw == !(*:*) ]] && continue
17605102370Smpi			route -qn delete -inet6 default >/dev/null 2>&1
17705102370Smpi			route -qn add -host -inet6 default $gw && break
17805102370Smpi	done
17905102370Smpi}
18005102370Smpi
18102723c93Sjasper# Make sure the invoking user has the right privileges.
18202723c93Sjasperif (($(id -u) != 0)); then
18302723c93Sjasper	echo "${0##*/}: need root privileges"
18402723c93Sjasper	exit 1
18502723c93Sjasperfi
18602723c93Sjasper
187a035c1adSrpe# Get network related vars from rc.conf using the parsing routine from rc.subr.
188a035c1adSrpeFUNCS_ONLY=1 . /etc/rc.d/rc.subr
1898799e9c8Srobert_rc_parse_conf
1900dc37902Sangelos
191*8222f376SrpeHN_DIR=${HN_DIR:-/etc}
192*8222f376SrpePRINT_ONLY=false
193*8222f376SrpeUSAGE="USAGE: ${0##*/} [-n] [interface ...]"
194*8222f376Srpewhile getopts ":n" opt; do
195*8222f376Srpe	case $opt in
196*8222f376Srpe	n)	PRINT_ONLY=true;;
197*8222f376Srpe	*)	print -u2 "$USAGE"; exit 1;;
198*8222f376Srpe	esac
199*8222f376Srpedone
200*8222f376Srpeshift $((OPTIND-1))
201*8222f376Srpe
202*8222f376Srpe# Option -n is only supported if interface names are specified as parameters.
203*8222f376Srpeif $PRINT_ONLY && (($# == 0)); then
204*8222f376Srpe	print -u2 "Missing parameters.\n$USAGE"
205*8222f376Srpe	exit 1
206*8222f376Srpefi
207*8222f376Srpe
208dfc209d0Smiod# If we were invoked with a list of interface names, just reconfigure these
20905102370Smpi# interfaces (or bridges), add default routes and return.
2100a295e45Srpeif (($# > 0)); then
2110a295e45Srpe	for _if; do ifstart $_if; done
21293230e63Srpe	ifv6autoconf
21305102370Smpi	defaultroute
214dfc209d0Smiod	return
215dfc209d0Smiodfi
216dfc209d0Smiod
217dfc209d0Smiod# Otherwise, process with the complete network initialization.
218dfc209d0Smiod
219300d0407Srpe# /etc/myname contains my symbolic name.
2200a295e45Srpe[[ -f /etc/myname ]] && hostname "$(stripcom /etc/myname)"
22137bbdc83Shenning
2224fbd02fcSsobrado# Set the address for the loopback interface.  Bringing the interface up,
2234fbd02fcSsobrado# automatically invokes the IPv6 address ::1.
224d216f73bShenningifconfig lo0 inet 127.0.0.1/8
22598c28033Skstailey
2263d8fed7cSitojunif ifconfig lo0 inet6 >/dev/null 2>&1; then
2273d8fed7cSitojun	# IPv6 configurations.
2283d8fed7cSitojun	ip6kernel=YES
2293d8fed7cSitojun
230dfc209d0Smiod	# Disallow link-local unicast dest without outgoing scope identifiers.
23103056e2eSderaadt	route -qn add -inet6 fe80:: -prefixlen 10 ::1 -reject >/dev/null
23292aceabbSitojun
233dfc209d0Smiod	# Disallow site-local unicast dest without outgoing scope identifiers.
23492aceabbSitojun	# If you configure site-locals without scope id (it is permissible
23592aceabbSitojun	# config for routers that are not on scope boundary), you may want
23692aceabbSitojun	# to comment the line out.
23703056e2eSderaadt	route -qn add -inet6 fec0:: -prefixlen 10 ::1 -reject >/dev/null
23892aceabbSitojun
239dfc209d0Smiod	# Disallow "internal" addresses to appear on the wire.
24003056e2eSderaadt	route -qn add -inet6 ::ffff:0.0.0.0 -prefixlen 96 ::1 -reject >/dev/null
24192aceabbSitojun
242dfc209d0Smiod	# Disallow packets to malicious IPv4 compatible prefix.
24303056e2eSderaadt	route -qn add -inet6 ::224.0.0.0 -prefixlen 100 ::1 -reject >/dev/null
24403056e2eSderaadt	route -qn add -inet6 ::127.0.0.0 -prefixlen 104 ::1 -reject >/dev/null
24503056e2eSderaadt	route -qn add -inet6 ::0.0.0.0 -prefixlen 104 ::1 -reject >/dev/null
24603056e2eSderaadt	route -qn add -inet6 ::255.0.0.0 -prefixlen 104 ::1 -reject >/dev/null
24792aceabbSitojun
248dfc209d0Smiod	# Disallow packets to malicious 6to4 prefix.
24903056e2eSderaadt	route -qn add -inet6 2002:e000:: -prefixlen 20 ::1 -reject >/dev/null
25003056e2eSderaadt	route -qn add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject >/dev/null
25103056e2eSderaadt	route -qn add -inet6 2002:0000:: -prefixlen 24 ::1 -reject >/dev/null
25203056e2eSderaadt	route -qn add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject >/dev/null
25392aceabbSitojun
254a4ee3723Sitojun	# Disallow packets without scope identifier.
255a4ee3723Sitojun	route -qn add -inet6 ff01:: -prefixlen 16 ::1 -reject >/dev/null
256a4ee3723Sitojun	route -qn add -inet6 ff02:: -prefixlen 16 ::1 -reject >/dev/null
257a4ee3723Sitojun
25892aceabbSitojun	# Completely disallow packets to IPv4 compatible prefix.
259300d0407Srpe	#
26092aceabbSitojun	# This may conflict with RFC1933 under following circumstances:
26192aceabbSitojun	# (1) An IPv6-only KAME node tries to originate packets to IPv4
2625e268fadSderaadt	#     compatible destination.  The KAME node has no IPv4 compatible
26392aceabbSitojun	#     support.  Under RFC1933, it should transmit native IPv6
26492aceabbSitojun	#     packets toward IPv4 compatible destination, hoping it would
26592aceabbSitojun	#     reach a router that forwards the packet toward auto-tunnel
26692aceabbSitojun	#     interface.
2675e268fadSderaadt	# (2) An IPv6-only node originates a packet to an IPv4 compatible
26892aceabbSitojun	#     destination.  A KAME node is acting as an IPv6 router, and
26992aceabbSitojun	#     asked to forward it.
270300d0407Srpe	#
2715e268fadSderaadt	# Due to rare use of IPv4 compatible addresses, and security issues
27292aceabbSitojun	# with it, we disable it by default.
27303056e2eSderaadt	route -qn add -inet6 ::0.0.0.0 -prefixlen 96 ::1 -reject >/dev/null
27482c17b75Sitojun
27582c17b75Sitojun	rtsolif=""
2763d8fed7cSitojunelse
2773d8fed7cSitojun	ip6kernel=NO
2783d8fed7cSitojunfi
2793d8fed7cSitojun
280df930be7Sderaadt
2819ac6b043Stodd# Configure all the non-loopback interfaces which we know about, but
2824eb97611Sderaadt# do not start interfaces which must be delayed. Refer to hostname.if(5)
28329ae3f59Srzalamenaifmstart "" "trunk svlan vlan carp gif gre pfsync pppoe tun bridge switch pflow"
28482c17b75Sitojun
2854bdcd471Sbrad# The trunk interfaces need to come up first in this list.
286f45bd3bdSmpf# The (s)vlan interfaces need to come up after trunk.
2874bdcd471Sbrad# Configure all the carp interfaces which we know about before default route.
288f45bd3bdSmpfifmstart "trunk svlan vlan carp"
2894bdcd471Sbrad
2906125fd66Ssthen# Now that $rtsolif has been populated, IPv6 autoconf those interfaces
29193230e63Srpeifv6autoconf
29282c17b75Sitojun
29380819bdcStodd# Look for default routes in /etc/mygate.
29405102370Smpidefaultroute
295cf3860a5Sderaadt
296745634aaSniklas# Multicast routing.
2976e0f151eSsthenif [[ $multicast != YES ]]; then
298705fcffdSreyk	route -qn delete 224.0.0.0/4 >/dev/null 2>&1
299f4b4b73bSderaadt	route -qn add -net 224.0.0.0/4 -interface 127.0.0.1 -reject >/dev/null
3006e0f151eSsthenfi
301dfc209d0Smiod
302f002925aSflorian# Configure PPPoE, GIF, GRE, TUN and PFLOW interfaces, delayed because they
303f002925aSflorian# require routes to be set. TUN might depend on PPPoE, and GIF or GRE may
304f002925aSflorian# depend on either of them. PFLOW might bind to ip addresses configured
305f002925aSflorian# on either of them.
30629ae3f59Srzalamenaifmstart "pppoe tun gif gre bridge switch pflow"
307dfc209d0Smiod
308300d0407Srpe# Reject 127/8 other than 127.0.0.1.
3098f8fdbefSderaadtroute -qn add -net 127 127.0.0.1 -reject >/dev/null
3108f8fdbefSderaadt
3110a295e45Srpeif [[ $ip6kernel == YES ]]; then
312300d0407Srpe	# This is to make sure DAD is completed before going further.
313c653ce7bSmarkus	count=0
3140a295e45Srpe	while ((count++ < 10 && $(sysctl -n net.inet6.ip6.dad_pending) != 0)); do
315c653ce7bSmarkus		sleep 1
316c653ce7bSmarkus	done
317089287c3Sdavidfi
318