且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

《精通SNMP》——2.2 ASN.1基础

更新时间:2022-09-15 10:16:44

本节书摘来自异步社区《精通SNMP》一书中的第2章,第2.2节,作者: 武孟军 更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.2 ASN.1基础

与其他高级语言中的数据类型相似,ASN.1定义的数据类型分为简单类型和结构类型。同时,它又不同于其他高级语言,它是一种数据描述语言,只用来定义数据类型,且每种数据类型都有对应的传输编码。

本节介绍ASN.1中类型和值的概念、命名规则和其他一些基本内容。

2.2.1 类型和值
在ASN.1中,类型(type)是可以编码传输值的非空命名集合;值(value)是类型的一个实例,必须属于某个类型。

类型可分为简单类型、结构类型、定义类型和其他类型。

简单类型是ASN.1中最基本的数据类型,用来描述事物的简单属性。简单类型包括如下几种:

INTEGER         整型 
BOOLEAN         布尔型 
REAL           实型 
OCTECT STRING      字节串型 
OBJECT IDENTIFIER     标识符型 
ENUMERATED        枚举型 
NULL           空类型

为描述事物的复杂属性,仅有这些简单类型是不够的。结构类型是将已知类型按照一定的结构组织起来,形成的一种更为复杂的数据类型。组成结构类型的已知类型,称为结构类型的组件。注意结构类型允许嵌套,即结构类型的组件可以是其他结构类型。

ASN.1提供了4种结构类型,它们是:

SET           集合结构 
SEQUENCE        序列结构 
SET OF         元素相同的集合结构 
SEQUENCE OF       元素相同的序列结构
其他类型有2种:

CHOICE          选择类型  
ANY           可以是任意一种已知类型

上面所讲的这些类型,是ASN.1标准中已定义好的,所以又称为ASN.1内置类型。一般使用时,用户可利用这些类型再定义满足自己需求的类型。定义类型时,需要为类型确定一个名字以便引用它,类型名又称为类型引用(type reference)。

需要指出的是,这里所说的用户定义类型并没有产生新的ASN.1类型,仅仅是为ASN.1类型定义了一个新的类型引用,作用类似于高级程序语言中为数据类型定义别名。例如,C语言中使用typedef为已有类型定义别名。

值是某个类型取值范围内的一个特定值,是需要处理的数据,它必须属于某个类型。与类型一样,值必须有一个值名引用。ASN.1中,定义值名类似于高级程序语言中定义的一般变量。通常,在定义值名的同时完成赋值操作。

类型定义
定义类型的语法如下:

< 类型名 > ::= <已有类型符号 >

例如,下面的类型定义语句,使用内置类型INTEGER定义了一个新类型Age(更确切地说,是一个新的类型引用)。

Age ::= INTEGER

值定义
赋值语句的语法如下:

< 值名 > <所属类型 > ::= < 值 >

例如,下面的赋值语句,将整数25赋给了一个属于Age类型的值age。

age Age ::= 25

下面的语句使用简单类型定义结构类型SampleType:

SampleType::= SEQUENCE { 
      name     OCTET STRING,  
      married   BOOLEAN, 
      age     INTEGER 
      }

结构类型SampleType的3个组件类型分别是OCTET STRING、BOOLEAN和INTEGER。下面的语句为该类型实例赋值:

sample SampleType ::= SEQUENCE { 
         name    'MARY'H, 
         married    TRUE, 
         age      28 
        }

其中,sample为值名,其类型为SampleType。

2.2.2 符号与命名约定
在ASN.1中,可以出现的字母符号有以下几种(注释中可以出现其他字符):

  • 26个大写英文字母A~Z;
  • 26个小写英文字母a~z;
  • 10个阿拉伯数字0~9;
  • 符号 : = , { } < . ( ) [ ] - ' ” >和|。

其中,英文字母区分大小写。

在类型和值的命名中,应遵守表2-2所示的规则。


《精通SNMP》——2.2 ASN.1基础

名字中可以出现的符号有大小写英文字母、阿拉伯数字以及连字符(-)。其中,连字符不能连用(如--),且连字符不能出现在结尾。
**
2.2.3 基本符号和关键字**
在SNMP中,不仅有ASN.1定义的类型和值,更多的时候会遇到使用一系列产生式定义的宏(注意产生式用来定义ASN.1语言本身,而不是用来定义类型或值)。产生式中经常出现一些关键字(keyword item)和基本单词(item),它们在ASN.1标准中具有特定的意义。

在产生式中,关键字可作为终结符号对待,基本单词却有特定的意义,有的可以作为终结符使用,有的需要进一步替换。理解这些关键字和基本单词的用法,对根据产生式推导正确的最终语言符号具有十分重要的意义。

例如,ASN.1整型类型符号产生式中,有两条形式如下:

