Creating a Dialplan in Asterisk 1.6: Part 1

When calls come into the switch, we tell Asterisk step-by-step how to handle the call. Steps can be as simple as playing a sound file to running a customized script. We are limited mostly by our imaginations at this point.

We define all the steps we want Asterisk to perform in our extensions.conf file, in the customary location /etc/asterisk. Before we begin, we need to set priorityjumping=yes in the [general] section of extensions.conf. This will allow the tips and tricks in this article to work with Asterisk 1.6.x.

Creating a context

What is a context? Simply said, a context is a group of extensions. Each extension must exist within a context. There is more to contexts than grouping extensions though. In our extensions.conf file (or any included files), a context is denoted by square brackets "[ ]", as shown:

[mycontext]. . .

So, if a context is a group of extensions, why do we need more than one? Let's think for a minute. Not all employees should be able to dial every phone. Would you trust your 16-year-old intern with the ability to dial international calls? I wouldn't. Also, do you want your president to be bothered by customers in the waiting room who use a courtesy phone and misdial? We could find that hazardous to our continued employment.

Certain extensions are hidden or made inaccessible from other extensions by context. This gives us some level of security. It also allows us to host multiple phone systems on a single server.

Imagine you have two businesses on the same phone system, each with only two handsets. It'd be a pain to have each dial four digits to reach the other handset. We can use contexts to treat each company as if it were on a separate server.

Something very important about contexts is we can include other contexts through the use of the include directive. This means all extensions in an included context are available. The value of this may not be immediately apparent, but soon we will see the full power of this tool.

Suppose we have some context named bob. If we wanted bob to include default, then we would have the following in our extensions.conf:

[bob]include => default

This single line placed in any context gives that context the ability to dial any extension in the default context, as well as all contexts included in the default context. This means that if the default context included the foo context, then anybody in the bob context could dial extensions in the foo context.

Now I know that we haven't yet discussed the definition of extensions. That's OK. All we need to know is that extension 1 in foo will play back a file that sounds like monkeys, and extension 1 in bar will play back a file that says, "weasels have taken over our phone system".

If we are in context foo and press 1, which file will play? This shows us the danger of include. We should be careful not to include multiple matches for the same extension. If we do include multiple contexts, the first included context with a match will win. Consider the following file:

If we are in context foobar1 and press 1, we will hear monkeys, while if we are in context foobar2 and press 1, we will hear weasels. While this can trip the unwary, we will use it to our advantage later on.

Creating an extension

We all have a good idea about what an extension is. On our legacy PBX, each handset was an extension. Pretty simple, right?

While conceptually simple, there is a little wrinkle. If all we want to do is provide a few handsets, then there's one extension per phone. But Asterisk can do much more! We need to think of an extension as a group of commands that tells Asterisk to do some things. As amorphous as that may be, it's true.

An extension can be tied to one handset, a queue, groups of handsets, or voicemail. An extension can be attributed to many different areas of the system. If you're familiar with programming terms, perhaps you could say that extensions are polymorphic.

To go further, extensions can be used to provide access to other applications, sound files, or other services of Asterisk. Extensions are important to the magic of Asterisk.

Now that we know why we create extensions, let's think about how we create them. Again, they are in the extensions.conf file, or any files that you include from there.

We may decide to break up files such as extensions.conf into multiple configuration files. A common example of this is when we create large groups of extensions and choose to give each its own file. This also applies to the other configuration files we use.

The general format for a line in the extensions.conf file is:

exten => extensionnum,priority,action

Let's take a closer look. Each line begins with the command exten. This is a directive inside Asterisk. You do not change this for each extension.

Next, we have the extension number. Each extension has a unique number. This number is how Asterisk knows which set of commands to run. This extension can be detected in three major ways. First, the phone company may send it in with the calls, as is the case with DID numbers. Users can enter an extension using their touch-tone keys. Finally, there are a few special extensions defined. Some of these are:

s: start extension. If no other extension number is entered, then this is the extension to execute.

t: timeout extension. If a user is required to give input, but does not do so quickly enough, this is the extension that will be executed.

i: invalid extension . If a user enters an extension that is not valid, this is the extension that will be executed.

fax: fax calls. If Asterisk detects a fax, the call will be rerouted to this extension.

Then we have the priority. Asterisk will start at priority 1 by default, complete the requested command, and then proceed to priority n+1. Some commands can force Asterisk to jump to priority n+101, allowing us to route based on decisions, such as if the phone is busy.

Finally, we have the action. This is where we tell Asterisk what we want to do. Some of the more common actions we may want to perform are:

Answer: This accepts the call. Many applications require that the call be answered before they can run as expected.

