Force calls from an extension going to a destination (eg 911) out a trunk

I am posting this as a solution, rather than a question, but if anyone has any feedback about this being likely to cause problems or if anyone has a better way to accomplish what I am trying to do, PLEASE provide feedback.

In Wazo v18 there was no provision to direct calls from an specified extension out a specified trunk. This is needed if you have satellite locations on your system where they are dialling from a physical street address other than the default physical street address which was used to register the trunk with e911 registration. In v18 this was solved with an addition to the dialplan as shown at

However, in v 20.05, this solution no longer works, so I played with the code and now have something that works. I have posted the full, heavily commented code below. If anyone has feedback on improvements, please provide.

I added, in


a file called force-trunk.conf and gave the file permissions 660 and asterisk:www-data and added to the file the following code (Note that only the last few lines are actual code; the rest is commentary.):

; Put this in a file in /etc/asterisk/extensions_extra.d/
; with permissions 660 and asterisk:www-data
; This custom handler is used to force an outgoing call out a specified trunk
; when a specified CallerID or Extension is the source of the call
; and the call is destined for a specified number (eg. 911)
; One example of this is when users in a satellite location dial 911
; In that scenario, to make sure the proper e911 service is called, you want to force a specific trunk,
; with that trunk properly registered at e911 with the street address of the satellite location.
; The normal Outgoing Calls setup uses designated trunk(s) for ALL calls from ALL extensions
; and the main trunks will be registered to the main physical street address of the system,
; but if one extension is at a different phsyical location / street address
; then 911 calls from that location must (legally in Canada) identify the correct phsyical address
; so the system must have a trunk registered to that location AND
; that trunk MUST be used for 911 calls from that location.
; Caveat: there is no failover with 911 calls when using this setup
; If the specified trunk is not avaialable, the outgoing call to 911 fails
; To miniimize the risk of failed calls for normal use,
; we also check (in the subroutinne called) to test what the destination number is
; and only force the specified trunk for specified destination numbers (ie 911 calls),
; leaving the normal outgoing call setup with failover options
; Thank you to Sylvain Boily and Jonathon Thomas for their help in getting this working
; This method identifies a range of extensions to be checked as the originator of a call
; (so for a satellite office with mutliple employees, set them each up with an extension starting with, say, 25)
; and if the originating extension is from within that range and is going to the specified destination number,
; then send the call out the specified trunk
; If we had wanted to specify an individual extension
; we could replace
; same => n(test_extension_1),ExecIf(["{XIVO_PICKUPMARK:0:2}" == “25”]?Goto(force_trunk_1,1))
; with
; same => n(test_extension_1),ExecIf(["{XIVO_PICKUPMARK:0:4}" == “2503”]?Goto(force_trunk_1,1))
; If we had wanted to specify an individual CallerID
; we could replace
; same => n(test_callerid_1),ExecIf(["{CallerIDNum::0:3}" == “201”]?Goto(force_trunk_1,1))
; with
; same => n(test_callerid_1),ExecIf(["{CallerIDNum}" == “2015551212”]?Goto(force_trunk_1,1))
; You could also specify one or more individual extensions or range of extensions by adding more tests and directives to this file
; Actual code below - edit to suit your situation
exten => s,1,NoOp(Subroutine to force calls from specified sources out specified trunks if going to specified destinations)
same => n,NoOp(Test for source equal to CallerID)
same => n(test_callerid_1),ExecIf(["{CallerIDNum::0:3}" == “201”]?Goto(force_trunk_1,1))
same => n,NoOp(Test for source equal to Extension / Line)
same => n(test_extension_1),ExecIf(["{PICKUPMARK:0:2}" == “11”]?Goto(force_trunk_1,1))
same => n(test_extension_2),ExecIf(["{PICKUPMARK:0:4}" == “1504”]?Goto(force_trunk_2,1))
same => n,Return()
exten => force_trunk_1,1,NoOp(If going to destination 911 then send out trunk 5555551212)
same => n(test_911),ExecIf(["{XIVO_DSTNUM}" == “911”]?Set(TRUNKEXTEN=${XIVO_DSTNUM}@5555551212)

same => n,Return()
exten => force_trunk_2,1,NoOp(If going to destination 911 then send out trunk 2015551212)
same => n(test_911),ExecIf(["{XIVO_DSTNUM}" == “911”]?Set(TRUNKEXTEN=${XIVO_DSTNUM}@2015551212)

same => n,Return()

Not sure why, but I had to add extra lines in the code at the end (for this post only; not in my code on my system) to force a line feed. It may have something to do with the @ character in the preceeeding line.

Blank line is NOT needed in actual code.

If this is the solution it needs to be added to the Wazo-UI. my sggestion borrowed from Fusion-PBX is to add a new box for emergency Caller id below Caller ID. Emergency Calling is to important for a long manual config for each number. Too many places for error and an error could be disastrous for your users and you.


for an updated version of how to force calls from a user out a designated trunk. The updated version:

  • uses Contexts
  • Can be done completely within the Wazo Web GUI
  • Does NOT require any manual edits to the Asterisk dialplan