net-snmp移植项目总结

黄俊智
2023-12-01

1、       项目移植总结

1.1  交叉编译的configure参数的配置

交叉编译参数的设置,这个部分是最基本的,如果参数设置的有问题,snmpd运行起来就会有问题。

在x86环境下进行测试的时候,选用一个简单的编译参数,可以工作:

LDFLAGS="-L/home/zmj/work/LNOS/mc218/lib/x86"LIBS="-lsqlite3 -lmc218 -lpthread"CPPFLAGS="-I/home/zmj/work/LNOS/mc218/include" ./configure  --enable-shared --with-perl-modules--with-mib-modules="XXX-MIB mibII/system_mib"--prefix=/home/zmj/work/snmp

对编译参数进行一下说明,

LDFLAGS:是要引用到的私有库的路径,

LIBS:是要引用的库,

CPPFLAGS:要引用的头文件的路径

--with-mib-modules:要编译进来的库,net-snmp有一些自带的库,其中mibII/system_mib就是net-snmp自带的库,还可以加一些自定义的库,如XXX_MIB

 

交叉编译的时候,参数如下:

LDFLAGS="-L`pwd`/../mc218/lib/arm"LIBS="-lsqlite3 -lmc218 -lpthread" CPPFLAGS="-I`pwd`/../mc218/include" ./configure --build=i386-linux--host=arm-linux --disable-ipv6 --with-endianness=little --disable-manuals--disable-ucd-snmp-compatibility --disable-embedded-perl --without-perl-modules--disable-snmptrapd-subagent --disable-applications --disable-scripts--with-enterprise-oid=n --with-enterprise-sysoid=.1.3.6.1.4.1.x.x--enable-mini-agent --with-mib-modules="mibII/system_mib XXX-MIB"--with-sys-location="Beijing"--with-sys-contact="wyz@localhost"-with-default-snmp-version="2"--with-logfile="/var/log/snmpd.log" --with-persistent-directory="/var/net-snmp"--sysconfdir="/etc/" --disable-mib-loading  --prefix=$PREFIX

为了在嵌入式环境当中编译出来的文件最小,对snmp进行了一定的简化,没有编译help、snmptrapd等信息,最小化snmpd,配置为小端模式,其中--with-enterprise-oid配置的是企业号是一个整数,--with-enterprise-sysoid配置的是企业系统ID,这样在snmp管理软件读取的时候才能正确显示相关信息

1.2  编译自定义的mib文件

具体详情可以参见《snmp学习笔记-自定义节点的实现.docx》文档

1.3  增加自定义的trap,inotify的使用

具体详情可行参见《RD030-snmptrap设计文档.docx》文档

1.4  修改启动daemon进程代码的位置

在net-snmp运行的过程中发现,snmpd启动的过程当中,如果打开调试开关,使用命令snmpd –f –Le运行snmpd,那么snmpd发送trap是正常的,指定的服务器可以接收到trap信息。但是,如果直接打开snmpd,使用命令snmpd,则snmpd在后台运行,这个时候发现服务器接收不到snmpd发送trap信息。

查看代码发现,启动daemon进程是在net-snmp-5.7.2/agent/snmpd.c文件当中入口函数main中,并且开启daemon进程的函数netsnmp_daemonize函数是在初始化mib(init_mib_modules)之后。应该是trap的某些工作在fork之前操作,但是子进程又没有继承过来。导致了trap的初始化工作做的不到位。

因此修改代码,把daemon的操作移到int_mib_modules之前去执行,这样后面的代码子进程就会执行一遍了。

1.5  解决发送冷启动、热启动trap的问题

在net-snmp的代码当中,默认发送coldstart告警,并且不论是冷启动还是热启动,都发送coldstart告警,在net-snmp官网上查看FAQ,发现这是一个一致存在的问题,官方没有找到解决方案。

在这个项目中,我们结合电源管理部分的特征,在启动的时候动一下手脚,创建一个只读文件/proc/tsc,如果是冷重启,那么创建文件的时候,写入0;否则就写入一个不等于0的数字。这样,我们就可以在snmpd启动的时候(net-snmp-5.7.2/agent/snmpd.c文件main函数当中),增加一个判断,读取文件/proc/tsc的值,如果是0,就发送coldstart告警(send_easy_trap(0,0);)否则,发送warmstart告警(send_easy_trap(1,0);)

1.6  sysName的问题

在net-snmp当中有三个节点sysName、sysLocation、sysContact,这三个节点比较特殊,在mib文件当中可以发现这三个节点是可读可写的,可是在实际的应用当中发现,在snmpd启动之后没有/etc/snmp/snmpd.conf配置文件的时候,sysName、sysLocation、sysContact三个节点都是可读可写的;如果已经存在了/etc/snmp/snmpd.conf配置文件,这时候sysLocation、sysContact两个节点是不可以写的,sysName可以写,但是修改的值并不对hostname造成影响,而是修改了配置文件/var/net-snmp/snmpd.conf,增加了psysName字段。

在官网的FAQ中解释说,出于安全考虑,sysName、sysLocation、sysContact只有在配置文件不存在的情况下才可以修改。

实际的情况跟官网有出入,就是sysName的特殊性,并且在网上也找到一些网友发出这样的疑问,但是目前没有得到解答。

追踪代码可以发现,在文件system_mib.c当中,这三个节点的更新是通过system_store函数实现,并且使用了三个特殊的变量sysLocationSet、sysContactSet、sysNameSet。就是这三个变量成为三个节点是否可写的开关。
目前,还没有找到为什么sysName跟sysLocation和sysContact两个节点表现不一样,后期还需要修改。

1.7  未解决的问题

在移植net-snmp的过程当中,需要引用外部自己写的库,包含外部头文件的时候发现使用相对路径包含不成功,最终使用了绝对路径进行引用,代码才编译通过,这个问题至今还没有找到原因。

2、       总结的经验教训

总体来说,net-snmp的移植只要掌握了技巧,移植的过程并不是特别难,因为net-snmp本来代码完整,还有编译自定义mib的软件mib2c,所以移植的过程当中注意以下几点:

1、   首先是自定义mib文件的形成,这个文件很重要,如果后期反复修改的话,每次都要编译一遍,增加了很多工作量。编写mib文件的时候要规范,结构要清楚,否则,后期snmp服务器就无法识别,而且也不好扩展,在snmp服务器上画面板图等工作就不好执行。

2、   其次,根据需要设置configure参数,这个参数直接影响了移植出来的snmpd是否可以工作,需要反复实验。

3、   不要蛮目的相信mib2c软件,在实际应用的过程当中,我就发现mib2c生成的代码有出错的情况,例如生成的XXX_interface.c文件里面把配置只读,还是可读可写的地方写反了。当然,这样的情况就发现一处,大部分的代码还是正确的。实际的应用当中,自己要稍微检查一下生成的代码,看看是否有问题。

4、   在使用mib2c编译自定义代码的时候,会生成一个配置文件,当第二次编译的时候就可以直接修改生成的配置文件,而不用一步一步的选择配置项了。例如使用mib2c –c mib2c.mfd.conf 命令的时候,就会在snmp\share\snmp\mibs\defaults文件夹下生成配置文件table-XXX.m2d

 类似资料: