snmp/mib采用子代理模式,编码,部署

0.环境

0.1 编译net-snmp

cd net-snmp-5.7.2

./configure --prefix=/usr/local/snmp

BEGIN failed--compilation aborted at Makefile.PL line 1.

make: *** [perlmakefiles] Error 2

yum install cpan -y

make && make install

/usr/local/snmp/sbin/snmpd 启动

0.2 直接安装(本文采用直接安装的方式)

yum install -y net-snmp, net-snmp-devel,net-snmp-perl,net-snmp-utils

vim /etc/snmp/snmpd.conf

master agentx

rocommunity public

rwcommunity public

service snmpd restart

service snmpd restart

1.验证

1.1 snmpd服务

vim /etc/snmp/snmpd.conf

master agentx

rocommunity public

rwcommunity public

service snmpd restart

1.2 启动编写的子代理程序:

./snmp_agent_mib &

提示NET-SNMP version 5.9.3 AgentX subagent connected

1.3 mib查询

1.3.1 验证方式1:

验证mib文件是否有错(LINUO-ATCA-BOARD-STATUS-MIB.txt):

snmptranslate -Tp -IR LINUO-ATCA-BOARD-STATUS-MIB::atcaModule //解析出来说明mib文件没有语法错误之类的

snmpget -v2c -c public localhost 1.3.6.1.4.1.12001.5.1.0

SNMPv2-SMI::enterprises.12001.5.1.0 = Gauge32: 2

snmpget -v2c -c public localhost 1.3.6.1.4.1.12001.5.5.1.0

SNMPv2-SMI::enterprises.12001.5.5.1.0 = Gauge32: 3

1.3.2 验证方式2:

安装mib-browse 加载LINUO-ATCA-BOARD-STATUS-MIB.txt后进行查询

2.mib文件

-- LINUO-ATCA-BOARD-STATUS-MIB.my

LINUO-ATCA-BOARD-STATUS-MIB DEFINITIONS ::= BEGIN

IMPORTS

OBJECT-GROUP, MODULE-COMPLIANCE, NOTIFICATION-GROUP

FROM SNMPv2-CONF

enterprises, OBJECT-TYPE, MODULE-IDENTITY, Unsigned32

FROM SNMPv2-SMI

DisplayString

FROM SNMPv2-TC;

-- Module Identity

-- OID: 1.3.6.1.4.1.12001

atcaModule MODULE-IDENTITY

LAST-UPDATED "202310010000Z" -- Update with actual timestamp

ORGANIZATION

"LINUO Corporation"

CONTACT-INFO

"Postal: LINUO Corp\nEmail: support@linuo.com"

DESCRIPTION

"MIB for ATCA Board Status Monitoring."

::= { enterprises 12001 } -- 1.3.6.1.4.1.12001

-- Top-level OID structure

linuoAtca OBJECT IDENTIFIER ::= { atcaModule 5 } -- 1.3.6.1.4.1.12001.5

-- Node 1: atcaCollectionStatus (Unsigned32)

-- OID: 1.3.6.1.4.1.12001.5.1

atcaCollectionStatus OBJECT-TYPE

SYNTAX Unsigned32

MAX-ACCESS read-only

STATUS current

DESCRIPTION

"Status of ATCA board collection."

::= { linuoAtca 1 }

-- Subtree for chassis info

atcaChassis OBJECT IDENTIFIER ::= { linuoAtca 5 } -- 1.3.6.1.4.1.12001.5.5

-- Node 2: atcaBoardInfoIndex (Unsigned32)

-- OID: 1.3.6.1.4.1.12001.5.5.1

atcaBoardInfoIndex OBJECT-TYPE

SYNTAX Unsigned32

MAX-ACCESS read-only

STATUS current

DESCRIPTION

"Index identifier for ATCA board chassis information."

::= { atcaChassis 1 }

END

3.代码(为了方便贴上来集中在一个文件中,支持get、get-next、walk操作)

/* add by zhuwei 2025/3/18

*

* 安装依赖库(如 Net-SNMP):yum install net-snmp net-snmp-utils

* yum install net-snmp-devel //相关头文件

* 编译:gcc -o snmp_agent snmp_agent.c -lnetsnmpagent -lnetsnmphelpers -lnetsnmpmibs -lnetsnmp //相关库在/usr/lib64

* 配置文件(/etc/snmp/snmpd.conf):

* 启动 Agent:./snmp_agent_mib

* 客户端测试:snmpget -v2c -c public localhost 1.3.6.1.4.1.12001.5.1.0

* 查看调试日志:net-snmp-config --log-file

* tail -f /var/log/snmpd.log

*

*/

