Dialplan Extensions

Example extension dialplan configuration sections in extensions.conf. Phone features such as call-forwarding, pickup and parking require x-cisco-serviceuri extensions to be configured.


Context to call a SIP phone extension. Call-forwarding and Alert-Info as well as an optional voice mailbox is supported.

[call-extension] exten => _X.,1,Set(PEERNAME=${EXTEN}) ; By manually checking for call-forwarding, the call can be forwarded even if the phone is unregistered same => next,Set(CALLFORWARD=${SIPPEER(${PEERNAME},callforward)}) same => next,GotoIf($[${LEN(${CALLFORWARD})} != 0]?callforward,1) same => next,Set(MAILBOX=${SIPPEER(${PEERNAME},mailbox)}) ; Phones can be made to play a different ring using the Alert-Info header, see Ring Tones for examples same => next,ExecIf($[${LEN(${ALERT_INFO})} != 0]?SIPAddHeader(Alert-Info: <${ALERT_INFO}>)) same => next,Dial(SIP/${PEERNAME},30) same => next,Goto(${TOLOWER(${DIALSTATUS})},1) ; Cisco SIP phones support displaying diversion information exten => callforward,1,SIPAddHeader(Diversion: "${SIPPEER(${PEERNAME},callerid_name)}" <sip:${SIPPEER(${PEERNAME},callerid_num)}@localhost>\;screen=yes\;privacy=off) same => next,Goto(extensions,${CALLFORWARD},1) ; If ${MAILBOX} is empty send congestion, otherwise go to voicemail extension below exten => congestion,1,ExecIf($[${LEN(${MAILBOX})} = 0]?Congestion(10)) same => next,Set(GREETING=u) same => next,Goto(voicemail,1) ; If ${MAILBOX} is empty send busy, otherwise go to voicemail extension below exten => busy,1,ExecIf($[${LEN(${MAILBOX})} = 0]?Busy(10)) same => next,Set(GREETING=b) same => next,Goto(voicemail,1) exten => noanswer,1,Goto(congestion,1) exten => chanunavail,1,Goto(congestion,1) exten => voicemail,1,Answer() same => next,Wait(0.5) same => next,VoiceMail(${MAILBOX},${GREETING}) same => next,Hangup(normal_clearing)


Incoming context for local phone extensions. Note: when defining a hint the peer name needs to be specified twice as there are two independant states, the device state and the presence state.

[extensions] exten => 301,1,Goto(call-extension,${EXTEN},1) ; Note the duplication of the hint peername same => hint,SIP/301,SIP/301 exten => 302,1,Goto(call-extension,${EXTEN},1) same => hint,SIP/302,SIP/302 exten => 303,1,Goto(call-extension,${EXTEN},1) same => hint,SIP/303,SIP/303 ...


Hunt-group login. Ring only those peers that are logged into the hunt-group.

; Clear dial group first exten => 370,1,Set(DIALGROUP(huntgroup)=) same => next,Set(PEERNAMES=301&302&303) same => next,While($[${LEN(${PEERNAMES})} != 0]) same => next,Set(PEERNAME=${SHIFT(PEERNAMES,&)}) ; Check if peer is logged-in to the hunt group and add them to the dial group if they are same => next,ExecIf($[${SIPPEER(${PEERNAME},huntgroup)} = yes]?Set(DIALGROUP(huntgroup,add)=SIP/${PEERNAME})) same => next,EndWhile() ; Send congestion if the dial group is empty same => next,ExecIf($[${LEN(${DIALGROUP(huntgroup)})} = 0]?Congestion(10)) same => next,Dial(${DIALGROUP(huntgroup)},30,i) same => next,Hangup(${HANGUPCAUSE})


Page a group of phones using the RTP streaming API.

; Only allow one page at a time exten => 380,1,Set(GROUP()=paging) same => next,ExecIf($[${GROUP_COUNT(paging)} != 1]?Busy(10)) ; Multicast audio mode is enabled using the m() option same => next,SIPCiscoPage(301&302&303,om( ${CALLERID(number)})) same => next,Hangup(normal_clearing)


Call the intercom line on multiple phones. Intercom is specified as a line key. See paging for how to page phones without requiring an intercom line.

; Clear dial group first exten => 390,1,Set(DIALGROUP(intercom)=) ; The list of SIP peers and their associated intercom line peer. List could be dynamically specified using EVAL() or DB() allowing for multiple intercom groups. same => next,Set(PEERNAMES=301/391&302/392&303/393) same => next,While($[${LEN(${PEERNAMES})} != 0]) same => next,Set(PEERNAME=${SHIFT(PEERNAMES,/)}) same => next,Set(INTERCOM_PEERNAME=${SHIFT(PEERNAMES,&)}) same => next,ExecIf($[${DEVICE_STATE(SIP/${PEERNAME})} = NOT_INUSE]?Set(DIALGROUP(intercom,add)=SIP/${INTERCOM_PEERNAME})) same => next,EndWhile() same => next,ExecIf($[${LEN(${DIALGROUP(intercom)})} = 0]?Busy(10)) same => next,Page(${DIALGROUP(intercom)},is,3) same => next,Hangup(normal_clearing)


Extension for the messages (voicemail) button, set by <messagesNumber> as part of the line key definition.

exten => 399,1,Set(CONNECTEDLINE(all)="Voice Mail" <${EXTEN}>) same => next,Answer() same => next,Wait(0.5) same => next,Set(MAILBOX=${SIPPEER(${CHANNEL(peername)},mailbox)}) same => next,VoiceMailMain(${MAILBOX},s) same => next,Hangup(normal_clearing)


