At Kloud we had an interesting chat amongst the UC group on how to best implement call blocking/screening on a Sonus Session Border Controller 1000/2000. We proceeded to trial various methods including a well documented ‘Action Set’ scenario, which proved to be unreliable in our implementation. It was from this we looked to a simpler method that I will share with you in this article.
The process to block a call will be to use a Call Route Type with ‘deny’ action as the destination type, rather than the standard process of the destination being a FXS, FXO or SIP signalling group. Sounds simple enough.
The high level tasks are:
- Create a Transformation Table
- Create a Call Route Entry
- Assign the Transformation Table to the Call Route Entry
- Assign the Call Route Entry to a Route Table
Create a Transformation Table
Create a Transformation Table, this will be populated with either calling or called address that you wish to block based on your scenario. I’ve created a table that will match a known calling address that is to be blocked. The basis of my table logic is if a call is matched set a value to equal 1. Once the call has finished the logic in the table sequence and the value is 1 then a mandatory match is made and the table becomes true/successful.
Update: My good friend Greig and I had a conversation about this table and we agreed that you don’t need this third line entry. I had the third line to make the call logging simple when searching for the specific string for the value 2 ‘Block’. Really I could remove it.
If a Transformation Table only contains multiple entries for a single Input Field Type (e.g. Calling Number above), and all of entries have a Match Type of Optional, then the table is true if any one of the transformations succeed.
Create a Call Route Entry
This step is where the magic happens and I will admit I have never toggled this drop down menu until this process. You can create a call route destination type with a ‘deny’, generally speaking as a voice consultant we are trying to complete calls not stop. Create a Call Route Entry that has the following specific settings:
- Transformation Table = Block Calls (table from above step)
- Destination Type = Deny
- Q.850 Cause Code = 21: Call Rejected
Assign the Transformation Table to a Route Table
Assign the Transformation Table to the Route Table that the call originates from:
Testing
The logic of the transformation table is as follows;
- The table gets processed for an inbound call session
-
A Calling Number (tfCallingNumber) field gets matched via regex we have assigned in a line entry
- IF TRUE – The output field User Value 1 (tfSGUserValue1) gets updated to the value ‘1’
-
A mandatory entry of User Value (tfSGUserValue1) equals 1 is matched in a line entry
- IF TRUE – The output field User Value 2 (tfUserValue2) is now ‘Block’
- Table is successfully matched based on mandatory assignment with User Value 1
- Process the session with Route Table Entry ‘Block Calls’
- The session will be denied with code 21 Rejected in the session info
Below is a trace of an inbound call session using the LX logging tool (above steps highlighted below)
Line 280: com.sonus.sbc.route.libcommon DEBUG (AFSessionManagementLayer.cpp:650) - SMConnection: Received REQ: id=12:47657/32769/0 session bit=1 moredata bit=0 message=MSG_CR_ROUTE
Line 281: com.sonus.sbc.route INFO (callrouter.cpp:2199) - Handling route request.
Line 282: com.sonus.sbc.route INFO (callrouter.cpp:2278) - Using table From PSTN (2) to route call.
Line 283: com.sonus.sbc.route INFO (callrouter.cpp:2354) - Rule Block Calls (2.1(3)) being tested for selection.
Line 284: com.sonus.sbc.route DEBUG (translation.cpp:1416) - Performing OPTIONAL transformation using entry User Value 0 (9.1(3)).
Line 285: com.sonus.sbc.route DEBUG (translation.cpp:704) - Successful regex match of "tfCallingNumber" field for "(.*)" (updated "(.*)") with input of "411111111"
Line 286: com.sonus.sbc.route DEBUG (translation.cpp:749) - Regex replacement output of "tfSGUserValue1" field is "0"
Line 287: com.sonus.sbc.route DEBUG (translation.cpp:1416) - Performing OPTIONAL transformation using entry Block ID (9.2(1)).
Line 288: com.sonus.sbc.route DEBUG (translation.cpp:704) - Successful regex match of "tfCallingNumber" field for "411111111" (updated "411111111") with input of "411111111"
Line 289: com.sonus.sbc.route DEBUG (translation.cpp:749) - Regex replacement output of "tfUserValue1" field is "1"
Line 290: com.sonus.sbc.route DEBUG (translation.cpp:1416) - Performing OPTIONAL transformation using entry Block ID (9.3(2)).
Line 291: com.sonus.sbc.route DEBUG (translation.cpp:700) - Failed regex match of "tfCallingNumber" field for "881111111" (updated "881111111") with input of "411111111"
Line 292: com.sonus.sbc.route DEBUG (translation.cpp:1416) - Performing MANDATORY transformation using entry User Value 1 True (9.4(4)).
Line 293: com.sonus.sbc.route DEBUG (translation.cpp:704) - Successful regex match of "tfUserValue1" field for "1" (updated "1") with input of "1"
Line 294: com.sonus.sbc.route DEBUG (translation.cpp:749) - Regex replacement output of "tfUserValue2" field is "Block"
Line 295: com.sonus.sbc.route INFO (translation.cpp:1493) - Transformation table(Block Calls:9) is a SUCCESS
Line 296: com.sonus.sbc.route INFO (callrouter.cpp:2412) - Successful route request with entry Block Calls (2.1(3))
Line 297: com.sonus.sbc.route.libcommon DEBUG (AFSessionManagementLayer.cpp:1984) - Sending RSP: state=1 session id=12:47657/32769/0 message=MSG_CR_ROUTE_ACK msg len=557 end session=0 sessions={lvl=1}<parent>0x11000023|0x16721c-[this]0x11013650|0x12f140. Process ID 5912
Line 305: com.sonus.sbc.route.libcommon DEBUG (AFSessionManagementLayer.cpp:1016) - SMConnection (0x167208): Received INFO: session id=12:47657/0/0 message=MSG_CR_CALLREPORT end session=1, moredata=0
Job Done
This is a very simple approach to an annoyance that we all could face at some stage. I’m sure there are many other ways to implement a call scenario like this, but I do enjoy the beauty in this simplicity. By using the standard call route logic of the Sonus we haven’t introduced anything new to the call flow procedure. I’d estimate that a implementation like above would take about 10-15 minutes once you know what you would like to block.