Syed Jahanzaib – Personal Blog to Share Knowledge !

January 28, 2017

Acquiring Cisco Switch Customized Report via Sms/Email

Filed under: Cisco Related — Syed Jahanzaib / Pinochio~:) @ 10:02 AM

img_20170127_163525339


Scenario:

We have few Cisco switches installed in our network. the OP wants to receive specific switch report via email, by sending SMS to the system (on demand or scheduled), and the system should return the detailed report by email with following details ….

The Task is quite simple, and surely it can be done with more better approach or professional coding, but this is just mine exploration which is working fine for my static requirements. We can add about any other information in the script, as per required.


Requirements for report:

  • The report should be customized according to the OP taste. For this purpose we made an script which does the following
  • Check if IP is missing, exit with error, and return error by email to Admin, otherwise Continue to Next Step…
  • Check if IP is invalid, exit with error, and return error by email to Admin, otherwise Continue to Next Step…
  • Check if IP is not accessible by ping, exit with error, and return error by email to Admin, otherwise Continue to Next Step…
  • Check if SNMP UDP port 161 is not accessible by nmap, exit with error, and return error by email to Admin, otherwise Continue to Next Step…
  • Check if remote device is not a Cisco switch, exit with error, and return error by email to Admin, otherwise Continue to Next Step…
  • Automatically check for all available ports like 24/28/48/52 etc,
  • Check Switch Mode/Type/Firmware/CPU Usage/Switch Uptime/Vlan Count etc
  • Check all Ports Up/Down Status / Port Speed / Last Status Change etc
  • Script start/end Time stamp.

Tools Used in this post … [Extra]

  • Kannel/playsms for receiving SMS and execute the script which will in return sends response by email (or sms) [ I have covered kannel and playSMS in my previous guides at my blog]
  • nmap to query remote device SNMP UDP 161 port [you can use some other methods as well]
  • sendEmail tool to send email [you can use some other methods as well]
    • [ I have covered sendEmail tool usage in my previous guide at my blog]

This script may be valid for Cisco 3750 or 3560 switch only. modify it as required.

zaiB!


the Script!


#!/bin/sh
# Script to detect Cisco switch Port status / speed / Description with various checks
# Useful for admins who want to query there switch information by SMS ,
# like we can configure this script to be executed from incoming SMS (using playSMS) and send result by email
# Syed Jahanziab
# http:// aacable . wordpress . com / aacable @ hotmail . com

# to debug script , remove # from following line
#set -x

# Color Codes, we can use these codes to color our black world output
ESC_SEQ="\x1b["
COL_RESET=$ESC_SEQ"39;49;00m"
COL_RED=$ESC_SEQ"31;01m"
COL_GREEN=$ESC_SEQ"32;01m"

# Hostname and other Variables
# Take ip from command line variable
IP="$1"
# Switch SNMP community string
SNMP_STRING="PUBLIC"
HOSTNAME=`hostname`
COMPANY="zaib (Pvt) Ltd."
FOOTER="Powered By Syed.Jahanzaib"
DATE=`date`

# EMAIL RELATED and KANNEL INFO
# for down status, we have to use GMAIL to send email
KANNELURL="127.0.0.1:13013"
KANNELID="kannel"
KANNELPASS="KANNEL_PASS"
CELL1="03333021909"
CELL2="0333XXXXXX"
# GMAIL Section
GMAILID="YOUR_GMAIL_ID@gmail.com"
GMAILPASS="PASS"
ADMINMAIL1="aacableAThotmailDOTcom"
ADMINMAIL2="XXX_XXX@hotmail.com"

#Email Subject Body etc
EMAIL_SUB="INFO: Switch IP $IP - Report @ $DATE"
EMAIL_BODY="/tmp/$ip.email.txt"
echo "
$IP SWITCH QUERY Starts @ $DATE

"

echo "
$IP SWITCH QUERY Starts @ $DATE

" > $EMAIL_BODY
############ DIFFERENT ERROR's VARIABLES ###########
ERR_NOIP="ERROR: Please provide IP of switch

Eaxmple:
portquery 192.168.155.255"

ERR_INVALID_IP="ERROR: Invalid IP address detected. Please provide valid IP of switch

Eaxmple:
portquery 192.168.155.255"

ERR_PING_FAILED="ERROR: Switch IP $IP PING is DOWN ... cannot proceed further... Wziring"
ERR_SNMP="ERROR: Switch IP $IP SNMP not responding. Cannot continue without it... Exiting"
ERR_NO_CISCO="ERROR: $IP - Remote device type doesn't look like CISCO switch... Exiting"

PORTS_TMP_HOLDER="/tmp/$IP.port.numbers"
PORTS_TMP_HOLDER_FINAL="$IP.port.numbers.final"

# If IP is not provided with variable , give error
if [ -z "$IP" ]; then
echo "$ERR_NOIP"
# Send Email reply to Admin for IP not provided error
echo "$ERR_NOIP" >> $EMAIL_BODY
/temp/sendEmail-v1.56/sendEmail -u "$EMAIL_SUB" -o tls=yes -s smtp.gmail.com:587 -t $ADMINMAIL1 -xu $GMAILID -xp $GMAILPASS -f $GMAILID -o message-file=$EMAIL_BODY -o message-content-type=text
/temp/sendEmail-v1.56/sendEmail -u "$EMAIL_SUB" -o tls=yes -s smtp.gmail.com:587 -t $ADMINMAIL2 -xu $GMAILID -xp $GMAILPASS -f $GMAILID -o message-file=$EMAIL_BODY -o message-content-type=text
exit 1
fi

# Check for IP addrrss validity, IP must be in format like `port query10.0.0.1`
if expr "$IP" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; then
echo "IP OK" > /dev/null
else
echo "$ERR_INVALID_IP"
# Send Email reply to Admin for invalid IP
echo "$ERR_INVALID_IP" >> $EMAIL_BODY
/temp/sendEmail-v1.56/sendEmail -u "$EMAIL_SUB" -o tls=yes -s smtp.gmail.com:587 -t $ADMINMAIL1 -xu $GMAILID -xp $GMAILPASS -f $GMAILID -o message-file=$EMAIL_BODY -o message-content-type=text
/temp/sendEmail-v1.56/sendEmail -u "$EMAIL_SUB" -o tls=yes -s smtp.gmail.com:587 -t $ADMINMAIL2 -xu $GMAILID -xp $GMAILPASS -f $GMAILID -o message-file=$EMAIL_BODY -o message-content-type=text
exit 1
fi

# Check if REMOTE DEVICE is accessibel or not, if not then EXIT immediately with error / zaib
#if [[ $(ping -q -c 3 P) == @(*100% packet loss*) ]]; then
PING_LOSS=`ping -c 1 -q $IP | grep -oP '\d+(?=% packet loss)'`
if [ "$PING_LOSS" = "100" ]; then
echo "$ERR_PING_FAILED"
# Send Email reply to Admin for IP not responding
echo "$ERR_PING_FAILED" >> $EMAIL_BODY
/temp/sendEmail-v1.56/sendEmail -u "$EMAIL_SUB" -o tls=yes -s smtp.gmail.com:587 -t $ADMINMAIL1 -xu $GMAILID -xp $GMAILPASS -f $GMAILID -o message-file=$EMAIL_BODY -o message-content-type=text
/temp/sendEmail-v1.56/sendEmail -u "$EMAIL_SUB" -o tls=yes -s smtp.gmail.com:587 -t $ADMINMAIL2 -xu $GMAILID -xp $GMAILPASS -f $GMAILID -o message-file=$EMAIL_BODY -o message-content-type=text
exit 1
fi

