SNMP简单网络管理协议总结,支持多种认证和加密方式

简单网络管理协议(SNMP)是设计用于IP网路管理网络节点的一种标准协议,它是应用层协议

SNMP协议目前在用的有3个版本,分别是V1,V2C,V3版本

认证方式有SHA,MD5

加密方式有DES,AES

需要支持版本、认证、加密不同的方式功能

自己也是各种找资料,但是很多资料都是复制粘贴,也不全;

所以就把自己的部分实现贴出来,仅供参考:

/*
*@author: 赵秋然
*@date:2021年8月7日
*@description:snmp.h
*/
#ifndef __SNMP_H__
#define __SNMP_H__
#include "public.h"
#include "cJSON.h"
#include<stdio.h>
#include<signal.h>
#include<string.h>
#include<net-snmp/net-snmp-config.h>
#include<net-snmp/net-snmp-includes.h>
#define SNMP_CONF "/backend-c/snmp/snmp_device.conf"

///snmp版本类型
typedef enum{
    SNMP_V1 = 1,
    SNMP_V2,
    SNMP_V3
} snmp_v;

//snmp认证方式
typedef enum{
    NOAUTH = 0,
    SHA,
    MD5
} auth_t;

//snmp加密连接方式
typedef enum{
    OPRIV = 0,
    DES,
    AES
} priv_t;

//snmp 机器类型
typedef enum{
    COMMON = 0,
    CISCO
} machine_t;


// snmp 通用机器内存 oid信息枚举
typedef enum{
    MEMTOTAL = 0,
    MEMAVAILABLE,
    MEM_SHARE,
    MEM_BUFFER,
    MEM_CACHE
}machine_common;

typedef enum{
    MEM_USE = 0,
    MEM_UNUSE
}machine_cscio;

#define RES_LEN 10
#define OID_LEN 30
#define LEN 256
#define SUCCE  0
#define ERROR -1

typedef struct snmp_basic_i{
    int snmp_on; // snmp主服务启用
    int snmp_cycle_time;//服务更新设备间隔(秒)
    int snmp_count;//snmp设备个数统计
}snmp_basic_info;

typedef struct snmp_machine{
    int snmp_device_on;//当前设备是否启用获取
    char m_ip[20]; // 机器ip
    int snmp_version;// snmp 版本号
    int snmp_auth;//snmp加密方式
    int snmp_ency;//snmp认证方式
    char community[LEN]; //snmp 团体字
    int time_cycle;// 获取周期时间 5秒 10秒等更新周期
    char security_name[LEN];//登录名称
    char security_pass[LEN];//密码
    char priiv_pass[LEN];//私钥
    struct timeval cur_time;///开始获取时间  戳   上一次更新的时间戳
    int machine_type;// 机器分类     common  思科  后续需要扩展
    char machine_name[LEN];// 机器名称
    char machine_id[LEN];// 机器id
    char cpu_oid[5][OID_LEN];// cpu oid
    char mem_oid[6][OID_LEN];// 内存  oid
    char cpu_use_percent[RES_LEN];//cpu 使用率
    char mem_use_percent[RES_LEN];//内存使用率
    netsnmp_session s_session;
}snmp_machine_info;

int is_valic_ip(char *ip);
int snmp_get_info(netsnmp_session * session,char *dest_ip ,char * oid_val, int * res);
int snmp_dialog_create(snmp_machine_info   * snmp_machine,snmp_basic_info snmp_info);
int snmp_basic_conf(snmp_basic_info * snmp_info,cJSON  * root);
int snmp_device_conf(snmp_machine_info * machine,cJSON  * root);
int snmp_config_init(snmp_machine_info   ** snmp_machine,snmp_basic_info * snmp_info);
int get_cycle_second(struct timeval  mache,int mache_time_cycle);


//通用 机器cpu 内存获取
void   snmp_common(snmp_machine_info *snmp_machine);
//思科 路由 cpu 内存获取
void   snmp_cisco(snmp_machine_info *snmp_machine);
void snmp_get_message(snmp_machine_info * snmp_machine);
void snmp_interval_get(snmp_machine_info *snmp_machine,snmp_basic_info snmp_info);
void snmp_free(snmp_machine_info * snmp_machine);
void * snmp_init(void * tmp);
void snmp_start();
#endif
/*
*@author: 赵秋然
*@date:2021年8月7日
*@description:snmp.c
*/
#include "snmp.h"
int quit = 0;
pthread_t snmp_tid;

