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