# Check if SNMP port is responding or not, because we require SNMP to query all results
SNMP_PORT_QUERY=`nmap -sU -p 161 $IP | grep open`
if [ -z "$SNMP_PORT_QUERY" ]; then
echo "$ERR_SNMP"
# Send Email reply to Admin for SNMP not responding
echo "$ERR_SNMP" >> $EMAIL_BODY
/temp/sendEmail-v1.56/sendEmail -u "$EMAIL_SUB" -o tls=yes -s smtp.gmail.com:587 -t $ADMINMAIL1 -xu $GMAILID -xp $GMAILPASS -f $GMAILID -o message-file=$EMAIL_BODY -o message-content-type=text
/temp/sendEmail-v1.56/sendEmail -u "$EMAIL_SUB" -o tls=yes -s smtp.gmail.com:587 -t $ADMINMAIL2 -xu $GMAILID -xp $GMAILPASS -f $GMAILID -o message-file=$EMAIL_BODY -o message-content-type=text
exit 1
fi

# Determine device OS type, if it doesnt contains 'Cisco IOS' word, then exit
DETECT_SW_OS=`snmpwalk -v1 -c $SNMP_STRING $IP 1.3.6.1.2.1.1.1 | grep -R "Cisco IOS"`
if [ -z "$DETECT_SW_OS" ]; then
echo "$ERR_NO_CISCO"
echo "$ERR_NO_CISCO" >> $EMAIL_BODY
/temp/sendEmail-v1.56/sendEmail -u "$EMAIL_SUB" -o tls=yes -s smtp.gmail.com:587 -t $ADMINMAIL1 -xu $GMAILID -xp $GMAILPASS -f $GMAILID -o message-file=$EMAIL_BODY -o message-content-type=text
/temp/sendEmail-v1.56/sendEmail -u "$EMAIL_SUB" -o tls=yes -s smtp.gmail.com:587 -t $ADMINMAIL2 -xu $GMAILID -xp $GMAILPASS -f $GMAILID -o message-file=$EMAIL_BODY -o message-content-type=text
exit 1
fi

# Switch name variable / mib etc
MIB="/cfg/mibs/HOST-RESOURCES-MIB"
SW_NAME=`snmpwalk -Oqv -v1 -c $SNMP_STRING $IP iso.3.6.1.2.1.1.5.0`
SW_MODEL=`snmpwalk -Oqv -v1 -c $SNMP_STRING $IP .1.3.6.1.2.1.47.1.1.1.1.13.1001`
SW_FW=`snmpwalk -Oqv -v1 -c $SNMP_STRING $IP .1.3.6.1.2.1.1.1.0 | sed -n '1p'`
SW_CPU_USAGE=`snmpwalk -Oqvn -v1 -c $SNMP_STRING $IP 1.3.6.1.4.1.9.2.1.56.0`
SW_UPTIME=`snmpwalk -v1 -c $SNMP_STRING $IP .1.3.6.1.2.1.1.3.0 | sed 's:.*)::'`
SW_VLAN_COUNT=`snmpwalk -v1 -c $SNMP_STRING $IP iso.3.6.1.2.1.47.1.2.1.1.2 | wc -l`
# Query Port number after trimming and store in file, it will be used for port counting and switch media type as well / zaib
snmpwalk -v1 -c gt $IP .1.3.6.1.2.1.2.2.1.2 | sed '/Stack\|Vlan\|Null/d' > $PORTS_TMP_HOLDER

# Count total ports in switch
PORT_COUNT=`cat $PORTS_TMP_HOLDER | wc -l`

# Query Switch type like if its megabit or gigabit, we will do it using FAST word, pretty lame but its working good for me / zaib
SW_TYPE_Q=`cat $PORTS_TMP_HOLDER | grep Fast`
if [ -z "$SW_TYPE_Q" ]; then

###########################################################
# Consider Switch as GIGAbit and do actions based upon it #
###########################################################

# Print
INFO_HEADER="Switch Model: $SW_MODEL
Switch Name: $SW_NAME
Switch type: GIGABIT Model
Switch Fw : $SW_FW
Switch Uptime: $SW_UPTIME
Switch CPU Usage: $SW_CPU_USAGE
Switch VLAN Numbers: $SW_VLAN_COUNT

Ports Status :
"
echo "$INFO_HEADER"

# Add text for Email Body
echo "$INFO_HEADER" >> $EMAIL_BODY

# Some junk maths
cat $PORTS_TMP_HOLDER | grep -o -P '.{0,0}101.{0,2}' | sed 's/101//' > $PORTS_TMP_HOLDER_FINAL
cat $PORTS_TMP_HOLDER_FINAL | while read ports
do
num=$[$num+1]
PORT_N=`echo $ports`
PORT_DESC_Q=`snmpwalk -Oqv -v1 -c $SNMP_STRING $IP 1.3.6.1.2.1.31.1.1.1.18.101$PORT_N | tr -d '"' | grep -E "[[:alnum:]]"`
SW_PORT_LAST_ST_CHANGE=`snmpwalk -On -v1 -c $SNMP_STRING $IP .1.3.6.1.2.1.2.2.1.9.101$PORT_N | sed 's:.*)::'`
if [ "$PORT_DESC_Q" = "" ]; then
PORT_DESC="n/a"
else
PORT_DESC="$PORT_DESC_Q"
fi
PORT_Q=`snmpwalk -Oqv -v1 -c $SNMP_STRING $IP 1.3.6.1.2.1.2.2.1.8.101$PORT_N`
if [ "$PORT_Q" -eq 1 ]; then
PORT_STATUS="UP"
else
PORT_STATUS="DOWN"
fi
if [ "$PORT_STATUS" = "DOWN" ]; then
PORT_SPEED="n/a"
else
PORT_SPEED_Q=`snmpwalk -Oqv -v1 -c $SNMP_STRING $IP iso.3.6.1.2.1.2.2.1.5.101$PORT_N`
PORT_SPEED=`echo $(($PORT_SPEED_Q/1000/1000)) mbps`
fi
PORT_NAME=`snmpwalk -Oqv -v1 -c $SNMP_STRING $IP 1.3.6.1.2.1.31.1.1.1.18.101$PORT_N`

# Finally Spit out all the info gaterhed by above junk code 😀 / zaib
echo "PORT_Number: $PORT_N / Status: $PORT_STATUS / Name: $PORT_DESC / Speed: $PORT_SPEED / Port_Last_Status_Change = $SW_PORT_LAST_ST_CHANGE"
#echo "PORT_Number: $PORT_N / Status: $PORT_STATUS / Name: $PORT_DESC / Speed: $PORT_SPEED / Port_Last_Status_Change = $SW_PORT_LAST_ST_CHANGE" >> $EMAIL_BODY
done

###########################################################
# Consider Switch as Megabit and do actions based upon it #
###########################################################
else
#Print
INFO_HEADER="Switch Model: $SW_MODEL
Switch Name: $SW_NAME
Switch type: MEGABIT Model
Switch Fw : $SW_FW
Switch Uptime: $SW_UPTIME
Switch CPU Usage: $SW_CPU_USAGE
Switch VLAN Numbers: $SW_VLAN_COUNT

Ports Status :
"
echo "$INFO_HEADER"
# Add text for Email Body
echo "$INFO_HEADER" >> $EMAIL_BODY

