Extensions_additional.conf | Where are the include elements located?

Hi FreePBX Pros!

In the context definitions of the configuration file /etc/asterisk/extensions_additional.conf there are “include” lines in every context. Example:

[sub-diversion-header]
include => sub-diversion-header-custom
exten => s,1,Set(DIVERSION_REASON=${IF($[${LEN(${DIVERSION_REASON})}=0]?no-answer:${DIVERSION_REASON})})
exten => s,n,Gosub(func-set-sipheader,s,1(Diversion,<tel:${FROM_DID}>\;reason=${DIVERSION_REASON}\;screen=no\;privacy=off))
exten => s,n,Return()

;--== end of [sub-diversion-header] ==--;

Here the “include” line is

include => sub-diversion-header-custom

My question:

  1. The referenced element “sub-diversion-header-custom”, is it a file?
  2. If yes, where can I find the file? It seems that it does not exist by default.
  3. If I have to create this file, where do I have to store it and how does it look like? Any examples?

Thank you!

It is not a file, it refers to another context[1].

[1] https://wiki.asterisk.org/wiki/display/AST/Include+Statements+Basics

OK, I understand that the custom contexts do not exist by default. They are only referenced in the “standard” contexts by include statement, in case you want to create a customised context.

If I want to create a custom context for the extensions_additional.conf file, do I have to create it in the extensions_override_freepbx.conf file ?

Hi @sipsepp

Most of the FreePBX generated contexts also include a corresponding custom context but none of them are usable. They remain as a remnant from legacy versions.

If you want to create your very own Asterisk context, you would put it in the file extensions_custom.conf. If you want to edit one of the FreePBX generated contexts in any way, you would copy it to extensions_override_freepbx.conf and make whatever changes you want. This will work fine, but you will never know if the changes you are introducing will be forward compatible with future generated dialplan, so use of the extensions_override_freepbx.conf is strongly discouraged and only for advanced users. I do a fair bit of FreePBX customization and I NEVER use the override file.

Hi @lgaetz

thank you for your reply.

I want to change one of the FreePBX generated contexts in extensions_additional.conf file.

You stated that you do FreePBX customisations and mentioned the extensions_custom.conf file. Is my assumption correct that you would create a customised extensions_additional.conf context in the extensions_custom.conf file?

Would the new context created in extensions_custom.conf file override the original context in extensions_additional.conf or do you have to delete it?

No, it is the literal opposite of what I wrote:

That is how you do what you’re asking, but I am recommending that you don’t do it.

Well, I already tried the extensions_override_freepbx.conf way, but the changes didn’t take effect (having executed fwconsole restart and even complete system reboot after the manipulation).

I understood that creating the customised context in the extensions_custom.conf file would be an alternative to the extensions_override_freepbx.conf way, because you stated that you customised your FreePBX that way.

Here is the thing about includes, they will only be executed if there is no other match in the existing context that is being used. So it doesn’t matter what you put in the _custom version if the main context matches, your include is never executed.

You are being recommended to forget about extensions_override_freepbx.conf entirely.

Instead you are probably better off explaining the details of the dial plan you want to change or add or whatever your want to accomplish, and then people can tell you how to achieve that.

Thank you @BlazeStudios for the hint.

From @lgaetz we learned that the include statements are not usable, so we forget about them, shouldn’t we?

My issue is that a customised context (precisely it is the [sub-diversion-header] context) which I added to extensions_override.conf file will not take effect. It should override the original context (same name) which is located in extensions_additonal.conf file.

Thank you @avayax for the proposal.

I have to customise the [sub-diversion-header] context to meet my SIP provider’s requirements for Call Forwardings, where a new INVITE request is being created.

The SIP trace shows this diversion header value

sip:[email protected];reason=unconditional

and my provider told me that the following value is expected:

sip:[email protected];reason=unconditional

Without the full number (country code Germany +49, Munich preselection 89, trunk number 9876, extension number 123) the authentication of the INVITE request will fail.

The respective context looks like this:

[sub-diversion-header]
include => sub-diversion-header-custom
exten => s,1,Set(DIVERSION_REASON=${IF($[${LEN(${DIVERSION_REASON})}=0]?no-answer:${DIVERSION_REASON})})
exten => s,n,Gosub(func-set-sipheader,s,1(Diversion,tel:${FROM_DID};reason=${DIVERSION_REASON};screen=no;privacy=off))
exten => s,n,Return()

;–== end of [sub-diversion-header] ==–;

and (I suppose that) I must customise it to look like this:

[sub-diversion-header]
include => sub-diversion-header-custom
exten => s,1,Set(DIVERSION_REASON=${IF($[${LEN(${DIVERSION_REASON})}=0]?no-answer:${DIVERSION_REASON})})
exten => s,n,Gosub(func-set-sipheader,s,1(Diversion,tel:+49899876${FROM_DID};reason=${DIVERSION_REASON};screen=no;privacy=off))
exten => s,n,Return()

;–== end of [sub-diversion-header] ==–;

See, that’s why I didn’t want to present the precise case but a more general approach. It seems that nobody knows how to rewrite the diversion header.

The general approache’s question was, how to customise any context of the extensions_additional.conf file.

I understood that you shouldn’t use the extensions_override_freepbx.conf file, but if for the FreePBX maker this is the designated (and may be the only) method to customise contexts, I would take the risk that in future FreePBX versions it wouldn’t work anymore.

As I already stated, I already added a customised [sub-diversion-header] context to the override file, but it didn’t take effect. The SIP trace still shows the original diversion header, lacking the +49899876 prefix and the forwarded call still fails.

What could be the cause that a customised context won’t take effect?

I just cannot believe that no FreePBX installation uses a Vodafone SIP connection* and where a working call forwarding function is not needed.

  • or any other provider who requests the full telephone number within the diversion header for the authentication not not fail.

If you call out on a trunk there is the macro-dialout-trunk-predial-hook macro that you can use to run custom dial plan right before the call is sent out.

So in extensions_custom.conf, you would have [macro-dialout-trunk-predial-hook] and put dial plan in there that adds a SIP header.
[macro-dialout-trunk-predial-hook]
exten => s,1,yourdialplan
exten => s,n,MacroExit()

1 Like

Exactly. You want to do something like I did here:

Edit: the context [sip-diversion-header] does not exist on my Asterisk 16 based FreePBX 14 systems. I don’t have immediate access to a system running something else to check against.

So I added my sub-diversion-header related dial plan to the extensions_custom.conf file which looked like this prior to the manipulation:

[ats-internal]

exten => _X.,1,NoOp(Default routing to SIP Endpoint)
  same => n,Dial(PJSIP/${EXTEN},20)

…and like this after the manipulation:

[ats-internal]

exten => _X.,1,NoOp(Default routing to SIP Endpoint)
  same => n,Dial(PJSIP/${EXTEN},20)

[macro-dialout-trunk-predial-hook]
exten => s,1,Set(DIVERSION_REASON=${IF($[${LEN(${DIVERSION_REASON})}=0]?no-answer:${DIVERSION_REASON})})
exten => s,n,Gosub(func-set-sipheader,s,1(Diversion,tel:+49899876${FROM_DID};reason=${DIVERSION_REASON};screen=no;privacy=off))
exten => s,n,MacroExit()

Result:

On forwarded calls, the diversion header looks exactly like before:

Diversion: <sip:[email protected]>;reason=unconditional

, lacking the trunk number and the forwarded call will fail due to authentication error.

Interestingly, on direct external calls (e.g. from my sip desk phone to a mobile device), the call will fail and the diversion header looks like this:

Diversion: tel:+49899876

Conclusion:
The [macro-dialout-trunk-predial-hook] has an unwanted effect on outgoing calls, but on forwarded calls, the diversion header is not interested in any way what the predial hook tells him.

Are you sure your Gosub even works in your dial plan?

Why not try something simple first.
Chansip or pjsip?(SIPAddHeader command is for chansip):

[macro-dialout-trunk-predial-hook]
exten => s,1,SIPAddHeader(Diversion:<sip:[email protected]>;reason=unconditional)
exten => s,n,MacroExit()

There is also a GUI setting that let’s you generate diversion headers in advanced settings. Maybe this is all that you need:

Well, the original dial plan is

[sub-diversion-header]
include => sub-diversion-header-custom
exten => s,1,Set(DIVERSION_REASON=${IF($[${LEN(${DIVERSION_REASON})}=0]?no-answer:${DIVERSION_REASON})})
exten => s,n,Gosub(func-set-sipheader,s,1(Diversion,tel:${FROM_DID};reason=${DIVERSION_REASON};screen=no;privacy=off))
exten => s,n,Return()

;–== end of [sub-diversion-header] ==–;

The line to investigate should be this one:

sipheader,s,1(Diversion,tel:${FROM_DID};reason=${DIVERSION_REASON};screen=no;privacy=off))

And the SIP trace shows this diversion header on forwarded calls:

sip:[email protected];reason=unconditional

If I am not totally wrong ${FROM_DID} shall reflect the extension number of the DID the caller dialed. In this case it should be the 123 and the diversion header shows that. So I should assume that the origianl dial plan works, shouldn’t I?

You mentioned the advanced settings’ Generate Diversion Headers option in the GUI. I already knew about that option and I played around with it. Interestingly, the SIP trace always shows the diversion header no matter if the above mentioned option is set to YES or NO.

I tried the [macro-dialout-trunk-predial-hook] you provided. The extensions_custom.conf lokked lik this having added it:

[ats-internal]

exten => _X.,1,NoOp(Default routing to SIP Endpoint)
  same => n,Dial(PJSIP/${EXTEN},20)

[macro-dialout-trunk-predial-hook]
exten => s,1,SIPAddHeader(Diversion:<sip:[email protected]>;reason=unconditional)
exten => s,n,MacroExit()

Result:

  1. Outgoing calls are not affected. They work as expected.

  2. Forwarded Calls still do not work. The diversion header in the SIP trace still looks like this:

sip:[email protected];reason=unconditional

have you validated that if clause within the context you are attempting to check things?

Also have you validated ${FROM_DID} it sounds like you are simply assuming.

dump the channel and look at things.

exten => s,n,DumpChan()

Where would I have to add this line in order to dump the channel? To the [macro-dialout-trunk-predial-hook] ?

Like this?

[macro-dialout-trunk-predial-hook]
exten => s,1,SIPAddHeader(Diversion:<sip:[email protected]>;reason=unconditional)
exten => s,n,DumpChan()
exten => s,n,MacroExit()

And then I could investigate the asterisk log file /var/log/asterisk/full to see the dump’s output?

OK there are a couple things I’m seeing in this thread that should be addressed.

  1. The semi-colon (;) in Asterisk is a comment delimiter and must be escaped. So it needs to be like this:

exten => s,1,SIPAddHeader(Diversion<sip:[email protected]>\;reason=unconditional)
That will escape the semi-colon. It needs to be done each time a semi-colon is used for these things.

  1. ${FROM_DID} is only set during the Inbound Route and it is not a global variable. Which means it will not be set on child channels that result from the inbound call.

  2. The actual call flow needs to be outlined here. When is this call being forwarded? I see Dial() code to hit an extension so is this when the extension is a no answer? What is going on here?

The last question would shed some light on at what point in the dialplan this is expected to happen so we can fully understand what variables and processes are being hit. There’s not even a single debug showing how this is being processed.