AAA_DIAMETER MODULE
     __________________________________________________________

   Table of Contents

   1. Admin Guide

        1.1. Overview
        1.2. Diameter Client
        1.3. Diameter Server
        1.4. Dependencies

              1.4.1. OpenSIPS Modules
              1.4.2. External Libraries or Applications

        1.5. Exported Parameters

              1.5.1. fd_log_level (integer)
              1.5.2. realm (string)
              1.5.3. peer_identity (string)
              1.5.4. aaa_url (string)
              1.5.5. answer_timeout (integer)

        1.6. Exported Functions

              1.6.1. dm_send_request(app_id, cmd_code, avps_json,
                      [rpl_avps_pv])

              1.6.2. dm_send_answer(avps_json, [is_error])

        1.7. Exported Asyncronous Functions

              1.7.1. dm_send_request(app_id, cmd_code, avps_json,
                      [rpl_avps_pv])

        1.8. Exported Events

              1.8.1. E_DM_REQUEST

   2. Contributors

        2.1. By Commit Statistics
        2.2. By Commit Activity

   3. Documentation

        3.1. Contributors

   List of Tables

   2.1. Top contributors by DevScore^(1), authored commits^(2) and
          lines added/removed^(3)

   2.2. Most recently active contributors^(1) to this module

   List of Examples

   1.1. Setting the fd_log_level parameter
   1.2. Setting the realm parameter
   1.3. Setting the peer_identity parameter
   1.4. Setting the aaa_url parameter
   1.5. Setting the aaa_url parameter
   1.6. Setting the answer_timeout parameter
   1.7. dictionary.opensips extended syntax
   1.8. dm_send_request usage
   1.9. dm_send_answer() usage
   1.10. dm_send_request asynchronous usage

Chapter 1. Admin Guide

1.1. Overview

   This module provides an RFC 6733 Diameter peer implementation,
   being able to act as either Diameter client or server, or both.

   Any module that wishes to use it has to do the following:
     * include aaa.h
     * make a bind call with a proper Diameter-specific URL, e.g.
       "diameter:freeDiameter-client.conf"

1.2. Diameter Client

   The module implements the core AAA OpenSIPS interface, thus
   offering an alternative client implementation to the aaa_radius
   module which can be useful, for example, when performing
   billing and accounting for the live SIP calls.

   In addition to the RADIUS client's auth and accounting
   features, the Diameter client includes support for sending
   arbitrary Diameter requests, further opening up the scope of
   applications which can be achieved through OpenSIPS scripting.
   Such Diameter requests can be sent using the dm_send_request()
   function.

1.3. Diameter Server

   Starting with OpenSIPS 3.5, the Diameter module includes
   server-side support as well.

   First, the event_route module must be loaded in order to be
   able to process E_DM_REQUEST events in the OpenSIPS
   configuration file. These events will contain all necessary
   information on the incoming Diameter request.

   Finally, once the request information is processed and the
   answer AVPs are prepared, script writers should use the
   dm_send_answer() function in order to reply with a Diameter
   answer message.

   Recommendation: When possible, always load the dict_sip.fdx
   freeDiameter extension module inside your freeDiameter.conf
   configuration file, as it contains hundreds of well-known AVP
   definitions which may be good to have when inter-operating with
   other Diameter peer implementations.

1.4. Dependencies

1.4.1. OpenSIPS Modules

   None.

1.4.2. External Libraries or Applications

   All Diameter message building and parsing, as well as the peer
   state machine and Diameter-related network communication are
   all powered by the freeDiameter project and C libraries,
   dynamically linking with the "aaa_diameter" module.

   The following libraries must be installed before running
   OpenSIPS with this module loaded:
     * libfdcore v1.2.1 or higher
     * libfdproto v1.2.1 or higher

1.5. Exported Parameters

1.5.1. fd_log_level (integer)

   This parameter measures the quietness of the logging done by
   the freeDiameter library. Possible values:
     * 0 (ANNOYING)
     * 1 (DEBUG)
     * 3 (NOTICE, default)
     * 5 (ERROR)
     * 6 (FATAL)

   NOTE: since freeDiameter logs to standard output, you must also
   enable the new core parameter, log_stdout, before getting any
   logs from the library.

   Example 1.1. Setting the fd_log_level parameter

modparam("aaa_diameter", "fd_log_level", 0)


1.5.2. realm (string)

   The unique realm to be used by all participating Diameter
   peers.

   Default value is "diameter.test".

   Example 1.2. Setting the realm parameter

modparam("aaa_diameter", "realm", "opensips.org")


1.5.3. peer_identity (string)

   The identity (realm subdomain) of the Diameter server peer, to
   which the OpenSIPS Diameter client peer will connect.

   Default value is "server" (i.e. "server.diameter.test").

   Example 1.3. Setting the peer_identity parameter

modparam("aaa_diameter", "peer_identity", "server")


