NetSnmp初步(一):讓我們的程序提供snmp服務


錄制程序要提供遠程控制功能,大概需求為:

(1)可以查詢程序當前的運行狀態:錄制了多少路節目,每路節目的狀態,數據碼率 等等;

(2)可以遠程控制節目的起停,也就是發一個命令,就可以停掉某一路節目;

(3)異常情況,主動上報。 

上頭決定使用snmp來實現。這幾天研究了一下,做點筆記。 

 

閑話休敘,開工干活:

1.去netsnmp官網下載最新版本,我下的是5.7.1源碼。

2.解壓到任意目錄,然后configure,make, sudo make install三步曲搞定。
(在我的ubuntu10.10上,需要安裝libperl-dev,否則make時會連接失敗。)

3.配置net-snmp,讓它跑起來。
(1)關於net-snmp的詳細配置,可以參看系統手冊頁。(強烈建議先看!!!了解一下snmp的配置)。
#man snmp_config
#man snmp.conf
#man snmpd.conf
(2)#sudo snmpd
(最好使用sudo啟動snmpd,否則默認情況下沒有權限,會啟動失敗退出,而又沒有任何打印信息)

4.添加MIB文件
(1)寫MIB文件(暫時使用已有的,文件名FIGURE-IT-MIB.txt)
(2)首先,將MIB文件拷到snmp的mibs目錄下,有兩種方式:
#cp FIGURE-IT-MIB.txt /usr/local/share/snmp/mibs
(which makes it available to everyone on the system)
or
#mkdir $HOME/.snmp
#mkdir $HOME/.snmp/mibs
#cp MY-MIB.txt $HOME/.snmp/mibs
(which makes it available to you only)
具體可參看:http://www.net-snmp.org/docs/FAQ.html#How_do_I_add_a_MIB_
(3)加載mib庫:
#vi /usr/local/share/snmp/snmp.conf
(4)檢查mib是否正常加載:
# snmptranslate -IR -Tp record
+--record(1)
|
+--recordStatusTable(1)
|
+--recordStatusEntry(1)
| Index: recordIndex
|
+-- -R-- INTEGER recordIndex(1)
| Range: 0..65535
+-- -R-- String recordChannelName(2)
| Size: 0..256
+-- -R-- String recordFileName(3)
| Size: 0..256
+-- -R-- IpAddr recordDeviceIp(4)
+-- -R-- String recordChannelStatus(5)
| Size: 1..256
+-- -RW- EnumVal recordChannelOp(6)
Textual Convention: RowStatus
Values: active(1), notInService(2), notReady(3), createAndGo(4), createAndWait(5), destroy(6)

4.使用mib2c生成代碼:
#sudo mib2c -c mib2c.iterate.conf FIGURE-IT-MIB::recordStatusTable
(1)通過-c mib2c.iterate.conf 指定使用的模板名,模板位於:“/usr/local/share/snmp”下。
(2)由於我在FIGURE-IT-MIB.txt中使用的table類型的,所以在這里指定“mib2c.iterate.conf”,其實也可使用“mib2c.mfd.conf”模板,但我在編譯時出現錯誤:
“ERROR: unknown node.decl: in_addr_t
exiting at conf file (/usr/local/share/snmp/mib2c-data/node-get.m2i:91) request”
在net-snmp的郵件列表中,有人說是Bug,修改一行代碼就OK,我沒試。
"http://sourceforge.net/mailarchive/forum.php?thread_name=20120227102423.5dcb9663%40freesnmp.com&forum_name=net-snmp-coders"
(3)mib2c提示生成的代碼是否帶數據緩存,緩存主要是減少snmp客戶端頻繁訪問數據時真正獲取數據的次數,提高性能用的。如果在很短的時間內獲取相同的數據,就直接返回緩存的數據,而不需要每次去更新數據。這里我選擇生成帶緩存的代碼。
(4)編譯成功后,就會在當前目錄下生成兩個文件:
recordStatusTable.c和recordStatusTable.h
(5)生成的源文件是有語法錯誤的,一個個修改掉就ok了。
(6)在生成的代碼中,大部分工作已近完成了,我們需要做的就是獲取、維護返回給snmp客戶端的數據。我們需要關注下面幾個函數:
1)這數據是通過一個鏈表維護的,鏈表的插入、銷毀分別是通過recordStatusTable_createEntry()、recordStatusTable_removeEntry()函數完成的(根據表名,實際的函數名會不一樣,但是以_createEntry和_removeEntry結尾的函數,下同)。
2)recordStatusTable_load(),當接收到snmp請求時,如果緩存的數據已超時,就會調用該函數來更新數據;否則,將直接使用緩存數據。我們需要在該函數里給緩存數據賦值。
我的示例如下:

 1 int recordStatusTable_load(netsnmp_cache *cache, void *vmagic)
2 {
3 if(g_pRecordCfg == NULL)
4 {
5 return -1;
6 }
7
8 for(unsigned int i=0; i<g_pRecordCfg->m_pRecordModules.size(); i++)
9 {
10 CRecordRule* pRule = g_pRecordCfg->m_pRecordModules[i]->m_pRecordRule;
11 IChannel* pChan = g_pRecordCfg->m_pRecordModules[i]->m_pChannel;
12 IInput* pInput = g_pRecordCfg->m_pRecordModules[i]->m_pInput;
13 IOutput* pOutput = g_pRecordCfg->m_pRecordModules[i]->m_pOutput;
14 if((pRule == NULL) || (pChan == NULL) || (pInput == NULL) || (pOutput == NULL))
15 {
16 return -1;
17 }
18
19 string strChannelName = "[" + CSourceRule::GetSourceType(pChan->m_enmSourceType) + "]" + pChan->m_strName;
20 string strFileName = pOutput->CurrentFile();
21 string strInputRate = pInput->m_pStatistics->Info();
22 string strOutputRate = pOutput->m_pStatistics->Info();
23 string strStatus = g_pRecordCfg->m_pRecordModules[i]->Status();
24
25 struct recordStatusTable_entry * pEntery = recordStatusTable_createEntry(pRule->m_nRuleID);
26 strcpy(pEntery->ChannelName, strChannelName.c_str());
27 pEntery->ChannelName_len = strlen(strChannelName.c_str());
28 pEntery->DeviceIp = inet_addr(pChan->m_strDeviceIP.c_str());
29 strcpy(pEntery->FileName, strFileName.c_str());
30 pEntery->FileName_len = strlen(strFileName.c_str());
31 strcpy(pEntery->InputRate, strInputRate.c_str());
32 pEntery->InputRate_len = strlen(strInputRate.c_str());
33 strcpy(pEntery->OutputRate, strOutputRate.c_str());
34 pEntery->OutputRate_len = strlen(strOutputRate.c_str());
35 strcpy(pEntery->Status, strStatus.c_str());
36 pEntery->Status_len = strlen(strStatus.c_str());
37 }
38
39 return 0;
40 }


3)recordStatusTable_free(),當緩存的數據超時后,系統會自動調用該函數將緩存釋放掉;但並不會主動調用recordStatusTable_load()來更新數據,除非收到新的snmp數據請求。可以不用關注。


5.將生成的recordStatusTable.c和recordStatusTable.h文件加入到工程中,修改Makefile,添加net-snmp頭文件和庫依賴。
net-snmp的頭文件在源碼目錄下的include目錄下,即<snmp-src>/include;
庫文件一般在/usr/lib下。
#ls /usr/lib |grep libnetsn
libnetsnmpagent.so.15
libnetsnmpagent.so.15.1.2
libnetsnmphelpers.so.15
libnetsnmphelpers.so.15.1.2
libnetsnmpmibs.so.15
libnetsnmpmibs.so.15.1.2
libnetsnmp.so.15
libnetsnmp.so.15.1.2
libnetsnmptrapd.so.15
libnetsnmptrapd.so.15.1.2
在Makefile中添加“-lnetsnmp -lnetsnmpagent -lnetsnmphelpers -lnetsnmptrapd -lnetsnmpmibs”即可。

