主要是接收并处理snmp客户端发送控制命令:启动/停止单个节目的录制。也就是实现snmp的SET命令。
1.还是从MIB开始。
由于只是一个简单的起停命令,前面定义的recordStatusTable中的Status字段完全满足要求,我们只需要给它设置一个不同的值就可以了。
之前在文件"/usr/local/share/snmp/mibs/FIGURE-IT-MIB.txt"中给它定义的访问属性是:“read-only”,将它改成“read-write”就OK了。
2.生成代码,与之前完全相同,就不多说了。
3.由于包含有“read-write”属性的IOD,生成的代码就多了些处理动作。我们在处理函数recordStatusTable_handler()的“case MODE_SET_ACTION”如下实现:
1 for (request = requests; request; request = request->next)
2 {
3 table_entry = (struct recordStatusTable_entry *)netsnmp_extract_iterator_context(request);
4 table_info = netsnmp_extract_table_info(request);
5 switch (table_info->colnum)
6 {
7 case COLUMN_STATUS:
8 memcpy(table_entry->old_Status,
9 table_entry->Status,
10 sizeof (table_entry->Status));
11 table_entry->old_Status_len =
12 table_entry->Status_len;
13 memset(table_entry->Status, 0,
14 sizeof (table_entry->Status));
15 memcpy(table_entry->Status,
16 request->requestvb->val.string,
17 request->requestvb->val_len);
18 table_entry->Status_len =
19 request->requestvb->val_len;
20
21 //在此响应设置命令
22 LOG(LOG_TYPE_NOTICE, "RECV SNMP CMD[SET]: rule[%ld]:%s\n", table_entry->Index, table_entry->Status);
23 if (g_pRecordCfg != NULL)
24 {
25 if(strcasecmp(table_entry->Status, "stop") == 0)
26 {
27 g_pRecordCfg->StartChannel(table_entry->Index);
28 }
29 else if(strcasecmp(table_entry->Status, "start") == 0)
30 {
31 g_pRecordCfg->StopChannel(table_entry->Index);
32 }
33 }
34 break;
35 }
36 }
37 break;
4.修改配置文件,/usr/local/share/snmp/Record.conf,确保里面类似有如下一行:
rwcommunity public
这个“public”可以定义成自己想要的其他名称,但一定要是rwcommunity,表示赋予读写权限。
更多的,参见FAQ的“How do I configure access control?”
5.编译程序,使用snmpset发送测试命令:
snmpset -v 1 -c public localhost FIGURE-IT-MIB::recordStatusTable.recordStatusEntry.Status.3 s stop
简单解释一下,-v 1:表示使用snmp v1命令
-c public localhost :表示"public"就是上面定义的名称。
FIGURE-IT-MIB::recordStatusTable.recordStatusEntry.Status 就是OID
3:表示设置index=3的行中的Status列
s:要设置值的类型
stop:就是具体的值了。
可以看到程序输出:
2012-03-30 14:32:26,826: NOTICE : RECV SNMP CMD[SET]: rule[3]:stop
说明就Ok了。
6.snmp到此告一段落了。一点体会:snmp虽然叫简单网管协议,可协议本身真的不简单!