SNMPv1/SNMP2c的报文格式:
version+community+PDU
SNMPv3的报文格式:
SNMPv3的报文格式要复杂一些,可以看作是header+PDU。具体可以看这里http://blog.csdn.net/fw0124/article/details/8557742
PDU的格式:
PDU Type + RequestId + ErrorStatus + ErrorIndex + Variable-Binding
PDU Type
GET 0
GETNEXT 1
RESPONSE 2
SET 3
TRAP-V1 4
GETBULK 5
INFORM 6
Notification(TRAP-V2) 7
Report 8
PDU使用ASN.1来定义数据格式,使用BER进行编码。
ASN.1
ASN.1 (Abstract Syntax Notation dot one)是定义抽象数据类型规格形式的标准。
它是用于描述数据的表示、编码、传输、解码的灵活的记法。它提供了一套正式、无歧义和精确的规则,以描述独立于特定计算机硬件的对象结构。
ASN.1是通信协议中描述数据传输的正式标记(notation),它与语言实现和物理表示无关,与应用的复杂度无关。ASN.1特别适合表示现代通信应用中那些复杂的、变化的及可扩展的数据结构。
ASN.1 本身只定义了表示信息的抽象句法,但是没有限定其编码的方法。各种ASN.1 编码规则提供了由ASN.1描述其抽象句法的数据的值的传送语法(具体表达)。
标准的ASN.1 编码规则有基本编码规则(BER,Basic Encoding Rules)、规范编码规则(CER,Canonical Encoding Rules)、唯一编码规则(DER,Distinguished Encoding Rules)、压缩编码规则(PER,Packed Encoding Rules)和XML编码规则(XER,XML Encoding Rules)。
BER
BER(Basic Encoding Rules)是ASN.1中最早定义的编码规则。
BER传输语法的格式一直是TLV三元组<Type, Length, Value>也可以认为是<Tag, Length, Value>。
TLV每个域都是一系列八位组,对于组合结构,其中V还可以是TLV三元组。
BER传输语法是基于八位组(为了避免不同系统上的混淆,没有采用Byte为单位)的,自定界的编码,因为其中L明确界定了八位组的长度。
BER编码常见的Type:BOOL(0x01);INT(0x02);OCTSTR(0x04);NULL(0x05);OBJID(0x06);ENUM(0x0A);SEQ(0x30);SETOF(0x31);IPADDR(0x40);COUNTER(0x41);GAUGE(0x42);TIMETICKS(0x43);OPAQUE(0x44)
BER编码中Length表示Value部分所占八位组的个数,有两大类:定长方式(Definite Form)和不定长方式(Indefinite Form)。
采用不定长方式时,Length所在八位组固定编码为0x80,但在Value编码结束后以两个0x00结尾。
在定长方式中,按照Length所占的八位组个数又分为短、长两种形式。
length<=127:使用一个八位组。
length>127:使用多个八位组。第一个八位组最高位1,低七位表示的是Length所占的长度,后续的八位组表示长度的实际值。
例如,
长度等于23(0x17) -> 17
长度等于255(0xFF) -> 81 FF
长度等于273(0x111) -> 82 01 11
BER中各种类型的值编码也有详细规定。其中OID的编码规则比较特殊。
以1.2.34.56789为例
A[1] = 1
A[2] = 2
A[3] = 34
A[4] = 56789
BER编码后的八位组用B[m]表示。
1) 两个数字a.b编码为40*a+b。
B[1] = A[1]×40 + A[2] → B[1] = 1 × 40 + 2 = 42(0x2A) = 00101010b
A[1]当前只定义了ccitt(0), iso(1), joint(2)三种。
2) A[3]~A[N]先转化为无符号二进制数
A[3] = 34 = 100010b
A[4] = 56789 = 1101110111010101b
3) 然后从低位开始按照7bit分割
A[3] = 34 = 100010b → 0100010b
A[4] = 56789 = 1101110111010101b → 0000011b, 0111011b, 1010101b
4) 第一个七位组的最高位补上0,其他的七位组的最高位补上1。
A[3] 0100010b → 00100010b
A[4] 0000011b, 0111011b, 1010101b → 10000011b, 10111011b, 01010101b
5) B[2]开始依次放入上面补好位的各个8位组
B[2] = 0100010b = 34(0x22)
B[3] = 10000011b = 131(0x83)
B[4] = 10111011b = 187(0xBB)
B[5] = 01010101b = 85(0x55)