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.
call-extension
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)
extensions
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
...
huntgroup
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})
; 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(224.0.1.1)d(From ${CALLERID(number)}))
same => next,Hangup(normal_clearing)
intercom
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)
voicemail
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)
x-cisco-serviceuri
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.
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)
blfpickup
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)
gpickup
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)
opickup
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
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
dpark
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)
cfwdall
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
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)
abbrdial
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
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)
idivert
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)
cisco_callback_number
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)
...