int is_valic_ip(char *ip){
    if(ip == NULL){
        return ERROR;
    }

    char  ip_val[30] = {'\0'};
    int a,b,c,d;
    strncpy(ip_val,ip,sizeof(ip_val)/sizeof(char)-1);
    if (4==sscanf(ip_val,"%d.%d.%d.%d",&a,&b,&c,&d)){
        if (0<=a && a<=255
                && 0<=b && b<=255
                && 0<=c && c<=255
                && 0<=d && d<=255){
            return SUCCE;
        }
    }
    return ERROR;
}

int snmp_get_info(netsnmp_session * session,char *dest_ip ,char * oid_val, int * res){
    netsnmp_session * ss = NULL;
    netsnmp_pdu * pdu;
    netsnmp_pdu * response;
    struct variable_list *vars;
    int status;
    if(session == NULL || dest_ip == NULL || oid_val == NULL || res == NULL){
        printf("snmp_get_info parameter is error \n");
        return STAT_ERROR;
    }

    if(is_valic_ip(dest_ip)){
        printf("snmp_get_info is_valic_ip ip is error \n");
        return STAT_ERROR;
    }

    session->peername =strdup(dest_ip) ;
    ss = snmp_open(session);
    if(ss == NULL){
        snmp_sess_perror("snmp_open", session);
        return STAT_ERROR;
    }

    oid requestOid[MAX_OID_LEN];
    size_t requestOidLength = MAX_OID_LEN;
    snmp_parse_oid(oid_val, requestOid, &requestOidLength);
    pdu = snmp_pdu_create(SNMP_MSG_GET);
    snmp_add_null_var(pdu,requestOid,requestOidLength);
    status = snmp_synch_response(ss, pdu,&response);
    if(status != STAT_SUCCESS || !response){
        snmp_sess_perror("faile snmp_synch_response",ss);
        status =  STAT_ERROR;
        goto SNMP_FREE;
    }
    if (response->errstat != SNMP_ERR_NOERROR){
        printf ("snmp: Error in packet: %s\n",snmp_errstring(response->errstat));
        status =  STAT_ERROR;
        goto SNMP_FREE;
    }

    for(vars = response->variables;vars; vars = vars->next_variable){
        if(vars->type == ASN_INTEGER || vars->type == ASN_GAUGE){
            //printf("FINISH value 33 [%d] \n",*vars->val.integer);
            *res = *vars->val.integer;
        }
        else if(vars->type == ASN_NULL){
            printf("OID value IS NULL wait a moment  [%s] \n", oid_val);
            *res = 0;
        }
        else{
            // printf("type  value IS error [%d] ,  \n", vars->type);
            *res = 0;
        }
    }

SNMP_FREE:
    snmp_free_pdu(response);
    snmp_close(ss);
    return status;
}

int snmp_dialog_create(snmp_machine_info   * snmp_machine,snmp_basic_info snmp_info){
    if(snmp_machine == NULL || snmp_info.snmp_count <= 0 ){
        printf("snmp_create_info parameter is error \n");
        return STAT_ERROR;
    }

    //snmp_machine_info * snmp_machine = *snmp_m;
    init_snmp("SNMP GET CPU MEMORY");
    int i = 0;
    for(i = 0;i<snmp_info.snmp_count;++i){
        snmp_sess_init(&snmp_machine[i].s_session);
        snmp_machine[i].s_session.community=(u_char*)snmp_machine[i].community;
        snmp_machine[i].s_session.community_len = strlen((const char*)snmp_machine[i].community);
        switch (snmp_machine[i].snmp_version){
        case SNMP_V1:
            snmp_machine[i].s_session.version = SNMP_VERSION_1;
            break;
        case SNMP_V2:
            snmp_machine[i].s_session.version = SNMP_VERSION_2c;
            break;
        case SNMP_V3:
            snmp_machine[i].s_session.version =  SNMP_VERSION_3;
            //   strncpy(snmp_machine[i].s_session.securityName , snmp_machine[i].security_name,strlen(snmp_machine[i].security_name)) ;
            snmp_machine[i].s_session.securityName = snmp_machine[i].security_name;
            snmp_machine[i].s_session.securityNameLen = strlen(snmp_machine[i].security_name);
            /* 设置认证方法 */
            if(snmp_machine[i].snmp_auth == MD5){
                snmp_machine[i].s_session.securityAuthProto = usmHMACMD5AuthProtocol;
                snmp_machine[i].s_session.securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN;
            }
            else if(snmp_machine[i].snmp_auth == SHA){
                snmp_machine[i].s_session.securityAuthProto = usmHMACSHA1AuthProtocol;
                snmp_machine[i].s_session.securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN;
            }

            /*需要进行认证 */
            if((snmp_machine[i].snmp_auth  == MD5) || (snmp_machine[i].snmp_auth  == SHA))
            {
                snmp_machine[i].s_session.securityAuthKeyLen = USM_AUTH_KU_LEN;
                // 设置认证级别
                snmp_machine[i].s_session.securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
                if (generate_Ku(snmp_machine[i].s_session.securityAuthProto,
                                snmp_machine[i].s_session.securityAuthProtoLen,
                                (u_char *)snmp_machine[i].security_pass, strlen(snmp_machine[i].security_pass),
                                snmp_machine[i].s_session.securityAuthKey,
                                &snmp_machine[i].s_session.securityAuthKeyLen) != SNMPERR_SUCCESS)
                {
                    snmp_perror("AUTH");
                    snmp_log(LOG_ERR,
                             "AUTH Error generating Ku from priv cation pass phrase. \n");
                    return STAT_ERROR;
                }
            }

            if(snmp_machine[i].snmp_ency  == OPRIV){
                //printf("SNMP ONLY AUTH \n");
                return STAT_SUCCESS;
            }

            /* 设置加密方式  */
            if(snmp_machine[i].snmp_ency  == DES){
                snmp_machine[i].s_session.securityPrivProto = usmDESPrivProtocol;
                snmp_machine[i].s_session.securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN;
            }
            else if(snmp_machine[i].snmp_ency  == AES){
                snmp_machine[i].s_session.securityPrivProto = usmAESPrivProtocol;
                snmp_machine[i].s_session.securityPrivProtoLen = USM_PRIV_PROTO_AES_LEN;
            }

            /*需要加密连接 */
            if((snmp_machine[i].snmp_ency == DES) || (snmp_machine[i].snmp_ency == AES)){
                snmp_machine[i].s_session.securityPrivKeyLen = USM_PRIV_KU_LEN;
                /// 加密等级  认证 并 加密
                snmp_machine[i].s_session.securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;//;
                if (generate_Ku(snmp_machine[i].s_session.securityAuthProto,
                                snmp_machine[i].s_session.securityAuthProtoLen,
                                (u_char *)snmp_machine[i].priiv_pass, strlen(snmp_machine[i].priiv_pass),
                                snmp_machine[i].s_session.securityPrivKey,
                                &snmp_machine[i].s_session.securityPrivKeyLen) != SNMPERR_SUCCESS){
                    snmp_perror("ENCRY Error");
                    snmp_log(LOG_ERR,
                             "ENCRY Error generating Ku from priv cation pass phrase. \n");
                    return STAT_ERROR;
                }
            }
            break;
        }
    }
    return STAT_SUCCESS;

}

int snmp_basic_conf(snmp_basic_info * snmp_info,cJSON  * root){
    if(root == NULL){
        printf("snmp_basic_conf cJSON failed \n");
        return ERROR;
    }

    cJSON *object = cJSON_GetObjectItem(root,"snmp_basic_setting");
    cJSON* js_value;
    js_value = cJSON_GetObjectItem(object, "snmp_on");
    if(NULL == js_value){
        printf( "snmp_basic_conf snmp_on \n");
        return ERROR;
    }
    else{
        snmp_info->snmp_on  = js_value->valueint;
    }

    js_value = cJSON_GetObjectItem(object, "snmp_cycle_time");
    if(NULL == js_value){
        printf( "snmp_basic_conf snmp_cycle_time \n");
        return ERROR;
    }
    else{
        snmp_info->snmp_cycle_time  = js_value->valueint;
    }

    js_value = cJSON_GetObjectItem(object, "snmp_count");
    if(NULL == js_value){
        printf( "snmp_basic_conf snmp_count \n");
        return ERROR;
    }
    else{
        snmp_info->snmp_count  = js_value->valueint;
    }

    return SUCCE;
}



