You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C语言中实现snmpwalk功能?解决仅获取部分OID行值问题

解决SNMP GETNEXT/GETBULK仅获取单条记录的问题

你的核心问题在于两点:一是只处理了响应中的第一个变量绑定,忽略了GETBULK返回的多条结果;二是没有循环发起请求,直到获取的OID超出目标表的范围。以下是修正后的代码,实现类似snmpwalk的遍历功能:

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/library/mib.h>

int main() {
    // 目标表的前缀OID(替换为你要遍历的表根节点,而非具体条目OID)
    oid target_oid[] = {1, 3, 6, 1, 4, 1, 89, 79, 17, 1, 1, 2};  
    size_t target_oid_len = OID_LENGTH(target_oid);
    oid current_oid[MAX_OID_LEN];
    size_t current_oid_len = target_oid_len;
    memcpy(current_oid, target_oid, target_oid_len * sizeof(oid));

    init_snmp("snmpwalk");

    // SNMP会话初始化
    netsnmp_session session, *ss;
    snmp_sess_init(&session);
    session.peername = strdup("172.16.100.46");  
    session.version = SNMP_VERSION_2c;
    session.community = "public";
    session.community_len = strlen(session.community);

    SOCK_STARTUP;
    ss = snmp_open(&session);
    if (!ss) {
        snmp_perror("snmp_open");
        SOCK_CLEANUP;
        exit(1);
    }

    netsnmp_pdu *response;
    int status;

    do {
        // 创建GETBULK请求(SNMPv2c及以上推荐使用,效率高于GETNEXT)
        netsnmp_pdu *pdu = snmp_pdu_create(SNMP_MSG_GETBULK);
        pdu->non_repeaters = 0;
        pdu->max_repetitions = 15; // 单次请求最多返回15条记录
        snmp_add_null_var(pdu, current_oid, current_oid_len);

        status = snmp_synch_response(ss, pdu, &response);
        
        if (status == STAT_SUCCESS && response) {
            netsnmp_variable_list *vars = response->variables;
            int valid = 1;

            // 遍历响应中的所有变量绑定
            while (vars) {
                // 检查当前OID是否属于目标表前缀
                if (!snmp_oid_compare(vars->name, vars->name_length, target_oid, target_oid_len)) {
                    // 打印用户信息(假设为字符串类型,可根据实际OID类型调整)
                    if (vars->type == ASN_OCTET_STR) {
                        printf("OID: ");
                        print_objid(vars->name, vars->name_length);
                        printf(" -> %s\n", vars->val.string);
                    }
                    // 更新当前OID为最后一条有效记录的OID,用于下一次请求
                    memcpy(current_oid, vars->name, vars->name_length * sizeof(oid));
                    current_oid_len = vars->name_length;
                } else {
                    valid = 0; // 超出目标表范围,终止循环
                    break;
                }
                vars = vars->next_variable;
            }

            if (!valid) {
                break;
            }
        } else if (status == STAT_TIMEOUT) {
            fprintf(stderr, "SNMP Timeout\n");
            break;
        } else {
            snmp_sess_perror("snmpwalk", ss);
            break;
        }

        // 清理响应PDU
        if (response) {
            snmp_free_pdu(response);
            response = NULL;
        }

    } while (1); // 循环直到超出目标表范围或请求出错

    // 资源清理
    snmp_close(ss);
    SOCK_CLEANUP;

    return 0;
}

关键修正说明:

  • 目标OID改为表前缀:原代码使用的是具体条目OID,需替换为表的根节点OID,才能遍历整个表的所有条目
  • 遍历变量链表:通过vars->next_variable遍历响应中的所有记录,而非仅处理第一条
  • 循环请求逻辑:每次请求后更新当前OID为最后一条有效记录的OID,持续发起请求直到返回的OID超出目标表范围
  • OID前缀校验:用snmp_oid_compare确保只处理目标表内的记录,避免获取无关OID

内容的提问来源于stack exchange,提问作者Rishi Kaimal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 13:42:03