查看源码 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_rfc3588diameter_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