#!/bin/sh # ip source routing ifupdown script # (C) 2015 Nirgal Vourgère # GPL-3+ # # This script set up source routing for a given interface # Optionnal argument $1: The gateway. If missing, the interface gateway is required. # Example usage: In /etc/network/interfaces # iface eth7 inet static # address 192.168.5.42/24 # post-up source-route 192.168.1.1 # or # iface eth7 inet static # address 192.168.5.42/24 # gateway 192.168.5.1 # post-up source-route #set -x RTTABLE=from$IFACE LOGGER="logger -t source-route -s" if test "$VERBOSITY" = 1 then $LOGGER -p user.debug -- IFACE=$IFACE LOGICAL=$LOGICAL ADDRFAM=$ADDRFAM METHOD=$METHOD MODE=$MODE PHASE=$PHASE VERBOSITY=$VERBOSITY PATH=$PATH fi if ! which ipv4calc >/dev/null then $LOGGER -p user.crit -- "ipv4calc not found: apt-get install libnetwork-ipv4addr-perl" exit 2 fi if ! which ipv6calc >/dev/null then $LOGGER -p user.crit -- "ipv6calc not found: apt-get install ipv6calc" exit 2 fi if test -z "$IFACE" then $LOGGER -p user.crit -- "\$IFACE is empty. Are you really running from /etc/network/interfaces ?" exit 2 fi if test "$PHASE" != "post-up" then $LOGGER -p user.error -- "Invalid \$PHASE. $0 is only valid in 'post-up'. Ignoring." exit 0 # Soft failure fi RT_TABLES=/etc/iproute2/rt_tables if ! grep -q $RTTABLE /etc/iproute2/rt_tables then $LOGGER -p user.crit -- "$RT_TABLES does not have $RTTABLE entry." exit 2 fi case $ADDRFAM in inet) IPFLAG=-4 ;; inet6) IPFLAG=-6 ;; *) $LOGGER -p user.error -- "\$ADDRFAM must be inet or inet6. Ignoring." exit 0 # Soft failure ;; esac IPADDR=$(ip $IPFLAG -o addr show $IFACE | grep -w $ADDRFAM | grep global | sed -re "s/.*$ADDRFAM (.*)\/.*/\1/") IPCIDR=$(ip $IPFLAG -o addr show $IFACE | grep -w $ADDRFAM | grep global | sed -re "s/.*$ADDRFAM .*\/([^ ]*).*/\1/") if test "$ADDRFAM" = "inet6" then IPNET=$(ipv6calc --in ipv6 --out ipv6 --maskprefix $IPADDR/$IPCIDR) else IPNET=$(ipv4calc --network $IPADDR/$IPCIDR)/$IPCIDR fi if test -n "$1" then IPGW=$1 else IPGW=$(ip $IPFLAG -o route show | grep default | sed -re "s/.*via ([^ ]*) .*/\1/") fi if test -z "$IPGW" then $LOGGER -p user.crit "Could not find the gateway and none was given." exit 2 fi # Setting up source routing on $IFACE, so that packets from $IFACE don't get answered on another interface $LOGGER -- "Setting up source routing on $IFACE: from $IPADDR -> route $IPNET via $IPGW" if ! ip $IPFLAG route show table $RTTABLE | grep -q default # Once only then if test "$VERBOSITY" = 1 then $LOGGER -p user.debug -- ip $IPFLAG route add $IPNET dev "$IFACE" scope link table $RTTABLE $LOGGER -p user.debug -- ip $IPFLAG route add default via "$IPGW" dev "$IFACE" table $RTTABLE fi ip $IPFLAG route add $IPNET dev "$IFACE" scope link table $RTTABLE ip $IPFLAG route add default via "$IPGW" dev "$IFACE" table $RTTABLE fi if ! ip $IPFLAG rule show | grep -q $RTTABLE # Once only then if test "$VERBOSITY" = 1 then $LOGGER -p user.debug -- ip $IPFLAG rule add from $IPADDR table $RTTABLE fi ip $IPFLAG rule add from $IPADDR table $RTTABLE fi ip $IPFLAG route flush cache