#!/bin/bash
#
# bal_local             Load-balance internet connection over two local links
#
# Version:              1.0.0 - Fri, Sep 26, 2008
#
# Author:               Niels Horn <niels.horn@gmail.com>
#
# changes by teknohog:
#
# this probably requires
# CONFIG_IP_ADVANCED_ROUTER=y
# CONFIG_IP_MULTIPLE_TABLES=y
# CONFIG_IP_ROUTE_MULTIPATH=y
# as per http://www.samag.com/documents/s=1824/sam0201h/0201h.htm
#
# This is pretty trivial to extend for more than 2 interfaces. We can
# even keep the two defaults :) This requires a change in rt_table
# numbering, as 253 to 255 are reserved, so let's start with
rt_start=230

# Set devices:
dev_list=($@)

# defaults: eth0 and ppp0
dev_list[0]=${1-eth0}
dev_list[1]=${2-ppp0}

# Get IP addresses of our devices:
find_ip() {
    for dev in $@; do
	ifconfig $dev | grep inet | awk '{ print $2 }' | awk -F: '{ print $2 } '
    done
}

ip_list=(`find_ip ${dev_list[*]}`)

# Get default gateway for our devices:
find_gw() {
    for dev in $@; do
	route -n | grep $dev | grep '^0.0.0.0' | awk '{ print $2 }'
    done
}

gw_list=(`find_gw ${dev_list[*]}`)

num_devs=${#dev_list[*]}

for i in `seq 0 $((num_devs - 1))`; do
    echo "${dev_list[$i]}: IP=${ip_list[$i]} GW=${gw_list[$i]}"
done

### Definition of routes ###

for i in `seq 0 $((num_devs - 1))`; do
# Check if tables exists, if not -> create them:
    if [ -z "`cat /etc/iproute2/rt_tables | grep ^$((i + rt_start))`" ] ; then
        echo "$((i + rt_start))       rt_dev$i" >> /etc/iproute2/rt_tables
    fi

# Define routing tables:
    ip route add default via ${gw_list[$i]} table rt_dev$i 

# Create rules:
    ip rule add from ${ip_list[$i]} table rt_dev$i 

done

# by teknohog; this seems to be necessary always
ip route del default scope global

# Balance links based on routes:

nexthop_gen() {
    for i in `seq 0 $((num_devs - 1))`; do
	echo "nexthop via ${gw_list[$i]} dev ${dev_list[$i]} weight 1"
    done
}

nexthop_list=(`nexthop_gen`)
ip route add default scope global ${nexthop_list[*]}

# Flush cache table:
ip route flush cache

# All done...
