Ubuntu 開發 net-snmp

繼上篇文章 “Ubuntu 編譯 net-snmp”,我們將 net-snmp 建立在/usr/local/net-snmp,本篇將介紹如何撰寫 subagent、snmpget、snmpset 的 code,以及如何利用 broadcast 詢問到支援 snmp 的設備。

另外因為我們是自己 build 一個環境,所以我們並沒有將 snmpd 掛載成一個服務,所以本篇全部都是以執行檔的方式使用 net-snmp 的程式

一、 snmpd service

1. snmpd.conf 配置

不囉嗦,直接建立好 v1、v2 的 rocomunity、rwcomunity, v3 之後出現 user 的存在一樣是 rwuser、rouser。

###########################################################################
#
# snmpd.conf
#
#   - created by the snmpconf configuration program
#
##########################################################################
# SECTION: System Information Setup
#
#   This section defines some of the information reported in
#   the "system" mib group in the mibII tree.

# syslocation: The [typically physical] location of the system.
#   Note that setting this value here means that when trying to
#   perform an snmp SET operation to the sysLocation.0 variable will make
#   the agent return the "notWritable" error code.  IE, including
#   this token in the snmpd.conf file will disable write access to
#   the variable.
#   arguments:  location_string

syslocation  Taiwan

# syscontact: The contact information for the administrator
#   Note that setting this value here means that when trying to
#   perform an snmp SET operation to the sysContact.0 variable will make
#   the agent return the "notWritable" error code.  IE, including
#   this token in the snmpd.conf file will disable write access to
#   the variable.
#   arguments:  contact_string

syscontact  XXXXXXXXXXX@gmail.com

###########################################################################
# SECTION: Access Control Setup
#
#   This section defines who is allowed to talk to your running
#   snmp agent.

# rouser: a SNMPv3 read-only user
#   arguments:  user [noauth|auth|priv] [restriction_oid]
createUser yuyan MD5 "987654321" DES "123456789"
createUser wyuyan MD5 "987654321" DES "123456789"
rouser  yuyan
rwuser  wyuyan

# rocommunity: a SNMPv1/SNMPv2c read-only access community name
#   arguments:  community [default|hostname|network/bits] [oid]

rocommunity  ezio
rwcommunity  wezio

# 可以指定你的 agent 要開甚麼 port,監聽哪張網卡的IP選0.0.0.0就是都監聽。
agentAddress udp:0.0.0.0:1611

# extend 作用就是當管理端用snmpget 詢問到你指定的 oid 你可以做一些script 的動作
extend .1.3.6.1.4.1.2021.999 ezio "echo 123456" 78910

# exec
exec .1.3.6.1.4.1.2021.51 ps /bin/ps
exec .1.3.6.1.4.1.2021.52 script /bin/sh /tmp/ca_check.sh

#表示本服務是master,要讓 subagent 連線,我們將port開在1610並且用tcp的方式
master agentx
agentxsocket tcp:localhost:1610

2. snmpd 執行

Finish configure and save, then start the snmpd.

Ex:

#at /usr/local/net-snmp/sbin
$sudo ./snmpd -c ../share/snmp/snmpd.conf
#or
$sudo ./snmpd -c ../share/snmp/snmpd.conf  -f -Le -d
#or
$sudo ./snmpd -c ../share/snmp/snmpd.conf  -f -Le -Dread_config

#snmpd 會掛在背景,用netstat -aunt 檢查udp:1611 跟 tcp:1610 port有沒有監聽成功

'小技巧:可以使用snmpd -f -Le -Dread_config 命令來查看日誌文件信息,排錯。

snmpd命令的有用選項:

-c FILE                指定文件為配置文件
-C                     不讀取默認的配置文件
-d                     dump接收和發送SNMP數據包
-D TOKEN               對於給定的TOKEN(標誌)打開調試信息   ( -Dmib_init)
-I [-]INITLIST         對於要初始化的MIB列表顯示
-M DIRLIST             指定MIB庫的路徑
-V                     顯示詳細信息
-Le                    把錯誤信息輸出到日誌中
-Lf FILE               把錯誤信息輸出到指定文件中
-m MIBLIST             use MIBLIST instead of the default MIB list'

$ netstat -aunt
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
(略)...
tcp        0      0 127.0.0.1:1610          0.0.0.0:*               LISTEN
(略)...
udp        0      0 0.0.0.0:1611            0.0.0.0:*

#用 snmpget 測試 snmpd
$

二、SNMP 應用程式開發

0. Folder Structure

$tree -d
├── build (建置PC程式)
├── arm-build (建置arm程式)
├── include(header)
├── lib(library)
├── ref(參考範例、內有makefile參考)
└── src(source code)
CMakeLists.txt
toolchain.cmake

1. CMakeLists.txt 撰寫

Source Link:

# CMakeLists.txt
cmake_minimum_required(VERSION 2.8)

# use folder name as project name
get_filename_component(ProjectId ${CMAKE_CURRENT_SOURCE_DIR} NAME)
string(REPLACE " " "_" ProjectId ${ProjectId})
project(${ProjectId})

set(CMAKE_BUILE_TYPE DEBUG)
set(CMAKE_C_FLAGS_DEBUG   "-O0 -g -Wall" )      # Debug not optimize
set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG " )     # release optimeze

set(CMAKE_CXX_FLAGS_DEBUG   "-O0 -g -Wall" )    # Debug not optimize
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG " )   # release optimeze

#set(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_LIST_DIR}")
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}")

message(STATUS "Project: ${ProjectId}")
message(STATUS "Project Directory: ${PROJECT_SOURCE_DIR}")
message(STATUS "Source Directory: ${CMAKE_CURRENT_LIST_DIR}/src")
message(STATUS "Output Directory: ${CMAKE_CURRENT_BINARY_DIR}")

# source code
aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/src DIR_SRC)

# include
include_directories(${CMAKE_CURRENT_LIST_DIR}/include /usr/local/net-snmp/include)

# library ${CMAKE_CURRENT_LIST_DIR}/lib
link_directories(/usr/local/net-snmp/lib)

# build
message(STATUS "Source Files: ${DIR_SRC}")
add_executable(${PROJECT_NAME}.out ${DIR_SRC})
target_link_libraries(${PROJECT_NAME}.out -lnetsnmpmibs -lnetsnmpagent -lnetsnmp -lnetsnmpmibs -lnetsnmpagent -lnetsnmp -ldl -lm)

2. toolchain.cmake 撰寫

這個檔案是方便做交叉編譯時使用。

Source Link:

3. Makefile 撰寫(可選)

如果不想要使用 cmake 可以參考本 makefile 的範例,只是沒有 cmake 封裝的那麼好就是了,但也算寫的簡潔明瞭。撰寫 makefile 在於要知道 net-snmp 的 include 和 library 在哪些位置。和要鏈結哪些 lib。

TARGET=XXXXXXXXXXX.out

CC=gcc
SRCS=$(wildcard *.c)
HEADS=$(shell find ./include -type f -name *.h)
OBJS=$(SRCS:%.c=%.o)

INCLUDES=/usr/local/net-snmp/include/
CFLAGS=-g -O2 -Wall -I$(INCLUDES)
LDFLAGS=-lnetsnmpmibs -lnetsnmpagent -lnetsnmp -lnetsnmpmibs -ldl  -lnetsnmpagent -lnetsnmp -lm
LIBS=-L/usr/local/net-snmp/lib

all: $(OBJS)
    $(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LIBS) $(LDFLAGS)
%.o: %.cpp
    $(CC) $(CFLAGS) -c $^ -o $@

.PHONY: clean
clean:
    rm -rf *.o *.out
run:
    ./$(TARGET)
tags:
    ctags -R -f ./.tags --c++-kinds=+p --fields=+iaS --extra=+q $(INCLUDES)

4. subagent code

subagent 的作用就是可以掛在你自己那端的程式,方便擴充 mibs,好處就是說程式不會跟 snmpd 綁在一起,也就是自己寫的程式 crash 還是能確保管理端能夠找到此設備。subagent 會內建 tcp 連線 snmpd。

Source link:

以上就是 only read oid(.1.3.6.1.4.1.16535.1.1.0)跟 write/read oid(.1.3.6.1.4.1.16536.1.1.0)被觸發時,會 call function 的基本代碼,另外官網也有提供,純量(scalar)的 oid 唯讀,詳情請洽官網教學頁面。

make 之後會產生 snmp-subagent.out,直接執行即可。如果想執行在背景可以將 main()裡面的 dont_fork 參數改成 0,他會以 daemon 的方式執行。


5. snmp-command code

If the master agent and subagent get ready, we will write a code to try whether service is working.

In addition, snmp-command includes snmpget、snmpset、finding snmp device by using broadcast functions.

Source link:

There are three following functions to mainly use.

// file:snmp_tool.h
int ysnmp_broadcast(struct snmp_session *ss, const char *intoid, char *host_ip);
int ysnmp_setInt(struct snmp_session *ss, const char *intoid, char *val);
int ysnmp_getInt(struct snmp_session *ss, const char *intoid, char *val);

  轉載請註明: YuYan's blog Ubuntu 開發 net-snmp

  目錄