1#!/bin/mksh
2# $MirSecuCron$
3# $MirOS: src/etc/netstart,v 1.12 2009/07/18 14:09:03 tg Exp $
4# $OpenBSD: netstart,v 1.105 2005/05/22 08:56:08 todd Exp $
5
6# strip comments (and leading/trailing whitespace if IFS is set) from
7# any file(s) given as argument, or stdin if none, and spew to stdout
8function stripcom
9{
10	cat "$@" | { set -o noglob; while read _line; do
11		_line=${_line%%#*}
12		[[ -n $_line ]] && print -r -- $_line
13	done; }
14}
15
16# Returns true if $1 contains only alphanumerics
17isalphanumeric() {
18	typeset _n
19	_n=$1
20	while [ ${#_n} != 0 ]; do
21		case $_n in
22			[A-Za-z0-9]*)	;;
23			*)		return 1;;
24		esac
25		_n=${_n#?}
26	done
27	return 0
28}
29
30# Start the $1 interface
31ifstart() {
32	if=$1
33	# Interface names must be alphanumeric only.  We check to avoid
34	# configuring backup or temp files, and to catch the "*" case.
35	if ! isalphanumeric "$if"; then
36		return
37	fi
38
39	ifconfig $if >/dev/null 2>&1
40	if [[ $? != 0 ]]; then
41		# Try to create interface if it does not exist
42		ifconfig $if create >/dev/null 2>&1
43		if [[ $? != 0 ]]; then
44			return
45		fi
46	fi
47
48	# Now parse the hostname.* file
49	while :; do
50		if [[ -n $cmd2 ]]; then
51			# We are carrying over from the 'read dt dtaddr'
52			# last time.
53			set -- $cmd2
54			af="$1" name="$2" mask="$3" bcaddr="$4" ext1="$5" cmd2=
55			# Make sure and get any remaining args in ext2,
56			# like the read below
57			i=1
58			while [[ i -lt 6 && -n $1 ]]; do
59				shift
60				let i++
61			done
62			ext2="$@"
63		else
64			# Read the next line or exit the while loop.
65			read af name mask bcaddr ext1 ext2 || break
66		fi
67		# $af can be "dhcp", "up", "rtsol", an address family,
68		# commands, or a comment.
69		case "$af" in
70		"#"*|"") # skip comments and empty lines
71			continue
72			;;
73		"!"*) # parse commands
74			cmd="${af#*!} ${name} ${mask} ${bcaddr} ${ext1} ${ext2}"
75			;;
76		bridge)
77			cmd="echo /etc/hostname.$if: bridges now supported via bridgename.* files"
78			;;
79		dhcp)
80			[[ $name = NONE ]] && name=
81			[[ $mask = NONE ]] && mask=
82			[[ $bcaddr = NONE ]] && bcaddr=
83			ifconfig $if $name $mask $bcaddr $ext1 $ext2 down
84			cmd="dhclient $if"
85			;;
86		route)
87			routep="-n $name"
88			[[ $name = +n ]] && routep=
89			cmd="/sbin/route ${routep} ${mask} ${bcaddr} ${ext1} ${ext2}"
90			;;
91		rtsol)
92			ifconfig $if $name $mask $bcaddr $ext1 $ext2 up
93			rtsolif="$rtsolif $if"
94			cmd=
95			;;
96		up)
97			# The only one of these guaranteed to be set is $if.
98			# The remaining ones exist so that media controls work.
99			cmd="ifconfig $if $name $mask $bcaddr $ext1 $ext2 up"
100			;;
101		*)
102			read dt dtaddr
103			if [[ $name  = alias ]]; then
104				# perform a 'shift' of sorts
105				alias=$name
106				name=$mask
107				mask=$bcaddr
108				bcaddr=$ext1
109				ext1=$ext2
110				ext2=
111			else
112				alias=
113			fi
114			cmd="ifconfig $if $af $alias $name "
115			case "$dt" in
116			dest)
117				cmd="$cmd $dtaddr"
118				;;
119			[a-z!]*)
120				cmd2="$dt $dtaddr"
121				;;
122			esac
123			if [[ -z $name ]]; then
124				echo "/etc/hostname.$if: invalid network configuration file"
125				return
126			fi
127			case $af in
128			inet)
129				[[ -n $mask ]] && \
130				    if [[ $mask = @([1-9]|[12][0-9]|3[0-2]) ]]; then
131					cmd="$cmd prefixlen $mask"
132				else
133					cmd="$cmd netmask $mask"
134				fi
135				if [[ -n $bcaddr && $bcaddr != NONE ]]; then
136					cmd="$cmd broadcast $bcaddr"
137				fi
138				[[ -n $alias ]] && rtcmd=";route -qn add -host $name 127.0.0.1"
139				;;
140			inet6)
141				[[ -n $mask ]] && cmd="$cmd prefixlen $mask"
142				cmd="$cmd $bcaddr"
143				;;
144			*)
145				cmd="$cmd $mask $bcaddr"
146				;;
147			esac
148			cmd="$cmd $ext1 $ext2$rtcmd" rtcmd=
149			;;
150		esac
151		eval "$cmd"
152	done </etc/hostname.$if
153}
154
155# Start multiple:
156#   start "$1" interfaces in order or all interfaces if empty
157#   don't start "$2" interfaces
158ifmstart() {
159	for sif in ${1:-ALL}; do
160		for hn in /etc/hostname.*; do
161			# Strip off /etc/hostname. prefix
162			if=${hn#/etc/hostname.}
163			test "$if" = "*" && continue
164
165			# Skip unwanted ifs
166			s=""
167			for xf in $2; do
168				test "$xf" = "${if%%[0-9]*}" && s="1" && break
169			done
170			test "$s" = "1" && continue
171
172			# Start wanted ifs
173			test "$sif" = "ALL" -o \
174			     "$sif" = "${if%%[0-9]*}" \
175				&& ifstart $if
176		done
177	done
178}
179
180# Start the $1 bridge
181bridgestart() {
182	# Interface names must be alphanumeric only.  We check to avoid
183	# configuring backup or temp files, and to catch the "*" case.
184	if ! isalphanumeric "$1"; then
185		return
186	fi
187	brconfig $1 >/dev/null 2>&1
188	if [[ $? != 0 ]]; then
189		# Try to create interface if it does not exist
190		ifconfig $if create >/dev/null 2>&1
191		if [[ $? != 0 ]]; then
192			return
193		fi
194	fi
195
196	# Now parse the bridgename.* file
197	# All lines are run as brconfig(8) commands.
198	while read line ; do
199		line=${line%%#*}		# strip comments
200		test -z "$line" && continue
201		case "$line" in
202		"!"*)
203			cmd="${line#*!}"
204			;;
205		*)
206			cmd="brconfig $1 $line"
207			;;
208		esac
209		eval "$cmd"
210	done </etc/bridgename.$1
211}
212
213# Re-read /etc/rc.conf
214. /etc/rc.conf
215
216# If we were invoked with a list of interface names, just reconfigure these
217# interfaces (or bridges) and return.
218[[ $1 = autoboot ]] && shift
219if [ $# -gt 0 ]; then
220	while [ $# -gt 0 ]; do
221		if [ -f /etc/bridgename.$1 ]; then
222			bridgestart $1
223		else
224			ifstart $1
225		fi
226		shift
227	done
228	return
229fi
230
231# Otherwise, process with the complete network initialization.
232
233# Since no interface is set up yet, using DNS is pointless.
234if [[ -e /etc/resolv.conf ]]; then
235	T=/etc/resolv.conf.$RANDOM
236	mv /etc/resolv.conf $T
237	echo lookup file >/etc/resolv.conf
238else
239	T=fail
240fi
241
242# /etc/myname contains my symbolic name
243if [ -f /etc/myname ]; then
244	hostname=$(stripcom /etc/myname)
245	hostname $hostname
246else
247	hostname=$(hostname)
248fi
249
250# Set the address for the loopback interface.  Bringing the
251# interface up, automatically invokes the IPv6 address ::1)
252ifconfig lo0 inet 127.0.0.1
253
254if ifconfig lo0 inet6 >/dev/null 2>&1; then
255	# IPv6 configurations.
256	ip6kernel=YES
257
258	# Disallow link-local unicast dest without outgoing scope identifiers.
259	route -qn add -inet6 fe80:: -prefixlen 10 ::1 -reject >/dev/null
260
261	# Disallow site-local unicast dest without outgoing scope identifiers.
262	# If you configure site-locals without scope id (it is permissible
263	# config for routers that are not on scope boundary), you may want
264	# to comment the line out.
265	route -qn add -inet6 fec0:: -prefixlen 10 ::1 -reject >/dev/null
266
267	# Disallow "internal" addresses to appear on the wire.
268	route -qn add -inet6 ::ffff:0.0.0.0 -prefixlen 96 ::1 -reject >/dev/null
269
270	# Disallow packets to malicious IPv4 compatible prefix.
271	route -qn add -inet6 ::224.0.0.0 -prefixlen 100 ::1 -reject >/dev/null
272	route -qn add -inet6 ::127.0.0.0 -prefixlen 104 ::1 -reject >/dev/null
273	route -qn add -inet6 ::0.0.0.0 -prefixlen 104 ::1 -reject >/dev/null
274	route -qn add -inet6 ::255.0.0.0 -prefixlen 104 ::1 -reject >/dev/null
275
276	# Disallow packets to malicious 6to4 prefix.
277	route -qn add -inet6 2002:e000:: -prefixlen 20 ::1 -reject >/dev/null
278	route -qn add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject >/dev/null
279	route -qn add -inet6 2002:0000:: -prefixlen 24 ::1 -reject >/dev/null
280	route -qn add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject >/dev/null
281
282	# Completely disallow packets to IPv4 compatible prefix.
283	# This may conflict with RFC1933 under following circumstances:
284	# (1) An IPv6-only KAME node tries to originate packets to IPv4
285	#     compatible destination.  The KAME node has no IPv4 compatible
286	#     support.  Under RFC1933, it should transmit native IPv6
287	#     packets toward IPv4 compatible destination, hoping it would
288	#     reach a router that forwards the packet toward auto-tunnel
289	#     interface.
290	# (2) An IPv6-only node originates a packet to an IPv4 compatible
291	#     destination.  A KAME node is acting as an IPv6 router, and
292	#     asked to forward it.
293	# Due to rare use of IPv4 compatible addresses, and security issues
294	# with it, we disable it by default.
295	route -qn add -inet6 ::0.0.0.0 -prefixlen 96 ::1 -reject >/dev/null
296
297	rtsolif=""
298else
299	ip6kernel=NO
300fi
301
302# Now put back the DNS resolver config
303[[ $T = fail ]] || mv $T /etc/resolv.conf
304
305# Configure all the non-loopback interfaces which we know about, but
306# do not start interfaces which must be delayed.
307# Refer to hostname.if(5) and bridgename.if(5)
308ifmstart "" "carp gif gre pfsync pppoe local"
309
310if [[ $ip6kernel = YES && -n $rtsolif ]]; then
311	fw=$(sysctl -n net.inet6.ip6.forwarding)
312	ra=$(sysctl -n net.inet6.ip6.accept_rtadv)
313	if [[ $fw = 0 && $ra = 1 ]]; then
314		echo "IPv6 autoconf:$rtsolif"
315		rtsol $rtsolif
316	else
317		echo "WARNING: inconsistent config - check /etc/sysctl.conf for IPv6 autoconf"
318	fi
319fi
320if [[ $ip6kernel = YES ]]; then
321	# this is to make sure DAD is completed before going further.
322	sleep $(sysctl -n net.inet6.ip6.dad_count)
323fi
324
325# The pfsync interface needs to come up before carp.
326# Configure all the carp interfaces which we know about.
327# They must come up after pfsync but before default route.
328ifmstart "pfsync carp" "local"
329
330# Multicast routing.
331#
332# The routing to the 224.0.0.0/4 net is setup according to these rules:
333# multicast_host	multicast_router	route		comment
334# NO			NO			-reject		no multicast
335# NO			YES			none installed	daemon will run
336# YES/interface		NO			-interface	YES=def. iface
337#	   Any other combination		-reject		config error
338case "$multicast_host:$multicast_router" in
339NO:NO)
340	route -qn add -net 224.0.0.0/4 -interface 127.0.0.1 -reject >/dev/null
341	;;
342NO:YES)
343	;;
344*:NO)
345	set $(if [ $multicast_host = YES ]; then
346		ed -s '!route -qn show -inet' <<EOF
347/^default/p
348EOF
349	else
350		ed -s "!ifconfig $multicast_host" <<EOF
351/^	inet /p
352EOF
353	fi)
354	route -qn add -net 224.0.0.0/4 -interface $2 >/dev/null
355	;;
356*:*)
357	echo 'config error, multicasting disabled until rc.conf is fixed'
358	route -qn add -net 224.0.0.0/4 -interface 127.0.0.1 -reject >/dev/null
359	;;
360esac
361
362
363# Configure PPPoE, GIF, GRE interfaces, delayed because they require routes
364# to be set.  PPPoE must be first, as GIF and GRE may depend on it.
365ifmstart "pppoe gif gre" "local"
366
367# reject 127/8 other than 127.0.0.1
368route -qn add -net 127 127.0.0.1 -reject >/dev/null
369
370# Configure all the bridges.
371for bn in /etc/bridgename.*; do
372	# Strip off /etc/bridgename. prefix
373	if=${bn#/etc/bridgename.}
374	test "$if" = "*" && continue
375
376	bridgestart $if
377done
378
379[[ -e /etc/hostname.local ]] && eval $(stripcom /etc/hostname.local)
380