Using Sonus SBC1k/2k AD Lookup to Block Outbound CallerID

The AD lookup feature in the Sonus SBC is an incredibly powerful and often under-utilised feature. I’ve written of it before, and my peer Luca Vitali has posted another example of its usefulness this week. That led to a Twitter conversation and what might yet turn into a bit of a competition to see who can come up with the “best” use of the feature. ;-) For my contribution I’ve figured for some time that it should be possible to use the AD lookup outbound, as Luca has done, to change the call handling and in this case suppress CallerID for certain users.

The old way

The old way was pretty ugly. In the Transformation Table that handles your outbound calls you’d simply add an entry that checked if the Calling Address/Number matched that of a given user and if true set the Calling Number Presentation flag to “Restricted”:

before

(If you’re SIP trunking to your carrier you’ll probably just strip the Calling Address/Number).

It worked, but its obvious weakness is that it requires intervention from the IT/Comms team to manage, and as the number of users grows the table’s going to get out of hand.

(Note that the image above is an incomplete mock-up. You would have other entries in the transformation table to ensure the Calling and Called numbers are correctly formatted for your carrier, etc).

Using AD lookups

Using AD lookups this ceases to be an IT/Comms problem. All “someone” needs to do is set an appropriate flag in AD and the user’s calls will automatically go to the PSTN as “Private Number”. For bonus points, this also works consistently across multiple gateways and/or multiple sites!

Here’s how.

I’ve gone with “Department” as the AD field I wish to use for my trigger, but you can of course use another, maybe “comment” or “info”. Whatever. If you’ve not previously enabled AD lookups in the Sonus, navigate to Auth and Directory Services / Active Directory / Domain Controllers and add a DC. You’re going to need a basic AD account for the Sonus to authenticate as. Depending upon the ultimate complexity of your AD lookups it might be better to change the “LDAP Query” to “msRTCSIP-Line=*”.

DCTable-edit2

Now jump to the adjoining “Configuration” element and set it like this:

ADConfiguration2

If yours is a vast AD don’t leave the Search Scope at the top of the tree, but drill down to where the users live.

I like to add “displayName” into the list here purely because it makes life easier when you’re troubleshooting – this way when you run a test of AD and manage to pull a record it’ll tell you WHO the user is.

Now just create a copy of your EXISTING outgoing Transformation Table and add this extra content:

TransformationTable-2lines

With some clever logic we can get away with only TWO lines to detect AD value and set the flag to block CLID:

  1. On the LHS of the first it performs the AD lookup, in this case looking up the user’s “telephoneNumber” field based upon the Calling Address/Number that’s coming from Lync. That pulls this user’s record (and all the other parameters we specified in the AD Configuration earlier) for use by this table.Assuming we find a match on the LHS – and this is expected for all correctly-configured “in-house” users – the RHS sticks the value of “finance” into “User Value 1”.
  2. On the LHS of the second line we test if what we just stored in User value 1 is a match with the user’s AD department. If it is we set the CLID Presentation flag to “Restricted”. That’s it!

A More Complex Table

There are a few optional or advanced steps:

  • You may choose to do some digit manipulation in the first line and test against the caller’s msRTCSIP-Line instead, and for this we’ll need to invoke another variable.
  • If you’re going to use this new transformation table as the basis for your sole outgoing routing table entry you’ll need to add dummy tests of User Value 1 and User Value 2 that ALWAYS return a true result. The trap here is that whilst the “User Value” test is of Match Type “Optional”, there MUST always be at least one test of User Value ‘n’ that returns a true result before the table can possibly ever be true.

TransformationTable-fancy

The results

Here are some traces showing the routing process through the Transformation Table based upon the different input scenarios. In all cases the table is true and its related route entry will be chosen, but only one call will be set to block its CallerID.

Annoyingly, the trace doesn’t show it actioning the change of Calling Number Presentation, but the attached images (captured from the “LX” app) show that the resulting ISDN SETUP message *does* have the setting as expected.

Line URI matches in AD & department = “finance”

