1 #include <net-snmp/net-snmp-config.h>
2 #include <net-snmp/net-snmp-includes.h>
3 #include <net-snmp/agent/net-snmp-agent-includes.h>
4 #include <net-snmp/agent/net-snmp-agent-includes.h>
5 #include <net-snmp/agent/table_container.h>
6 #include <net-snmp/agent/agent_sysORTable.h>
7 #include <net-snmp/agent/sysORTable.h>
8
9 #include "sysORTable.h"
10 #include "system_mib.h"
11
12 #include <net-snmp/net-snmp-features.h>
13
14 netsnmp_feature_require(table_container);
15
16
17 /** Typical data structure for a row entry */
18 typedef struct sysORTable_entry_s {
19 netsnmp_index oid_index;
20 oid sysORIndex;
21 const struct sysORTable* data;
22 } sysORTable_entry;
23
24 /*
25 * column number definitions for table sysORTable
26 */
27 #define COLUMN_SYSORINDEX 1
28 #define COLUMN_SYSORID 2
29 #define COLUMN_SYSORDESCR 3
30 #define COLUMN_SYSORUPTIME 4
31
32 static netsnmp_container *table = NULL;
33 static u_long sysORLastChange;
34 static oid sysORNextIndex = 1;
35
36 /** create a new row in the table */
37 static void
register_foreach(const struct sysORTable * data,void * dummy)38 register_foreach(const struct sysORTable* data, void* dummy)
39 {
40 sysORTable_entry *entry;
41
42 sysORLastChange = data->OR_uptime;
43
44 entry = SNMP_MALLOC_TYPEDEF(sysORTable_entry);
45 if (!entry) {
46 snmp_log(LOG_ERR,
47 "could not allocate storage, sysORTable is inconsistent\n");
48 } else {
49 const oid firstNext = sysORNextIndex;
50 netsnmp_iterator* it = CONTAINER_ITERATOR(table);
51
52 do {
53 const sysORTable_entry* value;
54 const oid cur = sysORNextIndex;
55
56 if (sysORNextIndex == SNMP_MIN(MAX_SUBID, 2147483647UL))
57 sysORNextIndex = 1;
58 else
59 ++sysORNextIndex;
60
61 for (value = (sysORTable_entry*)it->curr(it);
62 value && value->sysORIndex < cur;
63 value = (sysORTable_entry*)ITERATOR_NEXT(it)) {
64 }
65
66 if (value && value->sysORIndex == cur) {
67 if (sysORNextIndex < cur)
68 it->reset(it);
69 } else {
70 entry->sysORIndex = cur;
71 break;
72 }
73 } while (firstNext != sysORNextIndex);
74
75 ITERATOR_RELEASE(it);
76
77 if(firstNext == sysORNextIndex) {
78 snmp_log(LOG_ERR, "Failed to locate a free index in sysORTable\n");
79 free(entry);
80 } else {
81 entry->data = data;
82 entry->oid_index.len = 1;
83 entry->oid_index.oids = &entry->sysORIndex;
84
85 CONTAINER_INSERT(table, entry);
86 }
87 }
88 }
89
90 static int
register_cb(int major,int minor,void * serv,void * client)91 register_cb(int major, int minor, void* serv, void* client)
92 {
93 DEBUGMSGTL(("mibII/sysORTable/register_cb",
94 "register_cb(%d, %d, %p, %p)\n", major, minor, serv, client));
95 register_foreach((struct sysORTable*)serv, NULL);
96 return SNMP_ERR_NOERROR;
97 }
98
99 /** remove a row from the table */
100 static int
unregister_cb(int major,int minor,void * serv,void * client)101 unregister_cb(int major, int minor, void* serv, void* client)
102 {
103 sysORTable_entry *value;
104 netsnmp_iterator* it = CONTAINER_ITERATOR(table);
105
106 DEBUGMSGTL(("mibII/sysORTable/unregister_cb",
107 "unregister_cb(%d, %d, %p, %p)\n", major, minor, serv, client));
108 sysORLastChange = ((struct sysORTable*)(serv))->OR_uptime;
109
110 while ((value = (sysORTable_entry*)ITERATOR_NEXT(it)) && value->data != serv);
111 ITERATOR_RELEASE(it);
112 if(value) {
113 CONTAINER_REMOVE(table, value);
114 free(value);
115 }
116 return SNMP_ERR_NOERROR;
117 }
118
119 /** handles requests for the sysORTable table */
120 static int
sysORTable_handler(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * reqinfo,netsnmp_request_info * requests)121 sysORTable_handler(netsnmp_mib_handler *handler,
122 netsnmp_handler_registration *reginfo,
123 netsnmp_agent_request_info *reqinfo,
124 netsnmp_request_info *requests)
125 {
126 netsnmp_request_info *request;
127
128 DEBUGMSGTL(("mibII/sysORTable/sysORTable_handler",
129 "sysORTable_handler called\n"));
130
131 if (reqinfo->mode != MODE_GET) {
132 snmp_log(LOG_ERR,
133 "Got unexpected operation for sysORTable\n");
134 return SNMP_ERR_GENERR;
135 }
136
137 /*
138 * Read-support (also covers GetNext requests)
139 */
140 request = requests;
141 while(request && request->processed)
142 request = request->next;
143 while(request) {
144 sysORTable_entry *table_entry;
145 netsnmp_table_request_info *table_info;
146
147 if (NULL == (table_info = netsnmp_extract_table_info(request))) {
148 snmp_log(LOG_ERR,
149 "could not extract table info for sysORTable\n");
150 snmp_set_var_typed_value(
151 request->requestvb, SNMP_ERR_GENERR, NULL, 0);
152 } else if(NULL == (table_entry = (sysORTable_entry *)
153 netsnmp_container_table_extract_context(request))) {
154 switch (table_info->colnum) {
155 case COLUMN_SYSORID:
156 case COLUMN_SYSORDESCR:
157 case COLUMN_SYSORUPTIME:
158 netsnmp_set_request_error(reqinfo, request,
159 SNMP_NOSUCHINSTANCE);
160 break;
161 default:
162 netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
163 break;
164 }
165 } else {
166 switch (table_info->colnum) {
167 case COLUMN_SYSORID:
168 snmp_set_var_typed_value(
169 request->requestvb, ASN_OBJECT_ID,
170 (const u_char*)table_entry->data->OR_oid,
171 table_entry->data->OR_oidlen * sizeof(oid));
172 break;
173 case COLUMN_SYSORDESCR:
174 snmp_set_var_typed_value(
175 request->requestvb, ASN_OCTET_STR,
176 (const u_char*)table_entry->data->OR_descr,
177 strlen(table_entry->data->OR_descr));
178 break;
179 case COLUMN_SYSORUPTIME:
180 snmp_set_var_typed_integer(
181 request->requestvb, ASN_TIMETICKS,
182 table_entry->data->OR_uptime);
183 break;
184 default:
185 netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
186 break;
187 }
188 }
189 do {
190 request = request->next;
191 } while(request && request->processed);
192 }
193 return SNMP_ERR_NOERROR;
194 }
195
196 static netsnmp_handler_registration *sysORLastChange_reg;
197 static netsnmp_watcher_info sysORLastChange_winfo;
198 static netsnmp_handler_registration *sysORTable_reg;
199 static netsnmp_table_registration_info *sysORTable_table_info;
200
201 /** Initializes the sysORTable module */
202 void
init_sysORTable(void)203 init_sysORTable(void)
204 {
205 const oid sysORLastChange_oid[] = { 1, 3, 6, 1, 2, 1, 1, 8 };
206 const oid sysORTable_oid[] = { 1, 3, 6, 1, 2, 1, 1, 9 };
207
208 sysORTable_table_info =
209 SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
210
211 table = netsnmp_container_find("sysORTable:table_container");
212
213 if (sysORTable_table_info == NULL || table == NULL) {
214 SNMP_FREE(sysORTable_table_info);
215 CONTAINER_FREE(table);
216 return;
217 }
218 table->container_name = strdup("sysORTable");
219
220 netsnmp_table_helper_add_indexes(sysORTable_table_info,
221 ASN_INTEGER, /** index: sysORIndex */
222 0);
223 sysORTable_table_info->min_column = COLUMN_SYSORID;
224 sysORTable_table_info->max_column = COLUMN_SYSORUPTIME;
225
226 sysORLastChange_reg =
227 netsnmp_create_handler_registration(
228 "mibII/sysORLastChange", NULL,
229 sysORLastChange_oid, OID_LENGTH(sysORLastChange_oid),
230 HANDLER_CAN_RONLY);
231 netsnmp_init_watcher_info(
232 &sysORLastChange_winfo,
233 &sysORLastChange, sizeof(u_long),
234 ASN_TIMETICKS, WATCHER_FIXED_SIZE);
235 netsnmp_register_watched_scalar(sysORLastChange_reg,
236 &sysORLastChange_winfo);
237
238 sysORTable_reg =
239 netsnmp_create_handler_registration(
240 "mibII/sysORTable", sysORTable_handler,
241 sysORTable_oid, OID_LENGTH(sysORTable_oid), HANDLER_CAN_RONLY);
242 netsnmp_container_table_register(sysORTable_reg, sysORTable_table_info,
243 table, TABLE_CONTAINER_KEY_NETSNMP_INDEX);
244
245 sysORLastChange = netsnmp_get_agent_uptime();
246
247 /*
248 * Initialise the contents of the table here
249 */
250 netsnmp_sysORTable_foreach(®ister_foreach, NULL);
251
252 /*
253 * Register callbacks
254 */
255 snmp_register_callback(SNMP_CALLBACK_APPLICATION,
256 SNMPD_CALLBACK_REG_SYSOR, register_cb, NULL);
257 snmp_register_callback(SNMP_CALLBACK_APPLICATION,
258 SNMPD_CALLBACK_UNREG_SYSOR, unregister_cb, NULL);
259
260 #ifdef USING_MIBII_SYSTEM_MIB_MODULE
261 if (++system_module_count == 3)
262 REGISTER_SYSOR_TABLE(system_module_oid, system_module_oid_len,
263 "The MIB module for SNMPv2 entities");
264 #endif
265 }
266
267 void
shutdown_sysORTable(void)268 shutdown_sysORTable(void)
269 {
270 #ifdef USING_MIBII_SYSTEM_MIB_MODULE
271 if (system_module_count-- == 3)
272 UNREGISTER_SYSOR_TABLE(system_module_oid, system_module_oid_len);
273 #endif
274
275 snmp_unregister_callback(SNMP_CALLBACK_APPLICATION,
276 SNMPD_CALLBACK_UNREG_SYSOR, unregister_cb, NULL,
277 1);
278 snmp_unregister_callback(SNMP_CALLBACK_APPLICATION,
279 SNMPD_CALLBACK_REG_SYSOR, register_cb, NULL, 1);
280
281 if (table)
282 CONTAINER_CLEAR(table, netsnmp_container_simple_free, NULL);
283 netsnmp_container_table_unregister(sysORTable_reg);
284 sysORTable_reg = NULL;
285 table = NULL;
286 netsnmp_table_registration_info_free(sysORTable_table_info);
287 sysORTable_table_info = NULL;
288 netsnmp_unregister_handler(sysORLastChange_reg);
289 sysORLastChange_reg = NULL;
290 }
291