#!/bin/ksh

# Copyright (c) 2006 by Sun Microsystems, Inc.
# All rights reserved

PATH=/usr/bin:/usr/sbin:$PATH; export PATH

IPSECINIT="$BASEDIR/etc/inet/ipsecinit.conf"
IPSECINITSAMPLE="$BASEDIR/etc/inet/ipsecinit.sample"
typeset -i issue_warning
platform=`uname -i`

kbtrans_patch=118859-01
starcat="SUNW,Sun-Fire-15000"

rmpkg=SUNWckr
addpkg=SUNWusb
kbtrans=/kernel/misc/sparcv9/kbtrans
PKGCOND=/usr/bin/pkgcond
ZFSPKGS="SUNWsmapi"
admin=/tmp/admin.$$
NAWK="/bin/nawk"
DIRNAME="/bin/dirname"
PDO_REBOOT_LOC="/var/run/.solpatchsys/.pdo.patch-reboot-required.lock"

AlternateRoot()
# returns 0 if $PKG_INSTALL_ROOT -
{
	if [ -n "$ROOTDIR" ]; then
		if  [ "/" = "`echo $ROOTDIR|$NAWK '{gsub(/\/+/,"/"); print}'`" ]; then
			return 1
		else
			return 0
		fi
	else
		return 1
	fi
}

updateIPSEC () {		#update ipsec on 15000

	issue_warning=0

	# Make sure ipsecinit.conf exists
	if [ ! -f $IPSECINIT -a -f $IPSECINITSAMPLE ]
	then
		cp $IPSECINITSAMPLE $IPSECINIT
	else
		touch $IPSECINIT > /dev/null 2>&1
	fi

}

#
# Function to update ipsecinit.conf if necessary.
#
# Usage:
#	add_ipsecinit_entry  sport|dport  service  apply|permit \
#		auth_algs  [sa_state]
#
# Note: If an entry exists that uses the same (sport|dport)/service
# combination, the default entry is not added. This is to prevent
# the default policies from overriding any custom policies that might
# have been established.
#
add_ipsecinit_entry()
{
	# Build default entries
	if [ $3 = "permit" ]; then
		default="{ $1 $2 ulp tcp } $3 { auth_algs $4 }"
	else
		default="{ $1 $2 ulp tcp } $3 { auth_algs $4 sa $5 }"
	fi

	# Check for a default entry
	grep "$default" $IPSECINIT > /dev/null 2>&1
	if [ $? -eq 0 ]; then
		return
	fi

	#
	# Check the file for an entry that has
	# a matching (sport|dport)/service pair
	#
	nawk "	BEGIN		{ RS=\"}\" }
		/$1.*$2/	{ return 1 }
	" $IPSECINIT > /dev/null 2>&1

	# Add an entry if necessary
	if [ $? -eq 1 ]; then
	  cat Found a policy for $1 $2 that does not match the default policy > /tmp/post_patchrm.$$
		issue_warning=1
	else
		echo $default >> $IPSECINIT
	fi
}


update_starcat_ipsec()
{
	#
	# Update IPsec policy configuration file only if installed
	# on a Sun Fire 15000.
	#

	if [ ${platform} == "${starcat}" ]; then

		updateIPSEC

		#
		# Add all of our default policies
		#
		add_ipsecinit_entry dport sun-dr permit md5
		add_ipsecinit_entry sport sun-dr apply md5 unique
		add_ipsecinit_entry dport cvc_hostd permit md5
		add_ipsecinit_entry sport cvc_hostd apply md5 unique


		if [ $issue_warning -eq 1 ]; then

			cat <<-eof >> /tmp/post_patchrm.$$
				NOTICE: One or more of the default IPsec policies for the
				Sun Fire 15000 services has been modified. As a result, the 
				default policy for those services was not added. Please verify 
				that the /etc/inet/ipsecinit.conf file is correct.  For
				more information, refer to sckmd(1M) and ipsecconf(1M).
			eof

		fi

		if [ -f  /tmp/post_patchrm.$$ ]; then

		  cat  /tmp/post_patchrm.$$
		  rm /tmp/post_patchrm.$$

		fi
	fi
}

