netstart revision 1.160
1#!/bin/sh -
2#
3#	$OpenBSD: netstart,v 1.160 2015/11/12 22:50:46 rpe Exp $
4
5# Turn off Strict Bourne shell mode.
6set +o sh
7
8# Strip comment lines from a file.
9# Strip leading and trailing whitespace if IFS is set.
10# Usage: stripcom /path/to/file
11stripcom() {
12	local _file=$1 _line
13
14	[[ -f $_file ]] || return
15
16	while read _line; do
17		[[ -n ${_line%%#*} ]] && print -r -- "$_line"
18	done <$_file
19}
20
21# Start a single interface.
22# Usage: ifstart if1
23ifstart() {
24	if=$1
25	# Interface names must be alphanumeric only.  We check to avoid
26	# configuring backup or temp files, and to catch the "*" case.
27	[[ $if != +([[:alpha:]])+([[:digit:]]) ]] && return
28
29	file=/etc/hostname.$if
30	if ! [ -f $file ]; then
31		echo "netstart: $file: No such file or directory"
32		return
33	fi
34	# Not using stat(1), we can't rely on having /usr yet.
35	set -A stat -- `ls -nL $file`
36	if [ "${stat[0]#???????} ${stat[2]} ${stat[3]}" != "--- 0 0" ]; then
37		echo "WARNING: $file is insecure, fixing permissions"
38		chmod -LR o-rwx $file
39		chown -LR root.wheel $file
40	fi
41	# Check for ifconfig'able interface.
42	(ifconfig $if || ifconfig $if create) >/dev/null 2>&1 || return
43
44	# Now parse the hostname.* file.
45	while :; do
46		if [ "$cmd2" ]; then
47			# We are carrying over from the 'read dt dtaddr'
48			# last time.
49			set -- $cmd2
50			af="$1" name="$2" mask="$3" bcaddr="$4" ext1="$5" cmd2=
51			# Make sure and get any remaining args in ext2,
52			# like the read below.
53			i=1
54			while [ $i -lt 6 -a -n "$1" ]; do shift; let i=i+1; done
55			ext2="$@"
56		else
57			# Read the next line or exit the while loop.
58			read af name mask bcaddr ext1 ext2 || break
59		fi
60		# $af can be "dhcp", "up", "rtsol", an address family, commands,
61		# or a comment.
62		case "$af" in
63		"#"*|"") # Skip comments and empty lines.
64			continue
65			;;
66		"!"*) # Parse commands.
67			cmd="${af#*!} ${name} ${mask} ${bcaddr} ${ext1} ${ext2}"
68			;;
69		"dhcp")
70			[ "$name" = "NONE" ] && name=
71			[ "$mask" = "NONE" ] && mask=
72			[ "$bcaddr" = "NONE" ] && bcaddr=
73			cmd="ifconfig $if $name $mask $bcaddr $ext1 $ext2 down"
74			cmd="$cmd;dhclient $if"
75			dhcpif="$dhcpif $if"
76			;;
77		"rtsol")
78			rtsolif="$rtsolif $if"
79			cmd="ifconfig $if $name $mask $bcaddr $ext1 $ext2 up"
80			;;
81		*)
82			read dt dtaddr
83			if [ "$name"  = "alias" ]; then
84				# Perform a 'shift' of sorts.
85				alias=$name
86				name=$mask
87				mask=$bcaddr
88				bcaddr=$ext1
89				ext1=$ext2
90				ext2=
91			else
92				alias=
93			fi
94			cmd="ifconfig $if $af $alias $name"
95			case "$dt" in
96			dest)
97				cmd="$cmd $dtaddr"
98				;;
99			*)
100				cmd2="$dt $dtaddr"
101				;;
102			esac
103			case $af in
104			inet)
105				if [ ! -n "$name" ]; then
106					echo "/etc/hostname.$if: inet alone is invalid"
107					return
108				fi
109				[ "$mask" ] && cmd="$cmd netmask $mask"
110				if [ "$bcaddr" -a "X$bcaddr" != "XNONE" ]; then
111					cmd="$cmd broadcast $bcaddr"
112				fi
113				;;
114			inet6)
115				if [ ! -n "$name" ]; then
116					echo "/etc/hostname.$if: inet6 alone is invalid"
117					return
118				fi
119				[ "$mask" ] && cmd="$cmd prefixlen $mask"
120				cmd="$cmd $bcaddr"
121				;;
122			*)
123				cmd="$cmd $mask $bcaddr"
124				;;
125			esac
126			cmd="$cmd $ext1 $ext2"
127			;;
128		esac
129		eval "$cmd"
130	done </etc/hostname.$if
131}
132
133# Start multiple:
134# Usage: ifmstart "if1 if2" "if3 if4"
135#   Start "$1" interfaces in order or all interfaces if empty.
136#   Don't start "$2" interfaces.
137ifmstart() {
138	for sif in ${1:-ALL}; do
139		for hn in /etc/hostname.*; do
140			# Strip off /etc/hostname. prefix.
141			if=${hn#/etc/hostname.}
142			[ "$if" = "*" ] && continue
143
144			# Skip unwanted ifs.
145			s=""
146			for xf in $2; do
147				[ "$xf" = "${if%%[0-9]*}" ] && s="1" && break
148			done
149			[ "$s" = "1" ] && continue
150
151			# Start wanted ifs.
152			[ "$sif" = "ALL" -o "$sif" = "${if%%[0-9]*}" ] &&
153				ifstart $if
154		done
155	done
156}
157
158# IPv6 autoconf the interfaces in the list at $rtsolif
159# Usage: ifautoconf
160ifautoconf() {
161	# $ip6kernel will not have been set if we were invoked with a
162	# list of interface names
163	if ifconfig lo0 inet6 >/dev/null 2>&1; then
164		for curif in $rtsolif; do
165			ifconfig $curif inet6 autoconf
166		done
167	fi
168}
169
170# Get network related vars from rc.conf using the parsing routine from rc.subr.
171FUNCS_ONLY=1 . /etc/rc.d/rc.subr
172_rc_parse_conf
173
174# If we were invoked with a list of interface names, just reconfigure these
175# interfaces (or bridges) and return.
176if (($# > 0)); then
177	for _if; do ifstart $_if; done
178	ifautoconf
179	return
180fi
181
182# Otherwise, process with the complete network initialization.
183
184# /etc/myname contains my symbolic name.
185[[ -f /etc/myname ]] && hostname "$(stripcom /etc/myname)"
186
187# Set the address for the loopback interface.  Bringing the interface up,
188# automatically invokes the IPv6 address ::1.
189ifconfig lo0 inet 127.0.0.1/8
190
191if ifconfig lo0 inet6 >/dev/null 2>&1; then
192	# IPv6 configurations.
193	ip6kernel=YES
194
195	# Disallow link-local unicast dest without outgoing scope identifiers.
196	route -qn add -inet6 fe80:: -prefixlen 10 ::1 -reject >/dev/null
197
198	# Disallow site-local unicast dest without outgoing scope identifiers.
199	# If you configure site-locals without scope id (it is permissible
200	# config for routers that are not on scope boundary), you may want
201	# to comment the line out.
202	route -qn add -inet6 fec0:: -prefixlen 10 ::1 -reject >/dev/null
203
204	# Disallow "internal" addresses to appear on the wire.
205	route -qn add -inet6 ::ffff:0.0.0.0 -prefixlen 96 ::1 -reject >/dev/null
206
207	# Disallow packets to malicious IPv4 compatible prefix.
208	route -qn add -inet6 ::224.0.0.0 -prefixlen 100 ::1 -reject >/dev/null
209	route -qn add -inet6 ::127.0.0.0 -prefixlen 104 ::1 -reject >/dev/null
210	route -qn add -inet6 ::0.0.0.0 -prefixlen 104 ::1 -reject >/dev/null
211	route -qn add -inet6 ::255.0.0.0 -prefixlen 104 ::1 -reject >/dev/null
212
213	# Disallow packets to malicious 6to4 prefix.
214	route -qn add -inet6 2002:e000:: -prefixlen 20 ::1 -reject >/dev/null
215	route -qn add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject >/dev/null
216	route -qn add -inet6 2002:0000:: -prefixlen 24 ::1 -reject >/dev/null
217	route -qn add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject >/dev/null
218
219	# Disallow packets without scope identifier.
220	route -qn add -inet6 ff01:: -prefixlen 16 ::1 -reject >/dev/null
221	route -qn add -inet6 ff02:: -prefixlen 16 ::1 -reject >/dev/null
222
223	# Completely disallow packets to IPv4 compatible prefix.
224	#
225	# This may conflict with RFC1933 under following circumstances:
226	# (1) An IPv6-only KAME node tries to originate packets to IPv4
227	#     compatible destination.  The KAME node has no IPv4 compatible
228	#     support.  Under RFC1933, it should transmit native IPv6
229	#     packets toward IPv4 compatible destination, hoping it would
230	#     reach a router that forwards the packet toward auto-tunnel
231	#     interface.
232	# (2) An IPv6-only node originates a packet to an IPv4 compatible
233	#     destination.  A KAME node is acting as an IPv6 router, and
234	#     asked to forward it.
235	#
236	# Due to rare use of IPv4 compatible addresses, and security issues
237	# with it, we disable it by default.
238	route -qn add -inet6 ::0.0.0.0 -prefixlen 96 ::1 -reject >/dev/null
239
240	rtsolif=""
241else
242	ip6kernel=NO
243fi
244
245
246# Configure all the non-loopback interfaces which we know about, but
247# do not start interfaces which must be delayed. Refer to hostname.if(5)
248ifmstart "" "trunk svlan vlan carp gif gre pfsync pppoe tun tap bridge pflow"
249
250# The trunk interfaces need to come up first in this list.
251# The (s)vlan interfaces need to come up after trunk.
252# Configure all the carp interfaces which we know about before default route.
253ifmstart "trunk svlan vlan carp"
254
255# Now that $rtsolif has been populated, IPv6 autoconf those interfaces
256ifautoconf
257
258# Look for default routes in /etc/mygate.
259[[ -z $dhcpif ]] && stripcom /etc/mygate | while read gw; do
260		[[ $gw == @(*:*) ]] && continue
261		route -qn delete default >/dev/null 2>&1
262		route -qn add -host default $gw && break
263done
264[[ -z $rtsolif ]] && stripcom /etc/mygate | while read gw; do
265		[[ $gw == !(*:*) ]] && continue
266		route -qn delete -inet6 default >/dev/null 2>&1
267		route -qn add -host -inet6 default $gw && break
268done
269
270# Multicast routing.
271#
272# The routing to the 224.0.0.0/4 net is setup according to these rules:
273# multicast_host	multicast_router	route		comment
274# NO			NO			-reject		no multicast
275# NO			YES			none installed	daemon will run
276# YES/interface		NO			-interface	YES=def. iface
277#	   Any other combination		-reject		config error
278route -qn delete 224.0.0.0/4 >/dev/null 2>&1
279case "$multicast_host:$multicast_router" in
280NO:NO)
281	route -qn add -net 224.0.0.0/4 -interface 127.0.0.1 -reject >/dev/null
282	;;
283NO:YES)
284	;;
285*:NO)
286	maddr=$(if [[ $multicast_host == YES ]]; then
287		ed -s '!route -qn show -inet' <<EOF
288/^default/p
289EOF
290	else
291		ed -s "!ifconfig $multicast_host" <<EOF
292/^	inet /p
293EOF
294	fi 2>/dev/null)
295	if [[ -n $maddr ]]; then
296		set $maddr
297		route -qn add -net 224.0.0.0/4 -interface $2 >/dev/null
298	else
299		route -qn add -net 224.0.0.0/4 -interface \
300			127.0.0.1 -reject >/dev/null
301	fi
302	;;
303*:*)
304	echo 'config error, multicasting disabled until rc.conf is fixed'
305	route -qn add -net 224.0.0.0/4 -interface 127.0.0.1 -reject >/dev/null
306	;;
307esac
308
309
310# Configure PPPoE, GIF, GRE, TUN and PFLOW interfaces, delayed because they
311# require routes to be set. TUN might depend on PPPoE, and GIF or GRE may
312# depend on either of them. PFLOW might bind to ip addresses configured
313# on either of them.
314ifmstart "pppoe tun tap gif gre bridge pflow"
315
316# Reject 127/8 other than 127.0.0.1.
317route -qn add -net 127 127.0.0.1 -reject >/dev/null
318
319if [[ $ip6kernel == YES ]]; then
320	# This is to make sure DAD is completed before going further.
321	count=0
322	while ((count++ < 10 && $(sysctl -n net.inet6.ip6.dad_pending) != 0)); do
323		sleep 1
324	done
325fi
326