繼上篇文章 “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:
- https://github.com/tsaiyuyan/netsnmpProjects/blob/master/snmp-command/CMakeLists.txt
- https://github.com/tsaiyuyan/netsnmpProjects/blob/master/snmp-subagent/CMakeLists.txt
# 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);