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:
7 # * connect: connect to a switch, fetch all necessary data, store and
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.
14 # * listports: list all ports on the switch and their current status.
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.
19 # * listmacs: output unsorted list of all dynamically learned MAC
20 # addresses present on the switch
33 local endp
=$1 user
=$2 action
=$3 arg1
=$4 arg2
=$5 skip
=yes cval
34 [ -z "$endp" -o -z "$user" -o -z "$action" ] && return 1
36 # Now we strip PHP wrapping(s) and process auth rules only.
37 # Accept more than one ruleset on the floor.
39 if [ "$skip" = "yes" -a "$line" = "# S-T-A-R-T" ]; then
43 if [ "$skip" = "no" -a "$line" = "# S-T-O-P" ]; then
47 [ "$skip" = "yes" ] && continue
49 [ -z "${line###*}" ] && continue
51 # Parse the line and try to make a decision earliest possible.
52 # Username and endpoint must match values/regexps, action
53 # must exactly match. Action arguments are tested agains values
54 # or regexps, but only for 'change' action.
55 # If the current rule doesn't match, advance to the next one.
56 # We will fail authorization by default anyway.
59 cval
=`echo "$line" | cut -s -d' ' -f3`
60 [ "$action" = "$cval" ] ||
continue
63 cval
=`echo "$line" | cut -s -d' ' -f2 | cut -s -d'@' -f1`
64 [ -z "${user##$cval}" ] ||
continue
67 cval
=`echo "$line" | cut -s -d' ' -f2 | cut -s -d'@' -f2`
68 [ -z "${endp##$cval}" ] ||
continue
70 if [ "$action" = "change" ]; then
71 [ -z "$arg1" -o -z "$arg2" ] && return 1
72 cval
=`echo "$line" | cut -s -d' ' -f4`
73 [ -z "${arg1##$cval}" ] ||
continue
74 cval
=`echo "$line" | cut -s -d' ' -f5`
75 [ -z "${arg2##$cval}" ] ||
continue
78 # All criterias match. Pick the permission and bail out.
79 cval
=`echo "$line" | cut -s -d' ' -f1`
80 if [ "$cval" = "allow" ]; then
85 done < "$MYDIR/userauth.php"
89 # Not only connect, but gather all the data at once and remember the context.
92 endpoint
=`echo $args | cut -s -d' ' -f1`
93 hw
=`echo $args | cut -s -d' ' -f2`
94 sw
=`echo $args | cut -s -d' ' -f3`
95 user
=`echo $args | cut -s -d' ' -f4`
97 if [ -z "$endpoint" -o -z "$hw" -o -z "$sw" -o -z "$user" ]; then
98 echo 'ERR!too few arguments to connect'
102 Cisco
+IOS
+12.0|Cisco
+IOS
+12.2)
106 echo "ERR!Don't know how to handle $sw on $endpoint"
111 # authorize user, look for "connect" privilege
112 if ! authorized
$endpoint $user connect
; then
113 echo "ERR!User $user is not authorized to connect to $endpoint"
118 PORTINFO
=`mktemp /tmp/racktables.XXXX`
119 if ! [ -f "$PORTINFO" ]; then
120 echo 'ERR!could not create portinfo tmpfile'
123 VLANINFO
=`mktemp /tmp/racktables.XXXX`
124 if ! [ -f "$VLANINFO" ]; then
125 echo 'ERR!could not create vlaninfo tmpfile'
129 MACINFO
=`mktemp /tmp/racktables.XXXX`
130 if ! [ -f "$MACINFO" ]; then
131 echo 'ERR!could not create MACinfo tmpfile'
132 rm -f "$PORTINFO" "$VLANINFO"
137 "$MYDIR/$handler.connector" $endpoint $hw $sw fetch
"$VLANINFO" "$PORTINFO" "$MACINFO"
139 if [ $ret = 0 ]; then
141 echo "OK!connected to $endpoint";
143 echo "ERR!Cannot connect to $endpoint, connector returned code $ret"
150 if ! [ -f "$F" ]; then
151 echo "ERR!Lost temp file '$F' on the way"
156 # tr might do the work, but use our chance to perform filtering once more
157 cat "$F" |
while read line
; do
158 [ "$line" = "" ] && continue
159 echo -n "$semicolon$line"
169 if [ -z "$setline" ]; then
170 echo 'ERR!missing set argument'
173 local REQUESTS
=`mktemp /tmp/racktables.XXXX`
174 local REPLIES
=`mktemp /tmp/racktables.XXXX`
175 echo $1 |
tr ';' '\n' |
while read setexpr
; do
176 portname
=`echo $setexpr | cut -s -d'=' -f1`
177 newvlan
=`echo $setexpr | cut -s -d'=' -f2`
178 curvlan
=`egrep "^$portname=" $PORTINFO | cut -s -d'=' -f2 | cut -d',' -f2`
179 if [ -z "$curvlan" ]; then
180 echo "E!Could not find port $portname" >> "$REPLIES"
183 if [ "$curvlan" = "trunk" ]; then
184 echo "E!Port $portname is a trunk" >> "$REPLIES"
187 [ "$curvlan" = "$newvlan" ] && continue
188 # Authorize user for each change.
189 if ! authorized
$endpoint $user change
$curvlan $newvlan; then
190 echo "E!User $user is not authorized to assign port $portname@$endpoint from VLAN $curvlan to VLAN $newvlan" >> "$REPLIES"
193 echo "$portname $newvlan" >> "$REQUESTS"
195 nr
=`egrep -c '^.' "$REPLIES"`
196 if [ "$nr" -ge 1 ]; then
197 echo "W!$nr change request(s) have been ignored" >> "$REPLIES"
200 nq
=`egrep -c '^.' "$REQUESTS"`
201 if [ "$nq" -ge 1 ]; then
203 "$MYDIR/$handler.connector" $endpoint $hw $sw push
"$REQUESTS" "$REPLIES" "$MACINFO"
206 if [ $ret != 0 ]; then
207 echo "ERR!Failed to configure $endpoint, connector returned code $ret"
210 echo "I!$nq change request(s) have been processed" >> "$REPLIES"
215 echo -n $SEMICOLON$reply
217 timestamp
=`date '+%Y-%M-%d %H:%M:%S'`
218 [ -w "$MYDIR/changes.log" ] && echo "$timestamp $user@$endpoint $reply" >> "$MYDIR/changes.log"
221 rm -f "$REQUESTS" "$REPLIES"
225 while read cmd args
; do
228 if [ $CONNECTED = 1 ]; then
229 echo 'ERR!Already connected'
235 if [ $CONNECTED = 1 ]; then
236 do_listfile
"$VLANINFO"
238 echo 'ERR!Not connected'
242 if [ $CONNECTED = 1 ]; then
243 do_listfile
"$PORTINFO"
245 echo 'ERR!Not connected'
249 if [ $CONNECTED = 1 ]; then
250 do_listfile
"$MACINFO"
252 echo 'ERR!Not connected'
256 if [ $CONNECTED = 1 ]; then
259 echo 'ERR!Not connected'
263 echo "ERR!unknown command $cmd"
267 rm -f "$PORTINFO" "$VLANINFO" "$MACINFO"