diameter_dict(4)
β¨ diameter_dict β the dictionary interface of the diameter application β¨
okay bestie sit DOWN because we're about to talk about diameter_dict, the dictionary interface of the diameter application π«Ά this is the glow-up your Diameter app needs, fr fr.
πΈ DESCRIPTION πΈ
so a diameter service, the way you'd set it up with diameter:start_service/2, says "hey, I support these Diameter applications" β one or more of them. and every single Diameter application out there ships with a dictionary module that knows how to encode and decode its messages and AVPs. that dictionary module is generated from a file that defines all those messages and AVPs, and the format of that file is exactly what's in FILE FORMAT down below. π
so how do you add support for your own special little app? you create dictionary files, compile them into Erlang modules using either diameterc(1) or diameter_make, and then configure those resulting dictionary modules on a service. that's it. that's the whole vibe.
generating a dictionary module also gives you a hrl file, and that hrl defines records for the messages and Grouped AVPs of your dictionary. those records are literally what a user of the diameter application sends and receives, modulo other possible formats as discussed in diameter_app. these records, plus the underlying Erlang data types that correspond to Diameter data formats, are discussed in MESSAGE RECORDS and DATA TYPES respectively. the generated hrl also contains macro definitions for all the possible values of AVPs of type Enumerated. obsessed.
the diameter application ships with five dictionary modules, corresponding to applications defined in section 2.4 of RFC 6733:
diameter_gen_base_rfc3588anddiameter_gen_base_rfc6733β for the Diameter Common Messages application, application identifier0diameter_gen_accounting(for RFC 3588) anddiameter_gen_acct_rfc6733β for the Diameter Base Accounting application, application identifier3diameter_gen_relayβ the Relay application, application identifier0xFFFFFFFF
now here's the tea: the Common Message and Relay applications are the only applications that diameter itself has any specific knowledge of. the Common Message application is used for the messages that diameter itself handles: CER/CEA, DWR/DWA and DPR/DPA. and the Relay application gets special treatment when it comes to encode/decode, because the messages and AVPs it handles aren't specifically defined at all. main character energy honestly.
π FILE FORMAT π
a dictionary file is made of distinct sections. each section starts with a tag, followed by zero or more arguments, and it ends when the next section starts or when the file ends. tags are an ampersand character & followed by a keyword, and they're separated from their arguments by whitespace. whitespace separates individual tokens but is otherwise completely insignificant β it's just there for the aesthetic.
the tags, their arguments, and the contents of each corresponding section go like this. each section can occur multiple times unless it says otherwise. the order you put the sections in? doesn't matter. not even a little. β¨
@idNumber β defines the integer Number as the Diameter Application Id of the application in question. can occur at most once, and it's required if the dictionary defines@messages. this section has empty content.
the Application Id gets set in the Diameter Header of outgoing messages of the application, and the value in the header of an incoming message is used to identify the relevant dictionary module. iykyk.
Example:
@id 16777231
@nameMod β defines the name of the generated dictionary module. can occur at most once and defaults to the name of the dictionary file minus any extension. this section has empty content.
note bestie: a dictionary module should have a unique name so it doesn't collide with existing modules in the system. don't be out here causing drama.
Example:
@name etsi_e2
@prefixName β defines Name as the prefix to be added to record and constant names (followed by a'_'character) in the generated dictionary module and hrl. can occur at most once. this section has empty content.
a prefix is optional, but you can use it to disambiguate between record and constant names that come from similarly named messages and AVPs in different Diameter applications. so helpful.
Example:
@prefix etsi_e2
@vendorNumber Name β defines the integer Number as the default Vendor-Id of AVPs for which theVflag is set. Name documents the owner of the application but is otherwise unused. can occur at most once and is required if an AVP sets theVflag and isn't otherwise assigned a Vendor-Id. this section has empty content.
Example:
@vendor 13019 ETSI
@avp_vendor_idNumber β defines the integer Number as the Vendor-Id of the AVPs listed in the section content, overriding the@vendordefault. the section content is a list of AVP names. slay.
Example:
@avp_vendor_id 2937
WWW-Auth
Domain-Index
Region-Set
@inheritsMod β defines the name of a dictionary module containing AVP definitions that should be imported into the current dictionary. the section content is the names of those AVPs whose definitions should be imported from the dictionary β an empty list causes all of them to be imported. any listed AVPs must not be defined in the current dictionary, and it's an error to inherit the same AVP from more than one dictionary. π
note that an inherited AVP that sets the V flag takes its Vendor-Id from either @avp_vendor_id in the inheriting dictionary or @vendor in the inherited dictionary. in particular, @avp_vendor_id in the inherited dictionary is ignored. inheriting from a dictionary that specifies the required @vendor is equivalent to using @avp_vendor_id with a copy of the dictionary's definitions β but the former makes for easier reuse. icon behavior.
all dictionaries should typically inherit RFC 6733 AVPs from diameter_gen_base_rfc6733. π
Example:
@inherits diameter_gen_base_rfc6733
when you use the indirect_inherits option from codec/2, only @vendor from the dictionary that defined the AVPs and @avp_vendor_id in the currently compiled dictionary are used. all the other dictionaries along the chain are ignored, so for example:
a.dia:
@vendor 1 A
@avp_types
AAA 111 Unsigned32 V
BBB 222 Unsigned32 V
a.dia will see:
AAAvendor_id = 1BBBvendor_id = 1
b.dia:
@vendor 2 B
@avp_types
CCC 333 Unsigned32 V
@inherits diameter_a
@avp_vendor_id 4
AAA
b.dia will see:
AAAvendor_id = 4BBBvendor_id = 1CCCvendor_id = 2
c.dia:
@vendor 3 C
@avp_types
DDD 444 Unsigned32 V
@inherits diameter_b
@avp_vendor_id 5
BBB
CCC
c.dia will see:
AAAvendor_id = 1BBBvendor_id = 5CCCvendor_id = 5DDDvendor_id = 3
in particular, b.dia's override of AAA to vendor_id = 4 is ignored by c.dia, and AAA is back to having vendor_id = 1. the way that chain just resets the lore. π
@avp_typesβ defines the name, code, type and flags of individual AVPs. the section consists of definitions of the form
Name Code Type Flags
where Code is the integer AVP code, Type identifies an AVP Data Format as defined in section DATA TYPES below, and Flags is a string of V, M and P characters indicating the flags to be set on an outgoing AVP β or a single '-' (minus) character if none are to be set.
Example:
@avp_types
Location-Information 350 Grouped MV
Requested-Information 353 Enumerated V
β οΈ WARNING: The P flag has been deprecated by RFC 6733. we do NOT stan it anymore.
@custom_typesMod β specifies AVPs for which module Mod provides encode/decode functions. the section contents consist of AVP names. for each such name,Mod:Name(encode|decode, Type, Data, Opts)is expected to provide encode/decode for values of the AVP, where Name is the name of the AVP, Type is its type as declared in the@avp_typessection of the dictionary, Data is the value to encode/decode, and Opts is a term that is passed through encode/decode.
Example:
@custom_types rfc4005_avps
Framed-IP-Address
@codecsMod β like@custom_typesbut it requires the specified module to exportMod:Type(encode|decode, Name, Data, Opts)rather thanMod:Name(encode|decode, Type, Data, Opts). subtle, but she's different. π
Example:
@codecs rfc4005_avps
Framed-IP-Address
@messagesβ defines the messages of the application. the section content consists of definitions of the form specified in section 3.2 of RFC 6733, "Command Code Format Specification".
@messages
RTR ::= < Diameter Header: 287, REQ, PXY >
< Session-Id >
{ Auth-Application-Id }
{ Auth-Session-State }
{ Origin-Host }
{ Origin-Realm }
{ Destination-Host }
{ SIP-Deregistration-Reason }
[ Destination-Realm ]
[ User-Name ]
* [ SIP-AOR ]
* [ Proxy-Info ]
* [ Route-Record ]
* [ AVP ]
RTA ::= < Diameter Header: 287, PXY >
< Session-Id >
{ Auth-Application-Id }
{ Result-Code }
{ Auth-Session-State }
{ Origin-Host }
{ Origin-Realm }
[ Authorization-Lifetime ]
[ Auth-Grace-Period ]
[ Redirect-Host ]
[ Redirect-Host-Usage ]
[ Redirect-Max-Cache-Time ]
* [ Proxy-Info ]
* [ Route-Record ]
* [ AVP ]
@groupedβ defines the contents of the AVPs of the application having type Grouped. the section content consists of definitions of the form specified in section 4.4 of RFC 6733, "Grouped AVP Values".
Example:
@grouped
SIP-Deregistration-Reason ::= < AVP Header: 383 >
{ SIP-Reason-Code }
[ SIP-Reason-Info ]
* [ AVP ]
specifying a Vendor-Id in the definition of a grouped AVP is equivalent to specifying it with @avp_vendor_id. same energy, different font. β¨
@enumName β defines values of AVP Name having type Enumerated. section content consists of names and corresponding integer values. integer values can be prefixed with0xto be interpreted as hexadecimal. π
Okay so bestie, real talk: that AVP we were just talking about? It can be defined in an inherited dictionary, and that's how you introduce extra values to an enumeration that's otherwise defined in another dictionary. Periodt. β¨
Example:
@enum SIP-Reason-Code
PERMANENT_TERMINATION 0
NEW_SIP_SERVER_ASSIGNED 1
SIP_SERVER_CHANGE 2
REMOVE_SIP_SERVER 3
If the indirect_inherits option from codec/2 is used, new enum values can also be added in each .dia file along the inheritance chain, like this:
a.dia:
@avp_types
AAA 111 Enumerated V
@enum AAA
A 0
B 1
a.dia will see these enum values:
- 0
- 1
b.dia:
@inherits diameter_a
@enum AAA
C 2
D 3
b.dia will see these enum values:
- 0
- 1
- 2
- 3
c.dia:
@inherits diameter_b
@enum AAA
E 4
F 5
c.dia will see:
- 0
- 1
- 2
- 3
- 4
- 5
β οΈ Warning: messages are not shown in this example, but it is required to add enum AVPs to messages in order for the code to encode/decode them to be generated! Don't skip this, bestie, or your code won't generate. π
@end causes parsing of the dictionary to terminate: any remaining content is ignored. Like, bye. π
Comments can be included in a dictionary file using semicolon: characters from a semicolon to end of line are ignored. So ; is your comment bestie. π
β¨ MESSAGE RECORDS β¨
The .hrl generated from a dictionary specification defines records for the messages and grouped AVPs defined in @messages and @grouped sections. For each message or grouped AVP definition, a record is defined whose name is the message or AVP name, prefixed with any dictionary prefix defined with @prefix, and whose fields are the names of the AVPs contained in the message or grouped AVP in the order specified in the definition in question. For example, the grouped AVP
SIP-Deregistration-Reason ::= < AVP Header: 383 >
{ SIP-Reason-Code }
[ SIP-Reason-Info ]
* [ AVP ]
will result in the following record definition given an empty prefix.
-record('SIP-Deregistration-Reason', {'SIP-Reason-Code',
'SIP-Reason-Info',
'AVP'}).
The values encoded in the fields of generated records depends on the type and number of times the AVP can occur. In particular, an AVP which is specified as occurring exactly once is encoded as a value of the AVP's type while an AVP with any other specification is encoded as a list of values of the AVP's type. The AVP's type is as specified in the AVP definition, the RFC 6733 types being described below.
β¨ DATA TYPES β¨
The data formats defined in sections 4.2 ("Basic AVP Data Formats") and 4.3 ("Derived AVP Data Formats") of RFC 6733 are encoded as values of the types defined here. Values are passed to diameter:call/4 in a request record when sending a request, returned in a resulting answer record and passed to a handle_request/3 callback upon reception of an incoming request.
In cases in which there is a choice between string() and binary() types for OctetString() and derived types, the representation is determined by the value of diameter:service_opt() string_decode.
Basic AVP Data Formats
OctetString() = string() | binary()
Integer32() = -2147483647..2147483647
Integer64() = -9223372036854775807..9223372036854775807
Unsigned32() = 0..4294967295
Unsigned64() = 0..18446744073709551615
Float32() = '-infinity' | float() | infinity
Float64() = '-infinity' | float() | infinity
Grouped() = record()
On encode, an OctetString() can be specified as an iolist(), excessively large floats (in absolute value) are equivalent to infinity or '-infinity' and excessively large integers result in encode failure. The records for grouped AVPs are as discussed in the previous section.
Derived AVP Data Formats
Address() = OctetString()
| tuple()
On encode, an OctetString() IPv4 address is parsed in the usual x.x.x.x format while an IPv6 address is parsed in any of the formats specified by section 2.2 of RFC 2373, "Text Representation of Addresses". An IPv4 tuple() has length 4 and contains values of type 0..255. An IPv6 tuple() has length 8 and contains values of type 0..65535. The tuple representation is used on decode.
Time() = {date(), time()}
where
date() = {Year, Month, Day}
time() = {Hour, Minute, Second}
Year = integer()
Month = 1..12
Day = 1..31
Hour = 0..23
Minute = 0..59
Second = 0..59
Additionally, values that can be encoded are limited by way of their encoding as four octets as required by RFC 6733 with the required extension from RFC 2030. In particular, only values between {{1968,1,20},{3,14,8}} and {{2104,2,26},{9,42,23}} (both inclusive) can be encoded.
UTF8String() = [integer()] | binary()
List elements are the UTF-8 encodings of the individual characters in the string. Invalid codepoints will result in encode/decode failure. On encode, a UTF8String() can be specified as a binary, or as a nested list of binaries and codepoints.
DiameterIdentity() = OctetString()
A value must have length at least 1.
DiameterURI() = OctetString()
| #diameter_URI{type = Type,
fqdn = FQDN,
port = Port,
transport = Transport,
protocol = Protocol}
where
Type = aaa | aaas
FQDN = OctetString()
Port = integer()
Transport = sctp | tcp
Protocol = diameter | radius | 'tacacs+'
On encode, fields port, transport and protocol default to 3868, sctp and diameter respectively. The grammar of an OctetString-valued DiameterURI() is as specified in section 4.3 of RFC 6733. The record representation is used on decode.
Enumerated() = Integer32()
On encode, values can be specified using the macros defined in a dictionary's .hrl file.
IPFilterRule() = OctetString()
QoSFilterRule() = OctetString()
Values of these types are not currently parsed by diameter.
π¦ SEE ALSO π¦
diameterc(1)diameterdiameter_appdiameter_codecdiameter_make
That's the tea, bestie! This page is from Ericsson AB, version diameter 2.7.2, and the manpage date is whatever your system says β but you know the vibe. Stay iconic, and may your dictionaries always parse. πβ¨
π¦ where this page comes from
- arch rolling: erlang-core 29.1.1-1 Β· Apache-2.0
- nixos 26.05: erlang 29.1.2
- nixpkgs unstable: erlang 29.1.2
- ubuntu stonking: erlang-doc 1:29.0.6+dfsg-1 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms