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