You are on page 1of 8

#TraceMAC v0.

5 - GAWK script used to process Plink/NC/SSH/WGET output


BEGIN{
error_found=inside_port_channel=skip_error_check=0;
OS_TYPE = (index(tolower(ENVIRON["OS"]), "windows") > 0) ? "Windows" : "Linux";
INFO = (SHOW_PROT_LOGIN) ? " - [Login: " PROT "]" : "";
}
#Windows processing errors function
function win_error_check(line)
{
if(PROT ~ /Telnet|SSH/) #Plink error detection
{
if(line ~ /(Access denied|% Authentication failed)/)
{
err_msg("Wrong username or password");
}
else if((line ~ /Command authorization failed/) && (PROT =="Telnet")) #
On SSH I send a 'n' to skip Plink's question about SSH key accept, and can trigg
er that error
{
err_msg("Command authorization failed");
}
else if(line ~ /FATAL ERROR: Network error: Connection refused/)
{
err_msg("Connection refused");
}
else if(line ~ /FATAL ERROR: Network error: Connection timed out/)
{
err_msg("Connection timed out");
}
else if(line ~ /FATAL ERROR: Network error: No route to host/)
{
err_msg("No route to host");
}
else if(line ~ /^Host does not exist/)
{
err_msg("Host not found");
}
else if(line ~ /FATAL ERROR: Incoming packet was garbled on decryption/
)
{
err_msg("Please increase 'SSH_SLOW_START' to '5' (check config)
");
}
else if(line ~ /FATAL ERROR: /)
{
err_msg(substr(line,14));
}
}
else if(PROT ~ /HTTPS?/) #Wget error detection
{
if(line ~ /^Authorization failed|HTTP\/1.. 401 Unauthorized/)
{
err_msg("Wrong username or password");
}
else if(line ~ /Command authorization failed/)
{
err_msg("Command authorization failed");
}

else if(line ~ / ERROR 404:.*Not Found|HTTP\/1.. 404 Not Found/)


{
err_msg("404 (Not Found), Unsupported device");
}
else if(line ~ /(^Read error \(No such file or directory\) in headers|:
443... failed: Bad file descriptor)/)
{
err_msg("Connection refused");
}
else if(line ~ /^Read error \(Unknown error\) in headers/)
{
err_msg("No response from host/Timeout");
}
else if(line ~ /^Connecting.* failed: No route to host./)
{
err_msg("No route to host");
}
else if(line ~ /^Resolving.*failed: Host not found./)
{
err_msg("Host not found");
}
}
}
#Linux processing errors function
function linux_error_check(line)
{
if(PROT=="Telnet") #NC (NetCat) error detection
{
if(line ~ /(Access denied|% Authentication failed)/)
{
err_msg("Wrong username or password");
}
else if(line ~ /Command authorization failed/)
{
err_msg("Command authorization failed");
}
else if(line ~ /^nc: connect to .* failed: Connection refused/)
{
err_msg("Connection refused");
}
else if(line ~ /^nc: connect to .* timed out/)
{
err_msg("Connection timed out");
}
else if(line ~ /^nc: connect to .* failed: No route to host/)
{
err_msg("No route to host");
}
else if(line ~ /^nc: getaddrinfo: (Name or service not known|Temporary
failure in name resolution)/)
{
err_msg("Host not found");
}
}
else if(PROT=="SSH") #SSH error detection
{
if(line ~ /cat: .* No such file or directory|Connection closed by /)
{
err_msg("Wrong username or password");

}
else if(line ~ /Command authorization failed/)
{
err_msg("Command authorization failed");
}
else if(line ~ /^Permission denied/)
{
err_msg("Permission denied (Probably unsupported device)");
}
else if(line ~ /^ssh: connect to .* Connection refused/)
{
err_msg("Connection refused");
}
else if(line ~ /^ssh: connect to .* timed out/)
{
err_msg("Connection timed out");
}
else if(line ~ /^ssh: connect to .* No route to host/)
{
err_msg("No route to host");
}
else if(line ~ /^ssh: .* (Name or service not known|Temporary failure i
n name resolution)/)
{
err_msg("Host not found");
}
}
else if(PROT ~ /HTTPS?/) #Wget error detection
{
if(line ~ /^Authorization failed.|^HTTP request sent, awaiting response
... Read error \(Connection timed out\) in headers/)
{
err_msg("Wrong username or password");
}
else if(line ~ /Command authorization failed/)
{
err_msg("Command authorization failed");
}
else if(line ~ / ERROR 404:.*Not Found|HTTP\/1.. 404 Not Found/)
{
err_msg("404 (Not Found), Unsupported device");
}
else if(line ~ /^Connecting to .* failed: Connection refused/)
{
err_msg("Connection refused");
}
else if(line ~ /^(Resolving|Connecting to).* failed: Connection timed o
ut/)
{
err_msg("No response from host/Timeout");
}
else if(line ~ /^Connecting to .* failed: No route to host./)
{
err_msg("No route to host");
}
else if(line ~ /^Resolving .* failed: Name or service not known/)
{
err_msg("Host not found");
}
}

}
#Function used to print the error message and exit.
function err_msg(MSG)
{
if(OS_TYPE=="Windows")
{
TOOL = (PROT~/Telnet|SSH/) ? "Plink" : (PROT~/HTTPS?/) ? "Wget" : "Trac
emac";
}
else
{
TOOL = (PROT=="Telnet") ? "NetCat(nc)" : (PROT=="SSH") ? "SSH" : (PROT~
/HTTPS?/) ? "Wget" : "Tracemac";
}
print "Error: No output from SW ("SWIP"). " TOOL ": " MSG " - ("PROT")!" > "/de
v/stderr";
error_found=1;
exit 1;
}
#This is used to load the configuration from '.ini' file, but also checking the
variables
#On Windows can't use double quotes and also I need to escape all the variables
that are later used with awk (Telnet login and "external device" enable password
)
#On Linux can use anything, but still have to escape all the variables that will
be later used with awk and also escape them again because on Linux awk "print"
function is different then GAWK
function value_escape(arg, val)
{
if((OS_TYPE=="Windows") && (val ~ /\"/))
{
return "DOUBLE_QUOTE_WARN";
}
else if((OS_TYPE=="Windows") && (arg == "SNMP_COMMUNITYS"))
{
gsub(/\\/, "\\\\",
val);
}
else if(arg == "CLI_PASS")
{
CLI_PASS_AWK=val; #Create a new value used for telnet (awk login)
if(OS_TYPE=="Windows") { gsub(/\\/, "\\\\",
CLI_PASS_AWK); }
else
{ gsub(/\\/, "\\\\\\\\", CLI_PASS_AWK); }
print "CLI_PASS_AWK=" CLI_PASS_AWK;
}
else if(arg == "EXTERNAL_ENABLE"){ gsub(/\\/, "\\\\",
val); }
if(OS_TYPE=="Linux")
{ gsub(/\\/, "\\\\",
val); } #On Linux I h
ave to do it again... (print function different from Windows GAWK)
return val;
}
/./{
#Remove "ip domain name" from CDP neighbors device id, and shrink interface name
s ;)
gsub(/\r$/, "");
gsub(SW_DOMAIN, "");
gsub(/TenGigabitEthernet/, "Te");
gsub(/GigabitEthernet/,
"Gi");

gsub(/FastEthernet/,
gsub(/Ethernet/,
gsub(/Port-channel/,

"Fa");
"E");
"Po");

#This is used to load the configuration from


variables
if(length(PASS_ESCAPE))
{
if($0 !~ /(^[#;]|^$)/)
{
#If no WEB_USER is defined,
if($1 == "WEB_USER") {
else if($1 == "CLI_USER") {
,length($1)+2)); }
else if($1 == "CLI_PASS") {
,length($1)+2)); }

'.ini' file, but also checking the

use the same CLI User/Pass for Web


WEB_USER=1; }
CLI_USER=value_escape("", substr($0
CLI_PASS=value_escape("", substr($0

#Check if the value is ok and print the result (On windows batc
h scripting is a problem with double quotes and can't be solved)
print $1 "=" value_escape($1, substr($0,length($1)+2));
}
#Skip to the next line, without further processing
next;
}
#Process output from the external device, used to extract the MAC address
if(length(EXTERNAL))
{
if((EXTERNAL=="Cisco_RO")
&& (($2==IP) && ($4~/([0-9a-fA-F]{4}\.?)
{3}/)))
{
EXTERNAL_OK=1;
print tolower($4), $NF > FTMP;
exit 0;
}
else if((EXTERNAL=="Cisco_FW") && (($2==IP) && ($3~/([0-9a-fA-F]{4}\.?)
{3}/)))
{
EXTERNAL_OK=1;
print tolower($3), $1 > FTMP;
exit 0;
}
else if((EXTERNAL=="Unix")
&& (($1==IP) && ($3~/([0-9a-fA-F]{2}:?){
6}/)))
{
EXTERNAL_OK=1;
for(i=0;i<=2;i++)
{
sub(/:/, "", $3);
sub(/:/, ".",$3)
}
print tolower($3), $NF > FTMP;
exit 0;
}
#Skip to the next line, without further processing
next;
}
#Error processing mechanism
if(!skip_error_check)

{
if(OS_TYPE=="Windows")
{
win_error_check($0);
}
else
{
linux_error_check($0);
}
}
#This is used to solve a issue with HTTP/HTTPS. Is intended to skip multiple que
ries to the SW if the first one fails.
if(length(TEST_HTTP))
{
#If any of those are found then is ok, otherwise there is a problem
if($0 ~/Cisco IOS Software|Cisco Systems, Inc|Configuration register is
|Processor board ID|System image file|Technical Support:|Bootstrap program is/)
{
TEST_HTTP="1";
exit 0;
}
else
{
next;
}
}
#Get the local SW Hostname
if(!length(L_HOSTNAME) && ($0 ~ / uptime is /))
{
L_HOSTNAME=$1;
skip_error_check=1;
}
#Get the local SW type/model
else if(!length(L_MODEL) && ($0 ~ /^cisco.*processor/))
{
L_MODEL=$2;
}
#Get the interface on local SW where the MAC Address in Found
else if(!length(VLAN) && (($0 ~ / ([0-9a-fA-F]{4}\.?){3} .*(DYNAMIC|STATIC|dyna
mic|static)/) && (index($0, MAC))))
{
VLAN=$1;
L_PORT=$NF;
L_PORT_PO=$NF;
if(L_PORT ~ /^Po/) {PO_PORT=1} else {PO_PORT=0}
}
#If the MAC Address is found on a Port-channel interface, lookup on all its memb
ers and get a valid physical interface used later to find the next hop from CDP
else if(($2 == L_PORT_PO"(SU)") || (inside_port_channel))
{
inside_port_channel=1;
for(i=4; i<=NF; i++)
{
if($i ~ /\(P\)/) {L_PORT=substr($i, 0, length($i)-3); inside_po
rt_channel=0; break}
}
}
#Get the next hop SW Hostname from CDP

else if(length(L_PORT) && ($0 ~ /^Device ID:/))


{
R_HOSTNAME=$NF;
}
#Get the next hop SW IP Address from CDP
else if(length(L_PORT) && ($0 ~ /IP address:/))
{
R_IP=$3;
R_IS_SW=0; #Reset device capabilities.
}
#Get the next hop capabilities to be sure that is a switch - from CDP (Exclude R
outers/IP Phones/Etc)
else if(length(L_PORT) && ($0 ~ /^Platform: [Cc]isco WS-.* Capabilities: .*Swit
ch/))
{
R_IS_SW=1;
}
#Get the local and next hop interfaces where the MAC address is found and print
the info message if there will be a next hop SW
else if(length(R_IP) && R_IS_SW && (($1 == "Interface:") && ($2 == L_PORT ","))
)
{
R_PORT=$NF;
L_PORT= (PO_PORT) ? L_PORT_PO "(" L_PORT ")" : L_PORT;
print L_HOSTNAME " - " SWIP " [" L_MODEL "] " L_PORT " -> " R_PORT " "
R_HOSTNAME " - " R_IP INFO;
print R_IP > FTMP;
exit 0;
}
#Get the interface description on the interface where the MAC is found
else if(length(L_PORT) && (($1 == L_PORT) && ($0 ~ /[ ]*(up[ ]*){2}/)))
{
gsub(/.*[ ]*(up[ ]*){2}|[\-~@#\$%\*_=\+\.]{2,}/, "");
gsub(/[ ]+/, " ");
gsub(/^ | $/, "");
L_PORT_DESC = length($1) ? " - \"" $0 "\"" : "";
exit 0;
}
}
END{
#Set HTTP/HTTPS user/pass if is not found in the config file
if(length(PASS_ESCAPE))
{
if(!length(WEB_USER))
{
print "WEB_USER=" CLI_USER;
print "WEB_PASS=" CLI_PASS;
}
exit 0;
}
#Check if the external method succeed and print fail if not
else if(length(EXTERNAL))
{
if(!length(EXTERNAL_OK))
{
print "Fail" > FTMP;
}
exit 0;
}

#Check if HTTP protocol is ok and print a error if not


else if(length(TEST_HTTP))
{
if(TEST_HTTP=="1")
{
exit 0;
}
else
{
if(!error_found)
{
err_msg("Unclassified error");
}
exit 1;
}
}
#Exit with error if there was one...
else if(error_found)
{
exit 1;
}
#If Gawk doesn't receive output from SW, display a error message.
else if(!length(L_HOSTNAME))
{
err_msg("Unclassified error");
}
#If the MAC Address is found on this SW and no CDP is related to that interface
print the info. Or print "unreachable" if the MAC is not found.
else if(!length(R_PORT))
{
MSG = length(L_PORT) ? L_PORT " (Vlan" VLAN ")" L_PORT_DESC : "- MAC un
reachable on this Switch!";
print L_HOSTNAME " - " SWIP " [" L_MODEL "] " MSG INFO;
print "Final" > FTMP;
}
exit 0;
}

You might also like