#!/bin/sh
#
# Generate mangle rules to set fwmark for a host
# Note: --classify is a much superior to --set-mark, but OpenWRT
#       as of February 2005 had a kernel that didn't support --classify
#
# $1 - hostname
# $2 - source ip range
# $3 - destination ip range (use 0.0.0.0/0 for all)
# $4 - priority class
# $5 - medium class
# $6 - bulk class
# $7 - "incoming" or "outgoing"

if [ -z "$6" ]; then
    echo "$0 should not be run without parameters"
    exit 1
fi

CHAIN=$1
SOURCE_IP=$2
DEST_IP=$3
CLASS_PRIO=$4
CLASS_MEDIUM=$5
CLASS_BULK=$6
DIRECTION=$7

# Change chain name to add "_in" or "_out"
if [ $DIRECTION = incoming ]; then
    CHAIN=${CHAIN}_in
else
    CHAIN=${CHAIN}_out
fi

# Create new chain for this host
iptables -t mangle -N $CHAIN

# Send packets through this chain if they match source and destination
if [ $DIRECTION = incoming ]; then
    # Check after NAT rewriting by using the postrouting chain
    echo "    * directing $SOURCE_IP -> $LAN_IF:$DEST_IP to iptables chain $CHAIN"
    iptables -t mangle -A POSTROUTING -o $LAN_IF -s $SOURCE_IP -d $DEST_IP -j $CHAIN
    iptables -t mangle -A POSTROUTING -o $LAN_IF -s $SOURCE_IP -d $DEST_IP -j RETURN
else
    # Check before NAT rewriting by using the prerouting chain
    echo "    * directing $LAN_IF:$SOURCE_IP -> $DEST_IP to $CHAIN"
    iptables -t mangle -A PREROUTING -i $LAN_IF -s $SOURCE_IP -d $DEST_IP -j $CHAIN
    iptables -t mangle -A PREROUTING -i $LAN_IF -s $SOURCE_IP -d $DEST_IP -j RETURN
fi

echo "    * chain $CHAIN: giving priority (fwmark/class $CLASS_PRIO) to all icmp packets"
iptables -t mangle -A $CHAIN -p icmp -j MARK --set-mark $CLASS_PRIO
iptables -t mangle -A $CHAIN -p icmp -j RETURN

echo "    * chain $CHAIN: giving priority (fwmark/class $CLASS_PRIO) to tcp handshaking"
iptables -t mangle -A $CHAIN -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN \
    -j MARK --set-mark $CLASS_PRIO
iptables -t mangle -A $CHAIN -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN \
    -j RETURN

# --------------------------------------------------------------------------
echo "    * chain $CHAIN: adding iptables marks based on port"

echo "      - VOIP ports: 4569, 5036, 5060:5070, 16000:17000: fwmark/class $CLASS_PRIO"
iptables -t mangle -A $CHAIN -p udp --sport 4569 -j MARK --set-mark $CLASS_PRIO
iptables -t mangle -A $CHAIN -p udp --sport 4569 -j RETURN
iptables -t mangle -A $CHAIN -p udp --dport 4569 -j MARK --set-mark $CLASS_PRIO
iptables -t mangle -A $CHAIN -p udp --dport 4569 -j RETURN
iptables -t mangle -A $CHAIN -p udp --sport 5036 -j MARK --set-mark $CLASS_PRIO
iptables -t mangle -A $CHAIN -p udp --sport 5036 -j RETURN
iptables -t mangle -A $CHAIN -p udp --dport 5036 -j MARK --set-mark $CLASS_PRIO
iptables -t mangle -A $CHAIN -p udp --dport 5036 -j RETURN
iptables -t mangle -A $CHAIN -p udp --sport 5060:5070 -j MARK --set-mark $CLASS_PRIO
iptables -t mangle -A $CHAIN -p udp --sport 5060:5070 -j RETURN
iptables -t mangle -A $CHAIN -p udp --dport 5060:5070 -j MARK --set-mark $CLASS_PRIO
iptables -t mangle -A $CHAIN -p udp --dport 5060:5070 -j RETURN
iptables -t mangle -A $CHAIN -p udp --sport 16000:17000 -j MARK --set-mark $CLASS_PRIO
iptables -t mangle -A $CHAIN -p udp --sport 16000:17000 -j RETURN
iptables -t mangle -A $CHAIN -p udp --dport 16000:17000 -j MARK --set-mark $CLASS_PRIO
iptables -t mangle -A $CHAIN -p udp --dport 16000:17000 -j RETURN

echo "      - OpenVPN port: 1194: fwmark/class $CLASS_MEDIUM"
iptables -t mangle -A $CHAIN -p udp --sport 1194 -j MARK --set-mark $CLASS_MEDIUM
iptables -t mangle -A $CHAIN -p udp --sport 1194 -j RETURN
iptables -t mangle -A $CHAIN -p udp --dport 1194 -j MARK --set-mark $CLASS_MEDIUM
iptables -t mangle -A $CHAIN -p udp --dport 1194 -j RETURN

# For echo testing:
#echo "       - echo port (udp and tcp port 7): fwmark/class $CLASS_PRIO"
#iptables -t mangle -A $CHAIN -p udp --sport 7 -j MARK --set-mark $CLASS_PRIO
#iptables -t mangle -A $CHAIN -p udp --sport 7 -j RETURN
#iptables -t mangle -A $CHAIN -p udp --dport 7 -j MARK --set-mark $CLASS_PRIO
#iptables -t mangle -A $CHAIN -p udp --dport 7 -j RETURN
#iptables -t mangle -A $CHAIN -p tcp --sport 7 -j MARK --set-mark $CLASS_PRIO
#iptables -t mangle -A $CHAIN -p tcp --sport 7 -j RETURN
#iptables -t mangle -A $CHAIN -p tcp --dport 7 -j MARK --set-mark $CLASS_PRIO
#iptables -t mangle -A $CHAIN -p tcp --dport 7 -j RETURN

# --------------------------------------------------------------------------
echo "    * chain $CHAIN: adding iptables marks based on TOS"
iptables -t mangle -A $CHAIN -m tos --tos Minimize-Delay \
    -j MARK --set-mark $CLASS_MEDIUM
iptables -t mangle -A $CHAIN -m tos --tos Minimize-Delay \
    -j RETURN

iptables -t mangle -A $CHAIN -m tos --tos Maximize-Throughput \
    -j MARK --set-mark $CLASS_BULK
iptables -t mangle -A $CHAIN -m tos --tos Maximize-Throughput \
    -j RETURN
            
# --------------------------------------------------------------------------
echo "    * chain $CHAIN: setting default mark (fwmark/class $CLASS_BULK)"
iptables -t mangle -A $CHAIN -j MARK --set-mark $CLASS_BULK