#include <stdio.h>

#include <stdlib.h>

#include <net-snmp/net-snmp-config.h> // 必须首先包含

#include <net-snmp/types.h> // 定义 oid、netsnmp_container 等

#include <net-snmp/library/tools.h> // 提供基础工具函数

#include <net-snmp/library/container.h>

#include <net-snmp/agent/net-snmp-agent-includes.h>

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

extern int netsnmp_running;

const char *app_name = "snmp_agent_mib";

static int reconfig = 0;

// 定义 atcaCollectionStatus 的 OID

const oid atcaCollectionStatus_oid[] = { 1, 3, 6, 1, 4, 1, 12001, 5, 1 };

// 定义 atcaBoardInfoIndex 的 OID

const oid atcaBoardInfoIndex_oid[] = { 1, 3, 6, 1, 4, 1, 12001, 5, 5, 1 };

// OID比较函数

static int compare_oid(const oid *oid1, size_t len1, const oid *oid2, size_t len2) {

size_t i;

for (i = 0; i < len1 && i < len2; i++) {

if (oid1[i] != oid2[i]) {

return oid1[i] - oid2[i];

}

}

return len1 - len2;

}

#ifdef GNUC

#define UNUSED attribute((unused))

#else

#define UNUSED

#endif

RETSIGTYPE stop_server(UNUSED int a)

{

puts("捕捉到信号 SIGTERM/SIGINT");

netsnmp_running = 0;

}

#ifdef SIGHUP

RETSIGTYPE hup_handler(int sig)

{

puts("捕捉到信号 SIGHUP");

reconfig = 1;

signal(SIGHUP, hup_handler);

}

#endif

void reg_sig()

{

#ifdef SIGTERM

signal(SIGTERM, stop_server);

#endif

#ifdef SIGINT

signal(SIGINT, stop_server);

#endif

#ifdef SIGHUP

signal(SIGHUP, hup_handler);

#endif

}

int handle_atcaCollectionStatus(

netsnmp_mib_handler *handler,

netsnmp_handler_registration *reginfo,

netsnmp_agent_request_info *reqinfo,

netsnmp_request_info *requests

);

int handle_atcaBoardInfoIndex(

netsnmp_mib_handler *handler,

netsnmp_handler_registration *reginfo,

netsnmp_agent_request_info *reqinfo,

netsnmp_request_info *requests

);

void register_oids()

{

netsnmp_handler_registration *reg;

// 注册 atcaCollectionStatus

reg = netsnmp_create_handler_registration(

"atcaCollectionStatus",

handle_atcaCollectionStatus, // 回调函数

atcaCollectionStatus_oid,

OID_LENGTH(atcaCollectionStatus_oid),

HANDLER_CAN_RONLY //此处可以注册HANDLER_CAN_RWRITE即支持写操作

);

if(MIB_REGISTERED_OK != netsnmp_register_scalar(reg))

{

printf("atcaCollectionStatus register fail \n");

}

// 注册 atcaBoardInfoIndex(类似逻辑)

reg = netsnmp_create_handler_registration(

"atcaBoardInfoIndex",

handle_atcaBoardInfoIndex, // 回调函数

atcaBoardInfoIndex_oid,

OID_LENGTH(atcaBoardInfoIndex_oid),

HANDLER_CAN_RONLY //此处可以注册HANDLER_CAN_RWRITE即支持写操作

);

if(MIB_REGISTERED_OK != netsnmp_register_scalar(reg))

{

printf("atcaBoardInfoIndex register fail \n");

}

}

unsigned int read_hardware_status() {

// 通过 ioctl 或内存映射读取硬件寄存器

// int fd = open("/dev/atca_device", O_RDONLY);

unsigned int status = 2;

//ioctl(fd, ATCA_GET_STATUS, &status);

// close(fd);

return status;

}

// 修改处理函数以支持GETNEXT和预留SET

int handle_atcaCollectionStatus(

netsnmp_mib_handler *handler,

netsnmp_handler_registration *reginfo,

netsnmp_agent_request_info *reqinfo,

netsnmp_request_info *requests

) {

unsigned int status = 0;

oid requested_oid[MAX_OID_LEN];

size_t requested_oid_len;

switch (reqinfo->mode) {

case MODE_GET: {

status = read_hardware_status();

snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED, &status, sizeof(status));

break;

}

case MODE_GETNEXT: {

// 获取请求的OID

requested_oid_len = requests->requestvb->name_length;

memcpy(requested_oid, requests->requestvb->name, requested_oid_len * sizeof(oid));

// 确定下一个OID

if (compare_oid(requested_oid, requested_oid_len,

atcaCollectionStatus_oid,

OID_LENGTH(atcaCollectionStatus_oid)) < 0) {

status = read_hardware_status();

snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED, &status, sizeof(status));

snmp_set_var_objid(requests->requestvb, atcaCollectionStatus_oid,

OID_LENGTH(atcaCollectionStatus_oid));

} else {

// 传递到下一个OID处理

return SNMP_ERR_NOSUCHNAME;

}

break;

}

