r2906 - maintenance->trunk sync of changesets 2886~2894
[racktables] / gateways / switchvlans / cisco.connector
index 89fa461..c2f8f63 100755 (executable)
@@ -1,11 +1,27 @@
 #!/bin/sh
 
-[ $# = 4 ] || exit 1
+[ $# = 7 ] || exit 1
 
 ENDPOINT=$1
-COMMAND=$2
-FILE1=$3
-FILE2=$4
+HW=$2
+SW=$3
+COMMAND=$4
+FILE1=$5
+FILE2=$6
+FILE3=$7
+MYDIR=`dirname $0`
+ostype=`uname -s`
+case "$ostype" in
+       Linux)
+       SEDFLAG='-r'
+       ;;
+       FreeBSD)
+       SEDFLAG='-E'
+       ;;
+       *)
+       exit 7
+esac
+
 
 prepare_connect_commands()
 {
@@ -31,17 +47,18 @@ prepare_connect_commands()
                        # Don't be too smart at the moment, just be able to handle
                        # the known-good case ;-)
 
-                       echo $line | cut -s -d' ' -f6 > $CMDS1
+                       username=`echo $line | cut -s -d' ' -f5`
+                       [ "$username" != "-" ] && echo $username > $CMDS1
+                       echo $line | cut -s -d' ' -f6 >> $CMDS1
                        echo en >> $CMDS1
                        echo $line | cut -s -d' ' -f7 >> $CMDS1
-
                        # same for ports
-                       echo $line | cut -s -d' ' -f6 > $CMDS2
-                       echo en >> $CMDS2
-                       echo $line | cut -s -d' ' -f7 >> $CMDS2
+                       cat "$CMDS1" > "$CMDS2"
+                       # ...and MAC addresses
+                       cat "$CMDS1" > "$CMDS3"
                        break
                fi
-       done < `dirname $0`/cisco.secrets.php
+       done < "$MYDIR/cisco.secrets.php"
        [ "$found" = "yes" ] && return
        echo "E!connector could not find credentials for $1" >> "$FILE2"
        exit 3
@@ -51,6 +68,7 @@ prepare_fetch_commands()
 {
        printf 'term len 0\nshow vlan brief\nquit\n' >> $CMDS1
        printf 'term len 0\nshow int status\nquit\n' >> $CMDS2
+       printf 'term len 0\nshow mac-address-table\nquit\n' >> $CMDS3
 }
 
 prepare_push_commands()
@@ -65,22 +83,64 @@ prepare_push_commands()
                        echo "E!trunking is not allowed" >> "$FILE2"
                        continue
                fi
-               printf "int $portname\nswi access vlan $vlanid\nexit\n" >> $CMDS1
-               echo "I!Port $portname@$ENDPOINT has been assigned to VLAN $vlanid" >> "$FILE2"
+               printf "int $portname\n" >> $CMDS1
+               if [ $vlanid -lt 4096 ]; then
+                       printf "no description\n" >> $CMDS1
+               else
+                       printf "descr VLAN$vlanid\n" >> $CMDS1
+               fi
+               "$MYDIR/vlandecoder" $vlanid >> $CMDS1
+               printf "exit\n" >> $CMDS1
+               echo "C!64!$portname!$ENDPOINT!$vlanid" >> "$FILE2"
        done < "$FILE1"
-       printf "end\nquit\n" >> $CMDS1
+       printf "end\nwri\nquit\n" >> $CMDS1
 }
 
 do_fetch()
 {
+       local tmp_ifname tmp_ifdescr tmp_status tmp_vlanid
        nc $ENDPOINT 23 < $CMDS1 > "$OUT1"
        if fgrep -q '% Bad passwords' "$OUT1"; then
                echo "E!password mismatch while trying to connect to $ENDPOINT" >> "$FILE2"
                exit 4
        fi
-       nc $ENDPOINT 23 < $CMDS2 > "$OUT2"
-       cat "$OUT1" | fgrep ' active    ' | sed -E 's/^([[:digit:]]+)[[:space:]]+(.+)[[:space:]]+ active    (.*)/\1=\2/;s/[[:space:]]+$//' > $FILE1
-       cat "$OUT2" | egrep '^(Et|Fa|Gi|Te)' | sed -E 's/ +(notconnect|connected) +/=/;s/=(trunk|([0-9]+)) .*$/=\1/' > $FILE2
+       nc $ENDPOINT 23 < $CMDS2 > "$OUT2a"
+       nc $ENDPOINT 23 < $CMDS3 > "$OUT3"
+       cat "$OUT1" | fgrep ' active    ' | sed $SEDFLAG 's/^([[:digit:]]+)[[:space:]]+(.+)[[:space:]]+active    (.*)/\1=\2/;s/[[:space:]]+$//' > $FILE1
+       # Add trunk data, if appropriate.
+       [ -s "$MYDIR/vlantable" ] && cat "$MYDIR/vlantable" >> $FILE1
+
+       # First extract structured info about VLAN membership, then map
+       # special descriptions into VLAN IDs.
+       cat "$OUT2a" | egrep '^(Et|Fa|Gi|Te)' | sed $SEDFLAG 's/[~%]/__RTTMP_percent_sign__/g;s/^([A-Za-z/0-9]+) +(.*) +(connected|notconnect|disabled|err-disabled|monitoring|suspended) +/\1~\2%\3%/;s/%(trunk|routed|([0-9]+)) .*$/%\1/;s/%(monitoring|suspended)%/%connected%/;s/%(err-disabled)%/%disabled%/;s/ +%/%/;s/~/%/' > $OUT2b
+       while read line; do
+               tmp_ifname=`echo $line | cut -d% -f1`
+               tmp_ifdescr=`echo $line | cut -d% -f2`
+               tmp_status=`echo $line | cut -d% -f3`
+               tmp_vlanid=`echo $line | cut -d% -f4`
+               # If the port has a description pretending to be a martian VLAN, map it onto the VLAN ID.
+               if [ -n "$tmp_ifdescr" -a -z "${tmp_ifdescr##VLAN*}" ]; then
+                       tmp_vlanid=${tmp_ifdescr##VLAN}
+               fi
+               echo "$tmp_ifname=$tmp_status,$tmp_vlanid" >> $FILE2
+       done < $OUT2b
+       # FIXME
+       # Here we need to distinguish between different platforms and IOS version,
+       # cause they produce output in different formats.
+       if [ "$SW" = "Cisco+IOS+12.0" ]; then
+               cat "$OUT3" | LC_ALL=C tr -d '\r' | fgrep Dynamic | sed $SEDFLAG 's/ +Dynamic +([0-9]+) +(.+)/=\1@\2/;s/FastEthernet/Fa/;s/GigabitEthernet/Gi/' > "$FILE3"
+       elif [ "$SW" = "Cisco+IOS+12.2" -o "$SW" = "Cisco+IOS+12.1" ]; then
+               case "$HW" in
+                       Cisco+Catalyst+35*|Cisco+Catalyst+37*|Cisco+Catalyst+29*)
+                               cat "$OUT3" | LC_ALL=C tr -d '\r' | egrep 'STATIC|DYNAMIC' | \
+                               sed $SEDFLAG 's/ +([0-9]+|All) +(.+)    (DYNAMIC|STATIC) +(.+)/\2=\1@\4/;s/FastEthernet/Fa/;s/GigabitEthernet/Gi/' > "$FILE3"
+                       ;;
+                       Cisco+Catalyst+49*)
+                               cat "$OUT3" | LC_ALL=C tr -d '\r' | fgrep dynamic | \
+                               sed $SEDFLAG 's/ +([0-9]+) +([0-9a-f\.]+)   dynamic ip +([a-zA-Z/0-9]+) */\2=\1@\3/;s/FastEthernet/Fa/;s/GigabitEthernet/Gi/;s/TenGi/Te/' > "$FILE3"
+                       ;;
+               esac
+       fi
 }
 
 do_push()
