Modifying CID and CNAM info on a per-DID basis

Occasionally a customer will require incoming calls from a specific phone number to be displayed in a very particular way. An example of this would be the Town of Canton where they require certain calls to display on their phones simply as 2911. Fortunately modifying the display of incoming calls on a per-DID basis is a very simple process using what is known as a custom context in the Asterisk Dial Plan.

Asterisk, FreePBX, and Dial Plans

Ringfree makes use of a piece of software called FreePBX, which provides a graphical front end to Asterisk, the software which actually processes phone calls. Asterisk makes use of a Dial Plan which provides the specific rules for how it should go about handling certain types of calls. Most of the Dial Plans in use at Ringfree (and in all FreePBX installations) are generated automatically by FreePBX according to how you set up any given phone system. In fact most of what you’re doing when accessing pbxadmin is just giving FreePBX rules so it knows what to do when it generates the Dial Plans.

FreePBX fortunately gives us some room to add customizations that won’t be overwritten the next time it generates a new Dial Plan. Most commonly these customizations are added to the file located at /etc/asterisk/extensions_custom.conf.


Within the Dial Plan, particular Asterisk actions are organized into contexts, which are inherited and executed using some simple if/then/goto logic. For example, an incoming call will start by using one context while an outbound call will start by using another. If the inbound call goes to an extension, it’ll inherit a context associated with that extension whereas if it routes to a ring group, it’ll inherit a different context that is instead associated with that ring group.

When FreePBX generates the Dial Plan, it adds in support for custom contexts which can be arbitrarily defined by an administrator of the server where Asterisk is installed. To define a custom context, simply enclose the context name in square brackets. An example of a custom context with a dial plan rule would be:

exten => s,1,Quote("Custom dial plan rule in demo-context.")

In this case, there is nothing elsewhere in the Dial Plan that would point to [demo-context] so it would be not be used at all during call processing. However FreePBX has some custom contexts that it looks for by default so all you have to do to add new dial plan rules is to use one of the default custom contexts. In this particular case, we’re going to use the [from-pstn-custom] context.

Understanding Asterisk Variables and Conditionals

Within the Asterisk Dial Plan, the Caller ID number and the CNAM data are stored as variables which can be accessed and changed using the CALLERID() function. For example if we wanted to display the incoming number and the name on the Asterisk command line, we would do the following:

exten => _x.,1,Quote(${CALLERID(num)})
exten => _x.,n,Quote(${CALLERID(name)})

Similarly if we wanted to change the incoming number and name, we would make use of the Set() function to do as much:

exten => _x.,1,Set(CALLERID(num) = 15555555555)
exten => _x.,n,Set(CALLERID(name) = "RINGFREE")

Asterisk supports using the value of a variable or function within other functions as well using the syntax of a dollar sign and curly brackets containing the variable or function. The following replaces the CNAM data with the incoming phone number:

exten => _x.,1,Set(CALLERID(name) = ${CALLERID(num)})

At this point we must make use of conditionals to specify specifically when we want to make changes to the Caller ID number and CNAM data. Asterisk has a built in function called IF() which provides the logic to do what we need. The following checks to see if the incoming Caller ID number is 8285750030 and if so it changes it to 999:

exten => _x.,1,Set(CALLERID(num)=${IF($[ ${CALLERID(num)} = 8285750030] ? 999 : ${CALLERID(num)})})

Assembling a Complete Context

Now that you understand how this works, let’s combine some conditionals. Using the Town of Canton as an example, they want all calls from the number 8286462000 to show up simply as 2911. To do this, we’re going to check for the number, check again in case it’s in 11 digit format, and then change the CNAM data to match but only if we’ve already changed the caller ID number:

exten => _x.,1,Set(CALLERID(num)=${IF($[ ${CALLERID(num)} = 8286462000] ? 2911 : ${CALLERID(num)})})
exten => _x.,n,Set(CALLERID(num)=${IF($[ ${CALLERID(num)} = 18286462000] ? 2911 : ${CALLERID(num)})})
exten => _x.,n,Set(CALLERID(name)=${IF($[ ${CALLERID(num)} = 2911] ? "2911" : ${CALLERID(name)})})

In the first statement we’re checking the Caller ID number to see if it matches 8286462000. If so, then we set it to 2911, otherwise we set it to the value it already has (which doesn’t change it). In the second statement, we do the exact same thing, just with the phone number in 11 digit format instead.

In the final statement note that we’re now checking to see if the Caller ID number is 2911. The only practical way it would be so is if it had just been changed by one of the previous statements. If we find that the Caller ID number is in fact 2911, then we set the CNAM data, or CALLERID(name) in this case, to be 2911 as well but note that we’ve wrapped it in quotes.

NOTE: If you’ll notice, the first statement in each Dial Plan begins with “_x.,1,” whereas subsequent statements begin with “_x.,n,”. The “_x.” section simplly means to execute the statement on all extensions. The “1” in the initial line indicates the initial priority and the “n” in subsequent lines simply tells Asterisk to increment the priority with each successive line.