Using the Diameter Client Capability of OpenSIPS 3.3

Network Points Technology - Free image on Pixabay

In the previous iteration, OpenSIPS 3.2 introduced a first version of the support for Diameter protocol peering by leveraging the freeDiameter project and its excellent C libraries. Building on top of this, OpenSIPS 3.3 now offers a way of building and sending arbitrary Diameter protocol requests, from the opensips.cfg script.

This brief post will teach you everything about the new client-side Diameter support.

Configuration

Say we want to send User-Data-Request (306) Diameter messages, as part of the “3GPP Sh  Application” (16777217). Before actually working on the opensips.cfg logic, we must configure the freeDiameter client library with any custom application IDs, message IDs and AVP templates.

To achieve this, we have extended the syntax of the dictionary.opensips RADIUS/Diameter configuration file. Here is how we would configure all of the above:

ATTRIBUTE DRMP                       301 integer
...
ATTRIBUTE Wildcarded-Public-Identity 634 string
ATTRIBUTE DSAI-Tag                   711 string
...
ATTRIBUTE UDR-Flags                  719 unsigned32
...
ATTRIBUTE Supported-Features         628 grouped
{
    Vendor-Id | REQUIRED | 1
    Feature-List-ID | REQUIRED | 1
    Feature-List | REQUIRED | 1
}

APPLICATION 16777217  3GPP Sh Application

REQUEST 306 User-Data-Request
{
    Session-Id | FIXED_HEAD | 1
    Origin-Host | REQUIRED | 1
    Origin-Realm | REQUIRED | 1
    DRMP | OPTIONAL | 1
    Wildcarded-Public-Identity | OPTIONAL | 1
    Data-Reference | REQUIRED | 1
    Supported-Features | OPTIONAL | 1
    ...
}

ANSWER 306 User-Data-Answer
{
    Session-Id | FIXED_HEAD | 1
    DRMP | OPTIONAL | 1
    Result-Code | OPTIONAL | 1
    Origin-Host | REQUIRED | 1
    Origin-Realm | REQUIRED | 1
    ....
}

Notice the sections of this file:

  • any freeDiameter-unknown AVPs must be explicitly defined
  • any freeDiameter-unknown Applications must be explicitly defined
  • any freeDiameter-unknown Requests and their Answers must be explicitly defined

Regarding the Request/Answer format, notice how an AVP may be of three types: FIXED_HEAD (it must be the top-most AVP), REQUIRED or OPTIONAL. The final integer suggests the “max occurrences” allowed for that AVP, in that respective message type.

Sending a Request

Once you’ve “trained” freeDiameter to properly recognize your intended Diameter AVP and request formats, it’s time to move over to the opensips.cfg file and script the request sending part. Here is an example request taken from the docs:

