查看源码 diameter_dict
diameter 应用的字典接口。
描述
一个 diameter 服务,如使用 diameter:start_service/2
配置的那样,指定一个或多个支持的 Diameter 应用。每个 Diameter 应用都指定一个字典模块,该模块知道如何编码和解码其消息和 AVP。字典模块又是从定义这些消息和 AVP 的文件生成的。此类文件的格式在下面的 文件格式 中定义。用户通过创建字典文件、使用 diameterc(1) 或 diameter_make
将其编译为 Erlang 模块,并在服务上配置生成的字典模块,来添加对其特定应用的支持。
字典模块的生成还会产生一个 hrl 文件,该文件定义了字典定义的用于消息和分组 AVP 的记录。这些记录是 diameter 应用的用户发送和接收的内容,根据 diameter_app
中讨论的其他可能格式。这些记录和对应于 Diameter 数据格式的底层 Erlang 数据类型分别在 消息记录 和 数据类型 中讨论。生成的 hrl 还包含类型为枚举的 AVP 的可能值的宏定义。
diameter 应用包含五个字典模块,对应于 RFC 6733 第 2.4 节中定义的应用:diameter_gen_base_rfc3588
和 diameter_gen_base_rfc6733
用于应用标识符为 0 的 Diameter 通用消息应用,diameter_gen_accounting
(用于 RFC 3588)和 diameter_gen_acct_rfc6733
用于应用标识符为 3 的 Diameter 基本计费应用,以及 diameter_gen_relay
用于应用标识符为 0xFFFFFFFF 的中继应用。
通用消息和中继应用是 diameter 本身具有任何特定知识的唯一应用。通用消息应用用于 diameter 本身处理的消息:CER/CEA、DWR/DWA 和 DPR/DPA。中继应用在编码/解码方面受到了特殊处理,因为它处理的消息和 AVP 没有明确定义。
文件格式
字典文件由不同的部分组成。每个部分以一个标签开头,后跟零个或多个参数,并在下一个部分的开始或文件结尾处结束。标签由一个 & 字符后跟一个关键字组成,并与它们的参数用空格分隔。空格分隔各个标记,但在其他情况下无关紧要。
标签、它们的参数以及每个对应部分的内容如下所示。除非另有说明,否则每个部分都可以多次出现。指定部分的顺序并不重要。
@id 数字
- 将整数“数字”定义为所讨论应用的 Diameter 应用 ID。最多出现一次,并且如果字典定义了@messages
,则为必需。该部分的内容为空。应用 ID 设置在应用发出的消息的 Diameter 标头中,并且传入消息标头中的值用于标识相关的字典模块。
示例
@id 16777231
@name 模块
- 定义生成的字典模块的名称。最多出现一次,默认值为字典文件的名称减去任何扩展名。该部分的内容为空。请注意,字典模块应具有唯一的名称,以免与系统中现有的模块冲突。
示例
@name etsi_e2
@prefix 名称
- 将“名称”定义为添加到生成的字典模块和 hrl 中的记录和常量名称的前缀(后跟一个'_'
字符)。最多出现一次。该部分的内容为空。前缀是可选的,但可以用于消除来自不同 Diameter 应用中类似命名的消息和 AVP 的记录和常量名称之间的歧义。
示例
@prefix etsi_e2
@vendor 数字 名称
- 将整数“数字”定义为设置了 V 标志的 AVP 的默认供应商 ID。“名称”记录应用的拥有者,但在其他情况下未使用。最多出现一次,并且如果 AVP 设置了 V 标志并且未以其他方式分配供应商 ID,则为必需。该部分的内容为空。示例
@vendor 13019 ETSI
@avp_vendor_id 数字
- 将整数“数字”定义为部分内容中列出的 AVP 的供应商 ID,从而覆盖@vendor
默认值。该部分内容由 AVP 名称组成。示例
@avp_vendor_id 2937 WWW-Auth Domain-Index Region-Set
@inherits 模块
- 定义一个字典模块的名称,该模块包含应导入当前字典中的 AVP 定义。该部分内容由那些应从字典中导入其定义的 AVP 的名称组成,空列表会导致全部导入。任何列出的 AVP 都不能在当前字典中定义,并且从多个字典继承相同的 AVP 是错误的。请注意,设置了 V 标志的继承 AVP 从继承字典中的
@avp_vendor_id
或继承字典中的@vendor
获取其供应商 ID。特别是,忽略继承字典中的@avp_vendor_id
。从指定所需@vendor
的字典继承等效于使用@avp_vendor_id
和字典定义的副本,但前者更易于重用。所有字典通常都应从
diameter_gen_base_rfc6733
继承 RFC 6733 AVP。示例
@inherits diameter_gen_base_rfc6733
@avp_types
- 定义各个 AVP 的名称、代码、类型和标志。该部分由以下形式的定义组成名称 代码 类型 标志
其中,“代码”是整数 AVP 代码,“类型”标识 AVP 数据格式,如在下面的 数据类型 部分中所定义,“标志”是 V、M 和 P 字符的字符串,指示要在传出的 AVP 上设置的标志;如果未设置任何标志,则为单个
'-'
(减号)字符。示例
@avp_types Location-Information 350 Grouped MV Requested-Information 353 Enumerated V
警告
P 标志已在 RFC 6733 中弃用。
@custom_types 模块
- 指定模块“模块”提供编码/解码函数的 AVP。该部分内容由 AVP 名称组成。对于每个此类名称,期望Mod:Name(encode|decode, Type, Data, Opts)
提供 AVP 值的编码/解码,其中“名称”是 AVP 的名称,“类型”是其在字典的@avp_types
部分中声明的类型,“数据”是要编码/解码的值,“选项”是传递给编码/解码的项。示例
@custom_types rfc4005_avps Framed-IP-Address
@codecs 模块
- 与@custom_types
类似,但要求指定的模块导出Mod:Type(encode|decode, Name, Data, Opts)
,而不是Mod:Name(encode|decode, Type, Data, Opts)
。示例
@codecs rfc4005_avps Framed-IP-Address
@messages
- 定义应用的消息。该部分内容由 RFC 6733 第 3.2 节“命令代码格式规范”中指定的格式的定义组成。@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
- 定义类型为“分组”的应用的 AVP 的内容。该部分内容由 RFC 6733 第 4.4 节“分组 AVP 值”中指定的格式的定义组成。示例
@grouped SIP-Deregistration-Reason ::= < AVP Header: 383 > { SIP-Reason-Code } [ SIP-Reason-Info ] * [ AVP ]
在分组 AVP 的定义中指定供应商 ID 等效于使用
@avp_vendor_id
指定它。@enum 名称
- 定义类型为“枚举”的 AVP“名称”的值。部分内容由名称和相应的整数值组成。整数值可以以 0x 为前缀,以解释为十六进制。请注意,所讨论的 AVP 可以在继承的字典中定义,以便将其他值引入到另一个字典中定义的枚举中。
示例
@enum SIP-Reason-Code PERMANENT_TERMINATION 0 NEW_SIP_SERVER_ASSIGNED 1 SIP_SERVER_CHANGE 2 REMOVE_SIP_SERVER 3
@end
- 导致字典的解析终止:任何剩余的内容都将被忽略。
可以使用分号在字典文件中包含注释:从分号到行尾的字符将被忽略。
消息记录
从字典规范生成的 hrl 为 @messages
和 @grouped
部分中定义的消息和分组 AVP 定义记录。对于每个消息或分组 AVP 定义,定义一个记录,其名称为消息或 AVP 名称,前缀为使用 @prefix
定义的任何字典前缀,其字段是消息或分组 AVP 中包含的 AVP 的名称,顺序为相关定义中指定的顺序。例如,给定一个空前缀,分组 AVP
SIP-Deregistration-Reason ::= < AVP Header: 383 >
{ SIP-Reason-Code }
[ SIP-Reason-Info ]
* [ AVP ]
将导致以下记录定义。
-record('SIP-Deregistration-Reason', {'SIP-Reason-Code',
'SIP-Reason-Info',
'AVP'}).
在生成的记录的字段中编码的值取决于 AVP 的类型和可以出现的次数。特别是,指定为仅出现一次的 AVP 被编码为 AVP 类型的值,而具有任何其他规范的 AVP 被编码为 AVP 类型的值列表。AVP 的类型在 AVP 定义中指定,RFC 6733 类型如下所述。
数据类型
RFC 6733 的第 4.2 节(“基本 AVP 数据格式”)和 4.3 节(“派生 AVP 数据格式”)中定义的数据格式被编码为此处定义的类型的值。当发送请求时,值在请求记录中传递给 diameter:call/4
,在结果应答记录中返回,并在接收传入请求时传递给 handle_request/3 回调。
在 OctetString() 和派生类型在 string() 和 binary() 类型之间进行选择的情况下,表示形式由 diameter:service_opt() string_decode 的值确定。
基本 AVP 数据格式
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()
在编码时,OctetString() 可以指定为 iolist(),绝对值过大的浮点数等价于 infinity
或 '-infinity'
,而过大的整数会导致编码失败。分组 AVP 的记录如上一节所述。
派生的 AVP 数据格式
Address() = OctetString()
| tuple()
在编码时,OctetString() IPv4 地址以常用的 x.x.x.x 格式解析,而 IPv6 地址以 RFC 2373 的 2.2 节 “地址的文本表示” 中指定的任何格式解析。IPv4 tuple() 的长度为 4,包含 0..255 类型的值。IPv6 tuple() 的长度为 8,包含 0..65535 类型的值。tuple 表示在解码时使用。
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
此外,可以编码的值受到 RFC 6733 要求的使用四个八位字节进行编码的限制,并需要 RFC 2030 的扩展。特别是,只能编码 {{1968,1,20},{3,14,8}}
和 {{2104,2,26},{9,42,23}}
(包括两者)之间的值。
UTF8String() = [integer()] | binary()
列表元素是字符串中各个字符的 UTF-8 编码。无效的代码点会导致编码/解码失败。在编码时,UTF8String() 可以指定为二进制,或作为二进制和代码点的嵌套列表。
DiameterIdentity() = OctetString()
值必须至少包含一个字符。
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+'
在编码时,字段端口、传输和协议默认分别为 3868、sctp 和 diameter。OctetString 值的 DiameterURI() 的语法在 RFC 6733 的 4.3 节中指定。记录表示在解码时使用。
Enumerated() = Integer32()
在编码时,可以使用字典的 hrl 文件中定义的宏来指定值。
IPFilterRule() = OctetString()
QoSFilterRule() = OctetString()
这些类型的值当前未被 diameter 解析。
另请参阅
diameterc(1), diameter
, diameter_app
, diameter_codec
, diameter_make