Application LCDial

Application LCDial() - Least Cost Routing / FailOver application for Asterisk 1.4 and 1.6


LCDial is a very powerful and versatile solution for Least Cost Routing/FailOver which get information about call routing from 2 tables stored into a MySQL database.
Since release 770, it permits to specify an argument which established which paths the outgoing call should take: this is a very important feature for PBX that are shared by different companies.

The source code for the application with some examples and an automatic installation script is available for free, released under GNU GPL license.

The MySQL database should contains 2 tables:
  • lcdial_providers, within the provider name, dial string, and a flag to enable/disable it
  • lcdial_rates, within the regexp prefix, provider name, rate, and a comment
In this way is very very simple to compile the LCR database by hand, using phpmyadmin or other tool: you can insert a complete lcdial_rates table with several provider costs, and enable into lcdial_providers table only the available providers.

How does it do

  • In extensions.conf you need to dial a call using LCDial() instead of Dial() application
  • table lcdial_rates will be scan to extract all prefixes which match (using REGEXP) to the destination number
  • for each provider, if more than one record match, the longest will be taken (i.e. calling 0039328 matches both ^0039 and ^00393, so only the rate corresponding to ^00393 will be taken into account)
  • only enabled provider will be evaluated: this feature permit to manage least cost routing using a long lcdial_rates table with the costs for every provider, and enabling into lcdial_providers only the telephony provider really accessible (both VoIP, PSTN, Mobile)
  • provider will be sorted from the cheapest to the most expensive
  • Dial() application will be invoked for the #1 enabled provider (the cheapest)
  • if the call will be answered, at the end the application return; if the call will not be answered, the Dial() application will be invoked for the #2 enabled provider (less cheaper than #1), and so on.
As you can see, in this way the LCDial() application provide a FailOver mechanism so if provider #1 does not work, the 2nd one will be tried automatically, then the 3rd one, and so on.

Tables structure

The lcdial_providers define the list of providers. Look at the enabled field: freevoip is disabled (enabled=0), company 1 uses fastweb, wind-leonardo, voipvoice, voipvoice_backup (enabled=1), company2 uses fastweb and voipvoice (enabled=2).
lcdial_providers table structure/example
id provider dialstr enabled ratename ratemul

lcdial_rates table structure/example
^005521freevoip0.03brazil rio de janeiro
^32.......wind-leonardo0wind cellulars
^3[3469].......wind-leonardo0.06italian cellulars (not wind)

Using LCDial() on PBX for a single company (r770 o above)

  ; National context accessed through trunk
  exten => _0ZXXX.,1,NoOp(National outcall)
  exten => _0ZXXX.,n,LCDial(1,${EXTEN},90)
  exten => _0ZXXX.,n,Hangup

Using LCDial() on PBX for 3 different companies (r770 or above)

This feature is useful for PBX used by more than one company, so you can define that users 11,12,13,14,15 calls through the providers where the enabled field (in providers table) is 1, while users 51,52,53,54 calls through the providers which has enabled=2, and users 61,62,63 calls through the providers which has enabled=3
This can be done for up to 10 routes, between 1 and 9.
If the first parameter is not specified, 1 is assumed.


  ; set the variable "LCDialPath" (first argument of LCDial) to select
  ; the path for the outgoing call
  exten => s,1,Set(LCDialPath=1)
  ;exten => s,n,MacroExit
  ; select the path
  exten => s,n,GotoIf($["a${LCDIAL_PATH_2}"="a"]?:20)
  ; LCDIAL_PATH_2 exists: check that the extension that originate the call is inside LCDIAL_PATH_2
  exten => s,n,MacroExit
  exten => s,20,GotoIf(${REGEX("${CALLERID(number)}" ${LCDIAL_PATH_2})}?:40)
  exten => s,n,Set(LCDialPath=2)
  exten => s,n,MacroExit
  exten => s,20,GotoIf(${REGEX("${CALLERID(number)}" ${LCDIAL_PATH_3})}?:60)
  exten => s,n,Set(LCDialPath=3)
  exten => s,n,MacroExit
  exten => 60,MacroExit

  ; National context accessed through trunk
  exten => _0ZXXX.,1,NoOp(National outcall)
  exten => _0ZXXX.,n,Macro(LCDialSetPath) ; set the path to call to (enable=1 or enable=2 or...)
  exten => _0ZXXX.,n,LCDial(${LCDialPath},${EXTEN},90)
  exten => _0ZXXX.,n,Hangup

