#!/bin/sh # # Shorewall 4.1 -- /usr/share/shorewall/lib.accounting # # This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt] # # (c) 1999,2000,2001,2002,2003,2004,2005,2006,2007 - Tom Eastep (teastep@shorewall.net) # # Complete documentation is available at http://shorewall.net # # This program is free software; you can redistribute it and/or modify # it under the terms of Version 2 of the GNU General Public License # as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # This library is loaded by /usr/share/shorewall/compiler when the accounting file is # non-empty. # # # Process a record from the accounting file # process_accounting_rule() { rule= rule2= jumpchain= user1= accounting_error() { error_message "WARNING: Invalid Accounting rule" $action $chain $source $dest $proto $port $sport $user $mark } accounting_interface_error() { error_message "WARNING: Unknown interface $1 in " $action $chain $source $dest $proto $port $sport $user $mark } accounting_interface_verify() { verify_interface $1 || accounting_interface_error $1 } jump_to_chain() { if ! havechain $jumpchain; then if ! createchain2 $jumpchain No; then accounting_error return 2 fi fi rule="$rule -j $jumpchain" } do_ipp2p() { [ -n "$IPP2P_MATCH" ] || fatal_error "Your kernel and/or iptables does not have IPP2P match support" case $proto in *:*) proto=${proto#*:} ;; *) proto=tcp ;; esac rule="$rule -p $proto -m ipp2p --${port:-ipp2p}" } case $source in *:*) accounting_interface_verify ${source%:*} rule="$(source_ip_range ${source#*:}) $(match_source_dev ${source%:*})" ;; *.*.*.*|+*|!+*) rule="$(source_ip_range $source)" ;; -|all|any) ;; *) if [ -n "$source" ]; then accounting_interface_verify $source rule="$(match_source_dev $source)" fi ;; esac [ -n "$dest" ] && case $dest in *:*) accounting_interface_verify ${dest%:*} rule="$rule $(dest_ip_range ${dest#*:}) $(match_dest_dev ${dest%:*})" ;; *.*.*.*|+*|!*) rule="$rule $(dest_ip_range $dest)" ;; -|all|any) ;; *) accounting_interface_verify $dest rule="$rule $(match_dest_dev $dest)" ;; esac [ -n "$proto" ] && case $proto in -|any|all) ;; ipp2p|IPP2P|ipp2p:*|IPP2P:*) do_ipp2p ;; *) rule="$rule -p $proto" ;; esac multiport= [ -n "$port" ] && case $port in -|any|all) ;; *) if [ -n "$MULTIPORT" ]; then rule="$rule -m multiport --dports $port" multiport=Yes else rule="$rule --dport $port" fi ;; esac [ -n "$sport" ] && case $sport in -|any|all) ;; *) if [ -n "$MULTIPORT" ]; then [ -n "$multiport" ] && rule="$rule --sports $sport" || rule="$rule -m multiport --sports $sport" else rule="$rule --sport $sport" fi ;; esac [ -n "$user" ] && case $user in -|any|all) ;; *) [ "$chain" != OUTPUT ] && \ fatal_error "Invalid use of a user/group: chain is not OUTPUT but $chain" rule="$rule -m owner" user1="$user" case "$user" in !*+*) if [ -n "${user#*+}" ]; then rule="$rule ! --cmd-owner ${user#*+} " fi user1=${user%+*} ;; *+*) if [ -n "${user#*+}" ]; then rule="$rule --cmd-owner ${user#*+} " fi user1=${user%+*} ;; esac case "$user1" in !*:*) if [ "$user1" != "!:" ]; then temp="${user1#!}" temp="${temp%:*}" [ -n "$temp" ] && rule="$rule ! --uid-owner $temp " temp="${user1#*:}" [ -n "$temp" ] && rule="$rule ! --gid-owner $temp " fi ;; *:*) if [ "$user1" != ":" ]; then temp="${user1%:*}" [ -n "$temp" ] && rule="$rule --uid-owner $temp " temp="${user1#*:}" [ -n "$temp" ] && rule="$rule --gid-owner $temp " fi ;; !*) [ "$user1" != "!" ] && rule="$rule ! --uid-owner ${user1#!} " ;; *) [ -n "$user1" ] && rule="$rule --uid-owner $user1 " ;; esac ;; esac [ -n "$mark" ] && case $mark in -|any|all) mark= ;; !*) rule="$rule -m mark ! --mark ${mark#*!}" ;; *) rule="$rule -m mark --mark $mark" ;; esac case $action in COUNT) ;; DONE) rule="$rule -j RETURN" ;; *:COUNT) rule2="$rule" jumpchain=${action%:*} jump_to_chain || return ;; JUMP:*) jumpchain=${action#*:} jump_to_chain || return ;; *) jumpchain=$action jump_to_chain || return ;; esac [ "x${chain:=accounting}" = "x-" ] && chain=accounting ensurechain1 $chain if do_iptables -A $chain $(fix_bang $rule) ; then [ -n "$rule2" ] && run_iptables2 -A $jumpchain $rule2 progress_message " Accounting rule \"$action $chain $source $dest $proto $port $sport $user\" $DONE" save_progress_message_short " Accounting rule \\\"$action $chain $source $dest $proto $port $sport $user\\\" Added" else accounting_error fi } # # Set up Accounting # setup_accounting() # $1 = Name of accounting file { progress_message2 "$DOING Accounting..." save_progress_message "Setting up Accounting..." while read action chain source dest proto port sport user mark ; do process_accounting_rule done < $TMP_DIR/accounting if havechain accounting; then for chain in INPUT FORWARD OUTPUT; do run_iptables -I $chain -j accounting done fi }