IntegerType ::=INTEGER | INTEGER{NamedNumberList} 
SignedNumber ::= number | -number

其中,INTEGER为关键字,number为基本单词。根据规则,INTEGER可以在整型类型的符号中作为最终符号出现。SignedNumber可以被number或number替换,但符号number再没有对应的产生式定义了,它可以出现在最终类型符号中吗?

答案是否定的。number是基本单词,它被定义为字符0~9组成的任意数字,因此,必须做进一步的替换,即在最终类型符号中,必须用任意数字替换符号number。

下面是一些常用的基本单词。

(1)类型引用。

形式:typereference。

解释:类型引用,即类型名,要求符合类型名命名标准。不能和ASN.1标准中的关键字和保留字相同。

(2)标识符。

形式:identifier。

解释:标识符号。用来标识一个特定的值或类型,命名规则同表2-2中的值名。

(3)值引用。

形式:valuereference。

解释:值引用,即值名,要求符合值名的命名标准。由于它的命名规则与标识符相同,实际使用中,要根据上下文确定是值引用还是标识符。

(4)模块引用。

形式:modulereference。

解释:模块引用,即模块名,要求符合模块名命名标准。实际使用中,根据上下文确定是模块引用还是类型引用。

(5)空标识符。

形式:empty。

解释:空标识符,出现空标识符的地方不含任何字符。

(6)数字。

形式:unmber。

解释:一位或多位数字。除单个数字外,第一个数字不能是数字0。

(7)二进制串。

形式:bstring。

解释:单引号引起来的0个或多个以0、1组成的序列,后缀为大写字母B,形如'01101100'B。

(8)十六进制串。

形式:hstring。

解释:单引号引起来的0个或多个由字符A B C D E F 0 1 2 3 4 5 6 7 8 9组成的序列,后缀为大写字母H,形如'AB0196'H。

(9)字节字符串。

形式:cstring。

解释:双引号引起来的0个或多个字节序列。如序列中出现双引号字符本身,须用双引号引起来。

(10)单符号。

形式:{ } < , .( ) [ ]-和;。

解释:单字符,意义根据上下文确定,可作为终结符使用。

关键字为ASN.1语言本身保留使用的符号,具有特定的意义,一般不允许使用。以下为ASN.1保留关键字:

BOOLEAN      INTEGER     BIT       STRING 
OCTET       NULL      SEQUENCE      OF 
SET        IMPLICIT    CHOICE       ANY 
EXTERNAL     OBJECT     IDENTIFIER    OPTIONAL 
DEFAULT      COMPONENTS    UNIVERSAL     APPLICATION 
PRIVATE      TRUE      FALSE       BEGIN 
END        DEFINITIONS   EXPLICIT     ENUMERATED 
EXPORTS      IMPORTS     REAL       INCLUDES 
MIN        MAX       SIZE       FROM 
WITH        COMPONENT    PRESENT      ABSENT 
DEFINED      BY       PLUS-INFINITY   MINUS-INFINITY 
TAGS

2.2.4 ASN.1标签
ASN.1中定义类型主要是为了应用程序通信,因此,除了CHOICE 和ANY类型(这两种类型最终被归结为别的类型),其他的ASN.1类型都有传输标识,称为类型标签(Tag)。

标签用一个字节表示,包括三部分,依次是类别(2位)、P/C(1位)指示位和标志号(Tag number,5位)。

1.类别
ASN.1类型分为4个大的类别。

  • 通用类(UNIVERSAL)——通用类具有普遍意义,在任何应用领域,这些类型的定义都是一致的。ASN.1的所有内置类型都属于通用类别。
  • 应用类(APPLICATION)——应用类和某一具体的应用领域有关,只在该应用领域内才有意义。在不同的应用领域中,两个不同类型可以有相同的Tag,但意义不同。例如,SNMP中定义的类型Counter、IpAddress都属于该类。
  • 上下文有关类(CONTEXT-SPECIFIC)——上下文有关类只存在于结构类型中,用于区分在一个结构中可能引起混淆的组件。例如,在CHOICE类型中,如果两个组件都是INTEGER类型,就需要进一步为每个组件加区分标志。在SNMP中,PDU的定义用到了这种类。
  • 私有类(PRIVATE)——私有类只在一个私有团体中有效,SNMP中没有用到它。

2.P/C指示位
在Tag中占1位,用于指明该类型是简单类型还是结构类型。

3.标志号
标志号在Tag中占5位,是一个正整数。标志号用来唯一区分所有属于同一类别中的不同类型。

类型的标志号、P/C指示位和所属类别一起构成类型的Tag。Tag是区分类型的关键所在,不论类型符号形式如何定义,如果它们的Tag相同,则认为是同一种类型。

通用类类型的Tag由ASN.1定义,应用程序类、上下文有关类和私有类都属于用户定义的类型,它们的Tag在定义时确定。