Commit | Line | Data |
---|---|---|
533aefb8 | 1 | #!/bin/sh |
47a3aa24 DO |
2 | |
3 | # This is a RackTables gateway for changing switch ports membership | |
4 | # across VLANs. It works accordingly to the gateway protocol described | |
5 | # in gateways.php and accepts the following commands on its stdin: | |
fc11a02c DO |
6 | # |
7 | # * connect: connect to a switch, fetch all necessary data, store and | |
8 | # disconnect | |
9 | # | |
47a3aa24 DO |
10 | # * listvlans: list all VLANs found on the switch, propably filtering |
11 | # out those administratively prohibited. Only the VLANs from this | |
12 | # list will be allowed as new destination for 'set' command. | |
fc11a02c | 13 | # |
47a3aa24 | 14 | # * listports: list all ports on the switch and their current status. |
fc11a02c DO |
15 | # Untagged (switchport mode access) ports will be shown with their |
16 | # VLAN ID and tagged ports will be shown as 'trunk' regardless of | |
17 | # how many VLANs they are members of. | |
18 | # | |
19 | # * listmacs: output unsorted list of all dynamically learned MAC | |
20 | # addresses present on the switch | |
21 | # | |
47a3aa24 | 22 | |
7865c525 DO |
23 | endpoint= |
24 | hw= | |
25 | sw= | |
26 | user= | |
35331abf | 27 | handler= |
7865c525 | 28 | CONNECTED=0 |
35331abf | 29 | MYDIR=`dirname $0` |
47a3aa24 | 30 | |
35331abf | 31 | # Not only connect, but gather all the data at once and remember the context. |
533aefb8 DO |
32 | do_connect() |
33 | { | |
7865c525 DO |
34 | endpoint=`echo $args | cut -s -d' ' -f1` |
35 | hw=`echo $args | cut -s -d' ' -f2` | |
36 | sw=`echo $args | cut -s -d' ' -f3` | |
37 | user=`echo $args | cut -s -d' ' -f4` | |
35331abf | 38 | # sanity checks |
533aefb8 DO |
39 | if [ -z "$endpoint" -o -z "$hw" -o -z "$sw" -o -z "$user" ]; then |
40 | echo 'ERR!too few arguments to connect' | |
41 | return | |
42 | fi | |
35331abf | 43 | case "$sw" in |
987af914 | 44 | Cisco+IOS+12.0|Cisco+IOS+12.1|Cisco+IOS+12.2) |
35331abf DO |
45 | handler=cisco |
46 | ;; | |
47 | *) | |
48 | echo "ERR!Don't know how to handle $sw on $endpoint" | |
49 | return | |
50 | ;; | |
51 | esac | |
52 | ||
533aefb8 DO |
53 | # prepare temp files |
54 | PORTINFO=`mktemp /tmp/racktables.XXXX` | |
55 | if ! [ -f "$PORTINFO" ]; then | |
56 | echo 'ERR!could not create portinfo tmpfile' | |
57 | return | |
58 | fi | |
59 | VLANINFO=`mktemp /tmp/racktables.XXXX` | |
60 | if ! [ -f "$VLANINFO" ]; then | |
61 | echo 'ERR!could not create vlaninfo tmpfile' | |
62 | rm -f "$PORTINFO" | |
63 | return | |
64 | fi | |
fc11a02c DO |
65 | MACINFO=`mktemp /tmp/racktables.XXXX` |
66 | if ! [ -f "$MACINFO" ]; then | |
67 | echo 'ERR!could not create MACinfo tmpfile' | |
68 | rm -f "$PORTINFO" "$VLANINFO" | |
69 | return | |
70 | fi | |
47a3aa24 | 71 | |
533aefb8 | 72 | # get the data |
fc11a02c | 73 | "$MYDIR/$handler.connector" $endpoint $hw $sw fetch "$VLANINFO" "$PORTINFO" "$MACINFO" |
35331abf DO |
74 | ret=$? |
75 | if [ $ret = 0 ]; then | |
76 | CONNECTED=1 | |
77 | echo "OK!connected to $endpoint"; | |
78 | else | |
79 | echo "ERR!Cannot connect to $endpoint, connector returned code $ret" | |
80 | fi | |
533aefb8 DO |
81 | } |
82 | ||
83 | do_listfile() | |
84 | { | |
85 | local F=$1 | |
86 | if ! [ -f "$F" ]; then | |
87 | echo "ERR!Lost temp file '$F' on the way" | |
88 | return | |
89 | fi | |
90 | echo -n 'OK!' | |
d28ea105 | 91 | local semicolon='' |
533aefb8 DO |
92 | # tr might do the work, but use our chance to perform filtering once more |
93 | cat "$F" | while read line; do | |
94 | [ "$line" = "" ] && continue | |
d28ea105 DO |
95 | echo -n "$semicolon$line" |
96 | semicolon=';' | |
533aefb8 DO |
97 | done |
98 | echo | |
99 | } | |
100 | ||
101 | do_set() | |
102 | { | |
7865c525 DO |
103 | # sanity checks |
104 | local setline=$1 | |
105 | if [ -z "$setline" ]; then | |
106 | echo 'ERR!missing set argument' | |
107 | return | |
108 | fi | |
7865c525 DO |
109 | local REQUESTS=`mktemp /tmp/racktables.XXXX` |
110 | local REPLIES=`mktemp /tmp/racktables.XXXX` | |
111 | echo $1 | tr ';' '\n' | while read setexpr; do | |
112 | portname=`echo $setexpr | cut -s -d'=' -f1` | |
113 | newvlan=`echo $setexpr | cut -s -d'=' -f2` | |
0dc931a4 | 114 | curvlan=`egrep "^$portname=" $PORTINFO | cut -s -d'=' -f2 | cut -d',' -f2` |
7865c525 DO |
115 | if [ -z "$curvlan" ]; then |
116 | echo "E!Could not find port $portname" >> "$REPLIES" | |
117 | continue | |
118 | fi | |
119 | if [ "$curvlan" = "trunk" ]; then | |
120 | echo "E!Port $portname is a trunk" >> "$REPLIES" | |
121 | continue | |
122 | fi | |
5b6704b5 | 123 | [ "$curvlan" = "$newvlan" ] && continue |
7865c525 | 124 | echo "$portname $newvlan" >> "$REQUESTS" |
7082c58d | 125 | cmembers=`grep -c ",$newvlan$" "$PORTINFO"` |
38356044 | 126 | if [ "$cmembers" = "0" -a $newvlan -lt 4096 ]; then |
7082c58d DO |
127 | echo "W!Port $portname seems to be the first in VLAN $newvlan at this switch." >> "$REPLIES" |
128 | echo "W!Check uplink/downlink configuration for proper operation." >> "$REPLIES" | |
129 | fi | |
7865c525 | 130 | done |
7082c58d | 131 | nr=`egrep -c '^E!.' "$REPLIES"` |
7865c525 | 132 | if [ "$nr" -ge 1 ]; then |
5b6704b5 | 133 | echo "W!$nr change request(s) have been ignored" >> "$REPLIES" |
7865c525 | 134 | fi |
533aefb8 | 135 | |
7865c525 | 136 | nq=`egrep -c '^.' "$REQUESTS"` |
5b6704b5 | 137 | if [ "$nq" -ge 1 ]; then |
7865c525 | 138 | # Go! |
fc11a02c | 139 | "$MYDIR/$handler.connector" $endpoint $hw $sw push "$REQUESTS" "$REPLIES" "$MACINFO" |
7865c525 DO |
140 | local ret=$? |
141 | ||
142 | if [ $ret != 0 ]; then | |
143 | echo "ERR!Failed to configure $endpoint, connector returned code $ret" | |
144 | return | |
145 | fi | |
5b6704b5 | 146 | echo "I!$nq change request(s) have been processed" >> "$REPLIES" |
7865c525 DO |
147 | fi |
148 | echo -n 'OK!' | |
149 | local SEMICOLON= | |
150 | while read reply; do | |
151 | echo -n $SEMICOLON$reply | |
152 | SEMICOLON=';' | |
7c3cb03c | 153 | timestamp=`date '+%Y-%m-%d %H:%M:%S'` |
0dc931a4 | 154 | [ -w "$MYDIR/changes.log" ] && echo "$timestamp $user@$endpoint $reply" >> "$MYDIR/changes.log" |
7865c525 DO |
155 | done < "$REPLIES" |
156 | echo | |
157 | rm -f "$REQUESTS" "$REPLIES" | |
158 | } | |
533aefb8 DO |
159 | |
160 | # main loop | |
161 | while read cmd args; do | |
47a3aa24 | 162 | case $cmd in |
533aefb8 DO |
163 | connect) |
164 | if [ $CONNECTED = 1 ]; then | |
165 | echo 'ERR!Already connected' | |
166 | else | |
167 | do_connect $args | |
168 | fi | |
169 | ;; | |
47a3aa24 | 170 | listvlans) |
533aefb8 DO |
171 | if [ $CONNECTED = 1 ]; then |
172 | do_listfile "$VLANINFO" | |
173 | else | |
174 | echo 'ERR!Not connected' | |
175 | fi | |
47a3aa24 DO |
176 | ;; |
177 | listports) | |
533aefb8 DO |
178 | if [ $CONNECTED = 1 ]; then |
179 | do_listfile "$PORTINFO" | |
180 | else | |
181 | echo 'ERR!Not connected' | |
182 | fi | |
47a3aa24 | 183 | ;; |
9e76e210 DO |
184 | listmacs) |
185 | if [ $CONNECTED = 1 ]; then | |
186 | do_listfile "$MACINFO" | |
187 | else | |
188 | echo 'ERR!Not connected' | |
189 | fi | |
190 | ;; | |
47a3aa24 | 191 | set) |
533aefb8 DO |
192 | if [ $CONNECTED = 1 ]; then |
193 | do_set $args | |
194 | else | |
195 | echo 'ERR!Not connected' | |
196 | fi | |
47a3aa24 DO |
197 | ;; |
198 | *) | |
343d4bec | 199 | echo "ERR!unknown command $cmd" |
47a3aa24 DO |
200 | esac |
201 | done | |
202 | ||
fc11a02c | 203 | rm -f "$PORTINFO" "$VLANINFO" "$MACINFO" |
47a3aa24 | 204 | exit 0 |