r1194 + dropping useless file, cause svn:ignore is an internal property
[racktables] / gateways / switchvlans / main
CommitLineData
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:
6# * listvlans: list all VLANs found on the switch, propably filtering
7# out those administratively prohibited. Only the VLANs from this
8# list will be allowed as new destination for 'set' command.
9# * listports: list all ports on the switch and their current status.
10# Untagged (switchport mode access) ports will be shown with their
11# VLAN ID and tagged ports will be shown as 'trunk' regardless of
12# how many VLANs they are members of.
13
7865c525
DO
14endpoint=
15hw=
16sw=
17user=
35331abf 18handler=
7865c525 19CONNECTED=0
35331abf 20MYDIR=`dirname $0`
7865c525 21
533aefb8 22authorized()
47a3aa24 23{
533aefb8
DO
24 local endp=$1 user=$2 action=$3 arg1=$4 arg2=$5 skip=yes cval
25 [ -z "$endp" -o -z "$user" -o -z "$action" ] && return 1
26
27 # Now we strip PHP wrapping(s) and process auth rules only.
28 # Accept more than one ruleset on the floor.
29 while read line; do
30 if [ "$skip" = "yes" -a "$line" = "# S-T-A-R-T" ]; then
31 skip=no
32 continue
33 fi
34 if [ "$skip" = "no" -a "$line" = "# S-T-O-P" ]; then
35 skip=yes
36 continue
37 fi
38 [ "$skip" = "yes" ] && continue
39 # Allow comments.
40 [ -z "${line###*}" ] && continue
41
42 # Parse the line and try to make a decision earliest possible.
43 # Username and endpoint must match values/regexps, action
44 # must exactly match. Action arguments are tested agains values
45 # or regexps, but only for 'change' action.
46 # If the current rule doesn't match, advance to the next one.
47 # We will fail authorization by default anyway.
48
49 # Test action.
50 cval=`echo "$line" | cut -s -d' ' -f3`
51 [ "$action" = "$cval" ] || continue
52
53 # Test username.
54 cval=`echo "$line" | cut -s -d' ' -f2 | cut -s -d'@' -f1`
55 [ -z "${user##$cval}" ] || continue
56
57 # Test endpoint.
58 cval=`echo "$line" | cut -s -d' ' -f2 | cut -s -d'@' -f2`
59 [ -z "${endp##$cval}" ] || continue
60
7865c525 61 if [ "$action" = "change" ]; then
533aefb8
DO
62 [ -z "$arg1" -o -z "$arg2" ] && return 1
63 cval=`echo "$line" | cut -s -d' ' -f4`
64 [ -z "${arg1##$cval}" ] || continue
65 cval=`echo "$line" | cut -s -d' ' -f5`
66 [ -z "${arg2##$cval}" ] || continue
67 fi
68
69 # All criterias match. Pick the permission and bail out.
70 cval=`echo "$line" | cut -s -d' ' -f1`
71 if [ "$cval" = "allow" ]; then
72 return 0
73 else
74 return 1
75 fi
35331abf 76 done < "$MYDIR/userauth.php"
533aefb8 77 return 1
47a3aa24
DO
78}
79
35331abf 80# Not only connect, but gather all the data at once and remember the context.
533aefb8
DO
81do_connect()
82{
7865c525
DO
83 endpoint=`echo $args | cut -s -d' ' -f1`
84 hw=`echo $args | cut -s -d' ' -f2`
85 sw=`echo $args | cut -s -d' ' -f3`
86 user=`echo $args | cut -s -d' ' -f4`
35331abf 87 # sanity checks
533aefb8
DO
88 if [ -z "$endpoint" -o -z "$hw" -o -z "$sw" -o -z "$user" ]; then
89 echo 'ERR!too few arguments to connect'
90 return
91 fi
35331abf
DO
92 case "$sw" in
93 Cisco+IOS+12.0|Cisco+IOS+12.2)
94 handler=cisco
95 ;;
96 *)
97 echo "ERR!Don't know how to handle $sw on $endpoint"
98 return
99 ;;
100 esac
101
533aefb8
DO
102 # authorize user, look for "connect" privilege
103 if ! authorized $endpoint $user connect; then
104 echo "ERR!User $user is not authorized to connect to $endpoint"
105 return
106 fi
107
108 # prepare temp files
109 PORTINFO=`mktemp /tmp/racktables.XXXX`
110 if ! [ -f "$PORTINFO" ]; then
111 echo 'ERR!could not create portinfo tmpfile'
112 return
113 fi
114 VLANINFO=`mktemp /tmp/racktables.XXXX`
115 if ! [ -f "$VLANINFO" ]; then
116 echo 'ERR!could not create vlaninfo tmpfile'
117 rm -f "$PORTINFO"
118 return
119 fi
47a3aa24 120
533aefb8 121 # get the data
35331abf
DO
122 "$MYDIR/$handler.connector" $endpoint fetch "$VLANINFO" "$PORTINFO"
123 ret=$?
124 if [ $ret = 0 ]; then
125 CONNECTED=1
126 echo "OK!connected to $endpoint";
127 else
128 echo "ERR!Cannot connect to $endpoint, connector returned code $ret"
129 fi
533aefb8
DO
130}
131
132do_listfile()
133{
134 local F=$1
135 if ! [ -f "$F" ]; then
136 echo "ERR!Lost temp file '$F' on the way"
137 return
138 fi
139 echo -n 'OK!'
d28ea105 140 local semicolon=''
533aefb8
DO
141 # tr might do the work, but use our chance to perform filtering once more
142 cat "$F" | while read line; do
143 [ "$line" = "" ] && continue
d28ea105
DO
144 echo -n "$semicolon$line"
145 semicolon=';'
533aefb8
DO
146 done
147 echo
148}
149
150do_set()
151{
7865c525
DO
152 # sanity checks
153 local setline=$1
154 if [ -z "$setline" ]; then
155 echo 'ERR!missing set argument'
156 return
157 fi
7865c525
DO
158 local REQUESTS=`mktemp /tmp/racktables.XXXX`
159 local REPLIES=`mktemp /tmp/racktables.XXXX`
160 echo $1 | tr ';' '\n' | while read setexpr; do
161 portname=`echo $setexpr | cut -s -d'=' -f1`
162 newvlan=`echo $setexpr | cut -s -d'=' -f2`
163 curvlan=`egrep "^$portname=" $PORTINFO | cut -s -d'=' -f2`
164 if [ -z "$curvlan" ]; then
165 echo "E!Could not find port $portname" >> "$REPLIES"
166 continue
167 fi
168 if [ "$curvlan" = "trunk" ]; then
169 echo "E!Port $portname is a trunk" >> "$REPLIES"
170 continue
171 fi
5b6704b5 172 [ "$curvlan" = "$newvlan" ] && continue
7865c525
DO
173 # Authorize user for each change.
174 if ! authorized $endpoint $user change $curvlan $newvlan; then
175 echo "E!User $user is not authorized to assign port $portname@$endpoint from VLAN $curvlan to VLAN $newvlan" >> "$REPLIES"
176 continue
177 fi
178 echo "$portname $newvlan" >> "$REQUESTS"
179 done
180 nr=`egrep -c '^.' "$REPLIES"`
181 if [ "$nr" -ge 1 ]; then
5b6704b5 182 echo "W!$nr change request(s) have been ignored" >> "$REPLIES"
7865c525 183 fi
533aefb8 184
7865c525 185 nq=`egrep -c '^.' "$REQUESTS"`
5b6704b5 186 if [ "$nq" -ge 1 ]; then
7865c525 187 # Go!
35331abf 188 "$MYDIR/$handler.connector" $endpoint push "$REQUESTS" "$REPLIES"
7865c525
DO
189 local ret=$?
190
191 if [ $ret != 0 ]; then
192 echo "ERR!Failed to configure $endpoint, connector returned code $ret"
193 return
194 fi
5b6704b5 195 echo "I!$nq change request(s) have been processed" >> "$REPLIES"
7865c525
DO
196 fi
197 echo -n 'OK!'
198 local SEMICOLON=
199 while read reply; do
200 echo -n $SEMICOLON$reply
201 SEMICOLON=';'
35331abf 202 [ -w "$MYDIR/changes.log" ] && echo "$reply" >> "$MYDIR/changes.log"
7865c525
DO
203 done < "$REPLIES"
204 echo
205 rm -f "$REQUESTS" "$REPLIES"
206}
533aefb8
DO
207
208# main loop
209while read cmd args; do
47a3aa24 210 case $cmd in
533aefb8
DO
211 connect)
212 if [ $CONNECTED = 1 ]; then
213 echo 'ERR!Already connected'
214 else
215 do_connect $args
216 fi
217 ;;
47a3aa24 218 listvlans)
533aefb8
DO
219 if [ $CONNECTED = 1 ]; then
220 do_listfile "$VLANINFO"
221 else
222 echo 'ERR!Not connected'
223 fi
47a3aa24
DO
224 ;;
225 listports)
533aefb8
DO
226 if [ $CONNECTED = 1 ]; then
227 do_listfile "$PORTINFO"
228 else
229 echo 'ERR!Not connected'
230 fi
47a3aa24
DO
231 ;;
232 set)
533aefb8
DO
233 if [ $CONNECTED = 1 ]; then
234 do_set $args
235 else
236 echo 'ERR!Not connected'
237 fi
47a3aa24
DO
238 ;;
239 *)
343d4bec 240 echo "ERR!unknown command $cmd"
47a3aa24
DO
241 esac
242done
243
533aefb8 244rm -f "$PORTINFO" "$VLANINFO"
47a3aa24 245exit 0