配置mib2c工具

一句话:配置mib2c工具时,不要用交叉编译环境的配置来编译和安装SNMP

 

一般我们编译SNMP时都是用交叉编译环境,会修改toolchain的路径,编译出来snmpd等,是用来在板子上跑的。

 

而mib2c是在linux主机上跑的,要想编出来mib2c,需要linux主机上配套的库文件等等。如果前面用交叉编译的工具链来编lib,后面用主机环境的工具链编译连接mib2c,在链接时一定会出问题,一般会提示如下lib库不兼容问题:

LD_RUN_PATH="/home/xxx/test/temp/net-snmp-5.4.2.1/perl/default_store/../../snmplib/.libs" cc  -shared -O2 -g -L/usr/local/lib -fstack-protector -lpthread -lm default_store.o  -o ../blib/arch/auto/NetSNMP/default_store/default_store.so  \
    -L/home/xxx/test/temp/net-snmp-5.4.2.1/perl/default_store/../../snmplib/.libs -L/home/xxx/test/temp/net-snmp-5.4.2.1/perl/default_store/../../snmplib -lpthread -lm -L/home/xxx/test/temp/net-snmp-5.4.2.1/../rootfs/usr/local/lib -lnetsnmp   \
  
/usr/bin/ld: skipping incompatible /home/xxx/test/temp/net-snmp-5.4.2.1/perl/default_store/../../snmplib/.libs/libnetsnmp.so when searching for -lnetsnmp
/usr/bin/ld: skipping incompatible /home/xxx/test/temp/net-snmp-5.4.2.1/perl/default_store/../../snmplib/.libs/libnetsnmp.a when searching for -lnetsnmp
/usr/bin/ld: skipping incompatible /home/xxx/test/temp/net-snmp-5.4.2.1/../rootfs/usr/local/lib/libnetsnmp.so when searching for -lnetsnmp
/usr/bin/ld: skipping incompatible /home/xxx/test/temp/net-snmp-5.4.2.1/../rootfs/usr/local/lib/libnetsnmp.a when searching for -lnetsnmp

/usr/bin/ld: cannot find -lnetsnmp

 

所以从开始confingure make makeinstall 时就不能添加交叉编译的选项,按照以下第一篇文档关于mib2c的配置的说明即可。

 

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

以下转了两篇文档:

話先說在前面,不要旨望在這篇文章裡找到 SNMP 的基本理論以及詳盡的 MIB file 說明,本文目的是希望能夠幫大家一把,由零開始到使用 MIB2C 工具製作屬於自己的 MIB,最後建設起自己的 SNMP Server,方法不一定最好,但正如鄧小平說過:『不管黑貓白貓,能捉老鼠的就是好貓。』這篇博文應該能夠替茫無頭緒的朋友找到一點點微光 :)  不要像我這樣在云云網海中 Google 一大堆沒用的資料最後還是要自己亂試一通...

現在,讓我們由下載 Source 開始,一步一步向目標邁進!

1) 到 SourceForge 下載 Net-SNMP

到此處下載:http://net-snmp.sourceforge.net/download.html

在寫本文之時,最新的穩定版本為 5.5,而本文所有的運作步驟皆以 v5.5 為準,所使用的 OS 為 Linux (Ubuntu 10.04)。

2) 正常的 Configure / Compile / Install

下載回來的 Tar Ball,解壓應該不用多說了吧... 假設工作目錄為 ~/dev:
# cd ~/dev
# tar zxf net-snmp-5.5.tar.gz

cd 進去解壓出來的 net-snmp-5.5:
# cd net-snmp-5.5

只需要很簡單的執行一下:
# ./configure --with-default-snmp-version="2" --with-sys-contact="contact@contact" --with-sys-location="location" --with-logfile="/var/log/snmpd.log" --with-persistent-directory="/var/net-snmp"

上列的那些 parameters 若果不填的話,它也會在過程中問你,若果想製作 script 將 compile 過程自動化的話,就需要在執行 configure 時預先輸入參數。