Playback(filename): This command plays a file in .wav or .gsm format. It is important to note that the call must be answered before playing.

Background(filename): This command is like Playback, except that it listens for input from the user. It too requires that the call be answered first.

Goto(context,extension,priority): Here, we send the call to the specified context, extension, and priority. While useful, this can be a bad style, as it can be very confusing to us if something goes wrong. However, it can be a good style if it keeps us from duplicating extension definitions, as moves, adds, or changes would only have to be updated in one place.

Queue(queuename|options): This command does what it seems like it should. It places the current call in the queue, which we should have already defined in the queues.conf file.

Voicemail(extension): This transfers the current call to the voicemail application. There are some special options as well. If we preceed the extension with the letter s, it skips the greeting. When we place the letter u before the extension, it uses the unavailable greeting, and b uses the busy greeting.

VoicemailMain: This application allows users to listen to their messages, and also record their greetings and name, and set other configuration options.

Dial(technology/id,options,timeout): This is where we tell Asterisk to make the phone ring, and when the line is answered, to bridge the call. Common options include:

t: Allow the called user to transfer the call by pressing the # key.

T: Allow the calling user to transfer the call by pressing the # key.

r: Indicate ringing to the calling party.

m: Provide music on hold to the calling party.

H: Allow the calling party to hang up by pressing the * key.

g: Go on in the context if the destination hangs up.

While this list is not exhaustive, it should be enough to get us started. Suppose we just want to make a DAHDI phone ring, which is on interface 1, and we are going to work completely in the default context. Our extensions.conf file would look like:

[default]exten => s,1,Dial(dahdi/1)

Pretty simple, right? Now, imagine we want to transfer to the voicemail of user 100 if someone is on the phone. As Dial sends you to priority n+101 when the line is busy or not available, all we have to do is define what we want to do. Our dialplan would look like:

[default]exten => s,1,Dial(dahdi/1)exten => s,102,Voicemail(b100)

Great! We have some of the functionality that users have come to expect. But are you happy yet? The problem is that a phone could ring for years before someone picks it up.

So, for our next exercise, suppose we want to transfer the call to voicemail when the phone is not answered in 30 seconds. So, obviously, we're going to have to use the option in Dial to define a time-out. Our dialplan would have something like:

All we're doing is telling Asterisk how to handle the call, in a step-by-step way. It is important to think about all scenarios that a call can go through, and plan for them. Just to reiterate a point I made earlier, planning ahead will save us hours of debugging later.

Suppose we want to send anyone who is in a place where they shouldn't be to user 0's voicemail, which will be checked periodically by the receptionist.

All right, we're getting somewhere now! At least we know each call will be handled in some way. What about faxes? Suppose we have only one fax machine (or a centralized fax server) on DAHDI interface 2, then our dialplan should look similar to:

Congratulations! We now have a working phone system. May be not the most interesting yet, but we're making great progress. Don't worry, our phone system will grow in features.

Now, to create a list of useful extensions, we need to define a set of commands for each handset we have. Suppose we have three SIP phone users—1001-1003, with extensions 1001-1003. Our default context would look like:

For every extension we add, the length of extensions.conf will grow by four lines (three lines of code, and one line of whitespace). This is not very easy to read, and it is very easy to make mistakes. There has to be a better way, right? Of course there is!

We can use macros to define common actions. We will create a special macro context. The name of these contexts always starts with macro-. Suppose we want to call this one macro-normal. We would have:

So now, each extension we add requires only one extra line in extensions.conf. This is much more efficient and less prone to errors. But what if we knew that any four-digit extension beginning with a 1 would be a normal, SIP extension?

Here it is time for us to discuss Asterisk's powerful pattern-matching capabilities. We can define extensions with certain special wildcards in them, and Asterisk will match any extension that fits the description.

Using the underscore (_) character warns Asterisk that the extension number will include pattern matching. When matching patterns, the X character represents any number (0 to 9), the Z character will match the numbers 1 to 9, the N character represents numbers 2 to 9, and the period (.) represents a string of any number of digits.

Also, we can use certain variables in our dialplan. One such variable is ${EXTEN}, which represents the extension that was used.

So, for this example, we could use the following definition:

exten => _1XXX,1,Macro(normal|${EXTEN}|SIP/${EXTEN})

This one line of code has now defined 1000 extensions, from 1000 to 1999. All we have to do is ensure that our voicemail user, extension, and SIP user are all the same number. Pretty cool, huh?

Note that if we wish to modify the behavior of all extensions, all we have to do is modify the macro. This should help us quite a bit as we tweak Asterisk to fit our business needs.

Creating outgoing extensions

With this dialplan, we have only catered for incoming calls. Of course we will want to create extensions to dial out.

How these outgoing extensions look depends on the plan we made earlier. It also depends on how you want the switch to act for your users. We always want to make it as similar to any old system as possible to reduce the need to retrain users.

Most phone systems require a user to dial a certain digit to designate the call as one that has a destination outside the switch. In our legacy PBX, we accessed outgoing lines by dialing a 9. To copy this behavior, we could do something like:

[outgoing]exten => _9.,1,Dial(dahdi/g1/${EXTEN:1})

Notice that we are using pattern matching as we did before. Also notice that we used g1 as the DAHDI interface. This is a good use for a group. This simply means "any free interface in group 1". Thus, if we put all of our outgoing lines in group 1, when we dial an outside number, we do not have to guess which channel is free.

Remember that the variable EXTEN represents the extension that we are in. If a user dials 95555555, then EXTEN is equal to 95555555. By using ${EXTEN:1}, we instruct Asterisk to strip the first (leftmost) digit. Thus, ${EXTEN:1} equals 5555555. If we wanted to strip the two leftmost digits, it would be ${EXTEN:2}.

Many discount long distance carriers will charge the same for local calls as long distance. In a case like that, we would want to make sure that local and toll-free calls went out on lines connected to the local telephone company, while calls destined for long distance locations should go out through our discount carrier. For this example, we will assume that the discount carrier is DAHDI group 1, and the local telephone company is DAHDI group 2.

Notice that this is a problem. When we dial 9, followed by 1, we have two statements that match. When you start Asterisk, you will notice that the system parses the extensions.conf (and included files) and immediately reorders all of the extensions before building a database file. Therefore, it is ambiguous as to which statement it will execute.

While this method is technically functional, it is not the best way to do it. A better way would be:

This is getting much better, but what when all of our lines are busy for both groups? We should probably notify the user that their call didn't go through because all lines are in use. We could do something like this:

Imagine a phone switch, in which all extensions were exactly four digits long. How would this knowledge affect our outgoing lines? Perhaps the fundamental question is whether we really need to dial the 9 at all. While people generally expect to dial a 9 at work, they do not seem to care to do so from home. May be we should do this:

There is a drawback to this configuration. If you are using DAHDI interfaces, and people are touch-tone dialing, Asterisk will have to wait for a timeout period to complete dialing some four-digit extensions. The reason for this is simple. Any extension number that partially matches the beginning of the patterns above will have to be held to see if more digits are coming. However, SIP and IAX phones do not seem to suffer the same issue.

Because of this issue, from here we will assume that all outgoing calls are preceded with the digit 9.

We have already discussed that contexts can provide security for outgoing phone calls, but this example fails to describe such security. Suppose you have two groups of employees, those who may make toll calls, and those who may not. All employees have an individual handset. The most logical choice is to make two contexts:

We simply place each handset into one of the two contexts, based upon what numbers we want them to be able to dial. While this would work, we duplicated three lines between the contexts. Remember when we discussed contexts, and I mentioned that we can use the include directive? Here's a good place to do so. So now, we have:

Let's take a quick look at what we have. We can now place handsets in the local or longdistance context. This gives us a good bit of security, but there is one small problem. Do you see it? If we put our users into either context, they cannot dial internal extensions. Assuming we allowed calling our local extensions in the default context, we should update the local context like so:

By so doing, we give access to the extensions for the local context. We also give access to the default context for those in the longdistance context because longdistance includes local, which in turn includes default.

Thus, we must be very careful about what we include. When we include any context, we are in turn including all contexts it includes. It is easy to include our way out of the security we set up.

Alerts & Offers

Series & Level

We understand your time is important. Uniquely amongst the major publishers, we seek to develop and publish the broadest range of learning and information products on each technology. Every Packt product delivers a specific learning pathway, broadly defined by the Series type. This structured approach enables you to select the pathway which best suits your knowledge level, learning style and task objectives.

Learning

As a new user, these step-by-step tutorial guides will give you all the practical skills necessary to become competent and efficient.

Beginner's Guide

Friendly, informal tutorials that provide a practical introduction using examples, activities, and challenges.

Essentials

Fast paced, concentrated introductions showing the quickest way to put the tool to work in the real world.

Cookbook

A collection of practical self-contained recipes that all users of the technology will find useful for building more powerful and reliable systems.

Blueprints

Guides you through the most common types of project you'll encounter, giving you end-to-end guidance on how to build your specific solution quickly and reliably.

Mastering

Take your skills to the next level with advanced tutorials that will give you confidence to master the tool's most powerful features.

Starting

Accessible to readers adopting the topic, these titles get you into the tool or technology so that you can become an effective user.

Progressing

Building on core skills you already have, these titles share solutions and expertise so you become a highly productive power user.