一、net-snmp源码分析
Net-snmp代码的核心,就是初始化函数时,向代理(snmpd)注册了回调处理函数,当(snmpd)接收到一个snmp请求包时,它会先对包进行校验,如果校验不通过,会返回相应的错误。如果通过后,它会解析请求包,并把请求包的内容转换成请求结构(netsnmp_agent_request_info【包含请求包的pdu信息】,netsnmp_request_info【包含请求包的vb信息】)。匹配到相关的oid时,就调用相应的注册处理函数并传入请求结构给处理函数,处理函数只需要根据结构中的内容进行相应的业务处理就可以了。
下面用之前添加的testGet代码来做简要说明。
/** Initializes the testGet module */
void
init_testGet(void)
{
const oid GetTime_oid[] = { 1, 3, 6, 1, 4, 1, 77695, 1 };
DEBUGMSGTL(("testGet", "Initializing\n"));
netsnmp_register_scalar(netsnmp_create_handler_registration
("GetTime", handle_GetTime, GetTime_oid,
OID_LENGTH(GetTime_oid), HANDLER_CAN_RONLY));
}
int
handle_GetTime(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
time_t t;
switch (reqinfo->mode) {
case MODE_GET:
time(&t);
char szTime[100];
snprintf(szTime,100,"%s",ctime(&t));
snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
/*
* XXX: a pointer to the scalar's data
*/ szTime,
/*
* XXX: the length of the data in bytes
*/ strlen(szTime));
break;
default:
/*
* we should never get here, so this is a really bad error
*/
snmp_log(LOG_ERR, "unknown mode (%d) in handle_GetTime\n",
reqinfo->mode);
return SNMP_ERR_GENERR;
}
return SNMP_ERR_NOERROR;
}
初始函数调用netsnmp_create_handler_registration向snmpd注册GetTime_oid的处理函数为handle_GetTime,当snmpd调用handle_GetTime时,便会把相应的snmp包的信息从这几个参数中传进来。其中reqinfo 就是snmp请求包被snmpd解析后得到的结构,包含了请求包的会话和pdu信息;requests主要包含了 VB 信息。每次处理一个SNMP请求,就调用一次注册函数。
主要的几个结构体如下
netsnmp_agent_request_info
/** @struct netsnmp_agent_request_info_s
* The agent transaction request structure
*/
typedef struct netsnmp_agent_request_info_s {
int mode;
/** pdu contains authinfo, eg */
/* netsnmp_pdu *pdu; */
struct netsnmp_agent_session_s *asp; /* may not be needed */
/*
* can be used to pass information on a per-pdu basis from a
* helper to the later handlers
*/
netsnmp_data_list *agent_data;
} netsnmp_agent_request_info;
netsnmp_request_info
/** @typedef struct netsnmp_request_info_s netsnmp_request_info
* Typedefs the netsnmp_request_info_s struct into
* netsnmp_request_info*/
/** @struct netsnmp_request_info_s
* The netsnmp request info structure.
*/
typedef struct netsnmp_request_info_s {
/**
* variable bindings
*/
netsnmp_variable_list *requestvb;
/**
* can be used to pass information on a per-request basis from a
* helper to the later handlers
*/
netsnmp_data_list *parent_data;
/*
* pointer to the agent_request_info for this request
*/
struct netsnmp_agent_request_info_s *agent_req_info;
/** don't free, reference to (struct tree)->end */
oid *range_end;
size_t range_end_len;
/*
* flags
*/
int delegated;
int processed;
int inclusive;
int status;
/** index in original pdu */
int index;
/** get-bulk */
int repeat;
int orig_repeat;
netsnmp_variable_list *requestvb_start;
/* internal use */
struct netsnmp_request_info_s *next;
struct netsnmp_request_info_s *prev;
struct netsnmp_subtree_s *subtree;
} netsnmp_request_info;
二、net-snmp程序逻辑
snmpd代理完成两个功能:
1、接收网管发过来的snmp包,并对接收到的snmp包进行解析,校验后,找到并调用相应的处理函数进行处理。
2、调用注册了的告警函数,向网管发送告警信息。
Net-snmp代码流程图如下图所示