setZFSpkgs () { # part of postbackout script for ZFS smapi pkg check

	quiet() {
	cat <<-eof > $admin
		mail=
		instance=nocheck
		partial=nocheck
		runlevel=nocheck
		idepend=nocheck
		rdepend=nocheck
		space=quit
		setuid=nocheck
		conflict=nocheck
		action=nocheck
		eof

	chmod a+x $admin

	}

	if [ -f $ROOTDIR/var/sadm/pkg/$ZFSPKGS/save/$ZFSPKGS.$PatchNum ] ; then
		## then it is ok to remove them
		quiet
		for zfspkg in $ZFSPKGS ; do
			## is the pkg installed?
			if pkginfo -q -R $ROOTDIR $zfspkg ; then
				## yes, remove it.
				/bin/rm -f $ROOTDIR/var/sadm/pkg/$ZFSPKGS/save/$ZFSPKGS.$PatchNum
				pkgrm -n -a $admin -R $ROOTDIR $zfspkg
			fi
		done
		/bin/rm -f $admin
	fi
}


CheckZones()
{
        if [ -x /usr/bin/zonename ]; then
                ZONENAME=`/usr/bin/zonename`
                if [ ${ZONENAME} = "global" ]; then
                        GLOBAL_ZONE=true
                else
                        GLOBAL_ZONE=false
                fi
        else
                # Unable to determine zone
                GLOBAL_ZONE=true
        fi
}

LocalZones()
{
# Any local zone stuff here,
# typically this fuction is not used
        return 0
}

ExecuteALLCmds()
{
 restore_kbtrans
 remove_ba_start_method
 update_starcat_ipsec
}


determine_pkgcond () {

  if $PKGCOND  is_whole_root_nonglobal_zone > /dev/null 2>&1 ; then
      # Execute non-global whole root zone commands.
      # Should be same action as the default action.
      remove_ba_start_method
      return 0
  fi

  if $PKGCOND  is_nonglobal_zone > /dev/null 2>&1 ; then 
      # Execute non-global zone commands. Should be no action here
      return 0
  fi

  if $PKGCOND is_netinstall_image > /dev/null 2>&1 ; then
      # Execute commands applicable to patching the mini-root.
      # There are usually no actions to take here since your patching
      # the mini-root on an install server.
      return 0
  fi

  if $PKGCOND is_mounted_miniroot > /dev/null 2>&1 ; then
      # Execute commands specific to the mini-root
      return 0
  fi

  if $PKGCOND is_diskless_client > /dev/null 2>&1 ; then
      # Execute commands specific to diskless client
      return 0
  fi

  if $PKGCOND is_alternative_root > /dev/null 2>&1 ; then
      # Execute commands specific to an alternate root
      ExecuteALLCmds
      return 0
  fi

  if $PKGCOND is_global_zone > /dev/null 2>&1 ; then
      # In a global zone and system is mounted on /.
      # Execute all commands.
      ExecuteALLCmds
      return 0
  fi

}

last_patch() {

	## returns the number of patches installed at or above this rev.

	root_dir=${ROOTDIR:-/}

	## parse id and rev
	pid=`echo $1 | cut -d\- -f1`
	prev=`echo $1 | cut -d\- -f2`
	patch_cnt=0

	## get all installed refernces to the installed patch base id	
	installed_patches=`patchadd -p -R $root_dir -p | sed -n -e 's/Req.*//' -e 's/[a-zA-Z]*://g' -e 's/,//g' -e "/$pid/p"`
	
	for x in $installed_patches ; do
		base=`echo $x  | cut -d\- -f1`
		rev=`echo $x | cut -d\- -f2`
		if [ $pid -eq $base ] && [ $rev -ge $prev ] ; then 
			## count all installed patches includeing this patch
			patch_cnt=$(($patch_cnt + 1))
		fi
	done
	
	return $patch_cnt
}


