您的位置:首页 > 理论基础 > 计算机网络

【网络编程】——ne-snmp开发实例1

2016-02-21 17:04 495 查看
net-snmp扩展有多种方式,在此只介绍两种——动态库扩展,静态库扩展。

在做net-snmp开发之前,首先确定net-snmp相关的软件是否安装。

rpm -qa | grep snmp
net-snmp-5.3.1-19.el5
net-snmp-perl-5.3.1-19.el5
net-snmp-libs-5.3.1-19.el5
net-snmp-utils-5.3.1-19.el5
net-snmp-devel-5.3.1-19.el5


动态库扩展

使用动态库扩展net-snmp有4个步骤,分别是:

1:编写MIB库。

2:根据MIB库生成源代码。可以使用mib2c工具。

3:编译。

4:修改配置文件。

编写MIB库

  假设我们现在需要使用snmp来获取某个服务器上的硬盘使用情况——df命令显示的数据。首先我们需要一个字段来表示HostName,然后我们需要一个表来存放磁盘的信息DiskInfoTable。

/*
* Note: this file originally auto-generated by mib2c using
*  : mib2c.iterate.conf,v 5.17 2005/05/09 08:13:45 dts12 Exp $
*/

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "DiskInfoTable.h"
typedef struct _disk_info {
char            filesystem[64];
char            size[64];
char            used[64];
char            avail[64];
char            capacity[64];
char            mountedOn[64];
}disk_info_t;

disk_info_t disk_info[MAX_DISK] = {
{"/dev/mapper", "19G", "2.6G", "15G", "15%", "/"},
{"/dev/sda1", "99M", "12M", "83M", "13%", "/boot"},
{"tmpfs", "252M", "0", "252M", "0%", "/dev/shm"},
{"/dev/scd1", "2.8G", "2.8G", "0", "100%", "/media/"},
};

/** Initializes the DiskInfoTable module */
void
init_DiskInfoTable(void)
{
/*
* here we initialize all the tables we're planning on supporting
*/
initialize_table_DiskInfoTable();
}

/** Initialize the DiskInfoTable table by defining its contents and how it's structured */
void
initialize_table_DiskInfoTable(void)
{
static oid      DiskInfoTable_oid[] =
{ 1, 3, 6, 1, 4, 1, 888888, 1, 2 };
size_t          DiskInfoTable_oid_len = OID_LENGTH(DiskInfoTable_oid);
netsnmp_handler_registration *reg;
netsnmp_iterator_info *iinfo;
netsnmp_table_registration_info *table_info;

reg =
netsnmp_create_handler_registration("DiskInfoTable",
DiskInfoTable_handler,
DiskInfoTable_oid,
DiskInfoTable_oid_len,
HANDLER_CAN_RONLY);

table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
netsnmp_table_helper_add_indexes(table_info, ASN_OCTET_STR, /* index: Filesystem */
0);
table_info->min_column = COLUMN_FILESYSTEM;
table_info->max_column = COLUMN_MOUNTEDON;

iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info);
iinfo->get_first_data_point = DiskInfoTable_get_first_data_point;
iinfo->get_next_data_point = DiskInfoTable_get_next_data_point;
iinfo->table_reginfo = table_info;

netsnmp_register_table_iterator(reg, iinfo);

/*
* Initialise the contents of the table here
*/
}

/*
* Typical data structure for a row entry
*/
struct DiskInfoTable_entry {
/*
* Column values
*/
char            Filesystem[16];
char            size[8];
char            used[8];
char            avail[8];
char            capacity[8];
char            mountedOn[16];
/*
* Illustrate using a simple linked list
*/
int             valid;
struct DiskInfoTable_entry *next;
};

struct DiskInfoTable_entry *DiskInfoTable_head;

/*
* create a new row in the (unsorted) table
*/
struct DiskInfoTable_entry *
DiskInfoTable_createEntry(char *Filesystem)
{
struct DiskInfoTable_entry *entry;

entry = SNMP_MALLOC_TYPEDEF(struct DiskInfoTable_entry);
if (!entry)
return NULL;

//entry->Filesystem = Filesystem;
strncpy(entry->Filesystem, Filesystem, strlen(Filesystem));
entry->next = DiskInfoTable_head;
DiskInfoTable_head = entry;
return entry;
}
/*
* remove a row from the table
*/
void
DiskInfoTable_removeEntry(struct DiskInfoTable_entry *entry)
{
struct DiskInfoTable_entry *ptr, *prev;

if (!entry)
return;                 /* Nothing to remove */

for (ptr = DiskInfoTable_head, prev = NULL;
ptr != NULL; prev = ptr, ptr = ptr->next) {
if (ptr == entry)
break;
}
if (!ptr)
return;                 /* Can't find it */

if (prev == NULL)
DiskInfoTable_head = ptr->next;
else
prev->next = ptr->next;

SNMP_FREE(entry);           /* XXX - release any other internal resources */
}

static void fill_diskinfotable_entry(struct DiskInfoTable_entry *entry) {
int i;

for (i = 0; i < MAX_DISK; i++) {
if (!strcmp(disk_info[i].filesystem, entry->Filesystem)) {
strncpy(entry->size, disk_info[i].size, strlen(disk_info[i].size));
//strcpy(entry->size, "444G");
strncpy(entry->used, disk_info[i].used, strlen(disk_info[i].used));
strncpy(entry->avail, disk_info[i].avail, strlen(disk_info[i].avail));
strncpy(entry->capacity, disk_info[i].capacity, strlen(disk_info[i].capacity));
strncpy(entry->mountedOn, disk_info[i].mountedOn, strlen(disk_info[i].mountedOn));
}
}

}

