snmp总结

来源:互联网 发布:淘宝返利网怎么返利 编辑:程序博客网 时间:2024/05/12 17:16

接触snmp有3个星期左右了吧,现在来总结下子自己在这期间做了些什么,老板给我的任务有以下几项:

  1:aggen.cpp与globaltime版本对齐,就是个个文件是对应的,都保证是相互兼容的,不一定都是最新的。

  2:写一个gpd的驱动,他主要是用于电源的管理,用来查询和通知snmp电源现在的状况。

  3:系统的一些状态。例如cpu利用率,内存利用率。

  4:代理端发送trap时使用162端口,这样做有利于防火墙的规范

大体上是这多,以下对以上4点做详细的介绍.

对齐问题:

        在aggen.cpp里有一个读取硬件寄存器的一段,这是针对x86构架的:

//读取电源状态
    {
     int nVal;
         ioperm(0x2f1,1,1);
         nVal = inb(0x2f1);    //读取键盘
         nVal >>= 6;
         ioperm(0x2f1,1,0);
       
         //报警
         if(g_nPowerStatus != nVal && nVal != 0 && nVal != 3)
         {
          //printf("val = %d/n",nVal);
          g_nPowerStatus = nVal;
          g_lpSnmpData->SendAllTrapType(oidTrapMsgPowerErr);
         }

       }*/

     全部屏蔽掉,因为我们是用在arm上的。

signal (SIGTERM, sig);
 signal (SIGINT, sig);
 signal (SIGSEGV, sig);
 signal (SIGALRM,sig);

是对这4个信号的处理,至于这4个信号在我的另一片博客上有讲到。

保证mib树的值是对的,#define oidSysMsgReBoot                  "1.3.6.1.4.1.2354.1.2.1.0"
#define oidSysMsgLocalTime               "1.3.6.1.4.1.2354.1.2.2.0"
#define oidSysMsgLocalDate               "1.3.6.1.4.1.2354.1.2.3.0"
#define oidSysMsgTimeSource              "1.3.6.1.4.1.2354.1.2.4.0"
#define oidSysMsgSetTrapAddress           "1.3.6.1.4.1.2354.1.2.5.0"

#define oidSysMsgpower1status             "1.3.6.1.4.1.2354.1.2.6.0"
#define oidSysMsgpower2status             "1.3.6.1.4.1.2354.1.2.7.0"
#define oidSysMsgcpustatus                "1.3.6.1.4.1.2354.1.2.8.0"
#define oidSysMsgmemorystatus             "1.3.6.1.4.1.2354.1.2.9.0"

#define oidTrapMsgColdStart              "1.3.6.1.4.1.2354.1.3.1"
#define oidTrapMsgNtpAlarm               "1.3.6.1.4.1.2354.1.3.2"
#define oidTrapMsgGpsUnlocked            "1.3.6.1.4.1.2354.1.3.4"
#define oidTrapMsgNewSyncType            "1.3.6.1.4.1.2354.1.3.5"
#define oidTrapMsgPowerErr               "1.3.6.1.4.1.2354.1.3.7"
#define oidTrapMsgRootDlay               "1.3.6.1.4.1.2354.1.3.8"
#define oidTrapWorkStatusChange          "1.3.6.1.4.1.2354.1.3.9"
//2007-3-13 17:59添加错误时间源trap
#define oidTrapErrorTimeSource          "1.3.6.1.4.1.2354.1.3.10"
//2007-5-27 11:13添加主备机切换,0表示当前状态为备机,1表示为主机
#define oidTrappulsechange                "1.3.6.1.4.1.2354.1.3.11"
#define oidTrapcpualarm                   "1.3.6.1.4.1.2354.1.3.12"

#define oidNtpSysHostMode                "1.3.6.1.4.1.2354.1.4.6.0"
#define oidNtpSysStratum                 "1.3.6.1.4.1.2354.1.4.7.0"
#define oidNtpSysPoll                    "1.3.6.1.4.1.2354.1.4.8.0"
#define oidNtpSysPrecision               "1.3.6.1.4.1.2354.1.4.9.0"
#define oidNtpSysRootDelay               "1.3.6.1.4.1.2354.1.4.10.0"
#define oidNtpSysRootDisp                "1.3.6.1.4.1.2354.1.4.11.0"
#define oidNtpSysRefClockIdent           "1.3.6.1.4.1.2354.1.4.12.0"

#define oidNtpSysRunTime                 "1.3.6.1.4.1.2354.1.4.13.0"
#define oidNtpDeviceDiscrible            "1.3.6.1.4.1.2354.1.4.14.0"
#define oidNtpSysWorkStatus              "1.3.6.1.4.1.2354.1.4.15.0"
//2007-5-27 11:14,表示查询当前的机器为主备机状态
#define oidNtpSysPulseStatus             "1.3.6.1.4.1.2354.1.4.16.0"
#define oidTest         "1.3.6.1.4.1.2354.1.4.17.0"

#define oidGpsGroupValid                 "1.3.6.1.4.1.2354.1.5.1.0"
#define oidGpsNumTrackSats               "1.3.6.1.4.1.2354.1.5.2.0"
#define oidGpsLongitude                  "1.3.6.1.4.1.2354.1.5.4.0"
#define oidGpsLatitude                   "1.3.6.1.4.1.2354.1.5.5.0"
#define oidGpsHeight                     "1.3.6.1.4.1.2354.1.5.6.0"

//电源的状态
#define oidpower1status                  "1.3.6.1.4.1.2354.1.6.1.0"
#define oidpower2status                  "1.3.6.1.4.1.2354.1.6.2.0"
#define oidcpu                           "1.3.6.1.4.1.2354.1.6.3.0"
#define oidmemory                        "1.3.6.1.4.1.2354.1.6.4.0"

//手工添加的TRAP数据包参数OID定义
#define oidImuParamMsgDesc   "1.3.6.1.4.1.2354.1.7.1"
#define oidImuParamServerName   "1.3.6.1.4.1.2354.1.7.2"
#define oidImuParamServerIPAddress  "1.3.6.1.4.1.2354.1.7.1.3"
#define oidImuParamWarnningTime   "1.3.6.1.4.1.2354.1.7.1.4"
#define oidImuParamActData   "1.3.6.1.4.1.2354.1.7.1.5"
//#define oidGloblEnterprise   "1.3.6.1.4.1.2011.2.105.1.1"
#define oidGlobalTimeEnterprise        "1.3.6.1.4.1.2354.1"

//表示trap的值
#define oidTrapDataValue   "1.3.6.1.4.1.2354.1.7.3"

这些值是和globaltime_mib.txt对应的--iso           OBJECT IDENTIFIER ::= { 1 }
 --org             OBJECT IDENTIFIER ::= { iso 3 }
 --dod             OBJECT IDENTIFIER ::= { org 6 }
 --internet        OBJECT IDENTIFIER ::= { dod 1 }
 --private         OBJECT IDENTIFIER ::= { internet 4 }
 --enterprises     OBJECT IDENTIFIER ::= { private 1 }
 --globalTimeCom   OBJECT IDENTIFIER ::= { enterprises 2354 }

gttMIB MODULE-IDENTITY
    LAST-UPDATED    "200602230000Z"
    ORGANIZATION    "Shanghai GLOBALTIME CO. Ltd."
    CONTACT-INFO    "contact@globaltime.com.cn"
    DESCRIPTION     "NTP Server MIB File"
    ::= { gtt 1 }
  
    globalTimeEnt   OBJECT IDENTIFIER ::= { enterprises 2354 }
    gtt OBJECT IDENTIFIER ::= { globalTimeEnt 1 }
  
    --gttMIB          OBJECT IDENTIFIER ::= { gtt 1 }
    sysMsg          OBJECT IDENTIFIER ::= { gtt 2 }
 trapMsg         OBJECT IDENTIFIER ::= { gtt 3 }
 ntp             OBJECT IDENTIFIER ::= { gtt 4 }
 gps             OBJECT IDENTIFIER ::= { gtt 5 }

gttMIBConformance OBJECT IDENTIFIER ::= { gttMIB 1 }

gttMIBCompliances OBJECT IDENTIFIER ::= { gttMIBConformance 1 }

gttMIBGroups      OBJECT IDENTIFIER ::= { gttMIBConformance 2 }

gttMIBCompliance MODULE-COMPLIANCE
    STATUS   current
    DESCRIPTION "compliance statements."
    MODULE  -- this module
        MANDATORY-GROUPS
        {
--         trapMsgGroup,
         sysMsgGroup,
         ntpGroup,
      gpsGroup
      sysstatusGroup
        }
    ::= { gttMIBCompliances 1 }

gttNotificationsGroup NOTIFICATION-GROUP
 NOTIFICATIONS 
    {
        trapMsgColdStart,
        trapMsgNtpAlarm,
        trapMsgGpsUnlocked,
        trapClientTimeErr,
        trapMsgNewSyncType,
        trapMsgPower1Err,
     
        trapMsgRootDlay,
        trapMsgWorkStatusChange,
        trapErrorTimeSource,
        Trappulsechange,
        Trapcpualarm
    }
    STATUS    current
    DESCRIPTION
            "units of conformance"
    ::= { gttMIBGroups 4 }
  
sysMsgGroup OBJECT-GROUP
    OBJECTS 
    {
     sysMsgReBoot,
     sysMsgLocalTime,
     sysMsgLocalDate,
     sysMsgTimeSource,
     SysMsgSetTrapAddress,
     SysMsgpower1status,
    SysMsgpower2status,
    SysMsgcpu,
    SysMsgmemory
    }
    STATUS    current
    DESCRIPTION
            "units of conformance"
    ::= { gttMIBGroups 1 }

ntpGroup OBJECT-GROUP
    OBJECTS 
    {
     ntpSysHostMode,
     ntpSysStratum,
     ntpSysPoll,
     ntpSysPrecision,
     ntpSysRootDelay,
     ntpSysRootDisp,
     ntpSysRefClockIdent,
     ntpSysRunTime,
     ntpNtpDeviceDiscrible,
     ntpSysWorkStatus,
     ntpSysPulseStatus
    }
    STATUS    current
    DESCRIPTION   "units of conformance"
    ::= { gttMIBGroups 2 }

gpsGroup OBJECT-GROUP
    OBJECTS 
    {
  gpsGroupValid,
  gpsNumTrackSats,
  gpsLongitude,
  gpsLatitude,
  gpsHeight
    }
    STATUS    current
    DESCRIPTION
            "units of conformance"
    ::= { gttMIBGroups 3 }

还有就是globaltime_mib.txt里有的globaltime.h没有,这时就要相互添加了,怎么添加就是照葫芦画瓢,

class Trapcpualarm : public NotificationOriginator {

public:
 Trapcpualarm ();
 virtual ~Trapcpualarm ();

 virtual void         generate(Vbx*, int, const OctetStr&);
};

这就是照上一个类写出来的。

public NotificationOriginator 这是所有trap类都必须包含的子类,因为你的trap是于他来发送的

class globaltime: public MibGroup 这是mibgrop的一个分支,与他来产生树的。

class power1status: public MibLeaf  返回值是整型的

class gpsLongitude: public SnmpDisplayString  返回值是字符串的

对齐就讲到这吧。

现在现在讲讲电源的问题。我们用GPD14,GPD15来接受2路电源,在snmp中我们要知道2路电源的情况,谁有电谁没电,当有一路断电时会自动发trap,恩,电源基本上就是这些问题。

为了获取GPD14,GPD15的值,我们必须写驱动,因为这读取的是硬件寄存器的值,应用层不能直接访问。

驱动程序如下:

#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
#define DEVICE_NAME       "power"           //定义设备名
#define POWER_MAJOR  232                //手动定义主设备号
//定义要操作的设备,把每一个led作为结构体的一个成员
static unsigned long power_table[] = {         
       S3C2410_GPD14,
       S3C2410_GPD15,
     
     
     
};
//对设备进行设置,结构体的每一个成员是对对应led的设置
static unsigned int power_cfg_table [] = {
       S3C2410_GPD14_INP,
       S3C2410_GPD15_INP,
     
     
};
static int s3c2410_power_open(struct inode *inode,struct file *file)
{
       printk("open/n");
 return 0;  
}
//设备驱动程序中对设备的I/O通道进行管理的函数,用来实现对led的操作

static int s3c2410_power_read(struct file *file, unsigned int  *   buffer,   size_t   count,   loff_t   *ppos)
{
 
 unsigned  int k1, k2 ;
 k1=0;
 k2=0;
  if(s3c2410_gpio_getpin(S3C2410_GPD14))
   {
   k1=1;
   //printk("%d../n",s3c2410_gpio_getpin(S3C2410_GPD14));
  
  }
  if(s3c2410_gpio_getpin(S3C2410_GPD15))
   {
    k2=1;
   //printk("%d../n",s3c2410_gpio_getpin(S3C2410_GPD15));
  }
  //printk("%d..%d/n",k1,k2);
 
  buffer++;
  copy_to_user(buffer,   &k1,   sizeof(k1));
  buffer++;
  copy_to_user(buffer,   &k2,   sizeof(k2));

}

 

static struct file_operations s3c2410_power_fops = {
       .owner    =     THIS_MODULE,
 .open = s3c2410_power_open,
       .read       =     s3c2410_power_read,
};
//模块加载函数
static int __init s3c2410_power_init(void)
{
       int ret;
       int i;
    //注册设备号
       ret = register_chrdev(POWER_MAJOR, DEVICE_NAME, &s3c2410_power_fops);
       if (ret < 0) {
       printk(DEVICE_NAME " can't register major number/n");
       return ret;
       }
       devfs_mk_cdev(MKDEV(POWER_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, DEVICE_NAME);
     
       for (i = 0; i < 2; i++) {
              s3c2410_gpio_setpin(power_table[i], 0);
  s3c2410_gpio_cfgpin(power_table[i], power_cfg_table[i]);
       }
       printk(DEVICE_NAME " initialized/n");
       return 0;
}
//模块卸载函数
static void __exit s3c2410_power_exit(void)
{
       devfs_remove(DEVICE_NAME);
       unregister_chrdev(POWER_MAJOR, DEVICE_NAME);
}
module_init(s3c2410_power_init);
module_exit(s3c2410_power_exit);
MODULE_LICENSE("GPL");

pw= open("/dev/power",O_RDONLY);
    if (pw < 0)
    {
        perror("xxx device power");
        exit(1);
    }
   else
    {
      read(pw,buffer,2);
      printf("%d,%d/n",buffer[1],buffer[2]);
    }

就可以读到GPD14,GPD15的值了。

在globaltime_mib.txt中加入

    SysMsgpower1status,
    SysMsgpower2status,

并按提示写出具体定义,再在globaltime.h中添加

#define oidpower1status                  "1.3.6.1.4.1.2354.1.6.1.0"
#define oidpower2status                  "1.3.6.1.4.1.2354.1.6.2.0"

class power1status: public MibLeaf {

public:
 power1status();
 virtual ~power1status();

 static power1status* instance;

 virtual void        get_request(Request*, int);
 virtual long        get_state();
 virtual void        set_state(long);

//--AgentGen BEGIN=gpsNumTrackSats
//--AgentGen END
};

class power2status: public MibLeaf {

public:
 power2status();
 virtual ~power2status();

 static power2status* instance;

 virtual void        get_request(Request*, int);
 virtual long        get_state();
 virtual void        set_state(long);

//--AgentGen BEGIN=gpsNumTrackSats
//--AgentGen END
};
在globaltime.cpp中具体给出定义

power1status* power1status::instance = 0;

power1status::power1status():
   MibLeaf(oidSysMsgpower1status, READONLY, new SnmpInt32())
{
 
 instance = this;

}

power1status::~power1status()
{

 //--AgentGen BEGIN=gpsNumTrackSats::~gpsNumTrackSats
 //--AgentGen END
}

void power1status::get_request(Request* req, int ind)
{
g_lpSnmpData->readpowerstatus();
 *((SnmpInt32*)value) =g_lpSnmpData->power1;
 //--AgentGen BEGIN=gpsNumTrackSats::get_request
 //--AgentGen END
 MibLeaf::get_request(req, ind);
}

long power1status::get_state()
{
 return (long)*((SnmpInt32*)value);
}

void power1status::set_state(long l)
{
 *((SnmpInt32*)value) = l;
}

至于get_request怎么工作的暂时不用去管。

这些我们所需要的数据都是在readdata.h和readdata.cpp中我们自己写程序算出来的

trapMsgPower1Err的加入方法如下:

开始和get_reque的一样,后面的加入方法请看下一章

上一次讲到trapMsgPower1Err的加入方法,首先是在globaltime.h和globaltime.cpp里加入树的分支及trapMsgPower1Err这个类的声明和定义,其主要的实现部分在readdata.cpp里的SendAllTrapType这个类中if(oidTrapMsgPowerErr == id)
           {
            printf("oidTrapMsgPowerErr");
            trapMsgPowerErr pTrap;
           
            if(power1==0||power2==0)
             vbs.set_value(SnmpInt32(0));
            if(power1==1&&power2==1)
              vbs.set_value(SnmpInt32(1));
            power1jiu=power1;
            power2jiu=power2;
           
         
          pTrap.generate(&vbs, 1, "");//send trap

具体的power1,power2的值在void CAllSnmpData::readpowerstatus()
 {
  int pw, i;
unsigned int buffer[4];
buffer[0]=0;
buffer[1]=1;
buffer[2]=1;
buffer[3]=0;
       pw= open("/dev/power",O_RDONLY);
    if (pw < 0)
    {
        perror("xxx device power");
        exit(1);
    }
   else
    {
    read(pw,buffer,2);
    close(pw);
     power1=buffer[1];
     power2=buffer[2];
   }
 }

算出来的值还要进行分析,以确定是否要发生trap

//phase power data
void CAllSnmpData:: phasepowerdata()
 {
  readpowerstatus();
  if(power1!=power1jiu||power2!=power2jiu)
   SendAllTrapType(oidTrapMsgPowerErr);
  }

我们的原则是只要有一路电源有故障就发生trap,如果那路电源又好了的话在发送一个trap来提示电源正常

上次讲完了电源的部分,现在讲讲关于系统状态的部分:

我们关于系统状态只有2个一个是cpu利用率另一个是memory利用率。

先说cpu利用率吧:

   在/proc里关于cpu的信息好像只有cpuinfo,但是这里面只有cpu的一些出场信息,没什么有用的东西,在网上查了下,以下是一些关于cpu的资料:

在Linux的内核中,有一个全局变量:Jiffies。 Jiffies代表时间。它的单位随硬件平台的不同而不同。系统里定义了一个常数HZ,代表每秒种最小时间间隔的数目。这样jiffies的单位就是1/HZ。Intel平台jiffies的单位是1/100秒,这就是系统所能分辨的最小时间间隔了。每个CPU时间片,Jiffies都要加1。 CPU的利用率就是用执行用户态+系统态的Jiffies除以总的Jifffies来表示。

在Linux系统中,可以用/proc/stat文件来计算cpu的利用率(详细的解释可参考:http://www.linuxhowtos.org/System/procstat.htm)。这个文件包含了所有CPU活动的信息,该文件中的所有值都是从系统启动开始累计到当前时刻。

如:

QUOTE:
[sailorhzr@builder ~]$ cat /proc/stat
cpu 432661 13295 86656 422145968 171474 233 5346
cpu0 123075 2462 23494 105543694 16586 0 4615
cpu1 111917 4124 23858 105503820 69697 123 371
cpu2 103164 3554 21530 105521167 64032 106 334
cpu3 94504 3153 17772 105577285 21158 4 24
intr 1065711094 1057275779 92 0 6 6 0 4 0 3527 0 0 0 70 0 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7376958 0 0 0 0 0 0 0 1054602 0 0 0 0 0 0 0 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 19067887
btime 1139187531
processes 270014
procs_running 1
procs_blocked 0


输出解释
CPU 以及CPU0、CPU1、CPU2、CPU3每行的每个参数意思(以第一行为例)为:

参数 解释
user (432661) 从系统启动开始累计到当前时刻,用户态的CPU时间(单位:jiffies) ,不包含 nice值为负进程。1jiffies=0.01秒
nice (13295) 从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间(单位:jiffies)
system (86656) 从系统启动开始累计到当前时刻,核心时间(单位:jiffies)
idle (422145968) 从系统启动开始累计到当前时刻,除硬盘IO等待时间以外其它等待时间(单位:jiffies)
iowait (171474) 从系统启动开始累计到当前时刻,硬盘IO等待时间(单位:jiffies) ,
irq (233) 从系统启动开始累计到当前时刻,硬中断时间(单位:jiffies)
softirq (5346) 从系统启动开始累计到当前时刻,软中断时间(单位:jiffies)

CPU时间=user+system+nice+idle+iowait+irq+softirq

“intr”这行给出中断的信息,第一个为自系统启动以来,发生的所有的中断的次数;然后每个数对应一个特定的中断自系统启动以来所发生的次数。
“ctxt”给出了自系统启动以来CPU发生的上下文交换的次数。
“btime”给出了从系统启动到现在为止的时间,单位为秒。
“processes (total_forks) 自系统启动以来所创建的任务的个数目。
“procs_running”:当前运行队列的任务的数目。
“procs_blocked”:当前被阻塞的任务的数目。

那么CPU利用率可以使用以下两个方法。先取两个采样点,然后计算其差值:

QUOTE:
cpu usage=(idle2-idle1)/(cpu2-cpu1)*100
cpu usage=[(user_2 +sys_2+nice_2) - (user_1 + sys_1+nice_1)]/(total_2 - total_1)*100

我们采用第一种计算方法,自己写的shell,把cpu空闲的资源放在/var/cpu1.info下,总资源放在/var/cpu2.info下。5秒为间隔不断循环。

#!/bin/sh
while [ 1 ]
do
CPULOG_1=$(cat /proc/stat | grep 'cpu ' | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
SYS_IDLE_1=$(echo $CPULOG_1 | awk '{print $4}')
Total_1=$(echo $CPULOG_1 | awk '{print $1+$2+$3+$4+$5+$6+$7}')

sleep 5

CPULOG_2=$(cat /proc/stat | grep 'cpu ' | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
SYS_IDLE_2=$(echo $CPULOG_2 | awk '{print $4}')
Total_2=$(echo $CPULOG_2 | awk '{print $1+$2+$3+$4+$5+$6+$7}')

SYS_IDLE=`expr $SYS_IDLE_2 - $SYS_IDLE_1`

Total=`expr $Total_2 - $Total_1`
echo $SYS_IDLE >/var/cpu1.info
echo $Total >/var/cpu2.info

done

既然cpu利用率都可以计算出来了那我们就在snmp中添加这一项功能了。

 首先给他定义一个树在globaltime_mib.txt里,添加代码如下:

sysMsgGroup OBJECT-GROUP
    OBJECTS 
    {
     sysMsgReBoot,
     sysMsgLocalTime,
     sysMsgLocalDate,
     sysMsgTimeSource,
     SysMsgSetTrapAddress,
     SysMsgpower1status,
    SysMsgpower2status,
    SysMsgcpu,
    SysMsgmemory
    }
    STATUS    current
    DESCRIPTION
            "units of conformance"
    ::= { gttMIBGroups 1 }

其中SysMsgcpu,就是我们添加的然后具体说明他

SysMsgcpu OBJECT-TYPE
 SYNTAX INTEGER(0..100)
 MAX-ACCESS read-only
 STATUS current
 DESCRIPTION
 "The value of this variable indicates the Status of current cpu usage factor"
 ::= { sysMsg 8 }

在globaltime.h和globaltime.cpp里添加相应的代码

class cpu: public  MibLeaf {

public:
 cpu();
 virtual ~cpu();

 static cpu* instance;

 virtual void        get_request(Request*, int);
};

cpu* cpu::instance = 0;

cpu::cpu():
    MibLeaf(oidSysMsgcpustatus, READONLY, new SnmpInt32())
{
 // This leaf object is a singleton. In order to access it use
 // the static pointer gpsLatitude::instance.
 instance = this;

 //--AgentGen BEGIN=gpsLatitude::gpsLatitude
 //--AgentGen END

}

cpu::~cpu()
{

 //--AgentGen BEGIN=gpsLatitude::~gpsLatitude
 //--AgentGen END
}

void cpu::get_request(Request* req, int ind)
{
 
 g_lpSnmpData->readcpustatus();
 
*((SnmpInt32*)value) = g_lpSnmpData->cpustatus;

 MibLeaf::get_request(req, ind);
}

memory* memory::instance = 0;

memory::memory():
   MibLeaf(oidSysMsgmemorystatus, READONLY, new SnmpInt32())
{
 // This leaf object is a singleton. In order to access it use
 // the static pointer gpsLatitude::instance.
 instance = this;

 //--AgentGen BEGIN=gpsLatitude::gpsLatitude
 //--AgentGen END

}

g_lpSnmpData->cpustatus是在readdata.cpp理算出来的。

在readdata.cpp里

void CAllSnmpData:: readcpustatus()
 {
  int m, n ,d;
 float a, b , c ;
 
 //system("/mnt/bin/cpu.sh");
 FILE *fd3;
   char sz[5];
   fd3 = fopen("/var/cpu1.info","r");    //以流方式打开
    if(NULL == fd3)
       exit(1);
     
       else
        {
       if(fgets(sz, 4, fd3) != NULL)
      m = atoi(sz);
      fclose(fd3);
    }
    //printf("%d",m);
  
    FILE *fd2;
   char ss[5];
   fd2 = fopen("/var/cpu2.info","r");    //以流方式打开
    if(NULL == fd2)
       exit(1);
     
       else
        {
       if(fgets(ss, 4, fd2) != NULL)
      n= atoi(ss);
      fclose(fd2);
    }
      b=m;
      c=n;
      a=b/c;
      a=(1-a);
     
    cpustatus=(int)(a*100);
    }

到此cpu利用率就算是添加上去了。

cpu利用率讲完了,现在讲讲memory利用率。

 在/proc/meminfo里有关于memory的信息

[root@GlobalTime /proc]$cat meminfo
MemTotal:        61888 kB
MemFree:         49600 kB
Buffers:          2140 kB
Cached:           6428 kB
SwapCached:          0 kB
Active:           4504 kB
Inactive:         5028 kB
HighTotal:           0 kB
HighFree:            0 kB
LowTotal:        61888 kB
LowFree:         49600 kB
SwapTotal:           0 kB
SwapFree:            0 kB
Dirty:               0 kB
Writeback:           0 kB
Mapped:           2516 kB
Slab:             1880 kB
CommitLimit:     30944 kB
Committed_AS:     8404 kB
PageTables:        148 kB
VmallocTotal:   450560 kB
VmallocUsed:      3240 kB
VmallocChunk:   445944 kB
前2项是memory的总量和空闲量,有了他就不难算出memory利用率了。

于cpu利用率一样,首先给他定义一个树在globaltime_mib.txt里,添加代码如下:

sysMsgGroup OBJECT-GROUP
    OBJECTS 
    {
     sysMsgReBoot,
     sysMsgLocalTime,
     sysMsgLocalDate,
     sysMsgTimeSource,
     SysMsgSetTrapAddress,
     SysMsgpower1status,
    SysMsgpower2status,
    SysMsgcpu,
    SysMsgmemory
    }
    STATUS    current
    DESCRIPTION
            'units of conformance'
    ::= { gttMIBGroups 1 }

其中SysMsgmemory,就是我们添加的然后具体说明他

SysMsgmemory OBJECT-TYPE
 SYNTAX  INTEGER(0..100)
 MAX-ACCESS read-only
 STATUS current
 DESCRIPTION
 "The value of this variable indicates the Status of current memory usage factor"
 ::= { sysMsg 9 }

在globaltime.h和globaltime.cpp里添加相应的代码

#define oidmemory                        "1.3.6.1.4.1.2354.1.6.4.0"

class memory: public MibLeaf {

public:
 memory();
 virtual ~memory();

 static memory* instance;

 virtual void        get_request(Request*, int);
};

memory::~memory()
{

 //--AgentGen BEGIN=gpsLatitude::~gpsLatitude
 //--AgentGen END
}

void memory::get_request(Request* req, int ind)
{
 
            g_lpSnmpData->readmemstatus();
 
  *((SnmpInt32*)value) = g_lpSnmpData->memstatus;
 // *((SnmpInt32*)value) =3;

 MibLeaf::get_request(req, ind);
}

这时要注意了,之前我也犯这样的错误,就是globaltime::globaltime(): MibGroup("1.3.6.1.4.1.2354", "gttMIB")
{
 add(new sysMsgReBoot());
 add(new sysMsgLocalTime());
 add(new sysMsgLocalDate());
 add(new sysMsgSetTimeSource());
 add(new sysMsgSetTrapAddress());
 
 add(new ntpSysHostMode());
 add(new ntpSysStratum());
 add(new ntpSysPoll());
 add(new ntpSysPrecision());
 add(new ntpSysRootDelay());
 add(new ntpSysRootDisp());
 add(new ntpSysRefClockIdent());
 add(new ntpSysRunTime());
 add(new ntpSysDevDiscrible());
 add(new ntpSysWorkStatus());
 add(new ntpSysPulseStatus());
 
 add(new gpsGroupValid());
 add(new gpsNumTrackSats());
 add(new gpsLongitude());
 add(new gpsLatitude());
 add(new gpsHeight());
 add(new linjietest());
 add(new power1status());
 add(new power2status());
 add(new cpu());
 add(new memory());
}

里没有添加add(new power1status());
 add(new power2status());
 add(new cpu());
 add(new memory());
,不添加这个mib里就没有他的信息,就会导致我们不能get

在readdata.cpp里算出g_lpSnmpData->memstatus

void CAllSnmpData:: readmemstatus()
 {
  FILE *fd3;
    FILE *fd2;
    int i=0, m, n;
    float mm;
   char sz[256],sa[256], ss[5], aa[5];
   char *str1 , *ptr, *ptr1, *p, *p1, *p3;
   fd3 = fopen("/proc/meminfo","r");    //以流方式打开
    if(NULL == fd3)
       exit(1);
     
       else
        {
       if(fread(sz, 255,1, fd3) != NULL)
     fclose(fd3);
     }
    str1=sz;
     ptr=strstr(str1,"MemTotal:");
    
   while(*ptr!='1'&&*ptr!='2'&&*ptr!='3'&&*ptr!='4'&&*ptr!='5'&&*ptr!='6'&&*ptr!='7'&&*ptr!='8'&&*ptr!='9')
     {
     ptr++;
     }
   
     ptr1=ptr;
     while(*ptr1!='k')
     {
     ptr1++;
     }
        p1=ptr1;
     ptr1--;
      ptr1--;
    for(i;ptr1>=ptr;ptr1--,i++)
     ss[4-i]=*ptr1;
     m = atoi(ss);
    // printf("%d/n",m);
   
   
   
   str1=sz;
     ptr=strstr(str1,"MemFree: ");
    
   while(*ptr!='1'&&*ptr!='2'&&*ptr!='3'&&*ptr!='4'&&*ptr!='5'&&*ptr!='6'&&*ptr!='7'&&*ptr!='8'&&*ptr!='9')
     {
     ptr++;
     }
   
     ptr1=ptr;
     while(*ptr1!='k')
     {
     ptr1++;
     }
        p1=ptr1;
     ptr1--;
      ptr1--;
      i=0;
    for(i;ptr1>=ptr;ptr1--,i++)
     aa[4-i]=*ptr1;
     n = atoi(aa);
     //printf("%d/n",n);
 
   mm=1-(float)n/(float)m;
  // printf("%f",mm);
 // memstatus=mm;
 memstatus=(int)(mm*100);
 
 }

接下来是我花了最长时间才完成的发生trap时绑定162端口,就是说版子发送trap时用的是162端口。

先从源头找起,在readdata.cpp里都有pTrap.generate(&vbs, 1, "");//send trap这句话说明发trap的起点是generate这个函数,终点肯定是sendto,因为是以udp方式传送的。

pTrap.generate(&vbs, 1, "")首先看这个函数的定义

int NotificationOriginator::generate(Vbx* vbs, int size, const Oidx& id,
         unsigned int timestamp,
         const Oidx& enterprise,
         const OctetStr& contextName)
{
 // We have to be careful here about synchronisation because,
 // we may be called after an interrupt
 // Therefore synch everything or use synch methods like
 // MibTable::get_rows_cloned();
 List<MibTableRow>* typeList =
   snmpNotifyEntry::instance->get_rows_cloned();
 ListCursor<MibTableRow> typeCur;
 
 List<MibTableRow>* list =
   snmpTargetAddrEntry::instance->get_rows_cloned();
 ListCursor<MibTableRow> cur;


#ifdef _SNMPv3
 if (!localEngineID) {
  if (!v3MP::I) {
   LOG_BEGIN(ERROR_LOG | 0);
   LOG("NotificationOriginator: v3MP has to be initialized before notifications can be sent");
   LOG_END;     
  }
  localEngineID = new OctetStr(v3MP::I->get_local_engine_id());
 }
#endif

 int totalStatus = SNMP_ERROR_SUCCESS;

 NotificationOriginatorParams nop(vbs, size, id, timestamp, enterprise, contextName);

 for (cur.init(list); cur.get(); cur.next()) {

   int notify = NO_TRAP;
 
   // look for tags that identify notifications
   for (typeCur.init(typeList); typeCur.get(); typeCur.next()) {

  OctetStr tag;
  typeCur.get()->first()->get_value(tag);
  char* tagstr = new char[tag.len()+1];
  strncpy(tagstr, (char*)tag.data(), tag.len());
  tagstr[tag.len()] = 0;
 
  if (((SnmpTagList*)cur.get()->get_nth(4))->
      contains(tagstr)) {
   // determine notification type
   typeCur.get()->get_nth(1)->get_value(notify);

   nop.target = 0;
   if (check_access(cur, nop)) {
    int status = send_notify(cur, nop, notify);
    if (status != SNMP_ERROR_SUCCESS)
     totalStatus = status;
    delete nop.target;
   }
  }
  delete[] tagstr;
   }
   if (notify == NO_TRAP) {
  LOG_BEGIN(DEBUG_LOG | 6);
  LOG("NotificationOriginator: generate: could not find valid tag");
  LOG_END;
  continue;
   }
 }

 typeList->clearAll();
 delete typeList;
 list->clearAll();
 delete list;

 return totalStatus;
}

在函数里她又调用send_notify(cur, nop, notify)我们接着找,在看send_notify这个函数的定义:

int NotificationOriginator::send_notify(ListCursor<MibTableRow>& cur,
  NotificationOriginatorParams& nop, int notify)
{
 Vbx*& vbs = nop.vbs;
 int& size = nop.size;
 const Oidx& id = nop.id;
 const Oidx& enterprise = nop.enterprise;
 OctetStr& securityName = nop.securityName;
 int& mpModel = nop.mpModel;
#ifdef _SNMPv3
 int& securityLevel = nop.securityLevel;
 const OctetStr& contextName = nop.contextName;
 unsigned int& timestamp = nop.timestamp;
 UTarget*& target = nop.target;
#else
 CTarget*& target = nop.target;
#endif

   long targetDomain =
     ((snmpTargetAddrTDomain*)cur.get()->first())->get_state();

   Oidx trapoid(id);
#ifdef _SNMPv3
   Pdux pdu;
   pdu.set_type((notify == TRAP) ? sNMP_PDU_TRAP : sNMP_PDU_INFORM);
   pdu.set_vblist(vbs, size);
   pdu.set_notify_id(id);
   pdu.set_notify_enterprise(enterprise);
   pdu.set_notify_timestamp(timestamp);
   pdu.set_security_level(securityLevel);
   pdu.set_context_name(contextName);

   // get community info from SNMP-COMMUNITY-MIB
   if (((mpModel == mpV1) || (mpModel == mpV2c)) &&
       (snmpCommunityEntry::instance)) {
  if (snmpCommunityEntry::instance->get_community(securityName,
        *localEngineID,
        contextName)) {
   target->set_security_name(securityName);
  }
  else {
   LOG_BEGIN(WARNING_LOG | 2);
   LOG("NotificationOriginator: community lookup failed for (securityName) (context)");
   LOG(securityName.get_printable());
   LOG(OctetStr(contextName).get_printable());
   LOG_END;
  }
   }
#endif
   int status = SNMP_ERROR_SUCCESS;

   if (mpModel == mpV1) {

#ifdef _SNMPv3
     pdu.set_type(sNMP_PDU_V1TRAP);
#endif
     target->set_version(version1);

#ifdef _SNMPv3
     status = SnmpRequestV3::send(*target, pdu);
     if (nlmLogEntry::instance) {
  nlmLogEntry::instance->
    add_notification(*target, pdu, *localEngineID);
     }
#else
     status = SnmpRequest::process_trap(*target, vbs, size,
         id, enterprise,
         (notify != TRAP));
#endif

     GenAddress address;
     target->get_address(address);

     LOG_BEGIN(EVENT_LOG | 1);
     LOG("NotificationGenerator: sent v1 trap (id)(tdomain)(addr)(vbs)(community)");
     LOG(trapoid.get_printable());
     LOG(targetDomain);
     LOG(address.get_printable());
     LOG(size);
     LOG(securityName.get_printable());
     LOG_END;
   }
   else {
#ifdef _SNMPv3
     if (mpModel == mpV3)
  target->set_version(version3);
     else
#endif
  target->set_version(version2c); 

     if (notify != TRAP) {
  target->set_retry(((SnmpInt32MinMax*)
       cur.get()->get_nth(3))->get_state());
  target->set_timeout(((SnmpInt32MinMax*)
         cur.get()->get_nth(2))->get_state());
     }

#ifdef _SNMPv3
     status = SnmpRequestV3::send(*target, pdu);
     if (nlmLogEntry::instance) {
  nlmLogEntry::instance->
    add_notification(*target, pdu, *localEngineID);
     }
#else
     status = SnmpRequest::process_trap(*target, vbs, size, id, enterprise,
          (notify != TRAP));
#endif

     GenAddress address;
     target->get_address(address);

     LOG_BEGIN(EVENT_LOG | 1);
     if (notify == TRAP)
  LOG("NotificationGenerator: sent trap (vers)(id)(tdomain)(addr)(vbs)(community/secName)(status)");
     else
  LOG("NotificationGenerator: sent inform (vers)(id)(tdomain)(addr)(vbs)(community/secName)(status)");
     LOG(mpModel);
     LOG(trapoid.get_printable());
     LOG(targetDomain);
     LOG(address.get_printable());
     LOG(size);
     LOG(securityName.get_printable());
     LOG(status);
     LOG_END;
   }   
   return status;
}

他又调用process_trap,我们进一步跟进

现在找process_trap函数的定义:

int SnmpRequest::process_trap(SnmpTarget& target,
         Vbx* vbs, int sz,
         const Oidx& oid,
         const Oidx& enterprise, boolean ack)
{
 int status;

 Snmpx* snmp = get_new_snmp(status);
 // check construction status
 
 if (status != SNMP_CLASS_SUCCESS) {
  if (snmp) delete snmp;
  return status;
 }
 Pdux pdu;
 // the request id is set by Snmpx

 for (int i=0; i<sz; i++)
  pdu += vbs[i];

 pdu.set_notify_timestamp(sysUpTime::get());
 pdu.set_notify_id(oid);
 pdu.set_notify_enterprise(enterprise);

 if (ack)
  status = snmp->inform(pdu, target);
 else
  status = snmp->trap(pdu, target);

 if (status == SNMP_CLASS_SUCCESS) {
  MibIIsnmpCounters::incOutPkts();
  MibIIsnmpCounters::incOutTraps();
 }
 delete snmp;

 return status;
}

下面这2个函数还是让我头疼了一会。。。。
if (ack)
  status = snmp->inform(pdu, target);
 else
  status = snmp->trap(pdu, target);

现在先找snmpx这个类吧


class AGENTPP_DECL Snmpx: public NS_SNMP Snmp {
public:
 
 Snmpx (int &status , u_short port): Snmp(status, port) {};

#ifdef SNMP_PP_WITH_UDPADDR
 
 Snmpx(int& status, const NS_SNMP UdpAddress& addr): Snmp(status, addr) { }
#endif

#ifdef _SNMPv3 
 
 int receive(struct tim*, Pdux&, NS_SNMP UTarget&);
#else
 
 int receive(struct tim*, Pdux&, NS_SNMP UdpAddress&,
      NS_SNMP snmp_version&, NS_SNMP OctetStr&);
#endif
#ifdef _SNMPv3
 
        int send (Pdux, NS_SNMP SnmpTarget*);
#else
 
        int send (Pdux, NS_SNMP UdpAddress, NS_SNMP snmp_version, NS_SNMP OctetStr);
#endif
 
 u_short get_port();

 
#ifdef WIN32
 unsigned long get_session_fds() { return iv_snmp_session; }
#else
        SNMPHANDLE get_session_fds() { return iv_snmp_session; }
#endif


protected:
 unsigned long ProcessizedReqId(unsigned short);
 unsigned long MyMakeReqId();
 
 int snmp_engine( NS_SNMP Pdu &,   // pdu to use
    long int,     // # of non repititions
    long int,     // # of max repititions
    NS_SNMP SnmpTarget&,    // from this target
    const NS_SNMP snmp_callback cb,
    const void * cbd);
};  

在snmpx里他包含了snmp这个类原因是AGENT++ uses Snmpx instead of Snmp, because Snmp does not allow to listen on an UDP port for incoming SNMP requests.

其实status = snmp->inform(pdu, target)就是调用snmp类的trap这个函数

//---------------------[ send a trap ]-----------------------------------
int Snmp::trap(Pdu &pdu,                        // pdu to send
               const SnmpTarget &target)        // destination target
{
  OctetStr my_get_community;
  OctetStr my_set_community;
  GenAddress address;
  unsigned long my_timeout;
  int my_retry;
  unsigned char version;
  int status;

  debugprintf(1, "++ SNMP++, Send a Trap");
  //---------[ make sure pdu is valid ]---------------------------------
  if ( !pdu.valid())
    {
      debugprintf(0, "-- SNMP++, PDU Object Invalid");
      return  SNMP_CLASS_INVALID_PDU;
    }

  //---------[ make sure target is valid ]------------------------------
  if ( !target.valid())
    {
      debugprintf(0, "-- SNMP++, Target Object Invalid");
      return SNMP_CLASS_INVALID_TARGET;
    }

  CTarget* ctarget = NULL;
  UTarget* utarget = NULL;
  OctetStr security_name;
  int security_model;

  switch (target.get_type()) {
    case SnmpTarget::type_ctarget:
      ctarget = (CTarget*)(&target);
      break;
    case SnmpTarget::type_utarget:
      utarget = (UTarget*)(&target);
      break;
    case SnmpTarget::type_base:
      debugprintf(0, "-- SNMP++, do not use SnmpTarget, use a  CTarget or UTarget");
      return SNMP_CLASS_INVALID_TARGET;
    default:
      // target is not known
      debugprintf(0, "-- SNMP++, type of target is unknown!");
      return SNMP_CLASS_UNSUPPORTED;
  }

  if (ctarget) {
    debugprintf(3, "snmp::trap called with CTarget");
    if (!ctarget->resolve_to_C( my_get_community, my_set_community, address,
                                my_timeout, my_retry, version))
    {
      debugprintf(0, "-- SNMP++, Resolve Fail (CTarget)");
      return SNMP_CLASS_UNSUPPORTED;
    }
#ifdef _SNMPv3
    if (version == version3)
    {
      debugprintf(0, "-- SNMP++, use UTarget for SNMPv3");
      return SNMP_CLASS_INVALID_TARGET;
    }
#endif
  }
  else { // target is not a CTarget:
    if (utarget) {
      debugprintf(3, "trap called with UTarget");
      if (!utarget->resolve_to_U( security_name, security_model, address,
      my_timeout, my_retry, version))
      {
        debugprintf(0, "-- SNMP++, Resolve Fail (UTarget)");
        return SNMP_CLASS_UNSUPPORTED;
      }
#ifdef _SNMPv3
      if (version != version3) {
#endif
        my_get_community = security_name;
        if ((security_model != SecurityModel_v1) &&
            (security_model != SecurityModel_v2)) {
          debugprintf(0, "-- SNMP++, Target contains invalid security_model/version combination");
          return SNMP_CLASS_INVALID_TARGET;
        }
#ifdef _SNMPv3
      } // end if (version != version3)
#endif
    }
    else { // target is neither CTarget nor UTarget:
      debugprintf(0, "-- SNMP++, Resolve Fail");
      return SNMP_CLASS_INVALID_TARGET;
    }
  }

  //--------[ determine request id to use ]------------------------------
  pdu.set_request_id( MyMakeReqId());

  //--------[ check timestamp, if null use system time ]-----------------
  check_notify_timestamp(pdu);

  //------[ validate address to use ]-------------------------------------
  if (!address.valid()) {
    debugprintf(0, "-- SNMP++, Bad address");
    return SNMP_CLASS_INVALID_TARGET;
  }

  if ((address.get_type() != Address::type_ip) &&
      (address.get_type() != Address::type_udp) )
    {
      debugprintf(0, "-- SNMP++, Bad address type");
      return SNMP_CLASS_TL_UNSUPPORTED;
    }

  UdpAddress udp_address(address);
  if (!udp_address.valid()) {
    debugprintf(0, "-- SNMP++, copy address failed");
    return SNMP_CLASS_RESOURCE_UNAVAIL;
  }

  //----------[ choose the target address port ]-----------------------
  if ((address.get_type() == Address::type_ip) || !udp_address.get_port())
    udp_address.set_port(SNMP_TRAP_PORT);

  //----------[ based on the target type, choose v1 or v1 trap type ]-----
  if ( version == version1)
    pdu.set_type( sNMP_PDU_V1TRAP);
  else // v2 and v3 use v2TRAP
    pdu.set_type( sNMP_PDU_TRAP);

  SnmpMessage snmpmsg;

#ifdef _SNMPv3
  if ( version == version3) {

    OctetStr engine_id = v3MP::I->get_local_engine_id();
    if (!utarget) {
      debugprintf(0, "-- SNMP++, dont know how to handle SNMPv3 without UTarget!");
      return SNMP_CLASS_INVALID_TARGET;
    }

    // set context_engine_id of pdu, if it is not set
    if (pdu.get_context_engine_id().len() == 0)
    {
      debugprintf(8, "Setting contextEngineID of Pdu to (%s)",
                  engine_id.get_printable());
      pdu.set_context_engine_id(engine_id);
    }

    debugprintf(4,"Snmp::trap:");
    debugprintf(4," engineID (%s), securityName (%s)/n securityModel (%i) security_level (%i)",
                engine_id.get_printable(), security_name.get_printable(),
                security_model, pdu.get_security_level());
    debugprintf(4," Addr/Port (%s)",udp_address.get_printable());

    status = snmpmsg.loadv3( pdu, engine_id, security_name,
                             security_model, (snmp_version)version);
  }
  else
#endif
    status = snmpmsg.load( pdu, my_get_community, (snmp_version) version);

  if ( status != SNMP_CLASS_SUCCESS) {
    debugprintf(0, "snmp message load error!");
    return status;
  }

  lock();
  //------[ send the trap ]
  if (udp_address.get_ip_version() == Address::version_ipv4)
  {
    if (iv_snmp_session != INVALID_SOCKET)
      status = send_snmp_request((int) iv_snmp_session,
     snmpmsg.data(), (size_t)snmpmsg.len(),
     udp_address);
    else
    {
      udp_address.map_to_ipv6();
      status = send_snmp_request((int) iv_snmp_session_ipv6,
     snmpmsg.data(), (size_t)snmpmsg.len(),
     udp_address);
    }
  }
  else
    status = send_snmp_request((int) iv_snmp_session_ipv6,
                               snmpmsg.data(), (size_t)snmpmsg.len(),
                               udp_address);

  unlock();
  if (status != 0)
    return SNMP_CLASS_TL_FAILED;

  return SNMP_CLASS_SUCCESS;
}

//----------------[ set notify_timestamp if it is null ]-------------
#if defined (CPU) && CPU == PPC603

  struct SCommTimer
  {
 unsigned long NumMS;
 unsigned long FractMS;
  };

  extern "C"
  {
  void GetTime (struct SCommTimer *  Time);
  }
#endif

他调用 send_snmp_request((int) iv_snmp_session,
     snmpmsg.data(), (size_t)snmpmsg.len(),
     udp_address);
去发送trap,接着找

//---------[ Send SNMP Request ]---------------------------------------
// Send out a snmp request
DLLOPT int send_snmp_request(int sock, unsigned char *send_buf,
                             size_t send_len, Address & address)
{
  // UX only supports UDP type addresses (addr and port) right now
  if (address.get_type() != Address::type_udp)
    return -1;// unsupported address type

  debugprintf(1, "++ SNMP++: sending to %s:",
              ((UdpAddress &)address).UdpAddress::get_printable());
  debughexprintf(5, send_buf, send_len);

  int send_result;

  if (((UdpAddress &)address).get_ip_version() == Address::version_ipv4)
  {
    // prepare the destination address
    struct sockaddr_in agent_addr;  // send socket struct
    memset(&agent_addr, 0, sizeof(agent_addr));
    agent_addr.sin_family = AF_INET;
    agent_addr.sin_addr.s_addr
              = inet_addr(((IpAddress &)address).IpAddress::get_printable());
    agent_addr.sin_port = htons(((UdpAddress &)address).get_port());

    send_result = sendto( sock, (char*) send_buf, send_len, 0,
                          (struct sockaddr*) &agent_addr, sizeof(agent_addr));
  }
  else
  {
#ifdef SNMP_PP_IPv6
    struct sockaddr_in6 agent_addr;
    memset(&agent_addr, 0, sizeof(agent_addr));
    inet_pton(AF_INET6, ((IpAddress &)address).IpAddress::get_printable(),
              &agent_addr.sin6_addr);
    agent_addr.sin6_family = AF_INET6;
    agent_addr.sin6_port = htons(((UdpAddress &)address).get_port());

    send_result = sendto( sock, (char*) send_buf, send_len, 0,
                          (struct sockaddr*) &agent_addr, sizeof(agent_addr));
#else
    debugprintf(0, "User error: Enable IPv6 and recompile snmp++.");
    return -1;
#endif
  }

  if (send_result < 0)
  {
    debugprintf(0, "Error sending packet: %s", strerror(errno));
    return -1; // send error!
  }

  return 0;
}

好,在这里就看到了sendto,这已经到了最低成了。

可我在sendto之前用bind()想绑定162端口,不行,因为无论是trap还是get通信最终都是sendto出去的所以在这绑定肯定不行。

在trap函数里找到这句 status = send_snmp_request((int) iv_snmp_session,
     snmpmsg.data(), (size_t)snmpmsg.len(),
     udp_address);

iv_snmp_session他就是我们发送trap的套接口描述符,我们要想办法把他和162端口绑在一起,在这句话之前进行绑定,发现也不行,只好继续找原因,我们找到了init函数,他初始化套接口,初始化套接口这个地方我们应该很敏感,因为你bind()函数要么在socket()之后,要么在sendto之前,结果我们在这发现了bind()函数,狂喜呀。不过也是做了一会在搞出来,不是简单的改为162就可以了,他的第一次通信还是通过161端口来完成的,以后在发送trap时在随机指定端口。

原来程序:if (( iv_snmp_session = socket( AF_INET, SOCK_DGRAM,0)) == INVALID_SOCKET)
    {
#ifdef WIN32
      int werr = WSAGetLastError();
      debugprintf(1, "Call to socket throws error %d", werr);
      if (EMFILE == werr ||WSAENOBUFS == werr || ENFILE == werr)
        status = SNMP_CLASS_RESOURCE_UNAVAIL;
      else if (WSAEHOSTDOWN == werr)
        status = SNMP_CLASS_TL_FAILED;
      else
        status = SNMP_CLASS_TL_UNSUPPORTED;
#else
      if (EMFILE == errno || ENOBUFS == errno || ENFILE == errno)
        status = SNMP_CLASS_RESOURCE_UNAVAIL;
      else if (EHOSTDOWN == errno)
        status = SNMP_CLASS_TL_FAILED;
      else
        status = SNMP_CLASS_TL_UNSUPPORTED;
#endif
    }
    else
    {
      // set up the manager socket attributes
      unsigned long inaddr = inet_addr(addresses[0]->get_printable());
      struct sockaddr_in mgr_addr;
      memset(&mgr_addr, 0, sizeof(mgr_addr));
      mgr_addr.sin_family = AF_INET;
      mgr_addr.sin_addr.s_addr = inaddr;
      mgr_addr.sin_port = htons( port_v4);
#ifdef CYGPKG_NET_OPENBSD_STACK
      mgr_addr.sin_len = sizeof(mgr_addr);
#endif

      // bind the socket
      if (bind((int)iv_snmp_session, (struct sockaddr*)&mgr_addr,
               sizeof(mgr_addr)) < 0)
      改为: if (( iv_snmp_session = socket( AF_INET, SOCK_DGRAM,0)) == INVALID_SOCKET)
    {
#ifdef WIN32
      int werr = WSAGetLastError();
      debugprintf(1, "Call to socket throws error %d", werr);
      if (EMFILE == werr ||WSAENOBUFS == werr || ENFILE == werr)
        status = SNMP_CLASS_RESOURCE_UNAVAIL;
      else if (WSAEHOSTDOWN == werr)
        status = SNMP_CLASS_TL_FAILED;
      else
        status = SNMP_CLASS_TL_UNSUPPORTED;
#else
      if (EMFILE == errno || ENOBUFS == errno || ENFILE == errno)
        status = SNMP_CLASS_RESOURCE_UNAVAIL;
      else if (EHOSTDOWN == errno)
        status = SNMP_CLASS_TL_FAILED;
      else
        status = SNMP_CLASS_TL_UNSUPPORTED;
#endif
    }
    else
    {
      // set up the manager socket attributes
      unsigned long inaddr = inet_addr(addresses[0]->get_printable());
      struct sockaddr_in mgr_addr;
      memset(&mgr_addr, 0, sizeof(mgr_addr));
      //port_v4=162;
      if(port_v4==161)
      mgr_addr.sin_port = htons(port_v4);
      if(port_v4!=161)
        mgr_addr.sin_port = htons(162);
      mgr_addr.sin_family = AF_INET;
      mgr_addr.sin_addr.s_addr = inaddr;
   
   
      printf("port=%d,ip=%s",port_v4,addresses[0]->get_printable());
     // port_v4=162;
#ifdef CYGPKG_NET_OPENBSD_STACK
      mgr_addr.sin_len = sizeof(mgr_addr);
#endif

      // bind the socket
      if (bind((int)iv_snmp_session, (struct sockaddr*)&mgr_addr,
               sizeof(mgr_addr)) < 0)
      {

在版子上跑下子,ok成功

呵呵,加上了162端口后又发现了新问题,就是你是哪个ip发过来的trap,用工具查看全是255.255.255.255,这样不行。我们得知道具体的ip。那就找吧,从最后一个地方找起。

//---------[ Send SNMP Request ]---------------------------------------
// Send out a snmp request
DLLOPT int send_snmp_request(int sock, unsigned char *send_buf,
                             size_t send_len, Address & address)
{
 
  printf("send the trap");
 
  // UX only supports UDP type addresses (addr and port) right now
  if (address.get_type() != Address::type_udp)
    return -1;// unsupported address type

  debugprintf(1, "++ SNMP++: sending to %s:",
              ((UdpAddress &)address).UdpAddress::get_printable());
  debughexprintf(5, send_buf, send_len);

  int send_result;

  if (((UdpAddress &)address).get_ip_version() == Address::version_ipv4)
  {
    // prepare the destination address
    struct sockaddr_in agent_addr;  // send socket struct
    memset(&agent_addr, 0, sizeof(agent_addr));
    agent_addr.sin_family = AF_INET;
    agent_addr.sin_addr.s_addr
              = inet_addr(((IpAddress &)address).IpAddress::get_printable());
    agent_addr.sin_port = htons(((UdpAddress &)address).get_port());
 
 printf("por1t=%d,ip1=%s",((UdpAddress &)address).get_port(),((IpAddress &)address).IpAddress::get_printable());

    send_result = sendto( sock, (char*) send_buf, send_len, 0,
                          (struct sockaddr*) &agent_addr, sizeof(agent_addr));
  }
 

send_buf这是发送出去的trap的内容这里面可能有本地的ip,接着找到。send_snmp_request这个函数是trap调用的进入trap函数

//---------------------[ send a trap ]-----------------------------------
int Snmp::trap(Pdu &pdu,                        // pdu to send
               const SnmpTarget &target)        // destination target
{
 printf("trap");
  OctetStr my_get_community;
  OctetStr my_set_community;
  GenAddress address;
  unsigned long my_timeout;
  int my_retry;
  unsigned char version;
  int status;

  debugprintf(1, "++ SNMP++, Send a Trap");
  //---------[ make sure pdu is valid ]---------------------------------
  if ( !pdu.valid())
    {
      debugprintf(0, "-- SNMP++, PDU Object Invalid");
      return  SNMP_CLASS_INVALID_PDU;
    }

  //---------[ make sure target is valid ]------------------------------
  if ( !target.valid())
    {
      debugprintf(0, "-- SNMP++, Target Object Invalid");
      return SNMP_CLASS_INVALID_TARGET;
    }

  CTarget* ctarget = NULL;
  UTarget* utarget = NULL;
  OctetStr security_name;
  int security_model;

  switch (target.get_type()) {
    case SnmpTarget::type_ctarget:
      ctarget = (CTarget*)(&target);
      break;
    case SnmpTarget::type_utarget:
      utarget = (UTarget*)(&target);
      break;
    case SnmpTarget::type_base:
      debugprintf(0, "-- SNMP++, do not use SnmpTarget, use a  CTarget or UTarget");
      return SNMP_CLASS_INVALID_TARGET;
    default:
      // target is not known
      debugprintf(0, "-- SNMP++, type of target is unknown!");
      return SNMP_CLASS_UNSUPPORTED;
  }

  if (ctarget) {
    debugprintf(3, "snmp::trap called with CTarget");
    if (!ctarget->resolve_to_C( my_get_community, my_set_community, address,
                                my_timeout, my_retry, version))
    {
      debugprintf(0, "-- SNMP++, Resolve Fail (CTarget)");
      return SNMP_CLASS_UNSUPPORTED;
    }
#ifdef _SNMPv3
    if (version == version3)
    {
      debugprintf(0, "-- SNMP++, use UTarget for SNMPv3");
      return SNMP_CLASS_INVALID_TARGET;
    }
#endif
  }
  else { // target is not a CTarget:
    if (utarget) {
      debugprintf(3, "trap called with UTarget");
      if (!utarget->resolve_to_U( security_name, security_model, address,
      my_timeout, my_retry, version))
      {
        debugprintf(0, "-- SNMP++, Resolve Fail (UTarget)");
        return SNMP_CLASS_UNSUPPORTED;
      }
#ifdef _SNMPv3
      if (version != version3) {
#endif
        my_get_community = security_name;
        if ((security_model != SecurityModel_v1) &&
            (security_model != SecurityModel_v2)) {
          debugprintf(0, "-- SNMP++, Target contains invalid security_model/version combination");
          return SNMP_CLASS_INVALID_TARGET;
        }
#ifdef _SNMPv3
      } // end if (version != version3)
#endif
    }
    else { // target is neither CTarget nor UTarget:
      debugprintf(0, "-- SNMP++, Resolve Fail");
      return SNMP_CLASS_INVALID_TARGET;
    }
  }

  //--------[ determine request id to use ]------------------------------
  pdu.set_request_id( MyMakeReqId());

  //--------[ check timestamp, if null use system time ]-----------------
  check_notify_timestamp(pdu);

  //------[ validate address to use ]-------------------------------------
  if (!address.valid()) {
    debugprintf(0, "-- SNMP++, Bad address");
    return SNMP_CLASS_INVALID_TARGET;
  }

  if ((address.get_type() != Address::type_ip) &&
      (address.get_type() != Address::type_udp) )
    {
      debugprintf(0, "-- SNMP++, Bad address type");
      return SNMP_CLASS_TL_UNSUPPORTED;
    }

  UdpAddress udp_address(address);
  if (!udp_address.valid()) {
    debugprintf(0, "-- SNMP++, copy address failed");
    return SNMP_CLASS_RESOURCE_UNAVAIL;
  }

  //----------[ choose the target address port ]-----------------------
  if ((address.get_type() == Address::type_ip) || !udp_address.get_port())
    udp_address.set_port(SNMP_TRAP_PORT);

  //----------[ based on the target type, choose v1 or v1 trap type ]-----
  if ( version == version1)
    pdu.set_type( sNMP_PDU_V1TRAP);
  else // v2 and v3 use v2TRAP
    pdu.set_type( sNMP_PDU_TRAP);

  SnmpMessage snmpmsg;

#ifdef _SNMPv3
  if ( version == version3) {

    OctetStr engine_id = v3MP::I->get_local_engine_id();
    if (!utarget) {
      debugprintf(0, "-- SNMP++, dont know how to handle SNMPv3 without UTarget!");
      return SNMP_CLASS_INVALID_TARGET;
    }

    // set context_engine_id of pdu, if it is not set
    if (pdu.get_context_engine_id().len() == 0)
    {
      debugprintf(8, "Setting contextEngineID of Pdu to (%s)",
                  engine_id.get_printable());
      pdu.set_context_engine_id(engine_id);
    }

    debugprintf(4,"Snmp::trap:");
    debugprintf(4," engineID (%s), securityName (%s)/n securityModel (%i) security_level (%i)",
                engine_id.get_printable(), security_name.get_printable(),
                security_model, pdu.get_security_level());
    debugprintf(4," Addr/Port (%s)",udp_address.get_printable());

    status = snmpmsg.loadv3( pdu, engine_id, security_name,
                             security_model, (snmp_version)version);
  }
  else
#endif
    status = snmpmsg.load( pdu, my_get_community, (snmp_version) version);

  if ( status != SNMP_CLASS_SUCCESS) {
    debugprintf(0, "snmp message load error!");
    return status;
  }

  lock();
  printf("4444");
 
  //------[ send the trap ]
  if (udp_address.get_ip_version() == Address::version_ipv4)
  {
   printf("55555");
  
  if (iv_snmp_session != INVALID_SOCKET)
     {
     
 
    
       printf("send the 111trap");
      status = send_snmp_request((int) iv_snmp_session,
     snmpmsg.data(), (size_t)snmpmsg.len(),
     udp_address);
    }
   
    else
    {
      udp_address.map_to_ipv6();
      status = send_snmp_request((int) iv_snmp_session_ipv6,
     snmpmsg.data(), (size_t)snmpmsg.len(),
     udp_address);
    }
  }
  else
    status = send_snmp_request((int) iv_snmp_session_ipv6,
                               snmpmsg.data(), (size_t)snmpmsg.len(),
                               udp_address);

  unlock();
  if (status != 0)
    return SNMP_CLASS_TL_FAILED;

  return SNMP_CLASS_SUCCESS;
}

这个函数还是要仔细看看的,先找到 status = send_snmp_request((int) iv_snmp_session,
     snmpmsg.data(), (size_t)snmpmsg.len(),
     udp_address);,是在这调用的。。。好,看里面的snmpmsg.data()这个就是send_buf的传递。好,现在接着找snmpmsg.data()。这个就在snmpmsg这个文件里了。

在snmpmsg.h里unsigned char *data()     { return databuff; };

我们接着找databuff。找事找到了,但程序看起来很难理解,我换个方式进行。因为我看到了pdu,我想pdu里面应该含有本地ip。。于是我们找到了
#endif

int SnmpMessage::load(const Pdu &cpdu,
                      const OctetStr &community,
                      const snmp_version version,
                      const OctetStr* engine_id,
                      const OctetStr* security_name,
                      const int security_model)
{
  int status;
  const Pdu *pdu = &cpdu;
  Pdu temppdu;

  // make sure pdu is valid
  if ( !pdu->valid())
    return SNMP_CLASS_INVALID_PDU;

  // create a raw pdu
  snmp_pdu *raw_pdu;
  raw_pdu = snmp_pdu_create( (int) pdu->get_type());

  Oid enterprise;

  // load it up
  raw_pdu->reqid = pdu->get_request_id();
#ifdef _SNMPv3
  raw_pdu->msgid = pdu->get_message_id();
#endif
  raw_pdu->errstat= (unsigned long) pdu->get_error_status();
  raw_pdu->errindex= (unsigned long) pdu->get_error_index();

  // if its a V1 trap then load up other values
  // for v2, use normal pdu format
  if ( raw_pdu->command == sNMP_PDU_V1TRAP) {
    // DON'T forget about the v1 trap agent address (changed by Frank Fock)
    GenAddress gen_addr;
    IpAddress ip_addr;
    int addr_set = FALSE;

    if (pdu->get_v1_trap_address(gen_addr))
    {
    
      if ((gen_addr.get_type() != Address::type_ip) &&
          (gen_addr.get_type() != Address::type_udp) )
      {
        debugprintf(0, "Bad v1 trap address type in pdu");
        snmp_free_pdu( raw_pdu);
        return SNMP_CLASS_INVALID_PDU;
      }

      ip_addr = gen_addr;
      if (!ip_addr.valid()) {
        debugprintf(0, "Copy of v1 trap address failed");
        snmp_free_pdu( raw_pdu);
        return SNMP_CLASS_RESOURCE_UNAVAIL;
      }
      addr_set = TRUE;
    }
    else
    {
    
      char addrString[256];
      if (gethostname(addrString, 255) == 0)
      {
          ip_addr = addrString;
          addr_set = TRUE;
      }
    }
    struct sockaddr_in agent_addr;  // agent address socket struct
    // prepare the agent address
    memset(&agent_addr, 0, sizeof(agent_addr));
    agent_addr.sin_family = AF_INET;
    if (addr_set)
    {
      agent_addr.sin_addr.s_addr
        = inet_addr(((IpAddress &)ip_addr).IpAddress::get_printable());
      debugprintf(3, "setting v1 trap address to (%s).",
                  ((IpAddress &)ip_addr).IpAddress::get_printable());
    }
    raw_pdu->agent_addr = agent_addr;

    //-----[ compute generic trap value ]-------------------------------
    // determine the generic value
    // 0 - cold start
    // 1 - warm start
    // 2 - link down
    // 3 - link up
    // 4 - authentication failure
    // 5 - egpneighborloss
    // 6 - enterprise specific
    Oid trapid;
    pdu->get_notify_id( trapid);
    if ( !trapid.valid() || trapid.len() < 2 )
      {
        snmp_free_pdu( raw_pdu);
        return SNMP_CLASS_INVALID_NOTIFYID;
      }
    raw_pdu->specific_type=0;
    if ( trapid == coldStart)
      raw_pdu->trap_type = 0;  // cold start
    else if ( trapid == warmStart)
      raw_pdu->trap_type = 1;  // warm start
    else if( trapid == linkDown)
      raw_pdu->trap_type = 2;  // link down
    else if ( trapid == linkUp)
      raw_pdu->trap_type = 3;  // link up
    else if ( trapid == authenticationFailure )
      raw_pdu->trap_type = 4;  // authentication failure
    else if ( trapid == egpNeighborLoss)
      raw_pdu->trap_type = 5;  // egp neighbor loss
    else {
      raw_pdu->trap_type = 6;     // enterprise specific
      // last oid subid is the specific value
      // if 2nd to last subid is "0", remove it
      // enterprise is always the notify oid prefix
      raw_pdu->specific_type = (int) trapid[(int) (trapid.len()-1)];

      trapid.trim(1);
      if ( trapid[(int)(trapid.len()-1)] == 0 )
        trapid.trim(1);
      enterprise = trapid;
    }

    if ( raw_pdu->trap_type !=6)
      pdu->get_notify_enterprise( enterprise);
    if ( enterprise.len() >0) {
      // note!!
      // these are hooks into an SNMP++ oid
      // and therefor the raw_pdu enterprise
      // should not free them. null them out!!
      SmiLPOID rawOid;
      rawOid = enterprise.oidval();
      raw_pdu->enterprise = rawOid->ptr;
      raw_pdu->enterprise_length = (int) rawOid->len;
    }

    // timestamp
    TimeTicks timestamp;
    pdu->get_notify_timestamp( timestamp);
    raw_pdu->time = ( unsigned long) timestamp;

  }

  // if its a v2 trap then we need to make a few adjustments
  // vb #1 is the timestamp
  // vb #2 is the id, represented as an Oid
  if (( raw_pdu->command == sNMP_PDU_TRAP) ||
      ( raw_pdu->command == sNMP_PDU_INFORM))
  {
    Vb tempvb;

    temppdu = *pdu;
    temppdu.trim(temppdu.get_vb_count());

    // vb #1 is the timestamp
    TimeTicks timestamp;
    tempvb.set_oid(SNMP_MSG_OID_SYSUPTIME);   // sysuptime
    pdu->get_notify_timestamp( timestamp);
    tempvb.set_value ( timestamp);
    temppdu += tempvb;

    // vb #2 is the id
    Oid trapid;
    tempvb.set_oid(SNMP_MSG_OID_TRAPID);
    pdu->get_notify_id( trapid);
    tempvb.set_value( trapid);
    temppdu += tempvb;

    // append the remaining vbs
    for (int z=0; z<pdu->get_vb_count(); z++) {
      pdu->get_vb( tempvb,z);
      temppdu += tempvb;
    }

    pdu = &temppdu;          // reassign the pdu to the temp one
  }
  // load up the payload
  // for all Vbs in list, add them to the pdu
  int vb_count;
  Vb tempvb;
  Oid tempoid;
  SmiLPOID smioid;
  SmiVALUE smival;

  vb_count = pdu->get_vb_count();
  for (int z=0;z<vb_count;z++) {
    pdu->get_vb( tempvb,z);
    tempvb.get_oid( tempoid);
    smioid = tempoid.oidval();
    // clear the value portion, in case its
    // not already been done so by the app writer
    // only do it in the case its a get,next or bulk
    if ((raw_pdu->command == sNMP_PDU_GET) ||
        (raw_pdu->command == sNMP_PDU_GETNEXT) ||
        (raw_pdu->command == sNMP_PDU_GETBULK))
      tempvb.set_null();
    status = convertVbToSmival( tempvb, &smival );
    if ( status != SNMP_CLASS_SUCCESS) {
      snmp_free_pdu( raw_pdu);
      return status;
    }
    // add the vb to the raw pdu
    snmp_add_var( raw_pdu, smioid->ptr, (int) smioid->len, &smival);

    freeSmivalDescriptor( &smival);
  }

  // ASN1 encode the pdu
#ifdef _SNMPv3
  if (version == version3)
  {
    if ((!engine_id) || (!security_name))
    {
      debugprintf(1, "SnmpMessage::load, security_name and engine_id needed for SNMPv3 message.");
      snmp_free_pdu( raw_pdu);
      return SNMP_CLASS_INVALID_TARGET;
    }

    status = v3MP::I->snmp_build(raw_pdu, databuff, (int *)&bufflen,
     *engine_id, *security_name, security_model,
     pdu->get_security_level(),
     pdu->get_context_engine_id(),
     pdu->get_context_name());
    if (status == SNMPv3_MP_OK) {
      if ((pdu->get_type() == sNMP_PDU_RESPONSE) &&
          ((int)pdu->get_maxsize_scopedpdu() < pdu->get_asn1_length())) {
 debugprintf(0, "ERROR: TOO BIG should not happen.");
        // prevention of SNMP++ Enterprise Oid death
        if ( enterprise.len() >0) {
          raw_pdu->enterprise = 0;
          raw_pdu->enterprise_length=0;
        }
        snmp_free_pdu( raw_pdu);
        return SNMP_ERROR_TOO_BIG;
      }
    }
  }
  else
#endif
    status = snmp_build( raw_pdu, databuff, (int *) &bufflen, version,
                         community.data(), (int) community.len());
  debugprintf(3, "SnmpMsg: return status of snmpBuild (%i)",status);

  if ((status != 0)
#ifdef _SNMPv3
      && ((version != version3) || (status != SNMPv3_MP_OK))
#endif
      ) {
    valid_flag = false;
    // prevention of SNMP++ Enterprise Oid death
    if ( enterprise.len() >0) {
      raw_pdu->enterprise = 0;
      raw_pdu->enterprise_length=0;
    }
    snmp_free_pdu( raw_pdu);
#ifdef _SNMPv3
    if (version == version3)
      return status;
    else
#endif
      // NOTE: This is an assumption - in most cases during normal
      // operation the reason is a tooBig - another could be a
      // damaged variable binding.
      return SNMP_ERROR_TOO_BIG;
  }
  valid_flag = true;

  // prevention of SNMP++ Enterprise Oid death
  if ( enterprise.len() >0) {
    raw_pdu->enterprise = 0;
    raw_pdu->enterprise_length=0;
  }

  snmp_free_pdu( raw_pdu);

  return SNMP_CLASS_SUCCESS;
}

在load(const Pdu &cpdu,
                      const OctetStr &community,
                      const snmp_version version,
                      const OctetStr* engine_id,
                      const OctetStr* security_name,
                      const int security_model)里

他主要是加载pdu。在看看pdu的定义:

Trap PDU 格式如下所示:

PDU Type         Enterp         Agent Addr         Gen Trap         Spec Trap         Time Stamp         Obj 1,Val 1         Obj 1,Val 1         …

    * PDU Type:指定传输的 PDU 类型(Trap=4)。
    * Enterprise:识别管理企业,在其注册权下定义 Trap。
    * Agent Address:代理器的 IP 地址,用于进一步的识别。
    * Generic Trap Type:描述事件报告字段,以下定义了7个值。
    * Specific Trap Type:当通用 Trap 成为企业指定类型时,用于识别非通用 Trap。
    * Timestamp:SysUpTime 对象值,表示最后一次设置初值和产生对应 Trap 间的时间数量。

由此不难找到

struct sockaddr_in agent_addr;  // agent address socket struct
    // prepare the agent address
    memset(&agent_addr, 0, sizeof(agent_addr));
    agent_addr.sin_family = AF_INET;
    if (addr_set)
    {
      agent_addr.sin_addr.s_addr
        = inet_addr(((IpAddress &)ip_addr).IpAddress::get_printable());

的确就是在这里。把inet_addr后面换成自己本地的ip就好了

加的部分如下:

FILE *fd3;
    int i=0, m;
   char sz[256], ss[15];
   char *str1 , *ptr;
   fd3 = fopen("/mnt/etc/sysconfig/network-scripts/ifcfg-eth0","r");    //以流方式打开
    if(NULL == fd3)
       //exit(1);
       return 0;
       else
        {
       if(fread(sz, 255,1, fd3) != NULL)
     fclose(fd3);
     }
    str1=sz;
     ptr=strstr(str1,"IPADDR=");
     for(m=0;m<7;m++)
     ptr++;
  for(;*ptr!='N';i++,ptr++)
  ss[i]=*ptr;

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wangyi84971224/archive/2009/11/04/4767101.aspx

原创粉丝点击