INFO (callrouter.cpp:2198) - Handling route request.
INFO (callrouter.cpp:2277) - Using table LAB: from Lync (3) to route call.
INFO (callrouter.cpp:2353) - Rule Call to Telstra - Block CLID (3.1(2)) being tested for selection.
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Reformat Calling number (5.1(5)).
DEBUG (translation.cpp:653) - Successful regex match of "tfCallingNumber" field for "(\+.*)(\d{4})$" (updated "(\+.*)(\d{4})$") with input of "+61270001234"
DEBUG (translation.cpp:698) - Regex replacement output of "tfUserValue2" field is "+61270001234;ext=1234"
INFO (translation.cpp:1255) - Doing AD lookup for field 'msRTCSIP-Line' with value '+61270001234;ext=1234'
DEBUG (callrouter.cpp:3813) - Got AD lookup response with 4 field/value pairs.
INFO (callrouter.cpp:2198) - Handling route request.
DEBUG (callrouter.cpp:2201) - Using AD lookup response in request.
INFO (callrouter.cpp:2277) - Using table LAB: from Lync (3) to route call.
INFO (callrouter.cpp:2353) - Rule Call to Telstra - Block CLID (3.1(2)) being tested for selection.
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Lookup calling number (5.2(6)).
DEBUG (translation.cpp:635) - non wildcard AD, proceed as normal"
DEBUG (translation.cpp:653) - Successful regex match of "tfUserValue2" field for "=msRTCSIP-Line=" (updated "\+61270001234;ext=1234") with input of "+61270001234;ext=1234"
DEBUG (translation.cpp:698) - Regex replacement output of "tfUserValue2" field is "+61270001234;ext=1234"
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Initialise the variable (5.3(7)).
DEBUG (translation.cpp:653) - Successful regex match of "tfCallingNumber" field for "(.*)" (updated "(.*)") with input of "+61270001234"
DEBUG (translation.cpp:698) - Regex replacement output of "tfUserValue1" field is "finance"
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Test user's account (5.4(3)).
DEBUG (translation.cpp:635) - non wildcard AD, proceed as normal
DEBUG (translation.cpp:653) - Successful regex match of "tfUserValue1" field for "=department=" (updated "finance") with input of "finance"
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Always $true (5.5(4)).
DEBUG (translation.cpp:653) - Successful regex match of "tfUserValue1" field for "(.*)" (updated "(.*)") with input of "finance"
DEBUG (translation.cpp:698) - Regex replacement output of "tfUserValue1" field is "finance"
INFO (callrouter.cpp:2410) - Successful route request with entry Call to Telstra - Block CLID (3.1(2))

ISDN-Setup-Jessica-Edit

Line URI matches in AD & department = null

INFO (callrouter.cpp:2198) - Handling route request.
INFO (callrouter.cpp:2277) - Using table LAB: from Lync (3) to route call.
INFO (callrouter.cpp:2353) - Rule Call to Telstra - Block CLID (3.1(2)) being tested for selection.
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Reformat Calling number (5.1(5)).
DEBUG (translation.cpp:653) - Successful regex match of "tfCallingNumber" field for "(\+.*)(\d{4})$" (updated "(\+.*)(\d{4})$") with input of "+61270001223"
DEBUG (translation.cpp:698) - Regex replacement output of "tfUserValue2" field is "+61270001223;ext=1223"
INFO (translation.cpp:1255) - Doing AD lookup for field 'msRTCSIP-Line' with value '+61270001223;ext=1223'
DEBUG (callrouter.cpp:3813) - Got AD lookup response with 3 field/value pairs.
INFO (callrouter.cpp:2198) - Handling route request.
DEBUG (callrouter.cpp:2201) - Using AD lookup response in request.
INFO (callrouter.cpp:2277) - Using table LAB: from Lync (3) to route call.
INFO (callrouter.cpp:2353) - Rule Call to Telstra - Block CLID (3.1(2)) being tested for selection.
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Lookup calling number (5.2(6)).
DEBUG (translation.cpp:635) - non wildcard AD, proceed as normal"
DEBUG (translation.cpp:653) - Successful regex match of "tfUserValue2" field for "=msRTCSIP-Line=" (updated "\+61270001223;ext=1223") with input of "+61270001223;ext=1223"
DEBUG (translation.cpp:698) - Regex replacement output of "tfUserValue2" field is "+61270001223;ext=1223"
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Initialise the variable (5.3(7)).
DEBUG (translation.cpp:653) - Successful regex match of "tfCallingNumber" field for "(.*)" (updated "(.*)") with input of "+61270001223"
DEBUG (translation.cpp:698) - Regex replacement output of "tfUserValue1" field is "finance"
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Test user's account (5.4(3)).
DEBUG (translation.cpp:635) - non wildcard AD, proceed as normal
DEBUG (translation.cpp:649) - Failed regex match of "tfUserValue1" field for "=department=" (updated "") with input of "finance"
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Always $true (5.5(4)).
DEBUG (translation.cpp:653) - Successful regex match of "tfUserValue1" field for "(.*)" (updated "(.*)") with input of "finance"
DEBUG (translation.cpp:698) - Regex replacement output of "tfUserValue1" field is "finance"
INFO (callrouter.cpp:2410) - Successful route request with entry Call to Telstra - Block CLID (3.1(2))

ISDN-Setup-Greig-edit

Line URI not found in AD

INFO (callrouter.cpp:2198) - Handling route request.
INFO (callrouter.cpp:2277) - Using table LAB: from Lync (3) to route call.
INFO (callrouter.cpp:2353) - Rule Call to Telstra - Block CLID (3.1(2)) being tested for selection.
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Reformat Calling number (5.1(5)).
DEBUG (translation.cpp:653) - Successful regex match of "tfCallingNumber" field for "(\+.*)(\d{4})$" (updated "(\+.*)(\d{4})$") with input of "+61270001263"
DEBUG (translation.cpp:698) - Regex replacement output of "tfUserValue2" field is "+61270001263;ext=1263"
INFO (translation.cpp:1255) - Doing AD lookup for field 'msRTCSIP-Line' with value '+61270001263;ext=1263'
DEBUG (callrouter.cpp:3813) - Got AD lookup response with 1 field/value pairs.
INFO (callrouter.cpp:2198) - Handling route request.
DEBUG (callrouter.cpp:2201) - Using AD lookup response in request.
INFO (callrouter.cpp:2277) - Using table LAB: from Lync (3) to route call.
INFO (callrouter.cpp:2353) - Rule Call to Telstra - Block CLID (3.1(2)) being tested for selection.
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Lookup calling number (5.2(6)).
DEBUG (translation.cpp:635) - non wildcard AD, proceed as normal"
DEBUG (translation.cpp:649) - Failed regex match of "tfUserValue2" field for "=msRTCSIP-Line=" (updated ") with input of "+61270001263;ext=1263"
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Initialise the variable (5.3(7)).
DEBUG (translation.cpp:653) - Successful regex match of "tfCallingNumber" field for "(.*)" (updated "(.*)") with input of "+61270001263"
DEBUG (translation.cpp:698) - Regex replacement output of "tfUserValue1" field is "finance"
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Test user's account (5.4(3)).
DEBUG (translation.cpp:635) - non wildcard AD, proceed as normal
DEBUG (translation.cpp:649) - Failed regex match of "tfUserValue1" field for "=department=" (updated "") with input of "finance"
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Always $true (5.5(4)).
DEBUG (translation.cpp:653) - Successful regex match of "tfUserValue1" field for "(.*)" (updated "(.*)") with input of "finance"
DEBUG (translation.cpp:698) - Regex replacement output of "tfUserValue1" field is "finance"
DEBUG (translation.cpp:1342) - Performing OPTIONAL transformation using entry Always $true (5.6(8)).
DEBUG (translation.cpp:653) - Successful regex match of "tfUserValue2" field for "(.*)" (updated "(.*)") with input of "+61270001263;ext=1263"
DEBUG (translation.cpp:698) - Regex replacement output of "tfUserValue2" field is "+61270001263;ext=1263"
INFO (callrouter.cpp:2410) - Successful route request with entry Call to Telstra - Block CLID (3.1(2))

ISDN-Setup-Chode-edit

What else can it do?

If you’ve thought of some other clever uses of AD lookups, please post them in the comments below.

– Greig.

Postscript

Justin O’Meara posted a slightly different approach in the comments below, and was kind enough to send me a screen-grab:

ExampleFrmJustin

3 Comments

  1. Hello Greg,

    Great article, I have been meaning to document this, but never got around to it.

    A small modification we do is below: (I Can’t Paste Picture but the below is transformation Table)

    Input Input Value Output Output Value Match Type
    Calling Address/Number =msRTCSIP-Line= Calling Address/Number =ipPhone= Optional
    Calling Address/Number (Blocked) Calling Number Presnetation Restricted Optional
    Calling Address/Number (Blocked) Calling Address/Number 393485000 Optional
    Calling Address/Number \+61(.*) Calling Address/Number 0\1 Optional

    Notes:
    We use “ipPhone” AD field but can be any field as you mentioned
    We let Customer know to put one of three options in “ipPhone” field:
    1. Nothing (Leave AD Field Blank) this will display Lync Number as outbound CLI
    2. Put in the number you want to display in E.164 format. This will change outbound CLI to this number (Great for Response Group Members who want to display the RGS Number)
    3. Type the word “Blocked” – This will send out no number as CLI.

    • Great post Greig!

      Justin, only issue I would have with your approach is the possibility of an incorrect number being entered into the ipPhone field. With some SIP providers, an incorrect Calling Number would result in a dropped call. Perhaps updating the last transformation entry to be more specific? i.e. match only number ranges the business owns? If that fails pass pilot number

Leave a Reply

Your email address will not be published. Required fields are marked *

... and please just confirm for me that you're not a bot first: Time limit is exhausted. Please reload the CAPTCHA.

This site uses Akismet to reduce spam. Learn how your comment data is processed.