6.(1)在項目中開啟一個線程,啟動snmp服務。

 1 void CSnmpThread::run()
2 {
3 LOG(LOG_TYPE_NOTICE, "[Thread] CSnmpThread Start.");
4
5 int agentx_subagent=0; /* change this if you want to be a SNMP master agent */
6 int background = 0; /* change this if you want to run in the background */
7 int syslog = 0; /* change this if you want to use syslog */
8
9 //snmp_set_do_debugging(1);
10
11 /* print log errors to syslog or stderr */
12 if (syslog)
13 {
14 snmp_enable_calllog();
15 }
16 else
17 {
18 snmp_enable_stderrlog();
19 }
20
21 /* we're an agentx subagent? */
22 if (agentx_subagent)
23 {
24 /* make us a agentx client. */
25 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, 1);
26 }
27
28 /* run in background, if requested */
29 if (background && netsnmp_daemonize(1, !syslog))
30 {
31 LOG(LOG_TYPE_NOTICE, "netsnmp_daemonize() failed. [Thread] CSnmpThread exit!");
32 return;
33 }
34
35 /* Initialize tcpip, if necessary */
36 SOCK_STARTUP;
37
38 /* Initialize the agent library */
39 init_agent("Record");
40
41 /* Initialize our mib code here */
42 init_recordStatusTable(); // 加載節點信息
43
44 /* initialize vacm/usm access control */
45 // if (!agentx_subagent)
46 // {
47 // void init_vacm_vars();
48 // void init_usmUser();
49 // }
50
51 /* Example-demon will be used to read example-demon.conf files. */
52 init_snmp("Record");// 配置文件名---->/usr/local/share/snmp/Record.conf
53
54 /* If we're going to be a snmp master agent, initial the ports */
55 if (!agentx_subagent)
56 {
57 init_master_agent(); /* open the port to listen on (defaults to udp:161) */
58 }
59
60 /* In case we recevie a request to stop (kill -TERM or kill -INT) */
61 keep_running = 1;
62 //signal(SIGTERM, stop_server);
63 //signal(SIGINT, stop_server);
64
65 LOG(LOG_TYPE_INFO,"snmp service is up and running");
66
67 /* your main loop here... */
68 while(keep_running)
69 {
70 /* if you use select(), see snmp_select_info() in snmp_api(3) */
71 /* --- OR --- */
72 agent_check_and_process(1); /* 0 == don't block */
73 }
74
75 /* at shutdown time */
76 snmp_shutdown("Record");
77 SOCK_CLEANUP;
78 return;
79 }


(2)編寫配置文件Record.conf,放到vi /usr/local/share/snmp/下。

 1 ###############################################################################
2 # Access Control
3 ###############################################################################
4
5 # sec.name source community
6 com2sec local localhost public
7 com2sec mynetwork 192.168.0.0/24 public
8
9 ####
10 # Second, map the security names into group names:
11
12 # sec.model sec.name
13 group MyRWGroup v1 local
14 group MyRWGroup v2c local
15 group MyRWGroup usm local
16 group MyROGroup v1 mynetwork
17 group MyROGroup v2c mynetwork
18 group MyROGroup usm mynetwork
19
20 ####
21 # Third, create a view for us to let the groups have rights to:
22
23 # incl/excl subtree mask
24 view all included .1 80
25
26 ####
27 # Finally, grant the 2 groups access to the 1 view with different
28 # write permissions:
29
30 # context sec.model sec.level match read write notif
31 access MyROGroup "" any noauth exact all none none
32 access MyRWGroup "" any noauth exact all all none
33
34 agentaddress 161

配置文件是從別處拷來的,具體待研究。

7.測試snmp.
(1)編譯程序,sudo后以root權限運行。
否則會報錯:
“Error opening specified endpoint "161"”

(2)snmpwalk -v1 -c public localhost recordStatusTable
如果看到類似如下信息,就說明成功了:

 1 FIGURE-IT-MIB::Index.1 = INTEGER: 1
2 FIGURE-IT-MIB::Index.3 = INTEGER: 3
3 FIGURE-IT-MIB::Index.4 = INTEGER: 4
4 FIGURE-IT-MIB::ChannelName.1 = Hex-STRING: 5B 53 74 72 65 61 6D 54 53 5D E7 A0 81 E6 B5 81
5 5F E9 AD 85 E5 8A 9B E9 9F B3 20 E4 B9 90 E4 B8
6 BB E8 B7 AF
7 FIGURE-IT-MIB::ChannelName.3 = Hex-STRING: 5B 41 75 64 69 6F 50 61 72 61 6D 5D E9 9F B3 E9
8 A2 91 E5 8F 82 E6 95 B0 5F E8 8A 82 E7 9B AE 31
9 FIGURE-IT-MIB::ChannelName.4 = Hex-STRING: 5B 54 65 6D 70 48 75 6D 69 5D E6 B8 A9 E6 B9 BF
10 E5 BA A6 5F E9 80 9A E9 81 93 31
11 FIGURE-IT-MIB::DeviceIp.1 = IpAddress: 10.0.60.2
12 FIGURE-IT-MIB::DeviceIp.3 = IpAddress: 10.0.60.2
13 FIGURE-IT-MIB::DeviceIp.4 = IpAddress: 10.0.60.2
14 FIGURE-IT-MIB::Status.1 = STRING: "[Input]:No Input Data. [Output]:No Input Data."
15 FIGURE-IT-MIB::Status.3 = STRING: "[Input]:No Input Data. [Output]:No Input Data."
16 FIGURE-IT-MIB::Status.4 = STRING: "[Input]:No Input Data. [Output]:No Input Data."
17 FIGURE-IT-MIB::InputRate.1 = STRING: "0(bytes) "
18 FIGURE-IT-MIB::InputRate.3 = STRING: "0"
19 FIGURE-IT-MIB::InputRate.4 = STRING: "0"
20 FIGURE-IT-MIB::OutputRate.1 = STRING: "0(bytes) "
21 FIGURE-IT-MIB::OutputRate.3 = STRING: "0"
22 FIGURE-IT-MIB::OutputRate.4 = STRING: "0"
23 FIGURE-IT-MIB::FileName.1 = Hex-STRING: 2F 66 69 67 75 72 65 2F 52 65 63 6F 72 64 2F 53
24 74 72 65 61 6D 54 53 2F 31 2D 31 2D E7 A0 81 E6
25 B5 81 5F E9 AD 85 E5 8A 9B E9 9F B3 20 E4 B9 90
26 E4 B8 BB E8 B7 AF 2F 32 30 31 32 2D 30 33 2D 32
27 38 2F 32 30 31 32 30 33 32 38 31 36 31 38 30 30
28 2E 74 73
29 FIGURE-IT-MIB::FileName.3 = Hex-STRING: 2F 66 69 67 75 72 65 2F 52 65 63 6F 72 64 2F 41
30 75 64 69 6F 50 61 72 61 6D 2F 35 2D 33 2D E9 9F
31 B3 E9 A2 91 E5 8F 82 E6 95 B0 5F E8 8A 82 E7 9B
32 AE 31 2F 32 30 31 32 2D 30 33 2D 32 38 2F 32 30
33 31 32 30 33 32 38 31 36 31 37 34 31 2E 70 61 72
34 61 6D
35 FIGURE-IT-MIB::FileName.4 = ""
36 End of MIB


(3)有一個問題,snmpwalk似乎不支持中文?都是以ascii碼輸出中文?以后再研究。

8.經實際測試,我們的程序作為agent,可以單獨提供snmp服務,並不需要再啟動snmpd服務。

9.程序出現異常情況需要主動上報,接下來研究Notifications看看(初步看下來,In SNMPv1的TRAPs 似乎足夠了,因為我們不需要receiver的響應,“http://www.net-snmp.org/wiki/index.php/TUT:Configuring_snmptrapd_to_receive_SNMPv3_notifications”)。

 

---------------

你要的優惠券都在這兒了!漏洞價、內購價,便宜的令人發指! 羊毛黨們不可錯過!

https://yangmaocun.cn/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM