Home | History | Annotate | Download | only in ip
      1 #! /bin/bash
      2 
      3 CheckForwarding () {
      4   local sbase fwd
      5   sbase=/proc/sys/net/ipv4/conf
      6   fwd=0
      7   if [ -d $sbase ]; then
      8     for dir in $sbase/*/forwarding; do
      9       fwd=$[$fwd + `cat $dir`]
     10     done
     11   else
     12     fwd=2
     13   fi
     14   return $fwd
     15 }
     16 
     17 RestartRDISC () {
     18   killall -HUP rdisc || rdisc -fs
     19 }
     20 
     21 ABCMaskLen () {
     22   local class;
     23 
     24   class=${1%%.*}
     25   if [ "$1" = "" -o $class -eq 0 -o $class -ge 224 ]; then return 0
     26   elif [ $class -ge 224 ]; then return 0
     27   elif [ $class -ge 192 ]; then return 24
     28   elif [ $class -ge 128 ]; then return 16
     29   else return 8; fi
     30 }
     31 
     32 label="label $1"
     33 ldev="$1"
     34 dev=${1%:*}
     35 if [ "$dev" = "" -o "$1" = "help" ]; then
     36   echo "Usage: ifcfg DEV [[add|del [ADDR[/LEN]] [PEER] | stop]" 1>&2
     37   echo "       add - add new address" 1>&2
     38   echo "       del - delete address" 1>&2
     39   echo "       stop - completely disable IP" 1>&2
     40   exit 1
     41 fi
     42 shift
     43 
     44 CheckForwarding
     45 fwd=$?
     46 if [ $fwd -ne 0 ]; then
     47   echo "Forwarding is ON or its state is unknown ($fwd). OK, No RDISC." 1>&2
     48 fi
     49 
     50 
     51 deleting=0
     52 case "$1" in
     53 add) shift ;;
     54 stop)
     55   if [ "$ldev" != "$dev" ]; then
     56     echo "Cannot stop alias $ldev" 1>&2
     57     exit 1;
     58   fi
     59   ip -4 addr flush dev $dev $label || exit 1
     60   if [ $fwd -eq 0 ]; then RestartRDISC; fi
     61   exit 0 ;;
     62 del*)
     63   deleting=1; shift ;;
     64 *)
     65 esac
     66 
     67 ipaddr=
     68 pfxlen=
     69 if [ "$1" != "" ]; then
     70   ipaddr=${1%/*}
     71   if [ "$1" != "$ipaddr" ]; then
     72     pfxlen=${1#*/}
     73   fi
     74   if [ "$ipaddr" = "" ]; then
     75     echo "$1 is bad IP address." 1>&2
     76     exit 1
     77   fi
     78 fi
     79 shift
     80 
     81 peer=$1
     82 if [ "$peer" != "" ]; then
     83   if [ "$pfxlen" != "" -a "$pfxlen" != "32" ]; then
     84     echo "Peer address with non-trivial netmask." 1>&2
     85     exit 1
     86   fi
     87   pfx="$ipaddr peer $peer"
     88 else
     89   if [ "$ipaddr" = "" ]; then
     90     echo "Missing IP address argument." 1>&2
     91     exit 1
     92   fi
     93   if [ "$pfxlen" = "" ]; then
     94     ABCMaskLen $ipaddr
     95     pfxlen=$?
     96   fi
     97   pfx="$ipaddr/$pfxlen"
     98 fi
     99 
    100 if [ "$ldev" = "$dev" -a "$ipaddr" != "" ]; then
    101   label=
    102 fi
    103 
    104 if [ $deleting -ne 0 ]; then
    105   ip addr del $pfx dev $dev $label || exit 1
    106   if [ $fwd -eq 0 ]; then RestartRDISC; fi
    107   exit 0
    108 fi
    109 
    110 
    111 if ! ip link set up dev $dev ; then
    112   echo "Error: cannot enable interface $dev." 1>&2
    113   exit 1
    114 fi
    115 if [ "$ipaddr" = "" ]; then exit 0; fi
    116 
    117 if ! arping -q -c 2 -w 3 -D -I $dev $ipaddr ; then
    118   echo "Error: some host already uses address $ipaddr on $dev." 1>&2
    119   exit 1
    120 fi
    121 
    122 if ! ip address add $pfx brd + dev $dev $label; then
    123   echo "Error: failed to add $pfx on $dev." 1>&2
    124   exit 1
    125 fi
    126 
    127 arping -q -A -c 1 -I $dev $ipaddr
    128 noarp=$?
    129 ( sleep 2 ;
    130   arping -q -U -c 1 -I $dev $ipaddr ) >& /dev/null </dev/null &
    131 
    132 ip route add unreachable 224.0.0.0/24 >& /dev/null
    133 ip route add unreachable 255.255.255.255 >& /dev/null
    134 if [ `ip link ls $dev | grep -c MULTICAST` -ge 1 ]; then
    135   ip route add 224.0.0.0/4 dev $dev scope global >& /dev/null
    136 fi
    137 
    138 if [ $fwd -eq 0 ]; then
    139   if [ $noarp -eq 0 ]; then
    140     ip ro append default dev $dev metric 30000 scope global
    141   elif [ "$peer" != "" ]; then
    142     if ping -q -c 2 -w 4 $peer ; then
    143       ip ro append default via $peer dev $dev metric 30001
    144     fi
    145   fi
    146   RestartRDISC
    147 fi
    148 
    149 exit 0
    150