configure 完成後就可以 make 了:
# make

之後... 就會出現錯誤:
/usr/bin/ld: cannot find –lperl

這是因為我的系統太乾淨 :P ,不要緊,立刻安裝 libperl-dev 就好:
# apt-get install libperl-dev

現在所有 Binaries 已經準備就緒,隨時可以安裝了:
# make install

噢耶!安裝完成!但還差一個 conf 檔案:
# vi /etc/snmpd.conf

在 snmpd.conf 中輸入一行:
rocommunity public

:wq 儲存並退出 vim

立刻試試啟動 snmpd:
# snmpd -C -c /etc/snmpd.conf

snmpd: error while loading shared libraries: libnetsnmpagent.so.20: cannot open shared object file: No such file or directory

又出錯誤了... 這是因為 Net-SNMP 把 Lib 都放在 /usr/local/lib 中,但卻沒有把 LD_LIBRARY_PATH 設定好,現在再來一次!

# LD_LIBRARY_PATH=/lib:/usr/local/lib snmpd -C -c /etc/snmpd.conf

snmpd 已經跑起來了,現在可以找另一台電腦用 snmpwalk 看看﹝Remember to replace <ip address> with your IP﹞
# snmpwalk -v2c -c public <ip address>

若果看到一大堆今人摸不著頭腦的資料,例如:

SNMPv2-MIB::sysDescr.0 = STRING: Linux steve-ubuntu 2.6.32-22-generic #33-Ubuntu SMP Wed Apr 28 13:27:30 UTC 2010 i686

就代表安裝成功了 :)

嗯,這時候你會問,這跟文章題目 Cross-compile 以及 MIB2C 完全沒關係啊!好好... 現在我們回去 untar 出來的 net-snmp-5.5 再繼續我們的工作...

3) 使用 MIB2C

其實上面搞這麼一大堆,我目的只是想要 mib2c 這個工具而已... 我沒再研究怎樣可以執行 mib2c 而不安裝 net-snmp,反正這不是我的目的,mib2c 能用就好。

現在可以輸入 mib2c 看看...
# mib2c

Use of uninitialized value $key in hash element at /usr/local/lib/perl/5.10.1/SNMP.pm line 1325.
Use of uninitialized value $key in hash element at /usr/local/lib/perl/5.10.1/SNMP.pm line 1326.
Use of uninitialized value in null operation at /usr/local/lib/perl/5.10.1/SNMP.pm line 1325.

You didn't give mib2c a valid OID to start with.  IE, I could not find
any information about the mib node "".  This could be caused
because you supplied an incorrectly node, or by the MIB that you're
trying to generate code from isn't loaded.  To make sure your mib is
loaded, run mib2c using this as an example:

   env MIBS="+MY-PERSONAL-MIB" mib2c

You might wish to start by reading the MIB loading tutorial at:

   http://www.net-snmp.org/tutorial-5/commands/mib-options.html

And making sure you can get snmptranslate to display information about
your MIB node.  Once snmptranslate works, then come back and try mib2c
again.

嗯,證明 mib2c 已經安裝成功,可以開始製作我們自己的 MIB 了!

現在先進去 mibs 存放的地方 ( /usr/local/share/snmp/mibs/ ):
# cd /usr/local/share/snmp/mibs/

弄一個新的 MIB 出來:
# vi STEVE-TEST-MIB.txt

======[ BEGIN STEVE-TEST-MIB.txt ]======

STEVE-TEST-MIB DEFINITIONS ::= BEGIN

IMPORTS
        enterprises
                FROM RFC1155-SMI
        DisplayString
                FROM RFC-1213
        OBJECT-TYPE, Integer32
                FROM SNMPv2-SMI
        InetAddressType, InetAddress
                FROM INET-ADDRESS-MIB;

company         OBJECT IDENTIFIER ::= {enterprises 12345}
products        OBJECT IDENTIFIER ::= {company 1}

demoIpTable OBJECT-TYPE
        SYNTAX          SEQUENCE OF DemoIpEntry
        MAX-ACCESS      not-accessible
        STATUS          current
        DESCRIPTION
                "Demo IP Table"
        ::= { products 1 }

demoIpEntry      OBJECT-TYPE
        SYNTAX          DemoIpEntry
        MAX-ACCESS      not-accessible
        STATUS          current
        DESCRIPTION
                "Demo IP entry"
        INDEX   { demoIpIndex }
        ::= { demoIpTable 1 }

DemoIpEntry ::= SEQUENCE {
        demoIpIndex      Integer32,
        demoIpAddress    OCTET STRING
}

demoIpIndex OBJECT-TYPE
        SYNTAX          Integer32
        MAX-ACCESS      not-accessible
        STATUS          current
        DESCRIPTION
                "Demo IP entry index"
        ::= { demoIpEntry 1 }

demoIpAddress OBJECT-TYPE
    SYNTAX      OCTET STRING
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "Demo IP Address"
    ::= { demoIpEntry 2 }

END

======[ END STEVE-TEST-MIB.txt ]======

在使用 mib2c 之前,需要先設定 $MIBS 這個 Variable:
# export MIBS=ALL

之後 mib2c 就可以正常運作了:
# mib2c -c mib2c.mfd.conf demoIpTable

或者直接輸入 OID 也可以:
# mib2c -c mib2c.mfd.conf 1.3.6.1.4.1.12345.1.1

在繼續之前先解釋一下為什麼是 1.3.6.1.4.1.12345.1.1 吧。

在 txt 文件的最上方,我們 import 了 enterprises,這已經在 RFC 1155 中定義好,全世界通用,而 enterprises 的 OID 就是 1.3.6.1.4.1,之後,我們寫了一個 OBJECT IDENTIFIER,定義一個叫 company 的 OID 為 1.3.6.1.4.1.12345,根據這個規則,1.3.6.1.4.1.12345.1.1 就是我們要用的 demoIpTable 的 OID 了,明白了嗎?

這個 Demo MIB 使用了 Table,因為 Table 才可以依據情況輸出不同數量的資料,彈性比較大。

而在這個 MIB 中,真正提供資料的是 demoIpAddress,之後在 mib2c 生成的 c file 中,我們可以把任意數量的 IP 放進這裡,讓 SNMP Client 讀取。但為了方便,在 Demo 中使用了 OCTET STRING 而不是 InetAddress,正式使用時 IP Value 應該用 InetAddress 這個 type 才更好。

最後,要注意 demoIpTable 這個字一定要用 Table 作結尾!mib2c 是一個蠢到不行的 Perl 程式,它辨別你是不是 Table 的方法就是靠這個!若果沒有了 Table 字尾,它會認定你是一個 Scalar 而操作失敗!

基本資料理解好了,正式開始 mib2c 吧!

過程中,大部份選項選擇 Default 就可以了,除了以下列出的這些:

Do you need to initialize elements in the 'generated' DATA context when......
選 1) no, no initialization needed。

Which method would you like to use to gather data about available rows?
選 2) container-cached : This access method uses a netsnmp_container to keep track of the indexes (and data, usually) for each row.

好了好了,我承認我其實不知道為什麼要選這兩個,不過根據我的測試選這兩個保證成功,不要問只要信,OK?特別是 3) unsorted-external ,我折騰了大半天都沒搞成功,最後用 2) container-cached 就搞定了。

mib2c 完成之後,就會出現一堆 *.c *.h files:

demoIpTable.c              demoIpTable_data_get.h  demoIpTable.h
demoIpTable_data_access.c  demoIpTable_data_set.c  demoIpTable_interface.c
demoIpTable_data_access.h  demoIpTable_data_set.h  demoIpTable_interface.h
demoIpTable_data_get.c     demoIpTable_enums.h     demoIpTable_oids.h

