Documentation

Documentation.Tutorials-Diameter-Client-Server History

Hide minor edits - Show changes to markup

March 07, 2024, at 05:12 PM by liviu -
Added lines 113-124:

log_stdout = yes ... loadmodule "aaa_diameter.so" modparam("aaa_diameter", "fd_log_level", 0) modparam("aaa_diameter", "realm", "diameter.test") modparam("aaa_diameter", "peer_identity", "server") ... @]


[@

Added line 183:

log_stdout = yes

Added lines 185-189:

loadmodule "aaa_diameter.so" modparam("aaa_diameter", "fd_log_level", 0) modparam("aaa_diameter", "realm", "diameter.test") modparam("aaa_diameter", "peer_identity", "server")

March 07, 2024, at 12:50 PM by liviu -
Added lines 32-99:

@]

Defining a Generic Diameter Request + Answer

While the freeDiameter library is very robust, this also means it will be very nitpicky with its "known" set of Diameter Applications and Commands. The set of currently known apps and commands (along with each command's precise AVP structure!) make up the library's dictionary, in freeDiameter terminology.


This means that before we can build and send a generic request, we must make sure to define the request in the freeDiameter dictionary. You can achieve this by attaching an ;extra-avps-file:<path-to-dictionary.opensips> option to the aaa_url modparam of aaa_diameter. In order to define Apps and Command AVP structure, we have extended the classic, AAA dictionary.opensips AVP definitions file to support this. See dm_send_request for full examples.


For our case, we only need the following in dictionary.opensips:


[@ 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
	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

}

March 07, 2024, at 12:41 PM by liviu -
Changed line 124 from:

Next, the request must be processed according to the application specifications. Effectively, the result will be a set of AVPs to be included in the answer. Make sure to pack them as a JSON Array (similar to the input of dm_send_request()), before finally calling dm_send_answer():

to:

Next, the request must be processed according to the application specifications. Effectively, the result will be a set of AVPs to be included in the answer. Make sure to pack them as a JSON Array (similar to the input of dm_send_request()), before finally calling dm_send_answer():

March 07, 2024, at 12:41 PM by liviu -
Changed line 124 from:

Next, the request must be processed according to the application specifications. Effectively, the result will be a set of AVPs to be included in the answer. Make sure to pack them as a JSON Array (similar to the input of dm_send_request()), before calling dm_send_answer():

to:

Next, the request must be processed according to the application specifications. Effectively, the result will be a set of AVPs to be included in the answer. Make sure to pack them as a JSON Array (similar to the input of dm_send_request()), before finally calling dm_send_answer():

March 07, 2024, at 12:39 PM by liviu -
Changed lines 120-143 from:
  • avps_json (string) - a JSON Array containing the AVPs of the request
to:
  • avps_json (string) - a JSON Array containing the AVPs of the request


Next, the request must be processed according to the application specifications. Effectively, the result will be a set of AVPs to be included in the answer. Make sure to pack them as a JSON Array (similar to the input of dm_send_request()), before calling dm_send_answer():


  ...
  $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");
March 07, 2024, at 12:35 PM by liviu -
Deleted line 116:
  • 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
Added line 119:
  • 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
March 07, 2024, at 12:35 PM by liviu -
Added lines 26-27:


Changed lines 94-120 from:

Starting with OpenSIPS 3.5, there is the option of acting as a Diameter Server, and process incoming Diameter requests.

to:

Starting with OpenSIPS 3.5, there is the option of acting as a Diameter Server and process incoming Diameter requests, as well as to provide the appropriate AVPs for the Diameter answer, which may also be an error, of course. Here are the steps to achieve this:


First, make sure the event_route module is loaded. It is required in order to gain access to the event_route, which will be triggered with a E_DM_REQUEST event on each incoming Diameter request:


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


Notice there are several pieces of information provided through the event's parameters:

  • 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
  • app_id (integer) - the Diameter Application Identifier
  • cmd_code (integer) - the Diameter Command Code
  • avps_json (string) - a JSON Array containing the AVPs of the request
March 07, 2024, at 12:28 PM by liviu -
Changed line 67 from:

... and, finally, send the request out (in a blocking fashion, for async support, see ):

to:

... and, finally, send the request out (in a blocking fashion, for async support, see async dm_send_request()):

March 07, 2024, at 12:27 PM by liviu -
Changed line 38 from:

After making sure that aaa_diameter is loaded, simply build the request's AVP list as a JSON array:

to:

After making sure that aaa_diameter is loaded, start by building the request's AVP list as a JSON array:

March 07, 2024, at 12:27 PM by liviu -
Added lines 39-40:

\\

March 07, 2024, at 12:26 PM by liviu -
Changed lines 34-35 from:

OpenSIPS 3.2 and above releases offer the option of building generic Diameter requests with full control over the AVPs of the request, as well as full access to the content of the response. Below is a short tutorial on how to send a Diameter request.

to:

OpenSIPS 3.2 and above releases offer the option of building generic Diameter requests with full control over the AVPs of the request, as well as full access to the content of the response. Below is a short tutorial on how to send a Diameter request.

Changed lines 61-69 from:
to:

@]


