home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.ee.lbl.gov
/
2014.05.ftp.ee.lbl.gov.tar
/
ftp.ee.lbl.gov
/
acld-1.11.tar.gz
/
acld-1.11.tar
/
acld-1.11
/
force10.expect
< prev
next >
Wrap
Text File
|
2012-02-17
|
30KB
|
1,355 lines
# @(#) $Id: force10.expect 811 2012-02-18 04:50:40Z leres $ (LBL)
#
# Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012
# The Regents of the University of California. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that: (1) source code distributions
# retain the above copyright notice and this paragraph in its entirety, (2)
# distributions including binary code include the above copyright notice and
# this paragraph in its entirety in the documentation or other materials
# provided with the distribution, and (3) all advertising materials mentioning
# features or use of this software display the following acknowledgement:
# ``This product includes software developed by the University of California,
# Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
# the University nor the names of its contributors may be used to endorse
# or promote products derived from this software without specific prior
# written permission.
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
# force10.expect - acld script for controlling a force 10 router (using ssh)
#
#
# Always include an explicit "return" in each procedure:
#
# This will cause an expect error if the procedure is supposed
# to kreturn a value
#
# Always exclude \r\n in negated regex character classes:
#
# Otherwise the regex can match more than one line
#
set timeout 10
match_max 2048
set cprompt "\[^#\r\n]*#"
set currentmode "logout"
set currentacl ""
set f "expect.log"
set logname "/var/log/acld/expect.log"
if [catch {log_file -a $logname} err] {
#send_error "$prog: warning: $err\n"
set logname $f
if [catch {log_file -a $logname} err] {
#send_error "$prog: warning: $err\n"
}
}
set lastseq 65535
# Cleanup if our child dies
trap { wait } SIGCHLD
# Higher level is easier if the prompt doesn't change
proc prompt1 {} {
return "expect>"
}
# Required procedures
proc attr {acl attrlist} {
global isipv6
foreach attr $attrlist {
if { $attr == "ipv6" } {
set isipv6($acl) 1
continue
}
puts "attr-failed -"
puts "unknown attr \"$attr\""
puts "."
return
}
puts "attr"
return
}
proc drop {addr acl seq} {
global logname
set ip [acl2ip $acl]
if { [string first "/" $addr] > 0 } {
# Network with mask
aclcmd "drop" $acl $seq "" "deny $ip $addr any"
} else {
# Host address
aclcmd "drop" $acl $seq "" "deny $ip host $addr any"
}
# Reopen the logfile from time to time
log_file
log_file -a $logname
return
}
proc blockhosthost {addr1 addr2 acl seq} {
set ip [acl2ip $acl]
aclcmd "blockhosthost" $acl $seq "" "deny $ip host $addr1 host $addr2"
return
}
proc dropudpport {port acl seq} {
aclcmd "dropudpport" $acl $seq "" "deny udp any any eq $port"
return
}
proc droptcpport {port acl seq} {
aclcmd "droptcpport" $acl $seq "" "deny tcp any any eq $port"
return
}
proc droptcpdsthostport {addr port acl seq} {
aclcmd "droptcpdsthostport" $acl $seq "" \
"deny tcp any host $addr eq $port"
return
}
proc ayt {} {
global cprompt
sendcmd ""
set timeout 10
expect {
"Connection closed by foreign host" {
puts "ayt-failed -"
puts "ssh session ended"
puts "."
# exit so acld will start a fresh expect session
exit
}
-re $cprompt {
# done
}
timeout {
puts "ayt-failed -"
puts "timeout ($timeout seconds)"
puts "."
# exit so acld will start a fresh expect session
exit
}
}
puts "ayt"
return
}
# Try the "show ip accounting" version first (to get counts)
proc listacl {acl interface} {
global cprompt
global currentmode
set err [entermode "enable" ""]
if { $err != "" } {
puts "listacl-failed -"
puts "$err"
puts "."
return
}
set ip [acl2ip $acl]
sendcmd "show $ip accounting access-list $acl interface $interface"
set timeout 10
expect {
-re "Extended \[^\r\n]+ IP access list $acl on \[^\r\n]+\[\r\n]*\r\n" {
puts "listacl -"
expect {
-re "(Access List is not in sync with running config)\[\r\n]*\r\n" {
set s "# "
append s $expect_out(1,string)
puts $s
exp_continue
}
-re "(List is not in sync with running config)\[\r\n]*\r\n" {
set s "# "
append s $expect_out(1,string)
puts $s
exp_continue
}
-re "(Total cam count \[^\r\n]+)\[\r\n]*\r\n" {
set s "# "
append s $expect_out(1,string)
puts $s
exp_continue
}
-re "^ *(\[^\r\n]*)\[\r\n]*\r\n" {
printacl $expect_out(1,string)
exp_continue
}
-re $cprompt {
# This action must be last
# done
}
}
puts "."
return
}
-re "% Error: Access-list $acl does not exist\.\[\r\n]*\r\n" {
# Send back an empty list
expect -re $cprompt
puts "listacl"
return
}
-re "% Error: Access-list was not applied on this interface\.\[\r\n]*\r\n" {
# Fall back to config'd ACL (without counts)
expect -re $cprompt
listaclsimple $acl
return
}
"Connection closed by foreign host" {
puts "listacl-failed -"
puts "ssh session ended"
puts "."
# exit so acld will start a fresh expect session
exit
}
-re $cprompt {
# Fall back to config'd ACL (without counts)
# This action must be last
listaclsimple $acl
return
}
timeout {
puts "listacl-failed -"
puts "timeout ($timeout seconds)"
puts "."
# exit so acld will start a fresh expect session
exit
}
}
return
}
# List both IPv4 and IPv6 routes
# XXX there's no easy way to return an error if IPv4 are listed ok
# but IPv6 routes fail
proc listroute {} {
global currentmode
set err [entermode "enable" ""]
if { $err != "" } {
puts "listroute-failed -"
puts "$err"
puts "."
return
}
puts "listroute -"
_listroute ip
_listroute ipv6
puts "."
return
}
proc login {addr cuser cpass1 cpass2 euser epass1 epass2} {
global spawn_id
global cprompt
global currentmode
# Fire up subprocess
# We only use the enable username with the force 10
# Make swapping routers less painful: don't check the host key
set pid [spawn ssh "-2ax" "-o" "stricthostkeychecking=no" $euser@$addr]
# Wait for connect
# If the router is busy it can take a long time for the initial connect
set timeout 60
expect {
eof {
# Don't hammer on router if we're misconfigured
catch {close} err
sleep 10
puts "login-failed -"
puts "child died (1)"
puts "."
# exit so acld will start a fresh expect session
exit
}
timeout {
catch {close} err
puts "login-failed -"
puts "connect timeout ($timeout seconds)"
puts "."
# exit so acld will start a fresh expect session
exit
}
-re "The authenticity of host\[^\r\n]*\[\r\n]*\r\n" {
exp_continue
}
"Are you sure you want to continue connecting \(yes/no\)\? " {
sendcmd "yes"
exp_continue
}
"assword: " {
# done
}
default {
catch {close} err
puts "login-failed -"
puts "unknown response: $expect_out(buffer)"
puts "."
# exit so acld will start a fresh expect session
exit
}
}
# We only use the enable passwords with the force 10
if { ![sendpass "enable" $epass1 $epass2] } {
catch {close} err
return
}
sendcmd "terminal length 0"
expect -re $cprompt
set currentmode "enable"
puts "login -"
puts "child ssh pid is $pid"
puts "."
return
}
proc logout {} {
global currentmode
set err [entermode "enable" ""]
if { $err != "" } {
puts "logout-failed -"
puts "$err"
puts "."
# exit so acld will start a fresh expect session
exit
}
sendcmd "exit"
set currentmode "logout"
set timeout 10
expect {
-re "Connection.*closed by.*host" {
catch {close} err
puts "logout"
return
}
timeout {
puts "logout-failed -"
puts "timeout ($timeout seconds)"
puts "."
# exit so acld will start a fresh expect session
exit
}
default {
puts "logout-failed -"
puts "logout already logged out"
puts "."
# exit so acld will start a fresh expect session
exit
}
}
return
}
proc nonullzero {addr} {
nullzerocmd "nonullzero" $addr "no"
return
}
proc nullzero {addr} {
nullzerocmd "nullzero" $addr {}
return
}
proc permitudpdsthostport {addr port acl seq} {
aclcmd "permitudpdsthostport" $acl $seq "" \
"permit udp any host $addr eq $port"
return
}
proc permittcpdsthostport {addr port acl seq} {
aclcmd "permittcpdsthostport" $acl $seq "" \
"permit tcp any host $addr eq $port"
return
}
proc restore {addr acl seq} {
aclcmd "restore" $acl $seq "no" ""
return
}
proc restorehosthost {addr1 addr2 acl seq} {
set ip [acl2ip $acl]
aclcmd "restorehosthost" $acl $seq "no" \
"deny $ip host $addr1 host $addr2"
return
}
proc restoreudpport {port acl seq} {
aclcmd "restoreudpport" $acl $seq "no" "deny udp any any eq $port"
return
}
proc restoretcpport {port acl seq} {
aclcmd "restoretcpport" $acl $seq "no" "deny tcp any any eq $port"
return
}
proc restoretcpdsthostport {addr port acl seq} {
aclcmd "restoretcpdsthostport" $acl $seq "no" ""
return
}
proc sync {} {
global cprompt
global currentmode
global currentacl
# Save these so we can change back when we're done
set oldmode $currentmode
set oldacl $currentacl
set err [entermode "enable" ""]
if { $err != "" } {
puts "sync-failed -"
puts "$err"
puts "."
return
}
sendcmd "copy running-config startup-config"
set timeout 10
expect {
# Try to be compatible with old/new versions of this dialogue...
#
# "Proceed with copy"
# "Proceed to copy the file"
#
-re "Proceed \[^\r\n]* copy\[^:\r\n]*:" {
# done
}
"Connection closed by foreign host" {
puts "sync-failed -"
puts "ssh session ended"
puts "."
# exit so acld will start a fresh expect session
exit
}
-re $cprompt {
# This action must be last
puts "sync"
return
}
timeout {
puts "sync-failed -"
puts "confirm timeout ($timeout seconds)"
puts "exiting"
puts "."
# exit so acld will start a fresh expect session
exit
}
}
sendcmd "yes"
set timeout 90
expect {
-re "(% Error: \[^\r\n]*)\[\r\n]*\r\n" {
puts "sync-failed -"
puts "$expect_out(1,string)"
puts "."
expect -re $cprompt
return
}
-re "bytes successfully copied\[\r\n]*\r\n" {
# done
expect -re $cprompt
}
"Connection closed by foreign host" {
puts "sync-failed -"
puts "ssh session ended"
puts "."
# exit so acld will start a fresh expect session
exit
}
timeout {
puts "sync-failed -"
puts "copy timeout ($timeout seconds)"
puts "exiting"
puts "."
# exit so acld will start a fresh expect session
exit
}
}
set err [entermode $oldmode $oldacl]
if { $err != "" } {
puts "sync-failed -"
puts "$err"
puts "."
return
}
puts "sync"
return
}
proc unpermitudpdsthostport {addr port acl seq} {
aclcmd "unpermitudpdsthostport" $acl $seq "no" ""
return
}
proc unpermittcpdsthostport {addr port acl seq} {
aclcmd "unpermittcpdsthostport" $acl $seq "no" ""
return
}
# Local procedures
# Returns "ip" or "ipv6" based on the acl name
proc acl2ip {acl} {
global isipv6
if [catch { set ipv6 [set isipv6($acl)] } err] {
set ipv6 0
}
if { $ipv6 } {
set ip "ipv6"
} else {
set ip "ip"
}
return $ip
}
# aclcmd "restore" $acl $seq "no" "deny host $addr"
proc aclcmd {what acl seq pre cmd} {
global cprompt
global lastseq
if { $seq != 0 } {
if { $seq > $lastseq } {
puts "$what-failed -"
puts "sequence too large ($seq > $lastseq)"
puts "."
return
}
set cmd "seq $seq $cmd"
}
if { [string length $pre] > 0 } {
set cmd "$pre $cmd"
}
set err [entermode "acl" $acl]
if { $err != "" } {
puts "$what-failed -"
puts "$err"
puts "."
return
}
sendcmd "$cmd"
set timeout 10
expect {
-re "(% Error: IPv6 Access-list not supported on this CAM profile\.)\[\r\n]*\r\n" {
puts "$what-failed -"
puts "$expect_out(1,string)"
puts "."
return
}
-re "(% Error: \[^\r\n]*)\[\r\n]*\r\n" {
puts "$what-failed -"
puts "$expect_out(1,string)"
puts "exiting"
puts "."
# exit so acld will start a fresh expect session
exit
}
-re "^\[^\r\n]*\[\r\n]*\r\n" {
exp_continue
}
-re $cprompt {
# success
puts "$what"
return
}
timeout {
puts "$what-failed -"
puts "aclcmd: timeout ($timeout seconds)"
puts "."
# exit so acld will start a fresh expect session
exit
}
"Connection closed by foreign host" {
puts "$what-failed -"
puts "ssh session ended"
puts "."
# exit so acld will start a fresh expect session
exit
}
default {
puts "$what-failed -"
puts "aclcmd: unknown problem"
puts "."
return
}
}
return
}
# Fall back to this version when the ACL is not active
proc listaclsimple {acl} {
global cprompt
set err [entermode "acl" $acl]
if { $err != "" } {
puts "listacl-failed -"
puts "$err"
puts "."
return
}
set ip [acl2ip $acl]
if { $ip == "ip" } {
set expr "ip access-list extended $acl\[\r\n]*\r\n"
} else {
set expr "ipv6 access-list $acl\[\r\n]*\r\n"
}
sendcmd "show config"
set timeout 10
expect {
-re $expr {
# done
}
-re $cprompt {
# This action must be last
puts "listacl"
return
}
timeout {
puts "listacl-failed -"
puts "listaclsimple: timeout 1 ($timeout seconds)"
puts "."
# exit so acld will start a fresh expect session
exit
}
}
# List 'em out
puts "listacl -"
expect {
-re "^ *(\[^\r\n]*)\[\r\n]*\r\n" {
printacl $expect_out(1,string)
exp_continue
}
-re $cprompt {
# This action must be last
# done
}
timeout {
# We've already declared success
puts "listaclsimple: timeout 2 ($timeout seconds)"
puts "."
# exit so acld will start a fresh expect session
exit
}
}
puts "."
return
}
proc _listroute {ip} {
global cprompt
sendcmd "show $ip route"
set timeout 10
expect {
-re " ----+\[\r\n]+" {
# ok (IPv4 or IPv6)
}
-re $cprompt {
# This action must be last
puts "# couldn't find routes"
return
}
timeout {
puts "# timeout ($timeout seconds)"
puts "."
# exit so acld will start a fresh expect session
exit
}
}
set what ""
set src ""
set dst ""
expect {
-re "^ .(\[BCORS]) .. (\[^ \r\n]+) *via (\[^, \r\n]+).*\[\r\n]*\r\n" {
# IPv4
set what $expect_out(1,string)
set src $expect_out(2,string)
set dst $expect_out(3,string)
printroute $what $src $dst
exp_continue
}
-re "^ .(\[BCORS]) .. (\[^ \r\n]+) *Direct, (\[^ \r\n]+ \[^ \r\n]+) .*\[\r\n]*\r\n" {
# IPv4
set what $expect_out(1,string)
set src $expect_out(2,string)
set dst $expect_out(3,string)
printroute $what $src $dst
exp_continue
}
-re "^ .(\[BCORSL]) .. (\[^ \r\n]+) *\[[]\[0-9]+/\[0-9]+]\[\r\n]*\r\n" {
# IPv6: first line
set what $expect_out(1,string)
set src $expect_out(2,string)
exp_continue
}
-re "^ +via (\[^,\r\n]+), .*\[\r\n]*\r\n" {
set dst $expect_out(1,string)
printroute $what $src $dst
exp_continue
}
-re "^ +Direct, (\[^,\r\n]+), .*\[\r\n]*\r\n" {
# IPv6: second line
set dst $expect_out(1,string)
printroute $what $src $dst
exp_continue
}
-re "^\[\r\n]*\r\n" {
# eat blank lines
exp_continue
}
-re "^(.*)\[\r\n]*\r\n" {
# Echo stuff we don't understand
puts "# unknown $expect_out(1,string)"
exp_continue
}
-re $cprompt {
# This action must be last
# done
}
timeout {
puts "# timeout ($timeout seconds)"
puts "."
# exit so acld will start a fresh expect session
exit
}
}
return
}
proc printacl {str} {
# Break into a list
set av [split $str " "]
set an [llength $av]
# XXX gag me: remove empty elements (caused by multiple blanks)
set n 0
while { $n < $an } {
if { [lindex $av $n] == "" } {
set av [concat [lrange $av 0 [expr $n - 1]] \
[lrange $av [expr $n + 1] [expr $an - 1]]]
set an [expr $an - 1]
} else {
incr n
}
}
if { $an < 3 } {
error "# printacl: not enough args \"$str\""
}
if { [lindex $av 0] == "seq" } {
set seq [lindex $av 1]
} else {
set seq 0
}
if { [lindex $av [expr $an - 3]] == "count" } {
set count [lindex $av [expr $an - 2]]
set count [string trimleft $count "("]
# Remove from argument vector
set an [expr $an - 3]
set av [lrange $av 0 $an]
} else {
set count 0
}
set which [lindex $av 2]
if { $which == "deny" } {
set which "block"
} elseif { $which != "permit" } {
error "# printacl: can't find permit/deny \"$av\""
}
set proto [lindex $av 3]
set what "unknown # $str"
set append ""
if { $proto == "ip" || $proto == "icmp" } {
if { $proto == "icmp" } {
set protostr $proto
} else {
set protostr ""
}
if { $an == 7 &&
[lindex $av 4] == "host" &&
[lindex $av 6] == "any" } {
# "permithost/blockhost"
# seq 123 deny ip host 10.0.0.1 any
# 0 1 2 3 4 5 6
set what "[set which][set protostr]host"
append append [lindex $av 5]
} elseif { $an == 8 &&
[lindex $av 4] == "host" &&
[lindex $av 6] == "host" } {
# "permithosthost/blockhosthost"
# seq 666 deny ip host 1.2.3.4 host 4.5.6.7
# 0 1 2 3 4 5 6 7
set what "[set which][set protostr]hosthost"
append append "[lindex $av 5] [lindex $av 7]"
} elseif { $an == 6 &&
[string first "/" [lindex $av 4]] > 1 &&
[lindex $av 5] == "any" } {
# "permitnet/blocknet"
# "show ip accounting" style
# (net and mask width one word)
# seq 123 permit ip 10.0.0.0/24 any
# 0 1 2 3 4 5
set what "[set which][set protostr]net"
append append [lindex $av 4]
} elseif { $an == 7 &&
[string first "/" [lindex $av 5]] == 0 &&
[lindex $av 6] == "any" } {
# "permitnet/blocknet"
# "show config" style
# (blank between net and mask width)
# seq 123 permit ip 10.0.0.0 /24 any
# 0 1 2 3 4 5 6
set what "[set which][set protostr]net"
append append "[lindex $av 4][lindex $av 5]"
} elseif { $an == 6 &&
[lindex $av 4] == "any" &&
[string first "/" [lindex $av 5]] > 1 } {
# "permitdstnet/blockdstnet"
# "show ip accounting" style
# (net and mask width one word)
# seq 123 permit ip any 10.0.0.0/24
# 0 1 2 3 4 5
set what "[set which][set protostr]dstnet"
append append [lindex $av 5]
} elseif { $an == 7 &&
[lindex $av 4] == "any" &&
[string first "/" [lindex $av 6]] == 0 } {
# "permitdstnet/blockdstnet"
# "show config" style
# (blank between net and mask width)
# seq 123 permit ip any 10.0.0.0 /24
# 0 1 2 3 4 5 6
set what "[set which][set protostr]dstnet"
append append "[lindex $av 5][lindex $av 6]"
} elseif { $an == 6 && [lrange $av 4 5] == "any any" } {
# "permitany/blockany"
# seq 123 permit ip any any
# 0 1 2 3 4 5
set what "[set which][set protostr]any"
} elseif { $an == 7 &&
[string first "/" [lindex $av 4]] > 0 &&
[lindex $av 5] == "host" } {
# "permitnethost/blocknethost"
# "permiticmpnethost/blockicmpnethost"
# "show ip accounting" style
# (net and mask width one word)
# XXX do we still need the split version?
# seq 6 permit ip 10.0.0.0/22 host 10.1.2.3
# 0 1 2 3 4 5 6
set what "$which[set protostr]nethost"
append append "[lindex $av 4] [lindex $av 6]"
} elseif { $an == 7 &&
[lrange $av 4 5] == "any host" } {
# "permiticmpdsthost/blockicmpdsthost"
# seq 123 permit icmp any host 10.0.0.1
# 0 1 2 3 4 5 6
set what "$which[set protostr]dsthost"
append append "[lindex $av 6]"
}
} elseif { $proto == "udp" || $proto == "tcp" } {
if { $an == 8 &&
[lrange $av 4 6] == "any any eq" } {
# "permitudpport/blockudpport"
# "permittcpport/blocktcpport"
# seq 123 deny udp any any eq 666
# 0 1 2 3 4 5 6 7
set what "$which[set proto]port"
append append [lindex $av 7]
} elseif { $an == 9 &&
[lindex $av 4] == "host" &&
[lrange $av 6 7] == "any eq" } {
# "permitudphostport/blockudphostport"
# "permittcphostport/blocktcphostport"
# seq 123 permit udp host 10.0.0.1 any eq 666
# 0 1 2 3 4 5 6 7 8
set what "$which[set proto]hostport"
append append "[lindex $av 5] [lindex $av 8]"
} elseif { $an == 9 &&
[lrange $av 4 5] == "any host" &&
[lindex $av 7] == "eq" } {
# "permitudpdsthostport/blockudpdsthostport"
# "permittcpdsthostport/blocktcpdsthostport"
# seq 123 permit udp any host 10.0.0.1 eq 666
# 0 1 2 3 4 5 6 7 8
set what "$which[set proto]dsthostport"
append append "[lindex $av 6] [lindex $av 8]"
} elseif { $an == 7 &&
[string first "/" [lindex $av 5]] > 0 &&
[lindex $av 4] == "any" &&
[lindex $av 6] == "eq" } {
# "permitudpdsthostport/blockudpdsthostport"
# "permittcpdsthostport/blocktcpdsthostport"
# seq 500 permit tcp any 131.243.1.6/31 eq 22
# 0 1 2 3 4 5 6 7
set what "$which[set proto]dstnetport"
append append "[lindex $av 5] [lindex $av 7]"
} elseif { $an == 8 &&
[string first "/" [lindex $av 4]] > 0 &&
[lrange $av 5 6] == "any eq" } {
# "permitudpnetport/blockudpnetport"
# "permittcpnetport/blocktcpnetport"
# "show ip accounting" style
# (net and mask width one word)
# seq 123 permit udp 10.0.0.0/8 any eq 666
# 0 1 2 3 4 5 6 7
set what "$which[set proto]netport"
append append "[lindex $av 4] [lindex $av 7]"
} elseif { $an == 9 &&
[string first "/" [lindex $av 5]] == 0 &&
[lrange $av 6 7] == "any eq" } {
# "permitudpnetport/blockudpnetport"
# "permittcpnetport/blocktcpnetport"
# "show config" style
# (blank between net and mask width)
# seq 123 permit udp 10.0.0.0 /8 any eq 666
# 0 1 2 3 4 5 6 7 8
set what "$which[set proto]netport"
append append "[lindex $av 4][lindex $av 5]"
append append " [lindex $av 8]"
} elseif { $an == 9 &&
[lindex $av 4] == "host" &&
[lindex $av 6] == "eq" &&
[lindex $av 8] == "any" } {
# "permitudphostsrcport/blockudphostsrcport"
# "permittcphostsrcport/blocktcphostsrcport"
# seq 123 permit udp host 10.0.0.1 eq 666 any
# 0 1 2 3 4 5 6 7 8
set what "$which[set proto]hostsrcport"
append append "[lindex $av 5] [lindex $av 7]"
} elseif { $an == 10 &&
[lindex $av 4] == "host" &&
[lindex $av 6] == "host" &&
[lindex $av 8] == "eq" } {
# "permitudphostpairdstport/blockudphostpairdstport"
# "permittcphostpairdstport/blocktcphostpairdstport"
# seq 123 permit udp host 10.0.0.1 host 10.0.0.2 eq 666
# 0 1 2 3 4 5 6 7 8 9
set what "$which[set proto]hostpairdstport"
append append "[lindex $av 5] [lindex $av 7]"
append append " [lindex $av 9]"
} elseif { $an == 9 &&
[string first "/" [lindex $av 4]] > 0 &&
[lindex $av 5] == "host" &&
[lindex $av 7] == "eq" } {
# "permitudpnethostport/blockudpnethostport"
# "permittcpnethostport/blocktcpnethostport"
# "show ip accounting" style
# (net and mask width one word)
# XXX do we still need the split version?
# seq 7 permit tcp 10.0.0.0/22 host 10.3.4.5 eq 5
# 0 1 2 3 4 5 6 7 8
set what "$which[set proto]nethostport"
append append "[lindex $av 4] [lindex $av 6]"
append append " [lindex $av 8]"
} elseif { $an == 6 &&
[string first "/" [lindex $av 5]] > 0 &&
[lindex $av 4] == "any" } {
# "permitudpdstnet/blockudpdstnet"
# "permittcpdstnet/blocktcpdstnet"
# "show ip accounting" style
# (net and mask width one word)
# XXX2 do we still need the split version?
# seq 4 deny tcp any 10.1.0.0/30
# 0 1 2 3 4 5
set what "$which[set proto]dstnet"
append append "[lindex $av 5]"
} elseif { $an == 7 &&
[lrange $av 4 5] == "any host" } {
# "permitudpdsthost/blockudpdsthost"
# seq 123 permit udp any host 10.0.0.1
# 0 1 2 3 4 5 6
set what "$which[set proto]dsthost"
append append "[lindex $av 6]"
}
}
set msg "$seq $count $what"
if { $append != "" } {
append msg " $append"
}
puts $msg
return
}
proc printroute {what src dst} {
# Strip trailing /32 or /128 from host routes
if { [string first "." $src] > 0 } {
set w "32"
} else {
set w "128"
}
set i [string first "/$w" $src]
if { $i > 1 } {
set src [string range $src 0 [expr $i - 1]]
}
if { $what == "C" } {
# interface
puts "I $src"
} elseif { $what == "O" || $what == "B" || $what == "R" } {
# dynamic
puts "D $src $dst"
} elseif { $what == "S" || $what == "L" } {
if { $dst == "Nu 0" } {
# null zero
puts "N $src"
} else {
# static
puts "S $src $dst"
}
} else {
puts "# unknown $what $src $dst"
}
return
}
proc nullzerocmd {what addr pre} {
global cprompt
set err [entermode "config" {}]
if { $err != "" } {
puts "$what-failed -"
puts "$err"
puts "."
return
}
if { [string first "." $addr] > 0 } {
set ip "ip"
set w "32"
} else {
set ip "ipv6"
set w "128"
}
if { [string first "/" $addr] > 0 } {
# Network with mask
set cmd "$ip route $addr null 0"
} else {
# Host address
set cmd "$ip route $addr/$w null 0"
}
if { $pre != "" } {
set cmd "$pre $cmd"
}
sendcmd $cmd
set timeout 10
expect {
-re "(% Error: \[^\r\n]*)\[\r\n]*\r\n" {
puts "$what-failed -"
puts "$expect_out(1,string)"
puts "exiting"
puts "."
# exit so acld will start a fresh expect session
exit
}
-re "^\[^\r\n]*\[\r\n]*\r\n" {
exp_continue
}
"Connection closed by foreign host" {
puts "$what-failed -"
puts "ssh session ended"
puts "."
# exit so acld will start a fresh expect session
exit
}
-re $cprompt {
# This action must be last
# success
puts "$what"
return
}
timeout {
puts "$what-failed -"
puts "nullzerocmd: timeout ($timeout seconds)"
puts "."
# exit so acld will start a fresh expect session
exit
}
default {
puts "$what-failed -"
puts "nullzerocmd: unknown problem"
puts "."
return
}
}
return
}
proc sendcmd {cmd} {
global spawn_id
if [catch {send -- "$cmd\r"} err] {
puts "sendcmd: $err"
# exit so acld will start a fresh expect session
exit
}
return
}
proc sendpass {what pass1 pass2} {
global spawn_id
global cprompt
# Send first password
sendcmd "$pass1"
set timeout 10
set which "first"
expect {
"Received disconnect" {
puts "login-failed -"
puts "all passwords failed"
puts "."
return 0
}
"password: " {
if { $which == "second" } {
puts "login-failed -"
puts "first and second $what passwords failed"
puts "."
return 0
}
# Maybe we were only given one password
if { $pass2 == "" } {
puts "login-failed -"
puts "$what password failed"
puts "."
return 0
}
# Send second password
sendcmd "$pass2"
set which "second"
exp_continue
}
-re "^Permission denied.*\[\r\n]*\r\n" {
exp_continue
}
-re $cprompt {
# This action must be last
# done
}
timeout {
puts "login-failed -"
puts "sendpass: timeout ($timeout seconds)"
puts "."
return 0
}
}
return 1
}
#
# Modes we currently know about:
#
# enable
# config
# acl
#
# This table tells entermode how to get from one mode to another
#
set modemoves(enable,enable) { }
set modemoves(enable,config) { "config" }
set modemoves(enable,acl) { "config" "acl" }
set modemoves(config,enable) { "exit" }
set modemoves(config,config) { }
set modemoves(config,acl) { "acl" }
set modemoves(acl,enable) { "exit" "exit" }
set modemoves(acl,config) { "exit" }
set modemoves(acl,acl) { "acl" }
proc entermode {mode acl} {
global cprompt
global currentmode
global currentacl
global modemoves
set timeout 10
if [catch {set moves $modemoves($currentmode,$mode)} err] {
puts "entermode: $err"
# exit so acld will start a fresh expect session
exit
}
set n [llength $moves]
if { $n == 0 } {
return ""
}
set ip [acl2ip $acl]
set errstr ""
for { set i 0 } { $i < $n } { incr i } {
set move [lindex $moves $i]
if { $move != "acl" } {
set cmd "$move"
} elseif { $currentmode != "acl" || $currentacl != $acl } {
if { $ip == "ip" } {
set cmd "ip access-list extended $acl"
} else {
set cmd "ipv6 access-list $acl"
}
} else {
# already there
continue
}
sendcmd "$cmd"
expect {
-re "(% Warning: The following users are currently configuring the system:)\[\r\n]*\r\n" {
# Ignore
exp_continue
}
-re "(User \"\[^\"\r\n]*\" on \[^\r\n]*)\[\r\n]*\r\n" {
# Ignore
exp_continue
}
-re "(% Error: Access-list was not applied on this interface\.)\[\r\n]*\r\n" {
set errstr "$expect_out(1,string)"
if { $currentmode != "enable" } {
set currentmode "config"
}
exp_continue
}
-re "(% Error: IPv6 Access-list not supported on this CAM profile\.)\[\r\n]*\r\n" {
set errstr "$expect_out(1,string)"
set currentmode "config"
exp_continue
}
-re "(% Error: \[^\r\n]*)\[\r\n]*\r\n" {
set errstr "$expect_out(1,string)"
exp_continue
}
"Connection closed by foreign host" {
puts "entermode: ssh session ended"
# exit so acld will start a fresh expect session
exit
}
-re $cprompt {
# This action must be last
# done
}
timeout {
puts "entermode: timeout ($timeout seconds)"
# exit so acld will start a fresh expect session
exit
}
}
# Bail at the first sign of trouble
if { $errstr != "" } {
break
}
# Keep track of current mode in case we're making more than one
if { $move == "config" } {
set currentmode $move
} else {
set currentmode $mode
}
if { $move == "acl" } {
set currentacl $acl
}
}
return $errstr
}
# These are required to be at the end
log_user 0
interpreter