xref: /illumos-gate/usr/src/cmd/svc/milestone/net-install (revision 2a8bcb4efb45d99ac41c94a75c396b362c414f7f)
1#!/sbin/sh
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22#
23# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24#
25
26. /lib/svc/share/smf_include.sh
27. /lib/svc/share/net_include.sh
28
29IPADM=/sbin/ipadm
30SVCCFG=/usr/sbin/svccfg
31SVCPROP=/usr/bin/svcprop
32SVCADM=/usr/sbin/svcadm
33ROUTE=/sbin/route
34
35NET_NWAM_FMRI="svc:/network/physical:nwam"
36NET_INSTALL_FMRI=$SMF_FMRI
37
38NET_V4IF=install_ipv4_interface
39NET_V6IF=install_ipv6_interface
40
41NET_UNDEFINED_STRING_PROP="\"\""
42
43net_install_debug=0
44
45unset net_install_name net_install_addrtype net_install_addr \
46    net_install_dhcpwait net_install_interface_id \
47    net_install_stateless net_install_stateful net_install_route
48
49net_configure_install_if()
50{
51	ipv6_interface=$1
52
53	case $net_install_addrtype in
54	static)
55		cmd="$IPADM create-addr -T static "
56		cmd=$cmd"-a local=$net_install_addr $net_install_name"
57		;;
58
59	dhcp)
60		dhcpwait=""
61		if [ "$net_install_dhcpwait" != "" ]; then
62			dhcpwait="-w $net_install_dhcpwait"
63		fi
64
65		cmd="$IPADM create-addr -T dhcp $dhcpwait $net_install_name"
66		;;
67	addrconf)
68		interface_id=""
69		if [ "$net_install_interface_id" != "" ]; then
70			interface_id="-i $net_install_interface_id"
71		fi
72
73		state=""
74		if [ "$net_install_stateless" != "" ]; then
75			state="-p stateless=$net_install_stateless"
76		fi
77
78		if [ "$net_install_stateful" != "" ]; then
79			if [ "$state" = "" ]; then
80				state="-p stateful=$net_install_stateful"
81			else
82				state=$state",stateful=$net_install_stateful"
83			fi
84		fi
85
86		cmd="$IPADM create-addr -T addrconf "
87		cmd=$cmd"$interface_id $state $net_install_name"
88		;;
89	esac
90
91	$cmd
92	if [ $? -ne 0 ]; then
93		net_record_err "Error configuring interface:\n\"$cmd\"" $?
94		return $SMF_EXIT_ERR_FATAL
95	fi
96
97	if [ "$net_install_route" != "" ]; then
98		if [ $ipv6_interface == 1 ]; then
99			details="-inet6 default"
100		else
101			details="default"
102		fi
103		ifp=`echo $net_install_name | /usr/bin/cut -f1 -d'/'`
104		details="$details $net_install_route -ifp $ifp"
105		cmd="$ROUTE add $details"
106		$cmd
107		cmd="$ROUTE get $details"
108		$cmd
109		if [ $? -ne 0 ]; then
110			err=$?
111			msg="Error creating default route:\n\"$cmd\""
112			net_record_err "$msg" $err
113			return $SMF_EXIT_ERR_FATAL
114		fi
115		rootdir=/etc/svc/volatile
116		/usr/bin/mkdir -p $rootdir/etc/inet
117		if [ $? -ne 0 ]; then
118			err=$?
119			msg="Error creating \"$rootdir/etc/inet\" directory"
120			net_record_err "$msg" $err
121			return $SMF_EXIT_ERR_FATAL
122		fi
123		cmd="$ROUTE -R $rootdir -p add $details"
124		$cmd
125		if [ $? -ne 0 ]; then
126			err=$?
127			msg="Error adding persistent default route:\n\"$cmd\""
128			net_record_err "$msg" $err
129			return $SMF_EXIT_ERR_FATAL
130		fi
131	fi
132
133	return $SMF_EXIT_OK
134}
135
136net_process_v4_pg()
137{
138	net_install_name=""
139	net_install_addrtype=""
140	net_install_addr=""
141	net_install_dhcpwait=""
142	net_install_route=""
143
144	#
145	# Retrieve the mandatory interface name property value. If
146	# the value is empty, then no interface is configured.
147	#
148	prop=`$SVCPROP -p $NET_V4IF/name $NET_INSTALL_FMRI`
149	if [ $? -ne 0 -o "$prop" = "$NET_UNDEFINED_STRING_PROP" ]; then
150		return $SMF_EXIT_OK
151	fi
152	net_install_name=$prop
153
154	#
155	# Retrieve the mandatory address type property value. The two
156	# valid values are "static" and "dhcp".
157	#
158	prop=`$SVCPROP -p $NET_V4IF/address_type $NET_INSTALL_FMRI`
159	if [ $? -ne 0 -o "$prop" = "$NET_UNDEFINED_STRING_PROP" ]; then
160		msg="No \"address_type\" property defined in the "
161		msg=$msg"\"$NET_V4IF\" property group"
162		net_record_err "$msg" 0
163		return $SMF_EXIT_ERR_CONFIG
164	fi
165	case $prop in
166	static | dhcp)
167		net_install_addrtype=$prop
168		;;
169	*)
170		msg="Bad value, \"$prop\", defined for the \"address_type\" "
171		msg=$msg"property in the \"$NET_V4IF\" property group"
172		net_record_err "$msg" 0
173		return $SMF_EXIT_ERR_CONFIG
174		;;
175	esac
176
177	#
178	# Retrieve the static address property value. The address property
179	# only applies to static address type configurations. If not
180	# configuring a static address, then the property should still have
181	# its default value of 0.0.0.0/0.
182	#
183	prop=`$SVCPROP -p $NET_V4IF/static_address $NET_INSTALL_FMRI`
184	if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then
185		if [ "$net_install_addrtype" = "dhcp" ]; then
186			if [ "$prop" != "${NET_INADDR_ANY}/0" ]; then
187				msg="Warning: static address ignored "
188				msg=$msg"in the \"$NET_V4IF\ property group"
189				net_record_err "$msg" 0
190			fi
191		else
192			if [ "$prop" = "${NET_INADDR_ANY}/0" ]; then
193				msg="Error: static address required in the "
194				msg=$msg"\"$NET_V4IF\" property group"
195				net_record_err "$msg" 0
196				return $SMF_EXIT_ERR_CONFIG
197			fi
198			net_install_addr=$prop
199		fi
200	else
201		if [ "$net_install_addrtype" = "static" ]; then
202			msg="Error: static address required in the "
203			msg=$msg"\"$NET_V4IF\" property group"
204			net_record_err "$msg" 0
205			return $SMF_EXIT_ERR_CONFIG
206		fi
207	fi
208
209	#
210	# Retrieve the optional DHCP wait property value.
211	#
212	prop=`$SVCPROP -p $NET_V4IF/dhcp_wait $NET_INSTALL_FMRI`
213	if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then
214		if [ "$net_install_addrtype" != "dhcp" ]; then
215			if [ "$prop" != "120" ]; then
216				msg="Warning: DHCP wait value ignored in the "
217				msg=$msg"\"$NET_V4IF\" property group"
218				net_record_err "$msg" 0
219			fi
220		else
221			net_install_dhcpwait=$prop
222		fi
223	fi
224
225	#
226	# Retrieve the optional default route property value.
227	#
228	prop=`$SVCPROP -p $NET_V4IF/default_route $NET_INSTALL_FMRI`
229	if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then
230		if [ "$prop" != "$NET_INADDR_ANY" ]; then
231			net_install_route=$prop
232		fi
233	fi
234
235	net_configure_install_if 0
236
237	return $?
238}
239
240net_process_v6_pg()
241{
242	net_install_name=""
243	net_install_addrtype=""
244	net_install_addr=""
245	net_install_stateless=""
246	net_install_stateful=""
247	net_install_interface_id=""
248	net_install_route=""
249
250	#
251	# Retrieve the mandatory interface name property value. If
252	# the value is empty, then no interface is configured.
253	#
254	prop=`$SVCPROP -p $NET_V6IF/name $NET_INSTALL_FMRI`
255	if [ $? -ne 0 -o "$prop" = "$NET_UNDEFINED_STRING_PROP" ]; then
256		return $SMF_EXIT_OK
257	fi
258	net_install_name=$prop
259
260	#
261	# Retrieve the mandatory address type property value. The two
262	# valid values are "static" and "addrconf".
263	#
264	prop=`$SVCPROP -p $NET_V6IF/address_type $NET_INSTALL_FMRI`
265	if [ $? -ne 0 -o "$prop" = "$NET_UNDEFINED_STRING_PROP" ]; then
266		msg="No \"address_type\" property defined in the "
267		msg=$msg"\"$NET_V6IF\" property group"
268		net_record_err "$msg" 0
269		return $SMF_EXIT_ERR_CONFIG
270	fi
271	case $prop in
272	static | addrconf)
273		net_install_addrtype=$prop
274		;;
275	*)
276		msg="Bad value \"$prop\" defined for \"address_type\""
277		net_record_err "$msg" 0
278		return $SMF_EXIT_ERR_CONFIG
279		;;
280	esac
281
282	#
283	# Retrieve the static address property value. The address property
284	# only applies to static address type configurations. If not
285	# configuring a static address, then the property should still have
286	# its default value of ::0/0.
287	#
288	prop=`$SVCPROP -p $NET_V6IF/static_address $NET_INSTALL_FMRI`
289	if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then
290		if [ "$net_install_addrtype" = "addrconf" ]; then
291			if [ "$prop" != "${NET_IN6ADDR_ANY_INIT}/0" ]; then
292				msg="Warning: static address ignored in the "
293				msg=$msg"\"$NET_V6IF\" property group"
294				net_record_err "$msg" 0
295			fi
296		else
297			if [ "$prop" = "${NET_IN6ADDR_ANY_INIT}/0" ]; then
298				msg="Error: static address required in the "
299				msg=$msg"\"$NET_V6IF\" property group"
300				net_record_err "$msg" 0
301				return $SMF_EXIT_ERR_CONFIG
302			fi
303			net_install_addr=$prop
304		fi
305	else
306		if [ "$net_install_addrtype" = "static" ]; then
307			msg="Error: static address required in the "
308			msg=$msg"\"$NET_V6IF\" property group"
309			net_record_err "$msg" 0
310			return $SMF_EXIT_ERR_CONFIG
311		fi
312
313	fi
314
315	#
316	# Retrieve the optional interface id property value. The
317	# property only applies to addrconf address type configurations.
318	# If configuring a static address, then the property should still
319	# have its default value of ::0/0.
320	#
321	prop=`$SVCPROP -p $NET_V6IF/interface_id $NET_INSTALL_FMRI`
322	if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then
323		if [ "$prop" != "${NET_IN6ADDR_ANY_INIT}/0" ]; then
324			if [ "$net_install_addrtype" != "addrconf" ]; then
325				msg="Warning: interface id value ignored in "
326				msg=$msg"the \"$NET_V6IF\" property group"
327				net_record_err "$msg" 0
328			else
329				net_install_interface_id=$prop
330			fi
331		fi
332	fi
333
334	#
335	# Retrieve the optional stateless property value. The property
336	# only applies to addrconf address type configurations. If
337	# configuring a static address, then the property should still
338	# have its default value of "yes".
339	#
340	prop=`$SVCPROP -p $NET_V6IF/stateless $NET_INSTALL_FMRI`
341	if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then
342		case $prop in
343		yes)
344			net_install_stateless=$prop
345			;;
346		no)
347			if [ "$net_install_addrtype" != "addrconf" ]; then
348				msg="Warning: stateless value ignored in the "
349				msg=$msg"\"$NET_V6IF\" property group"
350				net_record_err "$msg" 0
351			else
352				net_install_stateless=$prop
353			fi
354			;;
355		*)
356			msg="Bad value \"$prop\" defined for the \"stateless\""
357			msg=$msg" property in the \"$NET_V6IF\" property group"
358			net_record_err "$msg" 0
359			return $SMF_EXIT_ERR_CONFIG
360		;;
361		esac
362	fi
363
364	#
365	# Retrieve the optional stateful property value. The property
366	# only applies to addrconf address type configurations. If
367	# configuring a static address, then the property should still
368	# have its default value of "yes".
369	#
370	prop=`$SVCPROP -p $NET_V6IF/stateful $NET_INSTALL_FMRI`
371	if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then
372		case $prop in
373		yes)
374			net_install_stateful=$prop
375			;;
376		no)
377			if [ "$net_install_addrtype" != "addrconf" ]; then
378				msg="Warning: stateless value ignored in the "
379				msg=$msg"\"$NET_V6IF\" property group"
380				net_record_err "$msg" 0
381			else
382				net_install_stateful=$prop
383			fi
384			;;
385		*)
386			msg="Bad value \"$prop\" defined for the \"stateless\""
387			msg=$msg" property in the \"$NET_V6IF\" property group"
388			net_record_err "$msg" 0
389			return $SMF_EXIT_ERR_CONFIG
390		;;
391		esac
392	fi
393
394	#
395	# Retrieve the optional default route property value.
396	#
397	prop=`$SVCPROP -p $NET_V6IF/default_route $NET_INSTALL_FMRI`
398	if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then
399		if [ "$prop" != "$NET_IN6ADDR_ANY_INIT" ]; then
400			net_install_route=$prop
401		fi
402	fi
403
404	net_configure_install_if 1
405
406	return $?
407}
408
409net_process_install()
410{
411	vout=`$SVCCFG -s $NET_INSTALL_FMRI validate 2>&1`
412	if [ "$vout" != "" ]; then
413		msg="Validation errors in $NET_INSTALL_FMRI:\n$vout"
414		net_record_err "$msg" 0
415		return $SMF_EXIT_ERR_CONFIG
416	fi
417
418	ecode=$SMF_EXIT_OK
419	errs=0
420	ifcnt=0
421	for intf in $NET_V4IF $NET_V6IF
422	do
423		pg=`$SVCPROP -p $intf $NET_INSTALL_FMRI`
424		if [ $? -eq 0 ]; then
425			if service_is_enabled $NET_NWAM_FMRI; then
426				msg="NWAM enabled. Install static "
427				msg=$msg"configuration ignored."
428				net_record_err "$msg" 0
429				errs=`expr $errs + 1`
430				ecode=$SMF_EXIT_ERR_CONFIG
431			else
432				if [ "$intf" == "$NET_V4IF" ]; then
433					net_process_v4_pg
434				else
435					net_process_v6_pg
436				fi
437				if [ $? -ne $SMF_EXIT_OK ]; then
438					#
439				    	# Last error wins.
440					#
441					ecode=$?
442					errs=`expr $errs + 1`
443				else
444					ifcnt=`expr $ifcnt + 1`
445				fi
446			fi
447			$SVCCFG -s $NET_INSTALL_FMRI delpg $intf
448			$SVCCFG -s $NET_INSTALL_FMRI refresh
449		fi
450	done
451
452 	if [ $net_install_debug -eq 1 ]; then
453		if [ $errs -ne 0 ]; then
454			echo "$errs errors encountered" \
455			    "configuring interfaces on behalf of install"
456		fi
457
458		if [ $ifcnt -ne 0 ]; then
459			echo "$ifcnt interfaces configured on" \
460			    "behalf of install"
461		fi
462	fi
463
464	return $ecode
465}
466
467#
468# The network/install service will be enabled by the install derived profile
469# after the intial install. The service will disable itself after processing
470# the install defined property values.
471#
472# When the non-global shared-IP stack zone boots, it tries to bring up this
473# service as well. We just want to exit successfully.
474#
475if smf_is_nonglobalzone; then
476	if [ `/sbin/zonename -t` = shared ]; then
477		$SVCADM disable $NET_INSTALL_FMRI
478		exit $SMF_EXIT_OK
479	fi
480fi
481
482net_process_install || exit $?
483
484$SVCADM disable $NET_INSTALL_FMRI
485exit $SMF_EXIT_OK
486