| 1 | #! /bin/sh |
| 2 | ### |
| 3 | ### TrIPE interface initialization script |
| 4 | ### suitable for Linux; other operating systems probably want something |
| 5 | ### similar |
| 6 | |
| 7 | ###----- Licensing notica --------------------------------------------------- |
| 8 | ### |
| 9 | ### Redistribution, modification and use of this file is permitted without |
| 10 | ### limitation. |
| 11 | ### |
| 12 | ### This file is distributed in the hope that it will be useful, |
| 13 | ### but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| 15 | |
| 16 | set -e |
| 17 | |
| 18 | ## Import compile-time configuration. |
| 19 | : ${bindir=@bindir@} |
| 20 | : ${tripectl=$bindir/tripectl} |
| 21 | PATH=/usr/bin:/usr/sbin:/bin:/sbin:$bindir |
| 22 | export PATH TRIPEDIR |
| 23 | |
| 24 | ## Determine whether we have IPv6 support. |
| 25 | if [ -d /proc/sys/net/ipv6 ]; then have6=t; else have6=nil; fi |
| 26 | |
| 27 | ###-------------------------------------------------------------------------- |
| 28 | ### Error handling. |
| 29 | |
| 30 | win=t |
| 31 | try () { |
| 32 | if "$@"; then :; else |
| 33 | rc=$? |
| 34 | tripectl warn tripe-ifup command-failed rc=$rc "$*" |
| 35 | win=nil |
| 36 | fi |
| 37 | } |
| 38 | |
| 39 | ###-------------------------------------------------------------------------- |
| 40 | ### Collect arguments. |
| 41 | |
| 42 | ## Collect the simple arguments. |
| 43 | if [ $# -lt 3 ]; then |
| 44 | echo >&2 "usage: $0 PEER IFNAME ADDR..."; exit 1 |
| 45 | fi |
| 46 | peer=$1 ifname=$2 family=$3; shift 3 |
| 47 | |
| 48 | ## Parse the address family. |
| 49 | case "$family" in |
| 50 | INET) ipsz=20 ;; |
| 51 | INET6) ipsz=40 ;; |
| 52 | *) echo >&2 "$0: unknown address family $family"; exit 1 ;; |
| 53 | esac |
| 54 | case "$family,$#" in |
| 55 | INET,1 | INET6,1) addr=$1 port=4070 ;; |
| 56 | INET,2 | INET6,2) addr=$1 port=$2 ;; |
| 57 | INET,* | INET6,*) echo >&2 "$0: bad $family address"; exit 1 ;; |
| 58 | *) echo >&2 "$0: unknown address family $family"; exit 1 ;; |
| 59 | esac |
| 60 | |
| 61 | ###-------------------------------------------------------------------------- |
| 62 | ### Set the interface name. |
| 63 | |
| 64 | case "${P_IFNAME+set}" in |
| 65 | set) |
| 66 | try ip link set "$ifname" name "$P_IFNAME" |
| 67 | ifname=$P_IFNAME |
| 68 | $tripectl setifname "$peer" "$ifname" |
| 69 | ;; |
| 70 | esac |
| 71 | |
| 72 | ###-------------------------------------------------------------------------- |
| 73 | ### Configure the link. |
| 74 | |
| 75 | ## Split local addresses into v4 and v6 lists. |
| 76 | unset l4addr l6addr |
| 77 | for a in $P_LADDR; do |
| 78 | case "$a" in |
| 79 | *:*) l6addr=${l6addr+$l6addr }$a ;; |
| 80 | *) l4addr=${l4addr+$l4addr }$a ;; |
| 81 | esac |
| 82 | done |
| 83 | |
| 84 | ## Determine the remote v4 and v6 addresses. We only allow one remote |
| 85 | ## address for each: others can be added as routes. |
| 86 | unset r4addr r6addr |
| 87 | for a in $P_RADDR; do |
| 88 | case "$a" in |
| 89 | *:*) r6addr=$a ;; |
| 90 | *) r4addr=$a ;; |
| 91 | esac |
| 92 | done |
| 93 | |
| 94 | ## Configure the first v4 address as point-to-point; add the others as plain |
| 95 | ## addresses. |
| 96 | haveaddr4=nil |
| 97 | set -- $l4addr |
| 98 | case $#,${r4addr+set} in |
| 99 | [1-9]*,set) |
| 100 | try ip addr add "$1" peer "$r4addr" dev "$ifname" |
| 101 | haveaddr4=t |
| 102 | shift |
| 103 | ;; |
| 104 | esac |
| 105 | for a in "$@"; do |
| 106 | try ip addr add "$a" dev "$ifname" |
| 107 | haveaddr4=t |
| 108 | done |
| 109 | |
| 110 | ## IPv6 point-to-point links seem broken in Linux. Attach the local and |
| 111 | ## remote addresses by hand. |
| 112 | haveaddr6=nil |
| 113 | set -- $l6addr |
| 114 | case $have6,$# in |
| 115 | t,[1-9]*) |
| 116 | |
| 117 | ## If we're configured to set IPv6 addresses then we should ensure that |
| 118 | ## they're going to work, even if the default setting for new interfaces |
| 119 | ## is to disable IPv6. |
| 120 | try sysctl -q net.ipv6.conf."$ifname".disable_ipv6=0 |
| 121 | |
| 122 | ## Now add the source and destination addresses. |
| 123 | for a in "$@"; do |
| 124 | try ip addr add "$a" dev "$ifname" |
| 125 | haveaddr6=t |
| 126 | done |
| 127 | case ${r6addr+set} in |
| 128 | set) try ip route add $r6addr proto static dev "$ifname" ;; |
| 129 | esac |
| 130 | ;; |
| 131 | esac |
| 132 | |
| 133 | ###-------------------------------------------------------------------------- |
| 134 | ### Bring the interface up. |
| 135 | |
| 136 | case $haveaddr4,$haveaddr6 in |
| 137 | nil,nil) |
| 138 | ;; |
| 139 | *) |
| 140 | case "${P_MTU+set}" in |
| 141 | set) |
| 142 | mtu=$P_MTU;; |
| 143 | *) |
| 144 | pathmtu=$(pathmtu "$addr") |
| 145 | mtu=$(( $pathmtu - $ipsz - 9 - $A_BULK_OVERHEAD )) |
| 146 | ;; |
| 147 | esac |
| 148 | try ip link set dev "$ifname" up mtu "$mtu" |
| 149 | ;; |
| 150 | esac |
| 151 | |
| 152 | ###-------------------------------------------------------------------------- |
| 153 | ### Set up routing. |
| 154 | |
| 155 | ## Split the routes into v4 and v6 lists. |
| 156 | unset route4 route6 |
| 157 | for p in $P_NETS; do |
| 158 | case "$p" in |
| 159 | *:*) route6=${route6+$route6 }$p ;; |
| 160 | *) route4=${route4+$route4 }$p ;; |
| 161 | esac |
| 162 | done |
| 163 | |
| 164 | ## Add the v4 routes. |
| 165 | set -- $route4 |
| 166 | case $haveaddr4,$# in |
| 167 | t,[1-9]*) |
| 168 | for p in "$@"; do |
| 169 | try ip route add $p proto static via "$r4addr" |
| 170 | done |
| 171 | ;; |
| 172 | esac |
| 173 | |
| 174 | ## Add the v6 routes. |
| 175 | set -- $route6 |
| 176 | case $haveaddr6,$# in |
| 177 | t,[1-9]*) |
| 178 | for p in "$@"; do |
| 179 | try ip route add $p proto static via "${r6addr%/*}" |
| 180 | done |
| 181 | ;; |
| 182 | esac |
| 183 | |
| 184 | ###-------------------------------------------------------------------------- |
| 185 | ### Maybe invoke a follow-on script. |
| 186 | |
| 187 | case "${P_IFUPEXTRA+set}" in |
| 188 | set) |
| 189 | eval "$P_IFUPEXTRA" |
| 190 | ;; |
| 191 | esac |
| 192 | |
| 193 | ###-------------------------------------------------------------------------- |
| 194 | ### Issue a notification that we've won. |
| 195 | |
| 196 | case $win in |
| 197 | t) $tripectl notify tripe-ifup configured "$peer" ;; |
| 198 | nil) $tripectl notify tripe-ifup configured "$peer" failed ;; |
| 199 | esac |
| 200 | |
| 201 | ###----- That's all, folks -------------------------------------------------- |