restore_kbtrans() {


	## This patch will add kbtrans to SUNWckr.  Manually remove it from SUNWusb
	## if it exists
	##

	if [ ! -f $ROOTDIR/$kbtrans ] ; then
		return
	fi
	last_patch $kbtrans_patch
	if [ "$?" = "0" ] ; then 
		pkgchk -R $ROOTDIR -l -p $kbtrans | grep $rmpkg >/dev/null 2>&1 \
		&& pkginfo -R "${ROOTDIR}" "${addpkg}" >/dev/null 2>&1
		if [ "$?" =  "0" ] ; then
			removef -R $ROOTDIR $rmpkg $ROOTDIR/$kbtrans 1>/dev/null 2>&1
			removef -R $ROOTDIR -f $rmpkg
			installf -R $ROOTDIR $addpkg $ROOTDIR/$kbtrans 1>/dev/null 2>&1
			installf -R $ROOTDIR -f $addpkg
			restore_kbtrans_pkgmap
		fi
	fi
}

##
## restore_kbtrans_pkgmap
##
## Address 6343544 by restoring the zones saved pkgmap entry to SUNWusb which
## was removed by the prepatch script thanks to workaround for 6312956.

restore_kbtrans_pkgmap () {

mypatchid=${PatchNum}
savedpkgmap=$ROOTDIR/var/sadm/pkg/$addpkg/save/pspool/$addpkg/pkgmap
backoutpkgmap=$ROOTDIR/var/sadm/patch/$mypatchid/$addpkg.pkgmap.$mypatchid
## backoutpkgmap=$ROOTDIR/var/sadm/patch/$mypatchid.savekbtrans.$addpkg.undo.pkgmap
kbtrans_entry=kernel/misc/sparcv9/kbtrans

        if test -s $backoutpkgmap
        then

        ## We did save something.  However, installf might have been fixed
        ## in the meantime, we check whether we still need the workaround.

                if grep "$kbtrans_entry" $savedpkgmap >/dev/null; then
                :
                else
                cat $backoutpkgmap >> $savedpkgmap
		rm -f $backoutpkgmap
                fi
        fi

}

ZONENAME=global


##
## Address 6348423 by removing boot-archive's start method from repository
## Address 6359117 by executing this call in certain zones conditions:
## is_whole_root_nonglobal_zones, is_global_zone, is_alternative_root
##

remove_ba_start_method () {
typeset -r ku_w_ba=118822-21
if last_patch $ku_w_ba ; then
	echo "exit 0" > $ROOTDIR/lib/svc/method/boot-archive
	chmod +x $ROOTDIR/lib/svc/method/boot-archive
fi
}


# Main

[ -x /sbin/zonename ] && ZONENAME=`/sbin/zonename`

setZFSpkgs

if [ -x "$PKGCOND" ] ; then
  determine_pkgcond
else
  CheckZones
  if [ "${GLOBAL_ZONE}" = "true" ]; then
       ExecuteALLCmds
  else
   LocalZones
  fi
fi

## log file for CAS scripts to communicate with console
if [ -f /tmp/$PatchNum.log ] ; then
	cat /tmp/$PatchNum.log
	/bin/rm -f /tmp/$PatchNum.log
fi

##
## Disable pdo, so after this patch installation reboot *MUST* happen
##
if AlternateRoot; then
	:
else
	cat > /var/run/nopatch <<EOF
#!/sbin/sh
echo "You must perform a reconfigure reboot before invoking any additional patch commands." >&2
exit 1
EOF
	chmod +x /var/run/nopatch
	mount -O -F lofs /var/run/nopatch /usr/lib/patch/pdo
fi

exit 0