static void read_data(void) {
int i = 0;
struct DiskInfoTable_entry *entry = NULL;

if(DiskInfoTable_head == NULL){
for (i = 0; i < MAX_DISK; i++) {
DiskInfoTable_createEntry(disk_info[i].filesystem);
}
}

entry = DiskInfoTable_head;

while (entry) {
fill_diskinfotable_entry(entry);
entry = entry->next;
}

}

/*
* Example iterator hook routines - using 'get_next' to do most of the work
*/
netsnmp_variable_list *
DiskInfoTable_get_first_data_point(void **my_loop_context,
void **my_data_context,
netsnmp_variable_list * put_index_data,
netsnmp_iterator_info *mydata)
{
read_data();
*my_loop_context = DiskInfoTable_head;
*my_data_context = DiskInfoTable_head;
return DiskInfoTable_get_next_data_point(my_loop_context,
my_data_context,
put_index_data, mydata);
}

netsnmp_variable_list *
DiskInfoTable_get_next_data_point(void **my_loop_context,
void **my_data_context,
netsnmp_variable_list * put_index_data,
netsnmp_iterator_info *mydata)
{
struct DiskInfoTable_entry *entry =
(struct DiskInfoTable_entry *) *my_loop_context;
netsnmp_variable_list *idx = put_index_data;

if (entry) {
snmp_set_var_value(idx, (u_char *)entry->Filesystem,
sizeof(entry->Filesystem));
idx = idx->next_variable;
*my_data_context = (void *) entry;
*my_loop_context = (void *) entry->next;
} else {
return NULL;
}
return put_index_data;
}

/** handles requests for the DiskInfoTable table */
int
DiskInfoTable_handler(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{

netsnmp_request_info *request;
netsnmp_table_request_info *table_info;
struct DiskInfoTable_entry *table_entry;

switch (reqinfo->mode) {
/*
* Read-support (also covers GetNext requests)
*/
case MODE_GET:
for (request = requests; request; request = request->next) {
table_entry = (struct DiskInfoTable_entry *)
netsnmp_extract_iterator_context(request);
table_info = netsnmp_extract_table_info(request);

switch (table_info->colnum) {
case COLUMN_FILESYSTEM:
if (table_entry == NULL) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
(u_char *)table_entry->Filesystem,
sizeof(table_entry->Filesystem));
break;
case COLUMN_SIZE:
if (table_entry == NULL) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
(u_char *)table_entry->size,
sizeof(table_entry->size));
break;
case COLUMN_USED:
if (table_entry == NULL) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
(u_char *)table_entry->used,
sizeof(table_entry->used));
break;
case COLUMN_AVAIL:
if (table_entry == NULL) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
(u_char *)table_entry->avail,
sizeof(table_entry->avail));
break;
case COLUMN_CAPACITY:
if (table_entry == NULL) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
(u_char *)table_entry->capacity,
sizeof(table_entry->capacity));
break;
case COLUMN_MOUNTEDON:
if (table_entry == NULL) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
(u_char *)table_entry->mountedOn,
sizeof(table_entry->mountedOn));
break;
default:
continue;
//netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE);
}
}
break;

}
return SNMP_ERR_NOERROR;
}


Table code
除了这些还需要有一个common.c把所有的代码连接到一起。

#include "HostName.h"
#include "DiskInfoTable.h"
void init_diskcheck(void) {
init_HostName();
init_DiskInfoTable();
}


注:init_动态库名 和生成的动态库名字有联系,如果动态库名字不为 diskcheck.so net-snmp有可能无法识别。

编译

编译这块主要是利用net-snmp给的命令,直接给出Makefile好了。

CC = gcc

DIR = HostName DiskInfoTable
#DIR = HostName

vpath %.c ./
vpath %.c $(DIR)

INCLUDE = -I./
INCLUDE += $(foreach x, $(DIR), -I./$(x))

CFLAGS = -fPIC -shared -O3
CFLAGS += $(shell net-snmp-config --cflags)

LDFLAGS = $(shell net-snmp-config --libs)

SRC = common.c
SRC += $(foreach x, $(DIR), $(x).c)
OBJS = $(SRC:.c=.o)

TARGET = diskcheck.so

all:$(TARGET)

$(TARGET):$(OBJS)
$(CC) $^ -o $@ $(CFLAGS) $(LDFLAGS)

$(OBJS):%.o:%.c
$(CC) -c $^ -o $@ $(CFLAGS) $(INCLUDE)

.PHONY:clean
clean:
rm *.o $(TARGET)


把编译好的diskcheck.so拷贝到 /usr/lib (32位系统) /usr/lib64 (64位系统)中.

修改配置文件

1:/etc/snmp/snmp.conf 中加上 mibs +MIB文件的名字(不带后缀)

2:/etc/snmp/snmpd.conf 中加上

  dlmod 动态库名 动态库绝对路径 —— dlmod diskcheck /usr/lib/diskcheck.so

  view systemview .1

Ps: 在/etc/snmp/snmpd.conf 中添加

view systemview included .1.3.6.1.4.1

有些系统在访问节点的时候有错误,例如在redhat as5.8 中有问题,而CentOS6.4中没问题【有可能是我的配置问题】。需要改成步骤二中的配置。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: