HOME
BLOG
net-snmp学习
May 22 2023

http://www.net-snmp.org/wiki/index.php/TUT:Simple_Application snmp官方文档**

net-snmp学习笔记

程序开始需要声明几个变量:
snmp_session,里面存储的是调用者与谁交互的信息,对标nta->三方。需要两个,一个用来填充信息,一个是库返回的指针
snmp_pdu 保存我们将要发送到远程主机的所有信息。他将为对方要发回的信息声明一秒钟
这俩都是struct结构体
oid类型 存oid -》比如 oid anOID [10]
variable_list 存储的是想要通过snmp操作的变量,也是结构体

接下来使用init_snmp初始化snmp 库,可以在调用的时候指定文件名,就会自动读取配置文件,默认/etc下

初始化完成,用snmp_sess_init创建一个会话去和nms交互,可以用snmp_sess_init去设置一下会话的属性,就是前面snmp_session结构体

完事用snmp_open去打开会话,打开他之后会返回一个指针,这个指针就用开始定义的snmp_session指针去接收,指向我们应该使用的另一个会话

接下来,我们创建要发送到远程主机的 PDU ,当我们要求提供信息时。示例中这是snmpget程序使用的。它检索用于初始化它的每个 OID 的值。

因此,当我们用我们请求的 oid 填充它。让我们获取此示例的 system.sysDescr.0 变量。可以自己将数字无符号整数值放入我们上面创建的 anOID 数组中。或者用

get_node("sysDescr.0", anOID, &anOID_len); 拿到oid 
   read_objid("system.sysDescr.0", anOID, &anOID_len); 解析
   

下来,我们使用snmp_add_null_var将此具有 NULL 值的 oid 添加到 PDU

最后,利用snmp_synch_response,我们可以使用会话指针和 pdu 发送请求,并返回状态和响应,该状态和响应存储在新定位错误的响应 pdu 指针中

最后snmp_sess_close关闭会话

用snmp_shutdown清理snmp库

示例demo:

#include <stdio.h>
#include <stdlib.h>
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>

void print_variable(const oid *obj, const size_t obj_len, const netsnmp_variable_list *value)
{
    int i;
    char buf[1024];
    switch(value->type) {
        case ASN_INTEGER:
            printf("%s = %ld\n",snprint_objid(buf, sizeof(buf), obj, obj_len),*(value->val.integer));
            break;
        case ASN_OCTET_STR:
            printf("%s = %.*s\n",snprint_objid(buf, sizeof(buf), obj, obj_len),value->val_len,value->val.string);
            break;
        default:
            printf("%s = ",snprint_objid(buf, sizeof(buf), obj, obj_len));
            for(i=0;i<value->val_len;i++) printf("%02X ",value->val.string[i]);
            printf("\n");
            break;
    }
}

int main(int argc, char ** argv) {
    struct snmp_session session, *snmp_sess_pointer;
    struct snmp_pdu *pdu;
    struct snmp_pdu *response;
    oid anOID[MAX_OID_LEN];
    size_t anOID_len;
    netsnmp_variable_list *vars;

    // 初始化SNMP库
    init_snmp("snmp_app");

    // 初始化会话
    snmp_sess_init(&session);
    session.peername = argv[1]; // 指定SNMP代理程序的IP地址
    session.version = SNMP_VERSION_2c; // 指定SNMP版本
    session.community = "public"; // 指定社区字符串
    session.community_len = strlen(session.community); // 计算社区字符串长度

    // 开启SNMP会话
    snmp_sess_pointer = snmp_sess_open(&session);    
    if (!snmp_sess_pointer) {
        snmp_perror("snmp error");
        snmp_log(LOG_ERR, "something horrible happened!!!\n");
        exit(1);
    }

    // 准备发送PDU
    pdu = snmp_pdu_create(SNMP_MSG_GET); // 创建一个GET请求的PDU
    anOID_len = MAX_OID_LEN;
    if (read_objid("IF-MIB::ifInOctets.1", anOID, &anOID_len)) { // 解析OID字符串
        snmp_perror("read_objid error");
        exit(1);
    }
    snmp_add_null_var(pdu, anOID, anOID_len); // 向PDU添加待查询的OID

    // 发送SNMP请求并获取响应
    if (snmp_synch_response(snmp_sess_pointer, pdu, &response) == STAT_SUCCESS) {
        // 打印接收到的响应结果
        for (vars = response->variables; vars; vars = vars->next_variable) {
            print_variable(vars->name, vars->name_length, vars);
        }
    } else {
        snmp_perror("snmp error");
    }

    // 关闭SNMP会话
    snmp_sess_close(snmp_sess_pointer);

    // 清理SNMP库
    snmp_shutdown("snmp_app");

    return 0;
}
  1. 初始化SNMP库:调用init_snmp()函数初始化SNMP库(在程序中,传入"snmp_app"作为库名)。
  2. 初始化会话:调用snmp_sess_init()函数初始化SNMP会话。
  3. 开启SNMP会话:调用snmp_sess_open()函数建立到SNMP代理程序的连接,并返回一个指向SNMP会话的指针,若返回NULL则连接失败。
  4. 准备发送PDU:使用snmp_pdu_create()函数创建一个待发送的PDU(本示例中创建的是一个SNMP GET请求的PDU),然后使用read_objid()函数解析OID字符串,并调用snmp_add_null_var()函数向PDU添加待查询的OID。
  5. 发送SNMP请求并获取响应:使用snmp_synch_response()函数向SNMP代理程序发送请求,并获取响应。
  6. 打印接收到的响应结果:使用print_variable()函数打印接收到的SNMP变量值。
  7. 关闭SNMP会话:调用snmp_sess_close()函数关闭到SNMP代理程序的连接。
  8. 清理SNMP库:调用snmp_shutdown()函数清理SNMP库,释放相关资源。
工作