; -- Start Asterisk extensions.conf Config >=1.2 -- ; ; 2005-12-18 jtodd@loligo.com v1.1 ; ; This is a reasonably complete, but minimalist, configuration ; for an Asterisk server connected to a PBX, which provides ; inbound SIP URI-to-extension mapping (which by default is ; also ISN inbound mapping) and then also performs outbound ; ISN dialing (PBX-to-SIP) conversion. There is also basic ; username-to-number mapping in a static file format (see ; the comments below for the "usernames-to-numbers" context) ; ; This will be a quick instruction on how to make an Asterisk ; server function as a very basic inbound session border ; controller (SBC) which then will sit in front of an existing ; PBX with a PRI attaching Asterisk to the PBX. ; ; Anyone elsewhere on the Internet dialing the ISN of ; "1415551234*255" will be routed to extension "51234" on the ; PRI, which then hopefully will ring the phone on the desk ; of that person. Similarly, dialing "51234*255" will go to ; the same place. ; ; The second part of this dialplan is to take calls from ; the PBX, and perform various ENUM lookups on them, or ISN ; lookups if appropriate. If there is a valid result from ; either source, then the call will be directed to that ; SIP destination. If there is no valid response, then the ; PBX will be given a "Congestion" signal, which hopefully ; will cause the PBX to (in the case of an E.164 number) ; fail over to a PSTN connection. In the case of an ISN ; dialing failure, a message will be played, as the call ; cannot continue out any other path. ; ; Further assumptions (all modifiable) will be: ; ; - the PBX uses 5 digit extensions ; ; - the PBX passes 5 digit extensions in as caller ID ; for calls from the PRI ; ; - the PBX routes all calls from all phones starting with ; "012" in the dialed string to the PRI on this Asterisk ; server. ; ; - the PBX has PSTN connectivity that handles calls for ; the E.164 ranges of 1-415-555-1xxx and 1-451-999-8xxx ; ; - there are no "black" or "white" lists that are desired ; ; - this demonstration server is called sip.bigu.edu, and ; has matching forward/inverse records to that extent ; ; - SRV records are in place for this domain, such that ; requests to "51234@bigu.edu" get mapped to this server. ; This means that the following line is in the zone file ; in the "bigu.edu" level: ; ; _sip._udp.bigu.edu. SRV 10 10 5060 sip.bigu.edu. ; ; - the ISN for this demonstration is "255" ; ; - the DNS for this ISN is (long line, careful of wraps): ; ; *.255.freenum.org IN NAPTR 100 10 "u" "E2U+sip" ; "!^\\+*([^\\*]*)!sip:\\1@sip.bigu.edu!" . ; ; (yes, it's to "sip.bigu.edu" since it's pointless to force ; an SRV lookup if this is a "behind-the-scenes" method.) ; If you don't know what ISNs are, see: ; http://www.internet2.edu/sip.edu/isn/ ; Don't worry if you don't understand or need this now; nothing ; will break if you're not using ISN inbound. ; ; - The PRI is configured to communicate with the PBX, and the PBX ; is expecting the following patterns: ; XXXXX = local user, on-campus ; 1XXXXXXXXXX = Domestic US call ; 011X. = International call (011 followed by 1 or more digits) ; x11 = Handoff to appropriate CLASS feature (911, 411, etc.) ; There are no "local" numbers with only seven digits in this ; dialplan. The luxury of seven digit PSTN dialing is over. ; Get used to it. Furthermore, requiring a leading "1" for North ; American calls eliminates a HUGE number of matching problems, ; so that is also enforced for SIP users. This is where PBX ; dialplans and VoIP gateway dialplans get complex and disgusting, ; so contact me if you can't make things work as expected and ; I'll try to help. ; ; - The PRI is on Zap/g1 ("group" 1). Here are some demonstration ; files, but you will probably need to read the docs to get ; the correct configs if you require more advanced settings: ; ; /etc/zaptel.conf: ; loadzone = us ; defaultzone = us ; span=1,1,0,esf,b8zs ; bchan=1-23 ; dchan=24 ; ; /etc/asterisk/zapata.conf: ; group=1 ; context=from-pri ; signalling=pri_net ; switchtype=national ; pridialplan=unknown ; usecallerid=yes ; channel => 1-23 ; ; - The sip.conf file has the following lines in it in the [general] ; stanza: ; ; ; Send calls from "the Internet" to the [from-internet] context ; context=from-internet ; ; Allow only "free" codecs. You may change this to ; ; just ulaw and alaw if this is a CPU-constrained box. ; disallow=all ; allow=ulaw ; allow=alaw ; allow=gsm ; allow=ilbc ; allow=speex ; ; Hang up any calls that don't have media flowing ; rtptimeout=60 ; ; and at the end of sip.conf, add this Tello peer, but change the ; parameters to match your account. To get a Tello account for your ; PBX, go to http://www.tello.com/ ; ; [tello] ; type=peer ; username=9 ;your Tello ID number ; secret=e98xza ;your password ; host=66.28.153.31 ;the Tello ZCR SIP proxy ; insecure=very ;accept inbound calls ; context=from-internet ;context for Tello inbound ; qualify=4000 ;max. latency for "heartbeat" ; ; ; If you want to use LDAP, this example does not cover that ; example, as it is "advanced magic." If you wish to give it ; a try, see http://www.mezzo.net/asterisk/app_ldap.html for ; an LDAPget lookup method that can be added to Asterisk. ; Currently, Astlinux does not support the OpenLDAP libraries ; and so this module is not included. You could use a System ; call to perform a wget or other web-based call to a remote ; platform that does have LDAP on it... ; ; ; ; [globals] ; ; These are some global values that each site will probably want ; to change based on their local data. They are used in the ; config in generic places. ; ; What SIP domain are you using? Typically this is your "primary" ; domain name, and you'll have SRV records pointed to this host, ; but we're using this as the "From:" header data. ; MYSIPDOMAIN=bigu.edu ; ; ; The IP address of this server. Used for determining if certain ; calls are destined for our own users, or somewhere else. ; MYIPADDRESS=111.222.333.444 ; ; ; Your "human-friendly" organization name (keep it very short) ; ORGANIZATIONNAME=Big University ; ; Your local area code, if 7-digit calls need to have an NPA prefixed ; onto them. ; AREACODE=212 ; ; ; ENUM zones we want to test. If the string is empty, it won't be ; tested. Otherwise, any numbers coming from your PRI in e.164 format ; will be tested in order against these ENUM (or ENUM-like) top-level ; domains. Careful with post-dial-delay here, folks... too many ; trees gets busy. Tello can do these in parallel... ; ENUM-TREE1=e164.arpa ENUM-TREE2=e164.org ENUM-TREE3= ENUM-TREE4= ; ; ; Tello, Inc. offers SIP lookups for inter-organization connections without ; using ENUM and providing even cooler features. See comments in ; README.FIRST for details on reaching Tello. ; ; ; [macro-setcid-uri] ; ; This Macro is used in several places to set caller ID. In calls from ; the PRI outbound to SIP destinations, use the extension number ; as the subscriber ID. ; ; In calls from sip-devices (like desktop softphones) we use the ; caller ID that was set in sip.conf for that device. ; ; Let's see if there is anything in the Caller ID Name that leads ; us to think it's already a SIP URI. Look for anything to the ; right of an "@" sign... if nothing there, then it's probably not ; a SIP URI. ; exten => s,1,Set(rightampersand=${CUT(CALLERID(name),@,-)}) exten => s,n,GotoIf(${ISNULL(${rightampersand})}?setpri:endmacro) ; ; So, if we get to priority "setpri" then there was no URI-formatted ; string in the Caller ID Name, so let's use the numeric extension ; that we've been given. There _better_ be a numeric extension... ; ; First, configure an outbound caller ID which at least looks ; like a SIP URI for the outbound call. ; ; We're going to assume that the ANI (callerid) extension of the PRI ; call is valid, so re-set it with the SIPDOMAIN (i.e.: "bigu.edu") for ; a complete SIP URI. If the name field is null, then set the ; caller ID name to $ORGANIZATIONNAME (i.e.: "Big University), ; otherwise leave alone. This will result in a caller ID like: ; ; From: "Jane Smith" ; or ; From: "Big University" ; ; If you want to get more clever with matching caller ID digit sequences ; to usernames via some external database, this is the place to do it. ; exten => s,n(setpri),Set(${CALLERID(num)=${CALLERID(num)}@${MYSIPDOMAIN}) exten => s,n,GotoIf($["${CALLERID(name)"=""]?setid:endmacro) exten => s,n(setid),Set(${CALLERID(name)=${ORGANIZATIONNAME}) exten => s,n(endmacro),NoOp ; ; ; ; ; [from-internet] ; ; Catch all inbound numbers that seem to be for us, and send ; them to context [from-internet2] with only the last five ; digits of the dialed number. ; ; Note that for ISN dialing, the number of digits presented is ; a function of the regular expression that is in the DNS for ; your ISN zone. Typically, the whole number will be passed ; through to the receiving server instead of the regexp trying ; to be clever. Asterisk will do all the conversion work here, ; no matter what format the number is passed in as. ; ; ***EDIT THESE LINES TO MATCH YOUR LOCAL CONFIGURATIONS *** ; exten => _14155551XXX,1,Goto(from-internet2,${EXTEN:6},1) exten => _4155551XXX,1,Goto(from-internet2,${EXTEN:5},1) exten => _51XXX,1,Goto(from-internet2,${EXTEN},1) ; exten => _14159998XXX,1,Goto(from-internet2,${EXTEN:6},1) exten => _4159998XXX,1,Goto(from-internet2,${EXTEN:5},1) exten => _98XXX,1,Goto(from-internet2,${EXTEN},1) ; ; ; Include email-address style name context from an external ; file called "usernames-to-numbers". This is for true inbound SIP ; username-to-extension mapping, so that "njersey@bigu.edu" will ; end up ringing Dr. Jersey's desktop phone. ; ; The file "usernames-to-numbers" on the remote server should contain a context ; and dialing rules for each user which redirects the call flow to the ; [from-internet2] context with their PBX extension number, like this: ; ; [usernames-to-numbers] ; exten => njersey,1,Goto(from-internet2,39914,1) ; exten => jsmallberries,1,Goto(from-internet2,39919,1) ; ; For external editing of this file from a different server, ; you could add a line that loads the file from a remote web ; server every time the extensions.conf file is re-loaded: ; ;#exec /mnt/kd/asterisk/fetch-user-context ; ; If you use this method, make sure to remove the ";" from the "exec" line, ; but leave the "#" sign. ; ; There is a file called /mnt/kd/asterisk/fetch-user-context in ; the standard distribution compact-flash versions of this astlinux ; installation which will provide the ability to fetch specific files ; from remote locations. However, if you are doing this "from scratch" you ; might need this file, so it is included here for cut-and-paste (make sure ; to "chmod a+x /mnt/kd/asterisk/fetch-user-context" ; ; #!/bin/sh ; # ; # Start up wget, try to fetch the file in the background ; # ; /usr/bin/wget -O /mnt/kd/asterisk/username-dialplan.conf http://my.webserver.tld/username-dialplan.conf & ; # ; # Wait 15 seconds regardless of result... ; # ; sleep 15 ; # ; # Now hand back the contents of the user-context file ; # via stdout... ; # ; /bin/cat /mnt/kd/asterisk/username-dialplan.conf ; # ; # end ; ; This just uses "wget" to fetch a file from a remote server and ; redirect the output into a "holding" file called username-dialplan.conf ; file via stdout. Regardless of the success or failure of the wget, ; we wait for 15 seconds for the fetch to be attempted, and then ; the contents of that file (hopefully a valid Asterisk context!) is ; included in the main extensions.conf file. If the fetch fails, the ; system will read the most recently downloaded copy of the file so ; that there is some minor "failsafe" capability. See the [test-special] ; context in the PRI sections of this file for how to allow remote ; users to update this file by dialing a number. ; ; Now that the "#exec" routine has created the context, include the ; [usernames-to-numbers] context in this context for dialplan matching. ; include => usernames-to-numbers ; ; Include some quick test destinations that can be used for ; debugging by other people. These are not standardized names ; yet, but it seems that they're a good idea for a network of ; experimental or test-heavy destionations. ; include => tests ; ; If no matches are in any of the above rules, then the call ; should be send to the "i"nvalid rule. This will send a ; SIP error back to the caller. ; exten => i,1,Congestion ; ; If someone hangs up before this context quits, we need an ; "h"angup extension. ; exten => h,1,Hangup ; ; Advanced Dialplan-Fu: if you have another internal SIP ; proxy, you could "include" a context in [from-internet] ; which points usernames at alternate SIP URIs and actually ; creates a SIP INVITE to them, like this: ; ; [more-usernames] ; exten => reno,1,Dial(SIP/reno@pbx.cs.bigu.edu) ; exten => ptommy,1,Dial(SIP/perfect@asterisk.ee.bigu.edu) ; ; ; [from-internet2] ; ; Here is where we pass off the call onto the PRI. The ; call is capped at 3 hours (to prevent "zombies") and then ; it is simply handed to the PRI, since we already normalized ; the extensions to the "expected" numeric digits which ; the PBX is looking for. ; exten => _X.,1,Set(TIMEOUT(absolute)=10800) ; ; Now dial! There are no parameters, since this system is ; not acting as a voicemail system or doing any clever stuff ; to the calls; this is purely a passthrough. This might ; sit and ring for 3 hours; nothing smart done here, it is ; assumed that the PBX is handling errors and timers after this ; handoff. ; We're using "g"roup 1, which means "any PRI trunks that aren't ; being used for other things right now." ; exten => _X.,n,Dial(Zap/g1/${EXTEN}) ; ; If we get to priority 3, something is wrong. Send congestion, ; hangup. ; exten => _X.,n,Congestion ; ; Handle "T"imeouts, and "h"angups. ; exten => T,1,Hangup exten => h,1,Hangup ; ; This is the end of the "core" of the inbound-from-Internet ; dialplan. Pretty simple, eh? ; ; ; [tests] ; ; Destinations used for testing purposes. ; ; "echo": Set timer on this call to 500 seconds, play announcement, ; echo ; exten => 999,1,Goto(echo,1) exten => echo,1,Set(TIMEOUT(absolute)=500) exten => echo,2,Playback(demo-echotest) exten => echo,3,Echo ; ; "date": Play date/time, hangup ; exten => 998,1,Goto(date,1) exten => date,1,Answer exten => date,2,Wait(2) exten => date,3,SayUnixTime exten => date,4,Hangup ; ; ; ; ====================================== ; ; This is for OUTBOUND lookups/calls, meaning from the PRI ; out to the Internet. ; ; This routine performs three possible functions: ; ; 1) Look up and route ISN numbers ; If the number is ISN-formatted and fails, the system will ; play back a failure message and hang up. ; ; 2) Look up and route ENUM destionations (E.164) ; If the number does not have an ENUM entry in any of the ; various ENUM trees consulted, the system will go to the ; SIP proxies (method 3) to test for a match ; ; 3) Test-dial via other SIP proxies ; If the SIP dialing method has no elements in it's list, ; or there are no valid results from the remote SIP proxies ; then the system will send a "Congestion" signal back down ; the PRI. At that time, the PBX should try sending the call ; out a "normal" PSTN trunk. ; ; ; If the number has less than 7 digits, the call will immediately ; result in a "Congestion" tone. 7 digit numbers will have an ; area code and a leading "1" added to guess the intention. Numbers ; starting with "011" will be assumed as international. ; International numbers do not need to start with "011". ; ; The PBX should send calls with the digits "012" to the Asterisk ; server, and leave everything else unmodified OR will take calls ; with at least one digit, followed by *, followed by at least ; one digit. Calls starting with "012" will be examined first. ; This is the "leading" prefix for ISN dialing. ; The prefix for ISN numbers on this local system is "012" so ; strip off those digits when presenting. Your site may be ; different. The system will handle ISN dialing with or without ; the leading three digit prefix. ; ; This method uses the "new" ENUMLOOKUP functions to look up ISN ; numbers in the DNS. The parsing for ISN numbers was ; specifically included in the code, so no fancy re-writing of ; the number is required by the dialplan administrator - Asterisk ; takes care of the internal swapping and zone creation that turns ; "1234*256" into "4.3.2.1.256" and then adds the zone. ; ; The ISN zone used is currently "freenum.org" as of 2005-11-22. This ; zone is subject to change; please see the http://www.freenum.org/ ; site for details, if available. ; ; This method uses the first SIP result from the list of valid ; NAPTRs for an ISN lookup. If you want to iterate through the ; NAPTRs, then you will need to learn more about the ENUMLOOKUP ; function and it's abilities - see "README.enum" in the docs ; directory in the Asterisk source code tree. ; ; There is little error handling in this very brief example. ; ; SPECIAL NOTE: Admittedly, these have not been tested with anyone's ; "real" PBX. Therefore, if your PBX sends overlap dial in certain ; ways, it may not work correctly on the matching sequence. If this ; is the case, PLEASE contact John Todd (jtodd@loligo.com) and he ; will attempt to come up with a site-specific workaround and then ; include the notes in this example. ; [from-pri] ; ; Force the ordering of "_012" first, then "_.*." second and then ; all other numbers last by using "include" to use evaluation ordering. ; ; At least one of these three included contexts should have a ; match, otherwise the call will get a "Congestion" signal back down ; the PRI. ; include => test-special include => test-isn include => test-isn2 include => test-e164 ; ; Hang up on invalid or hangup error conditions. exten => i,1,Congestion exten => h,1,hangup ; ; ; [test-special] ; ; This context is for a few "special" numbers that have meaning to this ; local system. Currently, the only special command that is included ; is the ability to re-load the extensions file. This is for use when ; there is an external file that maps usernames-to-numbers which is ; updated by an administrative person. If the file on the external ; webserver is changed, Asterisk needs to be told to re-read the file and ; use it in the dialplan. Four ways exist to tell Asterisk that it needs ; to execute an "extensions reload" command: ; 1) ssh to the machine, run "asterisk -rc" and type "extensions reload" ; 2) ssh -l root@the.soekris.box "asterisk -rx extensions reload" ; 3) Log into the Astlinux web interface with administrator rights, and ; execute an Asterisk shell command of "extensions reload" ; 4) Create a special extension that when called will perform the ; command. ; This single line assumes that the "magic" extension of 12345 has been ; routed to the PRI, and that it will only be used by the person who ; is administering the file on that webserver. ; ; YOU WILL NEED TO CHANGE THIS NUMBER AND UNCOMMENT THESE LINES IF YOU WANT ; TO PROVIDE THIS ABILITY. ; ;exten => 12345,1,System(/usr/sbin/asterisk -rx "extensions reload") ;exten => 12345,2,Answer ;exten => 12345,3,Wait(2) ;exten => 12345,4,Playback(good) ;exten => 12345,5,Wait(2) ;exten => 12345,6,Hangup ; ; ; [test-isn] ; ; Match on the prefix of "012" followed by one or more digits, ; followed by a "*", followed by one or more digits. Also match on a ; straight ISN (one or more digits starting with 1-9 as the first ; digit, followed by "*", followed by one or more digits.) ; ; If a match is found, jump to the [dial-isn] context to create the SIP ; call. The PRI channel will then be connected to the SIP channel. ; exten => _012.*.,1,Goto(dial-isn,${EXTEN:3},1) ; ; [test-isn2] ; ; We'll also match on any dialstring that contains all numerics and ; has inside it an "*" character somewhere separating at least two ; strings of numbers, each consisting of at least one digit. ; This is for those of you who are clipping any sort of special prefix ; out within your PBX. Even if you are not removing the special ; prefix on your PBX, this will not cause any harm since only numbers ; with "*" in them are match (which is impossible on E.164 calls, so ; no worries.) ; exten => _.*.,1,Cut(itad=EXTEN,*,2) exten => _.*.,n,GotoIf($[${LEN(${itad})} < 1]?bad-announce|${EXTEN}|1) exten => _.*.,n,Cut(subscriber=EXTEN,*,1) exten => _.*.,n,Gotoif($[${LEN(${subscriber})} < 1]?bad-announce|${EXTEN}|1:dial-isn|${EXTEN}|1) ; ; [test-e164] ; ; We're starting to build our "include" statements here. Since we have ; a lot of wildcards, many of which could match, we have to force ordering ; so that the "best" ones match first. ; include => test-e164.1 include => test-e164.2 include => test-e164.3 include => test-e164.4 include => test-e164.5 include => test-e164.6 include => test-e164.7 include => test-e164.8 include => test-e164.9 include => test-e164.10 ; exten => h,1,Hangup exten => T,1,Hangup exten => i,1,Congestion ; ; [test-e164.1] ; ; Now, let's match on all other numbers. We have a bias towards North ; American numbers, so let's do a little cleanup for those systems which ; are too dumb or ossified to allow flexible number plans... check for ; NANP numbers with a leading "1" or without... ; ; Add leading "1" to ten digit numerics, and loop. ; ***NOTE***: Your site may not require this. Think about this carefully. ; exten => _XXXXXXXXXX,1,Goto(test-e164,1${EXTEN}),1) ; ; We've found a match for a ten-digit number starting with "1", which ; means a possible North American destination. Jump out. ; exten => _1XXXXXXXXXX,1,Goto(dial-e164,${EXTEN},1) ; ; [test-e164.2] ; ; Remove leading "011", which is the three-digit prefix for "international" ; calls in North America. We just want to use the E.164 number; no leading ; digits. Strip "011" digits, and loop. ; exten => _011.,1,Goto(test-e164,${EXTEN:3},1) ; ; [test-e164.3] ; If the number is only 7 digits, add the "local" area code, loop. Yuck. ; ***NOTE***: This is REALLY REALLY ugly. Hopefully your site does not ; need this line, and you can just comment it out. Your PBX/switch should ; be trying to append an area code to all outbound calls, but just in case ; it doesn't, we prefix with the area code (specified at the top of this ; file in variable AREACODE) and a leading "1". This is site-specific and ; may need to be modified. ; ; exten => _XXXXXXX,1,Goto(test-e164,1${AREACODE}${EXTEN},1) ; ; [test-e164.4] ; If the number is less than 7 digits, dump to congestion immediately since ; that is almost certainly not a valid full E.164 number. (Can anyone prove ; that this is not a sufficient test?) ; exten => _XXXXXX,1,Congestion [test-e164.5] exten => _XXXXX,1,Congestion [test-e164.6] exten => _XXXX,1,Congestion [test-e164.7] exten => _XXX,1,Congestion [test-e164.8] exten => _XX,1,Congestion [test-e164.9] exten => _X,1,Congestion ; ; [test-e164.10] ; Now, if we've gone this far down the matching tree, it means that ; the number is probably a non-North American destination having more ; than seven digits and not starting with "011". Jump out and let's ; assume it's valid. ; exten => _X.,1,Goto(dial-e164,${EXTEN},1) ; ; ; ; [dial-isn] ; ; An ISN-formatted dialing pattern was detected! Time to try ; the actual call with the results, or play an error. ; ; Let's set the Caller ID correctly on our attempt... ; exten => _X.,1,Macro(setcid-uri) ; ; Now, set a maximum timer on the call to prevent zombies (3 hours) ; exten => _X.,n,Set(TIMEOUT(absolute)=10800) ; ; Do the ENUMLOOKUP on the number in the "freenum.org" zone... ; This is where we actually look up the ISN number in the DNS and ; get back a SIP record as a result. This is a very simple ; implementation, and we only look for the first SIP record. ; exten => _X.,n,Set(isnresult=${ENUMLOOKUP(${EXTEN},sip,i,freenum.org)}) ; ; If the result is not null, dial the SIP destination. If no ; answer in 100 seconds, go to an error message. This ends the ; process in either case (success or failure.) ; exten => _X.,n,GotoIf($["${isnresult}"=""]?failed:success) exten => _X.,n(success),Dial(SIP/${isnresult},100) ; ; The lookup failed, so we should play back an "invalid number" message ; to the caller twice, and then hang up. ; exten => _X.,n(failed),Answer exten => _X.,n,Playback(invalid) exten => _X.,n,Wait(3) exten => _X.,n,Playback(invalid) exten => _X.,n,Hangup ; ; ; Include standard failure mode extensions for "h"angup, ; "T"imeout, and "i"nvalid results ; exten => h,1,Hangup exten => i,1,Hangup exten => T,1,Hangup ; ; ; [dial-e164] ; ; There are two sub-parts to the E.164 dialing routines. ; First is the ENUM lookups. You can specify which ENUM trees you ; wish to search by giving values to the ENUM-TREEx variables ; in the [globals] section at the top of the file. ; ; Note: if you are using Tello services, you may want to do NO ; ENUM lookups, since Tello can integrate these lookups in their ; SIP query, in parallel (_much_ faster.) ; ; The second part of the E.164 process will attempt to dial the ; number using SIP peers. The only peer that is configured ; is the Tello peer, but others can be placed here as well. ; These might be SIP proxies that have a larger number of ; endpoints that they know about or can connect you to, or ; even some that might connect to PSTN endpoints. ; ; ; First, we'll test the number to see if there is an ENUM result... ; exten => _X.,1,GotoIf($["${ENUM-TREE1}"=""]?4:2) exten => _X.,2,Set(enum-result=${ENUMLOOKUP(${EXTEN},sip,1,${ENUM-TREE1})} exten => _X.,3,GotoIf($["${enum-result}"=""]4:20) ; exten => _X.,4,GotoIf($["${ENUM-TREE2}"=""]?7:5) exten => _X.,5,Set(enum-result=${ENUMLOOKUP(${EXTEN},sip,1,${ENUM-TREE2})} exten => _X.,6,GotoIf($["${enum-result}"=""]7:20) ; exten => _X.,7,GotoIf($["${ENUM-TREE3}"=""]?10:8) exten => _X.,8,Set(enum-result=${ENUMLOOKUP(${EXTEN},sip,1,${ENUM-TREE3})} exten => _X.,9,GotoIf($["${enum-result}"=""]10:20) ; exten => _X.,10,GotoIf($["${ENUM-TREE4}"=""]?13:11) exten => _X.,11,Set(enum-result=${ENUMLOOKUP(${EXTEN},sip,1,${ENUM-TREE4})} exten => _X.,12,GotoIf($["${enum-result}"=""]13:20) ; ; We get to priority 13 if there were no matches in any of the trees, or ; all the ENUM-TREEx values were empty. Jump to the next dialing method. ; exten => _X.,13,Goto(dial-e164.2,${EXTEN},1) ; ; One of the ENUM trees came back with a non-null answer, so try ; to dial it. First, set the caller ID appropriately... ; exten => _X.,20,Macro(setcid-uri) ; ; ...and try the dial. Either it works, or it doesn't, but here ; is the end of our dialplan for this test if we go this route. ; exten => _X.,21,Set(TIMEOUT(absolute)=10800) exten => _X.,22,Dial(SIP/${enum-result}) exten => _X.,23,Congestion ; ; Include standard extensions ; exten => h,1,Hangup exten => T,1,Hangup exten => i,1,Hangup ; ; ; [dial-e164.2] ; ; So, no valid ENUM lookups, so let's try sending to Tello. Tello ; will try to match this in their internal database, and possibly through ; various ENUM trees (therefore, making the previous ENUM lookups redundant ; if you have Tello service...) ; ; Set the timers, set the callerID, try to dial, and if we fail send a ; congestion signal. Easy! This is the end of the road for PRI-to-VoIP ; paths. If it's all failed at this point, the call can't be completed ; out VoIP to the knowledge of this system. ; ; If you don't have Tello service, this will fail and won't add any significant ; delay to the process, so you can probably leave it in without worry. To ; activate your Tello service, go into "sip.conf" and uncomment the Tello section ; of the file and add your account information/password data as has been ; provided by Tello. ; ; Now, if this is NOT a PRI-to-VoIP call, we should have something filling the ; "E164NUMBER" variable, since that is set in sip.conf for every SIP phone ; that is attached to this system. Therefore, if that variable is not null, ; then we should try dialing whatever the original dialed number is on the PRI ; channel. If it IS null, then we're dealing with a PRI-to-VoIP call, and ; we should go no further since we don't want to loop back into the PRI. ; exten => _X.,1,Set(TIMEOUT(absolute)=10800) exten => _X.,n,Macro(setcid-uri) exten => _X.,n,Dial(SIP/${EXTEN}@tello) exten => _X.,n,GotoIf($[ "${E164NUMBER}" = ""]?endcall:dialzap) exten => _X.,n(endcall),Congestion ; If we get here, it means that we've failed all of the IP-based methods for ; handing off this call. At this point, just use the original number that was ; dialed, and pass the call off to the PBX via the Zap channels after setting ; the caller ID number to be equal to the number that is set in the sip.conf ; file for this SIP user-agent. This is the end of the line for SIP UA ; calls if they have not been previously matched. ; exten => _X.,n(dialzap),Set(${CALLID(num)=${E164NUMBER}) exten => _X.,n,Dial(Zap/g1/${ORIGNUMBER}) exten => _X.,n,Congestion ; ; Include standard extensions... ; exten => h,1,Hangup exten => T,1,Hangup exten => i,1,Hangup ; ; ; [bad-announce] ; This routine is where calls to unknown extensions are sent, ; and this reads back the number in question. Very useful for ; debugging. ; ; Since there is a wildcard for _all_ destinations in here, we ; have to "include" some standard extension in to force the order ; of evaluation, otherwise the wildcard would get even "h" or ; "T" extensions ("h"angup or "T"imeout.) ; include => bad-announce1 include => bad-announce2 ; [bad-announce1] ; ; "special" meaning clauses go here, otherwise the uber-wildcard ; would match them, causing an endless loop. ; exten => h,1,Hangup exten => T,1,Hangup exten => t,1,Hangup exten => fax,1,Hangup ; ; [bad-announce2] ; ; Global match (dangerous wildcard of "_.") for all values ; exten => _.,1,Set(TIMEOUT(absolute)=90) exten => _.,n,Answer exten => _.,n,Wait(2) exten => _.,n,Playback(that-is-not-rec-phn-num) exten => _.,n,SayPhonetic(${EXTEN}) exten => _.,n,Wait(2) exten => _.,n,Playback(that-is-not-rec-phn-num) exten => _.,n,SayPhonetic(${EXTEN}) exten => _.,n,Playback(goodbye) exten => _.,n,Hangup [from-sip-clients] ; ; The matching of SIP records is fairly difficult, so this is not by any ; means a simple section, nor is it 100% robust. However, it will catch ; almost any common mappings. ; ; Here is the main context for handling calls that come from SIP UA ; clients on the desktop. These can be hardphones or softphones; ; see the configuration for each extension in sip.conf. ; ; Due to the complexity of this configuration model, we will be using ; usernames as the "Caller ID" for calls, except for when the call ; ends up on the PBX. For those calls, we have set a variable in ; sip.conf for each SIP "user" which equates to their local E.164 ; number. If your organization doesn't have a one-to-one mapping ; of "real" telephone numbers to users, then significant modification ; of this section will have to be done, or you'll simply have to ; set the E164NUMBER value in sip.conf for all users to be equal ; to the "main" number for your campus. ; ; Further note that Asterisk is a B2BUA. It doesn't even try to be a ; proxy. This also means that the identity of all calls are altered ; and "created" by Asterisk - the UA does not have any say in the ; matter. This is desirable in some cases, undesirable in others. ; It is possible to have Asterisk pass through everything from the UA ; but this is somewhat longer a configuration example than is necessary ; for this platform. ; ; We first must test to see if this SIP URI is destined for ourselves, or ; is destined for elsewhere. This decision needs to be first, since we ; cannot match on domain within the extension itself, so we must look at ; other variables. If it's for outside of our domain, hand the call off. ; If it is for inside our domain to a user OR to an sequence of digits ; that maps to a valid path on the PRI (extension, or E164 number, or ; what-have you) then handle it appropriately. ; ; We first check to see if the called "number" is a SIP URI by matching ; on strings that contain strings. If it is, then see if the domain ; part is this server (or the domain served by this server.) If so, strip ; off the domain part and loop. Otherwise, dial the URI. ; ; The $MYSIPDOMAIN and $MYIPADDRESS were defined in the [globals] section. ; ; SIPDOMAIN is a built-in variable that equals everything to the right of ; the @ sign in a dialstring. We first strip off any trailing port numbers ; or anything after a ":" so we can test match on this host/domain. ; ; Note: this will not match on single-letter usernames. Sorry. ; ; Note: this may fire off a bunch of warnings about "wildcards of _. are dangerous" ; You can ignore those warnings. It's dangerous, but necessary here. ; ; ; Very first thing: remember the number that was originally dialed. ; exten => _.,1,Set(ORIGNUMBER=${EXTEN}) ; ; Next, set SIP domain values... ; exten => _.,n,Cut(SHORTSIPDOMAIN=SIPDOMAIN,:,1) exten => _.,n,Cut(SIPUSER=EXTEN,@,1) ; ; Check to see if $SIPDOMAIN equals the caller's $SHORTSIPDOMAIN. If yes, send ; to the next context with just the user as the new dialed extension. ; If not, continue tests. ; exten => _.,n,GotoIf($[${MYSIPDOMAIN} = ${SHORTSIPDOMAIN}]?from-sip-clients2|${SIPUSER}|1:sipcheck2) ; ; Check to see if $MYIPADDRESS is equal to $SHORTSIPDOMAIN. If so, send the ; call to the next context with just the user as the new dialed extension. ; If not, dial the number because the domain part of the URI was not some ; variation of this server's IP address or domain. ; exten => _.,n(sipcheck2),GotoIf($[${MYIPADDRESS} = ${SHORTSIPDOMAIN}]?from-sip-clients2|${SIPUSER}|1:extern-dial) ; ; So, the string was not a local user, therefore it must be either garbage or ; a valid SIP URI. To determine if the string is garbage would take a very, ; very intense set of parsing routines. Therefore, punt and just try to dial ; it. If it's invalid, it will fail, otherwise it will succeed. You may ; wish to put some logging in here (like with a System call that dumps some ; values to a text file somewhere) so you can see who is dialing what and ; what the string values are other than what shows up in the /var/log/asterisk/ ; logfiles. ; exten => _.,n(extern-dial),Dial(SIP/${EXTEN}@${SIPDOMAIN},100,rt) ; ; The call failed. Jump to congestion. End of the line. ; exten => _.,n,Congestion ; ; ; [from-sip-clients2] ; ; Now, search through various contexts to see if the number or URI that has been ; dialed by the SIP client/user-agent can be found in any of the contexts ; that we have in this system. Check usernames, test extensions, PRI extensions, ; and finally test against E.164 numbering. If there are no matches, the system ; will attempt to send the call out on the PRI using the number originally dialed ; by the SIP client, which is why "test-e164" is last in the inclusion list. ; include => usernames include => tests include => test-extensions include => test-isn include => usernames-to-numbers include => test-e164 ; ; Include standard extensions... ; exten => h,1,Hangup exten => T,1,Hangup exten => i,1,Hangup ; ; [usernames] ; ; Any of your entries in sip.conf need to have an equivalent extension mapping ; here if you wish them to be dialed. These will be extremely simple mapping ; demonstrations - no voicemail, no dual-ring, no interesting paths for failed ; calls. This is a very plain config. Note that the context which may or may ; not be imported from an external file called [usernames-to-numbers] also may ; overlap with this context - make sure you use "include" correctly to always search ; this context first. The purpose for this context is for user-agents (SIP ; devices) which are local, while the usernames-to-numbers is to convert for ; users who don't have SIP devices but are reachable on an extension on the ; PBX via the PRI. The URI that external users use looks the same in it's syntax, ; but the destinations are different from Asterisk's perspective. ; exten => thikita,1,Dial(SIP/thikita) exten => thikita,2,Congestion ; ;