@@ -92,21 +152,28 @@ remove_tempfiles()
 {
        [ -f "$CMDS1" ] && rm -f "$CMDS1"
        [ -f "$CMDS2" ] && rm -f "$CMDS2"
+       [ -f "$CMDS3" ] && rm -f "$CMDS3"
        [ -f "$OUT1" ] && rm -f "$OUT1"
-       [ -f "$OUT2" ] && rm -f "$OUT2"
+       [ -f "$OUT2a" ] && rm -f "$OUT2a"
+       [ -f "$OUT2b" ] && rm -f "$OUT2b"
+       [ -f "$OUT3" ] && rm -f "$OUT3"
 }
 
 create_tempfiles()
 {
        # This one is for VLAN list.
        CMDS1=`mktemp /tmp/cisco.connector.XXXX`
-       # And this one holds ports list.
+       # And this one holds ports list...
        CMDS2=`mktemp /tmp/cisco.connector.XXXX`
-       # The following are two buffers to hold the whole switch output
+       # ...and one more for MAC address table
+       CMDS3=`mktemp /tmp/cisco.connector.XXXX`
+       # The following are buffers to hold the whole switch output
        # before filtering.
        OUT1=`mktemp /tmp/cisco.connector.XXXX`
-       OUT2=`mktemp /tmp/cisco.connector.XXXX`
-       [ -f "$CMDS1" -a -f "$CMDS2" -a -f "$OUT1" -a -f "$OUT2" ] && return
+       OUT2a=`mktemp /tmp/cisco.connector.XXXX`
+       OUT2b=`mktemp /tmp/cisco.connector.XXXX`
+       OUT3=`mktemp /tmp/cisco.connector.XXXX`
+       [ -f "$CMDS1" -a -f "$CMDS2" -a -f "$CMDS3" -a -f "$OUT1" -a -f "$OUT2a" -a -f "$OUT2b" -a -f "$OUT3" ] && return
        echo "E!connector cannot create tempfiles" >> "$FILE2"
        remove_tempfiles
        exit 5