1. 程式人生 > >Snmp Agent開發流程

Snmp Agent開發流程

作者:zyq

時間:2010-11-3

Snmp Agent擴充套件

該文件將主要講述基於開源專案net-snmpsnmp代理端開發流程,首先講標準代理的安裝流程,再講述三種mib擴充套件方式,每種方式對應不同的開發需求,最後會講下如何移植到arm板上。

一.系統環境:

作業系統:CentOS 5.4核心:Linux_2.6

編譯環境:gcc 4.1.2程式碼版本:net-snmp-5.4.3.tar.gz

(下載地址:http://jaist.dl.sourceforge.net/project/net-snmp/net-snmp/5.4.3/net-snmp-5.4.3.tar.gz)

二.安裝net-snmp

1.解壓縮包並切換目錄:

# tar zxvf net-snmp-5.4.3.tar.gz

#cd net-snmp-5.4.3

2.配置configure

#./configure --enable-mfd-rewrites --enable-embedded-perl --with-perl-modules --with-default-snmp-version="2" --with-sys-contact="linux" --with-sys-location="China"

此時會提示還需要一些引數,直接回車就行了

3.編譯和安裝

#make

#make install

此時一個標準的

snmp代理端已經安裝完成(預設安裝在/usr/local/share/snmp/路徑下,snmpd即為代理程式)

4.配置代理,修改配置檔案(可以通過snmpconf命令生成配置檔案,這裡我手動建立配置檔案,只做簡單配置,保證其可以工作,具體設定可以自己查詢)

#vim /usr/local/share/snmp/snpmd.conf

輸入如下兩行配置,儲存(其中public為預設讀密碼123456為讀寫密碼)

rocommunitypublic

rwcommunity123456

5.測試我們的代理是否正常工作,輸入:

#snmpwalk -v 1 -c public localhost 1.3.6.1.2.1.1

提示如下類似資訊,則配置成功

SNMPv2-MIB::sysDescr.0 = STRING: Linux localhost 2.6.18-164.el5 #1 SMP Thu Sep 3 03:33:56 EDT 2009 i686

SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-TC::linux

DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (1047697) 2:54:36.97

SNMPv2-MIB::sysContact.0 = STRING: linux

SNMPv2-MIB::sysName.0 = STRING: mylinux

SNMPv2-MIB::sysLocation.0 = STRING: China

SNMPv2-MIB::sysORLastChange.0 = Timeticks: (1) 0:00:00.01

SNMPv2-MIB::sysORID.1 = OID: SNMP-FRAMEWORK-MIB::snmpFrameworkMIBCompliance

SNMPv2-MIB::sysORID.2 = OID: SNMP-MPD-MIB::snmpMPDCompliance

SNMPv2-MIB::sysORID.3 = OID: SNMP-USER-BASED-SM-MIB::usmMIBCompliance

SNMPv2-MIB::sysORID.4 = OID: SNMPv2-MIB::snmpMIB

SNMPv2-MIB::sysORID.5 = OID: TCP-MIB::tcpMIB

SNMPv2-MIB::sysORID.6 = OID: IP-MIB::ip

SNMPv2-MIB::sysORID.7 = OID: UDP-MIB::udpMIB

SNMPv2-MIB::sysORID.8 = OID: SNMP-VIEW-BASED-ACM-MIB::vacmBasicGroup

SNMPv2-MIB::sysORDescr.1 = STRING: The SNMP Management Architecture MIB.

SNMPv2-MIB::sysORDescr.2 = STRING: The MIB for Message Processing and Dispatching.

SNMPv2-MIB::sysORDescr.3 = STRING: The management information definitions for the SNMP User-based Security Model.

SNMPv2-MIB::sysORDescr.4 = STRING: The MIB module for SNMPv2 entities

SNMPv2-MIB::sysORDescr.5 = STRING: The MIB module for managing TCP implementations

SNMPv2-MIB::sysORDescr.6 = STRING: The MIB module for managing IP and ICMP implementations

SNMPv2-MIB::sysORDescr.7 = STRING: The MIB module for managing UDP implementations

SNMPv2-MIB::sysORDescr.8 = STRING: View-based Access Control Model for SNMP.

SNMPv2-MIB::sysORUpTime.1 = Timeticks: (0) 0:00:00.00

SNMPv2-MIB::sysORUpTime.2 = Timeticks: (0) 0:00:00.00

SNMPv2-MIB::sysORUpTime.3 = Timeticks: (0) 0:00:00.00

SNMPv2-MIB::sysORUpTime.4 = Timeticks: (1) 0:00:00.01

SNMPv2-MIB::sysORUpTime.5 = Timeticks: (1) 0:00:00.01

SNMPv2-MIB::sysORUpTime.6 = Timeticks: (1) 0:00:00.01

SNMPv2-MIB::sysORUpTime.7 = Timeticks: (1) 0:00:00.01

SNMPv2-MIB::sysORUpTime.8 = Timeticks: (1) 0:00:00.01

三.擴充套件自己的mib

以上步驟只是完成了一個包含標準mib庫的代理端安裝,下面將介紹如何加入自己的mib庫,以下灰色部分是用mib2c工具生成.c.h檔案的方法,僅供參考,個人不推薦,可以跳過

1.假如下面是我們自己編寫的mib檔案(儲存為BVCOM-SYSTEMUPTIME-MIB.txt)

BVCOM-SYSTEMUPTIME-MIB DEFINITIONS ::= BEGIN

IMPORTS

TimeTicks FROM SNMPv2-SMI

enterprises FROM SNMPv2-SMI

OBJECT-TYPE, Integer32, MODULE-IDENTITY FROM SNMPv2-SMI;

bvcom OBJECT IDENTIFIER ::= { enterprises 26814 }

ipq6800 OBJECT IDENTIFIER ::= { bvcom 6800 }

bvcomAgentModules OBJECT IDENTIFIER ::= { ipq6800 1 }

bvcomAgentModuleObject OBJECT-TYPE

SYNTAX Integer32

MAX-ACCESS read-write

STATUS current

DESCRIPTION

"This is an object that simply supports a writable integer

when compiled into the agent. See

http://www.net-snmp.org/tutorial-5/toolkit/XXX for further

implementation details."

DEFVAL { 1 }

::= { bvcomAgentModules 1 }

bvcomAgentSubagentObject OBJECT-TYPE

SYNTAX Integer32

MAX-ACCESS read-write

STATUS current

DESCRIPTION

"This is an object that simply supports a writable integer

when attached to the agent. The object should be accessible

when the agentx subagent containing this object is attached.

See http://www.net-snmp.org/tutorial-5/toolkit/XXX for

further implementation details."

DEFVAL { 2 }

::= { bvcomAgentModules 2 }

bvcomAgentPluginObject OBJECT-TYPE

SYNTAX Integer32

MAX-ACCESS read-write

STATUS current

DESCRIPTION

"This is an object that simply supports a writable integer

when attached to the agent. This object should be accessible

when the dynamic plugin has been loaded into the agent. See

http://www.net-snmp.org/tutorial-5/toolkit/XXX for further

implementation details."

DEFVAL { 3 }

::= { bvcomAgentModules 3 }

END

2.複製mib庫檔案到/usr/local/share/snmp/mibs/
# cp BVCOM-SYSTEMUPTIME-MIB.txt /usr/local/share/snmp/mibs/BVCOM-SYSTEMUPTIME-MIB.txt

3. 載入mib庫(修改snmp.conf檔案,該檔案也要自己建立,或通過snmpconf生成)
vim /usr/local/share/snmp/snmp.conf

輸入如下並儲存:
mibs +BVCOM-SYSTEMUPTIME-MIB

4.測試mib庫是否載入成功

# snmptranslate -IR -Tp bvcom

出現如下資訊表示成功

+--bvcom(26814)

|

+--ipq6800(6800)

|

+--bvcomAgentModules(1)

|

+-- -RW- Integer32 bvcomAgentModuleObject(1)

+-- -RW- Integer32 bvcomAgentSubagentObject(2)

+-- -RW- Integer32 bvcomAgentPluginObject(3)

5. 檢視mib2c支援的模板
# ls /usr/local/share/snmp/

顯示如下
mib2c.access_functions.conf mib2c.create-dataset.conf mib2c.scalar.conf
mib2c.array-user.conf mib2c-data mib2c.table_data.conf
mib2c.check_values.conf mib2c.genhtml.conf mibs
mib2c.check_values_local.conf mib2c.int_watch.conf snmp.conf
mib2c.column_defines.conf mib2c.iterate_access.conf snmp.conf~
mib2c.column_enums.conf mib2c.iterate.conf snmpconf-data
mib2c.column_storage.conf mib2c.mfd.conf snmpd.conf
mib2c.conf mib2c.notify.conf snmp_perl.pl
mib2c.container.conf mib2c.old-api.conf snmp_perl_trapd.pl

6.
通過模板生成.c .h 檔案(因為自定義的mib庫中的變數都是int型別的所以模板選擇int_watch.conf,不同的模板功能不同)

自己建立一個資料夾example-demon,並切換到該目錄下,
# mib2c -c mib2c.int_watch.conf bvcomAgentModules
writing to -
*** Warning: only generating code for nodes of MIB type INTEGER
writing to bvcomAgentModules.h
writing to bvcomAgentModules.c
running indent on bvcomAgentModules.c
running indent on bvcomAgentModules.h

這樣在當前目錄下就生成了我們自己mib庫對應的bvcomAgentModules.cbvcomAgentModules.h,這兩個檔案只提供了框架,具體的讀內容和寫內容需要自己完成

這種通過工具生成的ch檔案,比較模式化,不夠靈活,不建議採用,建議參考原始碼net-snmp-5.4.3/agent/mibgroup/examples下的example.cexample.h,其相應的mib檔案在net-snmp-5.4.3/mibs/NET-SNMP-EXAMPLES-MIB.txt有了我們mib庫對應的example.c example.h檔案,現在我們就需要將其加入snmp代理中了,首先我們通過snmp_agent_api 編寫守護程式 example-demon.c(新建一個test資料夾,將example.c example.h考入其中),並將如下程式碼儲存為example-demon.c    (文章末尾有附件可以下載

/*主函式: */

#include <net-snmp/net-snmp-config.h>

#include <net-snmp/net-snmp-includes.h>

#include <net-snmp/agent/net-snmp-agent-includes.h>

#include <signal.h>

#include "example.h"//這裡要包含剛才的標頭檔案

static int keep_running;

RETSIGTYPE
stop_server(int a) {
keep_running = 0;
}

int
main (int argc, char **argv) {

int agentx_subagent=0; /* change this if you want to be a SNMP master agent */

int background = 0; /* change this if you want to run in the background */
int syslog = 0; /* change this if you want to use syslog */

/* print log errors to syslog or stderr */

if (syslog)
snmp_enable_calllog();
else
snmp_enable_stderrlog();

/* we're an agentx subagent? */
if (agentx_subagent) {
/* make us a agentx client. */
netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, 1);
}

/* run in background, if requested */
if (background && netsnmp_daemonize(1, !syslog))
exit(1);


/* Initialize tcpip, if necessary */
SOCK_STARTUP;

/* Initialize the agent library */
init_agent("example-demon"); //
配置檔名

/* Initialize our mib code here */
printf("Before init bvcomAgentModules /n");

init_bvcomAgentModules(); //
載入節點資訊

printf("End init bvcomAgentModules /n");

/* initialize vacm/usm access control */
if (!agentx_subagent) {
void init_vacm_vars();
void init_usmUser();
}

/* Example-demon will be used to read example-demon.conf files. */
init_snmp("example-demon");

/* If we're going to be a snmp master agent, initial the ports */
if (!agentx_subagent)
init_master_agent(); /* open the port to listen on (defaults to udp:161) */

printf("---------------------/n");
/* In case we recevie a request to stop (kill -TERM or kill -INT) */
keep_running = 1;
signal(SIGTERM, stop_server);

signal(SIGINT, stop_server);

snmp_log(LOG_INFO,"example-demon is up and running./n");

/* your main loop here... */
while(keep_running) {
/* if you use select(), see snmp_select_info() in snmp_api(3) */
/* --- OR --- */
agent_check_and_process(1); /* 0 == don't block */

}

/* at shutdown time */
snmp_shutdown("example-demon");
SOCK_CLEANUP;
return 0;
}

下面是makefile

CC=gcc

OBJS2=example-demon.o example.o

TARGETS=example-demon

CFLAGS=-I. `net-snmp-config --cflags`

BUILDLIBS=`net-snmp-config --libs`

BUILDAGENTLIBS=`net-snmp-config --agent-libs`

# shared library flags (assumes gcc)

DLFLAGS=-fPIC –shared

all: $(TARGETS)

example-demon: $(OBJS2)

$(CC) -o example-demon $(OBJS2) $(BUILDAGENTLIBS)

clean:

rm $(OBJS2) $(OBJS2) $(TARGETS)

編譯即可生成我們的代理example-demon

這裡要講一下int agentx_subagent=0;這個引數的意義

/* =0表示該程式要作為主代理,即不需要snmpd程序的支援,程式自身可以獨立執行(需要自己的配置檔案Vim /usr/local/share/snmp/example-demon.conf,與上配置一樣),此時能讀到的mib庫只有自己定義的那部分,=1表示作為子代理,需要snmpd先執行(在配置檔案snmpd.conf中新增master agentx,使snmpd作為主代理執行,),此時在執行我們的程序,即可以讀到原來的mib庫和自己新增的mib */

通過agentx_subagent引數的設定我們已經實現了兩種方式的代理擴充套件,

第三種方式

就是將我們自己的mib庫對應的c檔案和h檔案直接編譯進snmpd中,使其作為一個整體執行,這時我們需要重新編譯安裝net-snmp

1.example.cexample.h複製到net-snmp-5.4.3/agent/mibgroup

#cp example.? /net-snmp-5.4.3/agent/mibgroup/

2.設定編譯引數(紅色部分即為加上我們自己的mib模組)

#./configure --enable-mfd-rewrites --with-default-snmp-version="2" --with-sys-contact="linux" --with-sys-location="China" --enable-shared --with-mib-modules="example"

3.編譯並安裝

#make & make install

然後按第一步一樣進行snmpd.conf配置檔案修改,

此時再執行snmpd,我們自己的mib庫就已經在裡面了

四.將snmp代理移植到arm板上

移植主要就是修改configure引數,(當然要裝arm-linux-gcc,我的版本是gcc version 2.95.3 20010315)進行重新編譯,使其儘量小,儘量精簡,下面提供一種引數,至於進一步優化,可以自己嘗試修改

執行下列命令:

CC=arm-linux-gcc LDFLAGS="-static" ./configure --build=i386-linux --host=arm-linux --enable-mini-agent --disable-ipv6 --with-endianness=little --disable-manuals --disable-ucd-snmp-compatibility --enable-as-needed --disable-embedded-perl --without-perl-modules --disable-snmptrapd-subagent --disable-applications --disable-scripts

配置完成後進行編譯:make

切換到snmpd所在目錄/agent

使用如下命令進行壓縮,使代理更小:

#arm-linux-strip snmpd

snmpdsnmpd.conf檔案移到linuxnfs(一個網路內的主機共享主目錄)下,snmpd檔案上傳到nfs/usr/local/sbin目錄下(需要更改訪問許可權為可執行),將snmpd.conf檔案上傳到nfs/usr/local/share/snmp/(不存在的目錄先要建立)

至此,我們就可以在arm板上執行snmp代理了,當然這種最小話安裝,少了很多mib庫,能檢視的資訊不多,我們可以自己擴充套件和修改configure引數加入我們想要的mib

總結

擴充套件snmp 代理的難點在於例程中example.cexample.h檔案的編寫,例程裡提供的這兩個檔案寫的非常好,包含各種資料型別,整合度很高,建議對著這個示例進行擴充套件。