#define GET_CJSON_NUM_VALUE(object, buffer,value) \
{\
    cJSON* js_value = cJSON_GetObjectItem(object, buffer); \
    if(js_value != NULL) \
{\
    value = js_value->valueint;\
    }\
    else\
{  \
    printf("GET_CJSON_NUM_VALUE %s  failed \n",buffer);\
    return ERROR;\
    }\
    }

#define GET_CJSON_STR_VALUE(object,buffer,value) \
{\
    cJSON* js_value = cJSON_GetObjectItem(object, buffer); \
    if(js_value != NULL)\
{\
    if(js_value->valuestring != NULL) \
{\
    strncpy(value , js_value->valuestring,sizeof(value));\
    }\
    else\
{  \
    printf("GET_CJSON_STR_VALUE %s  failed \n",buffer);\
    return ERROR;\
    }\
    }\
    }

#define GET_CJSON_ARR_STR_VALUE(object, n,  value)\
{\
    cJSON * values = cJSON_GetArrayItem(object, n);\
    if(values != NULL)\
{\
    if(NULL != values->valuestring)\
{\
    strncpy(value, values->valuestring, sizeof(value));\
    }\
    else\
{\
    printf("GET_CJSON_ARR_STR_VALUE  failed \n");\
    return ERROR;\
    }\
    }\
    }


int snmp_device_conf(snmp_machine_info * machine,cJSON  * root)
{
    if(root == NULL){
        printf(" snmp_device_conf cJSON failed \n");
        return ERROR;
    }

    cJSON *array_item  = cJSON_GetObjectItem(root,"snmp_device");
    int object_count  = cJSON_GetArraySize(array_item), i = 0;
    for(i = 0;i<object_count;++i){
        cJSON *object = cJSON_GetArrayItem(array_item,i);
        GET_CJSON_NUM_VALUE(object,"snmp_device_on",machine[i].snmp_device_on);
        GET_CJSON_STR_VALUE(object,"machine_name",machine[i].machine_name);
        GET_CJSON_STR_VALUE(object,"machine_id",machine[i].machine_id);
        GET_CJSON_NUM_VALUE(object,"machine_type",machine[i].machine_type);
        GET_CJSON_STR_VALUE(object,"snmp_ip",machine[i].m_ip);
        GET_CJSON_NUM_VALUE(object,"snmp_version",machine[i].snmp_version);
        GET_CJSON_NUM_VALUE(object,"snmp_auth",machine[i].snmp_auth);
        GET_CJSON_NUM_VALUE(object,"snmp_ency",machine[i].snmp_ency);
        GET_CJSON_STR_VALUE(object,"community",machine[i].community);
        GET_CJSON_NUM_VALUE(object,"time_cycle",machine[i].time_cycle);
        GET_CJSON_STR_VALUE(object,"security_name",machine[i].security_name);
        GET_CJSON_STR_VALUE(object,"security_pass",machine[i].security_pass);
        GET_CJSON_STR_VALUE(object,"priiv_pass",machine[i].priiv_pass);
        gettimeofday(&machine[i].cur_time, NULL);
        cJSON* cpu_value = cJSON_GetObjectItem(object, "cpu_oid");
        int cpu_count  = cJSON_GetArraySize(cpu_value), j = 0;
        for(j = 0;j<cpu_count;++j){
            GET_CJSON_ARR_STR_VALUE(cpu_value,j, machine[i].cpu_oid[j]);
        }

        cJSON* mem_value = cJSON_GetObjectItem(object, "mem_oid");
        int mem_count  = cJSON_GetArraySize(mem_value), k = 0;
        for(k = 0;k<mem_count;++k){
            GET_CJSON_ARR_STR_VALUE(mem_value,k, machine[i].mem_oid[k]);
        }
    }

    return SUCCE;
}


int snmp_config_init(snmp_machine_info   ** snmp_machine,snmp_basic_info * snmp_info){
    char *p = NULL;
    cJSON *root = NULL;
    int ret = ERROR;
    p = file_get_contents(SNMP_CONF);
    // printf("SNMP__P [%s] \n",p);
    root = cJSON_Parse(p);
    if(root == NULL){
        printf(" snmp_config_init cJSON_Parse failed: [%s]\n",cJSON_GetErrorPtr());
        return ERROR;
    }

    ret = snmp_basic_conf(snmp_info,root);
    if(snmp_info->snmp_count == 0 ||  snmp_info->snmp_on == 0 ){
        goto END;
    }
    snmp_machine_info  * machine = (snmp_machine_info *)malloc(snmp_info->snmp_count*sizeof(snmp_machine_info));
    if(machine == NULL){
        printf(" snmp_config_init parameter failed \n");
        return ERROR;
    }
    
    memset(machine,'\0',snmp_info->snmp_count*sizeof(machine));
    ret = snmp_device_conf(machine,root);
    cJSON_Delete(root);
    safe_free(p);
    *snmp_machine = machine;

END:
    return ret;
}


int get_cycle_second(struct timeval  mache,int mache_time_cycle){
    struct timeval cur_time;
    gettimeofday(&cur_time, NULL);
    int timer0 = cur_time.tv_sec - mache.tv_sec;
    return (timer0 > mache_time_cycle)?1:0;
}

//通用 机器cpu 内存获取
void    snmp_common(snmp_machine_info *snmp_machine){
    if(snmp_machine == NULL){
        printf(" snmp_common parameter failed \n");
        return ;
    }

    int mem_total = 0,mem_aval=0,mem_share = 0,mem_buff = 0, mem_cache = 0;
    int cpu_free = 0;
    int status =  snmp_get_info(&snmp_machine->s_session,snmp_machine->m_ip ,snmp_machine->mem_oid[MEMTOTAL], &mem_total);
    status  = snmp_get_info(&snmp_machine->s_session,snmp_machine->m_ip ,snmp_machine->mem_oid[MEMAVAILABLE], &mem_aval);
    status  = snmp_get_info(&snmp_machine->s_session,snmp_machine->m_ip ,snmp_machine->mem_oid[MEM_SHARE], &mem_share);
    status  = snmp_get_info(&snmp_machine->s_session,snmp_machine->m_ip ,snmp_machine->mem_oid[MEM_BUFFER], &mem_buff);
    status  =snmp_get_info(&snmp_machine->s_session,snmp_machine->m_ip ,snmp_machine->mem_oid[MEM_CACHE], &mem_cache);

    if(status != SUCCE){
        printf("snmp_common snmp_get_info memory failed \n");
        return;
    }
    
    float mem_use_percent=0;
    if(mem_share +mem_buff + mem_cache > mem_total){
        mem_use_percent = (float)(mem_total - mem_aval - mem_buff - mem_cache + mem_share) / (float)mem_total *100;
        //printf(" 000  [%d] , [%d] \n",mem_total - mem_aval - mem_buff - mem_cache + mem_share,mem_total);
    }
    else{
        mem_use_percent = (float)(mem_total - mem_aval - mem_buff - mem_cache ) / (float)mem_total *100;
        // printf(" 111  [%d] , [%d] \n",mem_total - mem_aval - mem_buff - mem_cache,mem_total);
    }

    snprintf(snmp_machine->mem_use_percent ,RES_LEN,"%.3f",mem_use_percent);
    printf("a通用机器 内存使用率 %s%% \t", snmp_machine->mem_use_percent);


    snmp_get_info(&snmp_machine->s_session,snmp_machine->m_ip ,snmp_machine->cpu_oid[0], &cpu_free);
    if(status != SUCCE){
        printf("snmp_common snmp_get_info memory failed \n");
        return;
    }
    
    float cpu_use_percent = (float)((cpu_free == 0)?0:(100 -cpu_free));
    snprintf(snmp_machine->cpu_use_percent ,RES_LEN,"%.3f",cpu_use_percent);
    printf("   cpu 使用率 [%s%%] \n", snmp_machine->cpu_use_percent);
}