cat $PORTS_TMP_HOLDER | grep -o -P '.{0,0}100.{0,2}' | sed 's/100//' > $PORTS_TMP_HOLDER_FINAL
cat $PORTS_TMP_HOLDER_FINAL | while read ports
do
num=$[$num+1]
PORT_N=`echo $ports`
PORT_DESC_Q=`snmpwalk -Oqv -v1 -c $SNMP_STRING $IP 1.3.6.1.2.1.31.1.1.1.18.100$PORT_N | tr -d '"' | grep -E "[[:alnum:]]"`
SW_PORT_LAST_ST_CHANGE=`snmpwalk -On -v1 -c $SNMP_STRING $IP .1.3.6.1.2.1.2.2.1.9.100$PORT_N | sed 's:.*)::'`
if [ "$PORT_DESC_Q" = "" ]; then
PORT_DESC="n/a"
else
PORT_DESC="$PORT_DESC_Q"
fi
PORT_Q=`snmpwalk -Oqv -v1 -c $SNMP_STRING $IP 1.3.6.1.2.1.2.2.1.8.100$PORT_N`
if [ "$PORT_Q" -eq 1 ]; then
PORT_STATUS="UP"
PORT_SPEED_Q=`snmpwalk -Oqv -v1 -c $SNMP_STRING $IP iso.3.6.1.2.1.2.2.1.5.100$PORT_N`
PORT_SPEED=`echo $(($PORT_SPEED_Q/1000/1000)) mbps`
else
PORT_STATUS="DOWN"
PORT_SPEED="n/a"
PORT_NAME=`snmpwalk -Oqv -v1 -c $SNMP_STRING $IP 1.3.6.1.2.1.31.1.1.1.18.100$PORT_N`
fi
# Finally Spit out all the info gaterhed by above junk code 😀 / zaib
echo "PORT_Number: $PORT_N / Status: $PORT_STATUS / Name: $PORT_DESC / Speed: $PORT_SPEED / Port_Last_Status_Change = $SW_PORT_LAST_ST_CHANGE"
echo "PORT_Number: $PORT_N / Status: $PORT_STATUS / Name: $PORT_DESC / Speed: $PORT_SPEED / Port_Last_Status_Change = $SW_PORT_LAST_ST_CHANGE" >> $EMAIL_BODY
done
fi
# Send the result via EMAIL to admin emails as mentioned in start.
# Add footer
DATE=`date`
echo "
Switch Query Ends Here at $DATE

$COMPANY
$FOOTER"
echo "
Switch Query Ends Here at $DATE

$COMPANY
$FOOTER" >> $EMAIL_BODY
/temp/sendEmail-v1.56/sendEmail -u "$EMAIL_SUB" -o tls=yes -s smtp.gmail.com:587 -t $ADMINMAIL1 -xu $GMAILID -xp $GMAILPASS -f $GMAILID -o message-file=$EMAIL_BODY -o message-content-type=text
#cat $MSGDOWNHOLDER | curl "http://$KANNELURL/cgi-bin/sendsms?username=$KANNELID&password=$KANNELPASS&to=$CELL1" -G --data-urlencode text@-

# Script Ends here #

 


Result/Report Sample:

Result via Email:

1- sw-report.PNG


Result in CMD:


#### root@ubuntu:/temp# ./portquery.sh 192.168.255.254

192.168.255.254 SWITCH QUERY Starts @ Sat Jan 28 00:49:07 PKT 2017
Switch Model: "WS-C3750G-24PS-S"
Switch Name: "X-switch"
Switch type: GIGABIT Model
Switch Fw : "Cisco IOS Software, C3750 Software (C3750-IPBASE-M), Version 12.2(35)SE5, RELEASE SOFTWARE (fc1)
Switch Uptime: 13 days, 17:24:37.14
Switch CPU Usage: 6
Switch VLAN Numbers: 57

Ports Status :