Dialplan features used by the Cisco phones are prefixed with x-cisco-serviceuri-, start by stripping it off. Note: x needs to be surrounded by [] otherwise it will be interpreted as to match any digit. Available feature extensions are listed below.

exten => _[x]-cisco-serviceuri-.,1,Goto(${EXTEN:19},1)


Call Pickup. Hangup with normal_circuit_congestion which maps to SIP cause 503 so that No call available for pickup appears on the phone.

exten => pickup,1,Pickup() same => next,Hangup(normal_circuit_congestion)


Busy Lamp Field Directed Call Pickup, ${EXTEN:10} is the number specified as the <speedDialNumber> in a BLF speed-dial line key definition, also needs to have a matching subscribe entry in sip.conf.

exten => _blfpickup-.,1,PickupChan(SIP/${EXTEN:10}) same => next,Hangup(normal_circuit_congestion)


Group Call Pickup, manually sets the pickup extension or group.

; Try pickup on channel first exten => _gpickup-.,1,PickupChan(SIP/${EXTEN:8}) ; Otherwise, treat exten as pickup group same => next,Set(CHANNEL(pickupgroup)=${EXTEN:8}) same => next,Pickup() same => next,Hangup(normal_circut_congestion)


Other Call Pickup, example uses ${OTHERPICKUPGROUP} which is set in the phone's sip.conf. entry.

exten => opickup,1,Set(CHANNEL(pickupgroup)=${OTHERPICKUPGROUP}) same => next,Pickup() same => next,Hangup(normal_circut_congestion)


Park Call. You can omit the park exten if you have parkexten set to park in res_parking.conf. Note: the extension priority of the Park application must be 1.

; If the parked call isn't retrieved in 60 seconds it will be sent to extension 370 exten => park,1,Park(default,st(60)T(50)c(extensions,370,1)) ; Remember to include the parked calls context include => parked-calls


Directed BLF Call Park, blind-transfers the current call to this extension. ${EXTEN:6} is the number specified as the <speedDialNumber> in a BLF Directed Call Park line key definition, also needs to have a matching subscribe entry in sip.conf. The dpark prefix is only used when that parking extension is not in use, otherwise it uses the optional <retrievalPrefix>.

exten => _dpark-.,1,Set(PARKINGEXTEN=${EXTEN:6}) same => next,Goto(park,1)


Call Forwarding, you can reject invalid forwarding target extensions by hanging up with normal_circuit_congestion which maps to SIP cause 503.

; Enable call-forwarding exten => _cfwdall-.,1,Answer() same => next,Set(SIPPEER(${CHANNEL(peername)},callforward)=${EXTEN:8}) same => next,Hangup(normal_clearing) ; Disable call-forwarding exten => cfwdall,1,Answer() same => next,Set(SIPPEER(${CHANNEL(peername)},callforward)=) same => next,Hangup(normal_clearing)


Record call, inbound and outbound legs are recorded separately so ConfBridge() is used to merge them together.

exten => record,1,Answer() same => next,Wait(0.5) same => next,Set(CONFBRIDGE(bridge,record_conference)=yes) same => next,Set(CONFBRIDGE(bridge,record_file)=${RECORD_PEERNAME}) same => next,Set(CONFBRIDGE(user,quiet)=yes) ; Other channel variables available are ${RECORD_CHANNEL} and ${RECORD_DIRECTION}. same => next,ConfBridge(${RECORD_UNIQUEID}) same => next,Hangup(normal_clearing)


Abbrievated (or speed) dials, soft key is available from the dial number screen. Example uses ${SPEEDDIAL<X>} which is set in the phone's sip.conf entry.

exten => _abbrdial-.,1,Set(SPEEDDIAL=${EVAL(SPEEDDIAL${EXTEN:9})}) same => next,GotoIf($[${LEN(${SPEEDDIAL})} != 0]?extensions,${SPEEDDIAL},1) same => next,Hangup(unallocated)


Meetme Conferencing, used to detect creation of a conference bridge as opposed to just joining one.

; Only allow creation of conference bridge if no one else has first exten => _meetme-36X,1,ExecIf($[${CONFBRIDGE_INFO(${EXTEN:7},parties)} != 0]?Hangup(normal_circuit_congestion)) same => next,Set(CONFBRIDGE(bridge,template)=default_bridge) same => next,Set(CONFBRIDGE(user,template)=default_user) same => next,Set(CONFBRIDGE(user,admin)=yes) same => next,ConfBridge(${EXTEN:7}) same => next,Hangup(normal_clearing) ; Reject calls to conference bridges that haven't been created exten => _36X,1,ExecIf($[${CONFBRIDGE_INFO(${EXTEN},parties)} = 0]?Hangup(unallocated)) same => next,Set(CONFBRIDGE(bridge,template)=default_bridge) same => next,Set(CONFBRIDGE(user,template)=default_user) same => next,Set(CONFBRIDGE(user,admin)=no) same => next,ConfBridge(${EXTEN}) same => next,Hangup(normal_clearing)


Divert (Connected), allow call to be diverted to voicemail after being answered.

exten => idivert,1,Answer() same => next,Wait(0.5) same => next,Set(MAILBOX=${SIPPEER(${IDIVERT_PEERNAME},mailbox)}) same => next,VoiceMail(${MAILBOX},b) same => next,Hangup(normal_clearing)


Specifies the number the phone stores in the call history without modifying the caller-ID number. Example use is to include a prefix required for an outside line so it can be dialed unedited from the call history entry.

; If dialing outside numbers requires that they be prefixed with a '1' exten => _X.,1,Set(_CISCO_CALLBACK_NUMBER=1${CALLERID(number)}) same => next,Dial(SIP/${EXTEN},30) ...