summaryrefslogtreecommitdiff
path: root/src/pmdas/cisco
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmdas/cisco')
-rw-r--r--src/pmdas/cisco/Cisco.pmchart11
-rw-r--r--src/pmdas/cisco/GNUmakefile70
-rw-r--r--src/pmdas/cisco/Install156
-rw-r--r--src/pmdas/cisco/README76
-rw-r--r--src/pmdas/cisco/Remove38
-rw-r--r--src/pmdas/cisco/Samples291
-rw-r--r--src/pmdas/cisco/Tested76
-rw-r--r--src/pmdas/cisco/cisco.c265
-rw-r--r--src/pmdas/cisco/cisco.h86
-rw-r--r--src/pmdas/cisco/cisco.in_util.pmie64
-rw-r--r--src/pmdas/cisco/cisco.out_util.pmie64
-rw-r--r--src/pmdas/cisco/help76
-rw-r--r--src/pmdas/cisco/interface.c46
-rwxr-xr-xsrc/pmdas/cisco/parse.sh3
-rw-r--r--src/pmdas/cisco/pmda.c401
-rw-r--r--src/pmdas/cisco/pmns28
-rw-r--r--src/pmdas/cisco/probe.c367
-rw-r--r--src/pmdas/cisco/root10
-rw-r--r--src/pmdas/cisco/telnet.c755
19 files changed, 2883 insertions, 0 deletions
diff --git a/src/pmdas/cisco/Cisco.pmchart b/src/pmdas/cisco/Cisco.pmchart
new file mode 100644
index 0000000..6baf4e7
--- /dev/null
+++ b/src/pmdas/cisco/Cisco.pmchart
@@ -0,0 +1,11 @@
+#pmchart
+Version 1.2 host dynamic
+
+Chart Style plot
+ Plot Color #-cycle Host * Metric cisco.rate_in
+
+Chart Style plot
+ Plot Color #-cycle Host * Metric cisco.rate_out
+
+#
+# Created Mon Sep 1 11:34:14 1997
diff --git a/src/pmdas/cisco/GNUmakefile b/src/pmdas/cisco/GNUmakefile
new file mode 100644
index 0000000..e6c2733
--- /dev/null
+++ b/src/pmdas/cisco/GNUmakefile
@@ -0,0 +1,70 @@
+#
+# Copyright (c) 2014 Red Hat.
+# Copyright (c) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+
+TOPDIR = ../../..
+include $(TOPDIR)/src/include/builddefs
+
+IAM = cisco
+DOMAIN = CISCO
+TARGETS = $(IAM)$(EXECSUFFIX) probe$(EXECSUFFIX)
+CFILES = cisco.c pmda.c interface.c telnet.c
+HFILES = cisco.h
+DFILES = README
+LSRCFILES=Install Remove root pmns Cisco.pmchart help Samples Tested $(DFILES) \
+ cisco.in_util.pmie cisco.out_util.pmie probe.c parse.sh
+
+LLDLIBS = $(PCP_PMDALIB) $(LIB_FOR_PTHREADS)
+
+PMDADIR = $(PCP_PMDAS_DIR)/$(IAM)
+PMCHART = $(PCP_VAR_DIR)/config/pmchart
+PMIEDIR = $(PCP_VAR_DIR)/config/pmieconf/$(IAM)
+
+LDIRT = domain.h cisco.log *.dir *.pag so_locations a.out probe.o $(TARGETS)
+
+default: build-me
+
+include $(BUILDRULES)
+
+ifneq "$(TARGET_OS)" "mingw"
+build-me: $(TARGETS)
+
+install: build-me
+ $(INSTALL) -m 755 -d $(PMDADIR)
+ $(INSTALL) -m 755 $(IAM) $(PMDADIR)/pmda$(IAM)
+ $(INSTALL) -m 755 parse.sh $(PMDADIR)/parse
+ $(INSTALL) -m 755 probe Install Remove $(PMDADIR)
+ $(INSTALL) -m 644 $(DFILES) root help pmns domain.h $(PMDADIR)
+ $(INSTALL) -m 644 Cisco.pmchart $(PMCHART)/Cisco
+ $(INSTALL) -m 755 -d $(PMIEDIR)
+ $(INSTALL) -m 644 cisco.in_util.pmie $(PMIEDIR)/in_util
+ $(INSTALL) -m 644 cisco.out_util.pmie $(PMIEDIR)/out_util
+else
+build-me:
+install:
+endif
+
+$(IAM)$(EXECSUFFIX): $(OBJECTS)
+
+probe$(EXECSUFFIX): probe.o interface.o telnet.o
+ $(CCF) -o $@ $(LDFLAGS) probe.o interface.o telnet.o $(LDLIBS)
+
+cisco.o: domain.h
+
+domain.h: ../../pmns/stdpmid
+ $(DOMAIN_MAKERULE)
+
+default_pcp: default
+
+install_pcp: install
diff --git a/src/pmdas/cisco/Install b/src/pmdas/cisco/Install
new file mode 100644
index 0000000..5ee4742
--- /dev/null
+++ b/src/pmdas/cisco/Install
@@ -0,0 +1,156 @@
+#! /bin/sh
+#
+# Copyright (c) 1997-2003 Silicon Graphics, Inc. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# Install the cisco PMDA and/or PMNS
+#
+
+. $PCP_DIR/etc/pcp.env
+. $PCP_SHARE_DIR/lib/pmdaproc.sh
+
+iam=cisco
+pmda_interface=2
+forced_restart=false
+
+# Do it
+#
+pmdaSetup
+
+check_delay=20
+pollrate=120 # poll each Cisco interface once every 120 seconds
+ # -- change this if desired
+
+# special cisco PMDA args
+
+if $do_pmda
+then
+ args="-r$pollrate"
+ default="wanptg"
+ while true
+ do
+ no_host=true
+ while $no_host
+ do
+ echo
+ $PCP_ECHO_PROG $PCP_ECHO_N "Cisco hostname or IP address? [return to quit Cisco selection] ""$PCP_ECHO_C"
+ read host
+ [ "X$host" = X ] && break
+ echo '
+A username and/or user-level password may be required for the Cisco
+"show interface" command.
+ If you are unsure, try the command
+ $ telnet '$host'
+ and if the prompt "Username:" appears, then a username is required,
+ and if the prompt "Password:" appears, a user-level password is required,
+ otherwise respond with an empty line for the next two questions.
+ Once logged in, we need to know the termination string for the command
+ line prompt (one or more unique characters at the end of the prompt) -
+ the default is ">", but if this is not correct, enter the prompt
+ termination string also.
+'
+ $PCP_ECHO_PROG $PCP_ECHO_N "Cisco username? ""$PCP_ECHO_C"
+ read username
+ userarg=""
+ [ "X$username" != X ] && userarg="-U$username"
+ $PCP_ECHO_PROG $PCP_ECHO_N "User-level Cisco password? ""$PCP_ECHO_C"
+ read passwd
+ passarg=""
+ [ "X$passwd" != X ] && passarg="-P$passwd"
+ $PCP_ECHO_PROG $PCP_ECHO_N "Cisco command line prompt termination? [>] ""$PCP_ECHO_C"
+ read prompt
+ promptarg=""
+ [ "X$prompt" != X ] && promptarg="-s'$prompt'"
+ echo "Probing Cisco for list of interfaces ..."
+ for try in 1 2 3
+ do
+ intf=`eval ./probe $userarg $passarg $promptarg $host 2>$tmp/err`
+ [ ! -z "$intf" ] && break
+ sleep 2
+ done
+ if [ -z "$intf" ]
+ then
+ echo '
+There appears to be a problem ... after three attempts could not get
+interfaces. Output at the last attempt was:'
+ sed -e 's/^/ /' <$tmp/err
+ echo '
+You may wish to try the following commands to identify the configured
+interfaces for this Cisco.
+ $ telnet '$host'
+ ....> terminal length 0
+ ....> show interface
+ ....> quit
+'
+ else
+ no_host=false
+ fi
+ done
+ [ "X$host" = X ] && break
+
+ if [ -z "$username" ]
+ then
+ login=""
+ else
+ login="@$username"
+ fi
+ [ ! -z "$passwd" ] && login="$login?$passwd"
+ [ ! -z "$prompt" ] && login="$login!$prompt"
+
+ echo '
+Enter interfaces to monitor, one per line in the format tX where "t" is
+a type and one of "e" (Ethernet), "E" (FastEthernet), "f" (Fddi), "s"
+(Serial), "a" (ATM), "B" (ISDN BRI) or "h" (HSSC) and "X" is an
+interface identifier which is either an integer (e.g. 4000 Series
+routers) or two integers separated by a slash (e.g. 7000 Series
+routers).'
+
+ while true
+ do
+ echo
+ echo 'The currently unselected interfaces for the Cisco "'$host'" are:'
+ echo "$intf" | fmt | sed -e 's/^/ /'
+ echo 'Enter "*" to select all, "quit" to terminate selections for this Cisco.'
+
+ first=`echo "$intf" | sed -e 's/ .*//'`
+ [ -z "$first" ] && first=quit
+ $PCP_ECHO_PROG $PCP_ECHO_N "Interface? [$first] ""$PCP_ECHO_C"
+ read ans
+ [ "X$ans" = Xquit ] && break
+ if [ "X$ans" = "X*" ]
+ then
+ # do them all
+ for ans in `echo "$intf"`
+ do
+ args="$args $host:$ans$login"
+ login=''
+ done
+ break
+ fi
+ [ -z "$ans" ] && ans="$first"
+ if echo " $intf" | grep " $ans" >/dev/null
+ then
+ sed_ans=`echo $ans | sed -e 's;/;\\\\/;g'`
+ intf=`echo " $intf" | sed -e "s/ $sed_ans//" -e 's/^ //'`
+ else
+ echo "Warning: $ans is not in the list, I hope you know what you're doing"
+ fi
+ args="$args $host:$ans$login"
+ login=''
+ [ -z "$intf" ] && break
+ done
+ done
+fi
+
+pmdaInstall
+
+exit 0
diff --git a/src/pmdas/cisco/README b/src/pmdas/cisco/README
new file mode 100644
index 0000000..908c837
--- /dev/null
+++ b/src/pmdas/cisco/README
@@ -0,0 +1,76 @@
+Performance Co-Pilot PMDA for Monitoring Cisco Routers
+======================================================
+
+This PMDA is capable of collecting throughput measures from Cisco
+routers throughout a network.
+
+The PMDA needs to be configured to collect performance data from a
+designated set of interfaces on nominated Cisco routers. There is one
+instance of the metrics for nominated each router-interface pair.
+
+Metrics
+=======
+
+The file ./help contains descriptions for all of the metrics exported
+by this PMDA.
+
+Once the PMDA has been installed, the following command will list all
+the available metrics and their explanatory "help" text:
+
+ $ pminfo -fT cisco
+
+Installation
+============
+
+ + # cd $PCP_PMDAS_DIR/cisco
+
+ + Check that there is no clash in the Performance Metrics Domain
+ defined in ./domain.h and the other PMDAs currently in use (see
+ $PCP_PMCDCONF_PATH). If there is, edit ./domain.h to choose another
+ domain number.
+
+ + The Cisco PMDA is one that polls the Cisco routers, and caches the
+ most recent value for the performance metrics. The cached values
+ are the ones returned via the PMCD to clients requesting Cisco
+ performance metrics. The default polling rate is once every two
+ minutes to each Cisco interface being monitored, if you wish to
+ change this, edit Install and change the value of pollrate near the
+ start of the script.
+
+ + Then simply use
+
+ # ./Install
+
+ and choose both the "collector" and "monitor" installation
+ configuration options.
+
+ You will be prompted to identify the Cisco routers and
+ interfaces you wish to monitor.
+
+De-installation
+===============
+
+ + Simply use
+
+ # cd $PCP_PMDAS_DIR/cisco
+ # ./Remove
+
+Troubleshooting
+===============
+
+ + After installing or restarting the agent, the PMCD log file
+ ($PCP_LOG_DIR/pmcd/pmcd.log) and the PMDA log file
+ ($PCP_LOG_DIR/pmcd/cisco.log) should be checked for any warnings
+ or errors.
+
+ + The configured interfaces on a particular Cisco may be discovered
+ using the $PCP_PMDAS_DIR/cisco/probe application. See pmdacisco(1)
+ for more details.
+
+ + The $PCP_PMDAS_DIR/cisco/parse application supports the same
+ command line options as pmdacisco for identifying interfaces on
+ Cisco devices and shares the parser for the output from the Cisco
+ "show interface" command; this application may be used to gain
+ diagnostic traces of the interaction between the parser code and
+ the Cisco device in the event that metrics values are not being
+ returned by the Cisco PMDA. See pmdacisco(1) for more details.
diff --git a/src/pmdas/cisco/Remove b/src/pmdas/cisco/Remove
new file mode 100644
index 0000000..0f4f109
--- /dev/null
+++ b/src/pmdas/cisco/Remove
@@ -0,0 +1,38 @@
+#! /bin/sh
+#
+# Copyright (c) 1997 Silicon Graphics, Inc. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Remove the cisco PMDA and/or PMNS
+#
+
+# Get standard environment
+. $PCP_DIR/etc/pcp.env
+
+# Get the common procedures and variable assignments
+#
+. $PCP_SHARE_DIR/lib/pmdaproc.sh
+
+# The name of the PMDA
+#
+iam=cisco
+
+# Do it
+#
+pmdaSetup
+pmdaRemove
+
+exit 0
diff --git a/src/pmdas/cisco/Samples b/src/pmdas/cisco/Samples
new file mode 100644
index 0000000..dd25be6
--- /dev/null
+++ b/src/pmdas/cisco/Samples
@@ -0,0 +1,291 @@
+
+Serial 0 is up, line protocol is up
+ Hardware is MK5025
+ Description: frame-relay to MtVA, Tokyo, Hong Kong
+ Internet address is 155.11.201.172, subnet mask is 255.255.255.128
+ MTU 1500 bytes, BW 64 Kbit, DLY 20000 usec, rely 255/255, load 15/255
+ Encapsulation FRAME-RELAY, loopback not set, keepalive set (10 sec)
+ LMI DLCI 0, LMI sent 346516, LMI stat recvd 345070, LMI upd recvd 2
+ LMI type is ANSI Annex D
+ Last input 0:00:01, output 0:00:00, output hang never
+ Last clearing of "show interface" counters never
+ Output queue 0/8, 298580 drops; input queue 0/75, 0 drops
+ Five minute input rate 60000 bits/sec, 16 packets/sec
+ Five minute output rate 4000 bits/sec, 12 packets/sec
+ 18139408 packets input, 2763796661 bytes, 0 no buffer
+ Received 0 broadcasts, 0 runts, 0 giants
+ 189 input errors, 189 CRC, 0 frame, 0 overrun, 0 ignored, 0 abort
+ 15860554 packets output, 3098844973 bytes, 0 underruns
+ 0 output errors, 0 collisions, 668 interface resets, 0 restarts
+ 686 carrier transitions
+
+Ethernet 0 is up, line protocol is up
+ Hardware is Lance, address is 0000.0c03.ed85 (bia 0000.0c03.ed85)
+ Description: Sydney, Australia
+ Internet address is 155.11.226.3, subnet mask is 255.255.255.128
+ MTU 1500 bytes, BW 10000 Kbit, DLY 1000 usec, rely 255/255, load 1/255
+ Encapsulation ARPA, loopback not set, keepalive set (10 sec)
+ ARP type: ARPA, ARP Timeout 4:00:00
+ Last input 0:00:00, output 0:00:00, output hang never
+ Last clearing of "show interface" counters never
+ Output queue 0/40, 19188 drops; input queue 1/75, 0 drops
+ Five minute input rate 5000 bits/sec, 10 packets/sec
+ Five minute output rate 60000 bits/sec, 13 packets/sec
+ 12884820 packets input, 1321046112 bytes, 0 no buffer
+ Received 1570813 broadcasts, 0 runts, 0 giants
+ 891 input errors, 891 CRC, 634 frame, 0 overrun, 0 ignored, 0 abort
+ 14717105 packets output, 870622060 bytes, 0 underruns
+ 98605 output errors, 1883820 collisions, 1 interface resets, 0 restarts
+
+Fddi2/0 is up, line protocol is up
+ Hardware is cxBus FDDI, address is 0000.0c38.4360 (bia 0000.0c38.4360)
+ Internet address is 192.26.80.22, subnet mask is 255.255.255.0
+ MTU 4470 bytes, BW 100000 Kbit, DLY 100 usec, rely 255/255, load 1/255
+ Encapsulation SNAP, loopback not set, keepalive not set
+ ARP type: SNAP, ARP Timeout 4:00:00
+ Phy-A state is connect, neighbor is unk, cmt signal bits 008/000, status QLS
+ Phy-B state is active, neighbor is M, cmt signal bits 20C/00E, status ILS
+ CFM is wrap B, token rotation 5000 usec, ring operational 0:00:58
+ Upstream neighbor 0800.6904.155d, downstream neighbor 0040.0b80.a052
+ Last input 0:00:00, output 0:00:00, output hang never
+ Last clearing of "show interface" counters 1w0d
+ Output queue 0/40, 85 drops; input queue 0/75, 33437 drops
+ Five minute input rate 160000 bits/sec, 39 packets/sec
+ Five minute output rate 93000 bits/sec, 108 packets/sec
+ 33780622 packets input, 4009491185 bytes, 87 no buffer
+ Received 3768432 broadcasts, 0 runts, 0 giants
+ 2 input errors, 1 CRC, 1 frame, 0 overrun, 19 ignored, 0 abort
+ 83194423 packets output, 612803885 bytes, 492 underruns
+ 0 output errors, 0 collisions, 0 interface resets, 0 restarts
+ 21602 transitions, 0 traces, 11625 claims, 0 beacon
+
+Serial1 is up, line protocol is up
+ Hardware is HD64570
+ Description: Frame-relay, MtV, Hong Kong, Sydney
+ MTU 1500 bytes, BW 1544 Kbit, DLY 20000 usec, rely 255/255, load 5/255
+ Encapsulation FRAME-RELAY, loopback not set, keepalive set (10 sec)
+ LMI enq sent 14998, LMI stat recvd 14885, LMI upd recvd 0, DTE LMI up
+ LMI enq recvd 0, LMI stat sent 0, LMI upd sent 0
+ LMI DLCI 0 LMI type is ANSI Annex D frame relay DTE
+ Broadcast queue 0/200, broadcasts sent/dropped 508604/0
+ Last input 0:00:00, output 0:00:00, output hang never
+ Last clearing of "show interface" counters never
+ Output queue 0/40, 947 drops; input queue 0/75, 0 drops
+ Five minute input rate 117000 bits/sec, 29 packets/sec
+ Five minute output rate 32000 bits/sec, 20 packets/sec
+ 2578327 packets input, 1105345262 bytes, 0 no buffer
+ Received 0 broadcasts, 0 runts, 0 giants
+ 54 input errors, 4 CRC, 0 frame, 0 overrun, 1 ignored, 4 abort
+ 1975049 packets output, 675844616 bytes, 0 underruns
+ 0 output errors, 0 collisions, 142 interface resets, 0 restarts
+ 3 carrier transitions
+ DCD=up DSR=up DTR=up RTS=up CTS=up
+
+Ethernet3/5 is up, line protocol is up
+ Hardware is cxBus Ethernet, address is 0000.0c38.436d (bia 0000.0c38.436d)
+ Internet address is 198.29.108.4, subnet mask is 255.255.255.0
+ MTU 1500 bytes, BW 10000 Kbit, DLY 1000 usec, rely 255/255, load 2/255
+ Encapsulation ARPA, loopback not set, keepalive set (10 sec)
+ ARP type: ARPA, ARP Timeout 4:00:00
+ Last input 0:00:03, output 0:00:01, output hang never
+ Last clearing of "show interface" counters 6w2d
+ Output queue 0/40, 54880 drops; input queue 0/75, 1492 drops
+ 5 minute input rate 1000 bits/sec, 0 packets/sec
+ 5 minute output rate 91000 bits/sec, 98 packets/sec
+ 24627812 packets input, 1448819515 bytes, 862 no buffer
+ Received 3959194 broadcasts, 79 runts, 4 giants
+ 292 input errors, 195 CRC, 14 frame, 0 overrun, 0 ignored, 0 abort
+ 0 input packets with dribble condition detected
+ 150470373 packets output, 3227527737 bytes, 0 underruns
+ 1274 output errors, 11605581 collisions, 0 interface resets, 0 restarts
+
+ATM12/0 is up, line protocol is up
+ Hardware is cxBus ATM
+ Internet address is 150.166.230.24 255.255.255.0
+ MTU 4470 bytes, BW 156250 Kbit, DLY 80 usec, rely 255/255, load 1/255
+ Encapsulation ATM, loopback not set, keepalive set (10 sec)
+ Encapsulation(s): AAL5, PVC mode
+ 256 TX buffers, 256 RX buffers, 2048 maximum active VCs, 1024 VCs per VP, 15 current VCCs
+ Last input 0:00:00, output 0:00:00, output hang never
+ Last clearing of "show interface" counters never
+ Output queue 0/40, 511 drops; input queue 0/75, 10612 drops
+ 5 minute input rate 181000 bits/sec, 116 packets/sec
+ 5 minute output rate 160000 bits/sec, 68 packets/sec
+ 658262505 packets input, 1239748718 bytes, 199 no buffer
+ Received 0 broadcasts, 0 runts, 0 giants
+ 2570 input errors, 2569 CRC, 1 frame, 0 overrun, 0 ignored, 0 abort
+ 788426419 packets output, 4188341273 bytes, 0 underruns
+ 0 output errors, 0 collisions, 21 interface resets, 0 restarts
+ 0 output buffer failures, 63 output buffers swapped out
+
+Hssi3/0 is administratively down, line protocol is down
+ Hardware is cxBus HSSI
+ Description: 45 Meg Microwave Link to Building 27
+ Internet address is 150.166.124.1 255.255.255.0
+ MTU 4470 bytes, BW 45045 Kbit, DLY 200 usec, rely 255/255, load 1/255
+ Encapsulation HDLC, loopback not set, keepalive set (10 sec)
+ Last input 1:07:12, output 1:07:08, output hang never
+ Last clearing of "show interface" counters never
+ Output queue 0/40, 2 drops; input queue 0/75, 37 drops
+ 5 minute input rate 0 bits/sec, 0 packets/sec
+ 5 minute output rate 0 bits/sec, 0 packets/sec
+ 306700515 packets input, 1443052046 bytes, 5 no buffer
+ Received 1118787 broadcasts, 0 runts, 0 giants
+ 0 parity
+ 241 input errors, 0 CRC, 241 frame, 0 overrun, 0 ignored, 0 abort
+ 246381377 packets output, 3684064154 bytes, 0 underruns
+ 0 output errors, 0 applique, 210 interface resets, 0 restarts
+ 0 output buffer failures, 83 output buffers swapped out
+ 8214 carrier transitions
+
+FastEthernet1/0 is up, line protocol is up
+ Hardware is cyBus FastEthernet Interface, address is 0060.3eb0.8c20 (bia 0060.3eb0.8c20)
+ Internet address is 192.111.17.1 255.255.255.0
+ MTU 1500 bytes, BW 100000 Kbit, DLY 100 usec, rely 255/255, load 1/255
+ Encapsulation ARPA, loopback not set, keepalive set (10 sec), fdx, MII
+ ARP type: ARPA, ARP Timeout 4:00:00
+ Last input 0:00:05, output 0:00:05, output hang never
+ Last clearing of "show interface" counters never
+ Output queue 0/40, 0 drops; input queue 0/75, 362 drops
+ 5 minute input rate 8000 bits/sec, 1 packets/sec
+ 5 minute output rate 11000 bits/sec, 0 packets/sec
+ 4615550 packets input, 1942263093 bytes, 33 no buffer
+ Received 1947224 broadcasts, 0 runts, 8 giants
+ 30351 input errors, 30351 CRC, 15187 frame, 0 overrun, 0 ignored, 0 abort
+ 0 watchdog, 27381 multicast
+ 0 input packets with dribble condition detected
+ 11521698 packets output, 1811832796 bytes, 0 underruns
+ 0 output errors, 0 collisions, 2 interface resets, 0 restarts
+ 0 babbles, 0 late collision, 0 deferred
+ 0 lost carrier, 0 no carrier
+ 0 output buffer failures, 0 output buffers swapped out
+
+Serial1/0 is up, line protocol is up
+ Hardware is M4T
+ Description: frame-relay using subinterfaces
+ MTU 1500 bytes, BW 64 Kbit, DLY 20000 usec, rely 255/255, load 11/255
+ Encapsulation FRAME-RELAY, loopback not set, keepalive set (10 sec)
+ LMI enq sent 10084, LMI stat recvd 9997, LMI upd recvd 0, DTE LMI up
+ LMI enq recvd 0, LMI stat sent 0, LMI upd sent 0
+ LMI DLCI 0 LMI type is ANSI Annex D frame relay DTE
+ FR SVC disabled, LAPF state down
+ Broadcast queue 0/200, broadcasts sent/dropped 53152/0, interface broadcasts 49826
+ Last input 00:00:01, output 00:00:00, output hang never
+ Last clearing of "show interface" counters never
+ Queueing strategy: fifo
+ Output queue 0/8, 0 drops; input queue 0/75, 0 drops
+ 5 minute input rate 3000 bits/sec, 4 packets/sec
+ 5 minute output rate 3000 bits/sec, 4 packets/sec
+ 429076 packets input, 132623595 bytes, 0 no buffer
+ Received 0 broadcasts, 0 runts, 1 giants, 0 throttles
+ 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 0 abort
+ 474808 packets output, 73186481 bytes, 0 underruns
+ 0 output errors, 0 collisions, 31 interface resets
+ 0 output buffer failures, 0 output buffers swapped out
+ 35 carrier transitions DCD=up DSR=up DTR=up RTS=up CTS=up
+
+Serial1/0 is up, line protocol is up
+ Hardware is M4T
+ Description: frame-relay using subinterfaces
+ MTU 1500 bytes, BW 64 Kbit, DLY 20000 usec, rely 255/255, load 31/255
+ Encapsulation FRAME-RELAY, loopback not set, keepalive set (10 sec)
+ LMI enq sent 39756, LMI stat recvd 39753, LMI upd recvd 0, DTE LMI up
+ LMI enq recvd 0, LMI stat sent 0, LMI upd sent 0
+ LMI DLCI 0 LMI type is ANSI Annex D frame relay DTE
+ FR SVC disabled, LAPF state down
+ Broadcast queue 0/200, broadcasts sent/dropped 91696/0, interface broadcasts 85069
+ Last input 00:00:00, output 00:00:00, output hang never
+ Last clearing of "show interface" counters never
+ Queueing strategy: fifo
+ Output queue 0/8, 0 drops; input queue 0/75, 0 drops
+ 30 second input rate 62000 bits/sec, 9 packets/sec
+ 30 second output rate 8000 bits/sec, 5 packets/sec
+ 2238005 packets input, 630502832 bytes, 0 no buffer
+ Received 0 broadcasts, 0 runts, 0 giants, 0 throttles
+ 111 input errors, 108 CRC, 0 frame, 0 overrun, 0 ignored, 3 abort
+ 2274950 packets output, 230325061 bytes, 0 underruns
+ 0 output errors, 0 collisions, 2 interface resets
+ 0 output buffer failures, 0 output buffers swapped out
+ 3 carrier transitions DCD=up DSR=up DTR=up RTS=up CTS=up
+
+>show int s2/2.1
+Serial2/2.1 is up, line protocol is up
+ Hardware is M4T
+ Description: Frame Relay to Sydney (134.14.63.129)
+ Internet address is 134.14.63.130/30
+ MTU 1500 bytes, BW 512 Kbit, DLY 20000 usec,
+ reliability 255/255, txload 2/255, rxload 17/255
+ Encapsulation FRAME-RELAY
+
+CIR is BW 512 Kbit == 512*1024/10 bytes/sec (?)
+
+This number is hand typed, but there is no alternative for the CIR.
+
+For FrameRelay, utilization > 50% of CIR for alarm.
+
+>show frame pvc int s2/3.7
+
+PVC Statistics for interface Serial2/3.7 (Frame Relay DTE)
+
+ Active Inactive Deleted Static
+ Local 2 0 0 0
+ Switched 0 0 0 0
+ Unused 0 0 0 0
+
+DLCI = 17, DLCI USAGE = LOCAL, PVC STATUS = ACTIVE, INTERFACE = Serial2/3.7
+
+ input pkts 1287959 output pkts 1446754 in bytes 811690634
+ out bytes 187572881 dropped pkts 0 in FECN pkts 2333
+ in BECN pkts 0 out FECN pkts 0 out BECN pkts 0
+ in DE pkts 0 out DE pkts 0
+ out bcast pkts 43801 out bcast bytes 13172828
+ pvc create time 8w3d, last time pvc status changed 1w2d
+
+>show int Vlan256
+Vlan256 is up, line protocol is up
+ Hardware is Cat6k RP Virtual Ethernet, address is 0030.b630.b318 (bia 0030.b630.b318)
+ Description: Uplink to CTC tipctc2 (Area 2)
+ Internet address is 192.132.156.72/26
+ MTU 1500 bytes, BW 10000 Kbit, DLY 1000 usec,
+ reliablility 255/255, txload 1/255, rxload 44/255
+ Encapsulation ARPA, loopback not set
+ ARP type: ARPA, ARP Timeout 04:00:00
+ Last input 00:00:00, output never, output hang never
+ Last clearing of "show interface" counters never
+ Queueing strategy: fifo
+ Output queue 0/40, 2 drops; input queue 0/75, 1027 drops
+ 5 minute input rate 1754000 bits/sec, 158 packets/sec
+ 5 minute output rate 9000 bits/sec, 6 packets/sec
+ 3087365859 packets input, 816292345 bytes, 224 no buffer
+ Received 3085491728 broadcasts, 0 runts, 0 giants, 0 throttles
+ 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
+ 110141390 packets output, 3736073981 bytes, 0 underruns
+ 0 output errors, 3 interface resets
+ 0 output buffer failures, 0 output buffers swapped out
+
+>show int e1/0
+Ethernet1/0 is up, line protocol is up
+ Hardware is AmdP2, address is 0050.7343.f011 (bia 0050.7343.f011)
+ Description: >>> Connecion to melbourne pix-e1 <<<
+ Internet address is 134.14.71.241/30
+ MTU 1500 bytes, BW 10000 Kbit, DLY 1000 usec,
+ reliability 255/255, txload 3/255, rxload 1/255
+ Encapsulation ARPA, loopback not set
+ Keepalive set (10 sec)
+ ARP type: ARPA, ARP Timeout 04:00:00
+ Last input 00:09:05, output 00:00:00, output hang never
+ Last clearing of "show interface" counters never
+ Queueing strategy: fifo
+ Output queue 0/40, 0 drops; input queue 0/75, 0 drops
+ 30 second input rate 26000 bits/sec, 4 packets/sec
+ 30 second output rate 118000 bits/sec, 97 packets/sec
+ 3657465 packets input, 2161281566 bytes, 0 no buffer
+ Received 79047 broadcasts, 0 runts, 0 giants, 0 throttles
+ 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
+ 0 input packets with dribble condition detected
+ 13202080 packets output, 4162655553 bytes, 0 underruns
+ 6 output errors, 249819 collisions, 11 interface resets
+ 0 babbles, 0 late collision, 207020 deferred
+ 6 lost carrier, 0 no carrier
+ 0 output buffer failures, 0 output buffers swapped out
+
diff --git a/src/pmdas/cisco/Tested b/src/pmdas/cisco/Tested
new file mode 100644
index 0000000..fc3d6aa
--- /dev/null
+++ b/src/pmdas/cisco/Tested
@@ -0,0 +1,76 @@
+
+Cisco Model : MGS
+Interface(s) e2
+
+Cisco Model: Cisco 7000
+Interface(s) e1/2 f2/0
+
+Cisco Model: Cisco 7000
+Interface(s) e0/0 e0/1 e0/2 e0/3 e0/4 e0/5
+ f2/0 f4/0
+
+Cisco Model : 4500
+Interface(s) e0 f1
+
+Cisco Model : 2500 (68030) processor (revision A) 3000 Software
+Interface(s) e0 s0
+
+Cisco Model : 4000M
+Interface(s) e0#starchild
+ e1 -P starchild
+ f0 -P starchild
+ s0 -P starchild
+ s1#starchild
+ s2#starchild
+
+Cisco Model : 4500
+Interface(s) e0 e1
+ f0 f1
+
+
+Cisco Model : 7513
+Interface(s) e0/0 e0/1 e0/2 e0/3 e0/4 e0/5
+ E1/0 E1/1
+ s2/0 s2/1 s2/2 s2/3
+ h3/0
+ f5/0 f8/0 f9/0 f10/0 f11/0
+ a12/0
+
+Cisco Model : 7000
+Interface(s) e0/0 e0/1 e0/2 e0/3 e0/4 e0/5
+ e1/0 e1/1 e1/2 e1/3 e1/4 e1/5
+ e2/0 e2/1 e2/2 e2/3 e2/4 e2/5
+ f3/0
+ a4/0
+
+Cisco Model : 2500
+Interfaces e0?cisco e1 s0 s1
+
+Cisco Model : 3640 IOS 3600 Version 11.3(6), RELEASE SOFTWARE (fc1)
+Interface(s) e0/0 s1/0 s1/1 s1/2 s1/3
+
+
+Cisco Model: Cat6k-MSFC
+Interfaces Vlan32 Vlan33 Vlan34 Vlan35 Vlan36 Vlan37
+ Vlan38 Vlan39 Vlan41 Vlan43 Vlan44 Vlan47
+ Vlan48 Vlan50 Vlan51
+ Vlan140 Vlan149 Vlan156 Vlan240 Vlan249
+ Vlan256
+
+Cisco Model: Catalyst 6509
+Interfaces Vl2 Vl3 Vl4 Vl5 Vl6 Vl7 Vl8 Vl14 Vl15
+ Vl16 Vl17 Vl18 Vl19 Vl20 Vl21 Vl22 Vl23
+ Vl101 Vl109 Vl110 Vl111 Vl112 Vl113
+ Vl156 Vl209 Vl210 Vl211 Vl212 Vl213
+ Vl256
+
+Cisco Model: C2960 IOS Version 12.2(25)SEE2, RELEASE SOFTWARE (fc1)
+Interfaces
+ Vl1 Vl50
+ E0/1 E0/2 E0/3 E0/4 E0/5 E0/6 E0/7 E0/8 E0/9 E0/10
+ E0/11 E0/12 E0/13 E0/14 E0/15 E0/16 E0/17 E0/18 E0/19 E0/20
+ E0/21 E0/22 E0/23 E0/24 E0/25 E0/26 E0/27 E0/28 E0/29 E0/30
+ E0/31 E0/32 E0/33 E0/34 E0/35 E0/36 E0/37 E0/38 E0/39 E0/40
+ E0/41 E0/42 E0/43 E0/44 E0/45 E0/46 E0/47 E0/48
+ G0/1 G0/2
+
diff --git a/src/pmdas/cisco/cisco.c b/src/pmdas/cisco/cisco.c
new file mode 100644
index 0000000..f303480
--- /dev/null
+++ b/src/pmdas/cisco/cisco.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 1995-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <ctype.h>
+#include <signal.h>
+#include "cisco.h"
+#if defined(HAVE_SYS_RESOURCE_H)
+#include <sys/resource.h>
+#endif
+#if defined(HAVE_SYS_WAIT_H)
+#include <sys/wait.h>
+#endif
+#if defined(HAVE_PTHREAD_H)
+#include <pthread.h>
+#endif
+#if defined(HAVE_PRCTL_H)
+#include <sys/prctl.h>
+#endif
+
+extern int refreshdelay;
+
+#ifdef HAVE_SPROC
+static pid_t sproc_pid = 0;
+#elif defined (HAVE_PTHREAD_H)
+#include <pthread.h>
+static pthread_t sproc_pid;
+#else
+#error "Need sproc or pthreads here!"
+#endif
+
+/*
+ * all metrics supported in this PMD - one table entry for each
+ */
+static pmdaMetric metrictab[] = {
+ /* 0,0 ... for direct map, sigh */
+ { NULL, { PMDA_PMID(0,0), 0, 0, 0, PMDA_PMUNITS(0,0,0,0,0,0) } },
+ /* bytes-in */
+ { NULL, { PMDA_PMID(0,1), PM_TYPE_U64, CISCO_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) } },
+ /* bytes-out */
+ { NULL, { PMDA_PMID(0,2), PM_TYPE_U64, CISCO_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) } },
+ /* rate-in */
+ { NULL, { PMDA_PMID(0,3), PM_TYPE_U32, CISCO_INDOM, PM_SEM_INSTANT,
+ PMDA_PMUNITS(1,-1,0,PM_SPACE_BYTE,PM_TIME_SEC,0) } },
+ /* rate-out */
+ { NULL, { PMDA_PMID(0,4), PM_TYPE_U32, CISCO_INDOM, PM_SEM_INSTANT,
+ PMDA_PMUNITS(1,-1,0,PM_SPACE_BYTE,PM_TIME_SEC,0) } },
+ /* bandwidth */
+ { NULL, { PMDA_PMID(0,5), PM_TYPE_U32, CISCO_INDOM, PM_SEM_DISCRETE,
+ PMDA_PMUNITS(1,-1,0,PM_SPACE_BYTE,PM_TIME_SEC,0) } },
+ /* bytes_out_bcast */
+ { NULL, { PMDA_PMID(0,6), PM_TYPE_U64, CISCO_INDOM, PM_SEM_COUNTER,
+ PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) } },
+
+ };
+
+/* filled in from command line args in main() ... */
+pmdaIndom indomtab[] = {
+ { 0, 0, 0 },
+};
+
+#ifdef HAVE_SPROC
+static RETSIGTYPE
+onhup(int s)
+{
+ signal(SIGHUP, onhup);
+ exit(0);
+}
+#endif
+
+/*
+ * the sproc starts here to refresh the metric values periodically
+ */
+void
+refresh(void *dummy)
+{
+ int i;
+
+#ifdef HAVE_SPROC
+#if HAVE_PRCTL
+ signal(SIGHUP, onhup);
+#if HAVE_PR_TERMCHILD
+ prctl(PR_TERMCHILD); /* SIGHUP when the parent dies */
+#elif HAVE_PR_SET_PDEATHSIG
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+#endif
+#endif
+#endif
+
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0) {
+ fprintf(stderr, "Starting sproc ...\n");
+ for (i = 0; i < n_cisco; i++) {
+ int j;
+
+ fprintf(stderr, "cisco[%d] host: %s username: %s passwd: %s prompt: %s intf:",
+ i, cisco[i].host, cisco[i].username, cisco[i].passwd, cisco[i].prompt);
+
+ for (j = 0; j < n_intf; j++) {
+ if (intf[j].cp == (cisco+i))
+ fprintf(stderr, " %d-%s", j, intf[j].interface);
+ }
+ fputc('\n', stderr);
+ }
+ }
+#endif
+
+ for ( ; ; ) {
+ for (i = 0; i < n_intf; i++) {
+ if (grab_cisco(intf+i) != -1) {
+ intf[i].fetched = 1;
+ }
+ else
+ intf[i].fetched = 0;
+ }
+
+ if (parse_only)
+ exit(0);
+
+ for (i = 0; i < n_cisco; i++) {
+ if (cisco[i].fout != NULL) {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0)
+ fprintf(stderr, "... %s voluntary disconnect fout=%d\n", cisco[i].host, fileno(cisco[i].fout));
+#endif
+ /* close CISCO telnet session */
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL1) {
+ fprintf(stderr, "Send: exit\n");
+ }
+#endif
+ fprintf(cisco[i].fout, "exit\n");
+ fclose(cisco[i].fout);
+ cisco[i].fout = NULL;
+ }
+ if (cisco[i].fin != NULL) {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0)
+ fprintf(stderr, "... %s close fin=%d\n", cisco[i].host, fileno(cisco[i].fin));
+#endif
+ fclose(cisco[i].fin);
+ cisco[i].fin = NULL;
+ }
+ }
+
+ sleep(refreshdelay);
+ }
+}
+
+static int
+cisco_fetchCallBack(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *avp)
+{
+ __pmID_int *idp = (__pmID_int *)&(mdesc->m_desc.pmid);
+
+#ifndef HAVE_SPROC
+ /* Check is refresh thread is still with us */
+ int err;
+
+ if ( (err = pthread_kill (sproc_pid, 0)) != 0 ) {
+ exit (1);
+ }
+#endif
+
+ if (!intf[inst].fetched)
+ return PM_ERR_AGAIN;
+
+ switch (idp->item) {
+
+ case 1: /* bytes_in */
+ if (intf[inst].bytes_in == -1) return 0;
+ avp->ull = intf[inst].bytes_in;
+ break;
+
+ case 2: /* bytes_out */
+ if (intf[inst].bytes_out == -1) return 0;
+ avp->ull = intf[inst].bytes_out;
+ break;
+
+ case 3: /* rate_in */
+ if (intf[inst].rate_in == -1) return 0;
+ avp->ul = intf[inst].rate_in;
+ break;
+
+ case 4: /* rate_out */
+ if (intf[inst].rate_out == -1) return 0;
+ avp->ul = intf[inst].rate_out;
+ break;
+
+ case 5: /* bandwidth */
+ if (intf[inst].bandwidth == -1) return 0;
+ avp->ul = intf[inst].bandwidth;
+ break;
+
+ case 6: /* bytes_out_bcast */
+ if (intf[inst].bytes_out_bcast == -1) return 0;
+ avp->ull = intf[inst].bytes_out_bcast;
+ break;
+
+ default:
+ return PM_ERR_PMID;
+ }
+
+ return 1;
+}
+
+void
+cisco_init(pmdaInterface *dp)
+{
+ int i;
+
+ pmdaSetFetchCallBack(dp, cisco_fetchCallBack);
+
+ pmdaInit(dp, indomtab, sizeof(indomtab)/sizeof(indomtab[0]), metrictab,
+ sizeof(metrictab)/sizeof(metrictab[0]));
+
+ for (i = 0; i < n_intf; i++)
+ intf[i].fetched = 0;
+
+ /* start the sproc for async fetches */
+#ifdef HAVE_SPROC
+ i = sproc_pid = sproc(refresh, PR_SADDR);
+#elif defined (HAVE_PTHREAD_H)
+ i = pthread_create(&sproc_pid, NULL, (void (*))refresh, NULL);
+#else
+#error "Need sproc or pthread here!"
+#endif
+
+ if (i < 0)
+ dp->status = i;
+ else
+ dp->status = 0;
+}
+
+void
+cisco_done(void)
+{
+ int i;
+
+ if (sproc_pid > 0) {
+#ifndef HAVE_SPROC
+ pthread_kill(sproc_pid, SIGHUP);
+#else
+ kill(sproc_pid, SIGHUP);
+#endif
+ while (wait(&i) >= 0)
+ ;
+ }
+}
+
diff --git a/src/pmdas/cisco/cisco.h b/src/pmdas/cisco/cisco.h
new file mode 100644
index 0000000..acf14bc
--- /dev/null
+++ b/src/pmdas/cisco/cisco.h
@@ -0,0 +1,86 @@
+/*
+ * Instance Domain Data Structures, suitable for a PMDA
+ *
+ * Copyright (c) 2012-2014 Red Hat.
+ * Copyright (c) 1995-2002 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _CISCO_H
+#define _CISCO_H
+
+#include "pmapi.h"
+#include "impl.h"
+#include "pmda.h"
+#include "domain.h"
+
+typedef struct {
+ char *host; /* CISCO hostname */
+ __pmHostEnt *hostinfo; /* Address info for 'host' */
+ int port; /* port */
+ char *username; /* username */
+ char *passwd; /* password */
+ char *prompt; /* command prompt */
+ FILE *fout; /* write cmds here */
+ FILE *fin; /* read output here */
+} cisco_t;
+
+typedef struct {
+
+ cisco_t *cp; /* which CISCO? */
+ char *interface; /* interface name, e.g. s0 or e10/10 */
+ int fetched; /* valid stats? */
+ __uint32_t bandwidth; /* peak bandwidth */
+ __uint32_t rate_in;
+ __uint32_t rate_out;
+ __uint64_t bytes_in; /* stats */
+ __uint64_t bytes_out;
+ __uint64_t bytes_out_bcast;
+} intf_t;
+
+extern cisco_t *cisco;
+extern int n_cisco;
+extern intf_t *intf;
+extern int n_intf;
+
+/*
+ * Supported Cisco Interfaces
+ */
+typedef struct {
+ char *type; /* NULL to skip, else unique per interface
+ * type */
+ char *name; /* full name as per "show" */
+} intf_tab_t;
+
+extern intf_tab_t intf_tab[];
+extern int num_intf_tab;
+
+#define CISCO_INDOM 0
+extern pmdaIndom indomtab[];
+extern pmdaInstid *_router;
+
+#define PWPROMPT "Password:"
+#define USERPROMPT "Username:"
+
+extern int conn_cisco(cisco_t *);
+extern int grab_cisco(intf_t *);
+extern int dousername(cisco_t *, char **);
+extern int dopasswd(cisco_t *, char *);
+extern char *mygetwd(FILE *, char *);
+
+extern int parse_only;
+
+#endif /* _CISCO_H */
diff --git a/src/pmdas/cisco/cisco.in_util.pmie b/src/pmdas/cisco/cisco.in_util.pmie
new file mode 100644
index 0000000..75ecd08
--- /dev/null
+++ b/src/pmdas/cisco/cisco.in_util.pmie
@@ -0,0 +1,64 @@
+#pmieconf-rules 1
+# --- DO NOT MODIFY THIS FILE --- see pmieconf(4)
+
+rule cisco.in_util
+ summary = "$rule$"
+ enumerate = hosts
+ predicate =
+"some_inst (
+ 100 * cisco.rate_in $hosts$ / cisco.bandwidth $hosts$
+ > $threshold$
+)"
+ enabled = no
+ version = 1
+ help =
+"Some Cisco router interface exceeded threshold percent of its
+peak bandwidth receiving data during the last sample interval.
+Use the command:
+ $ pminfo -f cisco.bandwidth
+to discover the list of Cisco router interfaces currently being
+monitored by the Cisco PMDA - pmdacisco(1).";
+
+string rule
+ default = "Cisco router inbound bandwidth saturation"
+ modify = no
+ display = no;
+
+percent threshold
+ default = 90
+ help =
+"Threshold percentage for Cisco router saturation, in the range 0
+(idle) to 100 (operating at peak bandwidth)";
+
+string action_expand
+ default = %v%util[%i]@%h
+ display = no
+ modify = no;
+
+string email_expand
+ default = "host: %h Cisco router: %i inbound utilization: %v%"
+ display = no
+ modify = no;
+
+
+# Configuration info specific to non-PCP tools follows...
+#
+
+# for SGI Embedded Support Partner integration:
+string esp_type
+ default = "0x200093"
+ display = no
+ modify = no;
+
+# for EnlightenDSM integration:
+string enln_test
+ default = cisco.in_util
+ display = no
+ modify = no;
+string enln_units
+ default = %util[%i]
+ display = no
+ modify = no;
+
+#
+# --- DO NOT MODIFY THIS FILE --- see pmieconf(4)
diff --git a/src/pmdas/cisco/cisco.out_util.pmie b/src/pmdas/cisco/cisco.out_util.pmie
new file mode 100644
index 0000000..e003f59
--- /dev/null
+++ b/src/pmdas/cisco/cisco.out_util.pmie
@@ -0,0 +1,64 @@
+#pmieconf-rules 1
+# --- DO NOT MODIFY THIS FILE --- see pmieconf(4)
+
+rule cisco.out_util
+ summary = "$rule$"
+ enumerate = hosts
+ predicate =
+"some_inst (
+ 100 * cisco.rate_out $hosts$ / cisco.bandwidth $hosts$
+ > $threshold$
+)"
+ enabled = no
+ version = 1
+ help =
+"Some Cisco router interface exceeded threshold percent of its
+peak bandwidth sending data during the last sample interval.
+Use the command:
+ $ pminfo -f cisco.bandwidth
+to discover the list of Cisco router interfaces currently being
+monitored by the Cisco PMDA - pmdacisco(1).";
+
+string rule
+ default = "Cisco router outbound bandwidth saturation"
+ modify = no
+ display = no;
+
+percent threshold
+ default = 90
+ help =
+"Threshold percentage for Cisco router saturation, in the range 0
+(idle) to 100 (operating at peak bandwidth)";
+
+string action_expand
+ default = %v%util[%i]@%h
+ display = no
+ modify = no;
+
+string email_expand
+ default = "host: %h Cisco router: %i outbound utilization: %v%"
+ display = no
+ modify = no;
+
+
+# Configuration info specific to non-PCP tools follows...
+#
+
+# for SGI Embedded Support Partner integration:
+string esp_type
+ default = "0x200094"
+ display = no
+ modify = no;
+
+# for EnlightenDSM integration:
+string enln_test
+ default = cisco.out_util
+ display = no
+ modify = no;
+string enln_units
+ default = %util[%i]
+ display = no
+ modify = no;
+
+#
+# --- DO NOT MODIFY THIS FILE --- see pmieconf(4)
diff --git a/src/pmdas/cisco/help b/src/pmdas/cisco/help
new file mode 100644
index 0000000..eeb8c5f
--- /dev/null
+++ b/src/pmdas/cisco/help
@@ -0,0 +1,76 @@
+#
+# Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# cisco PMDA help file in the ASCII format
+#
+# lines beginning with a # are ignored
+# lines beginning @ introduce a new entry of the form
+# @ metric-name oneline-text
+# help test goes
+# here over multiple lines
+# ...
+#
+# the metric-name is decoded against the default PMNS -- as a special case,
+# a name of the form NNN.MM (for numeric NNN and MM) is interpreted as an
+# instance domain identification, and the text describes the instance domain
+#
+# blank lines before the @ line are ignored
+#
+
+@ CISCO.1 Interfaces on Cisco router
+There is one instance in this domain for each interface on a Cisco router
+that the Cisco PMDA (Performance Metrics Domain Agent) has been told about
+when the PMDA is started.
+
+The names of the instances are of the form hostname:tX where "t" is one of
+"a" for ATM, "B" for ISDN BRI, "e" for Ethernet, "E" (FastEthernet), "f" for
+Fddi, "h" for HSSC, "s" for Serial or "Vl" for Vlan. The "X" is the
+interface identifier which is either an integer (e.g. 4000 Series routers) or
+two integers separated by a slash (e.g. 7000 Series routers) or three
+integers separated by a slash and a period (Frame-Relay PVCs on serial line
+subinterfaces).
+
+@ cisco.bytes_in Total Kbytes input to the Cisco
+Total number of Kbytes input to the Cisco on this interface.
+
+Note that due to network delays in extracting the metrics from the
+Cisco routers, any rate computed from this metric over small deltas in time
+are likely to be subject to wide variance.
+
+@ cisco.bytes_out Total Kbytes output from the Cisco
+Total number of Kbytes output from the Cisco on this interface.
+
+Note that due to network delays in extracting the metrics from the
+Cisco routers, any rate computed from this metric over small deltas in time
+are likely to be subject to wide variance.
+
+@ cisco.bytes_out_bcast Total broadcast Kbytes output from the Cisco
+Total number of broadcast Kbytes output from the Cisco on this interface.
+
+Note that due to network delays in extracting the metrics from the
+Cisco routers, any rate computed from this metric over small deltas in
+time are likely to be subject to wide variance.
+
+@ cisco.rate_in 5 minutes average input rate in bytes (not bits!) per second
+Cisco's computed average input rate in bytes per second, over the recent
+past, for this interface.
+
+@ cisco.rate_out 5 minutes average output rate in bytes (not bits!) per second
+Cisco's computed average output rate in bytes per second, over the recent
+past, for this interface.
+
+@ cisco.bandwidth peak interface bandwidth in bytes per second
diff --git a/src/pmdas/cisco/interface.c b/src/pmdas/cisco/interface.c
new file mode 100644
index 0000000..022c8ac
--- /dev/null
+++ b/src/pmdas/cisco/interface.c
@@ -0,0 +1,46 @@
+/*
+ * Known Cisco Interfaces
+ *
+ * Copyright (c) 1995-2002 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "./cisco.h"
+
+/*
+ * first letter defines command line argument for interface type
+ * (0 means not allowed in command line)
+ * full name of interface is as found in "show interface" command
+ * output.
+ */
+
+intf_tab_t intf_tab[] = {
+ { "s", "Serial" },
+ { "e", "Ethernet" },
+ { "E", "FastEthernet" },
+ { "f", "Fddi" },
+ { "h", "Hssi" },
+ { "a", "ATM" },
+ { "B", "BRI" },
+ { "Vl", "Vlan" },
+ { "G", "GigabitEthernet" },
+ { NULL, "Controller" },
+ { NULL, "Port-channel" },
+ { NULL, "Dialer" },
+ { NULL, "Loopback" },
+};
+
+int num_intf_tab = sizeof(intf_tab) / sizeof(intf_tab[0]);
diff --git a/src/pmdas/cisco/parse.sh b/src/pmdas/cisco/parse.sh
new file mode 100755
index 0000000..c35a27c
--- /dev/null
+++ b/src/pmdas/cisco/parse.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+. $PCP_DIR/etc/pcp.env
+exec $PCP_PMDAS_DIR/cisco/pmdacisco -n parse -C $@
diff --git a/src/pmdas/cisco/pmda.c b/src/pmdas/cisco/pmda.c
new file mode 100644
index 0000000..d78190c
--- /dev/null
+++ b/src/pmdas/cisco/pmda.c
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2012,2014 Red Hat.
+ * Copyright (c) 1995-2002 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/*
+ * Cisco PMDA, based on generic driver for a daemon-based PMDA
+ * - cisco interfaces to monitor are named in the command line as
+ * hostname:tX[@username]
+ * hostname:tX[?passwd]
+ * hostname:tX[@username?passwd]
+ * hostname:tX[!prompt]
+ * hostname:tX[@username!prompt]
+ * hostname:tX[?passwd!prompt]
+ * hostname:tX[@username?passwd!prompt]
+ *
+ * where t identifies an interface type as defined by intf_tab[] in
+ * interface.c
+ * and X is either the ordinal i/f number (base 0, for Series 4000)
+ * or the card/port number (Series 7000 routers)
+ * e.g sydcisco.sydney:s0 (Frame-Relay to Mtn View)
+ * sydcisco.sydney:s1 (ISDN to Melbourne)
+ * cisco.melbourne:s0 (ISDN to Sydney)
+ * b8u-cisco1-e15.corp:e0 (Ethernet in Bldg 8 upper)
+ * b9u-cisco1-81.engr.sgi.com:f2/0
+ * wanbris.brisbane:B0 (BRI ISDN)
+ * If specified the username (after the @ delimiter) and/or the
+ * user-level password (after the ? delimiter) and/or the prompt (after
+ * the ! delimiter) over-rides the global username and/or user-level
+ * password and/or prompt, as specified via -U and/or -P and/or -s
+ * options and applies for all occurrences of the hostname.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/un.h>
+#include <netdb.h>
+#include <string.h>
+#include "./cisco.h"
+
+pmdaInstid *_router;
+cisco_t *cisco;
+int n_cisco;
+intf_t *intf;
+int n_intf;
+int refreshdelay = 120; /* default poll every two minutes */
+char *pmdausername; /* username for the pmda */
+char *username; /* username */
+char *passwd; /* user-level password */
+char *prompt = ">"; /* command prompt */
+int port = 23;
+int parse_only;
+int no_lookups;
+
+extern void cisco_init(pmdaInterface *);
+extern void cisco_done(void);
+
+int
+main(int argc, char **argv)
+{
+ int err = 0;
+ int sep = __pmPathSeparator();
+ char *endnum;
+ pmdaInterface dispatch;
+ int n;
+ int i;
+ int c;
+ char helptext[MAXPATHLEN];
+
+ __pmSetProgname(argv[0]);
+ __pmGetUsername(&pmdausername);
+
+ snprintf(helptext, sizeof(helptext), "%s%c" "cisco" "%c" "help",
+ pmGetConfig("PCP_PMDAS_DIR"), sep, sep);
+ pmdaDaemon(&dispatch, PMDA_INTERFACE_3, pmProgname, CISCO,
+ "cisco.log", helptext);
+
+ while ((c = pmdaGetOpt(argc, argv, "D:d:h:i:l:pu:6:" "CM:Nn:P:r:s:U:x:?",
+ &dispatch, &err)) != EOF) {
+ switch (c) {
+
+ case 'C': /* parser checking mode (debugging) */
+ pmDebug = DBG_TRACE_APPL0;
+ parse_only++;
+ break;
+
+ case 'N': /* do not perform name lookups (debugging) */
+ no_lookups = 1;
+ break;
+
+ case 'n': /* set program name, for parse (debugging) */
+ pmProgname = optarg;
+ break;
+
+ case 'P': /* passwd */
+ passwd = optarg;
+ break;
+
+ case 'r':
+ refreshdelay = (int)strtol(optarg, &endnum, 10);
+ if (*endnum != '\0') {
+ fprintf(stderr, "%s: -r requires numeric (number of seconds) argument\n",
+ pmProgname);
+ err++;
+ }
+ break;
+
+ case 's': /* command prompt */
+ prompt = optarg;
+ break;
+
+ case 'M': /* username (for the PMDA) */
+ pmdausername = optarg;
+ break;
+
+ case 'U': /* username (for the Cisco) */
+ username = optarg;
+ break;
+
+ case 'x':
+ port = (int)strtol(optarg, &endnum, 10);
+ if (*endnum != '\0') {
+ fprintf(stderr, "%s: -x requires numeric argument\n",
+ pmProgname);
+ err++;
+ }
+ break;
+
+ case '?':
+ err++;
+ }
+ }
+
+ n_intf = argc - optind;
+ if (n_intf == 0 || err) {
+ fprintf(stderr,
+ "Usage: %s [options] host:{a|B|E|e|f|h|s}N[/M[.I]] [...]\n\n",
+ pmProgname);
+ fputs("Options:\n"
+ " -d domain use domain (numeric) for metrics domain of PMDA\n"
+ " -i port expect PMCD to connect on given inet port (number or name)\n"
+ " -l logfile redirect diagnostics and trace output to logfile\n"
+ " -M username user account to run PMDA under (default \"pcp\")\n"
+ " -p expect PMCD to supply stdin/stdout (pipe)\n"
+ " -P password default user-level Cisco password\n"
+ " -r refresh update metrics every refresh seconds\n"
+ " -s prompt Cisco command prompt [default >]\n"
+ " -u socket expect PMCD to connect on given unix domain socket\n"
+ " -U username Cisco username\n"
+ " -x port telnet port [default 23]\n"
+ " -6 port expect PMCD to connect on given ipv6 port (number or name)\n",
+ stderr);
+ exit(1);
+ }
+
+ /* force errors from here on into the log */
+ if (!parse_only) {
+ pmdaOpenLog(&dispatch);
+ __pmSetProcessIdentity(pmdausername);
+ } else {
+ dispatch.version.two.text = NULL;
+ dispatch.version.two.ext->e_helptext = NULL;
+ }
+
+ /*
+ * build the instance domain and cisco data structures from the
+ * command line arguments.
+ */
+ if ((_router = (pmdaInstid *)malloc(n_intf * sizeof(pmdaInstid))) == NULL) {
+ __pmNoMem("main.router", n_intf * sizeof(pmdaInstid), PM_FATAL_ERR);
+ }
+ if ((intf = (intf_t *)malloc(n_intf * sizeof(intf_t))) == NULL) {
+ __pmNoMem("main.intf", n_intf * sizeof(intf_t), PM_FATAL_ERR);
+ }
+ /* pre-allocated cisco[] to avoid realloc and ptr movement */
+ if ((cisco = (cisco_t *)malloc(n_intf * sizeof(cisco_t))) == NULL) {
+ __pmNoMem("main.cisco", n_intf * sizeof(cisco_t), PM_FATAL_ERR);
+ }
+
+ indomtab[CISCO_INDOM].it_numinst = n_intf;
+ indomtab[CISCO_INDOM].it_set = _router;
+
+ for (n = 0 ; optind < argc; optind++, n++) {
+ char *p = strdup(argv[optind]);
+ char *q;
+ char *myusername;
+ char *mypasswd;
+ char *myprompt;
+
+ myprompt = strchr(p, '!');
+ if (myprompt) {
+ /* save prompt for later */
+ *myprompt++ = '\0';
+ }
+ else
+ myprompt = NULL;
+ mypasswd = strchr(p, '?');
+ if (mypasswd) {
+ /* save user-level password for later */
+ *mypasswd++ = '\0';
+ }
+ else
+ mypasswd = passwd;
+ myusername = strchr(p, '@');
+ if (myusername) {
+ /* save username for later */
+ *myusername++ = '\0';
+ }
+ else
+ myusername = username;
+
+ _router[n].i_inst = n;
+ _router[n].i_name = strdup(p);
+
+ if ((q = strchr(p, ':')) == NULL)
+ goto badintfspec;
+ *q++ = '\0';
+ for (i = 0; i < num_intf_tab; i++) {
+ if (strncmp(q, intf_tab[i].type, strlen(intf_tab[i].type)) == 0)
+ break;
+ }
+ if (i == num_intf_tab)
+ goto badintfspec;
+ if (strcmp(intf_tab[i].type, "E") == 0) {
+ /*
+ * Cisco parser is case insensitive, so 'E' means "Ethernet"
+ * and 'F' means "Fddi", need to use "FastEthernet" here
+ */
+ q++;
+ intf[n].interface = (char *)malloc(strlen("FastEthernet")+strlen(q)+1);
+ if ((intf[n].interface = (char *)malloc(strlen("FastEthernet")+strlen(q)+1)) == NULL) {
+ __pmNoMem("main.cisco", strlen("FastEthernet")+strlen(q)+1, PM_FATAL_ERR);
+ }
+ strcpy(intf[n].interface, "FastEthernet");
+ strcat(intf[n].interface, q);
+ }
+ else
+ intf[n].interface = q;
+
+ for (i = 0; i < n_cisco; i++) {
+ if (strcmp(p, cisco[i].host) == 0)
+ break;
+ }
+ if (i == n_cisco) {
+ __pmHostEnt *hostInfo = NULL;
+
+ if (!no_lookups)
+ hostInfo = __pmGetAddrInfo(p);
+
+ if (!hostInfo && parse_only) {
+ FILE *f;
+
+ /*
+ * for debugging, "host" may be a file ...
+ */
+ if ((f = fopen(p, "r")) == NULL) {
+ fprintf(stderr, "%s: unknown hostname or filename %s: %s\n",
+ pmProgname, argv[optind], hoststrerror());
+ /* abandon this host (cisco) */
+ continue;
+ }
+ else {
+ fprintf(stderr, "%s: assuming file %s contains output from \"show int\" command\n",
+ pmProgname, p);
+
+ cisco[i].host = p;
+ cisco[i].username = myusername != NULL ? myusername : username;
+ cisco[i].passwd = mypasswd != NULL ? mypasswd : passwd;
+ cisco[i].prompt = myprompt != NULL ? myprompt : prompt;
+ cisco[i].fin = f;
+ cisco[i].fout = stdout;
+ n_cisco++;
+ }
+ } else if (!hostInfo) {
+ fprintf(stderr, "%s: unknown hostname %s: %s\n",
+ pmProgname, p, hoststrerror());
+ /* abandon this host (cisco) */
+ continue;
+ } else {
+ cisco[i].host = p;
+ cisco[i].username = myusername != NULL ? myusername : username;
+ cisco[i].passwd = mypasswd != NULL ? mypasswd : passwd;
+ cisco[i].prompt = myprompt != NULL ? myprompt : prompt;
+ cisco[i].fin = NULL;
+ cisco[i].fout = NULL;
+ cisco[i].hostinfo = hostInfo;
+ cisco[i].port = port;
+
+ n_cisco++;
+ fprintf(stderr, "Adding new host %s\n", p);
+ fflush(stderr);
+ }
+ }
+ else {
+ if (cisco[i].username == NULL) {
+ if (myusername != NULL)
+ /* username on 2nd or later interface ... applies to all */
+ cisco[i].username = myusername;
+ }
+ else {
+ if (myusername != NULL) {
+ if (strcmp(cisco[i].username, myusername) != 0) {
+ fprintf(stderr,
+ "%s: conflicting usernames (\"%s\" "
+ "and \"%s\") for cisco \"%s\"\n",
+ pmProgname, cisco[i].username, myusername,
+ cisco[i].host);
+ exit(1);
+ }
+ }
+ }
+ if (cisco[i].passwd == NULL) {
+ if (mypasswd != NULL)
+ /* passwd on 2nd or later interface ... applies to all */
+ cisco[i].passwd = mypasswd;
+ }
+ else {
+ if (mypasswd != NULL) {
+ if (strcmp(cisco[i].passwd, mypasswd) != 0) {
+ fprintf(stderr,
+ "%s: conflicting user-level passwords (\"%s\" "
+ "and \"%s\") for cisco \"%s\"\n",
+ pmProgname, cisco[i].passwd, mypasswd,
+ cisco[i].host);
+ exit(1);
+ }
+ }
+ }
+ if (cisco[i].prompt == NULL) {
+ if (myprompt != NULL)
+ /* prompt on 2nd or later interface ... applies to all */
+ cisco[i].prompt = myprompt;
+ }
+ else {
+ if (myprompt != NULL) {
+ if (strcmp(cisco[i].prompt, myprompt) != 0) {
+ fprintf(stderr,
+ "%s: conflicting user-level prompts (\"%s\" "
+ "and \"%s\") for cisco \"%s\"\n",
+ pmProgname, cisco[i].prompt, myprompt,
+ cisco[i].host);
+ exit(1);
+ }
+ }
+ }
+ }
+
+ intf[n].cp = cisco+i;
+ /*
+ * special one-trip initialization for Frame-Relay over serial
+ * lines ... see grab_cisco()
+ */
+ intf[n].bandwidth = -2;
+
+ fprintf(stderr, "Interface %s(%d) is on host %s\n",
+ intf[n].interface, n, cisco[i].host);
+ fflush(stderr);
+
+ continue;
+
+badintfspec:
+ fprintf(stderr, "%s: bad interface specification \"%s\"\n", pmProgname, argv[optind]);
+ fprintf(stderr, " should be like sydcisco.sydney:s1 or b9u-cisco1-81.engr.sgi.com:f2/0\n");
+ fprintf(stderr, " or cisco.melbourne:e0?secret\n");
+ exit(1);
+ }
+
+ if (n_cisco == 0) {
+ fprintf(stderr, "%s: Nothing to monitor\n", pmProgname);
+ exit(1);
+ }
+
+ if (parse_only) {
+ fprintf(stderr, "Sleeping while sproc does the work ... SIGINT to terminate\n");
+ cisco_init(&dispatch);
+ for (i = 0; i < n_intf; i++)
+ intf[i].fetched = 0;
+ pause();
+ } else {
+ /* set up connection to PMCD */
+ cisco_init(&dispatch);
+ pmdaConnect(&dispatch);
+ pmdaMain(&dispatch);
+ }
+
+ cisco_done();
+ exit(0);
+}
diff --git a/src/pmdas/cisco/pmns b/src/pmdas/cisco/pmns
new file mode 100644
index 0000000..fc1ce50
--- /dev/null
+++ b/src/pmdas/cisco/pmns
@@ -0,0 +1,28 @@
+/*
+ * Metrics for cisco PMDA
+ *
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+cisco {
+ bandwidth CISCO:0:5
+ bytes_in CISCO:0:1
+ bytes_out CISCO:0:2
+ bytes_out_bcast CISCO:0:6
+ rate_in CISCO:0:3
+ rate_out CISCO:0:4
+}
diff --git a/src/pmdas/cisco/probe.c b/src/pmdas/cisco/probe.c
new file mode 100644
index 0000000..5cd5b4d
--- /dev/null
+++ b/src/pmdas/cisco/probe.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2012 Red Hat.
+ * Copyright (c) 1995-2003 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include "./cisco.h"
+
+int port = 23;
+int seen_fr = 0;
+char *prompt = ">"; /* unique suffix to IOS prompt */
+
+char *
+mygetfirstwd(FILE *f)
+{
+ char *p;
+ int c;
+ char line[1024];
+ char *lp;
+
+ for ( ; ; ) {
+ c = fgetc(f);
+ if (c == EOF)
+ break;
+ if (c == '\r' || c == '\n')
+ continue;
+ if (c != ' ') {
+ ungetc(c, f);
+ break;
+ }
+ lp = line;
+ while ((c = fgetc(f)) != EOF) {
+ *lp++ = c;
+ if (c == '\r' || c == '\n') {
+ *lp = '\0';
+ break;
+ }
+ }
+ /*
+ * some interesting things to look for here ...
+ */
+ if (strncmp(&line[1], "Encapsulation FRAME-RELAY", strlen("Encapsulation FRAME-RELAY")) == 0) {
+ seen_fr = 1;
+ }
+ }
+ /* either EOF, or line starts with a non-space */
+
+ p = mygetwd(f, prompt);
+
+ if (p != NULL && (strlen(p) < strlen(prompt) ||
+ strcmp(&p[strlen(p)-strlen(prompt)], prompt)) != 0) {
+ /* skip to end of line, ready for next one */
+ while ((c = fgetc(f)) != EOF) {
+ if (c == '\r' || c == '\n')
+ break;
+ }
+ }
+
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2)
+ fprintf(stderr, "mygetfirstwd: %s\n", p == NULL ? "<NULL>" : p);
+#endif
+
+ return p;
+}
+
+#define PREAMBLE 1
+#define IN_BODY 2
+
+static void
+probe_cisco(cisco_t * cp)
+{
+ char *w;
+ int fd;
+ int fd2;
+ int first = 1;
+ char *pass = NULL;
+ int defer = 0;
+ int state = PREAMBLE;
+ int i;
+ int namelen;
+ char *ctype = NULL;
+ char *name = NULL;
+
+ if (cp->fin == NULL) {
+ fd = conn_cisco(cp);
+ if (fd == -1) {
+ fprintf(stderr, "grab_cisco(%s): connect failed: %s\n",
+ cp->host, osstrerror());
+ return;
+ }
+ else {
+ cp->fin = fdopen (fd, "r");
+ if ((fd2 = dup(fd)) < 0) {
+ perror("dup");
+ exit(1);
+ }
+ cp->fout = fdopen (fd2, "w");
+ if (cp->username != NULL) {
+ /*
+ * Username stuff ...
+ */
+ if (dousername(cp, &pass) == 0) {
+ exit(1);
+ }
+ }
+ if (cp->passwd != NULL) {
+ /*
+ * User-level password stuff ...
+ */
+ if (dopasswd(cp, pass) == 0) {
+ exit(1);
+ }
+ }
+ }
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL1) {
+ fprintf(stderr, "Send: \n");
+ fprintf(stderr, "Send: terminal length 0\n");
+ }
+#endif
+ fprintf(cp->fout, "\n");
+ fflush(cp->fout);
+ fprintf(cp->fout, "terminal length 0\n");
+ fflush(cp->fout);
+
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL1) {
+ fprintf(stderr, "Send: show int\n");
+ }
+#endif
+ fprintf(cp->fout, "show int\n");
+ fflush(cp->fout);
+
+ }
+ else {
+ /*
+ * parsing text from a file, not a TCP/IP connection to a
+ * Cisco device
+ */
+ ;
+ }
+
+ for ( ; ; ) {
+ w = mygetfirstwd(cp->fin);
+ if (defer && ctype != NULL && name != NULL) {
+ if (seen_fr) {
+ if (first)
+ first = 0;
+ else
+ putchar(' ');
+ printf("%s%s", ctype, name);
+ free(name);
+ name = NULL;
+ }
+ }
+ defer = 0;
+ if (w == NULL) {
+ /*
+ * End of File (telenet timeout?)
+ */
+ fprintf(stderr, "grab_cisco(%s): forced disconnect fin=%d\n",
+ cp->host, fileno(cp->fin));
+ return;
+ }
+ if (*w == '\0')
+ continue;
+ if (state == PREAMBLE) {
+ if (strcmp(w, "show") == 0)
+ state = IN_BODY;
+ else if (strcmp(w, PWPROMPT) == 0) {
+ fprintf(stderr,
+ "Error: user-level password required for \"%s\"\n",
+ cp->host);
+ exit(1);
+ }
+ continue;
+ }
+ else {
+ if (strlen(w) >= strlen(prompt) &&
+ strcmp(&w[strlen(w)-strlen(prompt)], prompt) == 0)
+ break;
+ ctype = NULL;
+ for (i = 0; i < num_intf_tab; i++) {
+ namelen = strlen(intf_tab[i].name);
+ if (strncmp(w, intf_tab[i].name, namelen) == 0) {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2) {
+ fprintf(stderr, "Match: if=%s word=%s\n", intf_tab[i].name, w);
+ }
+#endif
+ name = strdup(&w[namelen]);
+ ctype = intf_tab[i].type;
+ if (intf_tab[i].type != NULL && strcmp(intf_tab[i].type, "a") == 0) {
+ /*
+ * skip ATMN.M ... need ATMN
+ */
+ if (strchr(&w[namelen], '.') != NULL)
+ ctype = NULL;
+ }
+ else if (intf_tab[i].type != NULL && strcmp(intf_tab[i].type, "s") == 0) {
+ /*
+ * skip SerialN.M ... need SerialN, unless frame-relay
+ */
+ if (strchr(&w[namelen], '.') != NULL)
+ defer = 1;
+ }
+ break;
+ }
+ }
+ if (i == num_intf_tab)
+ fprintf(stderr, "%s: Warning, unknown interface: %s\n", pmProgname, w);
+ if (ctype != NULL && name != NULL && !defer) {
+ if (first)
+ first = 0;
+ else
+ putchar(' ');
+ printf("%s%s", ctype, name);
+ free(name);
+ name = NULL;
+ }
+ }
+ }
+ putchar('\n');
+
+ /* close CISCO telnet session */
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL1) {
+ fprintf(stderr, "Send: exit\n");
+ }
+#endif
+ fprintf(cp->fout, "exit\n");
+ fflush(cp->fout);
+
+ return;
+}
+
+int
+main(int argc, char **argv)
+{
+ int errflag = 0;
+ int Nflag = 0;
+ int c;
+ int sts;
+ char *endnum;
+ char *passwd = NULL;
+ char *username = NULL;
+ __pmHostEnt *hostInfo = NULL;
+
+ __pmSetProgname(argv[0]);
+
+ while ((c = getopt(argc, argv, "ND:P:s:U:x:?")) != EOF) {
+ switch (c) {
+
+ case 'N': /* check flag */
+ Nflag = 1;
+ break;
+
+ case 'D': /* debug flag */
+ sts = __pmParseDebug(optarg);
+ if (sts < 0) {
+ fprintf(stderr, "%s: unrecognized debug flag specification (%s)\n",
+ pmProgname, optarg);
+ errflag++;
+ }
+ else
+ pmDebug |= sts;
+ break;
+
+ case 'P': /* passwd */
+ passwd = optarg;
+ break;
+
+ case 's': /* prompt */
+ prompt = optarg;
+ break;
+
+ case 'U': /* username */
+ username = optarg;
+ break;
+
+ case 'x':
+ port = (int)strtol(optarg, &endnum, 10);
+ if (*endnum != '\0') {
+ fprintf(stderr, "%s: -x requires numeric argument\n",
+ pmProgname);
+ errflag++;
+ }
+ break;
+
+ case '?':
+ errflag++;
+ }
+ }
+
+ if (errflag || optind != argc-1) {
+ fprintf(stderr, "Usage: %s [-U username] [-P passwd] [-s prompt] [-x port] host\n\n", pmProgname);
+ exit(1);
+ }
+
+ if (!Nflag)
+ hostInfo = __pmGetAddrInfo(argv[optind]);
+
+ if (hostInfo == NULL) {
+ FILE *f;
+
+ if ((f = fopen(argv[optind], "r")) == NULL) {
+ fprintf(stderr, "%s: unknown hostname or filename %s: %s\n",
+ pmProgname, argv[optind], hoststrerror());
+ exit(1);
+ }
+ else {
+ cisco_t c;
+
+ fprintf(stderr, "%s: assuming file %s contains output from \"show int\" command\n",
+ pmProgname, argv[optind]);
+
+ c.host = argv[optind];
+ c.username = NULL;
+ c.passwd = NULL;
+ c.fin = f;
+ c.fout = fopen("/dev/null", "w");
+ c.prompt = prompt;
+
+ probe_cisco(&c);
+ }
+ } else {
+ cisco_t c;
+
+ c.host = argv[optind];
+ c.username = username;
+ c.passwd = passwd;
+ c.fin = NULL;
+ c.fout = NULL;
+ c.prompt = prompt;
+ c.hostinfo = hostInfo;
+ c.port = 23; /* telnet */
+
+ probe_cisco(&c);
+ }
+
+ exit(0);
+}
diff --git a/src/pmdas/cisco/root b/src/pmdas/cisco/root
new file mode 100644
index 0000000..e0c1b81
--- /dev/null
+++ b/src/pmdas/cisco/root
@@ -0,0 +1,10 @@
+/*
+ * fake "root" for validating the local PMNS subtree
+ */
+
+#include <stdpmid>
+
+root { cisco }
+
+#include "pmns"
+
diff --git a/src/pmdas/cisco/telnet.c b/src/pmdas/cisco/telnet.c
new file mode 100644
index 0000000..bcee1db
--- /dev/null
+++ b/src/pmdas/cisco/telnet.c
@@ -0,0 +1,755 @@
+/*
+ * Copyright (c) 2012 Red Hat.
+ * Copyright (c) 1995-2004 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <syslog.h>
+#include "./cisco.h"
+
+extern int port;
+
+int
+conn_cisco(cisco_t * cp)
+{
+ __pmFdSet wfds;
+ __pmSockAddr *myaddr;
+ void *enumIx;
+ int flags = 0;
+ int fd;
+ int ret;
+
+ fd = -1;
+ enumIx = NULL;
+ for (myaddr = __pmHostEntGetSockAddr(cp->hostinfo, &enumIx);
+ myaddr != NULL;
+ myaddr = __pmHostEntGetSockAddr(cp->hostinfo, &enumIx)) {
+ /* Create a socket */
+ if (__pmSockAddrIsInet(myaddr))
+ fd = __pmCreateSocket();
+ else if (__pmSockAddrIsIPv6(myaddr))
+ fd = __pmCreateIPv6Socket();
+ else
+ continue;
+ if (fd < 0) {
+ __pmSockAddrFree(myaddr);
+ continue; /* Try the next address */
+ }
+
+ /* Attempt to connect */
+ flags = __pmConnectTo(fd, myaddr, cp->port);
+ __pmSockAddrFree(myaddr);
+
+ if (flags < 0) {
+ /*
+ * Mark failure in case we fall out the end of the loop
+ * and try next address. fd has been closed in __pmConnectTo().
+ */
+ setoserror(ECONNREFUSED);
+ fd = -1;
+ continue;
+ }
+
+ /* FNDELAY and we're in progress - wait on select */
+ __pmFD_ZERO(&wfds);
+ __pmFD_SET(fd, &wfds);
+ ret = __pmSelectWrite(fd+1, &wfds, NULL);
+
+ /* Was the connection successful? */
+ if (ret == 0)
+ setoserror(ETIMEDOUT);
+ else if (ret > 0) {
+ ret = __pmConnectCheckError(fd);
+ if (ret == 0)
+ break;
+ setoserror(ret);
+ }
+
+ /* Unsuccessful connection. */
+ __pmCloseSocket(fd);
+ fd = -1;
+ } /* loop over addresses */
+
+ if (fd == -1) {
+ fprintf(stderr, "conn_cisco(%s): connect: %s\n",
+ cp->host, netstrerror());
+ return -1;
+ }
+
+ fd = __pmConnectRestoreFlags(fd, flags);
+ if (fd < 0) {
+ fprintf(stderr, "conn_cisco(%s): setsockopt: %s\n",
+ cp->host, netstrerror());
+ return -1;
+ }
+
+ return fd;
+}
+
+static void
+skip2eol(FILE *f)
+{
+ int c;
+
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2)
+ fprintf(stderr, "skip2eol:");
+#endif
+
+ while ((c = fgetc(f)) != EOF) {
+ if (c == '\n')
+ break;
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2)
+ fprintf(stderr, "%c", c);
+#endif
+ }
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2)
+ fputc('\n', stderr);
+#endif
+}
+
+char *
+mygetwd(FILE *f, char *prompt)
+{
+ char *p;
+ int c;
+ static char buf[1024];
+ int len_prompt = strlen(prompt);
+ int found_prompt = 0;
+
+ p = buf;
+
+ while ((c = fgetc(f)) != EOF) {
+ if (c == '\r' || c == '\n' || c == ' ' || c == '\t') {
+ if (p == buf)
+ continue;
+ break;
+ }
+ *p++ = c;
+ if (p-buf >= len_prompt && strncmp(&p[-len_prompt], prompt, len_prompt) == 0) {
+ found_prompt = 1;
+ break;
+ }
+ }
+ *p = '\0';
+
+ if (feof(f)) {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2)
+ fprintf(stderr, "mygetwd: EOF fd=%d\n", fileno(f));
+#endif
+ return NULL;
+ }
+
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2)
+ fprintf(stderr, "mygetwd: fd=%d wd=\"%s\"%s\n", fileno(f), buf, found_prompt ? " [prompt]" : "");
+#endif
+
+ return buf;
+}
+
+/*
+ * The CISCO "show interface" command output is parsed.
+ *
+ * See the file Samples for examples.
+ *
+ * The parser is a Finite State Automaton (FSA) that follows these
+ * rules:
+ *
+ * SHOW_INT style ... uses "show int <interface>" command
+ * state token next state
+ * NOISE <interface name> IN_REPORT
+ * IN_REPORT Description: skip rest of line, IN_REPORT
+ * IN_REPORT <prompt> DONE
+ * IN_REPORT minute RATE
+ * IN_REPORT second RATE
+ * IN_REPORT input, BYTES_IN
+ * IN_REPORT output, BYTES_OUT
+ * IN_REPORT BW BW
+ * RATE input skip next token, RATE_IN
+ * RATE output skip next token, RATE_OUT
+ * RATE_IN <number> (rate_in) IN_REPORT
+ * RATE_OUT <number> (rate_out) IN_REPORT
+ * BYTES_IN <number> (bytes_in) IN_REPORT
+ * BYTES_OUT <number> (bytes_out) IN_REPORT
+ * BW <number> (bandwidth) IN_REPORT
+ *
+ * SHOW_FRAME style ... uses "show frame pvc int <interface>" command
+ * state token next state
+ * NOISE <interface name> IN_REPORT
+ * IN_REPORT Description: skip rest of line, IN_REPORT
+ * IN_REPORT <prompt> DONE
+ * IN_REPORT 1st bytes BYTES_IN
+ * IN_REPORT 2nd bytes BYTES_OUT
+ * IN_REPORT 3rd bytes BYTES_OUT_BCAST
+ * BYTES_IN <number> (bytes_in) IN_REPORT
+ * BYTES_OUT <number> (bytes_out) IN_REPORT
+ * BYTES_OUT_BCAST <number> (bytes_out_bcast) IN_REPORT
+ *
+ * Note lines are terminated with \r
+ */
+
+#define DONE -1
+#define NOISE 0
+#define IN_REPORT 1
+#define RATE 2
+#define RATE_IN 3
+#define RATE_OUT 4
+#define BYTES_IN 5
+#define BYTES_OUT 6
+#define BW 7
+#define BYTES_OUT_BCAST 8
+
+#ifdef PCP_DEBUG
+static char *statestr[] = {
+ "done", "noise", "in_report",
+ "rate", "rate_in", "rate_out", "bytes_in", "bytes_out", "bw",
+ "bytes_out_bcast"
+};
+#endif
+
+int
+dousername(cisco_t *cp, char **pw_prompt)
+{
+ char *w;
+ int len, done = 0;
+ int len_prompt = strlen(cp->prompt);
+
+ for ( ; ; ) {
+ w = mygetwd(cp->fin, cp->prompt);
+ if (w == NULL)
+ break;
+ if (strlen(w) >= len_prompt && strncmp(&w[strlen(w)-len_prompt], cp->prompt, len_prompt) == 0)
+ break;
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0)
+ fprintf(stderr, "Username:? got - %s\n", w);
+#endif
+ if (strcmp(w, USERPROMPT) == 0) {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL1) {
+ fprintf(stderr, "Send username: %s\n", cp->username);
+ }
+#endif
+ fprintf(cp->fout, "%s\n", cp->username);
+ fflush(cp->fout);
+ for ( ; ; ) {
+ w = mygetwd(cp->fin, cp->prompt);
+ if (w == NULL || strcmp(w, USERPROMPT) == 0)
+ /* closed connection or Username re-prompt */
+ break;
+ len = strlen(w);
+ if ((len >= len_prompt && strncmp(&w[len-len_prompt], cp->prompt, len_prompt) == 0) ||
+ w[len-1] == ':') {
+ /* command prompt or passwd */
+ if (w[len-1] == ':')
+ *pw_prompt = w;
+ done = 1;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ if (done == 0) {
+ fprintf(stderr, "Error: Cisco username negotiation failed for \"%s\"\n",
+ cp->host);
+ fprintf(stderr,
+"To check that a username is required, enter the following command:\n"
+" $ telnet %s\n"
+"If the prompt \"%s\" does not appear, no username is required.\n"
+"Otherwise, enter the username \"%s\" to check that this\n"
+"is correct.\n",
+cp->host, USERPROMPT, cp->username);
+ }
+
+ return done;
+}
+
+int
+dopasswd(cisco_t *cp, char *pw_prompt)
+{
+ char *w;
+ int done = 0;
+ int len_prompt = strlen(cp->prompt);
+
+ for ( ; ; ) {
+ if (pw_prompt) /* dousername may have read passwd prompt */
+ w = pw_prompt;
+ else
+ w = mygetwd(cp->fin, cp->prompt);
+ pw_prompt = NULL;
+ if (w == NULL)
+ break;
+ if (strlen(w) >= len_prompt && strncmp(&w[strlen(w)-len_prompt], cp->prompt, len_prompt) == 0)
+ break;
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0)
+ fprintf(stderr, "Password:? got - %s\n", w);
+#endif
+ if (strcmp(w, PWPROMPT) == 0) {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL1) {
+ fprintf(stderr, "Send passwd: %s\n", cp->passwd);
+ }
+#endif
+ fprintf(cp->fout, "%s\n", cp->passwd);
+ fflush(cp->fout);
+ for ( ; ; ) {
+ w = mygetwd(cp->fin, cp->prompt);
+ if (w == NULL || strcmp(w, PWPROMPT) == 0)
+ /* closed connection or user-level password re-prompt */
+ break;
+ if (strlen(w) >= len_prompt && strncmp(&w[strlen(w)-len_prompt], cp->prompt, len_prompt) == 0) {
+ /* command prompt */
+ done = 1;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ if (done == 0) {
+ fprintf(stderr, "Error: Cisco user-level password negotiation failed for \"%s\"\n",
+ cp->host);
+ fprintf(stderr,
+"To check that a user-level password is required, enter the following command:\n"
+" $ telnet %s\n"
+"If the prompt \"%s\" does not appear, no user-level password is required.\n"
+"Otherwise, enter the user-level password \"%s\" to check that this\n"
+"is correct.\n",
+cp->host, PWPROMPT, cp->passwd);
+ }
+
+ return done;
+}
+
+static int timeout;
+
+void
+onalarm(int dummy)
+{
+ timeout = 1;
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0) {
+ fprintf(stderr, "Alarm timeout!\n");
+ }
+#endif
+
+}
+
+static int
+get_fr_bw(cisco_t *cp, char *interface)
+{
+ int state = NOISE;
+ int bandwidth = -1;
+ char *w;
+ int len_prompt = strlen(cp->prompt);
+
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL1) {
+ fprintf(stderr, "Send: s%s\n", interface);
+ }
+#endif
+ fprintf(cp->fout, "show int s%s\n", interface);
+ fflush(cp->fout);
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2)
+ fprintf(stderr, "BW Parse:");
+#endif
+ while (state != DONE) {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2)
+ fprintf(stderr, "[%s] ", statestr[state+1]);
+#endif
+ w = mygetwd(cp->fin, cp->prompt);
+ if (w == NULL || timeout) {
+ /*
+ * End of File (telenet timeout?)
+ */
+ alarm(0);
+ return -1;
+ }
+ switch (state) {
+
+ case NOISE:
+ if (strncmp(w, "Serial", 6) == 0 && strcmp(&w[6], interface) == 0)
+ state = IN_REPORT;
+ break;
+
+ case IN_REPORT:
+ if (strcmp(w, "Description:") == 0)
+ skip2eol(cp->fin);
+ else if (strlen(w) >= len_prompt && strncmp(&w[strlen(w)-len_prompt], cp->prompt, len_prompt) == 0)
+ state = DONE;
+ else if (strcmp(w, "BW") == 0)
+ state = BW;
+ break;
+
+ case BW:
+ sscanf(w, "%d", &bandwidth);
+ bandwidth *= 1000; /* Kbit -> bytes/sec */
+ bandwidth /= 8;
+ state = IN_REPORT;
+ break;
+
+ }
+ }
+ alarm(0);
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0) {
+ fprintf(stderr, "Extracted bandwidth: %d bytes/sec\n", bandwidth);
+ }
+#endif
+ return bandwidth;
+}
+
+#define SHOW_INT 1
+#define SHOW_FRAME 2
+
+int
+grab_cisco(intf_t *ip)
+{
+ int style;
+ int next_state;
+ int state = NOISE;
+ int skip = 0;
+ int i;
+ int namelen;
+ char *pw_prompt = NULL;
+ char *w;
+ int fd;
+ int fd2;
+ int nval = 0;
+ cisco_t *cp = ip->cp;
+ intf_t tmp;
+ int len_prompt = strlen(cp->prompt);
+
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0) {
+ fprintf(stderr, "grab_cisco(%s:%s):\n", cp->host, ip->interface);
+ }
+#endif
+
+ tmp.bandwidth = tmp.rate_in = tmp.rate_out = -1;
+ tmp.bytes_in = tmp.bytes_out = tmp.bytes_out_bcast = -1;
+
+ if (cp->fin == NULL) {
+ fd = conn_cisco(cp);
+ if (fd < 0) {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0)
+ fprintf(stderr, "grab_cisco(%s:%s): connect failed: %s\n",
+ cp->host, ip->interface, netstrerror());
+#endif
+ return -1;
+ }
+ else {
+ cp->fin = fdopen (fd, "r");
+ if ((fd2 = dup(fd)) < 0) {
+ perror("dup");
+ exit(1);
+ }
+ cp->fout = fdopen (fd2, "w");
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0) {
+ fprintf(stderr, "grab_cisco(%s:%s): connected fin=%d fout=%d",
+ cp->host, ip->interface, fileno(cp->fin), fileno(cp->fout));
+ if (cp->username != NULL)
+ fprintf(stderr, " username=%s", cp->username);
+ else
+ fprintf(stderr, " NO username");
+ if (cp->passwd != NULL)
+ fprintf(stderr, " passwd=%s", cp->passwd);
+ else
+ fprintf(stderr, " NO passwd");
+ fputc('\n', stderr);
+ }
+#endif
+
+ if (cp->username != NULL) {
+ /*
+ * Username stuff ...
+ */
+ if (dousername(cp, &pw_prompt) == 0) {
+ fclose(cp->fin);
+ fclose(cp->fout);
+ cp->fin = cp->fout = NULL;
+ return -1;
+ }
+ }
+ if (cp->passwd != NULL) {
+ /*
+ * User-level password stuff ...
+ */
+ if (dopasswd(cp, pw_prompt) == 0) {
+ fclose(cp->fin);
+ fclose(cp->fout);
+ cp->fin = cp->fout = NULL;
+ return -1;
+ }
+ }
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL1) {
+ fprintf(stderr, "Send: \n");
+ }
+#endif
+ fprintf(cp->fout, "\n");
+ fflush(cp->fout);
+ }
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL1) {
+ fprintf(stderr, "Send: terminal length 0\n");
+ }
+#endif
+ fprintf(cp->fout, "terminal length 0\n");
+ fflush(cp->fout);
+ }
+
+ timeout = 0;
+ signal(SIGALRM, onalarm);
+ /*
+ * Choice of timeout here is somewhat arbitrary ... for a long
+ * time this was 5 (seconds), but then testing with an entry
+ * level Model 800 ADSL router revealed that up to 20 seconds
+ * was required to generate the expected output.
+ */
+ alarm(20);
+
+ style = SHOW_INT; /* default Cisco command */
+ if (ip->interface[0] == 's' && strchr(ip->interface, '.') != NULL) {
+ /*
+ * Frame-relay PVC on subinterface for s2/3.7 style interface name
+ */
+ style = SHOW_FRAME;
+ if (ip->bandwidth == -2) {
+ /*
+ * one-trip initialzation ... need show int s2/3.7 to
+ * get bandwidth
+ */
+ ip->bandwidth = get_fr_bw(cp, &ip->interface[1]);
+ }
+ tmp.bandwidth = ip->bandwidth;
+ if (tmp.bandwidth != -1)
+ nval++;
+ }
+ if (style == SHOW_FRAME) {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL1) {
+ fprintf(stderr, "Send: show frame pvc int s%s\n", &ip->interface[1]);
+ }
+#endif
+ fprintf(cp->fout, "show frame pvc int s%s\n", &ip->interface[1]);
+ next_state = BYTES_IN;
+ }
+ else {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL1) {
+ fprintf(stderr, "Send: show int %s\n", ip->interface);
+ }
+#endif
+ fprintf(cp->fout, "show int %s\n", ip->interface);
+ }
+ fflush(cp->fout);
+ state = NOISE;
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2) {
+ fprintf(stderr, "Parse:");
+ fflush(stderr);
+ }
+#endif
+ while (state != DONE) {
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL2) {
+ fprintf(stderr, "[%s] ", statestr[state+1]);
+ fflush(stderr);
+ }
+#endif
+ w = mygetwd(cp->fin, cp->prompt);
+ if (w == NULL || timeout) {
+ /*
+ * End of File (telenet timeout?)
+ * ... mark as closed, and try again at next request
+ */
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0)
+ fprintf(stderr, "grab_cisco(%s:%s): forced disconnect fin=%d\n",
+ cp->host, ip->interface, fileno(cp->fin));
+#endif
+ fclose(cp->fin);
+ fclose(cp->fout);
+ cp->fin = cp->fout = NULL;
+ alarm(0);
+ return -1;
+ }
+ switch (state) {
+
+ case NOISE:
+ for (i = 0; i < num_intf_tab; i++) {
+ namelen = strlen(intf_tab[i].name);
+ if (strncmp(w, intf_tab[i].name, namelen) == 0) {
+ state = IN_REPORT;
+ break;
+ }
+ }
+ break;
+
+ case IN_REPORT:
+ if (strcmp(w, "Description:") == 0)
+ skip2eol(cp->fin);
+ if (strlen(w) >= len_prompt && strncmp(&w[strlen(w)-len_prompt], cp->prompt, len_prompt) == 0)
+ state = DONE;
+ else if (style == SHOW_INT) {
+ if (strcmp(w, "minute") == 0 || strcmp(w, "second") == 0)
+ state = RATE;
+ else if (strcmp(w, "input,") == 0)
+ state = BYTES_IN;
+ else if (strcmp(w, "output,") == 0)
+ state = BYTES_OUT;
+ else if (strcmp(w, "BW") == 0)
+ state = BW;
+ }
+ else if (style == SHOW_FRAME) {
+ if (strcmp(w, "bytes") == 0) {
+ if (next_state == BYTES_IN) {
+ state = BYTES_IN;
+ next_state = BYTES_OUT;
+ }
+ else if (next_state == BYTES_OUT) {
+ state = BYTES_OUT;
+ next_state = BYTES_OUT_BCAST;
+ }
+ else if (next_state == BYTES_OUT_BCAST) {
+ state = BYTES_OUT_BCAST;
+ next_state = IN_REPORT;
+ }
+ else
+ state = next_state;
+ }
+ }
+ break;
+
+ case RATE:
+ if (strcmp(w, "input") == 0) {
+ skip = 1;
+ state = RATE_IN;
+ }
+ else if (strcmp(w, "output") == 0) {
+ skip = 1;
+ state = RATE_OUT;
+ }
+ break;
+
+ case RATE_IN:
+ if (skip-- == 0) {
+ tmp.rate_in = atol(w) / 8;
+ nval++;
+ state = IN_REPORT;
+ }
+ break;
+
+ case RATE_OUT:
+ if (skip-- == 0) {
+ tmp.rate_out = atol(w) / 8;
+ nval++;
+ state = IN_REPORT;
+ }
+ break;
+
+ case BYTES_IN:
+ tmp.bytes_in = strtoull(w, NULL, 10);
+ nval++;
+ state = IN_REPORT;
+ break;
+
+ case BYTES_OUT:
+ tmp.bytes_out = strtoull(w, NULL, 10);
+ nval++;
+ state = IN_REPORT;
+ break;
+
+ case BYTES_OUT_BCAST:
+ tmp.bytes_out_bcast = strtoull(w, NULL, 10);
+ nval++;
+ state = IN_REPORT;
+ break;
+
+ case BW:
+ sscanf(w, "%d", &tmp.bandwidth);
+ tmp.bandwidth *= 1000; /* Kbit -> bytes/sec */
+ tmp.bandwidth /= 8;
+ nval++;
+ state = IN_REPORT;
+ break;
+
+ }
+ }
+ alarm(0);
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0) {
+ fprintf(stderr, "Extracted %d values ...\n", nval);
+ if (tmp.bandwidth != 0xffffffff)
+ fprintf(stderr, "bandwidth: %d bytes/sec\n", tmp.bandwidth);
+ else
+ fprintf(stderr, "bandwidth: ? bytes/sec\n");
+ fprintf(stderr, "recent rate (bytes/sec):");
+ if (tmp.rate_in != 0xffffffff)
+ fprintf(stderr, " %d in", tmp.rate_in);
+ else
+ fprintf(stderr, " ? in");
+ if (tmp.rate_out != 0xffffffff)
+ fprintf(stderr, " %d out", tmp.rate_out);
+ else
+ fprintf(stderr, " ? out");
+ fprintf(stderr, "\ntotal bytes:");
+ if (tmp.bytes_in != 0xffffffffffffffffLL)
+ fprintf(stderr, " %llu in", (unsigned long long)tmp.bytes_in);
+ else
+ fprintf(stderr, " ? in");
+ if (tmp.bytes_out != 0xffffffffffffffffLL)
+ fprintf(stderr, " %llu out", (unsigned long long)tmp.bytes_out);
+ else
+ fprintf(stderr, " ? out");
+ if (tmp.bytes_out_bcast != 0xffffffffffffffffLL)
+ fprintf(stderr, " %llu out_bcast", (unsigned long long)tmp.bytes_out_bcast);
+ else
+ fprintf(stderr, " ? out_bcast");
+ fprintf(stderr, "\n\n");
+ }
+#endif
+
+ /* pretend this is atomic */
+ ip->bandwidth = tmp.bandwidth;
+ ip->rate_in = tmp.rate_in;
+ ip->rate_out = tmp.rate_out;
+ ip->bytes_in = tmp.bytes_in;
+ ip->bytes_out = tmp.bytes_out;
+ ip->bytes_out_bcast = tmp.bytes_out_bcast;
+
+ return nval;
+}