Asterisk dialplan

Asterisk’s configuration consists of numerous file sets. The dial plan, routing by number, is defined in extensions.conf.

Example of a simple extension

The dial plan follows the syntax as shown below:

[internal]

exten => _1XX,1,Dial(PJSIP/${EXTEN},30)
same => n,Hangup()

The structure of a block that matches each called number is as follows:

  • The heading [internal] at the beginning is the context, which serves to categorize multiple routings. It is referenced from the endpoint in pjsip.conf.
  • The first line is written as exten => number,1,application(). The elements on the right-hand side are written as follows from left to right:
    1. The first item, number, follows the number matching rules. For example, _1XX matches 3 digit numbers starting with 1, such as 103 or 199.
    2. The second item, 1, represents the priority, indicating that it is the first line to be executed.
    3. application() refers to any application process provided by Asterisk.
  • Subsequent lines are written as same => n,application(), which indicates they are executed in sequence:
    1. same => is shorthand for exten => number, and matches the same request as the line above.
    2. The second item, n, is a wildcard indicating the next priority after the previous line. If needed, labels in the format n(label) can be added to reference other lines.
    3. application() remains the same across all lines.

Thus, in this example, first Dial() is executed, followed by Hangup(), and then the process ends. The variable ${EXTEN} contains the requested number, so if the number starts with 1, it will call the corresponding SIP client.

In older examples, every line might be defined with exten => instead of using same =>, but in cases where lines are executed sequentially, same => can replace them.

While each application behaves much like a function, note that inserting spaces between arguments, such as in Voicemail(100, s), can cause an error. The cause of the error, particularly due to whitespace, may be difficult to identify from the error logs.

Voicemail

[internal]

exten => _1XX,1,Dial(PJSIP/${EXTEN},30)
same => n,Answer()
same => n,Playback(/var/lib/asterisk/sounds/custom/voice-absent)
same => n,Wait(1)
same => n,Voicemail(${EXTEN},s)
same => n,Congestion
  • Answer() switches the behavior so that Asterisk directly answers the call. In this example, it answers after a 30-second Dial() attempt timeout.
  • Playback(filepath) and Voicemail(mailbox,options) handle automated voice playback and recording to a file:
    • Voicemail() plays a default automated message. The s option skips the message, so Playback() can be used additionally.
    • The file path in Playback() omits the extension. Asterisk will search for the best quality format based on predefined extensions. In practice, .wav offers broad compatibility.
  • Wait(sec) and Congestion() control the call flow.

Additionally, the mailbox for Voicemail() needs to be configured in voicemail.conf according to its intended use.

In voicemail.conf, you can set up email sending using the sendmail method, or implement a notification method by adding System() to the dial plan to run a custom script.
Although System() may cause the auto-answer flow to pause while waiting for the command to finish, you can make the script run in the background to continue the process immediately. However, note that System() does not execute after Hangup().

Audio files for automated voice messages

Asterisk supports several codec variations, but the most stable format is 8-bit mono PCM with a fixed bitrate of 8000Hz sampling.

On Linux, you can install sox and use the following options to convert the audio files:

$ sox input.wav -b 8 -r 8000 -c 1 output.wav

# For 32kHz audio
$ sox input.wav -b 16 -r 32000 -c 1 output.sln32

The 8000Hz format is nearly the lowest quality, but since 8-bit u-law is widely used for PSTN telephony, it’s currently considered a compromise focused on compatibility.

Higher-quality formats may work depending on the client’s supported codec combinations and transcoding capabilities.
You will need to match the format with the appropriate file extension for each bitrate. Whether it will play correctly can only be determined by testing it in a real environment, so verification is necessary.

Voicemail Management Interface

To play or delete received voicemails, assign the VoiceMailMain() application to a specific extension number.

[internal]

exten => 199,1,VoiceMailMain()
same => n,Hangup()

In this example, you can manage voicemails by calling extension 199.
Password authentication and email notifications are set up separately in voicemail.conf.

Outbound Calls to Traditional Telephone Networks

If you want to make outbound calls to non-SIP PSTN phones, you will need to use an external SIP trunking service that provides circuit-switched connections.
Since connecting to a SIP trunking service must be implemented according to the service’s specifications, a standard description cannot be provided. However, there are limited options available in the dial plan configuration part.

[internal]

exten => _9.,1,Set(CALLERID(num)=+819876543210)
same => n,Dial(PJSIP/+81${EXTEN:1}@outbound-endpoint)
  • Example of defining an outbound call to external lines starting with the number 9
  • Set your own phone number in CALLERID(num)
    • This will be included in the SIP From header. In most cases, it should be the number assigned to you by the service provider.
    • This example is written in RFC2822 format, you will need to follow the format specified by the service.
  • Use Dial() to specify the recipient’s number and endpoint
    • The user part is the original request for the SIP Request-URI or To header.
    • In this example, the number is converted to RFC2822 format by adding the country code and appending the requested number. ${EXTEN:1} removes the first digit from the request. The initial digit in this example’s 9 dialing is not part of the PSTN phone number.
    • outbound-endpoint is an example of an endpoint name defined separately.

Dial plan configuration alone is unlikely to be sufficient for connecting to the service. Other request settings will need to be specified in the pjsip.conf endpoint.

Incoming Calls from Traditional Phone Networks

Incoming calls from PSTN phone networks also require configuration with an external SIP trunking service.
Proper connection setup must follow the service specifications, but the dial plan configuration part is relatively simple.

[dial-in]

exten => +819876543210,1,Dial(PJSIP/101&PJSIP/102,30)
same => n,Hangup()
  • Define the matching conditions for requests to PSTN phone numbers:
    • Incoming requests for PSTN numbers will come to the numbers obtained through the service contract, so you should be able to restrict the matching conditions.
  • Specify the endpoint to call with Dial():
    • In this example, it is assumed that multiple clients will be called, so endpoints 101 and 102 are specified.

Once you can receive calls properly, you can add other applications. For example, voicemail can be set up similarly to SIP network configurations.

Call Blocking

Asterisk provides the BLACKLIST() function to determine if a call should be blocked based on the CALLERID.
You can combine it with GotoIf() to create a control flow that jumps to a specific labeled line when the condition is met. The syntax for GotoIf() is similar to the ternary operator commonly used in programming.

[dial-in]

exten => +8150.,1,GotoIf(${BLACKLIST()}?spam)
same => n,Dial(PJSIP/101,30)
same => n,Hangup()
same => n(spam),Hangup()

In this example, if the BLACKLIST() condition is not met, it does not jump and instead executes lines 2 and 3.

The blacklist refers to the standard sqlite3 database in Asterisk, which can be managed using the CLI database command.

asterisk*CLI> database put blacklist +819876543210 note
asterisk*CLI> database del blacklist +819876543210
asterisk*CLI> database show blacklist

Editing Caller Name Display

Many SIP clients can display CALLERID(name). By using Set() before dialing with Dial(), you can, for example, add prefix characters to incoming caller numbers.

same => n,Set(CALLERID(name)=AA${CALLERID(num)})

In this example, the name is set to include the characters “AA” before the caller’s number.
For instance, even if a SIP device can only register one line, it can receive multiple phone numbers and distinguish between them.

⁋ Aug 13, 2024↻ Nov 7, 2024
中馬崇尋
Chuma Takahiro