If you use this setup a phone can dial *21*<number> for immediate redirect or *61*<number> for delayed redirect, and #21# or #61# to cancel the setting.
If you need help understanding how the variables used in these examples work, have a look at Asterisk variables. (Macro arguments can be referenced along with an offset, like so: exten => s,1,Set(CFIM=${DB(CFIM/${ARG1:-4})})).
Abbreviations used
- CFIM: Call forward database family for labels in Asterisk database.
- CFBS: Call forward when busy database family for labels in Asterisk database
Example 1
[macro-stdexten]
;
; Standard extension macro (with call forwarding):
; ${ARG1} - Extension(we could have used ${MACRO_EXTEN} here as well
; ${ARG2} - Device(s) to ring
;
exten => s,1,((Asterisk cmd DBget|DBget))(temp=CFIM/${ARG1}) ; Get CFIM key, if not existing, goto 102
exten => s,2,((Asterisk cmd Dial|Dial))(Local/${temp}@pbx/n) ; Unconditional forward
exten => s,3,Dial(${ARG2},20) ; 20sec timeout
exten => s,4,DBget(temp=CFBS/${ARG1}) ; Get CFBS key, if not existing, goto 105
exten => s,5,Dial(Local/${temp}@pbx/n) ; Forward on busy or unavailable
; No CFIM key
exten => s,102,Goto(s,3)
; No CFBS key - voicemail ?
exten => s,105,Busy
Asterisk 1.2
[macro-stdexten]
;
; Standard extension macro (with call forwarding):
; ${ARG1} - Extension(we could have used ${MACRO_EXTEN} here as well
; ${ARG2} - Device(s) to ring
;
exten => s,1,Set(temp=${DB(CFIM/${ARG1})})
exten => s,n,GotoIf(${temp}?cfim:nocfim)
exten => s,n(cfim),Dial(Local/${temp}@default/n) ; Unconditional forward
exten => s,n(nocfim),NoOp
exten => s,n,Dial(${ARG2},15) ; 15sec timeout
exten => s,n,Set(temp=${DB(CFBS/${ARG1})})
exten => s,n,GotoIf(${temp}?cfbs:nocfbs)
exten => s,n(cfbs),Dial(Local/${temp}@default/n) ; Forward on busy or unavailable
exten => s,n(nocfbs),Busy
Notes
- This macro reads variables stored in the Asterisk database
- The macro executes ‘Dial(Local/<number>@pbx)’ if a redirection number is found. This implies the number that was selected is dialable from the [pbx] context. You should probably modify this. (If you only want outbound redirect this could be Dial(Zap/1/<number>) for instance)
- If the DBget does not find a key, it exits with the result code 101, making the next step in the dial plan the current priority+101
Example 2
[apps]
; Unconditional Call Forward
exten => _*21*X.,1,DBput(CFIM/${CALLERIDNUM}=${EXTEN:4})
exten => _*21*X.,2,Hangup
exten => #21#,1,DBdel(CFIM/${CALLERIDNUM})
exten => #21#,2,Hangup
; Call Forward on Busy or Unavailable
exten => _*61*X.,1,DBput(CFBS/${CALLERIDNUM}=${EXTEN:4})
exten => _*61*X.,2,Hangup
exten => #61#,1,DBdel(CFBS/${CALLERIDNUM})
exten => #61#,2,Hangup
You can’t use use “#” for SIP adapters like Grandstream Handytone, because they will not be sent. These phones and adaptors use # as the character to end the phoneno., so that you don’t have to wait for the timeout. Use something like this for call forward instead:
Example 3
[apps]
;
; Unconditional Call Forward
;
; create call forward
exten => _*21*X.,1,GotoIf($[${EXTEN:-1} = #]?2:3)
exten => _*21*X.,2,StripLSD(1)
exten => _*21*X.,3,DBput(CFIM/${CALLERIDNUM}=${EXTEN:4})
exten => _*21*X.,4,Hangup
;
; delete call forward
exten => **21,1,DBdel(CFIM/${CALLERIDNUM})
exten => **21,2,Hangup
;
; delete call forward (with #)
exten => **21#,1,Goto(**21,1)
If you do it this way, both regular phones and SIP adaptors without dialplan will work the same way (ending the string with #)
Notes
- This context implements the functionality to set or cancel call forwarding. It needs to be included in the context used for outbound calls
- The ${EXTEN:4} variable construct takes the current extension and strips the first four characters.
- This programming does not confirm the setting with an audio prompt. Add this if you want the user to get a confirmation of the new status.
Example 4
[pbx]
exten => 7000,1,Macro(stdexten,7000,MGCP/aaln/1@<myphone>) ; IP10S
exten => 7001,1,Macro(stdexten,7001,SIP/oej) ; SIP connection
Note: Don’t forget to include the apps extension in your context.
Example 5
This is for V1.2.x and handles the forwarded call in the expected manner. IE the caller is dropped into the called mailbox rather than the extension that the called exten was forwarded to. IE 20 calls 21 which is forwarded to 22 but 22 doesn’t answer then the mailbox it drops into is 21 not as many examples 22.
The CFIM database entry is set as in the above examples.
== extensions.conf ==
[macro-stdexten]
;
; Standard extension macro:
; ${ARG1} - Extension (we could have used ${MACRO_EXTEN} here as well
; ${ARG2} - Device(s) to ring
; Retrieve the Call Forward number if available.
exten => s,1,Set(CFIM=${DB(CFIM/${ARG1:-4})})
;
; Dial the appropriate number depending on whether the Call Forward
exten => s,n,GotoIf($["${vmbox}"!=""]?s-NoCFIM,1)
exten => s,n,Set(_vmbox=${MACRO_EXTEN:-4})
exten => s,n,GotoIf($["${CFIM}"!=""]?s-CFIM,1:s-NoCFIM,1)
;
; Pass call to Voicemail with the appropriate greeting.
;exten => s,n,GosubIf($[${DIALSTATUS}=NOANSWER]?s-NOANSWER,1:s-BUSY,1)
; Hangup.
exten => s,n,Hangup
;
; Dial Call Forward number & return.
exten => s-CFIM,1,Dial(Local/${CFIM},30,Ttr)
exten => s-CFIM,n,GosubIf($[${DIALSTATUS}=NOANSWER]?s-NOANSWER,1:s-BUSY,1)
exten => s-CFIM,n,Hangup
; Dial actual extension & return.
exten => s-NoCFIM,1,Dial(${ARG1},30,Ttr)
exten => s-NoCFIM,n,GosubIf($[${DIALSTATUS}=NOANSWER]?s-NOANSWER,1:s-BUSY,1)
exten => s-NoCFIM,n,Hangup
;
; Unavailable voicemail message if there is no answer.
exten => s-NOANSWER,1,Voicemail(u${vmbox})
exten => s-NOANSWER,n,Return
; Busy voicemail message for any DIALSTATUS other than NOANSWER (or ANSWER).
exten => s-BUSY,1,Voicemail(b${vmbox})
exten => s-BUSY,n,Return
Example 6
For version 1.8
exten = _ZX,1,GotoIf(${DB_EXISTS(CFIM/${EXTEN})}?cfim)
exten = _ZX,n,GotoIf(${DB_EXISTS(CFBS/${EXTEN})}?cfbs)
exten = _ZX,n,Dial(SIP/${EXTEN},,${DIALOPTIONS})
exten = _ZX,n,Hangup
exten = _ZX,n(cfbs),Set(temp=${DB(CFBS/${EXTEN})}) ; Get CFBS key
exten = _ZX,n,Dial(SIP/${EXTEN},20,${DIALOPTIONS}) ; 20sec timeout
exten = _ZX,n,Dial(SIP/operator/${temp},,${DIALOPTIONS}) ; Forward on busy or unavailable
exten = _ZX,n,Hangup
exten = _ZX,n(cfim),Set(temp=${DB(CFIM/${EXTEN})}) ; Get CFIM key
exten = _ZX,n,Dial(SIP/operator/${temp},,${DIALOPTIONS}) ; Unconditional forward
exten = _ZX,n,Hangup
exten = _*21*X.,1,Set(DB(CFIM/${CALLERID(num)})=${REPLACE(EXTEN:4,*#-)})
exten = _*21*X.,n,Hangup
exten = **21,1,DBdel(CFIM/${CALLERID(num)})
exten = **21,n,Hangup
exten = _*61*X.,1,Set(DB(CFBS/${CALLERID(num)})=${REPLACE(EXTEN:4,*#-)})
exten = _*61*X.,n,Hangup
exten = **61,1,DBdel(CFBS/${CALLERID(num)})
exten = **61,n,Hangup
I also have a web gui for setting the callfwd as well as from the set. This allows the attendant to cancel or set forwards.
Because of limitations of this wiki, the above script is not displayed correctly, plz go to this homepage.