//思科 路由 cpu 内存获取
void   snmp_cisco(snmp_machine_info *snmp_machine){
    if(snmp_machine == NULL){
        printf(" snmp_cisco parameter failed \n");
        return ;
    }
    
    int mess_use = 0, mess_unuse = 0;
    int status = snmp_get_info(&snmp_machine->s_session,snmp_machine->m_ip ,snmp_machine->mem_oid[MEM_USE],&mess_use);
    status = snmp_get_info(&snmp_machine->s_session,snmp_machine->m_ip ,snmp_machine->mem_oid[MEM_UNUSE],&mess_unuse);
    if(status != SUCCE){
        printf("snmp_cisco snmp_get_info memory failed \n");
        return;
    }

    float mem_use_percent =   (float)mess_use /  (float)(mess_use+mess_unuse) * 100;
    snprintf(snmp_machine->mem_use_percent ,RES_LEN,"%.3f",mem_use_percent);
    int cpu_use = 0;
    status = snmp_get_info(&snmp_machine->s_session,snmp_machine->m_ip ,snmp_machine->cpu_oid[0],&cpu_use);
    if(status != SUCCE){
        printf("snmp_cisco snmp_get_info cpu failed \n");
        return;
    }
    
    float cpu_use_percent = (float)((cpu_use == 0)?0:(cpu_use));
    snprintf(snmp_machine->cpu_use_percent ,RES_LEN,"%.3f",cpu_use_percent);
    printf("思科 内存使用率 %s%%   cpu 5分钟 %s%% \n",snmp_machine->mem_use_percent ,snmp_machine->cpu_use_percent);
}


void snmp_get_message(snmp_machine_info * snmp_machine){
    if(snmp_machine == NULL)  {
        printf(" snmp_get_message parameter failed \n");
        return ;
    }

    switch (snmp_machine->machine_type)  {
    case COMMON:
        snmp_common(snmp_machine);
        break;
    case CISCO:
        snmp_cisco(snmp_machine);
        break;
    default:
        printf("未知类型");
    }
}
void snmp_interval_get(snmp_machine_info *snmp_machine,snmp_basic_info snmp_info){
    if(snmp_machine == NULL|| snmp_info.snmp_count <= 0){
        printf(" snmp_interval_get parameter failed \n");
        return ;
    }

    int i = 0;
    while(!quit){
        for(i = 0;i<snmp_info.snmp_count;++i){
            if(snmp_machine[i].snmp_device_on){
                if(get_cycle_second(snmp_machine[i].cur_time,snmp_machine[i].time_cycle))    {
                    gettimeofday(&snmp_machine[i].cur_time,NULL);
                    snmp_get_message(&snmp_machine[i]);
                }
            }
        }

        ///每隔1秒钟,进行整体循环一次 ,更新周期1秒钟
        sleep(snmp_info.snmp_cycle_time);
        i = 0;
    }

    
}

void snmp_free(snmp_machine_info * snmp_machine){
    if(snmp_machine){
        snmp_machine = NULL;
        free(snmp_machine);
    }
}


void sigroutine(int signo){
    switch (signo){
    case SIGINT:
        printf("SNMP service ctrl+c GET a signal , program exit!\n");
        quit = 1;
        pthread_join(snmp_tid,NULL);
        break;
    }
}

void * snmp_init(void * tmp){
    // 创建s_session
    // 定时获取  cpu 内存信息  ,这里确定一下 是否支持异步获取
    snmp_machine_info  * snmp_machine = NULL;
    int statu = -1;
    snmp_basic_info snmp_info;
    memset(&snmp_info,'\0',sizeof(snmp_info));
    
    /// snmp配置信息 初始化
    statu = snmp_config_init(&snmp_machine, &snmp_info);
    if(ERROR == statu){
        goto FIN;
    }

    if(snmp_info.snmp_count == 0 ||  snmp_info.snmp_on == 0 ){
        printf("snmp not configure no run!\n");
        goto FIN;
    }
    
    // snmp 会话创建
    statu =snmp_dialog_create(snmp_machine,snmp_info);
    if(ERROR == statu){
        goto FIN;
    }

    // snmp 信息 间隔获取
    snmp_interval_get(snmp_machine,snmp_info);

FIN:
    ///snmp 堆空间释放
    snmp_free(snmp_machine);

    return  0;
}

void snmp_start(){
    void * tmp = NULL;
    signal(SIGINT,sigroutine);
    pthread_create(&snmp_tid,NULL,snmp_init,tmp);
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值