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 2010 Sun Microsystems, Inc.  All rights reserved.
  24 # Use is subject to license terms.
  25 #
  26 
  27 #
  28 # This is third phase of TCP/IP startup/configuration.  This script
  29 # runs after the NIS startup script.  We run things here that may
  30 # depend on NIS maps.
  31 #
  32 
  33 . /lib/svc/share/smf_include.sh
  34 . /lib/svc/share/net_include.sh
  35 
  36 NWAM_FMRI="svc:/network/physical:nwam"
  37 
  38 case "$1" in
  39 'start')
  40         #
  41         # In a shared-IP zone we need this service to be up, but all of the
  42         # work it tries to do is irrelevant (and will actually lead to the
  43         # service failing if we try to do it), so just bail out. 
  44         # In the global zone and exclusive-IP zones we proceed.
  45         #
  46         smf_configure_ip || exit $SMF_EXIT_OK
  47 
  48         #
  49         # If nwam is enabled, the nwam service will handle the tasks performed
  50         # by this service, so just bail out.
  51         #
  52         service_is_enabled $NWAM_FMRI && exit $SMF_EXIT_OK
  53         ;; # fall through -- rest of script is the initialization code
  54 
  55 'stop')
  56         exit $SMF_EXIT_OK
  57         ;;
  58 
  59 *)
  60         echo "Usage: $0 { start | stop }"
  61         exit 1
  62         ;;
  63 esac
  64 
  65 interface=$2
  66 
  67 # If boot variables are not set, set variables we use
  68 [ -z "$_INIT_UTS_NODENAME" ] && _INIT_UTS_NODENAME=`/usr/bin/uname -n`
  69 
  70 #
  71 # This function takes two file names and the file mode as input. The two
  72 # files are compared for differences (using cmp(1)) and if different, the
  73 # second file is over written with the first. A chmod is done with the file
  74 # mode passed in. If the files are equal, the first file passed
  75 # in (the /tmp file) is deleted.
  76 #
  77 mv_file ()
  78 {
  79         /usr/bin/cmp -s $1 $2
  80         if [ $? -eq 1 ]; then
  81                 /usr/bin/mv $1 $2
  82                 #
  83                 # The umask during boot is configurable, which requires
  84                 # explicit setting of file permission modes when we
  85                 # create files.
  86                 #
  87                 /usr/bin/chmod $3 $2
  88         else
  89                 /usr/bin/rm $1
  90         fi
  91 }
  92 
  93 #
  94 # This function takes a DHCP parameter (as defined in /etc/dhcp/inittab)
  95 # and returns the value for that parameter returned by the DHCP server.
  96 # If the global 'interface' is defined, it will request the value learned
  97 # on that interface, else it will request the value learned on the primary
  98 # interface.
  99 #
 100 get_dhcp_var ()
 101 {
 102         if [ -n "$interface" ]; then
 103                 /sbin/dhcpinfo -i $interface $1
 104         else
 105                 /sbin/dhcpinfo $1
 106         fi
 107 }
 108 
 109 #
 110 # This function returns true if the string "# Added by DHCP$" occurs in
 111 # the passed-in file, false otherwise.
 112 #
 113 dhcp_edits ()
 114 {
 115         /usr/bin/grep '# Added by DHCP$' $1 >/dev/null 2>&1
 116         return $?
 117 }
 118 
 119 #
 120 # update_resolv()
 121 # Go through /etc/resolv.conf and replace any existing domain or
 122 # nameserver entries with new ones derived from DHCP.  Note that
 123 # it is important to preserve order of domain entries vs. search
 124 # entries; the search entries are reserved for administrator
 125 # customization and if placed after the domain entry will override
 126 # it.  See resolv.conf(4).
 127 #
 128 # The first arg should be the dns servers string, the second
 129 # should be the dns domain.
 130 #
 131 update_resolv ()
 132 {
 133         dnsservers=$1
 134         dnsdomain=$2
 135 
 136         if [ ! -f /etc/resolv.conf ]; then
 137                 /usr/bin/touch /etc/resolv.conf
 138         fi
 139         export dnsservers dnsdomain
 140         /usr/bin/nawk </etc/resolv.conf >/tmp/resolv.conf.$$ '
 141                 function writedomain() {
 142                         if (updated == 0) {
 143                                 # Use only first domain, not a search list
 144                                 split(ENVIRON["dnsdomain"], d)
 145                                 if(length(d[1]) != 0)
 146                                         printf("domain %s\n", d[1])
 147                         }
 148                         ++updated
 149                 }
 150                 $1 == "domain" { writedomain(); next }
 151                 $1 != "nameserver" { print $0 }
 152                 END {
 153                         writedomain()
 154                         n = split(ENVIRON["dnsservers"], s)
 155                         for (i = 1; i <= n; ++i)
 156                                 printf("nameserver %s\n", s[i])
 157                 }'
 158         unset dnsservers dnsdomain
 159         mv_file /tmp/resolv.conf.$$ /etc/resolv.conf 644
 160 }
 161 
 162 #
 163 # update_nss()
 164 # This routine takes as a parameter, the name of the respective policy 
 165 # to change in the nsswitch.conf (hosts or ipnodes) to update with dns.
 166 #
 167 update_nss ()
 168 {
 169         policy=$1;
 170         # Add dns to the nsswitch file, if it isn't already there.
 171         /usr/bin/awk ' $1 ~ /^'${policy}':/ {
 172                 n = split($0, a);
 173                 newl = a[1];
 174                 if ($0 !~ /dns/) {
 175                         printf("#%s # Commented out by DHCP\n", $0);
 176                         updated = 0;
 177                         for (i = 2; i <= n; i++) {
 178                                 if (updated == 0 && index(a[i], "[") == 1) {
 179                                         newl = newl" dns";
 180                                         updated++;
 181                                 }
 182                                 newl = newl" "a[i];
 183                         }
 184                         if (updated == 0) {
 185                                 newl = newl" dns";
 186                                 updated++;
 187                         }
 188                         if (updated != 0)
 189                                 newl = newl" # Added by DHCP";
 190                         else
 191                                 newl = $0;
 192                         printf("%s\n", newl);
 193                 } else
 194                         printf("%s\n", $0);
 195         } $1 !~ /^'${policy}':/ { printf("%s\n", $0); }' /etc/nsswitch.conf \
 196             >/tmp/nsswitch.conf.$$
 197 
 198         mv_file /tmp/nsswitch.conf.$$ /etc/nsswitch.conf 644
 199 }
 200 
 201 #
 202 # Remove any lines with the "# Added by DHCP" tag from /etc/nsswitch.conf;
 203 # also uncomment hosts and ipnodes entries which were previously commented
 204 # out by this script.
 205 #
 206 cleanup_nss ()
 207 {
 208         /usr/bin/sed \
 209             -e '/# Added by DHCP$/d' \
 210             -e 's/^\(#hosts:\)\(.*[^#]\)\(#.*\)$/hosts: \2/' \
 211             -e 's/^\(#ipnodes:\)\(.*[^#]\)\(#.*\)$/ipnodes: \2/' \
 212             /etc/nsswitch.conf >/tmp/nsswitch.conf.$$
 213 
 214         mv_file /tmp/nsswitch.conf.$$ /etc/nsswitch.conf 644
 215 }
 216 
 217 #
 218 # Remove any lines with the "# Added by DHCP" tag from /etc/inet/hosts.
 219 #
 220 cleanup_hosts ()
 221 {
 222         /usr/bin/nawk '{
 223                 if (index($0, "# Added by DHCP") == 0 ||
 224                     $1 == "127.0.0.1" || $1 == "::1") {
 225                         print $0
 226                 }
 227         }' /etc/inet/hosts > /tmp/hosts.$$
 228         mv_file /tmp/hosts.$$ /etc/inet/hosts 444
 229 }
 230 
 231 #
 232 # If our network configuration strategy is DHCP, check for DNS
 233 # configuration parameters obtained from the DHCP server.
 234 #
 235 # Script execution starts here.
 236 #
 237 smf_netstrategy
 238 
 239 if [ "$_INIT_NET_STRATEGY" = "dhcp" ]; then
 240         dnsservers=`get_dhcp_var DNSserv`
 241         dnsdomain=`get_dhcp_var DNSdmain`
 242 else
 243         dnsservers=""
 244         dnsdomain=""
 245 fi
 246 
 247 if [ -n "$dnsservers" ]; then
 248         #
 249         # add settings retrieved from dhcp server to /etc/resolv.conf
 250         #
 251         update_resolv "$dnsservers" "$dnsdomain"
 252 
 253         #
 254         # Add dns to the nsswitch file, if it isn't already there.
 255         #
 256         update_nss hosts
 257         update_nss ipnodes
 258 
 259 elif dhcp_edits /etc/nsswitch.conf; then
 260         # If we added DNS to the hosts and ipnodes
 261         # policy in the nsswitch, remove it.
 262         cleanup_nss
 263 fi
 264 
 265 if dhcp_edits /etc/inet/hosts; then
 266         # Clean up any old DHCP-added entries
 267         # (except loopback) in the hosts file.
 268         cleanup_hosts
 269 fi
 270