# Building an sending a My-Custom-Request (92001) for the
# My Diameter Application (42)
$var(payload) = "[
	{ \"Origin-Host\": \"client.diameter.test\" },
	{ \"Origin-Realm\": \"diameter.test\" },
	{ \"Destination-Realm\": \"diameter.test\" },
	{ \"Sip-From-Tag\": \"" + $ft + "\" },
	{ \"Sip-To-Tag\": \"" + $tt + "\" },
	{ \"Acct-Session-Id\": \"a59c-dff0d9efd167\" },
	{ \"Sip-Call-Duration\": " + $var(call_dur) + " },
	{ \"Sip-Call-Setuptime\": " + $var(setuptime) + " },
	{ \"Sip-Call-Created\": 1652372541 },
	{ \"Sip-Call-MSDuration\": " + $avp(ms_duration) + " },
	{ \"out_gw\": \"GW-774\" },
	{ \"Cost-Information\": [
            {\"Unit-Value\": [{\"Value-Digits\": 1000}]},
            {\"Currency-Code\": 35}
            ]}

]";

$var(rc) = dm_send_request(42, 92001, $var(payload), $var(rpl_avps));
xlog("rc: $var(rc), AVPs: $var(rpl_avps)\n");

Since the AVPs are well-known, we only have to specify their string name and the library will take care of looking them up and plugging in the appropriate code in the Diameter packet. The complete list of AVP codes and their values will effectively form the entire payload of the Diameter message: easy stuff! To avoid introducing too much complexity, we decided to require you to pass this information as a JSON Array string – the module will take care of interpreting the content, as long as it’s properly formatted.

Once we have the payload, we just send it out to the configured peer of the aaa_diameter module, using the dm_send_request() function.

PS: regarding pre-configuration, do make sure to check out the freediameter-extensions package, as it contains a lot of pre-defined Diameter applications, AVPs, requests and answers, possibly even the 3GPP ones discussed above.

Processing an Answer

Diameter replies will often contain several important pieces of data (AVPs), so OpenSIPS provides all AVPs of the Diameter Answer as a JSON Array (similar to the request JSON!), stored in an output variable (in our case: the $var(rpl_avps) variable). Once we have it, we use the json module in order to parse and iterate it:

$json(avps) := $var(rpl_avps);

for ($var(avp) in $(json(avps)[*])) {
  xlog("we have reply AVP: $var(avp)\n");
  ...
}

Further Improvements

There are several features from which the aaa_diameter module could further benefit. Support for dynamic peering (would having a short-lived Diameter exchange with an arbitrary peer be useful?), grouped AVPs, customizable AVP vendor IDs to name a few which I see as being useful.

But what is your favourite part of the Diameter support? Can you build your desired Diameter components and message exchanges with the current set of features? And, most importantly, will you be at OpenSIPS Summit 2022 in Athens to talk more about it?

11 thoughts on “Using the Diameter Client Capability of OpenSIPS 3.3

  1. Hi Liviuchircu,
    Thank you for helping me last time.
    Now am facing another issue. If i follow the same procedure as mentioned above and when sending Diameter message, then there is no Vendor-Id and vendor bit is set for few AVP’s. So after searching i found out that and Extention File need to be configured in freeDiameter.config file. After adding am getting error -22 while bringing up the opensips binary.

    805:48:28 DBG Generating fresh Diffie-Hellman parameters of size 1024 (this takes some time)…
    05:48:28 DBG Loading PS : /usr/local/lib/freeDiameter/dict_dcca_3gpp.fdx
    05:48:28 DBG Loading #####PS : /usr/local/lib/freeDiameter/dict_dcca_3gpp.fdx
    05:48:28 FATAL! PS Loading of extension /usr/local/lib/freeDiameter/dict_dcca_3gpp.fdx failed: /usr/local/lib/freeDiameter/dict_dcca_3gpp.fdx: undefined symbol: fd_g_config
    05:48:28 ERROR ERROR: in ‘((fd_ext_load()))’ : Invalid argument
    Nov 11 05:48:28 [5396] ERROR:aaa_diameter:freeDiameter_init: error in ((fd_core_parseconf(dm_conf_filename))): -22
    Nov 11 05:48:28 [5396] ERROR:aaa_diameter:diameter_peer_loop: failed to init freeDiameter library

    Can you please help me to overcome this error.

    Thank you so much

    Pavan

    Like

  2. Hi Liviuchircu,

    Can you please post a sample example of encoding JSON array string with variables. It will be really helpful.

    Thank you and have a nice day.
    Pavan

    Like

    1. Sure thing, pspavan56! In opensips.cfg, when assigning strings to variables, you cannot use string interpolation, unfortunately. So you will have to do something like: a = string1 + variable1 + string2 + variable2 + string3. I will update the example so it includes a few variables too. Thank you for the suggestion!

      Like

  3. Hi,

    Just took the latest Opensips-3.4-Dev source and same issue observed.

    root@ec-192-168-107-18-Ubuntu-18-04-dc:/home/ecadmin/opensips# opensips -V
    version: opensips 3.4.0-dev (x86_64/linux)
    flags: STATS: On, DISABLE_NAGLE, USE_MCAST, SHM_MMAP, PKG_MALLOC, Q_MALLOC, F_MALLOC, HP_MALLOC, DBG_MALLOC, CC_O0, FAST_LOCK-ADAPTIVE_WAIT
    ADAPTIVE_WAIT_LOOPS=1024, MAX_RECV_BUFFER_SIZE 262144, MAX_LISTEN 16, MAX_URI_SIZE 1024, BUF_SIZE 65535
    poll method support: poll, epoll, sigio_rt, select.
    git revision: 6e735356e
    main.c compiled on 04:03:59 Jul 11 2022 with gcc 7

    Required Diameter libs are properly initialized,

    04:07:40 NOTI libfdproto ‘1.5.0-1562+(6219359a36a9+)’ initialized.
    04:07:40 NOTI libfdcore ‘1.5.0-1562+(6219359a36a9+)’ initialized.

    At the start of Opensips CCR and CCA diameter messages are properly exchanged between Opensips and HSS.

    Below is the error am getting,

    Jul 11 04:08:57 [17650] rc: [
    { “Origin-Host”: “client.diameter.test” },
    { “Origin-Realm”: “diameter.test” },
    { “Destination-Realm”: “hss.ims.mnc001.mcc001.3gppnetwork.org” },
    { “Sip-From-Tag”: “dc93-4fba-91db” },
    { “Sip-To-Tag”: “ae12-47d6-816a” },
    { “Acct-Session-Id”: “a59c-dff0d9efd167” },
    { “Sip-Call-Duration”: 6 },
    { “Sip-Call-Setuptime”: 1 },
    { “Sip-Call-Created”: 1652372541 },
    { “Sip-Call-MSDuration”: 5850 }
    ]
    Jul 11 04:08:57 [17650] ERROR:aaa_diameter:dm_send_request: unrecognized Request command code: 92001
    Jul 11 04:08:57 [17650] ERROR:aaa_diameter:dm_send_request: to fix this, you can define the Request/Answer format in the ‘extra-avps-file’ config file
    Jul 11 04:08:57 [17650] rc: -1, AVPs:

    Please Suggest.

    Thank You,
    Pavan

    Like

    1. Hi, did you set the “extra-avps-file” modparam value? Follow this example:

      modparam(“acc”, “aaa_url”, “diameter:freeDiameter-client.conf;
      extra-avps-file: /var/tmp/acc-avps.conf”)

      Like

      1. Hi Liviuchircu,

        Thank you so much for the response.

        Before i didn’t add ‘extra-avps-file’ modparam values. I have updated accordingly,

        loadmodule “acc.so”
        modparam(“acc”, “aaa_url”, “diameter:freeDiameter.conf;
        extra-avps-file: /var/tmp/dictionary.opensips”)

        But still am facing the problem. Below is the error message from logs,

        Jul 12 13:53:40 [28977] DBG:core:init_mod: initializing module aaa_diameter
        Jul 12 13:53:40 [28977] DBG:aaa_diameter:mod_init: initializing module…
        Jul 12 13:53:40 [28977] INFO:aaa_diameter:dm_init_minimal: initializing the Diameter object dictionary…
        Jul 12 13:53:40 [28977] DBG:core:init_mod: register MI for aaa_diameter
        Jul 12 13:53:40 [28977] DBG:core:init_mod: initializing module acc
        Jul 12 13:53:40 [28977] INFO:acc:mod_init: initializing…
        Jul 12 13:53:40 [28977] DBG:core:find_mod_cmd_export_t: found in module tm [/usr/local/lib64/opensips/modules/]
        Jul 12 13:53:40 [28977] DBG:core:find_mod_export: found in module aaa_diameter [/usr/local/lib64/opensips/modules/]
        Jul 12 13:53:40 [28977] DBG:core:aaa_prot_bind: using aaa bind api for aaa_diameter
        Jul 12 13:53:40 [28977] DBG:aaa_diameter:parse_config_string: freeDiameter cfg file: ‘freeDiameter.conf’
        Jul 12 13:53:40 [28977] DBG:aaa_diameter:parse_config_string: freeDiameter extra-avps-file: ‘/var/tmp/dictionary.opensips’
        Jul 12 13:53:40 [28977] DBG:aaa_diameter:parse_attr_def: registered custom AVP (Sip-Method, code 204, type integer32, sub-avps: 0)
        13:53:40 ERROR error in ((fd_dict_new(fd_g_config->cnf_dict, (DICT_AVP), (&data), (parent), (pref)))): -17

        Jul 12 13:53:40 [28977] ERROR:aaa_diameter:dm_init_prot: failed to load the ‘extra-avps-file’
        Jul 12 13:53:40 [28977] ERROR:acc:init_acc_aaa: AAA protocol initialization failure
        Jul 12 13:53:40 [28977] ERROR:acc:mod_init: failed to init radius
        Jul 12 13:53:40 [28977] ERROR:core:init_mod: failed to initialize module acc
        Jul 12 13:53:40 [28977] ERROR:core:main: error while initializing modules
        Jul 12 13:53:40 [28977] INFO:core:cleanup: cleanup

        Please suggest what to do next. It will be really great helpful.

        Thank You,
        Pavan

        Like

      2. Can you post your dictionary.opensips content? Error -17 means: “EEXIST”, so the freeDiameter library is most likely complaining that you are trying to re-define a well-known AVP (which is already present in its internal lookup tables) 😉

        Like

  4. Hi Liviuchiru,

    I have tried sending diameter message as said above but am getting error as,

    Jul 8 07:56:17 [27884] ERROR:aaa_diameter:dm_send_request: to fix this, you can define the Request/Answer format in the ‘extra-avps-file’ config file
    Jul 8 07:56:17 [27884] rc: -1, AVPs:

    I followed the same procedure as said in this post.

    Can you please suggest how to processed.

    I am using Opensips-3.3 Version and Freediameter- 1.5 Version

    Thank You,
    Pavan

    Like

  5. Hello! Both the blog post and the aaa_diameter module docs have been updated to include examples of the recently finalized **Grouped AVP support**! And since it’s a critical feature, the Grouped AVP support has been backported to the 3.3 branch as well.

    Enjoy!

    Like

Leave a comment