#!/usr/sbin/sh # # Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T. # All rights reserved. # # # Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. # . /lib/svc/share/smf_include.sh . /lib/svc/share/net_include.sh # Make sure that the libraries essential to this stage of booting can be found. LD_LIBRARY_PATH=/lib; export LD_LIBRARY_PATH # # If DHCP was used on a primary interface then set the hostname # that was returned. If no hostname was returned, set the name # to be "unknown". The hostname must be set to something, because # tooltalk will hang unless the name can be locally resolved. # Sendmail also requires the name to be resolvable locally. # # For non-global zones, fall back to the `uname -n` value provided by the # kernel if svc:/system/identity:node config/nodename does not have a value, # as is expected on an initial boot. # SVCCFG=/usr/sbin/svccfg SVCADM=/usr/sbin/svcadm SVCPROP=/usr/bin/svcprop SVC=svc:/system/identity:node SVC_NODENAME=config/nodename SVC_IGNORE_DHCP=config/ignore_dhcp_hostname SVC_LOOPBACK=config/loopback SVC_ENABLE_MAPPING=config/enable_mapping SVC_HOSTNAME=private_data/mapped_hostname SVC_ADDRESSES=private_data/mapped_addresses NI_SVC=svc:/network/install:default NI_SVC_APPLIED=config/applied NI_SVC_V4_ADDROBJ=install_ipv4_interface/name NI_SVC_V6_ADDROBJ=install_ipv6_interface/name NAWK=/usr/bin/nawk GREP=/usr/bin/grep PATH=/usr/bin:/usr/sbin HOSTS=/etc/inet/hosts # Retrieve property values related to hosts(4) updates MAP_NODENAME=$($SVCPROP -p $SVC_ENABLE_MAPPING $SVC) [[ "$MAP_NODENAME" = '""' ]] && MAP_NODENAME="true" MAPPED_ADDRESSES=$($SVCPROP -p $SVC_ADDRESSES $SVC) [[ "$MAPPED_ADDRESSES" = '""' || "$MAPPED_ADDRESSES" = "0.0.0.0" ]] && \ MAPPED_ADDRESSES="" MAPPED_HOSTNAME=$($SVCPROP -p $SVC_HOSTNAME $SVC) [[ "$MAPPED_HOSTNAME" = '""' ]] && MAPPED_HOSTNAME="" LOOPBACK_PROP=$($SVCPROP -p $SVC_LOOPBACK $SVC) [[ "$LOOPBACK_PROP" = '""' ]] && LOOPBACK_PROP="" # # Modify hosts(4) entries. # # This function takes three arguments: # modify_action: "add" or "remove" # modify_address: the IP address to be added or removed # modify_host: the host entry from which the IP address is to # be added or removed # # When an entry is added: # 1) If the host entry does not already exist, then it is created # 2) If the host entry already exists, then the IP address is inserted # as the first IP address for the host entry # # When an entry is removed: # 1) If there is more than one IP address mapped to the host entry, # then the entry is modified in place # 2) If removing the IP address leaves the host with no IP addresses # mapped, then the host entry is deleted # modify_hosts() { export modify_action=$1 export modify_address=$2 export modify_host=$3 $NAWK <$HOSTS >$HOSTS.$$ ' function writeit(action, ip, host) { c=split($0, s); if (action == "remove" && s[1] == ip) { if (NF == 2 && s[2] == host) return; printf("%s ", s[1]); for (n=2; n<=c; ++n) { if (s[n] != host) printf("%s ", s[n]); } printf("\n"); return; } if (s[1] == ip) { printf("%s ", s[1]); printf("%s ", host); for (n=2; n<=c; ++n) { printf("%s ", s[n]); } printf("\n"); return; } printf("%s\n", $0); } { split(ENVIRON["modify_action"], action) } { split(ENVIRON["modify_address"], address) } { split(ENVIRON["modify_host"], host) } { writeit(action[1], address[1], host[1]); next } ' if [[ $modify_action = "add" ]]; then # IP address didn't already exist, add a new entry $GREP -v '^#' $HOSTS.$$ | $GREP -iwsq $modify_host if [[ $? -ne 0 ]]; then echo "${modify_address}\t${modify_host}" >> $HOSTS.$$ fi fi /usr/bin/mv $HOSTS.$$ $HOSTS /usr/bin/chmod 644 $HOSTS /usr/bin/chown root:sys $HOSTS } # # This function will remove any prior updates to hosts(4) # performed by the service. The service properties themselves # have already been removed by 'svccfg delcust'. # unconfigure_hosts() { # # Sanity check that hosts(4) exists. # if [[ ! -f $HOSTS ]] ; then echo "Warning: $HOSTS does not exist." \ "No unconfigure possible." return fi # # Remove any mapping to loopback # if [[ ! -z $LOOPBACK_PROP ]]; then modify_hosts "remove" 127.0.0.1 $LOOPBACK_PROP modify_hosts "remove" ::1 $LOOPBACK_PROP fi # # Remove any "primary" interface mapping # if [[ ! -z $MAPPED_HOSTNAME ]] ; then for i in $MAPPED_ADDRESSES do modify_hosts "remove" $i $MAPPED_HOSTNAME done fi } # # This function will map the system nodename to hosts(4) entries as # part of initial system configuration or as part of configuration # post the service being unconfigured. If the svc:/network/install:default # service was used to configure an IPv4 and/or IPv6 interface with a # static address, then the function will map the nodename to the IP # address/addresses on that/those interfaces. Otherwise, the function # will map nodename to the loopback addresses. # configure_hosts() { # # This configuration should only be performed immediately after # an install or after an unconfigure. If hosts has already been # configured, then just return. # [[ ! -z $LOOPBACK_PROP || ! -z $MAPPED_HOSTNAME ]] && return # # Sanity check that hosts(4) exists. # if [[ ! -f $HOSTS ]] ; then echo "Warning: $HOSTS does not exist." \ "No entries added for $1." return fi # # If the hostname is already mapped to an IP address, then the # service should not modify it. # $GREP -v '^#' $HOSTS | $GREP -iwsq $1 if [[ $? -eq 0 ]]; then echo "$SVC did not modify existing $1 entry in $HOSTS" return fi # # Check to see if svc:/network/install:default was used to # configure networking. If not, then map the nodename to loopback. # map_loopback="false" NI_APPLIED=$($SVCPROP -p $NI_SVC_APPLIED $NI_SVC) [[ "$NI_APPLIED" = '""' || "$NI_APPLIED" = "false" ]] \ && map_loopback="true" # # Retrieve the interface(s) and the address/addresses # configured on it/them. # if [[ $map_loopback != "true" ]] ; then NI_V4_ADDROBJ=$($SVCPROP -p $NI_SVC_V4_ADDROBJ $NI_SVC) if [[ "$NI_V4_ADDROBJ" = '""' ]]; then NI_V4_ADDR="" else NI_TYPE=`ipadm show-addr -p -o TYPE $NI_V4_ADDROBJ \ 2>/dev/null` if [[ $NI_TYPE == "static" ]]; then NI_V4_ADDR=`ipadm show-addr -p -o ADDR \ $NI_V4_ADDROBJ 2>/dev/null | cut -d '/' -f1` fi fi NI_V6_ADDROBJ=$($SVCPROP -p $NI_SVC_V6_ADDROBJ $NI_SVC) if [[ "$NI_V6_ADDROBJ" = '""' ]]; then NI_V6_ADDR="" else NI_TYPE=`ipadm show-addr -p -o TYPE $NI_V6_ADDROBJ \ 2>/dev/null` if [[ $NI_TYPE == "static" ]]; then NI_V6_ADDR=`ipadm show-addr -p -o ADDR \ $NI_V6_ADDROBJ 2>/dev/null | cut -d '/' -f1` fi fi if [[ $NI_V4_ADDR = "" && $NI_V6_ADDR = "" ]]; then map_loopback="true" else ADDRESSES="" [[ $NI_V4_ADDR != "" ]] && \ ADDRESSES="$ADDRESSES \"$NI_V4_ADDR\"" [[ $NI_V6_ADDR != "" ]] && \ ADDRESSES="$ADDRESSES \"$NI_V6_ADDR\"" fi fi # # Configure hosts(4) according to the whether or not there are # any static addresses to map. # if [[ $map_loopback == "true" ]] ; then # # Update the SMF property and then modify loopback entries # $SVCCFG -s $SVC setprop $SVC_LOOPBACK = astring: "$1" if [[ $? -eq 0 ]]; then $SVCADM refresh $SVC modify_hosts "add" 127.0.0.1 $1 modify_hosts "add" ::1 $1 else echo "$SVC failed to map $1 to loopback addresses" fi else # # Update the SMF properties and then add/modify the # appropriate entries. # props_updated="false" $SVCCFG -s $SVC setprop $SVC_HOSTNAME = astring: "$1" if [[ $? -eq 0 ]]; then $SVCCFG -s $SVC setprop $SVC_ADDRESSES = astring: \ "( $ADDRESSES )" if [[ $? -eq 0 ]]; then props_updated="true" fi fi if [[ $props_updated = "true" ]]; then $SVCADM refresh $SVC [[ $NI_V4_ADDR != "" ]] && \ modify_hosts "add" $NI_V4_ADDR $1 [[ $NI_V6_ADDR != "" ]] && \ modify_hosts "add" $NI_V6_ADDR $1 else echo "$SVC failed to map $1 to $ADDRESSES" fi fi } set_hostname() { if $SVCCFG -s $SVC setprop $SVC_NODENAME = astring: "$1"; then $SVCADM refresh $SVC else echo "$SVC failed to set nodename" fi } # # A hostname value might have been retrieved from $SVC_NODENAME prior to # this function being called. However, there are cases where this value # should be overridden or, in the case where no hostname value was # retrieved from $SVC_NODENAME, a hostname value retrieved from uname(1). # # Normally, if DHCP is the netstrategy for the system, then the hostname # should be retrieved from the dhcpagent using dhcpinfo(1). However, in # some instances (e.g., where a user has specifically set the system # hostname via hostname(1)) the DHCP value should be ignored. # # During AI installs, the hostname should be retrieved from OBP using # netbootinfo. This hostname should override the default hostname # defined in generic.xml. # # Lastly, it is possible during installs of non-global zones, that no # hostname value has yet been derived. If that's the case, then use # uname(1) to retrieve the zonename as the hostname value. # process_hostname_override() { # # If the service is ignoring DHCP hostnames, then do not allow # the hostname to be overidden by DHCP. Note that it is no longer # possible for the net strategy to be "rarp" - this is really # dead code that needs to be removed. # IGNORE_DHCP=$($SVCPROP -p $SVC_IGNORE_DHCP $SVC) IGNORE_DHCP="$(eval echo "$IGNORE_DHCP")" case "$_INIT_NET_STRATEGY" in "dhcp") [[ "$IGNORE_DHCP" == "true" ]] && return hostname=$(/usr/sbin/dhcpinfo Hostname) ;; "rarp") hostname=$(/usr/sbin/hostconfig -h -p bootparams) trap 'intr=1' 2 3 while [[ -z "$hostname" && ! -f /etc/.UNCONFIGURED && \ -z "$intr" ]]; do echo "re-trying host configuration..." # Restrict this to IPv4 interfaces. /usr/sbin/ifconfig -aLdD4 auto-revarp up hostname=$(/usr/sbin/hostconfig -h -p \ bootparams) done trap 2 3 ;; "none") is_install_environment if [[ $? -eq 1 && smf_is_globalzone ]]; then nb_hostname=$(/usr/lib/inet/wanboot/netbootinfo \ hostname 2>/dev/null) if [[ $? -eq 0 && ! -z "$nb_hostname" && \ "$nb_hostname" != "none" ]]; then hostname=$nb_hostname fi fi if [[ -z "$hostname" ]]; then hostname=$(/usr/sbin/uname -n) fi ;; esac } smf_netstrategy case "$1" in 'start'|'refresh') hostname=$($SVCPROP -p $SVC_NODENAME $SVC) hostname="$(eval echo "$hostname")" print -u1 "Hostname is '$hostname'" if [[ -z "$hostname" && -e /etc/nodename ]]; then hostname=$(cat /etc/nodename) set_hostname $hostname rm /etc/nodename fi process_hostname_override ;; 'unconfigure') # Unroll any admin customization $SVCCFG -s $SVC delcust if [ $? -ne 0 ]; then echo "Failed to unroll administrative customizations for $SVC" exit $SMF_EXIT_ERR_FATAL fi $SVCADM refresh $SVC ;; *) "Usage: $0 { start | refresh | unconfigure }" exit $SMF_EXIT_ERR_FATAL ;; esac # # If the netstrategy was unsuccessful and we haven't got a locally configured # name, default to "unknown" # If the unconfigure case was called, the locally configured name is set to # unknown if [[ -z "$hostname" ]]; then hostname=$($SVCPROP -p $SVC_NODENAME $SVC) # svcprop quotes too much hostname="$(eval echo "$hostname")" if [[ -z "$hostname" ]]; then hostname="unknown" set -- unconfigure fi fi curr_hostname=$(/usr/sbin/uname -n) /usr/sbin/uname -S "$hostname" if [ $? -ne 0 ] ; then exit $SMF_EXIT_ERR_FATAL fi case "$1" in 'start'|'refresh') # # Always log the name during service start and on refresh if # the name changes. # if [[ "$1" == "start" || "$hostname" != "$curr_hostname" ]]; then echo "Hostname: $(/usr/sbin/uname -n)" > /dev/msglog fi # The default behavior of configuring hosts(4) can be # disabled via a service property. if [[ "$MAP_NODENAME" == "true" ]] ; then configure_hosts $hostname fi ;; 'unconfigure') unconfigure_hosts ;; esac exit $SMF_EXIT_OK