Dynamic gateways and more
[source-route.git] / source-route
1 #!/bin/sh
2 # ip source routing ifupdown script
3 # (C) 2015 Nirgal Vourgère
4 # GPL-3+
5 #
6 # This script set up source routing for a given interface
7 # Optionnal argument $1: The gateway. If missing, the interface gateway is required.
8 # Example usage: In /etc/network/interfaces
9 # iface eth7 inet static
10 #     address 192.168.5.42/24
11 #     post-up source-route 192.168.1.1
12 # or
13 # iface eth7 inet static
14 #     address 192.168.5.42/24
15 #     gateway 192.168.5.1
16 #     post-up source-route
17
18 #set -x 
19 RTTABLE=from$IFACE
20 LOGGER="logger -t source-route"
21
22 if test "$VERBOSITY" = 1
23 then
24         echo " IFACE=$IFACE LOGICAL=$LOGICAL ADDRFAM=$ADDRFAM METHOD=$METHOD MODE=$MODE PHASE=$PHASE VERBOSITY=$VERBOSITY PATH=$PATH" >&2
25         $LOGGER -- IFACE=$IFACE LOGICAL=$LOGICAL ADDRFAM=$ADDRFAM METHOD=$METHOD MODE=$MODE PHASE=$PHASE VERBOSITY=$VERBOSITY PATH=$PATH
26 fi
27
28 critical_log() {
29         $LOGGER -- "$@"
30         echo "$@" >&2
31 }
32 if ! which ipv4calc >/dev/null
33 then
34     critical_log "ipv4calc not found: apt-get install libnetwork-ipv4addr-perl"
35     exit 2
36 fi
37 if ! which ipv6calc >/dev/null
38 then
39     critical_log "ipv6calc not found: apt-get install ipv6calc"
40     exit 2
41 fi
42 if test -z "$IFACE"
43 then
44    critical_log "\$IFACE var is empty. Are you really running from /etc/network/interfaces ?"
45    exit 2
46 fi
47 if test "$PHASE" != "post-up"
48 then
49    critical_log "Invalid \$PHASE. $0 is only valid in 'post-up'."
50    exit 2
51 fi
52
53 RT_TABLES=/etc/iproute2/rt_tables
54 if ! grep -q $RTTABLE /etc/iproute2/rt_tables
55 then
56         critical_log "$RT_TABLES does not have $RTTABLE entry."
57         exit 2
58 fi
59
60 case $ADDRFAM in
61 inet)
62         IPFLAG=-4
63         ;;
64 inet6)
65         IPFLAG=-6
66         ;;
67 *)
68         echo \$ADDRFAM must be inet or inet6. Ignoring. >&2
69         exit 0
70         ;;
71 esac
72 IPADDR=$(ip $IPFLAG -o addr show $IFACE | grep -w $ADDRFAM | grep global | sed -re "s/.*$ADDRFAM (.*)\/.*/\1/")
73 IPCIDR=$(ip $IPFLAG -o addr show $IFACE | grep -w $ADDRFAM | grep global | sed -re "s/.*$ADDRFAM .*\/([^ ]*).*/\1/")
74 if test "$ADDRFAM" = "inet6"
75 then
76         IPNET=$(ipv6calc --in ipv6 --out ipv6 --maskprefix $IPADDR/$IPCIDR)
77 else
78         IPNET=$(ipv4calc --network $IPADDR/$IPCIDR)/$IPCIDR
79 fi
80 if test -n "$1"
81 then
82         IPGW=$1
83 else
84         IPGW=$(ip $IPFLAG -o route show | grep default | sed -re "s/.*via ([^ ]*) .*/\1/")
85 fi
86 if test -z "$IPGW"
87 then
88    critical_log "Could not find the gateway."
89    exit 2
90 fi
91
92 # Setting up source routing on $IFACE, so that packets from $IFACE don't get answered on another interface
93 echo "Setting up source routing on $IFACE: from $IPADDR -> route $IPNET via $IPGW" >&2
94 $LOGGER -- "Setting up source routing on $IFACE: from $IPADDR -> route $IPNET via $IPGW"
95
96 if ! ip $IPFLAG route show table $RTTABLE | grep -q default  # Once only
97 then
98         if test "$VERBOSITY" = 1
99         then
100                 $LOGGER -- ip $IPFLAG route add $IPNET dev "$IFACE" scope link table $RTTABLE
101                 $LOGGER -- ip $IPFLAG route add default via "$IPGW" dev "$IFACE" table $RTTABLE
102         fi
103         ip $IPFLAG route add $IPNET dev "$IFACE" scope link table $RTTABLE
104         ip $IPFLAG route add default via "$IPGW" dev "$IFACE" table $RTTABLE
105 fi
106 if ! ip $IPFLAG rule show | grep -q $RTTABLE  # Once only
107 then
108         if test "$VERBOSITY" = 1
109         then
110                 $LOGGER -- ip $IPFLAG rule add from $IPADDR table $RTTABLE
111         fi
112         ip $IPFLAG rule add from $IPADDR table $RTTABLE
113 fi
114
115 ip $IPFLAG route flush cache