如何在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
相关产品推荐
相关产品推荐

