標識域指明數據的類型,占用1個字節,常見的類型有: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)。
長度域指明值域的長度,不定長,一般為一到三個字節。其格式可分為短格式(后面的值域沒有超過127長)和長格式,如下所示
短格式的表示方法:
| 0(1bit) |
長度(7bit) |
長格式的表示方法:
| 1(1bit) |
K(7bit) |
K個八位組長度(K Byte) |
例:
length=30=>1E(30沒有超過127,長度域為0001 1110)
length=169=>81 A9(169超過127,長度域為 1000 0001 1010 1001,169是后9位的值,前八位的第一個1表示這是長格式的表示方法,前八位的后七位表示后面有多少個字節表示針對的長度,這里,是000 0001,后面有一個字節表示真正的長度,1010 1001是169,后面的值有169個字節長。)
length=1500=>82 05 DC(1000 0010 0000 0101 1101 1100,先看第一個字節,表示長格式,后面有2個字節表示長度,這兩個字節是0000 0101 1101 1100 表示1500)
integer::=0x02 length{byte}*(*表示重復)
整型數據值域用補碼表示,去掉多余的零(正數)或一(負數)。值域最高位為符號位。例:
1500=>02 02 05 DC21500=>02 02 FA 24
SNMP服務器維護的所有管理信息庫(MIB)對象采用ObjectID表示,如,1.3.6.1.2.1.1.1表示MIB庫中的設備描述SysDesc變量,其編碼規則如下:
objectID::=0x06 length {subidentifier}* (1)
subidentifier::= {leadingbyte}* lastbyte (2)
leadingbyte::=1 7bitvalue (3)
lastbyte::=0 7bitvalue (4)
首兩個ID被合並為一個字節X*40+Y (5)
雖然規則很多,但由於大多數子對象標識在0~127,只需按規則(1)、(5)即可;
當子對象標識大於127,則按規則(2)、(3)、(4)將其分解為多個字節,最后一個字節的高位為零,其余字節的高位為一。如:1.3.6.1.810.1,根據規則(5),首兩個子對象標識1.3被合並為2B(1 3 40+3=43);
子對象標識810超過127,根據規則(2)、(3)、(4)將其拆分為兩個字節86 2A (810=11 0010 1010==>1000 0110 0010 1010);
整個MIB被編碼為:0x06 0x06 0x2b 0x06 0x01
0x86 0x2a 0x01。
sequence::=0x30 length{asndata}*
如:30 05 02 01 10 05 00表示一個sequence結構,內含兩個成員,其中一個為整型,另一個為空類型(NULL)。
null::=0x05 0x00
string::=0x04 length{byte}*
例如:04 06 70 75 62 6c 69 63表示字符串public
實例:
30 3c 02 01 00 04
06 70 75 62 6c 69 63 a2 2f 02 01 10 02 01 00 02
01 00 30 24 30 22 06 08 2b 06 01 02 01 01 01 00
04 16 53 54 41 52 20 53 77 69 74 63 68 20 53 32
38 30 30 20 56 34 2e 30
根據第2節BER編碼規則和3.1節SNMP數據報格式,我們對數據進行分解:
SNMP Length=60<=30 3c
Version=1<=02 01 00
Community=public<=04 06 70 75 62 6c 69 63
PDU Type=Get response length=2f<=a2 2f
Request ID=6<=02 01 10
Error status=(No error)<=02 01 00
Error index=0<=02 01 00
Variable List length=24<=30 24
Item1 Length=22<=30 22
Object={1.3.6.1.2.1.1.1.0}<=06 08 2b 06 01 02 01 01 01 00
Value=STAR Switch S2800 V4.0<=04 16 53 54 41 52 20…
整個報文的含義為SNMP GetReply sysDescr=
STAR Switch S2800 V4.0
駐留在被管設備上的AGENT從UDP端口161接受來自網管站的串行化報文,經解碼、團體名驗證、分析得到管理變量在MIB樹中對應的節點,從相應的模塊中得到管理變量的值,再形成響應報文,編碼發送回網管站。網管站得到響應報文后,再經同樣的處理,最終顯示結果。
下面根據RFC1157詳細介紹Agent接受到報文后采取的動作:
首先解碼生成用內部數據結構表示的報文,解碼依據ASN.1的基本編碼規則,如果在此過程中出現錯誤導致解碼失敗則丟棄該報文,不做進一步處理。
第二步:將報文中的版本號取出,如果與本Agent支持的SNMP版本不一致,則丟棄該報文,不做進一步處理。當前北研的數據通信產品只支持SNMP版本1。
第三步:將報文中的團體名取出,此團體名由發出請求的網管站填寫。如與本設備認可的團體名不符,則丟棄該報文,不做進一步處理,同時產生一個陷阱報文。SNMPv1只提供了較弱的安全措施,在版本3中這一功能將大大加強。
第四步:從通過驗證的ASN.1對象中提出協議數據單元PDU,如果失敗,丟棄報文,不做進一不處理。否則處理PDU,結果將產生一個報文,該報文的發送目的地址應同收到報文的源地址一致。
第一種情況:如果PDU中的變量名在本地維護的MIB樹中不存在,則接受到這個PDU的協議實體將向發出者發送一個GetResponse報文,其中的PDU與源PDU只有一點不同:將ERROR-STATUS置為noSuchName,並在ERROR-INDEX中指出產生該變量在變量LIST中的位置。
第二種情況:如果本地協議實體將產生的響應報文的長度大於本地長度限制,將向該PDU的發出者發送一個GetResponse報文,該PDU除了ERROR-STATUS置為tooBig,ERROR-INDEX置為0以外,與源PDU相同。
第三種情況:如果本地協議實體因為其他原因不能產生正確的響應報文,將向該PDU的發出者發送一個GetResponse報文,該PDU除了ERROR-STATUS置為genErr,ERROR-INDEX置為出錯變量在變量LIST中的位置,其余與源PDU相同。
第四中情況:如果上面的情況都沒有發生,則本地協議實體向該PDU的發出者發送一個GetResponse報文,該PDU中將包含變量名和相應值的對偶表,ERROR-STATUS為noError,ERROR-INDEX為0,request-id域的值應與收到PDU的request-id相同。
GetNextRequest PDU的最重要的功能是表的遍歷,這種操作受到了前面所說的管理變量的表示方法的支持,從而可以訪問一組相關的變量,就好象他們在一個表內。
下面通過一個例子解釋表遍歷的過程:
被管設備維護如下路由表:
Destination NextHop Metric
10.0.0.99 89.1.1.42 5
9.1.2.3 99.0.0.3 3
10.0.0.51 89.1.1.42 5
假設網管站欲取得這張路由表的信息,該表的索引是目的網絡地址。
網管站向被管設備發送一個GetNextRequest PDU,其中的受管對象的標識如下
GetNextRequest ( ipRouteDest, ipRouteNextHop, ipRouteMetric1 )
SNMP agent響應如下GetResponse PDU:
GetResponse (( ipRouteDest.9.1.2.3 = "9.1.2.3" ),
( ipRouteNextHop.9.1.2.3 = "99.0.0.3" ),
( ipRouteMetric1.9.1.2.3 = 3 ))
網管站繼續:
GetNextRequest ( ipRouteDest.9.1.2.3,
ipRouteNextHop.9.1.2.3,
ipRouteMetric1.9.1.2.3 )
agent響應:
GetResponse (( ipRouteDest.10.0.0.51 = "10.0.0.51" ),
( ipRouteNextHop.10.0.0.51 = "89.1.1.42" ),
( ipRouteMetric1.10.0.0.51 = 5 ))
值得注意的是agent必須能夠確定下一個管理變量名,以保證所有變量能被取到且只被取到一次。
網管站繼續:
GetNextRequest ( ipRouteDest.10.0.0.51,
ipRouteNextHop.10.0.0.51,
ipRouteMetric1.10.0.0.51 )
agent 響應:
GetResponse (( ipRouteDest.10.0.0.99 = "10.0.0.99" ),
( ipRouteNextHop.10.0.0.99 = "89.1.1.42" ),
( ipRouteMetric1.10.0.0.99 = 5 ))
網管站繼續
GetNextRequest ( ipRouteDest.10.0.0.99,
ipRouteNextHop.10.0.0.99,
ipRouteMetric1.10.0.0.99 )
這時因為路由表中所有的行都被取遍,agent因返回路由表對象的下一字典后繼即該管理對象在MIB樹中的后序遍歷的直接后繼。這里應是nettoMediaIndex,管理對象的OBJECT IDENTIFIER。這個響應通知網管站對表的遍歷已經完成。
GetResponse PDU只有當受到getRequest GetNextRequest SetRequest才由協議實體產生,網管站收到這個PDU后,應顯示其結果。
SetRequest PDU除了PDU類型標識以外,和GetRequest相同,當需要對被管變量進行寫操作時,網管站側的協議實體將生成該PDU。
對SetRequest的響應將根據下面情況分別處理:
1. 如果是關於一個只讀變量的設置請求,則收到該PDU的協議實體產生一個GetReponse報文,並置error status為noSuchName, error index的值是錯誤變量在變量list中的位置。
2. 如果被管設備上的協議實體收到的PDU中的變量對偶中的值,類型、長度不符和要求,則收到該PDU的協議實體產生一個GetReponse報文,並置error status為badValue, error index的值是錯誤變量在變量list中的位置。
3. 如果需要產生的GetReponse報文長度超過了本地限制,則收到該PDU的協議實體產生一個GetReponse報文,並置error status為tooBig, error index的值是0。
4. 如果是其他原因導致SET失敗,則收到該PDU的協議實體產生一個GetReponse報文,並置error status為genErr, error index的值是錯誤變量在變量list中的位置。
如果不符合上面任何情況,則agent將把管理變量設置收到的PDU中的相應值,這往往可以改變被管設備的運行狀態。同時產生一個GetResponse PDU,其中error status置為noError,error index的值為0。
Trap PDU的有如下的形式
| 產生trap的系統的OBJECT IDENTIFIER
|
| 系統的IP地址 |
| 普通類型 |
| 特定類型 |
| 時戳 |
| 變量對偶表 |
Trap是被管設備遇到緊急情況時主動向網管站發送的消息。網管站收到trap PDU后要將起變量對偶表中的內容顯示出來。一些常用的trap類型有冷、熱啟動,鏈路狀態發生變化等。
