Sonntag, 22. Mai 2011

Using VXML on Cisco Voice Gateways for Fax Detection and handling

One of our offices recently moved (and during that we moved the office from a pbx onto the centralized UCM). Part of the move was also a new PSTN phone number and the carrier promised to forward the old number to the new number.
Easy, huh?
Well, there was one big challgene which turned up pretty late:
While the provider was able to forward the old number, he could only forward all DIDs to the same new number.  While this was acceptable for enduser DIDs this meant some trouble for the old fax number.

Since the old fax number was quite important (orders...) we had to find a way to deal with both human callers as well as the fax messages, all coming to the same number.
We decided on using a callflow which goes like this:
  1. Play a prompt which informs the caller that the number has changes
  2. During this prompt the router should run CNG detection. This means, if it detects a T.30 fax tone we should jump to special fax handling section
  3. After the prompt, transfer the caller somewhere else

Luckily this was quite easy to implement with cisco voicexml. Let's assume the following things:
1.)The old number was 9988776600 , so forwarded calls will have a redirecting number of "9988776600"
2.)The new main number is : 1122334400
3.)The new fax number is: 1122334499

The header section just tells that this is a voicexml document

<?xml version="1.0" encoding="iso-8859-1"?>
<vxml version="2.0">

The following section is a variable assignment. We do save the value of the redirecting number of the call into the variable theRDNIS. We do this so we can later check if this call was redirected from the old number or wether it was a call to the new number.

<var name="theRDNIS" expr="session.telephone.rdnis"/>

 What follows now is the event handler for the CNG tone. If the script detects a CNG tone we do ouput a log messages (which we can output on the dateway via debug voip application vxml puts and then run a goto to the form with the name "FaxTrans".
<catch event="com.cisco.fax.cng">
   <log>!!!!!!! Got com.cisco.fax.cng !!!!!! </log>
   <goto next="#FaxTrans"/> 
</catch>

Now we move into the  form for the call Transfer
<form id="CallTransfer" scope="dialog">
   <block>
      <log>    RDNIS is  <value expr="theRDNIS"/></log>
   </block>

Now follows a block that only runs if the Redirecting number is equal to the value 9988776600
Inside of the block we play a prompt "oldoffice.au" If at any point during the prompt a CNG tone is detected, the script will jump to the CNG tone event handler above.
   <block cond="theRDNIS=='9988776600'" >
      <prompt bargein="true"> <audio src="flash:oldoffice.au"/></prompt>
      <goto next="#IVR_call"/>
      </block>
Now a form for  a transfer to the real reception number, we could also use event handlers to handle cases like busy now answer etc. (which we did in the real deployment)
   <transfer name="IVR_call" type="blind" dest="phone://1122334400" bridge="true">
      <filled>
      </filled>
   </transfer>
</form>

 Finally the fax form which initiates the final transfer of the fax to be handled via T.37. This also needs a MMOIP dialpeer on the router
<form id="FaxTrans" scope="dialog">
   <transfer name="FAX_CALL" type="blind" dest="fax://1122334499" bridge="false" />
</form>
</vxml>

So that is it, pretty easy.
To make it work, we need some config on the router as well:
First we need the config to load the vxml. If we put the script above into a file on the router flash called oldoffice.vxml we would define it like this:
application
 service oldoffice flash:oldoffice.vxml
 !

Then we need an incoming dial-peer that runs the script:

dial-peer voice 1000 pots
 service oldoffice
 incoming called-number 1122334400
!        



and finally we need a outbound mmoip dial-peer so the e-mail can be delivered somewhere:
dial-peer voice 2000 mmoip
 service fax_on_vfc_onramp_app out-bound
 destination-pattern 1122334499
 information-type fax
 session target mailto:fax@company.com
!
You will also need the normal T.37 fax config as described in the cisco docs

Dienstag, 8. März 2011

Accessing Files on a Cisco Unified Communications Manager via SFTP

Now, consider the following situation:
1.)You need to pull a lot of log files from a Cisco UCM server
2.)You can only access the UCM server via SSH/SFTP INBOUND to the UCM
or consider the following situation
1.)You need to pull a lot of log files from a Cisco UCM server
2.)You are lazy

So, is there another way to pull log files from the UCM without using RTMT and without making a outbound (CCM server to client) ssh connection?
Yes there is, even without adding users to the ucm. And it is quite easy:

Here are the steps:
1.)Obtain the Private DSA key (identity) of the UCM server:
Login via SSH (using the OS admin account)
run the following command file dump sftpdetails ../.ssh/id_dsa
You now should get something like this:
-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQDnqIguBCwLa0rC627ddmtUb8x1os3s0v9dFYItcTC2TM0KD4y9
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
nr3rhRK5dNqHV517/FWg6MQVk4JIW/0+V1MdhQiSn7jO4DWYENU0BvyLGwIVAIp9
6lqbG4Xk8GNnkiW2ANSLj5iDAoGBALObSb9jA3jmmb4E4p3jPyyW2XKqT8rl3uuN
Jc+hHJtdS/54hQPdQTEfDFKXt+FdOMl7rKT3bvG/iOZfVVJ7GDNQbWDsNRBraCsF
mfjjl1y39yu0msj1dEjhhLgYgyNAluFItRUalAgrLYNYBYxbtpjSGtUrCAwU/eqE
IAMNOTACTUALLYPOSTINGAREALKEYHERE
814QRrWx5IbKw8fXFK0i8N9xi4s6xA5Uc0xP6yq9MCTU7Y4ZMDtS1/CFZ5OsvXHw
rgKpRbfPuJ2XIKvCQV0CFV+zBJEUx5y/q9R6yF4C7WFTECLkH3oVgWUCFGT1qVPs
1Om5dP2rcfgTNOVc7wfE
-----END DSA PRIVATE KEY-----

well, that's about it.
Now copy this into a file on your computer and use a ftp client that can use identity files.
I'm on a unix machine so I just use openssh, assuming i copied the key into a file called ./ccm_dsa (you might need to set the permissions to 0600 for sftp to use the key file)
just run the following command
:~ balbler$ sftp -o IdentityFile=./ccm_dsa sftpuser@<ip of ccm>
Connecting to <IF OF CCM>...
sftp> ls 
logs                   sftp_connect.sh        sftp_knownhosts.exp    sftp_password.exp      tmp                   
sftp> cd /      
sftp> ls -la
-rw-r--r--    1 root     root          236 Mar  6 01:03 -
drwxr-xr-x   30 root     root         4096 Jun 27  2010 .
drwxr-xr-x   30 root     root         4096 Jun 27  2010 ..
-rw-r--r--    1 root     root            0 May 22  2010 .autofsck
-rwx------    1 root     root            0 May 22  2010 .hpshm_keyfile
-rw-------    1 root     root         1024 May 21  2010 .rnd
drwxrwxr-t    2 informix informix     4096 May 22  2010 INFORMIXTMP
drwxr-xr-x    2 root     root         4096 May 21  2010 CENSORED
drwxr-xr-x    2 root     root         4096 May 21  2010 CENSORED.Log
drwxr-xr-x    2 root     root         4096 May 21  2010 bin
drwxr-xr-x    3 root     root         4096 May 21  2010 boot
drwxrwxr-x    5 root     root         4096 May 21  2010 ccm
drwxr-xr-x    3 root     root         4096 May 21  2010 cm
drwxr-xr-x   11 root     root         4096 May 21  2010 common
drwxr-xr-x   12 root     root         6280 Mar  8 12:01 dev
drwxr-xr-x   46 root     root         4096 Mar  2 12:25 etc
drwxr-xr-x    4 root     root         1024 Oct 15  2007 grub
drwxr-xr-x   17 root     root         4096 Mar  2 12:25 home
-rw-r--r--    1 root     root        13199 Feb 21 11:08 infomgrlog.txt
drwxr-xr-x    2 root     root         4096 Aug 12  2004 initrd
drwxr-xr-x   12 root     root         4096 May 21  2010 lib
drwx------    2 root     root        16384 May 21  2010 lost+found
drwxr-xr-x    2 root     root         4096 Aug 12  2004 media
drwxr-xr-x    6 root     root         4096 May 21  2010 mnt
drwxr-xr-x    6 root     root         4096 May 22  2010 opt
drwxr-xr-x   25 root     root         4096 May 22  2010 partB
dr-xr-xr-x  1128 root     root            0 May 22  2010 proc
drwx------    4 root     root         4096 Jul 12  2010 root
drwxr-xr-x    2 root     root         4096 May 22  2010 sbin
drwxr-xr-x    2 root     root         4096 Aug 12  2004 selinux
drwxr-xr-x    2 root     root         4096 Aug 12  2004 srv
drwxr-xr-x    9 root     root            0 May 22  2010 sys
drwxrwxrwt   13 root     root         4096 Mar  8 15:11 tmp
drwxr-xr-x   16 root     root         4096 May 22  2010 usr
drwxr-xr-x   20 root     root         4096 May 22  2010 var
sftp>

That was easy, wasn't it?
To get the current logs, just go to:
/var/log/active
and then chose anything you need.

WARNING: This still likely might void your support with cisco (I will need to ask some cisco guys about this)
Still very helpful for some situations.

I didn't think up the SFTP part myself, so credit goes to the guys at recurity labs: http://blog.recurity-labs.com/articles/jail-breaking_cisco_unified_communication_manager/index.html

Donnerstag, 3. Februar 2011

disabling h225 CID Updates

So you have a customer who does not want to see the final transmitted number as shown in the last post.
Rather he wants to see the number that was send to the GW (e.g. in a e164 concept the one starting with a +).

Fear not, this can be done by disabling the h225 CID update during the call.
This can be set either globally:
voice service voip
no supplementary-service h225-notify cid-update 

or  on a individual dialpeer:
dial-peer voice 10
no supplementary-service h225-notify cid-update

Prefixing and number display on H323 Dial-peers for granular POTS interface selection

One of the advantages of using MGCP for GW control in UCM is that you can easily do granular routing, e.g. route out of a specific interface for calls.  With H323 and SIP the call is send to the Gateway and then the internal call routing logic (i.e. IOS dialpeers) will take over.
Let's compare the two models to make it clear what the "issue" is:
MGCP:
  • In UCM a "chassis" is configured to which multiple endpoints are attached. 
  • A endpoint is generally speaking a single interface (fxs, fxo, pri...)
  • every single endpoint is controlled by the UCM with regard to call routing logic
  • CDRs will show the specific selected endpoint

H323/SIP
  • GW is a single endpoint, identified by its IP address
  • There might be multiple Interfaces hidden behind that IP address
  • UCM does not know wether this is a CUBE or a PSTN GW
  • Dial-peer call routing logic applies on IOS GWs
  • CDRs will only show the IP of the GW

So unless one does really fancy stuff with multiple IPs on the GW UCM does not actually select the POTS interface (or a SIP trunk via CUBE) to be used but rather just speaks to a "chassis"

There are 2 main problem areas with the H323/SIP approach when used in projects
  • Granular Call routing
  • Billing

So is there some way to get granular call control  working at least for the call control part?

The requirements for the solution should be (that's what I generally need):
1.)It should be transparent to the user, e.g. he should not see which link is being used (e.g. no prefix is visible to the user)
2.)Path selection should be controlled via the UCM configuration and not via Dial-peer routing on the GW
3.)Failover should still work properly, e.g. RouteGroup redundancy inside of the Routelist can be used.

Consider the following situation:
1x normal PRI for standard PSTN Calls
1x PRI Directlink to Mobile Provider
1x SIP Trunk via CUBE

The goal is to enable selection of indiviual call directions on the UCM (rather than on the gateway itself)

So let's take this in steps:
First we need to decouple the path selection from the actual dialed number. For this we work with, (not very surprising) prefixes.
So for each Link on a GW we decide on a prefix. As an example let's take the following example:
  • Primary PSTN Link from Telco: *1
  • Directlink from mobile provider: *2
  • Alternative Provider via SIP Trunk *3
Now we create a dial-peer for each provider:
dial-peer voice 10 pots
 description Primary Link to Telco
 huntstop
 preference 1
 destination-pattern *10T
 progress_ind setup enable 3
 progress_ind alert enable 8
 progress_ind progress enable 8
 port 0/0/0:15
 forward-digits all
!
dial-peer voice 11 pots
description Directlink to Mobile
 huntstop
 preference 1
 destination-pattern *20T
 progress_ind setup enable 3
 progress_ind alert enable 8
 progress_ind progress enable 8
 port 0/0/1:15
 forward-digits all

dial-peer voice 2000 voip
description Link to SIP Provider
 destination-pattern *30T
 session protocol sipv2
 session target dns:proxy.siprovider.at
 voice-class sip bind control source-interface GigabitEthernet0/1
 voice-class sip bind media source-interface GigabitEthernet0/1
 dtmf-relay rtp-nte
 codec g711alaw

 huntstop

Notice 2 things:
We enabled huntstop on each link (there is actually a small caveat for this which I will explain in a future post)
The POTS Dialpeers will work out of the box (because the matched digits will be dropped), for the SIP dial-peer will not because of the extra *3, we will need a translation rule there.
But we are not finished yet.

On the UCM we will need to do the following:
1.)Create a Routegroup for each GW
2.)create Routelists depending on our routing requirements

When we create the RouteList and assign the Routegroup we do the following:
Assign the Routegroup to the Routelist, go into the details of the Routelist/Routegroup connection and set "prefix digits" to either *1, *2 or *3. This way we can now select the individual paths on the Gateway.
If we want to select the Directlink to the mobile provider, we would configure the RL - RG connection as shown on the following picture:


If we now make a test call there is one major caveat. Let's say we decide on sending everything starting with 0676 out the *2 Link.
Now the user will see the following number on the display of his phone:
*200676 XXX XXX

This of course is less than ideal because we might get some helpdesk calls from users because they are complaining about seeing something different then they have dialed.
This happends because the GW will send a display update via H323 during the call which will be displayed on the phone. Darn!
To get around this we slightly modify our configuration


voice translation-rule 5
 rule 1 /\*.0\(.*\)/ /\1/
!
voice translation-profile POTS-OUT
 translate called 5

voice translation-profile SIP-OUT
 translate called 5

dial-peer voice 10 pots
 translation-profile outgoing POTS-OUT
 description Primary Link to Telco
 huntstop
 preference 1
 destination-pattern *10T
 progress_ind setup enable 3
 progress_ind alert enable 8
 progress_ind progress enable 8
 port 0/0/0:15
 forward-digits all
!
dial-peer voice 11 pots
 translation-profile outgoing POTS-OUT
description Directlink to Mobile
 huntstop
 preference 1
 destination-pattern *20T
 progress_ind setup enable 3
 progress_ind alert enable 8
 progress_ind progress enable 8
 port 0/0/1:15
 forward-digits all

dial-peer voice 2000 voip
 translation-profile outgoing SIP-OUT
description Link to SIP Provider
 destination-pattern *30T
 session protocol sipv2
 session target dns:proxy.siprovider.at
 voice-class sip bind control source-interface GigabitEthernet0/1
 voice-class sip bind media source-interface GigabitEthernet0/1
 dtmf-relay rtp-nte
 codec g711alaw

 huntstop

On the POTS Dialpeers we enabled the command "forward-digits all". This means that digits matched by the destination-pattern will be forwarded rather than dropped.
This means we need now need to take care of the transformation of the called number via translation-rule and a translation-profile.
The rule is quite simple:
voice translation-rule 5
 rule 1 /\*.0\(.*\)/ /\1/

This will match a "*", then any digit, followed by a 0 and finally any number of digits. This will match all of our prefixes. Of course explicitly matching *10, *20 and so on would also be possible (the  0 is part of the match because it is used as the normal PSTN Access Code, e.g. in the US this would likely be *19, *29 and so on)

This rule is bound into the relevant translation-profiles (SIP-OUT and POTS-OUT) which then are applied to the relevant dialpeers.
If we drop the digits this way, the H323 display update will signal the "real" final called number (e..g 0676 XXX XXXX).
For the user this is ideal because he sees the actual, final called number.


Pretty easy, huh?

Dienstag, 18. Januar 2011

EMCC and Directory Syncronization: Be careful what you sync

One attractive new feature of UCM 8.x is Extension Mobility Cross Cluster (EMCC)
Extension mobility is the term used by Cisco for the ability to use a device profile to log into a EM capable phone, therefore preserving you personal settings (speed dials, your number etc.) while being on a different desk. This feature is  often used for shared desks or guest offices.

One of the caveats of EM was that one could only log into devices on a single cluster, e.g. if the organization has multiple clusters, user device profiles could not be used between clusters.

This limitation has been resolved in UCM 8.x with EMCC. EMCC allows one cluster to dynamically query "linked/trusted" clusters for a device profile.
The CCM Features Guide has a very nice diagram showing the login process.
EMCC Login Flow

There is one point which needs to be emphasized: For this to work, userids have to be unique across cluster and must not be duplicated. So if I am User "balbler" and the cluster in SJ is my home cluster and i want to do a EMCC login on the AMS cluster, my userid MUST not exist on the AMS cluster.
The reason for this is quite simple: The EMCC process will only query the remote cluster if it can not find the user in the local CCM db.

This is quite easy to do if you have a local user db.
It get's slightly more complicated if you bring LDAP integration into the picture.
DirSync allows you to sync userIDs from a LDAP directory (e.g. Active Directory or OpenLDAP) into the UCM user DB.
Most customers will have a single, global LDAP directory for the whole organization
In that case for EMCC to work, you have to make sure that usernames are not duplicated because of the sync.
There are 2 options on fulfilling this requirement:
  • If possible sync only part of the LDAP tree (a subtree)
  • Filter based on a attribute: This can be done via GUI on UCM 8.x (and was possible via sql manipulation of the ldapconfig table in prior versions)
So when planning on using EMCC and are already using LDAP Synchronisation, one needs to make sure there is a way to properly filter the users so there is no userid duplication.

Be aware that this will also mean that the ccm generated corporate directory will only contain the users from the local cluster. For a complate directory the CorpDir XML service will have to be replaced.