把這些檔案複製到 net-snmp-5.5/agent/mibgroup/STEVE-TEST-MIB/demoIpTable/,沒有的 directory 請自己 mkdir:
# cp demoIpTable* ~/dev/net-snmp-5.5/agent/mibgroup/STEVE-TEST-MIB/demoIpTable/

並且在 net-snmp-5.5/agent/mibgroup/ 新增一個 STEVE-TEST-MIB.h:
# cd ~/dev/net-snmp-5.5/agent/mibgroup
# echo 'config_require(STEVE-TEST-MIB/demoIpTable/demoIpTable)' > STEVE-TEST-MIB.h

打開 README 看一看:
# cd ~/dev/net-snmp-5.5/agent/mibgroup/STEVE-TEST-MIB/demoIpTable/
# less demoIpTable-README-FIRST.txt

裡邊有一句 grep command,試試執行一次:
# grep -n "TODO:" *.[ch] | sed 's/\([^ ]*\) \(.*\)TODO\(.*\)/\3 (\1)/' | sort -n

:099:x: ************************************************************* (demoIpTable.h:170:)
:100:r: Review all context structures (demoIpTable.h:62:)
:101:o: |-> Review demoIpTable registration context. (demoIpTable.h:65:)
:110:r: |-> Review demoIpTable data context structure. (demoIpTable.h:71:)
:120:r: |-> Review demoIpTable mib index. (demoIpTable.h:90:)
:121:r: |   |-> Review demoIpTable max index length. (demoIpTable.h:104:)
:130:o: |-> Review demoIpTable Row request (rowreq) context. (demoIpTable.h:112:)
:131:o: |   |-> Add useful data to demoIpTable rowreq context. (demoIpTable.h:133:)
:180:o: Review demoIpTable cache timeout. (demoIpTable_data_access.h:40:)
:199:x: ************************************************************* (demoIpTable.h:171:)
:200:r: Implement demoIpTable data context functions. (demoIpTable_data_get.c:41:)
:230:M: Implement demoIpTable get routines. (demoIpTable_data_get.c:18:)
:231:o: |-> Extract the current value of the demoIpAddress data. (demoIpTable_data_get.c:166:)
:240:M: Implement demoIpTable mapping routines (if any). (demoIpTable_data_get.c:19:)
:299:x: ************************************************************* (demoIpTable.h:172:)
:300:o: Perform demoIpTable one-time module initialization. (demoIpTable.c:43:)
:301:o: Perform demoIpTable one-time table initialization. (demoIpTable.c:78:)
:302:o: |->Initialize demoIpTable user context (demoIpTable.c:82:)
:303:o: Initialize demoIpTable data. (demoIpTable_data_access.c:57:)
:345:A: Set up demoIpTable cache properties. (demoIpTable_data_access.c:132:)
:350:M: Implement demoIpTable data load (demoIpTable_data_access.c:173:)
:351:M: |-> Load/update data in the demoIpTable container. (demoIpTable_data_access.c:244:)
:352:M: |   |-> set indexes in new demoIpTable rowreq context. (demoIpTable_data_access.c:280:)
:352:r: |   |-> populate demoIpTable data context. (demoIpTable_data_access.c:297:)
:380:M: Free demoIpTable container data. (demoIpTable_data_access.c:365:)
:390:o: Prepare row for request. (demoIpTable_data_access.c:390:)
:399:x: ************************************************************* (demoIpTable.h:173:)
:499:x: ************************************************************* (demoIpTable.h:174:)
:510:o: Perform demoIpTable pre-request actions. (demoIpTable.c:129:)
:511:o: Perform demoIpTable post-request actions. (demoIpTable.c:155:)

這樣子可以對整個過程有大概了解,但第一次看仍然會看得人頭昏腦脹... 所以之後我會用最少的修改來令 STEVE-TEST-MIB 成功運作。

*** 以下部份黃色字為修改的地方 ***

打開 demoIpTable_data_access.c,到第 234 行。

