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 2009 Sun Microsystems, Inc. All rights reserved. 24# Use is subject to license terms. 25# 26 27. /lib/svc/share/smf_include.sh 28. /lib/svc/share/ipf_include.sh 29 30PATH=${PATH}:/usr/sbin:/usr/lib/ipf 31PIDFILE=/var/run/ipmon.pid 32PFILCHECKED=no 33 34zone=`smf_zonename` 35ipfid=`/usr/sbin/modinfo 2>&1 | awk '/ipf/ { print $1 } ' - 2>/dev/null` 36if [ -f $PIDFILE ] ; then 37 pid=`cat $PIDFILE 2>/dev/null` 38else 39 pid=`pgrep -z $zone ipmon` 40fi 41 42logmsg() 43{ 44 logger -p daemon.warning -t ipfilter "$1" 45 echo "$1" >&2 46} 47 48load_ipf() { 49 bad=0 50 ipf -IFa 51 52 for file in $IPFILOVRCONF $CONF_FILES $IPFILCONF; do 53 if [ -r ${file} ]; then 54 ipf -I -f ${file} 55 if [ $? != 0 ]; then 56 echo "$0: load of ${file} into alternate" \ 57 "set failed" 58 bad=1 59 fi 60 fi 61 done 62 63 if [ -r ${IP6FILCONF} ]; then 64 ipf -6IFa -f ${IP6FILCONF} 65 if [ $? != 0 ]; then 66 echo "$0: load of ${IP6FILCONF} into alternate set failed" 67 bad=1 68 fi 69 fi 70 if [ $bad -eq 0 ] ; then 71 ipf -s -y 72 return 0 73 else 74 echo "Not switching config due to load error." 75 return 1 76 fi 77} 78 79 80load_ipnat() { 81 ipnat -CF 82 for nfile in $NAT_FILES $IPNATCONF; do 83 if [ -r ${nfile} ]; then 84 ipnat -f ${nfile} 85 if [ $? != 0 ]; then 86 echo "$0: load of ${nfile} failed" 87 return 1 88 else 89 ipf -y 90 fi 91 fi 92 done 93} 94 95 96load_ippool() { 97 if [ -r ${IPPOOLCONF} ]; then 98 ippool -F 99 ippool -f ${IPPOOLCONF} 100 if [ $? != 0 ]; then 101 echo "$0: load of ${IPPOOLCONF} failed" 102 return 1 103 else 104 return 0 105 fi 106 else 107 return 0 108 fi 109} 110 111# 112# Get current configuration version, fails if property doesn't exist. 113# 114config_get_version() 115{ 116 ver=`svcprop -p $FW_CONFIG_DEF_PG/version $SMF_FMRI 2>/dev/null` 117 [ $? -ne 0 -o -z "$ver" ] && return 1 118 119 echo "$ver" 120} 121 122# 123# Version 1 configuration migration - if there's an existing ipf.conf file, set 124# the default system-wide policy to "custom" and set the custom file value to 125# "/etc/ipf/ipf.conf". Do this migration once and set the 'version' property 126# to the current version value. 127# 128upgrade_config() 129{ 130 old_ipfconf="/etc/ipf/ipf.conf" 131 132 if [ -f ${old_ipfconf} ]; then 133 grep '^[ \t]*[^# \t]' ${old_ipfconf} >/dev/null 2>&1 134 if [ $? -eq 0 ]; then 135 svccfg -s $SMF_FMRI setprop \ 136 $FW_CONFIG_DEF_PG/$POLICY_PROP = astring: \ 137 "custom" >/dev/null 2>&1 138 svccfg -s $SMF_FMRI setprop \ 139 $FW_CONFIG_DEF_PG/$CUSTOM_FILE_PROP = astring: \ 140 "$old_ipfconf" >/dev/null 2>&1 141 fi 142 fi 143 144 svccfg -s $SMF_FMRI setprop $FW_CONFIG_DEF_PG/version = count: \ 145 "$CURRENT_VERSION" >/dev/null 2>&1 146 svcadm refresh $SMF_FMRI >/dev/null 2>&1 147} 148 149configure_firewall() 150{ 151 create_global_rules || exit $SMF_EXIT_ERR_CONFIG 152 create_global_ovr_rules || exit $SMF_EXIT_ERR_CONFIG 153 create_services_rules || exit $SMF_EXIT_ERR_CONFIG 154 155 [ ! -f ${IPFILCONF} -a ! -f ${IPNATCONF} ] && exit 0 156 ipf -E 157 load_ippool || exit $SMF_EXIT_ERR_CONFIG 158 load_ipf || exit $SMF_EXIT_ERR_CONFIG 159 load_ipnat || exit $SMF_EXIT_ERR_CONFIG 160} 161 162# 163# We handle configuration migration as well as a model change (transient to 164# contract based service) in the start, stop, and refresh methods. 165# 166# Configuration migration is straightforward, the start method will do the 167# upgrade if the repository version value is not the same as the version 168# defined in ipf_include.sh However, there are two problems. First, ipfilter 169# can start in parallel with manifest-import, thus the new configuration 170# properties and service definition may not be available to the start method 171# on the first reboot after an upgrade. Second, a transient to contract based 172# model change isn't well supported for an online service. 173# 174# - If the start method finds the property missing (manifest-import hasn't 175# completed), it will allow the still transient network/ipfilter to stay 176# 'online' and wait for manifest-import. Once manifest-import completes, the 177# refresh method will run svcadm restart if the version value is not 178# up-to-date and the subsequent start method will perform the upgrade. 179# 180# - Since the start method allows the service to stay online as a transient 181# service (no contract), the svcadm restart invoked by refresh (described 182# above) will result in a call to the stop method with no existing contract 183# property. The ipfilter manifest cannot include contract/restarter token in 184# its stop method definition since startd will fail to expand that token and 185# place the service in maintenance. Thus, the stop method has to explicitly 186# get the contract id before calling smf_kill_contract. 187# 188case "$1" in 189 start) 190 ver=`config_get_version` 191 if [ $? -eq 1 ]; then 192 echo "Warning: firewall properties are not available" 193 exit $SMF_EXIT_OK 194 fi 195 196 [ "$ver" -ne "$CURRENT_VERSION" ] && upgrade_config 197 198 configure_firewall 199 200 /lib/svc/bin/svc.ipfd 201 /usr/sbin/ipmon -Ds 202 ;; 203 204 stop) 205 ctid=`svcprop -p restarter/contract $SMF_FMRI` 206 if [ -n "$ctid" ]; then 207 smf_kill_contract $ctid TERM 1 208 fi 209 210 ipf -D 211 [ -n "$ipfid" ] && modunload -i $ipfid 212 ;; 213 214 pause) 215 ipfs -l 216 ipfs -d /var/db/ipf -W 217 ipf -D 218 if [ -f $PIDFILE ] ; then 219 if kill -0 $pid; then 220 kill -TERM $pid 221 else 222 cp /dev/null $PIDFILE 223 fi 224 fi 225 ;; 226 227 resume) 228 ipf -E 229 ipfs -R 230 load_ippool 231 load_ipf 232 load_ipnat 233 if [ -f $PIDFILE -a -n "$pid" ] ; then 234 /usr/sbin/ipmon -Ds 235 fi 236 ;; 237 238 reload) 239 ver=`config_get_version` 240 if [ $? -eq 1 ]; then 241 echo "Warning: firewall properties are not available" 242 exit $SMF_EXIT_ERR_CONFIG 243 fi 244 245 if [ "$ver" -ne "$CURRENT_VERSION" ]; then 246 svcadm restart $SMF_FMRI 247 exit $SMF_EXIT_OK 248 fi 249 250 configure_firewall 251 ;; 252 253 reipf) 254 load_ipf 255 ;; 256 257 reipnat) 258 load_ipnat 259 ;; 260 261 fw_update) 262 # 263 # The second argument is the fmri of the service to be updated. 264 # If it's the network/ipfilter, we want to repopulate firewall 265 # configuration for the entire system. 266 # 267 if [ "$2" = "$SMF_FMRI" ]; then 268 configure_firewall 269 else 270 service_update $2 || exit 1 271 fi 272 ;; 273 274 *) 275 echo "Usage: $0 \c" >&2 276 echo "(start|stop|reload|reipf|reipnat|pause|resume)" >&2 277 exit 1 278 ;; 279 280esac 281exit $SMF_EXIT_OK 282