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

如何使用NET-SNMP库实现C语言SNMP入站请求接收

基于NET-SNMP的SNMP服务器端入站请求接收问题排查与修复

问题背景

项目采用SNMP协议与NET-SNMP库开发,已完成SNMP客户端(管理器)的C语言实现并运行正常,但在开发服务器端(代理)时,现有代码无法正常接收并处理入站SNMP请求,需排查问题并实现功能。

现有代码的核心问题

  • 会话初始化错误:原代码使用客户端模式的snmp_sess_open并指定peername,这是客户端连接目标服务器的配置逻辑,服务器端需监听本地地址,应调整为无目标地址的会话配置。
  • 循环逻辑致命错误:初始化pdu = NULL后立即判断if(!pdu)并执行continue,导致永远不会触发snmp_sess_read接收请求,直接进入空转死循环。
  • PDU命令打印错误:pdu->command是枚举整数类型,用%s格式符打印会触发未定义行为,需改为整数打印或映射为对应字符串。
  • 响应发送方式错误:snmp_synch_response是客户端同步发送请求的接口,服务器端应使用snmp_send发送响应,且需将请求PDU的request_id复制到响应PDU中,否则客户端无法识别响应。

修正后的完整代码

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

int running = 1;

// 信号处理函数,支持Ctrl+C优雅退出
void sig_handler(int signo) {
    if (signo == SIGINT || signo == SIGTERM) {
        running = 0;
        printf("\nShutting down SNMP server...\n");
    }
}

int main(int argc, char **argv) {
    netsnmp_session session, *ss;
    netsnmp_pdu *pdu;
    netsnmp_pdu *response;
    oid anOID[MAX_OID_LEN];
    size_t anOID_len;
    int status;

    // 注册信号处理
    signal(SIGINT, sig_handler);
    signal(SIGTERM, sig_handler);

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

    // 配置服务器端会话参数
    snmp_sess_init(&session);
    // 服务器端监听所有本地地址,不指定目标地址
    session.peername = NULL;
    session.version = SNMP_VERSION_2c;
    // 设置服务端验证用的社区字符串
    session.community = (u_char *)"public";
    session.community_len = strlen((char *)session.community);
    // 指定监听默认SNMP端口161
    session.remote_port = SNMP_PORT;

    // 打开SNMP服务器端会话
    ss = snmp_open(&session);
    if (!ss) {
        snmp_perror("snmp_open");
        exit(1);
    }
    printf("SNMP server started, listening on port %d...\n", SNMP_PORT);

    // 循环接收并处理请求
    while (running) {
        pdu = NULL;
        // 阻塞等待接收SNMP请求
        status = snmp_read(ss, &pdu);
        
        if (status == STAT_SUCCESS && pdu != NULL) {
            // 映射请求类型为可读字符串
            const char *cmd_str = NULL;
            switch (pdu->command) {
                case SNMP_MSG_GET: cmd_str = "GET"; break;
                case SNMP_MSG_GETNEXT: cmd_str = "GETNEXT"; break;
                case SNMP_MSG_SET: cmd_str = "SET"; break;
                case SNMP_MSG_TRAP: cmd_str = "TRAP"; break;
                default: cmd_str = "UNKNOWN"; break;
            }
            printf("Received request: %s (code: %d)\n", cmd_str, pdu->command);

            // 处理GET/GETNEXT请求并返回响应
            if (pdu->command == SNMP_MSG_GET || pdu->command == SNMP_MSG_GETNEXT) {
                // 创建响应PDU
                response = snmp_pdu_create(SNMP_MSG_RESPONSE);
                // 复制请求的request_id,确保客户端能匹配响应
                response->request_id = pdu->request_id;
                response->errstat = SNMP_ERR_NOERROR;
                response->errindex = 0;

                // 添加响应变量(系统描述符OID)
                anOID_len = MAX_OID_LEN;
                if (snmp_parse_oid(".1.3.6.1.2.1.1.1.0", anOID, &anOID_len) != NULL) {
                    snmp_add_var(response, anOID, anOID_len, 's', "Custom SNMP Server - Hello World!");
                } else {
                    snmp_perror("Failed to parse OID .1.3.6.1.2.1.1.1.0");
                    response->errstat = SNMP_ERR_NOSUCHNAME;
                }

                // 发送响应,snmp_send会自动释放response
                status = snmp_send(ss, response);
                if (status != STAT_SUCCESS) {
                    snmp_perror("Failed to send response");
                }
            }

            // 释放请求PDU
            snmp_free_pdu(pdu);
        } else if (status != STAT_SUCCESS) {
            // 忽略非致命错误,继续运行
            snmp_perror("snmp_read failed");
        }
    }

    // 清理资源
    snmp_close(ss);
    snmp_shutdown("snmp_server");

    printf("SNMP server stopped.\n");
    return 0;
}

编译与运行说明

  1. 编译时链接NET-SNMP库:
    gcc -o snmp_server snmp_server.c -lnetsnmp
    
  2. 由于SNMP默认端口161是特权端口,需以root权限运行:
    sudo ./snmp_server
    
  3. 使用snmpget工具测试:
    snmpget -v 2c -c public localhost .1.3.6.1.2.1.1.1.0
    

内容的提问来源于stack exchange,提问作者sajad mosaybi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 09:24:55