case MODE_SET_RESERVE1:

case MODE_SET_RESERVE2:

case MODE_SET_ACTION:

case MODE_SET_COMMIT:

case MODE_SET_FREE:

// 预留SET支持(暂返回错误)

return SNMP_ERR_READONLY;

default:

return SNMP_ERR_GENERR;

}

return SNMP_ERR_NOERROR;

}

unsigned int read_hardware_index() {

// 通过 ioctl 或内存映射读取硬件寄存器

//int fd = open("/dev/atca_device", O_RDONLY);

unsigned int status = 3;

//ioctl(fd, ATCA_GET_STATUS, &status);

//close(fd);

return status;

}

int handle_atcaBoardInfoIndex(

netsnmp_mib_handler *handler,

netsnmp_handler_registration *reginfo,

netsnmp_agent_request_info *reqinfo,

netsnmp_request_info *requests

) {

unsigned int status = 0;

oid requested_oid[MAX_OID_LEN];

size_t requested_oid_len;

switch (reqinfo->mode) {

case MODE_GET: {

// 从设备读取数据(示例值)

status = read_hardware_index();// 自定义数据采集函数

snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED, &status, sizeof(status));

break;

}

case MODE_GETNEXT: {

// 获取请求的OID

requested_oid_len = requests->requestvb->name_length;

memcpy(requested_oid, requests->requestvb->name, requested_oid_len * sizeof(oid));

// 确定下一个OID

if (compare_oid(requested_oid, requested_oid_len,

atcaCollectionStatus_oid,

OID_LENGTH(atcaCollectionStatus_oid)) < 0) {

status = read_hardware_status();

snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED, &status, sizeof(status));

snmp_set_var_objid(requests->requestvb, atcaCollectionStatus_oid,

OID_LENGTH(atcaCollectionStatus_oid));

} else {

// 传递到下一个OID处理

return SNMP_ERR_NOSUCHNAME;

}

break;

}

case MODE_SET_RESERVE1:

case MODE_SET_RESERVE2:

case MODE_SET_ACTION:

case MODE_SET_COMMIT:

case MODE_SET_FREE:

// 预留SET支持(暂返回错误)

return SNMP_ERR_READONLY;

default:

return SNMP_ERR_GENERR;

}

return SNMP_ERR_NOERROR;

}

static void usage(const char *prog)

{

fprintf(stderr,

"USAGE: %s [OPTIONS]\n"

"\n"

"OPTIONS:\n", prog);

fprintf(stderr,

" -d\t\t\tdump all traffic\n"

" -D TOKEN[,...]\tturn on debugging output for the specified "

"TOKENs\n"

"\t\t\t (ALL gives extremely verbose debugging output)\n"

" -f\t\t\tDo not fork() from the calling shell.\n"

" -h\t\t\tdisplay this help message\n"

" -H\t\t\tdisplay a list of configuration file directives\n"

" -L LOGOPTS\t\tToggle various defaults controlling logging:\n");

snmp_log_options_usage("\t\t\t ", stderr);

#ifndef DISABLE_MIB_LOADING

fprintf(stderr,

" -m MIB[:...]\t\tload given list of MIBs (ALL loads "

"everything)\n"

" -M DIR[:...]\t\tlook in given list of directories for MIBs\n");

#endif /* DISABLE_MIB_LOADING */

#ifndef DISABLE_MIB_LOADING

fprintf(stderr,

" -P MIBOPTS\t\tToggle various defaults controlling mib "

"parsing:\n");

snmp_mib_toggle_options_usage("\t\t\t ", stderr);

#endif /* DISABLE_MIB_LOADING */

fprintf(stderr,

" -v\t\t\tdisplay package version number\n"

" -x TRANSPORT\tconnect to master agent using TRANSPORT\n");

exit(1);

}

static void version(void)

{

fprintf(stderr, "NET-SNMP version: %s\n", netsnmp_get_version());

exit(0);

}

int main (int argc, char **argv)