... and, finally, send the request out (in a blocking fashion, for async support, see ):


[@

March 07, 2024, at 12:25 PM by liviu -
Changed lines 38-78 from:

First,

to:

After making sure that aaa_diameter is loaded, simply build the request's AVP list as a JSON array:

# 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}
		]}
]";

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


In this example, the Diameter Application ID is 42, and the Command's Code is 92001. Finally, the response AVPs are available under $var(rpl_avps). Just use the OpenSIPS JSON module in order to parse & access them:


$json(rpl) := $var(rpl_avps);
xlog("Reply AVPs: $json(rpl)\n");
$var(i) = 0;
while ($json(rpl[$var(i)])) {
  xlog("   AVP: $json(rpl[$var(i)])\n");
}
March 07, 2024, at 12:15 PM by liviu -
Changed lines 34-35 from:

OpenSIPS 3.2 and above releases offer the option of building generic Diameter requests with full control over the AVPs of the request, as well as full access to the content of the response.

to:

OpenSIPS 3.2 and above releases offer the option of building generic Diameter requests with full control over the AVPs of the request, as well as full access to the content of the response. Below is a short tutorial on how to send a Diameter request.


First,

Changed line 42 from:

Starting with OpenSIPS 3.5, support

to:

Starting with OpenSIPS 3.5, there is the option of acting as a Diameter Server, and process incoming Diameter requests.

March 07, 2024, at 12:14 PM by liviu -
Changed lines 34-38 from:

opensips.cfg: Processing Generic Diameter Requests

to:

OpenSIPS 3.2 and above releases offer the option of building generic Diameter requests with full control over the AVPs of the request, as well as full access to the content of the response.

opensips.cfg: Processing Generic Diameter Requests

Starting with OpenSIPS 3.5, support

March 06, 2024, at 09:54 AM by liviu -
Added lines 1-34:
Documentation -> Tutorials -> Diameter Client/Server

This page has been visited 356 times.

How to build and process Diameter requests using OpenSIPS scripting

by Liviu Chircu

(:toc-float Table of Content:)


Setting up the freeDiameter libraries

This tutorial has been written for a Xubuntu 22.04 LTS, which comes with freeDiameter library v1.2.1 packages. Other distros, such as Debian 10, are also known to offer standard package-based support for freeDiameter v1.2.1, so they are expected to be compatible just as well.

sudo apt -y install libfreediameter-dev

Installing the "aaa_diameter" OpenSIPS module

If you are building from source:

include_modules=aaa_diameter make install

Otherwise, if you are installing from packages, make sure to grab the opensips-diameter-module:

sudo apt -y install opensips-diameter-module

opensips.cfg: Sending Generic Diameter Requests

opensips.cfg: Processing Generic Diameter Requests


Page last modified on March 07, 2024, at 05:12 PM