SNMP进阶
管理信息库:MIB
我们要扩展mib首先必须清楚mib是如何定义的,用的什么语言,有哪些约定,遵循哪些规则等等。这些基本东西掌握过后,我们就可以很轻松的来写自己的mib文件了。
所谓管理信息库,或者MIB,就是所有代理进程包含的、并且能够被管理进程进行查询和设置的信息的集合,或者叫管理对象的集合,在RFC 1213 [McColghrie 和Rose 1991]中定义了MIB-II,即第二版的MIB库。MIB是采用SMI(RFC 1155)来定义的。SMI全称为Structure Management Information,管理信息结构。SMI规范定义了一个基本框架,使用框架内的规范可以定义MIB,而SMI同时又是ASN.1的一个子集,它主要约定了使用到的语法、类型、宏、数据格式等。
本节知识相对来说有些枯燥,但是没办法,如果你要看懂mib的定义文件,并且能很灵活自如的对其进行扩展,那么这些基础是必须夯实的。俗话说“磨刀不误砍柴工”。
ASN.1语法
ASN.1(Abstract Syntax Notification 1),抽象语法描述语言,是一种独立于机器的描述语言,用于描述在网络上传递的消息。在SNMP中ANS.1主要用于MIB的定义,另一方面也用于协议的定义。所以理解ASN.1是理解协议、读懂SNMP国际规范RFC、进行SNMP开发的前提。在SNMP开发中,不但要用ASN.1编写MIB文件,还要使用ASN.1中的BER进行编解码。
ASN.1 可分为两个部分:
l 语法规则:从数据类型、内容顺序或结构等方面来描述消息的内容
l 编码规则:如何编码、解码实际消息中的数据
语法部分用于对数据结构、类型、顺序进行描述。编码则将语法部分描述的数据进行编码,变为二进制比特流,以便在网络上传输,或反方向地将接收到的数据流进行解码。这使得编码流可以跨平台、跨设备进行传输。
ASN.1的记法规则,ASN.1的结构、类型和取值的表示方法和编程语言的表示法相似:
Ø 多个空格和空行都看作是一个空格。
Ø 注释用成对的连字符(--)在注释的每行开始处表示,或者将一对连字符用在注释的开始处和注释行结束的结尾处。
Ø 标识符(取值和字段的名称)、类型引用(类型的名称)和模块名称由大写字母、小写字母、数字和连字符组成。
Ø 标识符、类型引用或模块名以由大写字母开始。
Ø 内建类型都由大写字母组成。内建类型一般用作标准表示法提供的类型。
Octet(字节)表示一个8bit的无符号整数。bit8表示最高位,bit1标识最低位。下列元语用于定义ASN.1符号:
l BIT 类型和值用等宽字体表示。它通畅表示一个十六进制的字节值。
l n1 粗斜体表示变量
l [] 粗的方括号标示该值为可选项
l {} 粗的大括号表示一组相关项。
l | 粗体竖杠表示一组之中的内容可任选其一。
l … 粗体省略号表示重复出现
l = 粗体等号,用一个子项表示该项
1 ASN.1术语
1.抽象语法(Abstract Syntax)
l 描述通用数据结构
l 允许定义数据类型和值
2.数据类型(Data Type)
l 值的集合,可以是简单类型或结构类型可以对数据类型命名
3.编码(Encoding)
l 用于表示数据值的字节序列
4.编码规则(Encoding Rules)
l 给出从一种语法到另一种的映射方法
5.传输语法(Transfer Syntax)
l 位模式(Bits pattern):描述数据是在传输时是如何表示的
2 ASN.1模块定义
模块(module)是ASN.1规范中的基本构造块,定义一个名为modulereference的模块,其格式如下:
DEFINITIONS ::=
BEGIN
EXPORTS
IMPORTS
AssignmentList
END
其中:EXPORTS 这个模块中的定义可能被其他模块引入,用的比较少;IMPORTS 定义将要由其他模块引入的对象或子模块;AssignmentList 这个模块中将定义类型分配、值分配及宏定义。
3 ASN.1数据类型
1. 基本类型:
ASN.1语法中有六种基本类型,分别如下,基本已经做到见名知意了:
BOOLEAN,INTEGER,ENUMERATED,REAL,BIT STRING,OCTET STRING
2. 字符串类型(ISO10646-1的子集):
Ø NumericString (0-9,)
Ø PrintableString (0-9,A-Z,a-z,,<s[ecial>])
Ø VisibleString
Ø GraphicString
Ø UTF8String
Ø IA5String (ASCII)
3. 对象类型:
OBJECT IDENTIFIER
ObjectDescriptor:一个任意长的非负整数序列,用于标记对象(如算法等)
4. 其它类型:
NULL 空值
UTCTime: yymmdd hhmm[ss]
GeneralizedTime:yyyymmdd hhmm[ss] ,强制始于2050年
4 ASN.1类型定义
ASN.1灵活之处在于,除了它内置的一些数据类型外,用户还可以自定义自己想要的任何类型,一般都是通过现有类型来组合来实现。
新类型定义的语法: ::=
示例:
Counter ::= INTEGER
IpAddress ::= OCTET STRING
Months ::= ENUMERATED {
january (1), february (2), march (3), april (4), may (5), june (6),
july (7), august (8), september (9),october (10), november (11), december(12)
}
上面的定义过程中,INTEGER太常见了,就用Counter来作为它的一种别名,注意是一种,以后就可以用Counter来定义新变量了。同理,IpAddress就是OCTE STRING类型一种别名。
5 ASN.1子类型定义
子类型是在类型的定义基础上增加更明确限制条件,如设定新类型的取值范围,缺省值等等。
语法: ::= ()
示例:
Counter ::= INTEGER (0..65536)
IpAddress ::= OCTET STRING ( SIZE(4) )
Spring ::= Months (march | april | may)
Summer ::= Months (june | july | august )
SmallPrime ::= INTEGER ( 2 | 3 | 5 | 7 | 11 )
ExportKey ::= BIT STRING ( SIZE(40) )
这样定义过后,以后用Counter定义的任何变量都被限定大于0小于65536。IpAddress定义变量长度都是4字节,等等。
6 ASN.1赋值
赋值在MIB库文件中的定义是最常见的一部分。
语法: ::=
value name :由用户自定义,但一般最好不要重名;
type:就是前面ASN.1的内置数据类型,或用户自定义类型;
value:当然就是该变量的值,一般要和变量类型所限定的范围一致。
示例:
ipInReceives Counter ::= 2450
ipRouteMask IpAddress ::= ‘FFFFFF00’H
currentMonth Months ::= july
currentTime UTCTime ::= “030708094018+0800”
name VisibleString ::= “John”
married BOOLEAN ::= TRUE
faxMessage BIT STRING ::= ‘01100001101’B
internet OBJECT IDENTIFIER ::= { iso(1) org(3) dod(6) 1 }
private OBJECT IDENTIFIER ::= { internet 4 }
最后两种赋值格式,我们后面再讲。
7 ASN.1的结构体类型
l SEQUENCE 一个或多个类型的有序集合,类似于C语言中的struct 类型定义:
UserAccount ::= SEQUENCE {
username PrintableString,
password PrintableString,
accountNr INTEGER
}
赋值
myAccount UserAccount ::= {
username “tly”,
password “guesswhat”,
accountNr 2345
}
l SEQUENCE OF 0个或多个某个给定类型多次出现的有序集合,对应于C语言中的数组:
定义
MemberCountries ::= SEQUENCE OF PrintableString
AccountRegistry ::= SEQUENCE OF UserAccount
赋值
eastAsia MemberCountries ::= {
“China”, “Japan”, “Korean”, “DPR”
}
l SET 一个或多个类型的无序集合,类似于SEQUENCE,但其中的组件不考虑分量顺序:
定义
UserAccount ::= SET {
username [0] PrintableString,
password [1] PrintableString,
accountNr [2] INTEGER
}
赋值
myAccount UserAccount ::= {
accountNr 2345,
username “tly”,
password “guesswhat”
}
l SET OF 0个或多个某个给定类型多次出现的无序集合,每一分量(组件)类型必须相同,但不考虑顺序要求。
类型定义
Keywords ::= SET OF PrintableString
赋值
someASN1Keywords Keywords ::= {
“INTEGER”, “BOOLEAN”, “REAL”
}
l CHOICE 多个类型其中的一个,类似于C语言中的枚举型:
例如:
SimpleSyntax ::=
CHOICE{
number
INTEGER,
string
OCTER STRING,
object
OBJECT IDENTIFIER,
empty
NULL
}
SimpleSyntax可以是INTEGER、OCTER STRING、OBJECT IDENTIFIER、NULL中的一个类型的变量。上述结构类型允许有可选组件。可选组件可能有默认值。SNMP中使用到的结构类型包括SEQUENCE、SEQUENCE OF和CHOICE。
8 ANS.1标签类型
标签用于区分不同的类型,并且在结构类型SEQUENCE和SET中,组件类型可能引起混淆,可以为它们的组件(分量)指定Context-specific标签,清晰指示组件的类型。除了CHOICE和ANY外,每种ASN.1类型都有一个标签,由一个类和一个非负的标签数组成。标签值可以唯一区分ASN.1类型。也就是说,ASN.1类型的名字并不影响它的抽象含义,只有标签才有这个作用。
标签用在编码中,可以唯一地标示类型,便于编码。ASN.1提供了4中标签:
l Universal:标识ISO和ITU定义的类型,ASN.1定义的类型均有Universal值,该值在所有的程序里都一致。
l Application:应用程序自定义类型。本标识可以唯一地标识自定义类型。类型名在ASN.1中可以相同,所以Application就成为唯一标识自定义类型的方法。类型的含义由制定者自己定义。例如:
name ::=[APPLICATION 0] VisibleString
Name ::=[APPLICATION 1] SEQUENCE
{
givenname VisibleString,
initial VisibleString,
familiyName VisibleString
}
l Private:该类型的含义根据具体的企业而不同。Private标识不会被用在国际规范中。企业提供的程序一般经常使用application和context-specific标识。在特殊场合下,一个企业的技术规范想要扩展成为一个国际规范时,使用private标识在企业规范成为国际规范的过程中可以较好地保护该企业的规范。例如:
CompanyNumber ::=[PRIVATE 2] INTEGER
companyNumber CompanyNumber ::=5651
l Context-specific:专用于结构类型中。该类型的含义根据给定的结构类型而不同。对于SET和SEQUENCE,为了避免里面的组件混淆,一般情况下给予不同的Context-specific标签。如:
CustomerRecord ::=SET{
name [0] VisibleString
mailingAddress [1] VisibleString
accountNumber [2] INTEGER,
balanceDue [3] INTEGER -- in cents--
}
SET和CHOICE中的分量顺序可能不同,例如name和mailingAddress都拥有同样的类型VisibleString,且它们的顺序可能颠倒,如果不指定一个context-specific标签就不知道一个VisibleString类型的值究竟是赋给name还是mailingAddress的。使用标签值就可以区分开,标签0是name,标签1是mailingAddress。
9 宏定义
ASN.1提供一种用户可以将符号扩展为自己使用的或别人使用的符号的机制,这就允许设计者去扩展语言定义一个“对象”,比如定义一个调制解调器或定义一个交换机。这些对象有普通的ASN.1属性和条件属性,比如父母和物理位置等。例如一个一部的调制解调器可以以普通调制解调器作为父类,从父类处继承属性。使用ASN.1可以定义为:
mode ::=SEQUENCE{
speed INTEGER,
modulation IA5String,
manufacturer IA5String
}
一个宏定义可以被导入和导出。ASN.1中的宏模板为:
MACRO ::=
BEGIN
TYPE NOTATION ::=
VALUE NOTATION ::=
END
下面是一个使用宏模板定义类型的例子:
ERROR MACRO ::=
BEGIN
TYPE NOTATION ::= Parameter
VALUE NOTATION ::=value(VALUE CHOICE
{
localValue INTEGER,
globalValue OBJECT INDENTIFIER
})
Parameter ::=“PARAMETER”NamedType | empty
NamedType ::=identifier type | type
END
PS:宏在1994年从ASN.1中移除,取而代之的是Information Object Class。2002年X.680和X.690系列标准中已经使用Information Object Class代替。SNMPv1在1990年发布,所以SNMPv1中使用ASN.1宏。而SNMPv2 SMI的RFC中明确指出,SNMPv2中使用1998版ASN.1,所以SNMPv2还是使用ASN.1中的宏定义管理对象和通告。
实战演练之MIB文件分析
请自己分析rfc-1303.mib、rfc1065-SMI.mib、rfc1155-SMI.mib、rfc1213-MIB.mib,以及SNMPv2-SMI.mib(rfc2578)、SNMPv2-TC.mib(rfc2579)和SNMPv2-TM.mib(rfc3417)。
本章内容理论性较强,但是如果很好掌握了ASN.1语法50%的基础知识就可以读懂现有80%的MIB文件,同时可以编写初中级的简单MIB文件了。