Download LCDial application

Support for LCDial application

This is free software and only limited support is provided for it by email to
If you add rates information to the provided database, please send the modification to so they will be added to the lcdial-psubiaco.tgz archive.

Original implementation of LCDial(), by Wolfgang Pichler


Does a mysql Database lookup to find the cheapest Provider for a given destination number, and than it invokes the dial command. If the channel is unavailable then it will fall back to the next configured Provider.


  • LCDial(number to dial,timeout,options,URL) — dial one channel


  • number to dial specifes the number which should get dial.
  • all other options are the same as within the standard Asterisk cmd dial command (the are directly passed to the dial comand)

Return codes

Behaves exactly like Asterisk cmd dial

exten => 4000,1,LCDial(${EXTEN},15)

For an up to date LCDial application, please look below at the "Improved version of LCDial() for Asterisk" section!

mysql Database Layout

providerInformations about each Provider (name,id,dialstr,status)
providerdestinationWhich destinations (countryprefixid) are available with which provider
providerrateThe tariffrate for the given provider / destination
countryprefixTable with dial codes
countryoptional - not really needed - but if you want to have nice names for the countries

CREATE TABLE `bit_countryprefix` (
`countryprefixid` int(11) NOT NULL auto_increment,
`prefix` text NOT NULL,
`countrycode` char(3) default NULL,
`subcode` varchar(10) NOT NULL default '',
PRIMARY KEY (`countryprefixid`)

CREATE TABLE `bit_provider` (
`providerid` int(11) NOT NULL auto_increment,
`providername` text NOT NULL,
`dialstr` varchar(200) NOT NULL default '',
`status` tinyint(3) unsigned NOT NULL default '0',
PRIMARY KEY (`providerid`)

CREATE TABLE `bit_providerdestination` (
`providerdestinationid` int(11) NOT NULL auto_increment,
`countryprefixid` int(11) NOT NULL default '0',
`providerid` int(11) NOT NULL default '0',
PRIMARY KEY (`providerdestinationid`)

CREATE TABLE `bit_providerrate` (
`providerrateid` int(11) NOT NULL auto_increment,
`providerid` int(11) NOT NULL default '0',
`countryprefixid` int(11) NOT NULL default '0',
`rate` double NOT NULL default '0',
PRIMARY KEY (`providerrateid`)

CREATE TABLE `bit_country` (
`countrycode` char(3) default NULL,
`countryname` text NOT NULL,
`countryid` int(11) default NULL


LCDial needs a configuration file called lcdial.conf in the standard asterisk configuration directory.
Example Configuration:


getproviders=SELECT providerrate.rate, dialstr, countryprefix.countryprefixid, provider.providerid, provider.providername FROM countryprefix LEFT JOIN providerdestination USING ( countryprefixid ) LEFT JOIN provider USING ( providerid )  LEFT JOIN providerrate ON concat( provider.providerid, countryprefix.countryprefixid ) = concat( providerrate.providerid, providerrate.countryprefixid ) WHERE prefix = substring( '%s', 1, length( prefix ) ) AND provider.status=0  ORDER BY length( prefix ) DESC , providerrate.rate ASC

Get it

Here <- Here you will find the new version which is now based on MysqlPool - please take a look at the documentation.

Compile It

It assumes that the asterisk sources can be found at /usr/src/asterisk, that the asterisk modules directory is at /usr/lib/asterisk/modules and that the asterisk configuration is at /etc/asterisk/.
For compiling it you need to have already installed asterisk ;-) - and the mysql client libary and header files.
From asterisk stable to asterisk cvs head the channel structure has changed a little bit - so if you want to compile against asterisk stable then you have to comment this "CFLAGS+=-DUSE_CVS" line to get it to compile (else you would get an error like "error: structure has no member named `cid'"


If you are having trouble getting the application up and running and need professional help, feel free to drop us a line at

Management Interface

If you are looking for a management frontend or a turn-key-solution please get in touch with us:

See also

Asterisk | Asterisk cmd dial
Created by: wuwu, Last modification: Mon 21 of May, 2012 (22:44 UTC) by admin
Please update this page with new information, just login and click on the "Edit" or "Discussion" tab. Get a free login here: Register Thanks! - Find us on Google+