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/problem.c
+++ new/usr/src/lib/fm/libfmd_snmp/common/problem.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 <sys/fm/protocol.h>
28 28 #include <fm/fmd_adm.h>
29 29 #include <fm/fmd_snmp.h>
30 30 #include <net-snmp/net-snmp-config.h>
31 31 #include <net-snmp/net-snmp-includes.h>
32 32 #include <net-snmp/agent/net-snmp-agent-includes.h>
33 33 #include <pthread.h>
34 34 #include <stddef.h>
35 35 #include <errno.h>
36 36 #include <alloca.h>
37 37 #include <locale.h>
38 38 #include <libuutil.h>
39 39 #include <libnvpair.h>
40 40 #include "sunFM_impl.h"
41 41 #include "problem.h"
42 42
43 43 /*
44 44 * We assume that the number of suspect fault events associated with a
45 45 * particular case will generally be sufficiently small that the overhead
46 46 * associated with indexing them in a tree would exceed the gain from
47 47 * not traversing the fault list for each request.
48 48 */
49 49 static uu_avl_pool_t *problem_uuid_avl_pool;
50 50 static uu_avl_t *problem_uuid_avl;
51 51
52 52 #define VALID_AVL_STATE (problem_uuid_avl_pool != NULL && \
53 53 problem_uuid_avl != NULL)
54 54
55 55 #define UPDATE_WAIT_MILLIS 10 /* poll interval in milliseconds */
56 56
57 57 /*
58 58 * Update types. Single-index and all are mutually exclusive.
59 59 */
60 60 #define UCT_INDEX 0x1
61 61 #define UCT_ALL 0x2
62 62 #define UCT_FLAGS 0x3
63 63
64 64 /*
65 65 * Locking strategy is described in module.c.
66 66 */
67 67 static int valid_stamp;
68 68 static pthread_mutex_t update_lock;
69 69 static pthread_cond_t update_cv;
70 70 static volatile enum { US_QUIET, US_NEEDED, US_INPROGRESS } update_status;
71 71
72 72 static Netsnmp_Node_Handler sunFmProblemTable_handler;
73 73 static Netsnmp_Node_Handler sunFmFaultEventTable_handler;
74 74
75 75 static sunFmProblem_data_t *
76 76 problem_key_build(const char *uuid)
77 77 {
78 78 static sunFmProblem_data_t key;
79 79
80 80 key.d_aci_uuid = uuid;
81 81
82 82 return (&key);
83 83 }
84 84
85 85 static sunFmProblem_data_t *
86 86 problem_lookup_uuid_exact(const char *uuid)
87 87 {
88 88 sunFmProblem_data_t *key, *data;
89 89
90 90 key = problem_key_build(uuid);
91 91
92 92 DEBUGMSGTL((MODNAME_STR, "lookup_exact for uuid %s\n", uuid));
93 93 data = uu_avl_find(problem_uuid_avl, key, NULL, NULL);
94 94
95 95 return (data);
96 96 }
97 97
98 98 static sunFmProblem_data_t *
99 99 problem_lookup_uuid_next(const char *uuid)
100 100 {
101 101 sunFmProblem_data_t *key, *data;
102 102 uu_avl_index_t idx;
103 103
104 104 key = problem_key_build(uuid);
105 105
106 106 DEBUGMSGTL((MODNAME_STR, "lookup_next for uuid %s\n", uuid));
107 107 (void) uu_avl_find(problem_uuid_avl, key, NULL, &idx);
108 108
109 109 data = uu_avl_nearest_next(problem_uuid_avl, idx);
110 110
111 111 DEBUGMSGTL((MODNAME_STR, "lookup_next: entry is %p\n", data));
112 112
113 113 return (data);
114 114 }
115 115
116 116 static sunFmFaultEvent_data_t *
117 117 faultevent_lookup_index_exact(sunFmProblem_data_t *data, ulong_t index)
118 118 {
119 119 if (index > data->d_nsuspects)
120 120 return (NULL);
121 121
122 122 if (data->d_suspects == NULL)
123 123 return (NULL);
124 124
125 125 return (data->d_suspects[index - 1]);
126 126 }
127 127
128 128 static sunFmFaultStatus_data_t
129 129 faultstatus_lookup_index_exact(sunFmProblem_data_t *data, ulong_t index)
130 130 {
131 131 if (index > data->d_nsuspects)
132 132 return (0);
133 133
134 134 if (data->d_statuses == NULL)
135 135 return (0);
136 136
137 137 if (data->d_valid != valid_stamp)
138 138 return (0);
139 139
140 140 return (data->d_statuses[index - 1]);
141 141 }
142 142
143 143 /*ARGSUSED*/
144 144 static int
145 145 problem_update_one(const fmd_adm_caseinfo_t *acp, void *arg)
146 146 {
147 147 sunFmProblem_data_t *data;
148 148 nvlist_t *nvl;
149 149 int64_t *diag_time;
150 150 uint_t nelem;
151 151 uint32_t nsusp;
152 152 int err;
153 153
154 154 DEBUGMSGTL((MODNAME_STR, "update_one\n"));
155 155
156 156 ASSERT(acp->aci_uuid != NULL);
157 157
158 158 if ((data = problem_lookup_uuid_exact(acp->aci_uuid)) == NULL) {
159 159 uu_avl_index_t idx;
160 160
161 161 DEBUGMSGTL((MODNAME_STR, "found new problem %s\n",
162 162 acp->aci_uuid));
163 163 if ((data = SNMP_MALLOC_TYPEDEF(sunFmProblem_data_t)) == NULL) {
164 164 (void) snmp_log(LOG_ERR, MODNAME_STR ": Out of memory "
165 165 "for new problem data at %s:%d\n", __FILE__,
166 166 __LINE__);
167 167 return (0);
168 168 }
169 169 if ((err = nvlist_dup(acp->aci_event, &data->d_aci_event, 0))
170 170 != 0) {
171 171 (void) snmp_log(LOG_ERR, MODNAME_STR ": Problem data "
172 172 "setup failed: %s\n", strerror(err));
173 173 SNMP_FREE(data);
174 174 return (0);
175 175 }
176 176
177 177 data->d_aci_uuid = data->d_aci_code = data->d_aci_url = "-";
178 178 (void) nvlist_lookup_string(data->d_aci_event, FM_SUSPECT_UUID,
179 179 (char **)&data->d_aci_uuid);
180 180 (void) nvlist_lookup_string(data->d_aci_event,
181 181 FM_SUSPECT_DIAG_CODE, (char **)&data->d_aci_code);
182 182 data->d_aci_url = strdup(acp->aci_url);
183 183
184 184 if (nvlist_lookup_nvlist(data->d_aci_event, FM_SUSPECT_DE,
185 185 &nvl) == 0)
186 186 if ((data->d_diag_engine = sunFm_nvl2str(nvl)) == NULL)
187 187 data->d_diag_engine = "-";
188 188
189 189 if (nvlist_lookup_int64_array(data->d_aci_event,
190 190 FM_SUSPECT_DIAG_TIME, &diag_time, &nelem) == 0 &&
191 191 nelem >= 2) {
192 192 data->d_diag_time.tv_sec = (long)diag_time[0];
193 193 data->d_diag_time.tv_usec = (long)diag_time[1];
194 194 }
195 195
196 196 (void) nvlist_lookup_uint32(data->d_aci_event,
197 197 FM_SUSPECT_FAULT_SZ, &nsusp);
198 198 data->d_nsuspects = (ulong_t)nsusp;
199 199
200 200 (void) nvlist_lookup_nvlist_array(data->d_aci_event,
201 201 FM_SUSPECT_FAULT_LIST, &data->d_suspects, &nelem);
202 202
203 203 ASSERT(nelem == data->d_nsuspects);
204 204
205 205 (void) nvlist_lookup_uint8_array(data->d_aci_event,
206 206 FM_SUSPECT_FAULT_STATUS, &data->d_statuses, &nelem);
207 207
208 208 ASSERT(nelem == data->d_nsuspects);
209 209
210 210 uu_avl_node_init(data, &data->d_uuid_avl,
211 211 problem_uuid_avl_pool);
212 212 (void) uu_avl_find(problem_uuid_avl, data, NULL, &idx);
213 213 uu_avl_insert(problem_uuid_avl, data, idx);
214 214
215 215 data->d_valid = valid_stamp;
216 216
217 217 DEBUGMSGTL((MODNAME_STR, "completed new problem %s@%p\n",
218 218 data->d_aci_uuid, data));
219 219 } else {
220 220 uint8_t *statuses;
221 221 int i;
222 222
223 223 (void) nvlist_lookup_uint8_array(acp->aci_event,
224 224 FM_SUSPECT_FAULT_STATUS, &statuses, &nelem);
225 225
226 226 ASSERT(nelem == data->d_nsuspects);
227 227
228 228 for (i = 0; i < nelem; i++)
229 229 data->d_statuses[i] = statuses[i];
230 230
231 231 data->d_valid = valid_stamp;
232 232 }
233 233
234 234 /*
235 235 * We don't touch problems we've seen before; they shouldn't change
236 236 * in any way we care about, since they've already been solved. The
237 237 * state, however, could change, and if we later expose that to the
238 238 * client we need to update it here.
239 239 */
240 240
241 241 return (0);
242 242 }
243 243
244 244 static int
245 245 problem_update(sunFmProblem_update_ctx_t *update_ctx)
246 246 {
247 247 fmd_adm_t *adm;
248 248
249 249 ASSERT(update_ctx != NULL);
250 250 ASSERT((update_ctx->uc_type & (UCT_INDEX|UCT_ALL)) !=
251 251 (UCT_INDEX|UCT_ALL));
252 252 ASSERT((update_ctx->uc_type & ~UCT_FLAGS) == 0);
253 253 ASSERT(VALID_AVL_STATE);
254 254
255 255 if ((adm = fmd_adm_open(update_ctx->uc_host, update_ctx->uc_prog,
256 256 update_ctx->uc_version)) == NULL) {
257 257 (void) snmp_log(LOG_ERR, MODNAME_STR ": Communication with fmd "
258 258 "failed: %s\n", strerror(errno));
259 259 return (SNMP_ERR_RESOURCEUNAVAILABLE);
260 260 }
261 261
262 262 ++valid_stamp;
263 263 if (fmd_adm_case_iter(adm, SNMP_URL_MSG, problem_update_one,
264 264 update_ctx) != 0) {
265 265 (void) snmp_log(LOG_ERR, MODNAME_STR ": fmd case information "
266 266 "update failed: %s\n", fmd_adm_errmsg(adm));
267 267 fmd_adm_close(adm);
268 268 return (SNMP_ERR_RESOURCEUNAVAILABLE);
269 269 }
270 270
271 271 DEBUGMSGTL((MODNAME_STR, "case iteration completed\n"));
272 272
273 273 fmd_adm_close(adm);
274 274 return (SNMP_ERR_NOERROR);
275 275 }
276 276
277 277 /*ARGSUSED*/
278 278 static void
279 279 update_thread(void *arg)
280 280 {
281 281 /*
282 282 * The current problem_update implementation offers minimal savings
283 283 * for the use of index-only updates; therefore we always do a full
284 284 * update. If it becomes advantageous to limit updates to a single
285 285 * index, the contexts can be queued by the handler instead.
286 286 */
287 287 sunFmProblem_update_ctx_t uc;
288 288
289 289 uc.uc_host = NULL;
290 290 uc.uc_prog = FMD_ADM_PROGRAM;
291 291 uc.uc_version = FMD_ADM_VERSION;
292 292
293 293 uc.uc_index = NULL;
294 294 uc.uc_type = UCT_ALL;
295 295
296 296 for (;;) {
297 297 (void) pthread_mutex_lock(&update_lock);
298 298 update_status = US_QUIET;
299 299 while (update_status == US_QUIET)
300 300 (void) pthread_cond_wait(&update_cv, &update_lock);
301 301 update_status = US_INPROGRESS;
302 302 (void) pthread_mutex_unlock(&update_lock);
303 303 (void) problem_update(&uc);
304 304 }
305 305 }
306 306
307 307 static void
308 308 request_update(void)
309 309 {
310 310 (void) pthread_mutex_lock(&update_lock);
311 311 if (update_status != US_QUIET) {
312 312 (void) pthread_mutex_unlock(&update_lock);
313 313 return;
314 314 }
315 315 update_status = US_NEEDED;
316 316 (void) pthread_cond_signal(&update_cv);
317 317 (void) pthread_mutex_unlock(&update_lock);
318 318 }
319 319
320 320 /*ARGSUSED*/
321 321 static int
322 322 problem_compare_uuid(const void *l, const void *r, void *private)
323 323 {
324 324 sunFmProblem_data_t *l_data = (sunFmProblem_data_t *)l;
325 325 sunFmProblem_data_t *r_data = (sunFmProblem_data_t *)r;
326 326
327 327 ASSERT(l_data != NULL && r_data != NULL);
328 328
329 329 return (strcmp(l_data->d_aci_uuid, r_data->d_aci_uuid));
330 330 }
331 331
332 332 int
333 333 sunFmProblemTable_init(void)
334 334 {
335 335 static oid sunFmProblemTable_oid[] = { SUNFMPROBLEMTABLE_OID };
336 336 netsnmp_table_registration_info *table_info;
337 337 netsnmp_handler_registration *handler;
338 338 int err;
339 339
340 340 if ((err = pthread_mutex_init(&update_lock, NULL)) != 0) {
341 341 (void) snmp_log(LOG_ERR, MODNAME_STR ": mutex_init failure: "
342 342 "%s\n", strerror(err));
343 343 return (MIB_REGISTRATION_FAILED);
344 344 }
345 345 if ((err = pthread_cond_init(&update_cv, NULL)) != 0) {
346 346 (void) snmp_log(LOG_ERR, MODNAME_STR ": cond_init failure: "
347 347 "%s\n", strerror(err));
348 348 return (MIB_REGISTRATION_FAILED);
349 349 }
350 350
351 351 if ((err = pthread_create(NULL, NULL, (void *(*)(void *))update_thread,
352 352 NULL)) != 0) {
353 353 (void) snmp_log(LOG_ERR, MODNAME_STR ": error creating update "
354 354 "thread: %s\n", strerror(err));
355 355 return (MIB_REGISTRATION_FAILED);
356 356 }
357 357
358 358 if ((table_info =
359 359 SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info)) == NULL)
360 360 return (MIB_REGISTRATION_FAILED);
361 361
362 362 if ((handler = netsnmp_create_handler_registration("sunFmProblemTable",
363 363 sunFmProblemTable_handler, sunFmProblemTable_oid,
364 364 OID_LENGTH(sunFmProblemTable_oid), HANDLER_CAN_RONLY)) == NULL) {
365 365 SNMP_FREE(table_info);
366 366 return (MIB_REGISTRATION_FAILED);
367 367 }
368 368
369 369 /*
370 370 * The Net-SNMP template uses add_indexes here, but that
371 371 * function is unsafe because it does not check for failure.
372 372 */
373 373 if (netsnmp_table_helper_add_index(table_info, ASN_OCTET_STR) == NULL) {
374 374 SNMP_FREE(table_info);
375 375 SNMP_FREE(handler);
376 376 return (MIB_REGISTRATION_FAILED);
377 377 }
378 378
379 379 table_info->min_column = SUNFMPROBLEM_COLMIN;
380 380 table_info->max_column = SUNFMPROBLEM_COLMAX;
381 381
382 382 if ((problem_uuid_avl_pool = uu_avl_pool_create("problem_uuid",
383 383 sizeof (sunFmProblem_data_t),
384 384 offsetof(sunFmProblem_data_t, d_uuid_avl), problem_compare_uuid,
385 385 UU_AVL_DEBUG)) == NULL) {
386 386 (void) snmp_log(LOG_ERR, MODNAME_STR ": problem_uuid avl pool "
387 387 "creation failed: %s\n", uu_strerror(uu_error()));
388 388 snmp_free_varbind(table_info->indexes);
389 389 SNMP_FREE(table_info);
390 390 SNMP_FREE(handler);
391 391 return (MIB_REGISTRATION_FAILED);
392 392 }
393 393
394 394 if ((problem_uuid_avl = uu_avl_create(problem_uuid_avl_pool, NULL,
395 395 UU_AVL_DEBUG)) == NULL) {
396 396 (void) snmp_log(LOG_ERR, MODNAME_STR ": problem_uuid avl "
397 397 "creation failed: %s\n", uu_strerror(uu_error()));
398 398 snmp_free_varbind(table_info->indexes);
399 399 SNMP_FREE(table_info);
400 400 SNMP_FREE(handler);
401 401 uu_avl_pool_destroy(problem_uuid_avl_pool);
402 402 return (MIB_REGISTRATION_FAILED);
403 403 }
404 404
405 405 if ((err = netsnmp_register_table(handler, table_info)) !=
406 406 MIB_REGISTERED_OK) {
407 407 snmp_free_varbind(table_info->indexes);
408 408 SNMP_FREE(table_info);
409 409 SNMP_FREE(handler);
410 410 uu_avl_destroy(problem_uuid_avl);
411 411 uu_avl_pool_destroy(problem_uuid_avl_pool);
412 412 return (err);
413 413 }
414 414
415 415 return (MIB_REGISTERED_OK);
416 416 }
417 417
418 418 int
419 419 sunFmFaultEventTable_init(void)
420 420 {
421 421 static oid sunFmFaultEventTable_oid[] = { SUNFMFAULTEVENTTABLE_OID };
422 422 netsnmp_table_registration_info *table_info;
423 423 netsnmp_handler_registration *handler;
424 424 int err;
425 425
426 426 if ((table_info =
427 427 SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info)) == NULL)
428 428 return (MIB_REGISTRATION_FAILED);
429 429
430 430 if ((handler =
431 431 netsnmp_create_handler_registration("sunFmFaultEventTable",
432 432 sunFmFaultEventTable_handler, sunFmFaultEventTable_oid,
433 433 OID_LENGTH(sunFmFaultEventTable_oid), HANDLER_CAN_RONLY)) == NULL) {
434 434 SNMP_FREE(table_info);
435 435 return (MIB_REGISTRATION_FAILED);
436 436 }
437 437
438 438 /*
439 439 * The Net-SNMP template uses add_indexes here, but that
440 440 * function is unsafe because it does not check for failure.
441 441 */
442 442 if (netsnmp_table_helper_add_index(table_info, ASN_OCTET_STR) == NULL) {
443 443 SNMP_FREE(table_info);
444 444 SNMP_FREE(handler);
445 445 return (MIB_REGISTRATION_FAILED);
446 446 }
447 447 if (netsnmp_table_helper_add_index(table_info, ASN_UNSIGNED) == NULL) {
448 448 snmp_free_varbind(table_info->indexes);
449 449 SNMP_FREE(table_info);
450 450 SNMP_FREE(handler);
451 451 return (MIB_REGISTRATION_FAILED);
452 452 }
453 453
454 454 table_info->min_column = SUNFMFAULTEVENT_COLMIN;
455 455 table_info->max_column = SUNFMFAULTEVENT_COLMAX;
456 456
457 457 if ((err = netsnmp_register_table(handler, table_info)) !=
458 458 MIB_REGISTERED_OK) {
459 459 snmp_free_varbind(table_info->indexes);
460 460 SNMP_FREE(table_info);
461 461 SNMP_FREE(handler);
462 462 return (err);
463 463 }
464 464
465 465 return (MIB_REGISTERED_OK);
466 466 }
467 467
468 468 /*
469 469 * Returns the problem data for the problem whose uuid is next according
470 470 * to ASN.1 lexical ordering after the request in table_info. Indexes are
471 471 * updated to reflect the OID of the value being returned. This allows
472 472 * us to implement GETNEXT.
473 473 */
474 474 static sunFmProblem_data_t *
475 475 sunFmProblemTable_nextpr(netsnmp_handler_registration *reginfo,
476 476 netsnmp_table_request_info *table_info)
477 477 {
478 478 sunFmProblem_data_t *data;
479 479 char *uuid = "";
480 480
481 481 if (table_info->number_indexes < 1) {
482 482 oid tmpoid[MAX_OID_LEN];
483 483
484 484 DEBUGMSGTL((MODNAME_STR, "nextpr: no indexes given\n"));
485 485
486 486 snmp_free_varbind(table_info->indexes);
487 487 table_info->indexes =
488 488 SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
489 489 (void) snmp_set_var_typed_value(table_info->indexes,
490 490 ASN_OCTET_STR, (const uchar_t *)uuid, 0);
491 491 (void) memcpy(tmpoid, reginfo->rootoid,
492 492 reginfo->rootoid_len * sizeof (oid));
493 493 tmpoid[reginfo->rootoid_len] = 1;
494 494 tmpoid[reginfo->rootoid_len + 1] = table_info->colnum;
495 495 if (build_oid_segment(table_info->indexes) != SNMPERR_SUCCESS) {
496 496 snmp_free_varbind(table_info->indexes);
497 497 return (NULL);
498 498 }
499 499 table_info->number_indexes = 1;
500 500 table_info->index_oid_len = table_info->indexes->name_length;
501 501 (void) memcpy(table_info->index_oid, table_info->indexes->name,
502 502 table_info->indexes->name_length);
503 503
504 504 DEBUGMSGTL((MODNAME_STR, "nextpr: built fake index:\n"));
505 505 DEBUGMSGVAR((MODNAME_STR, table_info->indexes));
506 506 DEBUGMSG((MODNAME_STR, "\n"));
507 507 } else {
508 508 /*
509 509 * Construct the next possible UUID to look for. We can
510 510 * simply increment the least significant byte of the last
511 511 * UUID because (a) that preserves SNMP lex order and (b)
512 512 * the characters that may appear in a UUID do not include
513 513 * 127 nor 255.
514 514 */
515 515 uuid = alloca(table_info->indexes->val_len + 1);
516 516 (void) strlcpy(uuid,
517 517 (const char *)table_info->indexes->val.string,
518 518 table_info->indexes->val_len + 1);
519 519 ++uuid[table_info->indexes->val_len - 1];
520 520
521 521 DEBUGMSGTL((MODNAME_STR, "nextpr: received index:\n"));
522 522 DEBUGMSGVAR((MODNAME_STR, table_info->indexes));
523 523 DEBUGMSG((MODNAME_STR, "\n"));
524 524 }
525 525
526 526 if ((data = problem_lookup_uuid_next(uuid)) == NULL) {
527 527 DEBUGMSGTL((MODNAME_STR, "nextpr: next match not found for "
528 528 "%s; trying next column\n", uuid));
|
↓ open down ↓ |
528 lines elided |
↑ open up ↑ |
529 529 if (table_info->colnum >=
530 530 netsnmp_find_table_registration_info(reginfo)->max_column) {
531 531 snmp_free_varbind(table_info->indexes);
532 532 table_info->indexes = NULL;
533 533 table_info->number_indexes = 0;
534 534 DEBUGMSGTL((MODNAME_STR, "nextpr: out of columns\n"));
535 535 return (NULL);
536 536 }
537 537 table_info->colnum++;
538 538 DEBUGMSGTL((MODNAME_STR, "nextpr: search for col %u empty "
539 - "uuid\n", table_info->colnum, uuid));
539 + "uuid\n", table_info->colnum));
540 540
541 541 if ((data = problem_lookup_uuid_next("")) == NULL) {
542 542 DEBUGMSGTL((MODNAME_STR, "nextpr: next match not found "
543 543 "for empty uuid; stopping\n"));
544 544 snmp_free_varbind(table_info->indexes);
545 545 table_info->indexes = NULL;
546 546 table_info->number_indexes = 0;
547 547 return (NULL);
548 548 }
549 549 }
550 550
551 551 (void) snmp_set_var_typed_value(table_info->indexes, ASN_OCTET_STR,
552 552 (uchar_t *)data->d_aci_uuid, strlen(data->d_aci_uuid));
553 553 table_info->number_indexes = 1;
554 554
555 555 DEBUGMSGTL((MODNAME_STR, "matching data is %s@%p\n", data->d_aci_uuid,
556 556 data));
557 557
558 558 return (data);
559 559 }
560 560
561 561 /*
562 562 * Returns the problem data corresponding to the request in table_info.
563 563 * All request parameters are unmodified.
564 564 */
565 565 /*ARGSUSED*/
566 566 static sunFmProblem_data_t *
567 567 sunFmProblemTable_pr(netsnmp_handler_registration *reginfo,
568 568 netsnmp_table_request_info *table_info)
569 569 {
570 570 char *uuid;
571 571
572 572 ASSERT(table_info->number_indexes >= 1);
573 573
574 574 uuid = alloca(table_info->indexes->val_len + 1);
575 575 (void) strlcpy(uuid, (const char *)table_info->indexes->val.string,
576 576 table_info->indexes->val_len + 1);
577 577
578 578 return (problem_lookup_uuid_exact(uuid));
579 579 }
580 580
581 581 /*
582 582 * Returns the ASN.1 lexicographically first fault event after the one
583 583 * identified by table_info. Indexes are updated to reflect the OID
584 584 * of the data returned. This allows us to implement GETNEXT.
585 585 */
586 586 static sunFmFaultEvent_data_t *
587 587 sunFmFaultEventTable_nextfe(netsnmp_handler_registration *reginfo,
588 588 netsnmp_table_request_info *table_info, sunFmFaultStatus_data_t *statusp)
589 589 {
590 590 sunFmProblem_data_t *data;
591 591 sunFmFaultEvent_data_t *rv;
592 592 netsnmp_variable_list *var;
593 593 ulong_t index;
594 594
595 595 for (;;) {
596 596 switch (table_info->number_indexes) {
597 597 case 2:
598 598 default:
599 599 DEBUGMSGTL((MODNAME_STR, "nextfe: 2 indices:\n"));
600 600 DEBUGMSGVAR((MODNAME_STR, table_info->indexes));
601 601 DEBUGMSG((MODNAME_STR, "\n"));
602 602 DEBUGMSGVAR((MODNAME_STR,
603 603 table_info->indexes->next_variable));
604 604 DEBUGMSG((MODNAME_STR, "\n"));
605 605 index = *(ulong_t *)
606 606 table_info->indexes->next_variable->val.integer + 1;
607 607
608 608 if ((data = sunFmProblemTable_pr(reginfo,
609 609 table_info)) != NULL &&
610 610 (*statusp = faultstatus_lookup_index_exact(data,
611 611 index)) != 0 &&
612 612 (rv = faultevent_lookup_index_exact(data, index)) !=
613 613 NULL) {
614 614 (void) snmp_set_var_typed_value(
615 615 table_info->indexes->next_variable,
616 616 ASN_UNSIGNED, (uchar_t *)&index,
617 617 sizeof (index));
618 618 return (rv);
619 619 }
620 620
621 621 if (sunFmProblemTable_nextpr(reginfo, table_info) ==
622 622 NULL)
623 623 return (NULL);
624 624 break;
625 625 case 1:
626 626 if ((data = sunFmProblemTable_pr(reginfo,
627 627 table_info)) != NULL) {
628 628 oid tmpoid[MAX_OID_LEN];
629 629 index = 0;
630 630
631 631 DEBUGMSGTL((MODNAME_STR, "nextfe: 1 index:\n"));
632 632 DEBUGMSGVAR((MODNAME_STR, table_info->indexes));
633 633 DEBUGMSG((MODNAME_STR, "\n"));
634 634 var =
635 635 SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
636 636 (void) snmp_set_var_typed_value(var,
637 637 ASN_UNSIGNED, (uchar_t *)&index,
638 638 sizeof (index));
639 639 (void) memcpy(tmpoid, reginfo->rootoid,
640 640 reginfo->rootoid_len * sizeof (oid));
641 641 tmpoid[reginfo->rootoid_len] = 1;
642 642 tmpoid[reginfo->rootoid_len + 1] =
643 643 table_info->colnum;
644 644 if (build_oid_segment(var) != SNMPERR_SUCCESS) {
645 645 snmp_free_varbind(var);
646 646 return (NULL);
647 647 }
648 648 snmp_free_varbind(
649 649 table_info->indexes->next_variable);
650 650 table_info->indexes->next_variable = var;
651 651 table_info->number_indexes = 2;
652 652 DEBUGMSGTL((MODNAME_STR, "nextfe: built fake "
653 653 "index:\n"));
654 654 DEBUGMSGVAR((MODNAME_STR, table_info->indexes));
655 655 DEBUGMSG((MODNAME_STR, "\n"));
656 656 DEBUGMSGVAR((MODNAME_STR,
657 657 table_info->indexes->next_variable));
658 658 DEBUGMSG((MODNAME_STR, "\n"));
659 659 } else {
660 660 if (sunFmProblemTable_nextpr(reginfo,
661 661 table_info) == NULL)
662 662 return (NULL);
663 663 }
664 664 break;
665 665 case 0:
666 666 if (sunFmProblemTable_nextpr(reginfo, table_info) ==
667 667 NULL)
668 668 return (NULL);
669 669 break;
670 670 }
671 671 }
672 672 }
673 673
674 674 static sunFmFaultEvent_data_t *
675 675 sunFmFaultEventTable_fe(netsnmp_handler_registration *reginfo,
676 676 netsnmp_table_request_info *table_info, sunFmFaultStatus_data_t *statusp)
677 677 {
678 678 sunFmProblem_data_t *data;
679 679
680 680 ASSERT(table_info->number_indexes == 2);
681 681
682 682 if ((data = sunFmProblemTable_pr(reginfo, table_info)) == NULL)
683 683 return (NULL);
684 684
685 685 *statusp = faultstatus_lookup_index_exact(data,
686 686 *(ulong_t *)table_info->indexes->next_variable->val.integer);
687 687 if (*statusp == 0)
688 688 return (NULL);
689 689 return (faultevent_lookup_index_exact(data,
690 690 *(ulong_t *)table_info->indexes->next_variable->val.integer));
691 691 }
692 692
693 693 /*ARGSUSED*/
694 694 static void
695 695 sunFmProblemTable_return(unsigned int reg, void *arg)
696 696 {
697 697 netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *)arg;
698 698 netsnmp_request_info *request;
699 699 netsnmp_agent_request_info *reqinfo;
700 700 netsnmp_handler_registration *reginfo;
701 701 netsnmp_table_request_info *table_info;
702 702 sunFmProblem_data_t *data;
703 703
704 704 ASSERT(netsnmp_handler_check_cache(cache) != NULL);
705 705
706 706 (void) pthread_mutex_lock(&update_lock);
707 707 if (update_status != US_QUIET) {
708 708 struct timeval tv;
709 709
710 710 tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
711 711 tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
712 712
713 713 (void) snmp_alarm_register_hr(tv, 0, sunFmProblemTable_return,
714 714 cache);
715 715 (void) pthread_mutex_unlock(&update_lock);
716 716 return;
717 717 }
718 718
719 719 request = cache->requests;
720 720 reqinfo = cache->reqinfo;
721 721 reginfo = cache->reginfo;
722 722
723 723 table_info = netsnmp_extract_table_info(request);
724 724 request->delegated = 0;
725 725
726 726 ASSERT(table_info->colnum >= SUNFMPROBLEM_COLMIN);
727 727 ASSERT(table_info->colnum <= SUNFMPROBLEM_COLMAX);
728 728
729 729 /*
730 730 * table_info->colnum contains the column number requested.
731 731 * table_info->indexes contains a linked list of snmp variable
732 732 * bindings for the indexes of the table. Values in the list
733 733 * have been set corresponding to the indexes of the
734 734 * request. We have other guarantees as well:
735 735 *
736 736 * - The column number is always within range.
737 737 * - If we have no index data, table_info->index_oid_len is 0.
738 738 * - We will never receive requests outside our table nor
739 739 * those with the first subid anything other than 1 (Entry)
740 740 * nor those without a column number. This is true even
741 741 * for GETNEXT requests.
742 742 */
743 743
744 744 switch (reqinfo->mode) {
745 745 case MODE_GET:
746 746 if ((data = sunFmProblemTable_pr(reginfo, table_info)) ==
747 747 NULL) {
748 748 netsnmp_free_delegated_cache(cache);
749 749 (void) pthread_mutex_unlock(&update_lock);
750 750 return;
751 751 }
752 752 break;
753 753 case MODE_GETNEXT:
754 754 case MODE_GETBULK:
755 755 if ((data = sunFmProblemTable_nextpr(reginfo, table_info)) ==
756 756 NULL) {
757 757 netsnmp_free_delegated_cache(cache);
758 758 (void) pthread_mutex_unlock(&update_lock);
759 759 return;
760 760 }
761 761 break;
762 762 default:
763 763 (void) snmp_log(LOG_ERR, MODNAME_STR ": Unsupported request "
764 764 "mode %d\n", reqinfo->mode);
765 765 netsnmp_free_delegated_cache(cache);
766 766 (void) pthread_mutex_unlock(&update_lock);
767 767 return;
768 768 }
769 769
770 770 switch (table_info->colnum) {
771 771 case SUNFMPROBLEM_COL_UUID:
772 772 {
773 773 (void) netsnmp_table_build_result(reginfo, request, table_info,
774 774 ASN_OCTET_STR, (uchar_t *)data->d_aci_uuid,
775 775 strlen(data->d_aci_uuid));
776 776 break;
777 777 }
778 778 case SUNFMPROBLEM_COL_CODE:
779 779 {
780 780 (void) netsnmp_table_build_result(reginfo, request, table_info,
781 781 ASN_OCTET_STR, (uchar_t *)data->d_aci_code,
782 782 strlen(data->d_aci_code));
783 783 break;
784 784 }
785 785 case SUNFMPROBLEM_COL_URL:
786 786 {
787 787 (void) netsnmp_table_build_result(reginfo, request, table_info,
788 788 ASN_OCTET_STR, (uchar_t *)data->d_aci_url,
789 789 strlen(data->d_aci_url));
790 790 break;
791 791 }
792 792 case SUNFMPROBLEM_COL_DIAGENGINE:
793 793 {
794 794 (void) netsnmp_table_build_result(reginfo, request, table_info,
795 795 ASN_OCTET_STR, (uchar_t *)data->d_diag_engine,
796 796 strlen(data->d_diag_engine));
797 797 break;
798 798 }
799 799 case SUNFMPROBLEM_COL_DIAGTIME:
800 800 {
801 801 /*
802 802 * The date_n_time function is not Y2038-safe; this may
803 803 * need to be updated when a suitable Y2038-safe Net-SNMP
804 804 * API is available.
805 805 */
806 806 size_t dt_size;
807 807 time_t dt_time = (time_t)data->d_diag_time.tv_sec;
808 808 uchar_t *dt = date_n_time(&dt_time, &dt_size);
809 809
810 810 (void) netsnmp_table_build_result(reginfo, request, table_info,
811 811 ASN_OCTET_STR, dt, dt_size);
812 812 break;
813 813 }
814 814 case SUNFMPROBLEM_COL_SUSPECTCOUNT:
815 815 {
816 816 (void) netsnmp_table_build_result(reginfo, request, table_info,
817 817 ASN_UNSIGNED, (uchar_t *)&data->d_nsuspects,
818 818 sizeof (data->d_nsuspects));
819 819 break;
820 820 }
821 821 default:
822 822 break;
823 823 }
824 824
825 825 netsnmp_free_delegated_cache(cache);
826 826 (void) pthread_mutex_unlock(&update_lock);
827 827 }
828 828
829 829 static int
830 830 sunFmProblemTable_handler(netsnmp_mib_handler *handler,
831 831 netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo,
832 832 netsnmp_request_info *requests)
833 833 {
834 834 netsnmp_request_info *request;
835 835 struct timeval tv;
836 836
837 837 tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
838 838 tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
839 839
840 840 request_update();
841 841
842 842 for (request = requests; request; request = request->next) {
843 843 if (request->processed != 0)
844 844 continue;
845 845
846 846 if (netsnmp_extract_table_info(request) == NULL)
847 847 continue;
848 848
849 849 request->delegated = 1;
850 850 (void) snmp_alarm_register_hr(tv, 0,
851 851 sunFmProblemTable_return,
852 852 (void *) netsnmp_create_delegated_cache(handler, reginfo,
853 853 reqinfo, request, NULL));
854 854 }
855 855
856 856 return (SNMP_ERR_NOERROR);
857 857 }
858 858
859 859 /*ARGSUSED*/
860 860 static void
861 861 sunFmFaultEventTable_return(unsigned int reg, void *arg)
862 862 {
863 863 netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *)arg;
864 864 netsnmp_request_info *request;
865 865 netsnmp_agent_request_info *reqinfo;
866 866 netsnmp_handler_registration *reginfo;
867 867 netsnmp_table_request_info *table_info;
868 868 sunFmProblem_data_t *pdata;
869 869 sunFmFaultEvent_data_t *data;
870 870 sunFmFaultStatus_data_t status;
871 871
872 872 ASSERT(netsnmp_handler_check_cache(cache) != NULL);
873 873
874 874 (void) pthread_mutex_lock(&update_lock);
875 875 if (update_status != US_QUIET) {
876 876 struct timeval tv;
877 877
878 878 tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
879 879 tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
880 880
881 881 (void) snmp_alarm_register_hr(tv, 0,
882 882 sunFmFaultEventTable_return, cache);
883 883 (void) pthread_mutex_unlock(&update_lock);
884 884 return;
885 885 }
886 886
887 887 request = cache->requests;
888 888 reqinfo = cache->reqinfo;
889 889 reginfo = cache->reginfo;
890 890
891 891 table_info = netsnmp_extract_table_info(request);
892 892 request->delegated = 0;
893 893
894 894 ASSERT(table_info->colnum >= SUNFMFAULTEVENT_COLMIN);
895 895 ASSERT(table_info->colnum <= SUNFMFAULTEVENT_COLMAX);
896 896
897 897 /*
898 898 * table_info->colnum contains the column number requested.
899 899 * table_info->indexes contains a linked list of snmp variable
900 900 * bindings for the indexes of the table. Values in the list
901 901 * have been set corresponding to the indexes of the
902 902 * request. We have other guarantees as well:
903 903 *
904 904 * - The column number is always within range.
905 905 * - If we have no index data, table_info->index_oid_len is 0.
906 906 * - We will never receive requests outside our table nor
907 907 * those with the first subid anything other than 1 (Entry)
908 908 * nor those without a column number. This is true even
909 909 * for GETNEXT requests.
910 910 */
911 911
912 912 switch (reqinfo->mode) {
913 913 case MODE_GET:
914 914 if ((data = sunFmFaultEventTable_fe(reginfo, table_info,
915 915 &status)) == NULL) {
916 916 netsnmp_free_delegated_cache(cache);
917 917 (void) pthread_mutex_unlock(&update_lock);
918 918 return;
919 919 }
920 920 break;
921 921 case MODE_GETNEXT:
922 922 case MODE_GETBULK:
923 923 if ((data = sunFmFaultEventTable_nextfe(reginfo, table_info,
924 924 &status)) == NULL) {
925 925 netsnmp_free_delegated_cache(cache);
926 926 (void) pthread_mutex_unlock(&update_lock);
927 927 return;
928 928 }
929 929 break;
930 930 default:
931 931 (void) snmp_log(LOG_ERR, MODNAME_STR ": Unsupported request "
932 932 "mode %d\n", reqinfo->mode);
933 933 netsnmp_free_delegated_cache(cache);
934 934 (void) pthread_mutex_unlock(&update_lock);
935 935 return;
936 936 }
937 937
938 938 switch (table_info->colnum) {
939 939 case SUNFMFAULTEVENT_COL_PROBLEMUUID:
940 940 {
941 941 if ((pdata = sunFmProblemTable_pr(reginfo, table_info))
942 942 == NULL) {
943 943 (void) netsnmp_table_build_result(reginfo, request,
944 944 table_info, ASN_OCTET_STR, NULL, 0);
945 945 break;
946 946 }
947 947 (void) netsnmp_table_build_result(reginfo, request, table_info,
948 948 ASN_OCTET_STR, (uchar_t *)pdata->d_aci_uuid,
949 949 strlen(pdata->d_aci_uuid));
950 950 break;
951 951 }
952 952 case SUNFMFAULTEVENT_COL_CLASS:
953 953 {
954 954 char *class = "-";
955 955
956 956 (void) nvlist_lookup_string(data, FM_CLASS, &class);
957 957 (void) netsnmp_table_build_result(reginfo, request, table_info,
958 958 ASN_OCTET_STR, (uchar_t *)class, strlen(class));
959 959 break;
960 960 }
961 961 case SUNFMFAULTEVENT_COL_CERTAINTY:
962 962 {
963 963 uint8_t pct = 0;
964 964 ulong_t pl;
965 965
966 966 (void) nvlist_lookup_uint8(data, FM_FAULT_CERTAINTY,
967 967 &pct);
968 968 pl = (ulong_t)pct;
969 969 (void) netsnmp_table_build_result(reginfo, request, table_info,
970 970 ASN_UNSIGNED, (uchar_t *)&pl, sizeof (pl));
971 971 break;
972 972 }
973 973 case SUNFMFAULTEVENT_COL_ASRU:
974 974 {
975 975 nvlist_t *asru = NULL;
976 976 char *fmri, *str;
977 977
978 978 (void) nvlist_lookup_nvlist(data, FM_FAULT_ASRU, &asru);
979 979 if ((str = sunFm_nvl2str(asru)) == NULL)
980 980 fmri = "-";
981 981 else
982 982 fmri = str;
983 983
984 984 (void) netsnmp_table_build_result(reginfo, request, table_info,
985 985 ASN_OCTET_STR, (uchar_t *)fmri, strlen(fmri));
986 986 free(str);
987 987 break;
988 988 }
989 989 case SUNFMFAULTEVENT_COL_FRU:
990 990 {
991 991 nvlist_t *fru = NULL;
992 992 char *fmri, *str;
993 993
994 994 (void) nvlist_lookup_nvlist(data, FM_FAULT_FRU, &fru);
995 995 if ((str = sunFm_nvl2str(fru)) == NULL)
996 996 fmri = "-";
997 997 else
998 998 fmri = str;
999 999
1000 1000 (void) netsnmp_table_build_result(reginfo, request, table_info,
1001 1001 ASN_OCTET_STR, (uchar_t *)fmri, strlen(fmri));
1002 1002 free(str);
1003 1003 break;
1004 1004 }
1005 1005 case SUNFMFAULTEVENT_COL_RESOURCE:
1006 1006 {
1007 1007 nvlist_t *rsrc = NULL;
1008 1008 char *fmri, *str;
1009 1009
1010 1010 (void) nvlist_lookup_nvlist(data, FM_FAULT_RESOURCE, &rsrc);
1011 1011 if ((str = sunFm_nvl2str(rsrc)) == NULL)
1012 1012 fmri = "-";
1013 1013 else
1014 1014 fmri = str;
1015 1015
1016 1016 (void) netsnmp_table_build_result(reginfo, request, table_info,
1017 1017 ASN_OCTET_STR, (uchar_t *)fmri, strlen(fmri));
1018 1018 free(str);
1019 1019 break;
1020 1020 }
1021 1021 case SUNFMFAULTEVENT_COL_STATUS:
1022 1022 {
1023 1023 ulong_t pl = SUNFMFAULTEVENT_STATE_OTHER;
1024 1024
1025 1025 if (status & FM_SUSPECT_FAULTY)
1026 1026 pl = SUNFMFAULTEVENT_STATE_FAULTY;
1027 1027 else if (status & FM_SUSPECT_NOT_PRESENT)
1028 1028 pl = SUNFMFAULTEVENT_STATE_REMOVED;
1029 1029 else if (status & FM_SUSPECT_REPLACED)
1030 1030 pl = SUNFMFAULTEVENT_STATE_REPLACED;
1031 1031 else if (status & FM_SUSPECT_REPAIRED)
1032 1032 pl = SUNFMFAULTEVENT_STATE_REPAIRED;
1033 1033 else if (status & FM_SUSPECT_ACQUITTED)
1034 1034 pl = SUNFMFAULTEVENT_STATE_ACQUITTED;
1035 1035 (void) netsnmp_table_build_result(reginfo, request, table_info,
1036 1036 ASN_INTEGER, (uchar_t *)&pl, sizeof (pl));
1037 1037 break;
1038 1038 }
1039 1039 case SUNFMFAULTEVENT_COL_LOCATION:
1040 1040 {
1041 1041 char *location = "-";
1042 1042
1043 1043 (void) nvlist_lookup_string(data, FM_FAULT_LOCATION, &location);
1044 1044 (void) netsnmp_table_build_result(reginfo, request, table_info,
1045 1045 ASN_OCTET_STR, (uchar_t *)location, strlen(location));
1046 1046 break;
1047 1047 }
1048 1048 default:
1049 1049 break;
1050 1050 }
1051 1051
1052 1052 netsnmp_free_delegated_cache(cache);
1053 1053 (void) pthread_mutex_unlock(&update_lock);
1054 1054 }
1055 1055
1056 1056 static int
1057 1057 sunFmFaultEventTable_handler(netsnmp_mib_handler *handler,
1058 1058 netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo,
1059 1059 netsnmp_request_info *requests)
1060 1060 {
1061 1061 netsnmp_request_info *request;
1062 1062 struct timeval tv;
1063 1063
1064 1064 tv.tv_sec = UPDATE_WAIT_MILLIS / 1000;
1065 1065 tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000;
1066 1066
1067 1067 request_update();
1068 1068
1069 1069 for (request = requests; request; request = request->next) {
1070 1070 if (request->processed != 0)
1071 1071 continue;
1072 1072
1073 1073 if (netsnmp_extract_table_info(request) == NULL)
1074 1074 continue;
1075 1075
1076 1076 request->delegated = 1;
1077 1077 (void) snmp_alarm_register_hr(tv, 0,
1078 1078 sunFmFaultEventTable_return,
1079 1079 (void *) netsnmp_create_delegated_cache(handler, reginfo,
1080 1080 reqinfo, request, NULL));
1081 1081 }
1082 1082
1083 1083 return (SNMP_ERR_NOERROR);
1084 1084 }
|
↓ open down ↓ |
535 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX