承接前三篇 (Get/Set 處理),本文聚焦 Net-SNMP Agent 擴展的最後一塊拼圖——主動發送 Trap/Inform 通知。示例代碼展示如何註冊週期性告警回調、構建 SNMPv1/v2c Trap PDU、動態綁定變量綁定、會話管理與資源釋放。
snmp_alarm_register() 註冊週期性定時器 (預設 5 秒/30 秒)。send_trap2() 中創建 SNMP_MSG_TRAP2 (v2c) 或 SNMP_MSG_TRAP (v1) PDU。create_trap_session() 建立目標管理站會話 (IP、Community、版本)。snmp_add_var() 動態加入 VarBind。send_trap_vars() 發送 → snmp_free_pdu()/snmpd_free_trapsinks() 清理。void init_alarm_info(void) {
DEBUGMSGTL(("dcsserver", "initializing (setting callback alarm)\n"));
snmp_alarm_register(
5, // 間隔秒數 (示例 5s,生產建議 30s+)
SA_REPEAT, // 週期性觸發
send_trap2, // 回調函數
NULL // 回調參數
);
}
SA_REPEAT 確保回調週期性執行;若需一次性告警可用 0 旗標。
void send_trap2(unsigned int clientreg, void *clientarg) {
// 企業私有 OID 基礎: 1.3.6.1.4.1.9000.2
static oid oid_cpu_Alarm[] = {1,3,6,1,4,1,9000,2,1};
static oid oid_memory_Alarm[] = {1,3,6,1,4,1,9000,2,2};
static oid oid_disk_Alarm[] = {1,3,6,1,4,1,9000,2,3};
netsnmp_pdu *pdu = snmp_pdu_create(SNMP_MSG_TRAP2); // v2c Trap
if (!pdu) { log_error("create trap PDU failed"); return; }
// 建立 Trap 發送會話
// SNMPv1: port=0 (內部自動用 162), community="public"
int status = create_trap_session(DEFAULT_ADDR, 0, "public", SNMP_VERSION_1, SNMP_MSG_TRAP);
if (status == 0) { log_error("create_trap_session failed"); snmp_free_pdu(pdu); return; }
// ...
}
關鍵點:
DEFAULT_ADDR 通常為 127.0.0.1 或配置文件讀取的 NMS IP。create_trap_session 第 2 參數必須為 0,否則會警告 (內部會強制用 162)。1.3.6.1.4.1.9000 需向 IANA 申請或使用實驗段 .1.3.6.1.4.1.99999。
bool flag = false;
// CPU > 85%
if (GetUsedCPU() > 85) {
flag = true;
snmp_add_var(pdu, oid_cpu_Alarm, OID_LENGTH(oid_cpu_Alarm), 's', "cpu Alarming");
}
// Memory > 85%
if (GetUsedMemory() > 85) {
flag = true;
snmp_add_var(pdu, oid_memory_Alarm, OID_LENGTH(oid_memory_Alarm), 's', "memory Alarming");
}
// Disk C: > 85%
if (GetUsedDisk() > 85) {
flag = true;
snmp_add_var(pdu, oid_disk_Alarm, OID_LENGTH(oid_disk_Alarm), 's', "disk Alarming");
}
// 有告警才發送
if (flag) {
send_trap_vars(1, 0, pdu->variables); // 發送 VarBind 鏈表
}
's' 表示 OCTET STRING 類型;實際部署建議用 'i' (INTEGER) 傳遞具體百分比,便於 NMS 做閾值圖表。
snmpd_free_trapsinks(); // 釋放會話緩存的 trap sinks
snmp_free_pdu(pdu); // 釋放 PDU 結構
notification.c 機制源碼 agent/notification.c 提供 send_v2trap() 高層封裝,但要求 snmpd 啟用 trapsink/trap2sink 配置並運行主 Agent 進程。本文示例採用獨立 create_trap_session 方式,適合 Subagent (AgentX) 或獨立可執行檔主動上報場景,不依賴主 Agent 狀態。
| 場景 | 推薦版本 | Port 參數 | PDU 類型 |
|---|---|---|---|
| 傳統網管設備相容 | SNMPv1 | 0 | SNMP_MSG_TRAP |
| 現代 NMS (Zabbix/PRRG/NetBrain) | SNMPv2c | 162 | SNMP_MSG_TRAP2 |
| 需確認送達 (ACK/重傳) | SNMPv2c Inform | 162 | SNMP_MSG_INFORM |
至此,Windows 下 Net-SNMP Agent 擴展核心技術棧已完整覆蓋。實際部署時請注意:
public。DEBUGMSGTL 方便現場排查。來源:vcsky.net havenzhao