r2083 + setSwitchVLANs(): use oneLiner(), handle "C" messages
[racktables] / gateways / switchvlans / cisco.connector
CommitLineData
533aefb8
DO
1#!/bin/sh
2
fc11a02c 3[ $# = 7 ] || exit 1
533aefb8
DO
4
5ENDPOINT=$1
fc11a02c
DO
6HW=$2
7SW=$3
8COMMAND=$4
9FILE1=$5
10FILE2=$6
11FILE3=$7
1b354441 12MYDIR=`dirname $0`
9814a868
DO
13ostype=`uname -s`
14case "$ostype" in
15 Linux)
16 SEDFLAG='-r'
17 ;;
18 FreeBSD)
19 SEDFLAG='-E'
20 ;;
21 *)
22 exit 7
23esac
24
533aefb8 25
697a123b 26prepare_connect_commands()
533aefb8 27{
697a123b
DO
28 [ $# = 1 ] || exit 2
29 local skip=yes cval found=no
533aefb8
DO
30 while read line; do
31 if [ "$skip" = "yes" -a "$line" = "# S-T-A-R-T" ]; then
32 skip=no
33 continue
34 fi
35 if [ "$skip" = "no" -a "$line" = "# S-T-O-P" ]; then
36 skip=yes
37 continue
38 fi
39 [ "$skip" = "yes" ] && continue
40 # Allow comments.
41 [ -z "${line###*}" ] && continue
42
43 # First endpoint string/regexp match is sufficient for us.
44 cval=`echo $line | cut -s -d' ' -f1`
45 if [ -z "${1##$cval}" ]; then
697a123b 46 found=yes
533aefb8
DO
47 # Don't be too smart at the moment, just be able to handle
48 # the known-good case ;-)
49
50 echo $line | cut -s -d' ' -f6 > $CMDS1
51 echo en >> $CMDS1
52 echo $line | cut -s -d' ' -f7 >> $CMDS1
533aefb8 53 # same for ports
9e76e210
DO
54 cat "$CMDS1" > "$CMDS2"
55 # ...and MAC addresses
56 cat "$CMDS1" > "$CMDS3"
533aefb8
DO
57 break
58 fi
1b354441 59 done < "$MYDIR/cisco.secrets.php"
697a123b
DO
60 [ "$found" = "yes" ] && return
61 echo "E!connector could not find credentials for $1" >> "$FILE2"
62 exit 3
63}
64
65prepare_fetch_commands()
66{
533aefb8
DO
67 printf 'term len 0\nshow vlan brief\nquit\n' >> $CMDS1
68 printf 'term len 0\nshow int status\nquit\n' >> $CMDS2
fc11a02c 69 printf 'term len 0\nshow mac-address-table dynamic\nquit\n' >> $CMDS3
533aefb8
DO
70}
71
7865c525 72prepare_push_commands()
533aefb8 73{
5b6704b5
DO
74 printf 'term len 0\nconf t\n' >> $CMDS1
75 while read portname vlanid; do
76 if [ -z "$portname" -o -z "$vlanid" ]; then
77 echo "E!could not parse input in connector" >> "$FILE2"
78 continue
79 fi
80 if [ "$vlanid" = "trunk" ]; then
81 echo "E!trunking is not allowed" >> "$FILE2"
82 continue
83 fi
1b354441
DO
84 printf "int $portname\n" >> $CMDS1
85 if [ $vlanid -lt 4096 ]; then
86 printf "swi access vlan $vlanid\nswi mode access\n" >> $CMDS1
22f2bc98 87 printf "no description\n" >> $CMDS1
1b354441
DO
88 else
89 printf "descr VLAN$vlanid\n" >> $CMDS1
22f2bc98 90 printf "swi trunk encap dot1q\nswi mode trunk\n" >> $CMDS1
1b354441
DO
91 "$MYDIR/trunkdecoder" $vlanid >> $CMDS1
92 fi
93 printf "exit\n" >> $CMDS1
f0ff4930 94 echo "C!64!$portname!$ENDPOINT!$vlanid" >> "$FILE2"
5b6704b5 95 done < "$FILE1"
be6ae134 96 printf "end\nwri\nquit\n" >> $CMDS1
7865c525
DO
97}
98
99do_fetch()
100{
1b354441 101 local tmp_ifname tmp_ifdescr tmp_status tmp_vlanid
697a123b
DO
102 nc $ENDPOINT 23 < $CMDS1 > "$OUT1"
103 if fgrep -q '% Bad passwords' "$OUT1"; then
104 echo "E!password mismatch while trying to connect to $ENDPOINT" >> "$FILE2"
105 exit 4
106 fi
1b354441 107 nc $ENDPOINT 23 < $CMDS2 > "$OUT2a"
fc11a02c 108 nc $ENDPOINT 23 < $CMDS3 > "$OUT3"
9814a868 109 cat "$OUT1" | fgrep ' active ' | sed $SEDFLAG 's/^([[:digit:]]+)[[:space:]]+(.+)[[:space:]]+active (.*)/\1=\2/;s/[[:space:]]+$//' > $FILE1
1b354441
DO
110 # Add trunk data, if appropriate.
111 [ -s "$MYDIR/trunktable" ] && cat "$MYDIR/trunktable" >> $FILE1
112
113 # First extract structured info about VLAN membership, then map
114 # special descriptions into VLAN IDs.
5d733030 115 cat "$OUT2a" | egrep '^(Et|Fa|Gi|Te)' | sed $SEDFLAG '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
1b354441
DO
116 while read line; do
117 tmp_ifname=`echo $line | cut -d% -f1`
118 tmp_ifdescr=`echo $line | cut -d% -f2`
119 tmp_status=`echo $line | cut -d% -f3`
120 tmp_vlanid=`echo $line | cut -d% -f4`
121 # If the port has a description pretending to be a martian VLAN, map it onto the VLAN ID.
122 if [ -n "$tmp_ifdescr" -a -z "${tmp_ifdescr##VLAN*}" ]; then
123 tmp_vlanid=${tmp_ifdescr##VLAN}
124 fi
125 echo "$tmp_ifname=$tmp_status,$tmp_vlanid" >> $FILE2
126 done < $OUT2b
fc11a02c 127 # FIXME
9e76e210
DO
128 # Here we need to distinguish between different platforms and IOS version,
129 # cause they produce output in different formats.
130 if [ "$SW" = "Cisco+IOS+12.0" ]; then
9814a868 131 cat "$OUT3" | tr -d '\r' | fgrep Dynamic | sed $SEDFLAG 's/ +Dynamic +([0-9]+) +(.+)/=\1@\2/;s/FastEthernet/Fa/;s/GigabitEthernet/Gi/' > "$FILE3"
1b354441 132 elif [ "$SW" = "Cisco+IOS+12.2" -o "$SW" = "Cisco+IOS+12.1" ]; then
2a078c28 133 case "$HW" in
9a8ce4df 134 Cisco+Catalyst+35*|Cisco+Catalyst+37*|Cisco+Catalyst+29*|Cisco+Catalyst+49*)
2a078c28 135 cat "$OUT3" | tr -d '\r' | fgrep DYNAMIC | \
9814a868 136 sed $SEDFLAG 's/ +([0-9]+) +(.+) DYNAMIC +(.+)/\2=\1@\3/;s/FastEthernet/Fa/;s/GigabitEthernet/Gi/' > "$FILE3"
2a078c28
DO
137 ;;
138 esac
9e76e210 139 fi
7865c525
DO
140}
141
142do_push()
143{
5b6704b5 144 nc $ENDPOINT 23 < $CMDS1 >/dev/null
533aefb8
DO
145}
146
697a123b
DO
147remove_tempfiles()
148{
149 [ -f "$CMDS1" ] && rm -f "$CMDS1"
150 [ -f "$CMDS2" ] && rm -f "$CMDS2"
fc11a02c 151 [ -f "$CMDS3" ] && rm -f "$CMDS3"
697a123b 152 [ -f "$OUT1" ] && rm -f "$OUT1"
1b354441
DO
153 [ -f "$OUT2a" ] && rm -f "$OUT2a"
154 [ -f "$OUT2b" ] && rm -f "$OUT2b"
fc11a02c 155 [ -f "$OUT3" ] && rm -f "$OUT3"
697a123b 156}
533aefb8 157
697a123b
DO
158create_tempfiles()
159{
160 # This one is for VLAN list.
161 CMDS1=`mktemp /tmp/cisco.connector.XXXX`
fc11a02c 162 # And this one holds ports list...
697a123b 163 CMDS2=`mktemp /tmp/cisco.connector.XXXX`
fc11a02c
DO
164 # ...and one more for MAC address table
165 CMDS3=`mktemp /tmp/cisco.connector.XXXX`
166 # The following are buffers to hold the whole switch output
697a123b
DO
167 # before filtering.
168 OUT1=`mktemp /tmp/cisco.connector.XXXX`
1b354441
DO
169 OUT2a=`mktemp /tmp/cisco.connector.XXXX`
170 OUT2b=`mktemp /tmp/cisco.connector.XXXX`
fc11a02c 171 OUT3=`mktemp /tmp/cisco.connector.XXXX`
1b354441 172 [ -f "$CMDS1" -a -f "$CMDS2" -a -f "$CMDS3" -a -f "$OUT1" -a -f "$OUT2a" -a -f "$OUT2b" -a -f "$OUT3" ] && return
697a123b
DO
173 echo "E!connector cannot create tempfiles" >> "$FILE2"
174 remove_tempfiles
175 exit 5
176}
533aefb8
DO
177
178case $COMMAND in
7865c525 179 fetch)
697a123b
DO
180 create_tempfiles
181 prepare_connect_commands $ENDPOINT
182 prepare_fetch_commands
7865c525 183 do_fetch
697a123b 184 remove_tempfiles
533aefb8 185 ;;
7865c525 186 push)
697a123b
DO
187 create_tempfiles
188 prepare_connect_commands $ENDPOINT
189 prepare_push_commands
7865c525 190 do_push
697a123b 191 remove_tempfiles
533aefb8
DO
192 ;;
193 *)
697a123b
DO
194 echo "E!unknown command for connector" >> "$FILE2"
195 exit 6
533aefb8
DO
196 ;;
197esac
198
533aefb8 199exit 0