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.
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.
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]
22 # Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23 # Copyright 2016 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
26 IPFILTER_FMRI
="svc:/network/ipfilter:default"
28 IPNATCONF
=`/usr/bin/svcprop -p config/ipnat_config_file $IPFILTER_FMRI \
31 IPNATCONF
=$ETC_IPF_DIR/ipnat.conf
33 IPPOOLCONF
=`/usr/bin/svcprop -p config/ippool_config_file $IPFILTER_FMRI \
36 IPPOOLCONF
=$ETC_IPF_DIR/ippool.conf
38 VAR_IPF_DIR
=/var
/run
/ipf
39 IPFILCONF
=$VAR_IPF_DIR/ipf.conf
40 IP6FILCONF
=$VAR_IPF_DIR/ipf6.conf
41 IPFILOVRCONF
=$VAR_IPF_DIR/ipf_ovr.conf
42 IP6FILOVRCONF
=$VAR_IPF_DIR/ipf6_ovr.conf
43 IPF_LOCK
=/var
/run
/ipflock
51 # version for configuration upgrades
54 IPF_FMRI
="svc:/network/ipfilter:default"
55 INETDFMRI
="svc:/network/inetd:default"
56 RPCBINDFMRI
="svc:/network/rpc/bind:default"
59 SMF_MAINT
="maintenance"
62 FW_CONTEXT_PG
="firewall_context"
63 METHOD_PROP
="ipf_method"
65 FW_CONFIG_PG
="firewall_config"
67 APPLY2_PROP
="apply_to"
68 APPLY2_6_PROP
="apply_to_6"
69 EXCEPTIONS_PROP
="exceptions"
70 EXCEPTIONS_6_PROP
="exceptions_6"
72 TARGET_6_PROP
="target_6"
73 BLOCKPOL_PROP
="block_policy"
75 FW_CONFIG_DEF_PG
="firewall_config_default"
76 FW_CONFIG_OVR_PG
="firewall_config_override"
77 CUSTOM_FILE_PROP
="custom_policy_file"
78 CUSTOM_FILE_6_PROP
="custom_policy_file_6"
79 OPEN_PORTS_PROP
="open_ports"
88 GLOBAL_BLOCK_POLICY
=""
90 SERVINFO
=/usr
/lib
/servinfo
93 # Get value(s) for given property from either firewall_config_default or
94 # firewall_config_override property groups.
96 # global_get_prop_value pg_name propname
97 # pg_name - FW_CONFIG_DEF_PG or FW_CONFIG_OVR_PG
98 # propname - property name
100 global_get_prop_value
()
105 [ "$1" != $FW_CONFIG_OVR_PG -a "$1" != $FW_CONFIG_DEF_PG ] && return
107 [ "$1" == $FW_CONFIG_DEF_PG ] && extra_pg
=$FW_CONFIG_OVR_PG || \
108 extra_pg
=$FW_CONFIG_DEF_PG
110 value
=`echo $GLOBAL_CONFIG | awk '{
112 for (i=1; i<=NF; i++) {
114 if (index($i, target_pg) == 1 || index($i, extra_pg) == 1)
120 if (split($i, values, "/") < 2)
123 if (values[1] == target_pg && values[2] == prop)
126 }' target_pg=$target_pg prop=$prop extra_pg=$extra_pg`
133 # Initialize and cache network/ipfilter configuration, global configuration.
135 # Since an SMF service configuration may get updated during the execution of the
136 # service method, it's best to read all relevant configuration via one svcprop
137 # invocation and cache it for later use.
139 # This function reads and stores relevant configuration into GLOBAL_CONFIG and
140 # initializes the GLOBAL_POLICY and GLOBAL_BLOCK_POLICY variables. GLOBAL_CONFIG
141 # is a string containing pg/prop and their corresponding values (i.e. svcprop -p
142 # pg fmri output). To get values for a certain pg/prop, use
143 # global_get_prop_value().
147 GLOBAL_CONFIG
=`svcprop -p ${FW_CONFIG_OVR_PG} -p ${FW_CONFIG_DEF_PG} \
148 $IPF_FMRI 2>/dev/null | awk '{$2=" "; print $0}'`
150 GLOBAL_POLICY
=`global_get_prop_value $FW_CONFIG_DEF_PG $POLICY_PROP`
151 GLOBAL_BLOCK_POLICY
=`global_get_prop_value $FW_CONFIG_DEF_PG \
156 # Given a service, gets its config pg name
160 if [ "$1" = "$IPF_FMRI" ]; then
161 echo "$FW_CONFIG_DEF_PG"
169 # Given a service, gets its firewall policy
173 config_pg
=`get_config_pg $1`
174 svcprop
-p $config_pg/${POLICY_PROP} $1 2>/dev
/null
178 # block policy can be set to "return", which will expand into
179 # separate block rules for tcp (block return-rst ...) and all other
180 # protocols (block return-icmp-as-dest ...)
184 config_pg
=`get_config_pg $1`
185 svcprop
-p $config_pg/${BLOCKPOL_PROP} $1 2>/dev
/null
189 # Given a service, gets its source address exceptions for IPv4
193 config_pg
=`get_config_pg $1`
194 exceptions
=`svcprop -p $config_pg/${EXCEPTIONS_PROP} $1 2>/dev/null`
195 echo $exceptions |
sed -e 's/\\//g'
199 # Given a service, gets its source address exceptions for IPv6
203 config_pg
=`get_config_pg $1`
204 exceptions6
=`svcprop -p $config_pg/${EXCEPTIONS_6_PROP} $1 2>/dev/null`
205 echo $exceptions6 |
sed -e 's/\\//g'
209 # Given a service, gets its firewalled source addresses for IPv4
213 config_pg
=`get_config_pg $1`
214 apply2
=`svcprop -p $config_pg/${APPLY2_PROP} $1 2>/dev/null`
215 echo $apply2 |
sed -e 's/\\//g'
219 # Given a service, gets its firewalled source addresses for IPv6
223 config_pg
=`get_config_pg $1`
224 apply2_6
=`svcprop -p $config_pg/${APPLY2_6_PROP} $1 2>/dev/null`
225 echo $apply2_6 |
sed -e 's/\\//g'
229 # Given a service, gets its firewalled target addresses for IPv4
233 config_pg
=`get_config_pg $1`
234 target
=`svcprop -p $config_pg/${TARGET_PROP} $1 2>/dev/null`
235 [ -z "$target" -o "$target" = '""' ] && target
=any
236 echo $target |
sed -e 's/\\//g'
240 # Given a service, gets its firewalled target addresses for IPv6
244 config_pg
=`get_config_pg $1`
245 target6
=`svcprop -p $config_pg/${TARGET_6_PROP} $1 2>/dev/null`
246 [ -z "$target6" -o "$target6" = '""' ] && target6
=any
247 echo $target6 |
sed -e 's/\\//g'
252 [ -d $VAR_IPF_DIR ] && return 0
253 mkdir
$VAR_IPF_DIR >/dev
/null
2>&1 ||
return 1
257 # fmri_to_file fmri suffix
261 check_ipf_dir ||
return 1
262 fprefix
="${VAR_IPF_DIR}/`echo $1 | tr -s '/:' '__'`"
263 echo "${fprefix}${2}"
267 # Return service's enabled property
272 # Temporary enabled state overrides the persistent state
275 enabled_ovr
=`svcprop -c -p general_ovr/enabled $1 2>/dev/null`
276 if [ -n "$enabled_ovr" ]; then
277 [ "$enabled_ovr" = "true" ] && return 0 ||
return 1
280 enabled
=`svcprop -c -p general/enabled $1 2>/dev/null`
281 [ -n "$enabled" -a "$enabled" = "true" ] && return 0 ||
return 1
285 # Return whether service is desired state
289 # 0 - desired state is service's current state
290 # 1 - desired state is not service's current state
292 service_check_state
()
295 # Make sure we're done with ongoing state transition
297 while [ "`svcprop -p restarter/next_state $1`" != "$SMF_NONE" ]; do
301 [ "`svcprop -p restarter/state $1`" = "$2" ] && return 0 ||
return 1
305 # Deny/Allow list stores values in the form "host:addr", "network:addr/netmask",
306 # "pool:number", and "if:interface". This function returns the
307 # IP(addr or addr/netmask) value or a pool number.
311 value_is_interface
$1 && return 1
312 echo "$1" |
sed -n -e "s,^${PREFIX_POOL}\(.*\),pool/\1,p" \
313 -e "s,^${PREFIX_HOST}\(.*\),\1,p" \
314 -e "s,^${PREFIX_NET}\(.*\),\1,p" \
320 value_is_interface
$1 ||
return 1
321 scratch
=`echo "$1" | sed -e "s/^${PREFIX_IF}//"`
323 ifconfig
$scratch >/dev
/null
2>&1 ||
return 1
324 echo $scratch |
sed -e 's/:.*//'
332 [ -z "$1" ] && return 1
333 echo $1 |
grep "^${PREFIX_IF}" >/dev
/null
2>&1
337 # Remove rules in given file from active list without restarting ipfilter
341 [ -f "$1" ] && ipf
$2 -r -f $1 >/dev
/null
2>&1
346 [ -f "$1" ] && ipnat
-r -f $1 >/dev
/null
2>&1
351 ipf
$2 -n -f $1 >/dev
/null
2>&1
356 ipnat
-n -f $1 >/dev
/null
2>&1
361 echo $
* |
xargs -n 1 echo |
sort -u
366 ipf
$2 -n -v -f $1 2>/dev
/null |
sed -n -e \
367 's/.*to.* port = \([a-z0-9]*\).*/\1/p' |
uniq | \
368 awk '{if (length($0) > 1) {printf("%s ", $1)}}'
373 ipfstat
$1 -io 2>/dev
/null |
sed -n -e \
374 's/.*to.* port = \([a-z0-9]*\).*/\1/p' |
uniq | \
375 awk '{if (length($0) > 1) {printf("%s ",$1)}}'
379 # Given two list of ports, return failure if there's a duplicate.
381 sets_check_duplicate
()
384 # If either list is empty, there isn't any conflict.
386 [ -z "$1" -o -z "$2" ] && return 0
390 [ "$p" = "$ap" ] && return 1
398 # Given a file containing ipf rules, check the syntax and verify
399 # the rules don't conflict, use same port number, with active
400 # rules (ipfstat -io output).
402 update_check_ipf_rules
()
404 check_ipf_syntax
$1 $2 ||
return 1
406 lports
=`file_get_ports $1 $2`
407 lactive_ports
=`get_active_ports $2`
409 sets_check_duplicate
"$lports" "$lactive_ports" ||
return 1
413 server_port_list_6
=""
416 # Given a file containing ipf rules, check the syntax and verify
417 # the rules don't conflict with already processed services.
419 # The list of processed services' ports are maintained in the global
420 # variables 'server_port_list' and 'server_port_list_6'.
425 check_ipf_syntax
$1 $2 ||
return 1
427 lports
=`file_get_ports $1 $2`
429 if [ "$2" = "-6" ]; then
430 sets_check_duplicate
"$lports" "$server_port_list_6" ||
return 1
431 server_port_list_6
="$server_port_list_6 $lports"
433 sets_check_duplicate
"$lports" "$server_port_list" ||
return 1
434 server_port_list
="$server_port_list $lports"
442 check_ipf_syntax
$1 $2 && tail -r $1 |
sed -e 's/^[a-z]/@0 &/' | \
443 ipf
$2 -f - >/dev
/null
2>&1
448 check_ipf_syntax
$1 $2 && ipf
$2 -f $1 >/dev
/null
2>&1
451 append_new_nat_rules
()
453 check_nat_syntax
$1 && ipnat
-f $1 >/dev
/null
2>&1
457 # get port information from string of the form "proto:{port | port-port}"
461 port_str
=`echo "$1" | sed -e 's/ //g; s/\\\//g; s/.*://' 2>/dev/null`
462 [ -z "$port_str" ] && return 1
464 echo $port_str |
grep "-" >/dev
/null
465 if [ $?
-eq 0 ]; then
466 echo $port_str |
grep '^[0-9]\{1,5\}-[0-9]\{1,5\}$' >/dev
/null || \
468 ports
=`echo $port_str | ( IFS=- read a b ; \
469 [ $a \-le $b ] && echo $a $b || echo $b $a )`
472 [ $p -gt 65535 ] && return 1
477 # port_str is a single port, verify and return it.
479 echo "$port_str" |
grep '^[0-9]\{1,5\}$' >/dev
/null ||
return 1
480 [ $port_str -gt 65535 ] && return 1
486 # get proto info from string of the form "{tcp | udp}:port"
490 proto
=`echo "$1" | sed -e 's/ //g; s/:.*//' 2>/dev/null`
491 [ -z "$proto" ] && return 0
493 [ "$proto" = "tcp" -o "$proto" = "udp" ] && echo $proto ||
return 1
501 if [ -f "$IPF_LOCK/pid" ]; then
502 curpid
=`cat $IPF_LOCK/pid 2>/dev/null`
503 [ "$curpid" = "$newpid" ] && return 0
506 # Clear lock if the owning process is no longer around.
508 ps
-p $curpid >/dev
/null
2>&1 ||
rm -r $IPF_LOCK >/dev
/null
2>&1
515 mkdir
$IPF_LOCK 2>/dev
/null
&& break;
518 echo $newpid > $IPF_LOCK/pid
522 # Remove lock if it's ours
526 if [ -f "$IPF_LOCK/pid" ]; then
527 [ "`cat $IPF_LOCK/pid`" = "$$" ] && rm -r $IPF_LOCK
533 # Make IPFILCONF, /var/tmp/ipf/ipf.conf, a symlink to the input file argument.
538 # Nothing to do if the input file doesn't exist.
540 [ ! -f "$1" ] && return 0
542 check_ipf_dir ||
return 1
544 rm $IPFILCONF >/dev
/null
2>&1
545 ln -s $1 $IPFILCONF >/dev
/null
2>&1
549 # Make IP6FILCONF, /var/tmp/ipf/ipf6.conf, a symlink to the input file argument.
551 custom_set_symlink_6
()
554 # Nothing to do if the input file doesn't exist.
556 [ ! -f "$1" ] && return 0
558 check_ipf_dir ||
return 1
560 rm $IP6FILCONF >/dev
/null
2>&1
561 ln -s $1 $IP6FILCONF >/dev
/null
2>&1
565 # New file replaces original file if they have different content
573 # IPFILCONF may be a symlink, remove it if that's the case
575 if [ -L "$orig" ]; then
580 check_ipf_dir ||
return 1
581 mv $new $orig && return 0 ||
return 1
585 # Given a service, gets the following details for ipf rule:
588 # - port(IANA port obtained by running servinfo)
593 policy
=`get_policy ${service}`
596 # Empties service's rules file so callers won't use existing rule if
599 file=`fmri_to_file $service $IPF_SUFFIX`
600 file6
=`fmri_to_file $service $IPF6_SUFFIX`
601 [ -z "$file" ] && return 1
602 echo "# $service" >${file}
603 echo "# $service" >${file6}
606 # Nothing to do if policy is "use_global"
608 [ "$policy" = "use_global" ] && return 0
610 restarter
=`svcprop -p general/restarter $service 2>/dev/null`
611 if [ "$restarter" = "$INETDFMRI" ]; then
612 iana_name
=`svcprop -p inetd/name $service 2>/dev/null`
613 isrpc
=`svcprop -p inetd/isrpc $service 2>/dev/null`
615 iana_name
=`svcprop -p $FW_CONTEXT_PG/name $service 2>/dev/null`
616 isrpc
=`svcprop -p $FW_CONTEXT_PG/isrpc $service 2>/dev/null`
620 # Bail if iana_name isn't defined. Services with static rules
621 # like nis/client don't need to generate rules using
622 # iana name and protocol information.
624 [ -z "$iana_name" ] && return 1
629 if [ "$isrpc" = "true" ]; then
630 # The ports used for IPv6 are usually also reachable
631 # through IPv4, so generate IPv4 rules for them, too.
632 tports
=`$SERVINFO -R -p -t -s $iana_name 2>/dev/null`
633 tports6
=`$SERVINFO -R -p -t6 -s $iana_name 2>/dev/null`
634 if [ -n "$tports" -o -n "$tports6" ]; then
635 tports
=`unique_ports $tports $tports6`
636 for tport
in $tports; do
637 generate_rules
$service $policy "tcp" \
642 if [ -n "$tports6" ]; then
643 for tport6
in $tports6; do
644 generate_rules
$service $policy "tcp" \
649 uports
=`$SERVINFO -R -p -u -s $iana_name 2>/dev/null`
650 uports6
=`$SERVINFO -R -p -u6 -s $iana_name 2>/dev/null`
651 if [ -n "$uports" ]; then
652 uports
=`unique_ports $uports $uports6`
653 for uport
in $uports; do
654 generate_rules
$service $policy "udp" \
659 if [ -n "$uports6" ]; then
660 for uport6
in $uports6; do
661 generate_rules
$service $policy "udp" \
670 # Get the IANA port and supported protocols(tcp and udp)
672 tport
=`$SERVINFO -p -t -s $iana_name 2>&1`
673 if [ $?
-eq 0 -a -n "$tport" ]; then
674 generate_rules
$service $policy "tcp" $tport $file
677 tport6
=`$SERVINFO -p -t6 -s $iana_name 2>&1`
678 if [ $?
-eq 0 -a -n "$tport6" ]; then
679 generate_rules
$service $policy "tcp" $tport6 $file6 _6
682 uport
=`$SERVINFO -p -u -s $iana_name 2>&1`
683 if [ $?
-eq 0 -a -n "$uport" ]; then
684 generate_rules
$service $policy "udp" $uport $file
687 uport6
=`$SERVINFO -p -u6 -s $iana_name 2>&1`
688 if [ $?
-eq 0 -a -n "$uport6" ]; then
689 generate_rules
$service $policy "udp" $uport6 $file6 _6
696 # Given a service's name, policy, protocol and port, generate ipf rules
697 # - list of host/network/interface to apply policy
699 # A 'use_global' policy inherits the system-wided Global Default policy
700 # from network/ipfilter. For {deny | allow} policies, the rules are
703 # - make exceptions to policy for those in "exceptions" list
704 # - apply policy to those specified in "apply_to" list
717 # Default mode is to inherit from global's policy
719 [ "$mypolicy" = "use_global" ] && return 0
722 [ "$proto" = "tcp" ] && tcp_opts
="flags S keep state keep frags"
724 block_policy
=`get_block_policy $1`
725 if [ "$block_policy" = "use_global" ]; then
726 block_policy
=${GLOBAL_BLOCK_POLICY}
729 if [ "$block_policy" = "return" ]; then
730 [ "$proto" = "tcp" ] && block_policy
="return-rst"
731 [ "$proto" != "tcp" ] && block_policy
="return-icmp-as-dest"
736 iplist
=`get_target${_6}_list $service`
739 # Allow all if policy is 'none'
741 if [ "$mypolicy" = "none" ]; then
742 for ip
in $iplist; do
744 [ -z "$daddr" -o "$daddr" = '""' ] && continue
745 echo "pass in log quick proto ${proto} from any to ${daddr}" \
746 "port = ${port} ${tcp_opts}" >>${out}
752 # For now, let's concern ourselves only with incoming traffic.
754 [ "$mypolicy" = "deny
" ] && { ecmd="pass
"; acmd="block
${block_policy}"; }
755 [ "$mypolicy" = "allow
" ] && { ecmd="block
${block_policy}"; acmd="pass
"; }
757 for name in `get_exceptions${_6} $service`; do
758 [ -z "$name" -o "$name" = '""' ] && continue
760 ifc=`get_interface $name`
761 if [ $? -eq 0 -a -n "$ifc" ]; then
762 for ip in $iplist; do
764 [ -z "$daddr" -o "$daddr" = '""' ] && continue
765 echo "${ecmd} in log quick on
${ifc} from any to
" \
766 "${daddr} port = ${port}" >>${out}
771 saddr
=`get_IP ${name}`
772 if [ $?
-eq 0 -a -n "$saddr" ]; then
773 for ip
in $iplist; do
775 [ -z "$daddr" -o "$daddr" = '""' ] && continue
776 echo "${ecmd} in log quick proto ${proto} from ${saddr}" \
777 "to ${daddr} port = ${port} ${tcp_opts}" >>${out}
782 for name in `get_apply2${_6}_list $service`; do
783 [ -z "$name" -o "$name" = '""' ] && continue
785 ifc=`get_interface $name`
786 if [ $? -eq 0 -a -n "$ifc" ]; then
787 for ip in $iplist; do
789 [ -z "$daddr" -o "$daddr" = '""' ] && continue
790 echo "${acmd} in log quick on
${ifc} from any to
" \
791 "${daddr} port = ${port}" >>${out}
796 saddr
=`get_IP ${name}`
797 if [ $?
-eq 0 -a -n "$saddr" ]; then
798 for ip
in $iplist; do
800 [ -z "$daddr" -o "$daddr" = '""' ] && continue
801 echo "${acmd} in log quick proto ${proto} from ${saddr}" \
802 "to ${daddr} port = ${port} ${tcp_opts}" >>${out}
807 for ip in $iplist; do
809 [ -z "$daddr" -o "$daddr" = '""' ] && continue
810 echo "${ecmd} in log quick proto ${proto} from any to ${daddr}" \
811 "port
= ${port} ${tcp_opts}" >>${out}
818 # Service has either IANA ports and proto or its own firewall method to
819 # generate the rules.
821 # - if service has a custom method, use it to populate its rules
822 # - if service has a firewall_config pg, use process_server_svc
829 # Don't process network/ipfilter
831 [ "$1" = "$IPF_FMRI" ] && return 0
833 service_check_state
$1 $SMF_MAINT && return 1
835 method
=`svcprop -p $FW_CONTEXT_PG/$METHOD_PROP $1 2>/dev/null | \
837 if [ -n "$method" -a "$method" != '""' ]; then
838 ( exec $method $1 >/dev
/null
)
840 svcprop
-p $FW_CONFIG_PG $1 >/dev
/null
2>&1 ||
return 1
841 process_server_svc
$1 ||
return 1
847 # Generate rules for protocol/port defined in firewall_config_default/open_ports
848 # property. These are non-service programs whose network resource info are
849 # defined as "{tcp | upd}:{PORT | PORT-PORT}". Essentially, these programs need
850 # some specific local ports to be opened. For example, BitTorrent clients need to
851 # have 6881-6889 opened.
853 process_nonsvc_progs
()
856 echo "# Non-service programs rules" >>${out}
857 progs
=`global_get_prop_value $FW_CONFIG_DEF_PG $OPEN_PORTS_PROP`
859 for prog
in $progs; do
860 [ -z "$prog" -o "$prog" = '""' ] && continue
862 port
=`tuple_get_port $prog`
863 [ $?
-eq 1 -o -z "$port" ] && continue
865 proto
=`tuple_get_proto $prog`
866 [ $?
-eq 1 ] && continue
869 if [ $# -gt 1 ]; then
870 if [ -z "$proto" ]; then
871 echo "pass in log quick from any to any" \
872 "port ${1} >< ${2}" >>${out}
874 echo "pass
in log quick proto
${proto} from any
" \
875 "to any port
${1} >< ${2}" >>${out}
878 if [ -z "$proto" ]; then
879 echo "pass in log quick from any to any" \
880 "port = ${1}" >>${out}
882 echo "pass in log quick proto ${proto} from any" \
883 "to any port = ${1}" >>${out}
892 # Generate a new /etc/ipf/ipf.conf. If firewall policy is 'none',
893 # ipf.conf is empty .
895 create_global_rules
()
897 if [ "$GLOBAL_POLICY" = "custom" ]; then
898 file=`global_get_prop_value $FW_CONFIG_DEF_PG $CUSTOM_FILE_PROP`
899 file6
=`global_get_prop_value $FW_CONFIG_DEF_PG $CUSTOM_FILE_6_PROP`
901 [ -n "$file" ] && custom_set_symlink
$file
902 [ -n "$file6" ] && custom_set_symlink_6
$file6
907 TEMP
=`mktemp /var/run/ipf.conf.pid$$.XXXXXX`
908 TEMP6
=`mktemp /var/run/ipf6.conf.pid$$.XXXXXX`
909 process_nonsvc_progs
$TEMP
910 process_nonsvc_progs
$TEMP6
912 echo "# Global Default rules" >>${TEMP}
913 echo "# Global Default rules" >>${TEMP6}
914 if [ "$GLOBAL_POLICY" != "none" ]; then
915 echo "pass out log quick all keep state" >>${TEMP}
916 echo "pass out log quick all keep state" >>${TEMP6}
919 case "$GLOBAL_POLICY" in
922 replace_file
${IPFILCONF} ${TEMP}
923 replace_file
${IP6FILCONF} ${TEMP6}
941 for name
in `global_get_prop_value $FW_CONFIG_DEF_PG $EXCEPTIONS_PROP`; do
942 [ -z "$name" -o "$name" = '""' ] && continue
944 ifc
=`get_interface $name`
945 if [ $?
-eq 0 -a -n "$ifc" ]; then
946 echo "${ecmd} in log quick on ${ifc} all" >>${TEMP}
950 addr=`get_IP ${name}`
951 if [ $? -eq 0 -a -n "$addr" ]; then
952 echo "${ecmd} in log quick from ${addr} to any" >>${TEMP}
957 for name
in `global_get_prop_value $FW_CONFIG_DEF_PG $EXCEPTIONS_6_PROP`; do
958 [ -z "$name" -o "$name" = '""' ] && continue
960 ifc
=`get_interface $name`
961 if [ $?
-eq 0 -a -n "$ifc" ]; then
962 echo "${ecmd} in log quick on ${ifc} all" >>${TEMP6}
966 addr=`get_IP ${name}`
967 if [ $? -eq 0 -a -n "$addr" ]; then
968 echo "${ecmd} in log quick from ${addr} to any" >>${TEMP6}
973 for name
in `global_get_prop_value $FW_CONFIG_DEF_PG $APPLY2_PROP`; do
974 [ -z "$name" -o "$name" = '""' ] && continue
976 ifc
=`get_interface $name`
977 if [ $?
-eq 0 -a -n "$ifc" ]; then
978 echo "${acmd} in log quick on ${ifc} all" >>${TEMP}
982 addr=`get_IP ${name}`
983 if [ $? -eq 0 -a -n "$addr" ]; then
984 echo "${acmd} in log quick from ${addr} to any" >>${TEMP}
988 for name
in `global_get_prop_value $FW_CONFIG_DEF_PG $APPLY2_6_PROP`; do
989 [ -z "$name" -o "$name" = '""' ] && continue
991 ifc
=`get_interface $name`
992 if [ $?
-eq 0 -a -n "$ifc" ]; then
993 echo "${acmd} in log quick on ${ifc} all" >>${TEMP6}
997 addr=`get_IP ${name}`
998 if [ $? -eq 0 -a -n "$addr" ]; then
999 echo "${acmd} in log quick from ${addr} to any" >>${TEMP6}
1003 if [ "$GLOBAL_POLICY" = "allow" ]; then
1005 # Allow DHCP(v6) traffic if running as a DHCP client
1007 /sbin
/netstrategy |
grep dhcp
>/dev
/null
2>&1
1008 if [ $?
-eq 0 ]; then
1009 echo "pass out log quick from any port = 68" \
1010 "keep state" >>${TEMP}
1011 echo "pass in log quick from any to any port = 68" >>${TEMP}
1013 echo "pass out log quick from any port = 546" \
1014 "keep state" >>${TEMP6}
1015 echo "pass in log quick from any to any port = 546" >>${TEMP6}
1017 echo "block in log all" >>${TEMP}
1018 echo "block in log all" >>${TEMP6}
1021 replace_file
${IPFILCONF} ${TEMP}
1022 replace_file
${IP6FILCONF} ${TEMP6}
1027 # Generate a new /etc/ipf/ipf_ovr.conf, the override system-wide policy. It's
1028 # a simplified policy that doesn't support 'exceptions' entities.
1030 # If firewall policy is "none", no rules are generated.
1032 # Note that "pass" rules don't have "quick" as we don't want
1033 # them to override services' block rules.
1035 create_global_ovr_rules
()
1038 # Simply empty override file if global policy is 'custom'
1040 if [ "$GLOBAL_POLICY" = "custom" ]; then
1041 echo "# 'custom' global policy" >$IPFILOVRCONF
1042 echo "# 'custom' global policy" >$IP6FILOVRCONF
1047 # Get and process override policy
1049 ovr_policy
=`global_get_prop_value $FW_CONFIG_OVR_PG $POLICY_PROP`
1050 if [ "$ovr_policy" = "none" ]; then
1051 echo "# global override policy is 'none'" >$IPFILOVRCONF
1052 echo "# global override policy is 'none'" >$IP6FILOVRCONF
1056 TEMP
=`mktemp /var/run/ipf_ovr.conf.pid$$.XXXXXX`
1057 [ "$ovr_policy" = "deny" ] && acmd
="block in log quick"
1058 [ "$ovr_policy" = "allow" ] && acmd
="pass in log"
1060 apply2_list
=`global_get_prop_value $FW_CONFIG_OVR_PG $APPLY2_PROP`
1061 for name
in $apply2_list; do
1062 [ -z "$name" -o "$name" = '""' ] && continue
1064 ifc
=`get_interface $name`
1065 if [ $?
-eq 0 -a -n "$ifc" ]; then
1066 echo "${acmd} on ${ifc} all" >>${TEMP}
1070 addr=`get_IP ${name}`
1071 if [ $? -eq 0 -a -n "$addr" ]; then
1072 echo "${acmd} from ${addr} to any" >>${TEMP}
1076 apply2_6_list
=`global_get_prop_value $FW_CONFIG_OVR_PG $APPLY2_6_PROP`
1077 for name
in $apply2_6_list; do
1078 [ -z "$name" -o "$name" = '""' ] && continue
1080 ifc
=`get_interface $name`
1081 if [ $?
-eq 0 -a -n "$ifc" ]; then
1082 echo "${acmd} on ${ifc} all" >>${TEMP6}
1086 addr=`get_IP ${name}`
1087 if [ $? -eq 0 -a -n "$addr" ]; then
1088 echo "${acmd} from ${addr} to any" >>${TEMP6}
1092 replace_file
${IPFILOVRCONF} ${TEMP}
1093 replace_file
${IP6FILOVRCONF} ${TEMP6}
1098 # Service is put into maintenance state due to its invalid firewall
1099 # definition and/or policy.
1101 svc_mark_maintenance
()
1103 svcadm mark maintenance
$1 >/dev
/null
2>&1
1106 echo "[ $date ${0}: $1 has invalid ipf configuration. ]"
1107 echo "[ $date ${0}: placing $1 in maintenance. ]"
1110 # Move service's rule files to another location since
1111 # they're most likely invalid.
1113 ipfile
=`fmri_to_file $1 $IPF_SUFFIX`
1114 [ -f "$ipfile" ] && mv $ipfile "$ipfile.bak"
1115 ip6file
=`fmri_to_file $1 $IPF6_SUFFIX`
1116 [ -f "$ip6file" ] && mv $ip6file "$ip6file.bak"
1118 natfile
=`fmri_to_file $1 $NAT_SUFFIX`
1119 [ -f "$natfile" ] && mv $natfile "$natfile.bak"
1126 svcprop
-p $FW_CONFIG_PG $1 >/dev
/null
2>&1
1130 # Create rules for enabled firewalling and client services.
1131 # - obtain the list of enabled services and process them
1132 # - save the list of rules file for later use
1134 create_services_rules
()
1137 # Do nothing if global policy is 'custom'
1139 [ "$GLOBAL_POLICY" = "custom" ] && return 0
1144 # Get all enabled services
1146 allsvcs
=`svcprop -cf -p general/enabled -p general_ovr/enabled '*' \
1147 2>/dev/null | sed -n 's,^\(svc:.*\)/:properties/.* true$,\1,p' | sort -u`
1150 # Process enabled services
1152 for s
in $allsvcs; do
1153 service_is_enabled
$s ||
continue
1154 process_service
$s ||
continue
1156 ipfile
=`fmri_to_file $s $IPF_SUFFIX`
1157 if [ -n "$ipfile" -a -r "$ipfile" ]; then
1158 check_ipf_syntax
$ipfile
1159 if [ $?
-ne 0 ]; then
1160 svc_mark_maintenance
$s
1165 if [ $?
-eq 0 ]; then
1166 check_ipf_rules
$ipfile
1167 if [ $?
-ne 0 ]; then
1168 svc_mark_maintenance
$s
1172 CONF_FILES
="$CONF_FILES $ipfile"
1175 ip6file
=`fmri_to_file $s $IPF6_SUFFIX`
1176 if [ -n "$ip6file" -a -r "$ip6file" ]; then
1177 check_ipf_syntax
$ip6file -6
1178 if [ $?
-ne 0 ]; then
1179 svc_mark_maintenance
$s
1184 if [ $?
-eq 0 ]; then
1185 check_ipf_rules
$ip6file -6
1186 if [ $?
-ne 0 ]; then
1187 svc_mark_maintenance
$s
1191 CONF6_FILES
="$CONF6_FILES $ip6file"
1194 natfile
=`fmri_to_file $s $NAT_SUFFIX`
1195 if [ -n "$natfile" -a -r "$natfile" ]; then
1196 check_nat_syntax
$natfile
1197 if [ $?
-ne 0 ]; then
1198 svc_mark_maintenance
$s
1202 NAT_FILES
="$NAT_FILES $natfile"
1211 # We update a services ipf ruleset in the following manners:
1212 # - service is disabled, tear down its rules.
1213 # - service is disable or refreshed(online), setup or update its rules.
1215 service_update_rules
()
1219 ipfile
=`fmri_to_file $svc $IPF_SUFFIX`
1220 ip6file
=`fmri_to_file $svc $IPF6_SUFFIX`
1221 [ -n "$ipfile" ] && remove_rules
$ipfile
1222 [ -n "$ip6file" ] && remove_rules
$ip6file -6
1224 [ -z "$ipfile" -a -z "$ip6file" ] && return 0
1226 natfile
=`fmri_to_file $svc $NAT_SUFFIX`
1227 [ -n "$natfile" ] && remove_nat_rules
$natfile
1230 # Don't go further if service is disabled or in maintenance.
1232 service_is_enabled
$svc ||
return 0
1233 service_check_state
$1 $SMF_MAINT && return 0
1235 process_service
$svc ||
return 1
1236 if [ -f "$ipfile" ]; then
1237 check_ipf_syntax
$ipfile
1238 if [ $?
-ne 0 ]; then
1239 svc_mark_maintenance
$svc
1244 if [ -f "$ip6file" ]; then
1245 check_ipf_syntax
$ip6file -6
1246 if [ $?
-ne 0 ]; then
1247 svc_mark_maintenance
$svc
1252 if [ -f "$natfile" ]; then
1253 check_nat_syntax
$natfile
1254 if [ $?
-ne 0 ]; then
1255 svc_mark_maintenance
$svc
1260 if [ -f "$ipfile" ]; then
1262 if [ $?
-eq 0 ]; then
1263 update_check_ipf_rules
$ipfile
1264 if [ $?
-ne 0 ]; then
1265 svc_mark_maintenance
$svc
1270 prepend_new_rules
$ipfile
1273 # reload Global Override rules to
1274 # maintain correct ordering.
1276 remove_rules
$IPFILOVRCONF
1277 prepend_new_rules
$IPFILOVRCONF
1280 if [ -f "$ip6file" ]; then
1282 if [ $?
-eq 0 ]; then
1283 update_check_ipf_rules
$ip6file -6
1284 if [ $?
-ne 0 ]; then
1285 svc_mark_maintenance
$svc
1290 prepend_new_rules
$ip6file -6
1293 # reload Global Override rules to
1294 # maintain correct ordering.
1296 remove_rules
$IP6FILOVRCONF -6
1297 prepend_new_rules
$IP6FILOVRCONF -6
1300 [ -f "$natfile" ] && append_new_nat_rules
$natfile
1306 # Call the service_update_rules with appropriate svc fmri.
1308 # This is called from '/lib/svc/method/ipfilter fw_update' whenever
1309 # a service is disabled/enabled/refreshed.
1317 # If ipfilter isn't online or global policy is 'custom',
1318 # nothing should be done.
1320 [ "$GLOBAL_POLICY" = "custom" ] && return 0
1321 service_check_state
$SMF_FMRI $SMF_ONLINE ||
return 0
1324 service_update_rules
$svc || ret
=1
1331 # Initialize global configuration