可以看到它會打開 /etc/dummy.conf 並讀取每一行的內容,往下一點看,會找到 while(1),在 while 之前插入幾行:
    */
    demoIpIndex = 0;
    char demoIpAddress[256];
    size_t demoIpAddress_len;

    while( 1 ) {

再到 327 行左右,會看到 ++count; ,在它之後加入一行:
        CONTAINER_INSERT(container, rowreq_ctx);
        ++count;
        demoIpIndex++;

之後就要把資料 save 下來,到第 271 行找並加入黃色的兩行:
     * check for end of data
     */
    if(NULL == filep)
        break;
    strcpy(demoIpAddress, line);
    demoIpAddress_len = strlen(demoIpAddress);
    /*

然後到 321 行,找這兩句並把它們 comment 掉:
    if ((NULL == rowreq_ctx->data.demoIpAddress) ||
        (rowreq_ctx->data.demoIpAddress_len <
        (demoIpAddress_len* sizeof(demoIpAddress[0])))) {
        //snmp_log(LOG_ERR,"not enough space for value\n");
        //return MFD_ERROR;

    }

這個 comment 純粹是 quick fix,正式使用請詳細檢查,我懷疑 mib2c 這裡有 bug,永遠也會出現 not enough space 錯誤... 但由於我的 buffer 只有 256,但目標 data 卻有 65535... 所以,我相信就算 comment 掉應該也沒有問題的。

4) Compile / Cross-compile

這樣子,修改算是完成了,現在我們可以重新 configure net-snmp :

*** 注意:以下為 Cross-compile 使用的 command ***

# ./configure \
--host=armeb-linux \
--with-install-prefix="/root/dev/net-snmp-5.5/build/" \
--with-default-snmp-version="2" \
--with-sys-contact="contact@contact" \
--with-sys-location="location" \
--with-logfile="/var/log/snmpd.log" \
--with-persistent-directory="/var/net-snmp" \
--sbindir="/sbin" \
--libdir="/lib" \
--datarootdir="/etc" \
--disable-debugging \
--disable-embedded-perl \
--without-perl-modules \
--without-rpm \
--enable-mini-agent \
--enable-static \
--with-mib-modules="STEVE-TEST-MIB"

這次我把 make install 的所有檔案集中起來放到 /root/dev/net-snmp-5.5/build/ 中,還有修改了一下預設的 sbin , lib 等 directory 位置,以及停用了 perl modules,Cross-compile 也很方便,以 armeb-linux 為例,只要加一句 --host=armeb-linux 就可以了。

之後,照例的 make & make install:
# make
# make install

完成後,所有的檔案都會放在 /root/dev/net-snmp-5.5/build/ 這個 directory 內,只要把 build 內的所有檔案複製到 Cross-compile 的目標電腦,就可以運作了~

 

好,那在同一部電腦使用無需 Cross-compile 的話就看這邊

# ./configure \
--with-default-snmp-version="2" \
--with-sys-contact="contact@contact" \
--with-sys-location="location" \
--with-logfile="/var/log/snmpd.log" \
--with-persistent-directory="/var/net-snmp" \
--disable-debugging \
--disable-embedded-perl \
--without-perl-modules \
--without-rpm \
--enable-mini-agent \
--enable-static \
--with-mib-modules="STEVE-TEST-MIB"

之後當然,一樣的 make & make install:
# make
# make install

這樣子所有的 binaries 及 libraries 都會安裝到預設的 /usr/local/ 目錄,現在可以執行 snmpd 看看新的 Custom MIB 了!

不過執行 snmpd 前先要在 /etc/dummy.conf 隨便輸入兩行資料,mib2c 製作的 c file 預設會在這裡讀資料還記得嗎?我寫了兩行 IP 作測試:

10.9.1.1
192.168.1.1

準備好 dummy.conf 之後,就可以正式啟動 snmpd 了!為安全起見我們先 killall 一下:
# killall snmpd
# LD_LIBRARY_PATH=/usr/local/lib snmpd -C -c /etc/snmpd.conf

再 snmpwalk 1.3.6.1.4.1.12345 看看結果,成功的話就會看到類似這樣的資料嘍:
# snmpwalk -v2c -c public <ip address> 1.3.6.1.4.1.12345

SNMPv2-SMI::enterprises.12345.1.1.1.2.0 = STRING: "10.9.1.1"
SNMPv2-SMI::enterprises.12345.1.1.1.2.1 = STRING: "192.168.1.1"

一直走到這裡,恭喜你!你成功利用 mib2c 製作了一個屬於自己的 MIB 啦!

希望這篇文章對急需學習 Net-SNMP 的大家有少許幫助,又或大家發現了文章中的錯處,請務必留言告訴我,讓我可以盡快修正 :)

最後,此文章歡迎轉載,但請註明出處為‧好天氣‧http://blogger.kesteve.com,謝謝啦

 

 

 

 

 

 

 

 

另一篇文档,http://lazyflai.blogspot.com/2007/01/net-snmpmib2c.html:

 

Net-SNMP的mib2c 收藏
今天在搞net-snmp所提供的mib2c tool,
用起來說實在的實在有點難用。
大概是我對它還不太熟的關係吧。
以下是今天弄的一些心得:
(因為開發需求,所以設定prefix為/opt/net-snmp。)

1.
首先,在安裝net-snmp時,需在configure時加入以下參數
$ ./configure --prefix=/opt/net-snmp/ --enable-embedded-perl --enable-shared --with-perl-modules
$ make
$ make test
# make install (should be root)


2.
在確定PATH設定好後,執行mib2c時,
通常會遇到訊息說沒有安裝Perl SNMP Module,
這是因為我們在configure時有設了prefix的關係,
導致perl找不到share library。
解決的方法是將net-snmp的lib目錄設定給ldconfig知道即可。
# echo /opt/net-snmp/lib > /etc/ld.so.conf.d/net-snmp.conf
# ldconfig -v


3.
最後就是mib2c操作方法,
據mib2c的manpage裡說明,
mib2c的功用是產生template code給agent來擴充功能使用。
Usage為
mib2c [-h] -c CONFIGFILE [-I PATH] [-f OUTNAME] [-i][q][-S VAR=VAL] MIBNODE

而mib2c的使用方法是以mib node為parameter來開始生成template code。
所以必須先將mib file放置在$HOME/.mibs/或/opt/net-snmp/share/snmp/mibs,
然後在環境變數中設定MIBS,
export MIBS=+NET-SNMP-TUTORIAL-MIB

接著麻煩的在這裡,
你必須依著你的的mib node來選定所產生的template code的CONFIGFILE。
下面是CONFIGFILE所支援的類型:
如果你要寫些scalars所需的code,請用:
mib2c -c mib2c.scalar.conf MIBNODE

如果你要用int scalars,請用:
mib2c -c mib2c.int_watch.conf MIBNODE


一般來講Table是建議採用MDF:
mib2c -c mib2c.mfd.conf MIBNODE

如果Table Data是在外部時:
mib2c -c mib2c.iterate.conf MIBNODE

如果Table Data是在agent裡:
mib2c -c mib2c.create-dataset.conf MIBNODE

承上,如果還需排序時:
mib2c -c mib2c.array-user.conf MIBNODE


如果是要產生Table上任一Column的header時:
mib2c -c mib2c.column_defines.conf MIBNODE

如果是要產生Column上任一Enum的header時:
mib2c -c mib2c.column_enums.conf MIBNODE


4.
結論,大概就是麻煩吧。
Net-SNMP不像其他商用的SNMP套件一樣提供簡易的開發擴充功能的環境,
像在EMANATE中打一個make就ok了,連型態都自動判斷。
不過也許是我對mib2c還不太熟的關係吧,Orz。

 

你可能感兴趣的:(c,String,table,Integer,工具,library)