{

int arg;

char* cp = NULL;

int dont_fork = 0, do_help = 0;

while ((arg = getopt(argc, argv, "dD:fhHL:"

#ifndef DISABLE_MIB_LOADING

"m:M:"

#endif /* DISABLE_MIB_LOADING */

"n:"

#ifndef DISABLE_MIB_LOADING

"P:"

#endif /* DISABLE_MIB_LOADING */

"vx:")) != EOF)

{

switch (arg) {

case 'd':

//netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_LOG_FILE, "/var/log/snmpd.log");

//netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_DEBUG_LEVEL, 3);

netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,NETSNMP_DS_LIB_DUMP_PACKET, 1);

break;

case 'D':

debug_register_tokens(optarg);

snmp_set_do_debugging(1);

break;

case 'f':

dont_fork = 1;

break;

case 'h':

usage(argv[0]);

break;

case 'H':

do_help = 1;

break;

case 'L':

if (snmp_log_options(optarg, argc, argv) < 0) {

exit(1);

}

break;

#ifndef DISABLE_MIB_LOADING

case 'm':

if (optarg != NULL) {

setenv("MIBS", optarg, 1);

} else {

usage(argv[0]);

}

break;

case 'M':

if (optarg != NULL) {

setenv("MIBDIRS", optarg, 1);

} else {

usage(argv[0]);

}

break;

#endif /* DISABLE_MIB_LOADING */

case 'n':

if (optarg != NULL) {

app_name = optarg;

netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,

NETSNMP_DS_LIB_APPTYPE, app_name);

} else {

usage(argv[0]);

}

break;

#ifndef DISABLE_MIB_LOADING

case 'P':

cp = snmp_mib_toggle_options(optarg);

if (cp != NULL) {

fprintf(stderr, "Unknown parser option to -P: %c.\n", *cp);

usage(argv[0]);

}

break;

#endif /* DISABLE_MIB_LOADING */

case 'v':

version();

break;

case 'x':

if (optarg != NULL) {

netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,

NETSNMP_DS_AGENT_X_SOCKET, optarg);

} else {

usage(argv[0]);

}

break;

default:

fprintf(stderr, "invalid option: -%c\n", arg);

usage(argv[0]);

break;

}

}

if (do_help)

{

netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,

NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1);

}

else

{

netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,NETSNMP_DS_AGENT_ROLE, 1);

if (!dont_fork)

{

if (netsnmp_daemonize(1, snmp_stderrlog_status()) != 0)

exit(1);

}

SOCK_STARTUP;

}

init_agent(app_name);

register_oids();

//load app_name.conf

init_snmp(app_name);

if (do_help)

{

fprintf(stderr, "Configuration directives understood:\n");

read_config_print_usage(" ");

exit(0);

}

netsnmp_running = 1;

reg_sig();

while(netsnmp_running)

{

if (reconfig)

{

free_config();

read_configs();

reconfig = 0;

}

agent_check_and_process(1);

}

snmp_shutdown(app_name);

shutdown_agent();

SOCK_CLEANUP;

exit(0);

}

4.Makefile

Makefile for SNMP Agent (snmp_agent_mib)

Compiler and flags

CC = gcc

CFLAGS = -g -Wall -I/usr/include/net-snmp

LDFLAGS += -L/usr/local/lib -Wl,-rpath=/usr/local/lib

LDFLAGS += -lnetsnmpagent -lnetsnmphelpers -lnetsnmpmibs -lnetsnmp

Targets

TARGET = snmp_agent_mib

SRC = snmp_agent_mib.c

all: $(TARGET)

(TARGET): (SRC)

(CC) (CFLAGS) -o @ ^ $(LDFLAGS)

clean:

rm -f $(TARGET)

.PHONY: all clean

5.代码直接拷贝编译运行即能使用

需要set的tx可以自行添加.

相关推荐
努力学习的小廉21 小时前
【C++】 —— 笔试刷题day_9
开发语言·c++·代理模式
码农幻想梦3 天前
第五章 动态规划
算法·动态规划·代理模式
每天减 1/5kg6 天前
结构型——代理模式
python·设计模式·代理模式
huang_xiaoen6 天前
java设计模式之代理模式《赛博园丁的代理觉醒》
java·设计模式·代理模式
J不知道ava8 天前
Mybatis的代理模式
mybatis·代理模式
述雾学java11 天前
反射(第三篇)、代理模式、静态代理和动态代理、InvocationHandler实际应用
java·代理模式·java核心基础
图论难的离谱11 天前
Java算法之解题套路
java·算法·代理模式
Blockchina12 天前
Python自动化脚本:2分钟快速搭建MTProto代理服务(支持多端口负载均衡)
运维·自动化·代理模式