1.5.4. aaa_url (string)

   URL of the diameter client: the configuration file, with an
   optional extra-avps-file, where the Diameter client is
   configured.

   By default, the connection is not created.

   Example 1.4. Setting the aaa_url parameter

modparam("aaa_diameter", "aaa_url", "diameter:freeDiameter-client.conf")


   Example 1.5. Setting the aaa_url parameter
   with an extra AVPs file.

modparam("aaa_diameter", "aaa_url", "diameter:freeDiameter-client.conf;e
xtra-avps-file:dictionary.opensips")


1.5.5. answer_timeout (integer)

   Time, in milliseconds, after which a dm_send_request() function
   call with no received reply will time out and return a -2 code.

   Default value is 2000 ms.

   Example 1.6. Setting the answer_timeout parameter

modparam("aaa_diameter", "answer_timeout", 5000)


1.6. Exported Functions

1.6.1.  dm_send_request(app_id, cmd_code, avps_json, [rpl_avps_pv])

   Perform a blocking Diameter request over to the interconnected
   peer and return the Result-Code AVP value from the reply.

   Parameters
     * app_id (integer) - ID of the application. A custom
       application must be defined in the dictionary.opensips
       Diameter configuration file before it can be recognized.
     * cmd_code (integer) - ID of the command. A custom command
       code, name and AVP requirements must be defined in the
       dictionary.opensips Diameter configuration file beforehand.
       body of the HTTP response.
     * avps_json (string) - A JSON Array containing the AVPs to
       include in the message.
     * rpl_avps_pv (var, optional) - output variable which will
       hold all AVP names from the Diameter Answer along with
       their values, packed as a JSON Array string. The "json"
       module and its $json variable could be used to iterate this
       array.

   Return Codes
     * 1 - Success
     * -1 - Internal Error
     * -2 - Request timeout (the answer_timeout was exceeded
       before an Answer could be processed)

   This function can be used from any route.

   Example 1.7. dictionary.opensips extended syntax

# Example of defining custom Diameter AVPs, Application IDs,
# Requests and Replies in the "dictionary.opensips" file

ATTRIBUTE out_gw            232 string
ATTRIBUTE trunk_id          233 string

ATTRIBUTE rated_duration    234 integer
ATTRIBUTE call_cost         235 integer

ATTRIBUTE Exponent          429 integer32
ATTRIBUTE Value-Digits      447 integer64

ATTRIBUTE Cost-Unit 424 grouped
{
        Value-Digits | REQUIRED | 1
        Exponent | OPTIONAL | 1
}

ATTRIBUTE Currency-Code     425 unsigned32

ATTRIBUTE Unit-Value  445 grouped
{
        Value-Digits | REQUIRED | 1
        Exponent | OPTIONAL | 1
}

ATTRIBUTE Cost-Information  423 grouped
{
        Unit-Value | REQUIRED | 1
        Currency-Code | REQUIRED | 1
        Cost-Unit | OPTIONAL | 1
}

APPLICATION 42 My Diameter Application

REQUEST 92001 My-Custom-Request
{
        Origin-Host | REQUIRED | 1
        Origin-Realm | REQUIRED | 1
        Destination-Realm | REQUIRED | 1
        Transaction-Id | REQUIRED | 1
        Sip-From-Tag | REQUIRED | 1
        Sip-To-Tag | REQUIRED | 1
        Acct-Session-Id | REQUIRED | 1
        Sip-Call-Duration | REQUIRED | 1
        Sip-Call-Setuptime | REQUIRED | 1
        Sip-Call-Created | REQUIRED | 1
        Sip-Call-MSDuration | REQUIRED | 1
        out_gw | REQUIRED | 1
        call_cost | REQUIRED | 1
        Cost-Information | OPTIONAL | 1
}

ANSWER 92001 My-Custom-Answer
{
        Origin-Host | REQUIRED | 1
        Origin-Realm | REQUIRED | 1
        Destination-Realm | REQUIRED | 1
        Transaction-Id | REQUIRED | 1
        Result-Code | REQUIRED | 1
}


   Example 1.8. dm_send_request usage

# Building an sending an 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\": \"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 },
        { \"out_gw\": \"GW-774\" },
        { \"cost\": \"10.84\" },
        { \"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");
$json(avps) := $var(rpl_avps);


1.6.2.  dm_send_answer(avps_json, [is_error])

   Send back a Diameter answer message to the interconnected peer
   in a non-blocking fashion, in response to its request.

   The following fields will be automatically copied over from the
   Diameter request when building the answer message:
     * Application ID
     * Command Code
     * Session-Id AVP, if any
     * Transaction-Id AVP, if any (only applies when Session-Id is
       not present)

   Parameters
     * avps_json (string) - A JSON Array containing the AVPs to
       include in the answer message (example below).
     * is_error (boolean, default: false) - Set to true in order
       to set the 'E' (error) bit in the answer message.

   Return Codes
     * 1 - Success
     * -1 - Internal Error

   This function can only be used from an EVENT_ROUTE.

   Example 1.9. dm_send_answer() usage

event_route [E_DM_REQUEST] {
  xlog("Req: $param(sess_id) / $param(app_id) / $param(cmd_code)\n");
  xlog("AVPs: $param(avps_json)\n");

  $json(avps) := $param(avps_json);

  /* ... process the data (AVPs) ... */

  /* ... and reply back with more AVPs! */
  $var(ans_avps) = "[
          { \"Vendor-Specific-Application-Id\": [{
                  \"Vendor-Id\": 0
                  }] },

          { \"Result-Code\": 2001 },
          { \"Auth-Session-State\": 0 },
          { \"Origin-Host\": \"opensips.diameter.test\" },
          { \"Origin-Realm\": \"diameter.test\" }
  ]";

  if (!dm_send_answer($var(ans_avps)))
    xlog("ERROR - failed to send Diameter answer\n");
}


1.7. Exported Asyncronous Functions

1.7.1.  dm_send_request(app_id, cmd_code, avps_json, [rpl_avps_pv])

   Similar to dm_send_request() but performs an asynchronous
   Diameter request.

   Uses the same parameters and return codes as dm_send_request().

   Example 1.10. dm_send_request asynchronous usage

# Building an sending an 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\": \"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 },
        { \"out_gw\": \"GW-774\" },
        { \"cost\": \"10.84\" },
        { \"Cost-Information\": [
                {\"Unit-Value\": [{\"Value-Digits\": 1000}]},
                {\"Currency-Code\": 35}
                ]}
]";

async(dm_send_request(42, 92001, $var(payload), $var(rpl_avps), dm_reply
);

route[dm_reply] {
        xlog("rc: $retcode, AVPs: $var(rpl_avps)\n");
        $json(avps) := $var(rpl_avps);
}


1.8. Exported Events

1.8.1.  E_DM_REQUEST

   This event is raised whenever the aaa_diameter module is loaded
   and OpenSIPS receives a Diameter request on the configured
   Diameter listening interface.

   Parameters:
     * app_id (integer) - the Diameter Application Identifier
     * cmd_code (integer) - the Diameter Command Code
     * sess_id (string) - the value of either the Session-Id AVP,
       Transaction-Id AVP or a NULL value if neither of these
       transaction-identifying AVPs is present in the Diameter
       request.
     * avps_json (string) - a JSON Array containing the AVPs of
       the request. Use the json module's $json variable to easily
       parse and work with it.

   Note that this event is currently designed to be mainly
   consumed by an event_route, since that is the only way to gain
   access to the dm_send_answer() function in order to build
   custom answer messages. On the other hand, if the application
   does not mind the answer being always a 3001
   (DIAMETER_COMMAND_UNSUPPORTED) error, this event can be
   successfully consumed through any other EVI-compatible delivery
   channel ☺️

Chapter 2. Contributors

2.1. By Commit Statistics

   Table 2.1. Top contributors by DevScore^(1), authored
   commits^(2) and lines added/removed^(3)
                   Name               DevScore Commits Lines ++ Lines --
   1. Liviu Chircu (@liviuchircu)       113      37      6850     1105
   2. Razvan Crainea (@razvancrainea)    38      21      1423     251
   3. Peter Lemenkov (@lemenkov)         4        2       2        2
   4. Larry Laffer                       3        1       6        5
   5. Maksym Sobolyev (@sobomax)         3        1       5        5
   6. Alexandra Titoc                    2        1       8        0

   (1) DevScore = author_commits + author_lines_added /
   (project_lines_added / project_commits) + author_lines_deleted
   / (project_lines_deleted / project_commits)

   (2) including any documentation-related commits, excluding
   merge commits. Regarding imported patches/code, we do our best
   to count the work on behalf of the proper owner, as per the
   "fix_authors" and "mod_renames" arrays in
   opensips/doc/build-contrib.sh. If you identify any
   patches/commits which do not get properly attributed to you,
   please submit a pull request which extends "fix_authors" and/or
   "mod_renames".

   (3) ignoring whitespace edits, renamed files and auto-generated
   files

2.2. By Commit Activity

   Table 2.2. Most recently active contributors^(1) to this module
                   Name                 Commit Activity
   1. Razvan Crainea (@razvancrainea) May 2023 - Nov 2025
   2. Peter Lemenkov (@lemenkov)      Jul 2024 - Jul 2025
   3. Larry Laffer                    Jul 2025 - Jul 2025
   4. Alexandra Titoc                 Sep 2024 - Sep 2024
   5. Liviu Chircu (@liviuchircu)     May 2021 - Mar 2024
   6. Maksym Sobolyev (@sobomax)      Feb 2023 - Feb 2023

   (1) including any documentation-related commits, excluding
   merge commits

Chapter 3. Documentation

3.1. Contributors

   Last edited by: Liviu Chircu (@liviuchircu), Razvan Crainea
   (@razvancrainea).

   Documentation Copyrights:

   Copyright © 2021 www.opensips-solutions.com
