Print this page
NEX-18695 libfmd_snmp is unable to handle multiple OIDs in GET request
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Cynthia Eastham <cynthia.eastham@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-17777 snmptable produces bogus output for FM tables
Reviewed by: Cynthia Eastham <cynthia.eastham@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-3125 libfmd_snmp should compile with newer net-snmp
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/fm/libfmd_snmp/common/module.c
+++ new/usr/src/lib/fm/libfmd_snmp/common/module.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 +/*
28 + * Copyright 2018 Nexenta Systems, Inc.
29 + */
30 +
27 31 #include <fm/fmd_adm.h>
28 32 #include <fm/fmd_snmp.h>
33 +
29 34 #include <net-snmp/net-snmp-config.h>
30 35 #include <net-snmp/net-snmp-includes.h>
31 36 #include <net-snmp/agent/net-snmp-agent-includes.h>
32 -#include <pthread.h>
33 -#include <stddef.h>
37 +
34 38 #include <errno.h>
35 39 #include <libuutil.h>
40 +#include <pthread.h>
41 +#include <stddef.h>
42 +
36 43 #include "sunFM_impl.h"
37 44 #include "module.h"
38 45
39 46 static uu_avl_pool_t *mod_name_avl_pool;
40 47 static uu_avl_pool_t *mod_index_avl_pool;
41 48 static uu_avl_t *mod_name_avl;
42 49 static uu_avl_t *mod_index_avl;
43 50
44 51 #define VALID_AVL_STATE (mod_name_avl_pool != NULL && \
45 52 mod_index_avl_pool != NULL && mod_name_avl != NULL && \
46 53 mod_index_avl != NULL)
47 54
48 -#define UPDATE_WAIT_MILLIS 10 /* poll interval in milliseconds */
49 -
50 55 /*
51 56 * Update types. Single-index and all are mutually exclusive.
52 57 */
53 58 #define UCT_INDEX 0x1
54 59 #define UCT_ALL 0x2
55 60 #define UCT_FLAGS 0x3
56 61
57 62 #define MODULE_DATA_VALID(d) ((d)->d_valid == valid_stamp)
58 63
59 -/*
60 - * Locking rules are straightforward. There is only one updater thread
61 - * for each table, and requests for update that are received while
62 - * another update is in progress are ignored. The single per-table lock
63 - * protects all the data for the table, the valid_stamp and max_index
64 - * tags for new data, and - importantly - all the hidden static data
65 - * used by the Net-SNMP library. The result return callbacks are always
66 - * called in the master agent thread; holding the table lock is
67 - * therefore sufficient since only one table's callback can be run at
68 - * any one time. Finer-grained locking is possible here but
69 - * substantially more difficult because nearly all Net-SNMP functions
70 - * are unsafe.
71 - *
72 - * In practice this is more than adequate, since the purpose of
73 - * threading out the update is to prevent excessively time-consuming
74 - * data collection from bottlenecking the entire agent, not to improve
75 - * result throughput (SNMP is not intended to be used for applications
76 - * requiring high throughput anyway). If the agent itself ever becomes
77 - * multithreaded, locking requirements become limited to our local
78 - * per-table data (the tree, max_index, and valid_stamp), and the
79 - * implementation could be revisited for better performance.
80 - */
81 -
82 64 static ulong_t max_index;
83 65 static int valid_stamp;
84 66 static pthread_mutex_t update_lock;
85 -static pthread_cond_t update_cv;
86 -static volatile enum { US_QUIET, US_NEEDED, US_INPROGRESS } update_status;
87 67
88 68 static Netsnmp_Node_Handler sunFmModuleTable_handler;
89 69
90 70 static sunFmModule_data_t *
91 71 key_build(const char *name, const ulong_t index)
92 72 {
93 73 static sunFmModule_data_t key;
94 74
95 75 key.d_index = index;
96 76 if (name)
97 77 (void) strlcpy(key.d_ami_name, name, sizeof (key.d_ami_name));
98 78 else
99 79 key.d_ami_name[0] = '\0';
100 80
101 81 return (&key);
102 82 }
103 83
104 84 /*
105 85 * If name is the name of a module we have previously seen and indexed, return
106 86 * data for it. Otherwise, return NULL. Note that the module may not be
107 87 * valid; that is, it may have been removed from the fault manager since its
108 88 * information was last updated.
109 89 */
110 90 static sunFmModule_data_t *
111 91 module_lookup_name(const char *name)
112 92 {
113 93 sunFmModule_data_t *key;
114 94
115 95 key = key_build(name, 0);
116 96 return (uu_avl_find(mod_name_avl, key, NULL, NULL));
117 97 }
118 98
119 99 /*
120 100 * If index corresponds to a module we have previously seen and indexed, return
121 101 * data for it. Otherwise, return NULL. Note that the module may not be
122 102 * valid; that is, it may have been removed from the fault manager since its
123 103 * information was last updated.
124 104 */
125 105 static sunFmModule_data_t *
126 106 module_lookup_index_exact(const ulong_t index)
127 107 {
128 108 sunFmModule_data_t *key;
129 109
130 110 key = key_build(NULL, index);
131 111 return (uu_avl_find(mod_index_avl, key, NULL, NULL));
132 112 }
133 113
134 114 /*
135 115 * If index corresponds to a valid (that is, extant as of latest information
136 116 * from the fault manager) fmd module, return the data for that module.
137 117 * Otherwise, return the data for the valid module whose index is as close as
138 118 * possible to index but not lower. This preserves the lexicographical
139 119 * ordering required for GETNEXT processing.
140 120 */
141 121 static sunFmModule_data_t *
142 122 module_lookup_index_nextvalid(const ulong_t index)
143 123 {
144 124 sunFmModule_data_t *key, *data;
145 125 uu_avl_index_t idx;
146 126
147 127 key = key_build(NULL, index);
148 128
149 129 if ((data = uu_avl_find(mod_index_avl, key, NULL, &idx)) != NULL &&
150 130 MODULE_DATA_VALID(data))
151 131 return (data);
152 132
153 133 data = uu_avl_nearest_next(mod_index_avl, idx);
154 134
155 135 while (data != NULL && !MODULE_DATA_VALID(data))
156 136 data = uu_avl_next(mod_index_avl, data);
157 137
158 138 return (data);
159 139 }
160 140
161 141 /*
162 142 * Possible update the contents of a single module within the cache. This
163 143 * is our callback from fmd_module_iter.
164 144 */
165 145 static int
166 146 modinfo_update_one(const fmd_adm_modinfo_t *modinfo, void *arg)
167 147 {
168 148 const sunFmModule_update_ctx_t *update_ctx =
169 149 (sunFmModule_update_ctx_t *)arg;
170 150 sunFmModule_data_t *data = module_lookup_name(modinfo->ami_name);
171 151
172 152 /*
173 153 * An fmd module we haven't seen before. We're obligated to index
174 154 * it and link it into our cache so that we can find it, but we're
175 155 * not obligated to fill it in completely unless we're doing a
176 156 * thorough update or this is the module we were asked for. This
177 157 * avoids unnecessary iteration and memory manipulation for data
178 158 * we're not going to return for this request.
179 159 */
180 160 if (data == NULL) {
181 161 uu_avl_index_t idx;
182 162
183 163 DEBUGMSGTL((MODNAME_STR, "found new fmd module %s\n",
184 164 modinfo->ami_name));
185 165 if ((data = SNMP_MALLOC_TYPEDEF(sunFmModule_data_t)) == NULL) {
186 166 (void) snmp_log(LOG_ERR, MODNAME_STR ": Out of memory "
187 167 "for new module data at %s:%d\n", __FILE__,
188 168 __LINE__);
189 169 return (1);
190 170 }
191 171 /*
192 172 * We allocate indices sequentially and never reuse them.
193 173 * This ensures we can always return valid GETNEXT responses
194 174 * without having to reindex, and it provides the user a
195 175 * more consistent view of the fault manager.
196 176 */
197 177 data->d_index = ++max_index;
198 178 DEBUGMSGTL((MODNAME_STR, "index %lu is %s@%p\n", data->d_index,
199 179 modinfo->ami_name, data));
200 180
201 181 (void) strlcpy(data->d_ami_name, modinfo->ami_name,
202 182 sizeof (data->d_ami_name));
203 183
204 184 uu_avl_node_init(data, &data->d_name_avl, mod_name_avl_pool);
205 185 (void) uu_avl_find(mod_name_avl, data, NULL, &idx);
206 186 uu_avl_insert(mod_name_avl, data, idx);
207 187
208 188 uu_avl_node_init(data, &data->d_index_avl, mod_index_avl_pool);
209 189 (void) uu_avl_find(mod_index_avl, data, NULL, &idx);
210 190 uu_avl_insert(mod_index_avl, data, idx);
211 191
212 192 DEBUGMSGTL((MODNAME_STR, "completed new module %lu/%s@%p\n",
213 193 data->d_index, data->d_ami_name, data));
214 194 }
215 195
216 196 data->d_valid = valid_stamp;
217 197
218 198 DEBUGMSGTL((MODNAME_STR, "timestamp updated for %lu/%s@%p: %d\n",
219 199 data->d_index, data->d_ami_name, data, data->d_valid));
220 200
221 201 if ((update_ctx->uc_type & UCT_ALL) ||
222 202 update_ctx->uc_index == data->d_index) {
223 203 (void) strlcpy(data->d_ami_vers, modinfo->ami_vers,
224 204 sizeof (data->d_ami_vers));
225 205 (void) strlcpy(data->d_ami_desc, modinfo->ami_desc,
226 206 sizeof (data->d_ami_desc));
227 207 data->d_ami_flags = modinfo->ami_flags;
228 208 }
229 209
230 210 return (!(update_ctx->uc_type & UCT_ALL) &&
231 211 update_ctx->uc_index == data->d_index);
232 212 }
233 213
234 214 /*
235 215 * Update some or all module data from fmd. If thorough is set, all modules
236 216 * will be indexed and their data cached. Otherwise, updates will stop once
237 217 * the module matching index has been updated.
238 218 *
239 219 * Returns appropriate SNMP error codes.
240 220 */
241 221 static int
242 222 modinfo_update(sunFmModule_update_ctx_t *update_ctx)
243 223 {
244 224 fmd_adm_t *adm;
245 225
246 226 ASSERT(update_ctx != NULL);
247 227 ASSERT((update_ctx->uc_type & (UCT_INDEX|UCT_ALL)) !=
248 228 (UCT_INDEX|UCT_ALL));
249 229 ASSERT((update_ctx->uc_type & ~UCT_FLAGS) == 0);
250 230 ASSERT(VALID_AVL_STATE);
251 231
252 232 if ((adm = fmd_adm_open(update_ctx->uc_host, update_ctx->uc_prog,
253 233 update_ctx->uc_version)) == NULL) {
254 234 (void) snmp_log(LOG_ERR, MODNAME_STR ": Communication with fmd "
255 235 "failed: %s\n", strerror(errno));
256 236 return (SNMP_ERR_RESOURCEUNAVAILABLE);
257 237 }
258 238
259 239 ++valid_stamp;
260 240 if (fmd_adm_module_iter(adm, modinfo_update_one, update_ctx) != 0) {
261 241 (void) snmp_log(LOG_ERR, MODNAME_STR ": fmd module information "
262 242 "update failed: %s\n", fmd_adm_errmsg(adm));
|
↓ open down ↓ |
166 lines elided |
↑ open up ↑ |
263 243 fmd_adm_close(adm);
264 244 return (SNMP_ERR_RESOURCEUNAVAILABLE);
265 245 }
266 246
267 247 DEBUGMSGTL((MODNAME_STR, "module iteration completed\n"));
268 248
269 249 fmd_adm_close(adm);
270 250 return (SNMP_ERR_NOERROR);
271 251 }
272 252
273 -/*ARGSUSED*/
274 253 static void
275 -update_thread(void *arg)
254 +request_update(void)
276 255 {
256 + sunFmModule_update_ctx_t uc;
257 +
277 258 /*
278 259 * The current modinfo_update implementation offers minimal savings
279 260 * for the use of index-only updates; therefore we always do a full
280 261 * update. If it becomes advantageous to limit updates to a single
281 262 * index, the contexts can be queued by the handler instead.
282 263 */
283 - sunFmModule_update_ctx_t uc;
284 -
285 264 uc.uc_host = NULL;
286 265 uc.uc_prog = FMD_ADM_PROGRAM;
287 266 uc.uc_version = FMD_ADM_VERSION;
288 -
289 267 uc.uc_index = 0;
290 268 uc.uc_type = UCT_ALL;
291 269
292 - for (;;) {
293 - (void) pthread_mutex_lock(&update_lock);
294 - update_status = US_QUIET;
295 - while (update_status == US_QUIET)
296 - (void) pthread_cond_wait(&update_cv, &update_lock);
297 - update_status = US_INPROGRESS;
298 - (void) pthread_mutex_unlock(&update_lock);
299 - (void) modinfo_update(&uc);
300 - }
270 + (void) modinfo_update(&uc);
301 271 }
302 272
303 -static void
304 -request_update(void)
305 -{
306 - (void) pthread_mutex_lock(&update_lock);
307 - if (update_status != US_QUIET) {
308 - (void) pthread_mutex_unlock(&update_lock);
309 - return;
310 - }
311 - update_status = US_NEEDED;
312 - (void) pthread_cond_signal(&update_cv);
313 - (void) pthread_mutex_unlock(&update_lock);
314 -}
315 -
316 273 /*ARGSUSED*/
317 274 static int
318 275 module_compare_name(const void *l, const void *r, void *private)
319 276 {
320 277 sunFmModule_data_t *l_data = (sunFmModule_data_t *)l;
321 278 sunFmModule_data_t *r_data = (sunFmModule_data_t *)r;
322 279
323 280 ASSERT(l_data != NULL && r_data != NULL);
324 281
325 282 return (strcmp(l_data->d_ami_name, r_data->d_ami_name));
326 283 }
327 284
328 285 /*ARGSUSED*/
329 286 static int
330 287 module_compare_index(const void *l, const void *r, void *private)
331 288 {
332 289 sunFmModule_data_t *l_data = (sunFmModule_data_t *)l;
333 290 sunFmModule_data_t *r_data = (sunFmModule_data_t *)r;
334 291
335 292 ASSERT(l_data != NULL && r_data != NULL);
336 293
337 294 return (l_data->d_index < r_data->d_index ? -1 :
338 295 l_data->d_index > r_data->d_index ? 1 : 0);
339 296 }
340 297
341 298 int
342 299 sunFmModuleTable_init(void)
343 300 {
|
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
344 301 static oid sunFmModuleTable_oid[] = { SUNFMMODULETABLE_OID };
345 302 netsnmp_table_registration_info *table_info;
346 303 netsnmp_handler_registration *handler;
347 304 int err;
348 305
349 306 if ((err = pthread_mutex_init(&update_lock, NULL)) != 0) {
350 307 (void) snmp_log(LOG_ERR, MODNAME_STR ": mutex_init failure: "
351 308 "%s\n", strerror(err));
352 309 return (MIB_REGISTRATION_FAILED);
353 310 }
354 - if ((err = pthread_cond_init(&update_cv, NULL)) != 0) {
355 - (void) snmp_log(LOG_ERR, MODNAME_STR ": cond_init failure: "
356 - "%s\n", strerror(err));
357 - return (MIB_REGISTRATION_FAILED);
358 - }
359 311
360 - if ((err = pthread_create(NULL, NULL, (void *(*)(void *))update_thread,
361 - NULL)) != 0) {
362 - (void) snmp_log(LOG_ERR, MODNAME_STR ": error creating update "
363 - "thread: %s\n", strerror(err));
364 - return (MIB_REGISTRATION_FAILED);
365 - }
366 -
367 312 if ((table_info =
368 313 SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info)) == NULL)
369 314 return (MIB_REGISTRATION_FAILED);
370 315
371 316 if ((handler = netsnmp_create_handler_registration("sunFmModuleTable",
372 317 sunFmModuleTable_handler, sunFmModuleTable_oid,
373 318 OID_LENGTH(sunFmModuleTable_oid), HANDLER_CAN_RONLY)) == NULL) {
374 319 SNMP_FREE(table_info);
375 320 return (MIB_REGISTRATION_FAILED);
376 321 }
377 322
378 323 /*
379 324 * The Net-SNMP template uses add_indexes here, but that
380 325 * function is unsafe because it does not check for failure.
381 326 */
382 327 if (netsnmp_table_helper_add_index(table_info, ASN_UNSIGNED) == NULL) {
383 328 SNMP_FREE(table_info);
384 329 SNMP_FREE(handler);
385 330 return (MIB_REGISTRATION_FAILED);
386 331 }
387 332
388 333 table_info->min_column = SUNFMMODULE_COLMIN;
389 334 table_info->max_column = SUNFMMODULE_COLMAX;
390 335
391 336 if ((mod_name_avl_pool = uu_avl_pool_create("mod_name",
392 337 sizeof (sunFmModule_data_t),
393 338 offsetof(sunFmModule_data_t, d_name_avl), module_compare_name,
394 339 UU_AVL_DEBUG)) == NULL) {
395 340 snmp_free_varbind(table_info->indexes);
396 341 SNMP_FREE(table_info);
397 342 SNMP_FREE(handler);
398 343 }
399 344
400 345 if ((mod_name_avl = uu_avl_create(mod_name_avl_pool, NULL,
401 346 UU_AVL_DEBUG)) == NULL) {
402 347 (void) snmp_log(LOG_ERR, MODNAME_STR ": mod_name_avl creation "
403 348 "failed: %s\n", uu_strerror(uu_error()));
404 349 snmp_free_varbind(table_info->indexes);
405 350 SNMP_FREE(table_info);
406 351 SNMP_FREE(handler);
407 352 uu_avl_pool_destroy(mod_name_avl_pool);
408 353 return (MIB_REGISTRATION_FAILED);
409 354 }
410 355
411 356 if ((mod_index_avl_pool = uu_avl_pool_create("mod_index",
412 357 sizeof (sunFmModule_data_t),
413 358 offsetof(sunFmModule_data_t, d_index_avl),
414 359 module_compare_index, UU_AVL_DEBUG)) == NULL) {
415 360 snmp_free_varbind(table_info->indexes);
416 361 SNMP_FREE(table_info);
417 362 SNMP_FREE(handler);
418 363 uu_avl_destroy(mod_name_avl);
419 364 uu_avl_pool_destroy(mod_name_avl_pool);
420 365 }
421 366
422 367 if ((mod_index_avl = uu_avl_create(mod_index_avl_pool, NULL,
423 368 UU_AVL_DEBUG)) == NULL) {
424 369 (void) snmp_log(LOG_ERR, MODNAME_STR ": mod_index_avl creation "
425 370 "failed: %s\n", uu_strerror(uu_error()));
426 371 snmp_free_varbind(table_info->indexes);
427 372 SNMP_FREE(table_info);
428 373 SNMP_FREE(handler);
429 374 uu_avl_destroy(mod_name_avl);
430 375 uu_avl_pool_destroy(mod_name_avl_pool);
431 376 uu_avl_pool_destroy(mod_index_avl_pool);
432 377 return (MIB_REGISTRATION_FAILED);
433 378 }
434 379
435 380 if ((err = netsnmp_register_table(handler, table_info)) !=
436 381 MIB_REGISTERED_OK) {
437 382 snmp_free_varbind(table_info->indexes);
438 383 SNMP_FREE(table_info);
439 384 SNMP_FREE(handler);
440 385 uu_avl_destroy(mod_name_avl);
|
↓ open down ↓ |
64 lines elided |
↑ open up ↑ |
441 386 uu_avl_pool_destroy(mod_name_avl_pool);
442 387 uu_avl_destroy(mod_index_avl);
443 388 uu_avl_pool_destroy(mod_index_avl_pool);
444 389 return (err);
445 390 }
446 391
447 392 return (MIB_REGISTERED_OK);
448 393 }
449 394
450 395 /*
451 - * These two functions form the core of GET/GETNEXT/GETBULK handling (the
396 + * These two functions form the core of GET/GETNEXT handling (the
452 397 * only kind we do). They perform two functions:
453 398 *
454 399 * - First, frob the request to set all the index variables to correspond
455 400 * to the value that's going to be returned. For GET, this is a nop;
456 - * for GETNEXT/GETBULK it always requires some work.
401 + * for GETNEXT it always requires some work.
457 402 * - Second, find and return the fmd module information corresponding to
458 403 * the (possibly updated) indices.
459 404 *
460 405 * These should be as fast as possible; they run in the agent thread.
461 406 */
462 407 static sunFmModule_data_t *
463 408 sunFmModuleTable_nextmod(netsnmp_handler_registration *reginfo,
464 409 netsnmp_table_request_info *table_info)
465 410 {
466 411 sunFmModule_data_t *data;
467 412 netsnmp_variable_list *var;
468 413 ulong_t index;
469 414
470 415 /*
471 416 * If we have no index, we must make one.
472 417 */
473 418 if (table_info->number_indexes < 1) {
474 419 oid tmpoid[MAX_OID_LEN];
475 420 index = 1;
476 421
477 422 DEBUGMSGTL((MODNAME_STR, "nextmod: no indexes given\n"));
478 423 var = SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
479 424 (void) snmp_set_var_typed_value(var, ASN_UNSIGNED,
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
480 425 (uchar_t *)&index, sizeof (index));
481 426 (void) memcpy(tmpoid, reginfo->rootoid,
482 427 reginfo->rootoid_len * sizeof (oid));
483 428 tmpoid[reginfo->rootoid_len] = 1; /* Entry is .1 */
484 429 tmpoid[reginfo->rootoid_len + 1] = table_info->colnum;
485 430 if (build_oid(&var->name, &var->name_length, tmpoid,
486 431 reginfo->rootoid_len + 2, var) != SNMPERR_SUCCESS) {
487 432 snmp_free_varbind(var);
488 433 return (NULL);
489 434 }
490 - DEBUGMSGTL((MODNAME_STR, "nextmod: built fake index:\n"));
435 + DEBUGMSGTL((MODNAME_STR, "nextmod: built fake index: "));
491 436 DEBUGMSGVAR((MODNAME_STR, var));
492 437 DEBUGMSG((MODNAME_STR, "\n"));
493 438 } else {
494 439 var = snmp_clone_varbind(table_info->indexes);
495 440 index = *var->val.integer;
496 - DEBUGMSGTL((MODNAME_STR, "nextmod: received index:\n"));
441 + DEBUGMSGTL((MODNAME_STR, "nextmod: received index: "));
497 442 DEBUGMSGVAR((MODNAME_STR, var));
498 443 DEBUGMSG((MODNAME_STR, "\n"));
499 444 index++;
500 445 }
501 446
502 447 snmp_free_varbind(table_info->indexes);
503 448 table_info->indexes = NULL;
504 449 table_info->number_indexes = 0;
505 450
506 451 if ((data = module_lookup_index_nextvalid(index)) == NULL) {
507 452 DEBUGMSGTL((MODNAME_STR, "nextmod: exact match not found for "
508 453 "index %lu; trying next column\n", index));
509 454 if (table_info->colnum >=
510 455 netsnmp_find_table_registration_info(reginfo)->max_column) {
511 456 snmp_free_varbind(var);
512 457 DEBUGMSGTL((MODNAME_STR, "nextmod: out of columns\n"));
513 458 return (NULL);
514 459 }
515 460 table_info->colnum++;
516 461 index = 1;
517 462
518 463 data = module_lookup_index_nextvalid(index);
519 464 }
520 465
521 466 if (data == NULL) {
522 467 DEBUGMSGTL((MODNAME_STR, "nextmod: exact match not found for "
523 468 "index %lu; stopping\n", index));
524 469 snmp_free_varbind(var);
525 470 return (NULL);
526 471 }
527 472
528 473 *var->val.integer = data->d_index;
529 474 table_info->indexes = var;
530 475 table_info->number_indexes = 1;
531 476
532 477 DEBUGMSGTL((MODNAME_STR, "matching data is %lu/%s@%p\n", data->d_index,
533 478 data->d_ami_name, data));
534 479
535 480 return (data);
536 481 }
537 482
538 483 /*ARGSUSED*/
|
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
539 484 static sunFmModule_data_t *
540 485 sunFmModuleTable_mod(netsnmp_handler_registration *reginfo,
541 486 netsnmp_table_request_info *table_info)
542 487 {
543 488 ASSERT(table_info->number_indexes == 1);
544 489
545 490 return (module_lookup_index_exact(table_info->index_oid[0]));
546 491 }
547 492
548 493 /*ARGSUSED*/
549 -static void
550 -sunFmModuleTable_return(unsigned int reg, void *arg)
494 +static int
495 +sunFmModuleTable_handler(netsnmp_mib_handler *handler,
496 + netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo,
497 + netsnmp_request_info *request)
551 498 {
552 - netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *)arg;
553 - netsnmp_request_info *request;
554 - netsnmp_agent_request_info *reqinfo;
555 - netsnmp_handler_registration *reginfo;
556 499 netsnmp_table_request_info *table_info;
557 500 sunFmModule_data_t *data;
558 501 ulong_t modstate;
502 + int ret = SNMP_ERR_NOERROR;
559 503
560 - ASSERT(netsnmp_handler_check_cache(cache) != NULL);
561 -
562 - (void) pthread_mutex_lock(&update_lock);
563 - if (update_status != US_QUIET) {
564 - struct timeval tv;
565 -
566 - tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
567 - tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
568 -
569 - (void) snmp_alarm_register_hr(tv, 0, sunFmModuleTable_return,
570 - cache);
571 - (void) pthread_mutex_unlock(&update_lock);
572 - return;
573 - }
574 -
575 - request = cache->requests;
576 - reqinfo = cache->reqinfo;
577 - reginfo = cache->reginfo;
578 -
579 - table_info = netsnmp_extract_table_info(request);
580 - request->delegated = 0;
581 -
582 - ASSERT(table_info->colnum >= SUNFMMODULE_COLMIN);
583 - ASSERT(table_info->colnum <= SUNFMMODULE_COLMAX);
584 -
585 504 /*
586 - * table_info->colnum contains the column number requested.
587 - * table_info->indexes contains a linked list of snmp variable
588 - * bindings for the indexes of the table. Values in the list
589 - * have been set corresponding to the indexes of the
590 - * request. We have other guarantees as well:
591 - *
592 - * - The column number is always within range.
593 - * - If we have no index data, table_info->index_oid_len is 0.
594 - * - We will never receive requests outside our table nor
595 - * those with the first subid anything other than 1 (Entry)
596 - * nor those without a column number. This is true even
597 - * for GETNEXT requests.
505 + * We don't support MODE_GETBULK directly, so all bulk requests should
506 + * come through bulk_to_next helper. Make sure it stays that way.
598 507 */
508 + ASSERT(reqinfo->mode == MODE_GET || reqinfo->mode == MODE_GETNEXT);
599 509
600 - switch (reqinfo->mode) {
601 - case MODE_GET:
602 - if ((data = sunFmModuleTable_mod(reginfo, table_info)) ==
603 - NULL) {
604 - netsnmp_free_delegated_cache(cache);
605 - (void) pthread_mutex_unlock(&update_lock);
606 - return;
607 - }
608 - break;
609 - case MODE_GETNEXT:
610 - case MODE_GETBULK:
611 - if ((data = sunFmModuleTable_nextmod(reginfo, table_info)) ==
612 - NULL) {
613 - netsnmp_free_delegated_cache(cache);
614 - (void) pthread_mutex_unlock(&update_lock);
615 - return;
616 - }
617 - break;
618 - default:
619 - (void) snmp_log(LOG_ERR, MODNAME_STR ": Unsupported request "
620 - "mode %d\n", reqinfo->mode);
621 - netsnmp_free_delegated_cache(cache);
622 - (void) pthread_mutex_unlock(&update_lock);
623 - return;
624 - }
625 -
626 - switch (table_info->colnum) {
627 - case SUNFMMODULE_COL_NAME:
628 - (void) netsnmp_table_build_result(reginfo, request, table_info,
629 - ASN_OCTET_STR, (uchar_t *)data->d_ami_name,
630 - strlen(data->d_ami_name));
631 - break;
632 - case SUNFMMODULE_COL_VERSION:
633 - (void) netsnmp_table_build_result(reginfo, request, table_info,
634 - ASN_OCTET_STR, (uchar_t *)data->d_ami_vers,
635 - strlen(data->d_ami_vers));
636 - break;
637 - case SUNFMMODULE_COL_STATUS:
638 - modstate = (data->d_ami_flags & FMD_ADM_MOD_FAILED) ?
639 - SUNFMMODULE_STATE_FAILED : SUNFMMODULE_STATE_ACTIVE;
640 - (void) netsnmp_table_build_result(reginfo, request, table_info,
641 - ASN_INTEGER, (uchar_t *)&modstate,
642 - sizeof (modstate));
643 - break;
644 - case SUNFMMODULE_COL_DESCRIPTION:
645 - (void) netsnmp_table_build_result(reginfo, request, table_info,
646 - ASN_OCTET_STR, (uchar_t *)data->d_ami_desc,
647 - strlen(data->d_ami_desc));
648 - break;
649 - default:
650 - break;
651 - }
652 - netsnmp_free_delegated_cache(cache);
653 - (void) pthread_mutex_unlock(&update_lock);
654 -}
655 -
656 -static int
657 -sunFmModuleTable_handler(netsnmp_mib_handler *handler,
658 - netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo,
659 - netsnmp_request_info *requests)
660 -{
661 - netsnmp_request_info *request;
662 - struct timeval tv;
663 -
664 - tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
665 - tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
666 -
510 + (void) pthread_mutex_lock(&update_lock);
667 511 request_update();
668 512
669 - for (request = requests; request; request = request->next) {
670 - if (request->processed != 0)
513 + for (; request != NULL; request = request->next) {
514 + table_info = netsnmp_extract_table_info(request);
515 + if (table_info == NULL)
671 516 continue;
672 517
673 - if (netsnmp_extract_table_info(request) == NULL)
674 - continue;
518 + ASSERT(table_info->colnum >= SUNFMMODULE_COLMIN);
519 + ASSERT(table_info->colnum <= SUNFMMODULE_COLMAX);
675 520
676 - request->delegated = 1;
677 - (void) snmp_alarm_register_hr(tv, 0, sunFmModuleTable_return,
678 - (void *) netsnmp_create_delegated_cache(handler, reginfo,
679 - reqinfo, request, NULL));
521 + /*
522 + * table_info->colnum contains the column number requested.
523 + * table_info->indexes contains a linked list of snmp variable
524 + * bindings for the indexes of the table. Values in the list
525 + * have been set corresponding to the indexes of the
526 + * request. We have other guarantees as well:
527 + *
528 + * - The column number is always within range.
529 + * - If we have no index data, table_info->index_oid_len is 0.
530 + * - We will never receive requests outside our table nor
531 + * those with the first subid anything other than 1 (Entry)
532 + * nor those without a column number. This is true even
533 + * for GETNEXT requests.
534 + */
535 + switch (reqinfo->mode) {
536 + case MODE_GET:
537 + data = sunFmModuleTable_mod(reginfo, table_info);
538 + if (data == NULL)
539 + goto out;
540 + break;
541 + case MODE_GETNEXT:
542 + data = sunFmModuleTable_nextmod(reginfo, table_info);
543 + if (data == NULL)
544 + goto out;
545 + break;
546 + default:
547 + (void) snmp_log(LOG_ERR, MODNAME_STR
548 + ": unsupported request mode: %d\n", reqinfo->mode);
549 + ret = SNMP_ERR_GENERR;
550 + goto out;
551 + }
552 +
553 + switch (table_info->colnum) {
554 + case SUNFMMODULE_COL_NAME:
555 + (void) netsnmp_table_build_result(reginfo, request,
556 + table_info, ASN_OCTET_STR,
557 + (uchar_t *)data->d_ami_name,
558 + strlen(data->d_ami_name));
559 + break;
560 + case SUNFMMODULE_COL_VERSION:
561 + (void) netsnmp_table_build_result(reginfo, request,
562 + table_info, ASN_OCTET_STR,
563 + (uchar_t *)data->d_ami_vers,
564 + strlen(data->d_ami_vers));
565 + break;
566 + case SUNFMMODULE_COL_STATUS:
567 + modstate = (data->d_ami_flags & FMD_ADM_MOD_FAILED) ?
568 + SUNFMMODULE_STATE_FAILED : SUNFMMODULE_STATE_ACTIVE;
569 + (void) netsnmp_table_build_result(reginfo, request,
570 + table_info, ASN_INTEGER, (uchar_t *)&modstate,
571 + sizeof (modstate));
572 + break;
573 + case SUNFMMODULE_COL_DESCRIPTION:
574 + (void) netsnmp_table_build_result(reginfo, request,
575 + table_info, ASN_OCTET_STR,
576 + (uchar_t *)data->d_ami_desc,
577 + strlen(data->d_ami_desc));
578 + break;
579 + default:
580 + break;
581 + }
680 582 }
681 583
682 - return (SNMP_ERR_NOERROR);
584 +out:
585 + (void) pthread_mutex_unlock(&update_lock);
586 + return (ret);
683 587 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX