diff options
author | Mark Haywood <Mark.Haywood@Oracle.COM> | 2010-07-27 20:35:25 -0400 |
---|---|---|
committer | Mark Haywood <Mark.Haywood@Oracle.COM> | 2010-07-27 20:35:25 -0400 |
commit | 9b5bf10ab04b9be5564d70a57980cfb68b6372e7 (patch) | |
tree | 4eb6a11161f8b5338c1411a51a71cd00004c3ca1 /usr/src/cmd | |
parent | ae3d7f90695ef456a6da4f7bdccd448ebe0b99e1 (diff) | |
download | illumos-joyent-9b5bf10ab04b9be5564d70a57980cfb68b6372e7.tar.gz |
PSARC/2010/164 interfaces for basic install network configuration
6923163 Automated Install requires mechanism for configuring static IP addresses
6923168 Automated Install requires a mechanism for configuring name services for clients
Diffstat (limited to 'usr/src/cmd')
-rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h | 9 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c | 85 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_util.c | 88 | ||||
-rw-r--r-- | usr/src/cmd/svc/milestone/Makefile | 5 | ||||
-rw-r--r-- | usr/src/cmd/svc/milestone/net-install | 485 | ||||
-rw-r--r-- | usr/src/cmd/svc/milestone/net-routing-setup | 20 | ||||
-rw-r--r-- | usr/src/cmd/svc/milestone/network-install.xml | 246 | ||||
-rw-r--r-- | usr/src/cmd/svc/shell/net_include.sh | 14 |
8 files changed, 943 insertions, 9 deletions
diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h index 36768b5ae0..4388c29971 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_impl.h @@ -45,6 +45,7 @@ extern void ipmgmt_handler(void *, char *, size_t, door_desc_t *, uint_t); /* ipmgmt_util.c */ extern void ipmgmt_log(int, const char *, ...); +extern int ipmgmt_cpfile(const char *, const char *, boolean_t); /* ipmgmt_persist.c */ @@ -137,8 +138,16 @@ extern ipmgmt_aobjmap_list_t aobjmap; * in-memory copy of list `aobjmap' on disk. This is done to recover from * daemon reboot (using svcadm) or crashes. */ +#define IPADM_TMPFS_DIR "/etc/svc/volatile/ipadm" #define ADDROBJ_MAPPING_DB_FILE IPADM_TMPFS_DIR"/aobjmap.conf" +/* + * A temporary copy of the ipadm configuration file might need + * to be created if write requests are encountered during boottime + * and the root filesystem is mounted read-only. + */ +#define IPADM_VOL_DB_FILE IPADM_TMPFS_DIR"/ipadm.conf" + extern int ipmgmt_db_walk(db_wfunc_t *, void *, ipadm_db_op_t); extern int ipmgmt_aobjmap_op(ipmgmt_aobjmap_t *, uint32_t); extern boolean_t ipmgmt_aobjmap_init(void *, nvlist_t *, char *, diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c index 25e2f3a5ee..e316f888a2 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c @@ -69,6 +69,9 @@ extern pthread_rwlock_t ipmgmt_dbconf_lock; +/* signifies whether volatile copy of data store is in use */ +static boolean_t ipmgmt_rdonly_root = B_FALSE; + /* * Checks if the database nvl, `db_nvl' contains and matches ALL of the passed * in private nvpairs `proto', `ifname' & `aobjname'. @@ -358,8 +361,49 @@ ipmgmt_db_getaddr(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, } /* + * This function only gets called if a volatile filesystem version + * of the configuration file has been created. This only happens in the + * extremely rare case that a request has been made to update the configuration + * file at boottime while the root filesystem was read-only. This is + * really a rare occurrence now that we don't support UFS root filesystems + * any longer. This function will periodically attempt to write the + * configuration back to its location on the root filesystem. Success + * will indicate that the filesystem is no longer read-only. + */ +/* ARGSUSED */ +static void * +ipmgmt_db_restore_thread(void *arg) +{ + int err; + + for (;;) { + (void) sleep(5); + (void) pthread_rwlock_wrlock(&ipmgmt_dbconf_lock); + if (!ipmgmt_rdonly_root) + break; + err = ipmgmt_cpfile(IPADM_VOL_DB_FILE, IPADM_DB_FILE, B_FALSE); + if (err == 0) { + ipmgmt_rdonly_root = B_FALSE; + break; + } + (void) pthread_rwlock_unlock(&ipmgmt_dbconf_lock); + } + (void) pthread_rwlock_unlock(&ipmgmt_dbconf_lock); + return (NULL); +} + +/* * This function takes the appropriate lock, read or write, based on the - * `db_op' and then calls DB walker ipadm_rw_db(). + * `db_op' and then calls DB walker ipadm_rw_db(). The code is complicated + * by the fact that we are not always guaranteed to have a writable root + * filesystem since it is possible that we are reading or writing during + * bootime while the root filesystem is still read-only. This is, by far, + * the exception case. Normally, this function will be called when the + * root filesystem is writable. In the unusual case where this is not + * true, the configuration file is copied to the volatile file system + * and is updated there until the root filesystem becomes writable. At + * that time the file will be moved back to its proper location by + * ipmgmt_db_restore_thread(). */ extern int ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op) @@ -367,9 +411,9 @@ ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op) int err; boolean_t writeop; mode_t mode; + pthread_t tid; writeop = (db_op != IPADM_DB_READ); - if (writeop) { (void) pthread_rwlock_wrlock(&ipmgmt_dbconf_lock); mode = IPADM_FILE_MODE; @@ -378,7 +422,42 @@ ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op) mode = 0; } - err = ipadm_rw_db(db_walk_func, db_warg, IPADM_DB_FILE, mode, db_op); + /* + * Did a previous write attempt fail? If so, don't even try to + * read/write to IPADM_DB_FILE. + */ + if (!ipmgmt_rdonly_root) { + err = ipadm_rw_db(db_walk_func, db_warg, IPADM_DB_FILE, + mode, db_op); + if (err != EROFS) + goto done; + } + + /* + * If we haven't already copied the file to the volatile + * file system, do so. This should only happen on a failed + * writeop(i.e., we have acquired the write lock above). + */ + if (access(IPADM_VOL_DB_FILE, F_OK) != 0) { + assert(writeop); + err = ipmgmt_cpfile(IPADM_DB_FILE, IPADM_VOL_DB_FILE, B_TRUE); + if (err != 0) + goto done; + err = pthread_create(&tid, NULL, ipmgmt_db_restore_thread, + NULL); + if (err != 0) { + (void) unlink(IPADM_VOL_DB_FILE); + goto done; + } + ipmgmt_rdonly_root = B_TRUE; + } + + /* + * Read/write from the volatile copy. + */ + err = ipadm_rw_db(db_walk_func, db_warg, IPADM_VOL_DB_FILE, + mode, db_op); +done: (void) pthread_rwlock_unlock(&ipmgmt_dbconf_lock); return (err); } diff --git a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_util.c b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_util.c index 8ef9a09e3d..704dab2d36 100644 --- a/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_util.c +++ b/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_util.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -33,8 +32,12 @@ #include <stdio.h> #include <syslog.h> #include <stdarg.h> +#include <unistd.h> +#include <errno.h> #include "ipmgmt_impl.h" +#define IPMGMT_BUFSIZ 1024 + void ipmgmt_log(int pri, const char *fmt, ...) { @@ -44,3 +47,84 @@ ipmgmt_log(int pri, const char *fmt, ...) vsyslog(pri, fmt, alist); va_end(alist); } + +/* + * Copy a source file to a new destination. The source file will be + * removed if rdonly is false (i.e., used when the source file resides + * on a read-only file system). + * + * Returns 0 on success and errno on failure. + */ +int +ipmgmt_cpfile(const char *src, const char *dst, boolean_t rdonly) +{ + struct stat statbuf; + FILE *sfp, *dfp; + char buf[IPMGMT_BUFSIZ]; + size_t bytes; + int err = 0; + + /* + * Attempt to open the destination file first since we + * want to optimize for the case where it is read-only + * and will return EROFS. + */ + if ((dfp = fopen(dst, "w+")) == NULL) + return (errno); + + /* + * Require that the source file exists. + */ + if (stat(src, &statbuf) != 0) { + err = errno; + (void) fclose(dfp); + return (err); + } + if ((sfp = fopen(src, "r")) == NULL) { + err = errno; + (void) fclose(dfp); + return (err); + } + + /* + * Copy the file. + */ + while (((bytes = fread(buf, 1, sizeof (buf), sfp)) != 0) && + (errno == 0)) { + (void) fwrite(buf, bytes, 1, dfp); + if (errno != 0) + break; + } + if (errno != 0) + err = errno; + + (void) fclose(sfp); + (void) fclose(dfp); + + /* + * If any error occurred, then remove the destination file. + */ + if (err != 0) { + (void) unlink(dst); + return (err); + } + + /* + * Make sure the file attributes are correct. + */ + if (chmod(dst, IPADM_FILE_MODE) != 0 || + chown(dst, UID_NETADM, GID_NETADM) != 0) { + err = errno; + (void) unlink(dst); + return (err); + } + + /* + * If the source file does not reside on a read-only file system + * then remove it. + */ + if (!rdonly) + (void) unlink(src); + + return (0); +} diff --git a/usr/src/cmd/svc/milestone/Makefile b/usr/src/cmd/svc/milestone/Makefile index a509f39970..52579a3af4 100644 --- a/usr/src/cmd/svc/milestone/Makefile +++ b/usr/src/cmd/svc/milestone/Makefile @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. # include ../../Makefile.cmd @@ -40,6 +39,7 @@ FSMANIFESTS= $(FSSVCS:%=$(ROOTSVCSYSTEMFILESYSTEM)/%) NETSVCS= \ network-initial.xml \ + network-install.xml \ network-iptun.xml \ network-ipqos.xml \ network-location.xml \ @@ -112,6 +112,7 @@ SVCMETHOD=\ net-loc \ net-loopback \ net-init \ + net-install \ net-iptun \ net-ipqos \ net-netmask \ diff --git a/usr/src/cmd/svc/milestone/net-install b/usr/src/cmd/svc/milestone/net-install new file mode 100644 index 0000000000..c2e6d1506b --- /dev/null +++ b/usr/src/cmd/svc/milestone/net-install @@ -0,0 +1,485 @@ +#!/sbin/sh +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +. /lib/svc/share/smf_include.sh +. /lib/svc/share/net_include.sh + +IPADM=/sbin/ipadm +SVCCFG=/usr/sbin/svccfg +SVCPROP=/usr/bin/svcprop +SVCADM=/usr/sbin/svcadm +ROUTE=/sbin/route + +NET_NWAM_FMRI="svc:/network/physical:nwam" +NET_INSTALL_FMRI=$SMF_FMRI + +NET_V4IF=install_ipv4_interface +NET_V6IF=install_ipv6_interface + +NET_UNDEFINED_STRING_PROP="\"\"" + +net_install_debug=0 + +unset net_install_name net_install_addrtype net_install_addr \ + net_install_dhcpwait net_install_interface_id \ + net_install_stateless net_install_stateful net_install_route + +net_configure_install_if() +{ + ipv6_interface=$1 + + case $net_install_addrtype in + static) + cmd="$IPADM create-addr -T static " + cmd=$cmd"-a local=$net_install_addr $net_install_name" + ;; + + dhcp) + dhcpwait="" + if [ "$net_install_dhcpwait" != "" ]; then + dhcpwait="-w $net_install_dhcpwait" + fi + + cmd="$IPADM create-addr -T dhcp $dhcpwait $net_install_name" + ;; + addrconf) + interface_id="" + if [ "$net_install_interface_id" != "" ]; then + interface_id="-i $net_install_interface_id" + fi + + state="" + if [ "$net_install_stateless" != "" ]; then + state="-p stateless=$net_install_stateless" + fi + + if [ "$net_install_stateful" != "" ]; then + if [ "$state" = "" ]; then + state="-p stateful=$net_install_stateful" + else + state=$state",stateful=$net_install_stateful" + fi + fi + + cmd="$IPADM create-addr -T addrconf " + cmd=$cmd"$interface_id $state $net_install_name" + ;; + esac + + $cmd + if [ $? -ne 0 ]; then + net_record_err "Error configuring interface:\n\"$cmd\"" $? + return $SMF_EXIT_ERR_FATAL + fi + + if [ "$net_install_route" != "" ]; then + if [ $ipv6_interface == 1 ]; then + details="-inet6 default" + else + details="default" + fi + ifp=`echo $net_install_name | /usr/bin/cut -f1 -d'/'` + details="$details $net_install_route -ifp $ifp" + cmd="$ROUTE add $details" + $cmd + cmd="$ROUTE get $details" + $cmd + if [ $? -ne 0 ]; then + err=$? + msg="Error creating default route:\n\"$cmd\"" + net_record_err "$msg" $err + return $SMF_EXIT_ERR_FATAL + fi + rootdir=/etc/svc/volatile + /usr/bin/mkdir -p $rootdir/etc/inet + if [ $? -ne 0 ]; then + err=$? + msg="Error creating \"$rootdir/etc/inet\" directory" + net_record_err "$msg" $err + return $SMF_EXIT_ERR_FATAL + fi + cmd="$ROUTE -R $rootdir -p add $details" + $cmd + if [ $? -ne 0 ]; then + err=$? + msg="Error adding persistent default route:\n\"$cmd\"" + net_record_err "$msg" $err + return $SMF_EXIT_ERR_FATAL + fi + fi + + return $SMF_EXIT_OK +} + +net_process_v4_pg() +{ + net_install_name="" + net_install_addrtype="" + net_install_addr="" + net_install_dhcpwait="" + net_install_route="" + + # + # Retrieve the mandatory interface name property value. If + # the value is empty, then no interface is configured. + # + prop=`$SVCPROP -p $NET_V4IF/name $NET_INSTALL_FMRI` + if [ $? -ne 0 -o "$prop" = "$NET_UNDEFINED_STRING_PROP" ]; then + return $SMF_EXIT_OK + fi + net_install_name=$prop + + # + # Retrieve the mandatory address type property value. The two + # valid values are "static" and "dhcp". + # + prop=`$SVCPROP -p $NET_V4IF/address_type $NET_INSTALL_FMRI` + if [ $? -ne 0 -o "$prop" = "$NET_UNDEFINED_STRING_PROP" ]; then + msg="No \"address_type\" property defined in the " + msg=$msg"\"$NET_V4IF\" property group" + net_record_err "$msg" 0 + return $SMF_EXIT_ERR_CONFIG + fi + case $prop in + static | dhcp) + net_install_addrtype=$prop + ;; + *) + msg="Bad value, \"$prop\", defined for the \"address_type\" " + msg=$msg"property in the \"$NET_V4IF\" property group" + net_record_err "$msg" 0 + return $SMF_EXIT_ERR_CONFIG + ;; + esac + + # + # Retrieve the static address property value. The address property + # only applies to static address type configurations. If not + # configuring a static address, then the property should still have + # its default value of 0.0.0.0/0. + # + prop=`$SVCPROP -p $NET_V4IF/static_address $NET_INSTALL_FMRI` + if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then + if [ "$net_install_addrtype" = "dhcp" ]; then + if [ "$prop" != "${NET_INADDR_ANY}/0" ]; then + msg="Warning: static address ignored " + msg=$msg"in the \"$NET_V4IF\ property group" + net_record_err "$msg" 0 + fi + else + if [ "$prop" = "${NET_INADDR_ANY}/0" ]; then + msg="Error: static address required in the " + msg=$msg"\"$NET_V4IF\" property group" + net_record_err "$msg" 0 + return $SMF_EXIT_ERR_CONFIG + fi + net_install_addr=$prop + fi + else + if [ "$net_install_addrtype" = "static" ]; then + msg="Error: static address required in the " + msg=$msg"\"$NET_V4IF\" property group" + net_record_err "$msg" 0 + return $SMF_EXIT_ERR_CONFIG + fi + fi + + # + # Retrieve the optional DHCP wait property value. + # + prop=`$SVCPROP -p $NET_V4IF/dhcp_wait $NET_INSTALL_FMRI` + if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then + if [ "$net_install_addrtype" != "dhcp" ]; then + if [ "$prop" != "120" ]; then + msg="Warning: DHCP wait value ignored in the " + msg=$msg"\"$NET_V4IF\" property group" + net_record_err "$msg" 0 + fi + else + net_install_dhcpwait=$prop + fi + fi + + # + # Retrieve the optional default route property value. + # + prop=`$SVCPROP -p $NET_V4IF/default_route $NET_INSTALL_FMRI` + if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then + if [ "$prop" != "$NET_INADDR_ANY" ]; then + net_install_route=$prop + fi + fi + + net_configure_install_if 0 + + return $? +} + +net_process_v6_pg() +{ + net_install_name="" + net_install_addrtype="" + net_install_addr="" + net_install_stateless="" + net_install_stateful="" + net_install_interface_id="" + net_install_route="" + + # + # Retrieve the mandatory interface name property value. If + # the value is empty, then no interface is configured. + # + prop=`$SVCPROP -p $NET_V6IF/name $NET_INSTALL_FMRI` + if [ $? -ne 0 -o "$prop" = "$NET_UNDEFINED_STRING_PROP" ]; then + return $SMF_EXIT_OK + fi + net_install_name=$prop + + # + # Retrieve the mandatory address type property value. The two + # valid values are "static" and "addrconf". + # + prop=`$SVCPROP -p $NET_V6IF/address_type $NET_INSTALL_FMRI` + if [ $? -ne 0 -o "$prop" = "$NET_UNDEFINED_STRING_PROP" ]; then + msg="No \"address_type\" property defined in the " + msg=$msg"\"$NET_V6IF\" property group" + net_record_err "$msg" 0 + return $SMF_EXIT_ERR_CONFIG + fi + case $prop in + static | addrconf) + net_install_addrtype=$prop + ;; + *) + msg="Bad value \"$prop\" defined for \"address_type\"" + net_record_err "$msg" 0 + return $SMF_EXIT_ERR_CONFIG + ;; + esac + + # + # Retrieve the static address property value. The address property + # only applies to static address type configurations. If not + # configuring a static address, then the property should still have + # its default value of ::0/0. + # + prop=`$SVCPROP -p $NET_V6IF/static_address $NET_INSTALL_FMRI` + if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then + if [ "$net_install_addrtype" = "addrconf" ]; then + if [ "$prop" != "${NET_IN6ADDR_ANY_INIT}/0" ]; then + msg="Warning: static address ignored in the " + msg=$msg"\"$NET_V6IF\" property group" + net_record_err "$msg" 0 + fi + else + if [ "$prop" = "${NET_IN6ADDR_ANY_INIT}/0" ]; then + msg="Error: static address required in the " + msg=$msg"\"$NET_V6IF\" property group" + net_record_err "$msg" 0 + return $SMF_EXIT_ERR_CONFIG + fi + net_install_addr=$prop + fi + else + if [ "$net_install_addrtype" = "static" ]; then + msg="Error: static address required in the " + msg=$msg"\"$NET_V6IF\" property group" + net_record_err "$msg" 0 + return $SMF_EXIT_ERR_CONFIG + fi + + fi + + # + # Retrieve the optional interface id property value. The + # property only applies to addrconf address type configurations. + # If configuring a static address, then the property should still + # have its default value of ::0/0. + # + prop=`$SVCPROP -p $NET_V6IF/interface_id $NET_INSTALL_FMRI` + if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then + if [ "$prop" != "${NET_IN6ADDR_ANY_INIT}/0" ]; then + if [ "$net_install_addrtype" != "addrconf" ]; then + msg="Warning: interface id value ignored in " + msg=$msg"the \"$NET_V6IF\" property group" + net_record_err "$msg" 0 + else + net_install_interface_id=$prop + fi + fi + fi + + # + # Retrieve the optional stateless property value. The property + # only applies to addrconf address type configurations. If + # configuring a static address, then the property should still + # have its default value of "yes". + # + prop=`$SVCPROP -p $NET_V6IF/stateless $NET_INSTALL_FMRI` + if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then + case $prop in + yes) + net_install_stateless=$prop + ;; + no) + if [ "$net_install_addrtype" != "addrconf" ]; then + msg="Warning: stateless value ignored in the " + msg=$msg"\"$NET_V6IF\" property group" + net_record_err "$msg" 0 + else + net_install_stateless=$prop + fi + ;; + *) + msg="Bad value \"$prop\" defined for the \"stateless\"" + msg=$msg" property in the \"$NET_V6IF\" property group" + net_record_err "$msg" 0 + return $SMF_EXIT_ERR_CONFIG + ;; + esac + fi + + # + # Retrieve the optional stateful property value. The property + # only applies to addrconf address type configurations. If + # configuring a static address, then the property should still + # have its default value of "yes". + # + prop=`$SVCPROP -p $NET_V6IF/stateful $NET_INSTALL_FMRI` + if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then + case $prop in + yes) + net_install_stateful=$prop + ;; + no) + if [ "$net_install_addrtype" != "addrconf" ]; then + msg="Warning: stateless value ignored in the " + msg=$msg"\"$NET_V6IF\" property group" + net_record_err "$msg" 0 + else + net_install_stateful=$prop + fi + ;; + *) + msg="Bad value \"$prop\" defined for the \"stateless\"" + msg=$msg" property in the \"$NET_V6IF\" property group" + net_record_err "$msg" 0 + return $SMF_EXIT_ERR_CONFIG + ;; + esac + fi + + # + # Retrieve the optional default route property value. + # + prop=`$SVCPROP -p $NET_V6IF/default_route $NET_INSTALL_FMRI` + if [ $? -eq 0 -a "$prop" != "$NET_UNDEFINED_STRING_PROP" ]; then + if [ "$prop" != "$NET_IN6ADDR_ANY_INIT" ]; then + net_install_route=$prop + fi + fi + + net_configure_install_if 1 + + return $? +} + +net_process_install() +{ + vout=`$SVCCFG -s $NET_INSTALL_FMRI validate 2>&1` + if [ "$vout" != "" ]; then + msg="Validation errors in $NET_INSTALL_FMRI:\n$vout" + net_record_err "$msg" 0 + return $SMF_EXIT_ERR_CONFIG + fi + + ecode=$SMF_EXIT_OK + errs=0 + ifcnt=0 + for intf in $NET_V4IF $NET_V6IF + do + pg=`$SVCPROP -p $intf $NET_INSTALL_FMRI` + if [ $? -eq 0 ]; then + if service_is_enabled $NET_NWAM_FMRI; then + msg="NWAM enabled. Install static " + msg=$msg"configuration ignored." + net_record_err "$msg" 0 + errs=`expr $errs + 1` + ecode=$SMF_EXIT_ERR_CONFIG + else + if [ "$intf" == "$NET_V4IF" ]; then + net_process_v4_pg + else + net_process_v6_pg + fi + if [ $? -ne $SMF_EXIT_OK ]; then + # + # Last error wins. + # + ecode=$? + errs=`expr $errs + 1` + else + ifcnt=`expr $ifcnt + 1` + fi + fi + $SVCCFG -s $NET_INSTALL_FMRI delpg $intf + $SVCCFG -s $NET_INSTALL_FMRI refresh + fi + done + + if [ $net_install_debug -eq 1 ]; then + if [ $errs -ne 0 ]; then + echo "$errs errors encountered" \ + "configuring interfaces on behalf of install" + fi + + if [ $ifcnt -ne 0 ]; then + echo "$ifcnt interfaces configured on" \ + "behalf of install" + fi + fi + + return $ecode +} + +# +# The network/install service will be enabled by the install derived profile +# after the intial install. The service will disable itself after processing +# the install defined property values. +# +# When the non-global shared-IP stack zone boots, it tries to bring up this +# service as well. We just want to exit successfully. +# +if smf_is_nonglobalzone; then + if [ `/sbin/zonename -t` = shared ]; then + $SVCADM disable $NET_INSTALL_FMRI + exit $SMF_EXIT_OK + fi +fi + +net_process_install || exit $? + +$SVCADM disable $NET_INSTALL_FMRI +exit $SMF_EXIT_OK diff --git a/usr/src/cmd/svc/milestone/net-routing-setup b/usr/src/cmd/svc/milestone/net-routing-setup index 663b537774..6ab1a6c7f0 100644 --- a/usr/src/cmd/svc/milestone/net-routing-setup +++ b/usr/src/cmd/svc/milestone/net-routing-setup @@ -20,8 +20,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. # This script configures IP routing. @@ -185,6 +184,23 @@ else fi # +# See if static routes were created by install. If so, they were created +# under /etc/svc/volatile. Copy them into their proper place. +# +if [ -f /etc/svc/volatile/etc/inet/static_routes ]; then + echo "Installing persistent routes" + if [ -f /etc/inet/static_routes ]; then + cat /etc/svc/volatile/etc/inet/static_routes | grep -v '^#' \ + >> /etc/inet/static_routes + else + cp /etc/svc/volatile/etc/inet/static_routes \ + /etc/inet/static_routes + fi + /usr/bin/rm /etc/svc/volatile/etc/inet/static_routes + +fi + +# # Read /etc/inet/static_routes and add each route. # if [ -f /etc/inet/static_routes ]; then diff --git a/usr/src/cmd/svc/milestone/network-install.xml b/usr/src/cmd/svc/milestone/network-install.xml new file mode 100644 index 0000000000..69e49986f4 --- /dev/null +++ b/usr/src/cmd/svc/milestone/network-install.xml @@ -0,0 +1,246 @@ +<?xml version="1.0"?> +<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1"> +<!-- + Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + + CDDL HEADER START + + The contents of this file are subject to the terms of the + Common Development and Distribution License (the "License"). + You may not use this file except in compliance with the License. + + You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + or http://www.opensolaris.org/os/licensing. + See the License for the specific language governing permissions + and limitations under the License. + + When distributing Covered Code, include this CDDL HEADER in each + file and include the License file at usr/src/OPENSOLARIS.LICENSE. + If applicable, add the following below this CDDL HEADER, with the + fields enclosed by brackets "[]" replaced with your own identifying + information: Portions Copyright [yyyy] [name of copyright owner] + + CDDL HEADER END + + NOTE: This service manifest is not editable; its contents will + be overwritten by package or patch operations, including + operating system upgrade. Make customizations in a different + file. +--> + +<service_bundle type='manifest' name='SUNWcsr:network-install'> + +<service + name='network/install' + type='service' + version='1'> + + <create_default_instance enabled='false' /> + + <single_instance /> + + <dependency + name='ipmgmt' + grouping='require_all' + restart_on='none' + type='service'> + <service_fmri value='svc:/network/ip-interface-management' /> + </dependency> + + <dependent name='physical_default' + grouping='optional_all' + restart_on='none'> + <service_fmri value='svc:/network/physical:default' /> + </dependent> + + <exec_method + type='method' + name='start' + exec='/lib/svc/method/net-install' + timeout_seconds='600' /> + + <exec_method + type='method' + name='stop' + exec=':true' + timeout_seconds='0' /> + + <property_group name='startd' type='framework'> + <propval name='duration' type='astring' value='transient' /> + </property_group> + + <!-- The following property group is used only at install time to + configure an initial IPv4 network interface --> + <property_group name='install_ipv4_interface' type='application'> + <propval name='name' type='astring' value='' /> + <propval name='address_type' type='astring' value='static' /> + <propval name='static_address' type='net_address_v4' + value='0.0.0.0/0' /> + <propval name='dhcp_wait' type='astring' value='120' /> + <propval name='default_route' type='net_address_v4' + value='0.0.0.0' /> + </property_group> + + <!-- The following property group is used only at install time to + configure an initial IPv6 network interface --> + <property_group name='install_ipv6_interface' type='application'> + <propval name='name' type='astring' value='' /> + <propval name='address_type' type='astring' value='addrconf' /> + <propval name='static_address' type='net_address_v6' + value='::0/0' /> + <propval name='interface_id' type='net_address_v6' + value='::0/0' /> + <propval name='stateless' type='astring' value='yes' /> + <propval name='stateful' type='astring' value='yes'/> + <propval name='default_route' type='net_address_v6' + value='::0' /> + </property_group> + + <stability value='Unstable' /> + + <template> + <common_name> + <loctext xml:lang='C'> + physical network interfaces install + </loctext> + </common_name> + <documentation> + <manpage title='ipadm' section='1M' + manpath='/usr/share/man' /> + </documentation> + <pg_pattern name='install_ipv4_interface' type='application' + target='this' required='false'> + <description> <loctext xml:lang='C'> + Install derived configuration data used to configure an initial IPv4 physical interface. + </loctext> </description> + <prop_pattern name='name' type='astring' + required='true'> + <description> <loctext xml:lang='C'> + The "addrobj" value to be passed to the ipadm(1M) "create-addr" command. + </loctext> </description> + <cardinality min='1' max='1'/> + </prop_pattern> + <prop_pattern name='address_type' type='astring' + required='true'> + <description> <loctext xml:lang='C'> + The "-T" option value to be passed to the ipadm(1M) "create-addr" command. + </loctext> </description> + <cardinality min='1' max='1'/> + <constraints> + <value name='static'> + <description> <loctext xml:lang='C'> + Signifies that the IPv4 interface will be configured with a static address defined by the "static_address" property. + </loctext> </description> + </value> + <value name='dhcp'> + <description> <loctext xml:lang='C'> + Signifies that the IPv4 interface will be configured by DHCP. The "static_address" property will be ignored. + </loctext> </description> + </value> + </constraints> + </prop_pattern> + <prop_pattern name='static_address' + type='net_address_v4' required='false'> + <description> <loctext xml:lang='C'> + The "local" address value to be passed to the ipadm(1M) "create-addr" command. Only required if "address_type" has a value of "static". + </loctext> </description> + <cardinality min='1' max='1'/> + </prop_pattern> + <prop_pattern name='dhcp_wait' type='astring' + required='false'> + <description> <loctext xml:lang='C'> + The "-w" option value to be passed to the ipadm(1M) "create-addr" command. Represents the maximum time to wait for DHCP offer. + </loctext> </description> + <units> + <loctext xml:lang='C'>seconds</loctext> + </units> + <cardinality min='1' max='1'/> + </prop_pattern> + <prop_pattern name='default_route' + type='net_address_v4' required='false'> + <description> <loctext xml:lang='C'> + The default route associated with this interface. Used to add a default route using route(1M). + </loctext> </description> + <cardinality min='1' max='1'/> + </prop_pattern> + </pg_pattern> + <pg_pattern name='install_ipv6_interface' type='application' + target='this' required='false'> + <description> <loctext xml:lang='C'> + Install derived configuration data used to configure an initial IPv6 physical interface. + </loctext> </description> + <prop_pattern name='name' type='astring' + required='true'> + <description> <loctext xml:lang='C'> + The "addrobj" value to be passed to the ipadm(1M) "create-addr" command. + </loctext> </description> + <cardinality min='1' max='1'/> + </prop_pattern> + <prop_pattern name='address_type' type='astring' + required='true'> + <description> <loctext xml:lang='C'> + The "-T" option value to be passed to the ipadm(1M) "create-addr" command. + </loctext> </description> + <cardinality min='1' max='1'/> + <constraints> + <value name='static'> + <description> <loctext xml:lang='C'> + Signifies that the IPv4 interface will be configured with a static address defined by the "static_address" property. + </loctext> </description> + </value> + <value name='addrconf'> + <description> <loctext xml:lang='C'> + Signifies that the IPv6 interface will be configured by IPv6 auto-configuration. The "static_address" property will be ignored. + </loctext> </description> + </value> + </constraints> + </prop_pattern> + <prop_pattern name='static_address' + type='net_address_v6' required='false'> + <description> <loctext xml:lang='C'> + The "local" address value to be passed to the ipadm(1M) "create-addr" command. Only required if "address_type" has a value of "static". + </loctext> </description> + <cardinality min='1' max='1'/> + </prop_pattern> + <prop_pattern name='interface_id' + type='net_address_v6' required='false'> + <description> <loctext xml:lang='C'> + The "-i" token value to be passed to the ipadm(1M) "create-addr" command. Ignored if "address_type" has a value of "static". + </loctext> </description> + <cardinality min='1' max='1'/> + </prop_pattern> + + <prop_pattern name='stateless' + type='astring' required='false'> + <description> <loctext xml:lang='C'> + The "stateless" value to be passed to the ipadm(1M) "create-addr" command. Ignored if "address_type" has a value of "static". + </loctext> </description> + <cardinality min='1' max='1'/> + <constraints> + <value name='yes'/> + <value name='no'/> + </constraints> + </prop_pattern> + <prop_pattern name='stateful' + type='astring' required='false'> + <description> <loctext xml:lang='C'> + The "stateful" value to be passed to the ipadm(1M) "create-addr" command. Ignored if "address_type" has a value of "static". + </loctext> </description> + <cardinality min='1' max='1'/> + <constraints> + <value name='yes'/> + <value name='no'/> + </constraints> + </prop_pattern> + <prop_pattern name='default_route' + type='net_address_v6' required='false'> + <description> <loctext xml:lang='C'> + The default route associated with this interface. Used to add a default route using route(1M). + </loctext> </description> + <cardinality min='1' max='1'/> + </prop_pattern> + </pg_pattern> + </template> +</service> + +</service_bundle> diff --git a/usr/src/cmd/svc/shell/net_include.sh b/usr/src/cmd/svc/shell/net_include.sh index 2c08eeda1f..cac56873f8 100644 --- a/usr/src/cmd/svc/shell/net_include.sh +++ b/usr/src/cmd/svc/shell/net_include.sh @@ -26,6 +26,9 @@ # All rights reserved. # +NET_INADDR_ANY="0.0.0.0" +NET_IN6ADDR_ANY_INIT="::0" + # Print warnings to console warn_failed_ifs() { echo "Failed to $1 interface(s):$2" >/dev/msglog @@ -44,6 +47,17 @@ shcat() { done } +net_record_err() +{ + message=$1 + err=$2 + + echo "$message" | smf_console + if [ $err -ne 0 ]; then + echo "Error code = $err" | smf_console + fi +} + # # inet_list list of IPv4 interfaces. # inet6_list list of IPv6 interfaces. |