#!/bin/zsh
# from https://gist.github.com/oskar456/7264828

ip() {
	[ "$1" = "-v" ] && { shift ; echo "ip $@" }
	/bin/ip "$@"
}

prepare_rt_table() {
        local rttables=/etc/iproute2/rt_tables
        local iface=$1
        [[ "${iface}" = 'lo' ]] && return
        if ! egrep -q "\s${iface}\s*"\$ $rttables; then
                idx=$(wc -l <$rttables)
                echo -e "$(( 300 + ${idx} ))\t${iface}" >> $rttables
        fi
}

get_ipv4_addressses() {
        ip -4 addr show dev ${1} \
	| sed -rn '/inet / s_^.*inet ([0-9.]*)/.*$_\1_p'
}

get_ipv6_addressses() {
        ip -6 addr show dev ${1} \
	| sed -rn '/inet6 / s_^.*inet6 ([0-9a-f:]*)/.*$_\1_p'
}

transfer_routes_ipv4() {
        ip -4 route flush table ${1}
	ip -4 route show table main | grep "dev ${1}" \
	| sed -r 's:expires [^ ]*::' | sed -r 's:proto [^ ]*::' \
	| while read line; do
                [[ -z "$line" ]] && continue
                ip -v -4 route add ${(s: :)line} table ${1}
        done
}

transfer_routes_ipv6() {
        ip -6 route flush table ${1}
	ip -6 route show table main | grep "dev ${1}" \
	| sed -r 's_expires [^ ]*__' | sed -r 's_proto [^ ]*__' \
	| while read line; do
                [[ -z "$line" ]] && continue
                ip -v -6 route add ${(s: :)line} table ${1}
        done
}

get_table_id() {
        sed -rn "/^\s*[0-9]*\s*${1}/ s_^\s*([0-9]+)\s.*_\1_p" \
		/etc/iproute2/rt_tables
}

replace_rules_ipv4() {
        local tableid=$(get_table_id $1)
        while ip -4 rule show | egrep -q ^${tableid}; do
                ip -4 rule del prio ${tableid}
        done
        for ipaddr in $(get_ipv4_addressses ${1}); do
                ip -v -4 rule add prio ${tableid} from ${ipaddr} table ${1}
        done
}

replace_rules_ipv6() {
        local tableid=$(get_table_id $1)
        while ip -6 rule show | egrep -q ^${tableid}; do
                ip -6 rule del prio ${tableid}
        done
        for ipaddr in $(get_ipv6_addressses ${1}); do
                echo $ipaddr | egrep -q '^fe80:' && continue
                ip -v -6 rule add prio ${tableid} from ${ipaddr} table ${1}
        done
}

for ifpath in /sys/class/net/*; do
        iface=${ifpath##*/}
        [[ "${iface}" = "lo" || "${iface}" = "sit0" ]] && continue
        prepare_rt_table ${iface}
        transfer_routes_ipv4 ${iface}
        replace_rules_ipv4 ${iface}
        transfer_routes_ipv6 ${iface}
        replace_rules_ipv6 ${iface}
done | tee /tmp/$(basename $0).status
#| sed -e 's/ip -\(4\|6\) \(route\|rule\) add //' \