PORT_Number: 01 / Status: UP / Name: n/a / Speed: 1000 mbps / Port_Last_Status_Change = 0:01:19.59
PORT_Number: 02 / Status: DOWN / Name: ServerX / Speed: n/a / Port_Last_Status_Change = 0:01:13.07
PORT_Number: 03 / Status: UP / Name: Server4 / Speed: 1000 mbps / Port_Last_Status_Change = 7 days, 23:46:45.26
PORT_Number: 04 / Status: UP / Name: n/a / Speed: 1000 mbps / Port_Last_Status_Change = 7 days, 23:46:44.53
PORT_Number: 05 / Status: UP / Name: n/a / Speed: 1000 mbps / Port_Last_Status_Change = 0:01:16.08
PORT_Number: 06 / Status: UP / Name: n/a / Speed: 1000 mbps / Port_Last_Status_Change = 7 days, 23:46:42.48
PORT_Number: 07 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 0:01:13.07
PORT_Number: 08 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 0:01:13.07
PORT_Number: 09 / Status: DOWN / Name: vlanX / Speed: n/a / Port_Last_Status_Change = 0:01:13.07
PORT_Number: 10 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 13 days, 1:53:58.05
PORT_Number: 11 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 0:01:13.08
PORT_Number: 12 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 0:01:13.08
PORT_Number: 13 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 0:01:13.08
PORT_Number: 14 / Status: DOWN / Name: test-trunk-XX-new / Speed: n/a / Port_Last_Status_Change = 0:01:13.08
PORT_Number: 15 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 0:01:13.08
PORT_Number: 16 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 0:01:13.08
PORT_Number: 17 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 0:01:13.08
PORT_Number: 18 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 0:01:13.08
PORT_Number: 19 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 0:01:13.08
PORT_Number: 20 / Status: UP / Name: XXX_gb_media_test / Speed: 1000 mbps / Port_Last_Status_Change = 0:01:16.09
PORT_Number: 21 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 0:01:13.08
PORT_Number: 22 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 0:01:13.08
PORT_Number: 23 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 0:01:13.08
PORT_Number: 24 / Status: DOWN / Name: up_2_jr_sw / Speed: n/a / Port_Last_Status_Change = 0:01:11.68
PORT_Number: 25 / Status: UP / Name: up-2-XXX / Speed: 1000 mbps / Port_Last_Status_Change = 0:01:18.92
PORT_Number: 26 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 0:01:11.71
PORT_Number: 27 / Status: DOWN / Name: n/a / Speed: n/a / Port_Last_Status_Change = 0:01:11.72
PORT_Number: 28 / Status: UP / Name: XXX-SWX by FC / Speed: 1000 mbps / Port_Last_Status_Change = 12 days, 10:12:00.62

Switch Query Ends Here at Sat Jan 28 00:49:22 PKT 2017

zaib (Pvt) Ltd.
Powered By Syed.Jahanzaib
Jan 28 00:49:26 ubuntu sendEmail[16553]: Email was sent successfully!


playSMS COMMAND sample config [for incoming sms action]

playsms command.PNG

playSMS log when incoming message with specific keyword ‘switch x.x.x.x’ is received

127.0.0.1 localhost 2017-01-28 01:11:32 PID588ba9743d5c2 - L2 kannel__call # start load:/var/www/playsms/plugin/gateway/kannel/geturl.php
127.0.0.1 localhost 2017-01-28 01:11:32 PID588ba9743d5c2 - L3 kannel__incoming # remote_addr:127.0.0.1 remote_host:localhost t:[2017-01-28 03:11:27] q:[+923333021909] a:[switch X.X.X.X] Q:[13013] smsc:[] smsc:[]
127.0.0.1 localhost 2017-01-28 01:11:32 PID588ba9743d5c2 - L3 recvsms # isrecvsmsd:1 dt:2017-01-28 03:11:27 sender:+923333021909 m:switch X.X.X.X receiver:13013 smsc:
127.0.0.1 localhost 2017-01-28 01:11:32 PID588ba9743d5c2 - L2 kannel__call # end load geturl
- - 2017-01-28 01:11:32 PID58798d2cbeb7d - L3 recvsmsd # id:261 dt:2017-01-28 03:11:27 sender:+923333021909 m:switch X.X.X.X receiver:13013 smsc:
- - 2017-01-28 01:11:32 PID58798d2cbeb7d - L3 recvsms_process # dt:2017-01-28 03:11:27 sender:+923333021909 m:switch X.X.X.X receiver:13013 smsc:
- - 2017-01-28 01:11:32 PID58798d2cbeb7d - L3 gateway_decide_smsc # SMSC supplied:[] configured:[] decided smsc:[]
- - 2017-01-28 01:11:32 PID58798d2cbeb7d - L3 sms__command # command_exec:/var/lib/playsms/sms_command/1/portquery.sh 'X.X.X.X'
- - 2017-01-28 01:11:58 PID58798d2cbeb7d - L3 recvsms_process # feature:sms_command datetime:2017-01-28 03:11:27 sender:+923333021909 receiver:13013 keyword:SWITCH message:X.X.X.X raw:switch X.X.X.X smsc:

once the sms is received the playsms will execute the script, and will reply back by email or sms OR according to the configuration set in the script.


Regard’s

Syed Jahanzaib

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment