Tuesday, December 11, 2018

Cisco CME - Emergency Call History Notification - Part 2

Let's say you wanted to notify all phones that a Lockdown scenario has started  or 911 was dialed at this location.  We would need to find all registered phones and push out a message.

Short version...
a) Person dials the predetermined emergency number
b) CME Syslog see this event and runs the Event Manager applet
c) The CME uploads the TXT file to the Windows server and the PowerShell script sees the new file and runs the PHP script. 
d) The PHP script then reads each line of the uploaded TXT file and pushes out the XML file to the registered phones.



See the start of the event manager applet on Part 1

Find all register phones (SCCP and SIP) and add them to an variable
 action 002.60.01  cli command "show ephone registered sum | include 192.168"
 action 002.60.02 foreach line "$_cli_result" "\n"
 action 002.60.03  regexp "192\.168\....\...." "$line"
 action 002.60.04  if $_regexp_result eq "1"
 action 002.60.05   regexp "192\.168\.[0-9]+\.[0-9]+" "$line" temp_IP
 action 002.60.06   append array_IP "$temp_IP\n"
 action 002.60.07  end
 action 002.60.08 end
 action 002.61.01 cli command "show voice register pool registered | include IP address"
 action 002.61.02 foreach line "$_cli_result" "\n"
 action 002.61.03  regexp "192\.168\....\...." "$line"
 action 002.61.04  if $_regexp_result eq "1"
 action 002.61.05   regexp "192\.168\.[0-9]+\.[0-9]+" "$line" temp_IP
 action 002.61.06   append array_IP "$temp_IP\n"
 action 002.61.07  end
 action 002.61.08 end
 Send the results to a file on a TFTP server.  (In our case it's a TFTP server running on Windows Server 2016)
 action 003.01.01 set result_Final "$result_Site $result_Ext $result_Mac $result_IP $result_Called"
 action 003.01.02 set result_Notify "$result_Final\n$array_IP"
 action 003.02.01 if $result_Called eq "911"
 action 003.02.02  file open fh flash:911.txt w
 action 003.02.03  file write fh $result_Final
 action 003.02.04  file close fh
 action 003.02.05 else
 action 003.02.06  file open fh flash:Notify.txt w
 action 003.02.07  file write fh $result_Notify
 action 003.02.08  file close fh
 action 003.02.09 end

 action 003.03 cli command "configure terminal"
 action 003.04 cli command "file prompt quiet"
 action 003.05 cli command "end"
 action 003.06.01 if $result_Called eq "911"
 action 003.06.02  cli command "copy flash:911.txt tftp://eventlogger/demo911.txt"
 action 003.06.03 else
 action 003.06.04  cli command "copy flash:Notify.txt tftp://eventlogger/demoLock.txt"
 action 003.06.05 end
 action 003.07 cli command "configure terminal"
 action 003.08 cli command "no file prompt quiet"
 action 003.09 cli command "end" 
 Do something with those results.

This is were some searching on the Internet found a PowerShell script that can run commands based on different file actions. Create a new task that runs at computer startup and runs as System account.
Remove-Item c:\oss_snmp\LockDownlog.log
Remove-Item c:\oss_snmp\PHPlog.log
Remove-Item c:\tftp-root\*lock.txt
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
    $watcher = New-Object System.IO.FileSystemWatcher
    $watcher.Path = "c:\tftp-root"
    $watcher.Filter = "*lock.txt"
    $watcher.IncludeSubdirectories = $false
    $watcher.EnableRaisingEvents = $true 
### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
    $LogAction = { $path = $Event.SourceEventArgs.FullPath
                $changeType = $Event.SourceEventArgs.ChangeType
                $logline = "$(Get-Date), $changeType, $path"
                Add-content "c:\oss_snmp\LockDownlog.log" -value $logline
              }   
    $PHPAction = { php -f C:\OSS_SNMP\LockdownCMEPHones.php
$path = $Event.SourceEventArgs.FullPath
                $changeType = $Event.SourceEventArgs.ChangeType
                $logline = "$(Get-Date), $changeType, $path"
                Add-content "c:\oss_snmp\LockDownlog.log" -value $logline
              } 
### DECIDE WHICH EVENTS SHOULD BE WATCHED
    Register-ObjectEvent $watcher "Created" -Action $PHPAction
    Register-ObjectEvent $watcher "Changed" -Action $LogAction
    Register-ObjectEvent $watcher "Deleted" -Action $LogAction
    Register-ObjectEvent $watcher "Renamed" -Action $LogAction
    while ($true) {sleep 1}
Install PHP for Windows on IIS.
This will allow us to run the Push2Phone function from the Cisco IP Services development kit.
Save the below text into the PHP file mention in the above PowerShell script.
<?php
//header("refresh: 30;");
$File = 'c:\TFTP-Root\demoLock.txt';
chdir('c:\OSS_SNMP');
$School = "";
$Address = "";
$Site = "Empty";
//echo "Start\n";
if (file_exists($File))
{
//echo "found \n";
$contents = file_get_contents($File);
$lines = explode("\n", $contents);
foreach ($lines as $line)
{
if ($line === ""){
//nothing
//echo 'Nothing';
}
else
{
if (strpos($line," ") !== false){
$Found = explode(" ", $line);
$Site = substr_replace(strTOUpper($Found[0]),"",-1);
$Site = str_replace($Site,"DEMO","DEMO-SITE");
$LookupSchool = SiteLocation($Site);
$School = $LookupSchool[0];
$Address = $LookupSchool[1];
//echo "$Site \n";
$Ext = $Found[1];
$Mac = $Found[2];
$IP = $Found[3];
$Number = $Found[4];
}
else
{
$IP = $line;
$Today = date("F j, Y, g:i a");
$Textdata = "$School \n$Address\nIs in LOCKDOWN\n$Today";
set_time_limit(0); //http://php.net/manual/en/function.set-time-limit.php
$uri = "http://cmephones.emailhost.ca:8080/XML/$IP.xml";
$uid = "icxml";
$pwd = "password";
$filename = "XML/$IP.xml";
$data = "<CiscoIPPhoneText><Title>$Number called from $Ext</Title><Prompt>Sent from $Ext</Prompt><Text>$Textdata</Text></CiscoIPPhoneText>";
//echo $data;
file_put_contents($filename, $data);
push2phone($IP, $uri, $uid, $pwd);
}
}
}
}
else
{
echo "$File not found \n";
}
unlink ($File); //Remove file

function push2phone($IP, $uri, $uid, $pwd)
{
$auth = base64_encode($uid.":".$pwd);
$Chime = "Play:chime.raw";
$xml = "<CiscoIPPhoneExecute><ExecuteItem Priority=\"0\"URL=\"".$Chime."\"/><ExecuteItem Priority=\"0\"URL=\"".$uri."\"/></CiscoIPPhoneExecute>";
//echo $xml;
$xml = "XML=".urlencode($xml);
$post = "POST /CGI/Execute HTTP/1.0\r\n";
$post .= "Host: $IP\r\n";
$post .= "Authorization: Basic $auth\r\n";
$post .= "Connection: close\r\n";
$post .= "Content-Type: application/x-www-form-urlencoded\r\n";
$post .= "Content-Length: ".strlen($xml)."\r\n\r\n";
$fp = fsockopen ( $IP, 80, $errno, $errstr, 30);
$response = "";
if(!$fp){ echo "$errstr ($errno)<br>\n"; }
else
{
fputs($fp, $post.$xml);
flush();
}
//return $response;
}
function SiteLocation($Site)
{
if($Site === "DEMO-SITE"){
return array("IT South","Street Address");
}
}

?>

Monday, December 10, 2018

Cisco CME - Emergency Call History Notification - Part 1

Here is one way to monitor those 911/emergency calls on a Cisco CME system.
In a later post, I will explain how we use that demoLock.txt file to send broadcasts to other phones using the Push2Phone.php file provided by Cisco's IP Services development kit.

Using Cisco's Event Manager applets we can monitor any dial peer and send out notifications to end users.

Basic Required Settings
event manager environment _email_from it.voip@emailhost.ca
event manager environment _email_to it.voip@emailhost.ca
event manager environment _email_server mail.emailhost.ca
voice emergency response settings
 elin 5555551234

Sample dial-peers (We use an 'Emergency lockdown' number for paging)
dial-peer voice 1407 pots
 description Emergency Paging
 emergency response zone
 preference 1
 destination-pattern 1407
 port 0/1/0
 prefix ,07#
dial-peer voice 600 pots
 trunkgroup pstn-outgoing
 description 911
 emergency response zone
 preference 1
 destination-pattern 911
 forward-digits all
Create a syslog event monitor that is trigger when one of the dial peers is called.
event manager applet Emergency_Call_Out
event syslog occurs 1 pattern "E911-5-EMERGENCY_CALL_HISTORY" period 1
Find the hostname and set the destination email (if you want to use something other than what was declared in the Basic Required Settings)
 action 001      cli command "enable"
 action 001.1    foreach line "$_cli_result" "\n"
 action 001.2     regexp "#" "$line"
 action 001.3     if $_regexp_result eq "1"
 action 001.4      set result_host "$line"
 action 001.5      regexp "[A-Za-z]+\-" "$line" result_Site
 action 001.6     end
 action 001.7    end
 action 001.8    set _email_to "voipgroupnotify@emailhost.ca"

Do some regexp work to extract the "Calling number, Mac-address & IP address" of the call being placed - used for logging purposes.
 action 002.01   set result_Ext "Empty"
 action 002.02   regexp "calling number\[([0-9]+)\]" "$_syslog_msg" result_Ext
 action 002.03   regexp "([0-9]+)" "$result_Ext" result_Ext
 action 002.10   set result_Mac "Empty"
 action 002.11   cli command "show ephone telephone-number $result_Ext | include mac-address"
 action 002.12   foreach line "$_cli_result" "\n"
 action 002.13    regexp "(.*)\.(.*)\.(.*)" "$line"
 action 002.14    if $_regexp_result eq "1"
 action 002.15     regexp "....\.....\....." "$line" result_Mac
 action 002.16    end
 action 002.17   end

 action 002.20   set result_IP "Empty"
 action 002.21   cli command "show ephone $result_Mac | include IP"
 action 002.22   foreach line "$_cli_result" "\n"
 action 002.23    regexp "10\.174\....\...." "$line"
 action 002.24    if $_regexp_result eq "1"
 action 002.25     regexp "10\.174\.[0-9]+\.[0-9]+" "$line" result_IP
 action 002.26    end
 action 002.27   end
 action 002.30   if $result_Mac eq "Empty"
 action 002.31    cli command "show voice register pool telephone-number $result_Ext | include 10.174"
 action 002.32    foreach line "$_cli_result" "\n"
 action 002.33     regexp "(.*)\.(.*)\.(.*)" "$line"
 action 002.34     if $_regexp_result eq "1"
 action 002.35      regexp "....\.....\....." "$line" result_Mac
 action 002.36     end
 action 002.37     regexp "10\.174\....\...." "$line"
 action 002.38     if $_regexp_result eq "1"
 action 002.39      regexp "10\.174\.[0-9]+\.[0-9]+" "$line" result_IP
 action 002.40     end
 action 002.41    end
 action 002.42   end
Getting the "Called Number" (Regular numbers and E164 format)
 action 002.50   set result_Called "Empty"
 action 002.51   regexp "called number\[([0-9]+)\]" "$_syslog_msg" result_Called
 action 002.52   regexp "([0-9]+)" "$result_Called" result_Called
 action 002.53  if $result_Called eq "Empty"
 action 002.53.01 regexp "called number\[\+([0-9]+)\]" "$_syslog_msg" result_Called
 action 002.53.02 regexp "([0-9]+)" "$result_Called" result_Called
 action 002.53.03 end
 Copy the results to the flash
 action 003.01.01 set result_Final "$result_Site $result_Ext $result_Mac $result_IP $result_Called"
 action 003.02.01 file open fh flash:911.txt w
 action 003.02.02 file write fh $result_Final
 action 003.02.03 file close fh
Copy to an offsite TFTP server. (The "no file prompt quiet" - prevents prompt for file names)
 action 003.03 cli command "configure terminal"
 action 003.04 cli command "file prompt quiet"
 action 003.05 cli command "end"
 action 003.06.01 if $result_Called eq "911"
 action 003.06.02  cli command "copy flash:911.txt tftp://eventlogger/demo911.txt"
 action 003.06.03 else
 action 003.06.04  cli command "copy flash:911.txt tftp://eventlogger/demoLock.txt"
 action 003.06.05 end
 action 003.07 cli command "configure terminal"
 action 003.08 cli command "no file prompt quiet"
 action 003.09 cli command "end"
 Send an email with the information
 action 003.10  mail server "$_email_server" to "$_email_to" from "$_email_from" subject "$result_host $_event_pub_time: Emergency call out $result_Called" body "Extension $result_Ext called $result_Called. Notification was sent to phones."