#!/bin/sh #---------------------------------------------------------------------------- # /etc/rc.d/fwrules-helper-ipv6 __FLI4LVER__ # helper functions for packet filter rules # # Creation: 2003-07-05 jw5 # Last Update: $Id$ #---------------------------------------------------------------------------- . /etc/boot.d/base-helper . /etc/rc.d/fwrules-helper.common : ${IP6TABLES:=sbin_ip6tables} : ${fwh_state6:=/var/run/fwrules-helper.state.ipv6} : ${tmpl_dir6:=/etc/fwrules.tmpl} : ${ext_dir6:=/etc/rc.d} fw_tmp6=/tmp/fwrules-helper.$$ ip6tables_dynrules=/var/run/ip6tables.dynrules ip6tables_dynrules_idx=/var/run/ip6tables.dynrules.next ip6tables_rules=/var/run/ip6tables.rules ip6tables_complexchains=/var/run/ip6tables.complex-chains fw_chain_suffix= dummy_rule6="::1 !::1 ACCEPT" create_next_dynrule6() { phidx=$(cat $ip6tables_dynrules_idx) echo $((phidx+1)) > $ip6tables_dynrules_idx dummy_comment="(PLACEHOLDER:$phidx)" comment="$comment $dummy_comment" cat <<-EOF > $ip6tables_dynrules/$phidx.rule dyn_ips="$dyn_ips" dyn_ifs="$dyn_ifs" table=$orig_table chain=$orig_chain rule="$full_rule" comment="$comment" dummy_rule="$dummy_rule6" dummy_comment="$dummy_comment" EOF } # $1 = table # $2 = chain get_next_rule_index6() { table=$1 chain=$2 file=$ip6tables_rules/$table/$chain.next if [ ! -f $file ] then echo 1 else echo $(($(cat $file)+1)) fi } ip6tables_rules_added=0 reset_rules_added6 () { ip6tables_rules_added=0 } get_rules_added6 () { eval $1=$ip6tables_rules_added } set_rules_added6 () { ip6tables_rules_added=$1 } sbin_ip6tables () { if ! /sbin/ip6tables "$@" > $fw_tmp6 2>&1 then log_error "Error executing ip6tables $@" log_error < $fw_tmp6 rc=1 else ip6tables_rules_added=`expr $ip6tables_rules_added + 1` rc=0 fi rm -f $fw_tmp6 [ "$op" = R ] && op=I [ "$op" = I ] && position=$((position+1)) return $rc } [ "$IPV6_NET_N" ] || . /var/run/ip6_net.conf # read extensions for i in $ext_dir6/fwrules-*.ext.ipv6 do if [ -f $i ] then if sh -c ". $i" > $fw_tmp6 2>&1 then . $i else log_error "Error parsing extension $i, rules with this extension in them will fail." log_error < $fw_tmp6 fi rm -f $fw_tmp6 fi done assert_empty6 () { case x$2 in x) ;; *) set_error "$1: to many subexpressions after translation" ;; esac } get_limit6() { limit= case x"$1" in x | xnone) ;; *) set -- `echo $1 | sed -e 's/:/ /'` case x$2 in x) limit="-m limit --limit $1" ;; *) limit="-m limit --limit $1 --limit-burst $2" ;; esac ;; esac } # mangle_params6 param option # - replace ':' with ' ', '-' with ':' mangle_params6 () { echo $1 | sed -e "s/:/ /g;s/\([0-9]\+\)-\([0-9]\+\)/\1:\2/g;" } do6_recent_param () { eval `echo $1 | sed -e 's/^\([a-z]*\)=\(.*\)/recent_tok=\1;recent_val=\2/'` recent_opt="$recent_opt --$recent_tok $recent_val" } do6_recent () { recent_opt= set -- `echo $1 | sed -e 's/,/ /g'` while [ "$1" ]; do case $1 in \!*) recent_param=`echo $1 | sed -e 's/^!//'` recent_neg='!' ;; *) recent_param="$1" recent_neg= ;; esac case $recent_param in name=* | seconds=* | hitcount=*) do6_recent_param $recent_param ;; set | update | rcheck | remove) recent_opt="$recent_opt $recent_neg --$recent_param" ;; rttl | rsource | rdest) recent_opt="$recent_opt --$recent_param" ;; *) set_error "recent: unknown option $recent_param" ;; esac shift done match_opt="$match_opt -m recent $recent_opt" } # mangle_ip_params6 param option # in: ip:port, ip or port[-range] # out: ip, ip_neg_opt; port, port_neg_opt, tcp_udp_needed # replaces '-' with ':' if $2 is empty # FQDNs are mapped to ipsets instead to IP addresses if $3 is empty mangle_ip_params6 () { dnsipset= param=$1 keepslash=$2 nomap=$3 case $param in \[*\]:*) set -- `echo $param | sed -e 's/\[//;s/]:/ /'` ip=$1 port=$2 tcp_udp_needed='yes' ;; \[*\]) set -- `echo $param | sed -e 's/\[//;s/]//'` ip=$1 port='' ;; *) if matches_port "$param" then ip=::/0 port=$param tcp_udp_needed='yes' else ip=$param port='' fi ;; esac get_negation6 $ip ip=$param ip_neg_opt="$neg_opt" get_negation6 $port port=$param port_neg_opt="$neg_opt" [ "$port" -a ! "$keepslash" ] && port="`echo $port | sed -e 's/-/:/'`" if [ "${ip#@}" != "$ip" ] then local host="${ip#@}" if ! lookup_name_ipv6 "$host" then # it's an external host name to be resolved by DNS eval $(grep "^\(OPT_DNS\|DNS_SUPPORT_IPV6\)=" /etc/rc.cfg) if [ ! "$nomap" -a "$OPT_DNS" = "yes" -a "$DNS_SUPPORT_IPV6" = "yes" ] then create_next_ipset res="${res}6" dnsipset=1 else set_error fi return else # it's an internal host name if [ -z "$res" ] then dynamic=1 dyn_ips="$dyn_ips $ip" return fi fi fi if is_static_ip6_net $ip then translate_ip6_net $ip || set_error else dynamic=1 if ! translate_ip6_net $ip "" "" 1 then dyn_ips="$dyn_ips $ip" fi fi if [ -n "$res" ] then normalize_network $res ip=$res fi } # get_negation6 param # - removes '!' from param and sets neg_opt accordingly get_negation6 () { case $1 in !*) param=`echo $1 | sed -e 's/^!//g'` neg_opt='! ' ;; *) param=$1 neg_opt='' ;; esac } # # default matches # recent6_p=yes prot6_p=yes state6_p=yes length6_p=yes limit6_p=yes mark6_p=yes if6_p=yes mac6_p=yes # do6_something handle "something:" statments # # do6_prot param opt # - handles "prot:" statements do6_prot () { set -- `mangle_params6 $1` proto=$1 opt=$2 case $proto in icmpv6) assert_empty6 "do6_prot $*" "$3" ;; *) assert_empty6 "do6_prot $*" "$2" ;; esac get_negation6 $proto case $param in any) ;; icmpv6) prot_opt="${neg_opt}-p icmpv6" case x$opt in x) ;; *) get_negation6 $opt prot_opt="$prot_opt ${neg_opt}--icmpv6-type $param" ;; esac ;; *) handle_l4prot "$param" prot_opt="${neg_opt}-p $param" ;; esac } do6_mark () { get_negation6 $1 match_opt="$match_opt -m mark ${neg_opt}--mark $param" } do6_state () { get_negation6 $1 match_opt="$match_opt -m conntrack ${neg_opt}--ctstate $param" } do6_length () { param=`mangle_params6 $1` get_negation6 $param match_opt="$match_opt -m length ${neg_opt}--length $param" } do6_limit () { get_limit6 $1 match_opt="$match_opt $limit" } do6_mac () { get_negation6 $1 match_opt="$match_opt -m mac ${neg_opt}--mac-source $param" } do6_if_opt () { local real_if= if is_static_net_if $3 then translate_net_if $3 real_if else dynamic=1 if ! translate_net_if $3 real_if 1 then dyn_ifs="$dyn_ifs $3" fi fi if [ -n "$real_if" ] then [ "$real_if" != "any" ] && if_opt="$if_opt $1$2 $real_if" fi } do6_if () { set -- `mangle_params6 $1` assert_empty6 "do6_if $*" "$3" get_negation6 $1 if_in=$param if_in_negopt="$neg_opt" get_negation6 $2 if_out=$param if_out_negopt="$neg_opt" do6_if_opt "$if_in_negopt" -i $if_in do6_if_opt "$if_out_negopt" -o $if_out } do6_default () { rule="$*" full_rule_suffix= case "$rule" in *BIDIRECTIONAL*) rule=`echo $rule | sed -e 's#\(.*\)BIDIRECTIONAL\(.*\)#\1\2#'` bidirectional='yes' full_rule_suffix="$full_rule_suffix BIDIRECTIONAL" ;; esac case "$rule" in *DROP*|*REJECT*|*ACCEPT*|*SNAT*|*DNAT*|*NETMAP*|*MASQUERADE*|*REDIRECT*|*HELPER*) case "$rule" in *NOLOG*) rule=`echo $rule | sed -e 's#\(.*\)NOLOG[^[:space:]]*\(.*\)#\1\2#'` full_rule_suffix="$full_rule_suffix NOLOG" log_opt='no' ;; *LOG*) log_prefix="`echo $rule | sed -e 's#.*LOG:\?\([^[:space:]]*\).*#\1#'`" log_opt='yes' rule=`echo $rule | sed -e 's#\(.*\)LOG[^[:space:]]*\(.*\)#\1\2#'` full_rule_suffix="$full_rule_suffix LOG" [ -n "$log_prefix" ] && full_rule_suffix="${full_rule_suffix}:$log_prefix" ;; esac ;; esac set -- $rule # rewrite arguments case "$#" in 3) src=$1 dst=$2 action=$3 ;; 2) case $1 in \[*\]:* | dynamic* | \[dynamic\]*) dst=$1 ;; *) # port without destination address (used by templates only!) if matches_port "$1" then dst=$1 else src=$1 fi ;; esac action=$2 ;; 1) action=$1 ;; *) set_error "*** Error in rule $rule ***" ;; esac mangle_ip_params6 $src "" nomap if is_error then set_error "$rule: error while processing source '$src'" return 1 fi src_unmapped=$src if [ -n "$dnsipset" ] then match_opt="$match_opt -m set ${ip_neg_opt}--match-set $res src" src=::/0 src_neg= else src="$ip" src_neg="$ip_neg_opt" fi case "x$port" in x) ;; *,*) src_port_opt="-m multiport ${port_neg_opt} --source-ports $port" ;; *) src_port_opt="${port_neg_opt} --source-port $port" ;; esac if [ -z "$in_template" ] then full_src="$ip_neg_opt" if [ -n "$port" ] then full_src="$full_src[$ip]:$(echo $port | sed 's/:/-/')" else full_src="$full_src$ip" fi fi mangle_ip_params6 $dst if is_error then set_error "$rule: error while processing destination '$dst'" return 1 fi dst_unmapped=$dst if [ -n "$dnsipset" ] then match_opt="$match_opt -m set ${ip_neg_opt}--match-set $res dst" dst=::/0 dst_neg= else dst="$ip" dst_neg="$ip_neg_opt" fi [ -n "$port" ] && dport=$port case "x$port" in x) ;; *,*) dst_port_opt="-m multiport ${port_neg_opt} --destination-ports $port" ;; *) dst_port_opt="${port_neg_opt} --destination-port $port" ;; esac if [ -z "$in_template" ] then full_dst="$ip_neg_opt" if [ -n "$dport" ] then full_dst="$full_dst[$ip]:$(echo $dport | sed 's/:/-/')" else full_dst="$full_dst$ip" fi full_rule="$full_rule $full_src $full_dst $action $full_rule_suffix" fi action_opt= case $action in NONE) ;; DROP) case x$log_prefix in x) action_opt="$drop";; *) action_opt="$action";; esac ;; REJECT) case x$log_prefix in x) action_opt="$reject";; *) action_opt="$action";; esac ;; MARK:*) val=`echo $action | sed -e 's/MARK://'` action_opt="MARK --set-mark $val" ;; MASQUERADE:*) mangle_ip_params6 `echo $action | sed -e 's/MASQUERADE://'` keepslash nomap action_opt="MASQUERADE" [ "$port" ] && action_opt="$action_opt --to-ports $port" ;; SNAT:*) mangle_ip_params6 `echo $action | sed -e 's/SNAT://'` keepslash nomap ip=$(list_last $ip) ip=${ip%/*} action_opt="SNAT --to-source [$ip]" [ "$port" ] && action_opt="$action_opt:$port" ;; NETMAP:*) mangle_ip_params6 `echo $action | sed -e 's/NETMAP://'` keepslash nomap ip=$(list_last $ip) action_opt="NETMAP --to ${ip}" ;; DNAT:*) mangle_ip_params6 `echo $action | sed -e 's/DNAT://'` keepslash nomap ip=$(list_last $ip) ip=${ip%/*} action_opt="DNAT --to-dest [$ip]" [ "$port" ] && action_opt="$action_opt:$port" ;; REDIRECT:*) mangle_ip_params6 `echo $action | sed -e 's/REDIRECT://'` keepslash nomap : ${port:=$dport} action_opt="REDIRECT --to-ports $port" ;; HELPER:*) helper=`echo $action | sed -e 's/HELPER://'` action_opt="CT --helper $helper" handle_ct_helper $helper ipv6 ;; LOG:*) log_prefix="`echo $action | sed -e 's/LOG://'`" action_opt=LOG ;; *) action_opt="$action" ;; esac } execute_log_statement6 () { case x$log_prefix in x) $IP6TABLES -t $table -$op $chain $position $1 -m comment --comment "$comment" -j LOG $log_level ;; *) $IP6TABLES -t $table -$op $chain $position $1 -m comment --comment "$comment" -j LOG --log-prefix "$log_prefix " $log_level ;; esac } # prot:(tcp|udp|gre|[0-9]{1,3}) if:in:out state:RELATED,ESTABLISHED,NEW,INVALID src[:port-port] dest[:port-port] accept|reject|drop really_execute_iptables6 () { do_action=$2 do_log='' case $do_action in *drp-log | *rej-log) if [ "$log_opt" = 'no' ] then do_action=`echo $do_action | sed -e 's#^\(.*\)-log#\1#'` fi ;; *drp | *rej) if [ "$log_opt" = 'yes' ] then do_action=${do_action}-log fi ;; *) do_log="$log_opt" ;; esac set -f case "$do_log" in yes) execute_log_statement6 "$1" $IP6TABLES -t $table -$op $chain $position $1 -m comment --comment "$comment" -j $do_action ;; *) case $do_action in LOG) execute_log_statement6 "$1" ;; *) $IP6TABLES -t $table -$op $chain $position $1 -m comment --comment "$comment" -j $do_action ;; esac ;; esac set +f } exec_iptables6 () { table=$1 chain=$2 case $op in I|R) ;; *) position= ;; esac local s d for s in $src do for d in $dst do opts="$if_opt $match_opt ${src_neg}-s $s $src_port_opt ${dst_neg}-d $d $dst_port_opt" if [ -z "$tcp_udp_needed" -o "$prot_opt" ] then really_execute_iptables6 "$prot_opt $opts" "$action_opt" else really_execute_iptables6 "-p tcp $opts" "$action_opt" really_execute_iptables6 "-p udp $opts" "$action_opt" fi done done } init_options6 () { table=$1 chain=$2 op=$3 comment=$4 if_opt='' match_opt='' prot_opt='' src='any' src_neg='' src_port_opt='' src_unmapped='any' dst='any' dst_neg='' dst_port_opt='' dst_unmapped='any' dport= action_opt='' tcp_udp_needed='' bidirectional='' log_opt='' log_prefix='' log_target='LOG' dyn_ips= dyn_ifs= dynamic= full_rule= if [ -f $fwh_state6.$chain ] then . $fwh_state6.$chain else drop=DROP reject=REJECT fi } parse_rule6 () { parse_rule_param="$1" while true do set -- $parse_rule_param local first="$1" eval `echo $1 | sed -e 's/^[[:space:]]*/#/;s/^#\([a-z][[:alnum:]]\+\):\([^[:space:]]*\).*/present=\$\16_p;ext=\1;val=\2/;s/^#.*/ext=;/;s/.*ext=any.*/ext=/'` case x$ext in x) do6_default $* return $? ;; *) shift parse_rule_param="$*" case $present in yes) full_rule="$full_rule $ext:$val" eval do6_$ext $val ;; *) if echo "$ext" | grep -q "^[a-fA-F0-9]\+$" then # assuming IPv6 address do6_default $first $* return $? else log_error "invalid match $ext:" fi ;; esac ;; esac done } exec_rule6 () { if [ -n "$dynamic" ] && ! echo "$comment" | grep -q "(PLACEHOLDER:[0-9]\+)$" then case $orig_op in A|I|R) create_next_dynrule6 ;; *) ;; esac fi if [ -n "$dyn_ips$dyn_ifs" ] then save_full_rule="$full_rule" do_rule6 "$orig_table" "$orig_chain" "$orig_op" "$dummy_rule6" "$position" exec_rule6 "$comment" rc=$? full_rule="$save_full_rule" return $rc else $pre_exec if [ "$bidirectional" = 'yes' ] then exec_iptables6 $table $chain swp=$src swp_neg=$src_neg swp_port_opt=$src_port_opt src=$dst src_neg=$dst_neg src_port_opt=$(echo $dst_port_opt | sed 's/--destination-port/--source-port/') dst=$swp dst_neg=$swp_neg dst_port_opt=$(echo $swp_port_opt | sed 's/--source-port/--destination-port/') if_opt=`echo $if_opt | sed -e 's#-i #-x #' -e 's#-o #-i #' -e 's#-x #-o #'` fi exec_iptables6 $table $chain fi } exec_access_rule6() { rule="$full_rule" new_rule= # let extensions unchanged while true do set -- $rule eval `echo $1 | sed -e 's/^[[:space:]]*/#/;s/^#\([a-z][[:alnum:]]\+\):\([^[:space:]]*\).*/present=\$\1_p;ext=\1;val=\2/;s/^#.*/ext=;/;s/.*ext=any.*/ext=/'` case x$ext in x) break ;; *) new_rule="$new_rule $1" shift rule="$*" ;; esac done # extract source, destination, actions set -- $rule src=$1 dst=$2 action=$3 shift 3 rule_tail="$*" # split destination into address and port (if available) set -- $(echo $dst | sed -e 's/\[//;s/]:/ /;s/]//') dst="[$1]" dport=$2 # override parts of destination, according to PREROUTING rule case $action in DNAT:*) chain=PORTFWACCESS set -- $(echo $action | sed 's/^DNAT://;s/\[//;s/]:/ /;s/]//') dst="[$1]" [ -n "$2" ] && dport=$2 ;; REDIRECT:*) chain=PORTREDIRACCESS set -- $(echo $action | sed 's/^REDIRECT://') dport=$1 ;; *) # no access rules for targets other then DNAT or REDIRECT return ;; esac # combine parts to form the new FORWARD rule new_rule="$new_rule $src $dst" [ -n "$dport" ] && new_rule="$new_rule:$dport" new_rule="$new_rule ACCEPT $rule_tail" # add rule to the FORWARD chain do_rule6 filter $chain "$orig_op" "$new_rule" "$position" exec_rule6 "$comment" } exec_prerouting_rule6() { exec_rule6 || return $? get_rules_added6 saved_rules_added exec_access_rule6 local rc=$? set_rules_added6 $saved_rules_added return $rc } read_tmpl () { local tmpl_name=$1 { if [ -e $tmpl_dir6/$tmpl_name ] then cat $tmpl_dir6/$tmpl_name else tmpl_name=$(echo $tmpl_name | tr "A-Z" "a-z") sed -n "s/^$tmpl_name[[:space:]]\+//p" $tmpl_dir6/templates fi } | sed -e "s/#.*//;/^[[:space:]]*$/d" } # do_rule6 table chain operation rule position method comment do_rule6 () { case x$FWRULES6_DO_DEBUG in x) set +x; ;; esac local orig_table=$1 local orig_chain=$2 local orig_op=$3 local orig_rule="$4" local full_orig_rule="$4" local position=$5 local method="$6" local orig_comment="$7" : ${method:=exec_rule6} : ${orig_comment:="$orig_rule"} reset_rules_added6 case "$orig_rule" in *tmpl:*) eval set -- `echo "$orig_rule" | sed -e "s#\(.*\)[[:space:]:]*tmpl:\([^[:space:]]*\)\(.*\)#'\1' '\2' '\3'#"` rule_head="$1" rule_tail="$3" orig_rule="$rule_head $rule_tail" local orig_tmpl_name=$2 local orig_position=$position : ${orig_position:=1} tmpl_rules="`read_tmpl $2`" if [ -n "$tmpl_rules" ] then while read tmpl_rule do init_options6 $orig_table $orig_chain $orig_op "$orig_comment" in_template=yes parse_rule6 "$tmpl_rule DROP" in_template= parse_rule6 "$orig_rule" if ! is_error then if [ -n "$bidirectional" ] then set_error "$full_orig_rule: using templates and BIDIRECTIONAL simultaneously is not allowed" else $method fi else set_error fi get_rules_added6 rules_added position=`expr $orig_position + $rules_added` done < /dev/null 2>&1; then do_chain6 $1 test-chain N add-test-chain fi do_rule6 $1 $2 A "$3" '' "$4" "$3" if [ -f $base_log_file ]; then echo "Invalid rule '$3'" cat $base_log_file rm -f $base_log_file dcr_res=1 else do_rule6 $1 $2 D "$3" '' "$4" "$3" fi unset pre_exec unset base_colecho unset base_log_file return $dcr_res } check_rule6 () { : ${SCRIPT:=check_rule6} do_check_rule6 filter foo "$1" '' } # setup_logging6 # setup_logging6 () { enabled=$1 chain=$2 prefix="$3" log_limit="$4" rej_limit="$5" udp_rej_limit="$6" log_level=$7 get_limit6 "$log_limit" log_limit="$limit" get_limit6 "$rej_limit" rej_limit="$limit" get_limit6 "$udp_rej_limit" udp_rej_limit="$limit" case $chain in FORWARD) drop="fw-drp" reject="fw-rej" ;; INPUT) drop="in-drp" reject="in-rej" ;; OUTPUT) drop="out-drp" reject="out-rej" ;; *) log_error "setup_loggig: unknown chain $chain" drop="un-drp" reject="un-rej" ;; esac cat <<-EOF > $fwh_state6.$chain drop_name=$drop reject_name=$reject EOF case x$log_level in x) ;; *) log_level="--log-level $log_level" echo "log_level='$log_level'" >> $fwh_state.$chain ;; esac $IP6TABLES -N ${drop} $IP6TABLES -N ${drop}-log $IP6TABLES -N ${reject} $IP6TABLES -N ${reject}-log $IP6TABLES -N ${reject}-fin $IP6TABLES -A ${drop}-log $log_limit -j LOG --log-prefix "${prefix}-drop " $log_level $IP6TABLES -A ${drop}-log -j DROP $IP6TABLES -A ${drop} -j DROP $IP6TABLES -A ${reject}-log $log_limit -j LOG --log-prefix "${prefix}-reject " $log_level $IP6TABLES -A ${reject}-log -j ${reject} $IP6TABLES -A ${reject} -p udp $udp_rej_limit -j ${reject}-fin $IP6TABLES -A ${reject} ! -p udp $rej_limit -j ${reject}-fin $IP6TABLES -A ${reject} -j DROP case $reject in *in*) $IP6TABLES -A ${reject}-fin -p tcp -j REJECT --reject-with tcp-reset $IP6TABLES -A ${reject}-fin -p udp -j REJECT --reject-with port-unreach $IP6TABLES -A ${reject}-fin -j DROP ;; *) $IP6TABLES -A ${reject}-fin ! -p icmpv6 -j REJECT --reject-with icmp6-adm-prohibited $IP6TABLES -A ${reject}-fin -j DROP ;; esac case $enabled in yes) drop="${drop}-log" reject="${reject}-log" ;; *) drop=DROP ;; esac cat <<-EOF >> $fwh_state6.$chain drop=$drop reject=$reject EOF } # get log chain names and default drop/reject actions get_defaults6 () { . $fwh_state6.$1 } # close_chain close_chain6 () { . $fwh_state6.$1 case "$2" in DROP) $IP6TABLES -A $1-tail -j $drop ;; REJECT) $IP6TABLES -A $1-tail -j $reject ;; ACCEPT) $IP6TABLES -P $1 ACCEPT ;; esac } do_chain6 () { local table=$1 local chain=$2 local op=$3 local name=$4 if ! $IP6TABLES -t $table -$op $chain then log_error "${name} $chain failed..." fi } #################################### # OBSOLETE FIREWALL API, DON'T USE # #################################### # add_rule6 table chain rule comment method add_rule6 () { log_warn "add_rule6 is obsolete and has been replaced by fw_append_rule6" fw_append_rule6 "$@" } # del_rule6 table chain rule comment method del_rule6 () { log_warn "del_rule6 is obsolete and has been replaced by fw_delete_rule6" fw_delete_rule6 "$@" } # ins_rule6 table chain rule position comment method ins_rule6 () { local pos=${4:-1} if [ $pos -eq $FW_DUMMY_COUNT ] then # warning has already been printed by get_count6() fw_append_rule6 "$1" "$2" "$3" "$5" "$6" else log_warn "ins_rule6 is obsolete and has been replaced by fw_insert_rule6" fw_insert_rule6 "$1" "$2" "$4" "$3" "$5" "$6" fi } set_count6 () { log_warn "set_count6 is obsolete, don't use it anymore" } get_count6 () { log_warn "get_count6/ins_rule6 is obsolete, use fw_append_rule6 instead" res=$FW_DUMMY_COUNT } chain_present6 () { local table=$2 : ${table:=filter} log_warn "chain_present6 is obsolete and has been replaced by fw_is_chain_present6 $table" fw_is_chain_present6 $table $1 } nat_chain_present6 () { log_warn "nat_chain_present6 is obsolete and has been replaced by fw_is_chain_present6 nat" fw_is_chain_present6 nat $1 } add_chain6 () { log_warn "add_chain6 is obsolete and has been replaced by fw_add_chain6 filter" fw_add_chain6 filter $1 } add_nat_chain6 () { log_warn "add_nat_chain6 is obsolete and has been replaced by fw_add_chain6 nat" fw_add_chain6 nat $1 } flush_chain6 () { log_warn "flush_chain6 is obsolete, simply use fw_delete_chain6 filter" do_chain6 filter $1 F flush } flush_nat_chain6 () { log_warn "flush_nat_chain6 is obsolete, simply use fw_delete_chain6 nat" do_chain6 nat $1 F flush } del_chain6 () { log_warn "del_chain6 is obsolete and has been replaced by fw_add_chain6 filter" fw_delete_chain6 filter $1 } del_nat_chain6 () { log_warn "del_nat_chain6 is obsolete and has been replaced by fw_add_chain6 nat" fw_delete_chain6 nat $1 } ################ # FIREWALL API # ################ # Adds a simple IPv6 firewall chain. # # Input: # $1 = table to use # $2 = name of chain fw_add_chain6() { do_chain6 $1 $2 N fw_add_chain6 } # Checks whether an IPv6 firewall chain is present. # # Input: # $1 = table to use # $2 = name of chain # Exit code: # zero if the chain is present, non-zero otherwise fw_is_chain_present6() { ip6tables -t $1 -L $2 > /dev/null 2>&1 } # Makes an IPv6 firewall chain a complex one with JUMPs to three entries: # $name-head, $name-middle, $name-tail # This allows for simple appending of rules without having to count rules. # # Input: # $1 = table to use # $2 = name of chain fw_convert_to_complex_chain6() { fw_is_chain_present6 $1 $2 || return 1 if fw_add_chain6 $1 $2-head then if fw_add_chain6 $1 $2-middle then if fw_add_chain6 $1 $2-tail then do_chain6 $1 $2 F fw_convert_to_complex_chain6 $IP6TABLES -t $1 -A $2 -j $2-head $IP6TABLES -t $1 -A $2 -j $2-middle $IP6TABLES -t $1 -A $2 -j $2-tail mkdir -p $ip6tables_complexchains/$1 > $ip6tables_complexchains/$1/$2 return 0 fi fw_delete_chain6 $1 $2-middle fi fw_delete_chain6 $1 $2-head fi return 1 } # Determines if a chain is a complex IPv6 firewall chain. # # Input: # $1 = table to use # $2 = name of chain fw_is_complex_chain6() { [ -f $ip6tables_complexchains/$1/$2 ] } # Removes an IPv6 firewall chain. # # Input: # $1 = table to use # $2 = name of chain fw_delete_chain6() { if fw_is_complex_chain6 $1 $2 then rm -f $ip6tables_complexchains/$1/$2 fw_delete_chain6 $1 $2-head fw_delete_chain6 $1 $2-middle fw_delete_chain6 $1 $2-tail fi do_chain6 $1 $2 F fw_delete_chain6 do_chain6 $1 $2 X fw_delete_chain6 } # Locks an IPv6 firewall chain. # # Input: # $1 = table # $2 = chain # $3 = caller fw_lock_chain6() { sync_lock_resource "ip6tables:$1:$2" $3 } # Unlocks an IPv6 firewall chain. # # Input: # $1 = table # $2 = chain # $3 = caller fw_unlock_chain6() { sync_unlock_resource "ip6tables:$1:$2" $3 } # Appends a rule to a IPv6 firewall chain. If the chain is a complex chain, # the rule is appended to the -middle chain, unless fw_chain_suffix is set # (in this case $fw_chain_suffix is appended to the name of the chain). # # Input: # $1 = table # $2 = chain # $3 = rule # $4 = comment # $5 = method fw_append_rule6() { local pf_table=$1 local pf_chain=$2 local pf_rule="$3" local pf_comment="$4" local pf_method="$5" if fw_is_complex_chain6 $pf_table $pf_chain then pf_chain=$pf_chain${fw_chain_suffix:--middle} fi local pf_file=$ip6tables_rules/$pf_table/$pf_chain fw_lock_chain6 $pf_table $pf_chain fw_append_rule do_rule6 $pf_table $pf_chain A "$pf_rule" "" "$pf_method" "$pf_comment" fw_unlock_chain6 $pf_table $pf_chain fw_append_rule if is_error then set_error else add_rule_to_file fi } # Prepends a rule to an IPv6 firewall chain. If the chain is a complex chain, # the rule is prepended to the -middle chain, unless fw_chain_suffix is set # (in this case $fw_chain_suffix is appended to the name of the chain). # # Input: # $1 = table # $2 = chain # $3 = rule # $4 = comment # $5 = method fw_prepend_rule6() { fw_insert_rule6 $1 $2 1 "$3" "$4" "$5" } # Inserts a rule into an IPv6 firewall chain at a specific position. If the # chain is a complex chain, the rule is appended to the -middle chain, unless # fw_chain_suffix is set (in this case $fw_chain_suffix is appended to the name # of the chain). # # Input: # $1 = table # $2 = chain # $3 = position (set to 1 if empty) # $4 = rule # $5 = comment # $6 = method fw_insert_rule6() { local pf_table=$1 local pf_chain=$2 local pf_pos=${3:-1} local pf_rule="$4" local pf_comment="$5" local pf_method="$6" if fw_is_complex_chain6 $pf_table $pf_chain then pf_chain=$pf_chain${fw_chain_suffix:--middle} fi local pf_file=$ip6tables_rules/$pf_table/$pf_chain fw_lock_chain6 $pf_table $pf_chain fw_insert_rule do_rule6 $pf_table $pf_chain I "$pf_rule" $pf_pos "$pf_method" "$pf_comment" fw_unlock_chain6 $pf_table $pf_chain fw_insert_rule if is_error then set_error else add_rule_to_file fi } # Deletes a rule from an IPv6 firewall chain. If the chain is a complex chain, # the rule is deleted from the -middle chain, unless fw_chain_suffix is set # (in this case $fw_chain_suffix is appended to the name of the chain). # # Input: # $1 = table # $2 = chain # $3 = rule # $4 = comment # $5 = method fw_delete_rule6() { local pf_table=$1 local pf_chain=$2 local pf_rule="$3" local pf_comment="$4" local pf_method="$5" if fw_is_complex_chain6 $pf_table $pf_chain then pf_chain=$pf_chain${fw_chain_suffix:--middle} fi local pf_file=$ip6tables_rules/$pf_table/$pf_chain fw_lock_chain6 $pf_table $pf_chain fw_append_rule do_rule6 $pf_table $pf_chain D "$pf_rule" "" "$pf_method" "$pf_comment" fw_unlock_chain6 $pf_table $pf_chain fw_append_rule if is_error then set_error else del_rule_from_file fi }