1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * The SNMP picl plugin connects to the agent on the SP and creates 31 * and populates the /physical-platform subtree in picl tree for use 32 * by picl consumers. 33 */ 34 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <syslog.h> 39 #include <stdarg.h> 40 #include <libgen.h> 41 #include <libintl.h> 42 #include <thread.h> 43 #include <synch.h> 44 #include <errno.h> 45 46 #include <picldefs.h> 47 #include <picl.h> 48 #include <picltree.h> 49 50 #include "picloids.h" 51 #include "libpiclsnmp.h" 52 #include "snmpplugin.h" 53 54 #pragma init(snmpplugin_register) /* place in .init section */ 55 56 picld_plugin_reg_t snmpplugin_reg = { 57 PICLD_PLUGIN_VERSION_1, 58 PICLD_PLUGIN_NON_CRITICAL, 59 "snmp_plugin", 60 snmpplugin_init, 61 snmpplugin_fini 62 }; 63 64 static picl_snmphdl_t hdl; 65 66 /* 67 * The stale_tree_rwlp protects the stale_xxx vars. The 'stale_tree' flag 68 * and the 'rebuild_tree' flag below are both initialized to B_TRUE to 69 * let the tree_builder() thread build the initial tree without blocking. 70 */ 71 static rwlock_t stale_tree_rwlp; 72 static boolean_t stale_tree = B_TRUE; 73 74 /* 75 * vol_props, volprop_ndx and n_vol_props are protected by the stale_tree 76 * flag. They are read only when the stale_tree flag is B_FALSE and written 77 * to only when the flag is B_TRUE. 78 * 79 * The change_time (last changed time) is read by only one thread at a 80 * time when stale_tree is B_FALSE (protected by stale_tree_rwlp). It is 81 * written by only one thread (the tree builder) when stale_tree is B_TRUE. 82 * 83 * Note that strictly speaking, change_time should be uint_t (timeticks32). 84 * But keeping it as int is fine, since we don't do any arithmetic on it 85 * except equality check. 86 */ 87 static vol_prophdl_t *vol_props = NULL; 88 static int volprop_ndx = 0, n_vol_props = 0; 89 static int change_time = 0; 90 static time_t change_time_check; 91 92 /* 93 * The rebuild_tree_lock and cv are used by the tree builder thread. 94 * rebuild_tree has to be initialized to B_TRUE to let the tree_builder 95 * do the first build without blocking. 96 */ 97 static mutex_t rebuild_tree_lock; 98 static cond_t rebuild_tree_cv; 99 static boolean_t rebuild_tree = B_TRUE; 100 static boolean_t tree_builder_thr_exit = B_FALSE; 101 static thread_t tree_builder_thr_id; 102 103 /* 104 * These two should really not be global 105 */ 106 static picl_nodehdl_t *physplat_nodes = NULL; 107 static int n_physplat_nodes = 0; 108 109 static char *group1[] = { 110 OID_entPhysicalDescr, 111 OID_entPhysicalContainedIn, 112 OID_entPhysicalClass, 113 OID_entPhysicalName, 114 OID_entPhysicalHardwareRev, 115 OID_entPhysicalFirmwareRev, 116 OID_entPhysicalSerialNum, 117 OID_entPhysicalMfgName, 118 OID_entPhysicalModelName, 119 OID_entPhysicalIsFRU, 120 0 121 }; 122 123 static char *group2[] = { 124 OID_sunPlatEquipmentHolderAcceptableTypes, 125 OID_sunPlatCircuitPackReplaceable, 126 OID_sunPlatCircuitPackHotSwappable, 127 OID_sunPlatPhysicalClass, 128 OID_sunPlatSensorClass, 129 OID_sunPlatSensorType, 130 OID_sunPlatAlarmType, 131 OID_sunPlatPowerSupplyClass, 132 0 133 }; 134 135 static char *group3[] = { 136 OID_sunPlatNumericSensorEnabledThresholds, 137 OID_sunPlatNumericSensorBaseUnits, 138 OID_sunPlatNumericSensorRateUnits, 139 0 140 }; 141 142 static char *group4[] = { 143 OID_sunPlatBinarySensorInterpretTrue, 144 OID_sunPlatBinarySensorInterpretFalse, 145 }; 146 147 static char *volgroup1[] = { 148 OID_sunPlatBinarySensorCurrent, 149 OID_sunPlatBinarySensorExpected, 150 0 151 }; 152 153 static char *volgroup2[] = { 154 OID_sunPlatNumericSensorExponent, 155 OID_sunPlatNumericSensorCurrent, 156 OID_sunPlatNumericSensorLowerThresholdFatal, 157 OID_sunPlatNumericSensorLowerThresholdCritical, 158 OID_sunPlatNumericSensorLowerThresholdNonCritical, 159 OID_sunPlatNumericSensorUpperThresholdNonCritical, 160 OID_sunPlatNumericSensorUpperThresholdCritical, 161 OID_sunPlatNumericSensorUpperThresholdFatal, 162 0 163 }; 164 165 static char *volgroup3[] = { 166 OID_sunPlatEquipmentOperationalState, 167 0 168 }; 169 170 static char *volgroup4[] = { 171 OID_sunPlatAlarmState, 172 0 173 }; 174 175 static char *volgroup5[] = { 176 OID_sunPlatBatteryStatus, 177 0 178 }; 179 180 /* 181 * The following two items must match the Sun Platform MIB specification 182 * in their indices and values. 183 */ 184 static char *sensor_baseunits[] = { 185 "", "other", "unknown", "degC", "degF", "degK", "volts", "amps", 186 "watts", "joules", "coulombs", "va", "nits", "lumens", "lux", 187 "candelas", "kPa", "psi", "newtons", "cfm", "rpm", "hertz", 188 "seconds", "minutes", "hours", "days", "weeks", "mils", "inches", 189 "feet", "cubicInches", "cubicFeet", "meters", "cubicCentimeters", 190 "cubicMeters", "liters", "fluidOunces", "radians", "steradians", 191 "revolutions", "cycles", "gravities", "ounces", "pounds", "footPounds", 192 "ounceInches", "gauss", "gilberts", "henries", "farads", "ohms", 193 "siemens", "moles", "becquerels", "ppm", "decibels", "dBA", "dbC", 194 "grays", "sieverts", "colorTemperatureDegK", "bits", "bytes", "words", 195 "doubleWords", "quadWords", "percentage" 196 }; 197 static const int n_baseunits = sizeof (sensor_baseunits) / sizeof (char *); 198 199 static char *sensor_rateunits[] = { 200 "", 201 "none", 202 "perMicroSecond", 203 "perMilliSecond", 204 "perSecond", 205 "perMinute", 206 "perHour", 207 "perDay", 208 "perWeek", 209 "perMonth", 210 "perYear" 211 }; 212 static const int n_rateunits = sizeof (sensor_rateunits) / sizeof (char *); 213 214 /* 215 * Local declarations 216 */ 217 static void snmpplugin_register(void); 218 static void register_group(char **g, int is_volatile); 219 static void *tree_builder(void *arg); 220 static int build_physplat(picl_nodehdl_t *subtree_rootp); 221 static void free_resources(picl_nodehdl_t subtree_root); 222 223 static picl_nodehdl_t make_node(picl_nodehdl_t subtree_root, int row, 224 int *snmp_syserr_p); 225 static void save_nodeh(picl_nodehdl_t nodeh, int row); 226 static picl_nodehdl_t lookup_nodeh(int row); 227 228 static void save_volprop(picl_prophdl_t prop, char *oidstr, int row, 229 int proptype); 230 static void check_for_stale_data(boolean_t nocache); 231 static int read_volprop(ptree_rarg_t *parg, void *buf); 232 233 static void threshold(picl_nodehdl_t node, char *oidstr, int row, 234 char *propname, int *snmp_syserr_p); 235 static void add_thresholds(picl_nodehdl_t node, int row, int *snmp_syserr_p); 236 237 static char *get_slot_type(int row, int *snmp_syserr_p); 238 static int add_volatile_prop(picl_nodehdl_t nodeh, char *name, 239 int type, int access, int size, int (*rdfunc)(ptree_rarg_t *, void *), 240 int (*wrfunc)(ptree_warg_t *, const void *), picl_prophdl_t *propp); 241 static int add_string_prop(picl_nodehdl_t node, char *propname, char *propval); 242 static int add_void_prop(picl_nodehdl_t node, char *propname); 243 static void add_prop(picl_nodehdl_t nodeh, picl_prophdl_t *php, char *label, 244 int row, sp_propid_t pp, int *snmp_syserr_p); 245 246 static void log_msg(int pri, const char *fmt, ...); 247 248 #ifdef SNMPPLUGIN_DEBUG 249 static mutex_t snmpplugin_dbuf_lock; 250 static char *snmpplugin_dbuf = NULL; 251 static char *snmpplugin_dbuf_curp = NULL; 252 static int snmpplugin_dbuf_sz = 0; 253 static int snmpplugin_dbuf_overflow = 0; 254 static char snmpplugin_lbuf[SNMPPLUGIN_DMAX_LINE]; 255 256 static void snmpplugin_log_init(void); 257 static void snmpplugin_log(const char *fmt, ...); 258 static void snmpplugin_log_append(void); 259 static void snmpplugin_dbuf_realloc(void); 260 #endif 261 262 static void 263 snmpplugin_register(void) 264 { 265 (void) picld_plugin_register(&snmpplugin_reg); 266 } 267 268 static void 269 register_group(char **g, int is_volatile) 270 { 271 int i, len = 0; 272 int n_oids; 273 char *p, *oidstrs; 274 275 for (i = 0; g[i]; i++) 276 len += strlen(g[i]) + 1; 277 n_oids = i; 278 279 if ((oidstrs = (char *)calloc(1, len)) == NULL) 280 return; 281 282 for (p = oidstrs, i = 0; g[i]; i++) { 283 (void) strcpy(p, g[i]); 284 p += strlen(g[i]) + 1; 285 } 286 287 snmp_register_group(hdl, oidstrs, n_oids, is_volatile); 288 } 289 290 void 291 snmpplugin_init(void) 292 { 293 int ret; 294 295 (void) mutex_init(&rebuild_tree_lock, USYNC_THREAD, NULL); 296 (void) cond_init(&rebuild_tree_cv, USYNC_THREAD, NULL); 297 (void) rwlock_init(&stale_tree_rwlp, USYNC_THREAD, NULL); 298 tree_builder_thr_exit = B_FALSE; 299 300 LOGINIT(); 301 302 /* 303 * Create the tree-builder thread and let it take over 304 */ 305 LOGPRINTF("Tree-builder thread being created.\n"); 306 if ((ret = thr_create(NULL, NULL, tree_builder, NULL, 307 THR_BOUND, &tree_builder_thr_id)) < 0) { 308 log_msg(LOG_ERR, SNMPP_CANT_CREATE_TREE_BUILDER, ret); 309 snmp_fini(hdl); 310 hdl = NULL; 311 (void) rwlock_destroy(&stale_tree_rwlp); 312 (void) cond_destroy(&rebuild_tree_cv); 313 (void) mutex_destroy(&rebuild_tree_lock); 314 tree_builder_thr_exit = B_TRUE; 315 } 316 } 317 318 void 319 snmpplugin_fini(void) 320 { 321 322 if (tree_builder_thr_exit == B_TRUE) 323 return; 324 325 /* 326 * Make reads of volatile properties return PICL_PROPUNAVAILABLE 327 * since we're about to recycle the plug-in. No need to worry 328 * about removing /physical-platform since tree_builder() will 329 * take care of recycling it for us. 330 */ 331 (void) rw_wrlock(&stale_tree_rwlp); 332 stale_tree = B_TRUE; 333 if (vol_props) { 334 free(vol_props); 335 } 336 vol_props = NULL; 337 volprop_ndx = 0; 338 n_vol_props = 0; 339 (void) rw_unlock(&stale_tree_rwlp); 340 341 /* wake up the tree_builder thread, tell it to exit */ 342 (void) mutex_lock(&rebuild_tree_lock); 343 rebuild_tree = B_TRUE; 344 tree_builder_thr_exit = B_TRUE; 345 (void) cond_signal(&rebuild_tree_cv); 346 (void) mutex_unlock(&rebuild_tree_lock); 347 348 /* reap the thread */ 349 (void) thr_join(tree_builder_thr_id, NULL, NULL); 350 351 /* close the channel */ 352 if (hdl != NULL) { 353 snmp_fini(hdl); 354 hdl = NULL; 355 } 356 357 /* finish cleanup... */ 358 (void) rwlock_destroy(&stale_tree_rwlp); 359 (void) cond_destroy(&rebuild_tree_cv); 360 (void) mutex_destroy(&rebuild_tree_lock); 361 } 362 363 /*ARGSUSED*/ 364 static void * 365 tree_builder(void *arg) 366 { 367 int ret, rv; 368 picl_nodehdl_t root_node; 369 picl_nodehdl_t physplat_root; 370 picl_nodehdl_t old_physplat_root; 371 372 /* 373 * Initialize SNMP service 374 */ 375 LOGPRINTF("Initializing SNMP service.\n"); 376 if ((hdl = snmp_init()) == NULL) { 377 log_msg(LOG_ERR, SNMPP_CANT_INIT); 378 return ((void *)-1); 379 } 380 381 /* 382 * Register OID groupings for BULKGET optimizations 383 */ 384 LOGPRINTF("Registering OID groups.\n"); 385 register_group(group1, 0); 386 register_group(group2, 0); 387 register_group(group3, 0); 388 register_group(group4, 0); 389 register_group(volgroup1, 1); 390 register_group(volgroup2, 1); 391 register_group(volgroup3, 1); 392 register_group(volgroup4, 1); 393 register_group(volgroup5, 1); 394 395 (void) mutex_lock(&rebuild_tree_lock); 396 397 for (;;) { 398 LOGPRINTF("tree_builder: check whether to rebuild subtree\n"); 399 while (rebuild_tree == B_FALSE) 400 (void) cond_wait(&rebuild_tree_cv, &rebuild_tree_lock); 401 402 LOGPRINTF("tree_builder: woke up\n"); 403 404 if (tree_builder_thr_exit == B_TRUE) { 405 (void) mutex_unlock(&rebuild_tree_lock); 406 LOGPRINTF("tree_builder: time to exit\n"); 407 return (NULL); 408 } 409 410 old_physplat_root = NULL; 411 physplat_root = NULL; 412 413 LOGPRINTF("tree_builder: getting root node\n"); 414 if ((ret = ptree_get_root(&root_node)) != PICL_SUCCESS) { 415 (void) mutex_unlock(&rebuild_tree_lock); 416 log_msg(LOG_ERR, SNMPP_NO_ROOT, ret); 417 return ((void *)-2); 418 } 419 420 LOGPRINTF("tree_builder: getting existing physplat node\n"); 421 rv = ptree_find_node(root_node, PICL_PROP_NAME, 422 PICL_PTYPE_CHARSTRING, PICL_NODE_PHYSPLAT, 423 sizeof (PICL_NODE_PHYSPLAT), &old_physplat_root); 424 425 LOGPRINTF("tree_builder: building physical-platform\n"); 426 if ((ret = build_physplat(&physplat_root)) < 0) { 427 (void) mutex_unlock(&rebuild_tree_lock); 428 log_msg(LOG_ERR, SNMPP_CANT_CREATE_PHYSPLAT, ret); 429 snmp_fini(hdl); 430 hdl = NULL; 431 return ((void *)-3); 432 } 433 434 if (rv == PICL_SUCCESS && old_physplat_root != NULL) { 435 LOGPRINTF("tree_builder: destroying existing nodes\n"); 436 ptree_delete_node(old_physplat_root); 437 ptree_destroy_node(old_physplat_root); 438 } 439 440 LOGPRINTF("tree_builder: attaching new subtree\n"); 441 if ((ret = ptree_add_node(root_node, physplat_root)) < 0) { 442 (void) mutex_unlock(&rebuild_tree_lock); 443 free_resources(physplat_root); 444 log_msg(LOG_ERR, SNMPP_CANT_CREATE_PHYSPLAT, ret); 445 snmp_fini(hdl); 446 hdl = NULL; 447 return ((void *)-4); 448 } 449 450 LOGPRINTF("tree_builder: setting stale_tree to FALSE\n"); 451 (void) rw_wrlock(&stale_tree_rwlp); 452 stale_tree = B_FALSE; 453 (void) rw_unlock(&stale_tree_rwlp); 454 455 LOGPRINTF("tree_builder: setting rebuild_tree to FALSE\n"); 456 rebuild_tree = B_FALSE; 457 } 458 459 /*NOTREACHED*/ 460 return (NULL); 461 } 462 463 static int 464 build_physplat(picl_nodehdl_t *subtree_rootp) 465 { 466 int change_time1; 467 int row, nxtrow; 468 int clr_linkreset = 0; 469 int ret = 0; 470 int snmp_syserr = 0; 471 472 retry: 473 (void) snmp_reinit(hdl, clr_linkreset); 474 clr_linkreset = 0; 475 476 /* 477 * Record LastChangeTime before we start building the tree 478 */ 479 ret = snmp_get_int(hdl, OID_entLastChangeTime, 0, 480 &change_time1, &snmp_syserr); 481 if (ret < 0) { 482 if (snmp_syserr == ECANCELED) { 483 LOGPRINTF(SNMPP_LINK_RESET); 484 clr_linkreset = 1; 485 goto retry; 486 } 487 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 488 snmp_syserr ? snmp_syserr : ret, OID_entLastChangeTime, 0); 489 } 490 491 /* 492 * Create the physical-platform node 493 */ 494 ret = ptree_create_node(PICL_NODE_PHYSPLAT, PICL_CLASS_PICL, 495 subtree_rootp); 496 if (ret != PICL_SUCCESS) 497 return (-1); 498 499 /* 500 * Scan entPhysicalTable and build the "physical-platform" subtree 501 */ 502 ret = 0; 503 for (row = -1; ret == 0; row = nxtrow) { 504 ret = snmp_get_nextrow(hdl, OID_entPhysicalDescr, 505 row, &nxtrow, &snmp_syserr); 506 if (ret == 0) 507 (void) make_node(*subtree_rootp, nxtrow, &snmp_syserr); 508 switch (snmp_syserr) { 509 case ECANCELED: 510 /* 511 * If we get this error, a link reset must've 512 * happened and we need to throw away everything 513 * we have now and rebuild the tree again. 514 */ 515 log_msg(LOG_WARNING, SNMPP_LINK_RESET); 516 free_resources(*subtree_rootp); 517 clr_linkreset = 1; 518 goto retry; 519 /*NOTREACHED*/ 520 break; 521 case ENOSPC: /* end of MIB */ 522 LOGPRINTF("build_physplat: end of MIB\n"); 523 break; 524 case ENOENT: /* end of table */ 525 LOGPRINTF("build_physplat: end of table\n"); 526 break; 527 default: 528 /* 529 * make_node() will print messages so don't 530 * repeat that exercise here. 531 */ 532 if (ret == -1) { 533 log_msg(LOG_WARNING, 534 SNMPP_CANT_FETCH_OBJECT_VAL, 535 snmp_syserr ? snmp_syserr : ret, 536 OID_entPhysicalDescr, row); 537 } 538 } 539 } 540 541 /* 542 * Record LastChangeTime after we're done building the tree 543 */ 544 ret = snmp_get_int(hdl, OID_entLastChangeTime, 0, 545 &change_time, &snmp_syserr); 546 if (ret < 0) { 547 if (snmp_syserr == ECANCELED) { 548 log_msg(LOG_WARNING, SNMPP_LINK_RESET); 549 free_resources(*subtree_rootp); 550 clr_linkreset = 1; 551 goto retry; 552 } else 553 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 554 snmp_syserr ? snmp_syserr : ret, 555 OID_entLastChangeTime, row); 556 } 557 558 /* 559 * If they don't match, some hotplugging must've happened, 560 * free resources we've created and still holding, then go 561 * back and retry 562 */ 563 if (change_time != change_time1) { 564 LOGPRINTF("build_physplat: entLastChangeTime has changed!\n"); 565 free_resources(*subtree_rootp); 566 change_time1 = change_time; 567 goto retry; 568 } 569 570 /* 571 * The physplat_nodes table is no longer needed, free it 572 */ 573 if (physplat_nodes) { 574 free(physplat_nodes); 575 physplat_nodes = NULL; 576 n_physplat_nodes = 0; 577 } 578 579 return (0); 580 } 581 582 /* 583 * Destroy all resources that were created during the building 584 * of the subtree 585 */ 586 static void 587 free_resources(picl_nodehdl_t subtree_root) 588 { 589 if (physplat_nodes) { 590 free(physplat_nodes); 591 physplat_nodes = NULL; 592 n_physplat_nodes = 0; 593 } 594 595 if (subtree_root) { 596 (void) ptree_delete_node(subtree_root); 597 (void) ptree_destroy_node(subtree_root); 598 } 599 600 if (vol_props) { 601 free(vol_props); 602 n_vol_props = 0; 603 volprop_ndx = 0; 604 } 605 } 606 607 static picl_nodehdl_t 608 make_node(picl_nodehdl_t subtree_root, int row, int *snmp_syserr_p) 609 { 610 picl_nodehdl_t nodeh, parenth; 611 picl_prophdl_t proph; 612 char *phys_name, *node_name; 613 int parent_row; 614 int ent_physclass, sunplat_physclass; 615 int sensor_class, sensor_type; 616 int alarm_type; 617 int ps_class; 618 int ret; 619 620 /* 621 * If we've already created this picl node, just return it 622 */ 623 if ((nodeh = lookup_nodeh(row)) != NULL) 624 return (nodeh); 625 626 /* 627 * If we are creating it only now, make sure we have the parent 628 * created first; if there's no parent, then parent it to the 629 * subtree's root node 630 */ 631 ret = snmp_get_int(hdl, OID_entPhysicalContainedIn, row, 632 &parent_row, snmp_syserr_p); 633 CHECK_LINKRESET(snmp_syserr_p, NULL) 634 if (ret < 0 || parent_row <= 0) 635 parenth = subtree_root; 636 else { 637 parenth = make_node(subtree_root, parent_row, snmp_syserr_p); 638 CHECK_LINKRESET(snmp_syserr_p, NULL) 639 if (parenth == NULL) 640 parenth = subtree_root; 641 } 642 643 /* 644 * Figure out the physical-platform node name from entPhysicalName; 645 * all rows in the MIB that have a valid entPhysicalIndex should 646 * have a physical name. 647 */ 648 ret = snmp_get_str(hdl, OID_entPhysicalName, row, 649 &phys_name, snmp_syserr_p); 650 CHECK_LINKRESET(snmp_syserr_p, NULL) 651 if (ret < 0 || phys_name == NULL) { 652 log_msg(LOG_WARNING, SNMPP_NO_ENTPHYSNAME, row); 653 return (NULL); 654 } 655 656 node_name = basename(phys_name); 657 658 ret = snmp_get_int(hdl, OID_entPhysicalClass, row, 659 &ent_physclass, snmp_syserr_p); 660 CHECK_LINKRESET(snmp_syserr_p, NULL) 661 if (ret < 0) { 662 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 663 *snmp_syserr_p ? *snmp_syserr_p : ret, 664 OID_entPhysicalClass, row); 665 free(phys_name); 666 return (NULL); 667 } 668 669 switch (ent_physclass) { 670 case SPC_OTHER: 671 ret = snmp_get_int(hdl, OID_sunPlatPhysicalClass, row, 672 &sunplat_physclass, snmp_syserr_p); 673 CHECK_LINKRESET(snmp_syserr_p, NULL) 674 if (ret < 0) { 675 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 676 *snmp_syserr_p ? *snmp_syserr_p : ret, 677 OID_sunPlatPhysicalClass, row); 678 free(phys_name); 679 return (NULL); 680 } 681 682 if (sunplat_physclass == SSPC_ALARM) { 683 ret = snmp_get_int(hdl, OID_sunPlatAlarmType, 684 row, &alarm_type, snmp_syserr_p); 685 CHECK_LINKRESET(snmp_syserr_p, NULL) 686 if (ret < 0) { 687 log_msg(LOG_WARNING, 688 SNMPP_CANT_FETCH_OBJECT_VAL, 689 *snmp_syserr_p ? *snmp_syserr_p : ret, 690 OID_sunPlatAlarmType, row); 691 free(phys_name); 692 return (NULL); 693 } 694 695 if (alarm_type == SSAT_VISIBLE) { 696 ADD_NODE(PICL_CLASS_LED) 697 } else { 698 ADD_NODE(PICL_CLASS_ALARM) 699 } 700 701 add_prop(nodeh, &proph, node_name, row, PP_STATE, 702 snmp_syserr_p); 703 CHECK_LINKRESET(snmp_syserr_p, NULL) 704 } else { 705 ADD_NODE(PICL_CLASS_OTHER) 706 } 707 708 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 709 snmp_syserr_p); 710 CHECK_LINKRESET(snmp_syserr_p, NULL) 711 break; 712 713 case SPC_UNKNOWN: 714 ADD_NODE(PICL_CLASS_UNKNOWN) 715 break; 716 717 case SPC_CHASSIS: 718 ADD_NODE(PICL_CLASS_CHASSIS) 719 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 720 snmp_syserr_p); 721 CHECK_LINKRESET(snmp_syserr_p, NULL) 722 break; 723 724 case SPC_BACKPLANE: 725 ADD_NODE(PICL_CLASS_BACKPLANE) 726 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 727 snmp_syserr_p); 728 CHECK_LINKRESET(snmp_syserr_p, NULL) 729 break; 730 731 case SPC_CONTAINER: 732 ADD_NODE(PICL_CLASS_CONTAINER) 733 734 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 735 snmp_syserr_p); 736 CHECK_LINKRESET(snmp_syserr_p, NULL) 737 738 add_prop(nodeh, &proph, node_name, row, PP_SLOT_TYPE, 739 snmp_syserr_p); 740 CHECK_LINKRESET(snmp_syserr_p, NULL) 741 break; 742 743 case SPC_POWERSUPPLY: 744 ret = snmp_get_int(hdl, OID_sunPlatPowerSupplyClass, 745 row, &ps_class, snmp_syserr_p); 746 CHECK_LINKRESET(snmp_syserr_p, NULL) 747 if (ret < 0) { 748 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 749 *snmp_syserr_p ? *snmp_syserr_p : ret, 750 OID_sunPlatPowerSupplyClass, row); 751 free(phys_name); 752 return (NULL); 753 } 754 755 if (ps_class == SSPSC_BATTERY) { 756 ADD_NODE(PICL_CLASS_BATTERY) 757 add_prop(nodeh, &proph, node_name, row, 758 PP_BATT_STATUS, snmp_syserr_p); 759 CHECK_LINKRESET(snmp_syserr_p, NULL) 760 } else { 761 ADD_NODE(PICL_CLASS_POWERSUPPLY) 762 } 763 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 764 snmp_syserr_p); 765 CHECK_LINKRESET(snmp_syserr_p, NULL) 766 break; 767 768 case SPC_FAN: 769 ADD_NODE(PICL_CLASS_FAN) 770 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 771 snmp_syserr_p); 772 CHECK_LINKRESET(snmp_syserr_p, NULL) 773 break; 774 775 case SPC_SENSOR: 776 ret = snmp_get_int(hdl, OID_sunPlatSensorClass, 777 row, &sensor_class, snmp_syserr_p); 778 CHECK_LINKRESET(snmp_syserr_p, NULL) 779 if (ret < 0) { 780 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 781 *snmp_syserr_p ? *snmp_syserr_p : ret, 782 OID_sunPlatSensorClass, row); 783 free(phys_name); 784 return (NULL); 785 } 786 787 ret = snmp_get_int(hdl, OID_sunPlatSensorType, 788 row, &sensor_type, snmp_syserr_p); 789 CHECK_LINKRESET(snmp_syserr_p, NULL) 790 if (ret < 0) { 791 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 792 *snmp_syserr_p ? *snmp_syserr_p : ret, 793 OID_sunPlatSensorType, row); 794 free(phys_name); 795 return (NULL); 796 } 797 798 if (sensor_class == SSSC_NUMERIC) { 799 if (sensor_type == SSST_TEMPERATURE) { 800 ADD_NODE(PICL_CLASS_TEMPERATURE_SENSOR) 801 add_prop(nodeh, &proph, node_name, row, 802 PP_TEMPERATURE, snmp_syserr_p); 803 } else if (sensor_type == SSST_VOLTAGE) { 804 ADD_NODE(PICL_CLASS_VOLTAGE_SENSOR) 805 add_prop(nodeh, &proph, node_name, row, 806 PP_VOLTAGE, snmp_syserr_p); 807 } else if (sensor_type == SSST_CURRENT) { 808 ADD_NODE(PICL_CLASS_CURRENT_SENSOR) 809 add_prop(nodeh, &proph, node_name, row, 810 PP_CURRENT, snmp_syserr_p); 811 } else if (sensor_type == SSST_TACHOMETER) { 812 ADD_NODE(PICL_CLASS_RPM_SENSOR) 813 add_prop(nodeh, &proph, node_name, row, 814 PP_SPEED, snmp_syserr_p); 815 } else { 816 ADD_NODE(PICL_CLASS_SENSOR) 817 add_prop(nodeh, &proph, node_name, row, 818 PP_SENSOR_VALUE, snmp_syserr_p); 819 } 820 CHECK_LINKRESET(snmp_syserr_p, NULL) 821 822 add_prop(nodeh, &proph, node_name, row, 823 PP_OPSTATUS, snmp_syserr_p); 824 CHECK_LINKRESET(snmp_syserr_p, NULL) 825 826 add_prop(nodeh, &proph, node_name, row, 827 PP_BASE_UNITS, snmp_syserr_p); 828 CHECK_LINKRESET(snmp_syserr_p, NULL) 829 830 add_prop(nodeh, &proph, node_name, row, 831 PP_EXPONENT, snmp_syserr_p); 832 CHECK_LINKRESET(snmp_syserr_p, NULL) 833 834 add_prop(nodeh, &proph, node_name, row, 835 PP_RATE_UNITS, snmp_syserr_p); 836 CHECK_LINKRESET(snmp_syserr_p, NULL) 837 838 add_thresholds(nodeh, row, snmp_syserr_p); 839 CHECK_LINKRESET(snmp_syserr_p, NULL) 840 841 } else if (sensor_class == SSSC_BINARY) { 842 if (sensor_type == SSST_TEMPERATURE) { 843 ADD_NODE(PICL_CLASS_TEMPERATURE_INDICATOR) 844 } else if (sensor_type == SSST_VOLTAGE) { 845 ADD_NODE(PICL_CLASS_VOLTAGE_INDICATOR) 846 } else if (sensor_type == SSST_CURRENT) { 847 ADD_NODE(PICL_CLASS_CURRENT_INDICATOR) 848 } else if (sensor_type == SSST_TACHOMETER) { 849 ADD_NODE(PICL_CLASS_RPM_INDICATOR) 850 } else if (sensor_type == SSST_PRESENCE) { 851 ADD_NODE(PICL_CLASS_PRESENCE_INDICATOR) 852 } else { 853 ADD_NODE(PICL_CLASS_INDICATOR) 854 } 855 856 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 857 snmp_syserr_p); 858 CHECK_LINKRESET(snmp_syserr_p, NULL) 859 860 add_prop(nodeh, &proph, node_name, row, PP_CONDITION, 861 snmp_syserr_p); 862 CHECK_LINKRESET(snmp_syserr_p, NULL) 863 864 add_prop(nodeh, &proph, node_name, row, PP_EXPECTED, 865 snmp_syserr_p); 866 CHECK_LINKRESET(snmp_syserr_p, NULL) 867 } else { 868 log_msg(LOG_ERR, 869 SNMPP_UNSUPP_SENSOR_CLASS, sensor_class, row); 870 return (NULL); 871 } 872 break; 873 874 case SPC_MODULE: 875 ADD_NODE(PICL_CLASS_MODULE) 876 877 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 878 snmp_syserr_p); 879 CHECK_LINKRESET(snmp_syserr_p, NULL) 880 881 add_prop(nodeh, &proph, node_name, row, PP_REPLACEABLE, 882 snmp_syserr_p); 883 CHECK_LINKRESET(snmp_syserr_p, NULL) 884 885 add_prop(nodeh, &proph, node_name, row, PP_HOTSWAPPABLE, 886 snmp_syserr_p); 887 CHECK_LINKRESET(snmp_syserr_p, NULL) 888 break; 889 890 case SPC_PORT: 891 ADD_NODE(PICL_CLASS_PORT) 892 break; 893 894 case SPC_STACK: 895 ADD_NODE(PICL_CLASS_STACK) 896 break; 897 898 default: 899 log_msg(LOG_WARNING, 900 SNMPP_UNKNOWN_ENTPHYSCLASS, ent_physclass, row); 901 free(phys_name); 902 return (NULL); 903 } 904 905 add_prop(nodeh, &proph, node_name, row, PP_DESCRIPTION, snmp_syserr_p); 906 CHECK_LINKRESET(snmp_syserr_p, NULL) 907 908 add_prop(nodeh, &proph, node_name, row, PP_LABEL, snmp_syserr_p); 909 CHECK_LINKRESET(snmp_syserr_p, NULL) 910 911 add_prop(nodeh, &proph, node_name, row, PP_HW_REVISION, snmp_syserr_p); 912 CHECK_LINKRESET(snmp_syserr_p, NULL) 913 914 add_prop(nodeh, &proph, node_name, row, PP_FW_REVISION, snmp_syserr_p); 915 CHECK_LINKRESET(snmp_syserr_p, NULL) 916 917 add_prop(nodeh, &proph, node_name, row, PP_SERIAL_NUM, snmp_syserr_p); 918 CHECK_LINKRESET(snmp_syserr_p, NULL) 919 920 add_prop(nodeh, &proph, node_name, row, PP_MFG_NAME, snmp_syserr_p); 921 CHECK_LINKRESET(snmp_syserr_p, NULL) 922 923 add_prop(nodeh, &proph, node_name, row, PP_MODEL_NAME, snmp_syserr_p); 924 CHECK_LINKRESET(snmp_syserr_p, NULL) 925 926 add_prop(nodeh, &proph, node_name, row, PP_IS_FRU, snmp_syserr_p); 927 CHECK_LINKRESET(snmp_syserr_p, NULL) 928 929 free(phys_name); 930 save_nodeh(nodeh, row); 931 932 return (nodeh); 933 } 934 935 /* 936 * Saves the node handle and the row id into physplat_nodes[]. If we're 937 * doing this in response to a hotplug event, we should've freed the 938 * old physplat_nodes before entering here to save the first node of the 939 * new physplat subtree. 940 */ 941 static void 942 save_nodeh(picl_nodehdl_t nodeh, int row) 943 { 944 size_t sz, count; 945 picl_nodehdl_t *p; 946 947 if (row >= n_physplat_nodes) { 948 count = (((size_t)row >> NODE_BLOCK_SHIFT) + 1) * 949 N_ELEMS_IN_NODE_BLOCK; 950 sz = count * sizeof (picl_nodehdl_t); 951 952 p = (picl_nodehdl_t *)calloc(count, sizeof (picl_nodehdl_t)); 953 if (p == NULL) { 954 log_msg(LOG_ERR, SNMPP_NO_MEM, sz); 955 return; 956 } 957 958 if (physplat_nodes) { 959 (void) memcpy((void *) p, (void *) physplat_nodes, 960 n_physplat_nodes * sizeof (picl_nodehdl_t)); 961 free((void *) physplat_nodes); 962 } 963 964 physplat_nodes = p; 965 n_physplat_nodes = count; 966 } 967 968 physplat_nodes[row] = nodeh; 969 } 970 971 static picl_nodehdl_t 972 lookup_nodeh(int row) 973 { 974 if (row >= n_physplat_nodes) 975 return (NULL); 976 977 return (physplat_nodes[row]); 978 } 979 980 /* 981 * We enter this routine only when we are building the physical-platform 982 * subtree, whether for the first time or in response to a hotplug event. 983 * If we're here for rebuilding the tree, we have already set stale_tree 984 * to be B_TRUE, so no one else would be accessing vol_props, n_vol_props 985 * or volprop_ndx. If we're here to build the tree for the first time, 986 * picld hasn't yet created doors and is running single-threaded, so no 987 * one else would be accessing them anyway. 988 */ 989 static void 990 save_volprop(picl_prophdl_t prop, char *oidstr, int row, int proptype) 991 { 992 vol_prophdl_t *p; 993 int count; 994 995 if (volprop_ndx == n_vol_props) { 996 count = n_vol_props + N_ELEMS_IN_VOLPROP_BLOCK; 997 p = (vol_prophdl_t *)calloc(count, sizeof (vol_prophdl_t)); 998 if (p == NULL) { 999 log_msg(LOG_ERR, SNMPP_NO_MEM, 1000 count * sizeof (vol_prophdl_t)); 1001 return; 1002 } 1003 1004 if (vol_props) { 1005 (void) memcpy((void *) p, (void *) vol_props, 1006 n_vol_props * sizeof (vol_prophdl_t)); 1007 free((void *) vol_props); 1008 } 1009 1010 vol_props = p; 1011 n_vol_props += N_ELEMS_IN_VOLPROP_BLOCK; 1012 } 1013 1014 vol_props[volprop_ndx].prop = prop; 1015 vol_props[volprop_ndx].oidstr = oidstr; 1016 vol_props[volprop_ndx].row = row; 1017 vol_props[volprop_ndx].proptype = proptype; 1018 1019 volprop_ndx++; 1020 } 1021 1022 static void 1023 check_for_stale_data(boolean_t nocache) 1024 { 1025 int cur_change_time; 1026 int ret; 1027 int snmp_syserr; 1028 1029 (void) rw_wrlock(&stale_tree_rwlp); 1030 1031 /* 1032 * Check if some other thread beat us to it 1033 */ 1034 if (stale_tree == B_TRUE) { 1035 (void) rw_unlock(&stale_tree_rwlp); 1036 return; 1037 } 1038 1039 /* 1040 * Cache OID_entLastChangeTime for up to 10 seconds before 1041 * fetching it from ILOM again. This prevents us from fetching 1042 * this value from ILOM when the we're filling or refreshing a 1043 * whole bunch of items in the cache around the same time. 1044 */ 1045 if (nocache == B_FALSE && time(NULL) - change_time_check <= 10) { 1046 (void) rw_unlock(&stale_tree_rwlp); 1047 return; 1048 } 1049 1050 /* 1051 * Check if mib data has changed (hotplug? link-reset?) 1052 */ 1053 ret = snmp_get_int(hdl, OID_entLastChangeTime, 0, &cur_change_time, 1054 &snmp_syserr); 1055 (void) time(&change_time_check); 1056 if ((ret == 0) && (cur_change_time == change_time)) { 1057 (void) rw_unlock(&stale_tree_rwlp); 1058 return; 1059 } 1060 1061 /* 1062 * If we can't read entLastChangeTime we assume we need to rebuild 1063 * the tree. This will also cover the case when we need to rebuild 1064 * the tree because a link reset had happened. 1065 */ 1066 LOGPRINTF2("check_for_stale_data: LastChange times have changed, " 1067 "(%#x != %#x)\n", change_time, cur_change_time); 1068 1069 /* 1070 * If the mib data has changed, we need to rebuild the physical-platform 1071 * subtree. To do this, we set a flag to mark the tree stale, 1072 * so that any future reads to get value of volatile properties will 1073 * return PICL_PROPVALUNAVAILABLE, until the stale_tree flag 1074 * is reset by the tree builder thread. 1075 */ 1076 stale_tree = B_TRUE; 1077 if (vol_props) { 1078 free(vol_props); 1079 } 1080 vol_props = NULL; 1081 volprop_ndx = 0; 1082 n_vol_props = 0; 1083 1084 (void) rw_unlock(&stale_tree_rwlp); 1085 1086 (void) mutex_lock(&rebuild_tree_lock); 1087 rebuild_tree = B_TRUE; 1088 (void) cond_signal(&rebuild_tree_cv); 1089 LOGPRINTF("check_for_stale_data: signalled tree builder\n"); 1090 (void) mutex_unlock(&rebuild_tree_lock); 1091 } 1092 1093 /* 1094 * This is the critical routine. This callback is invoked by picl whenever 1095 * it needs to fetch the value of a volatile property. The first thing we 1096 * must do, however, is to see if there has been a hotplug or a link-reset 1097 * event since the last time we built the tree and whether we need to 1098 * rebuild the tree. If so, we do whatever is necessary to make that happen, 1099 * but return PICL_PROPVALUNAVAILABLE for now, without making any further 1100 * snmp requests or accessing any globals. 1101 */ 1102 static int 1103 read_volprop(ptree_rarg_t *parg, void *buf) 1104 { 1105 char *pstr; 1106 int propval; 1107 int i, ndx; 1108 int ret; 1109 int snmp_syserr = 0; 1110 1111 /* 1112 * First check for any event that would make us throw away 1113 * the existing /physical-platform subtree and rebuild 1114 * another one. If we are rebuilding the subtree, we just 1115 * return the stale value until the tree is fully built. 1116 */ 1117 check_for_stale_data(B_FALSE); 1118 1119 (void) rw_rdlock(&stale_tree_rwlp); 1120 1121 if (stale_tree == B_TRUE) { 1122 (void) rw_unlock(&stale_tree_rwlp); 1123 return (PICL_PROPVALUNAVAILABLE); 1124 } 1125 1126 for (i = 0; i < volprop_ndx; i++) { 1127 if (vol_props[i].prop == parg->proph) { 1128 ndx = i; 1129 break; 1130 } 1131 } 1132 if (i == volprop_ndx) { 1133 (void) rw_unlock(&stale_tree_rwlp); 1134 log_msg(LOG_ERR, SNMPP_CANT_FIND_VOLPROP, parg->proph); 1135 return (PICL_FAILURE); 1136 } 1137 1138 /* 1139 * If we can't read the value, return failure. Even if this was 1140 * due to a link reset, between the check for stale data and now, 1141 * the next volatile callback by picl will initiate a tree-rebuild. 1142 */ 1143 ret = snmp_get_int(hdl, vol_props[ndx].oidstr, vol_props[ndx].row, 1144 &propval, &snmp_syserr); 1145 if (ret < 0) { 1146 (void) rw_unlock(&stale_tree_rwlp); 1147 check_for_stale_data(B_TRUE); 1148 if (stale_tree == B_TRUE) { 1149 return (PICL_PROPVALUNAVAILABLE); 1150 } 1151 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1152 snmp_syserr ? snmp_syserr : ret, 1153 vol_props[ndx].oidstr, vol_props[ndx].row); 1154 return (PICL_FAILURE); 1155 } 1156 1157 switch (vol_props[ndx].proptype) { 1158 case VPT_PLATOPSTATE: 1159 if (propval == SSOS_DISABLED) { 1160 (void) strlcpy(buf, STR_SSOS_DISABLED, MAX_OPSTATE_LEN); 1161 } else if (propval == SSOS_ENABLED) { 1162 (void) strlcpy(buf, STR_SSOS_ENABLED, MAX_OPSTATE_LEN); 1163 } else { 1164 (void) rw_unlock(&stale_tree_rwlp); 1165 log_msg(LOG_ERR, SNMPP_INV_PLAT_EQUIP_OPSTATE, 1166 propval, vol_props[ndx].row); 1167 return (PICL_FAILURE); 1168 } 1169 break; 1170 1171 case VPT_NUMSENSOR: 1172 (void) memcpy(buf, &propval, sizeof (propval)); 1173 break; 1174 1175 case VPT_BINSENSOR: 1176 if (propval == ST_TRUE) { 1177 ret = snmp_get_str(hdl, 1178 OID_sunPlatBinarySensorInterpretTrue, 1179 vol_props[ndx].row, &pstr, &snmp_syserr); 1180 if (snmp_syserr == ECANCELED) { 1181 (void) rw_unlock(&stale_tree_rwlp); 1182 if (pstr) 1183 free(pstr); 1184 return (PICL_FAILURE); 1185 } 1186 if (ret < 0 || pstr == NULL) { 1187 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1188 snmp_syserr ? snmp_syserr : ret, 1189 OID_sunPlatBinarySensorInterpretTrue, 1190 vol_props[ndx].row); 1191 (void) strlcpy(buf, STR_ST_TRUE, 1192 MAX_TRUTHVAL_LEN); 1193 } else { 1194 (void) strlcpy(buf, pstr, MAX_TRUTHVAL_LEN); 1195 } 1196 if (pstr) 1197 free(pstr); 1198 } else if (propval == ST_FALSE) { 1199 ret = snmp_get_str(hdl, 1200 OID_sunPlatBinarySensorInterpretFalse, 1201 vol_props[ndx].row, &pstr, &snmp_syserr); 1202 if (snmp_syserr == ECANCELED) { 1203 (void) rw_unlock(&stale_tree_rwlp); 1204 if (pstr) 1205 free(pstr); 1206 return (PICL_FAILURE); 1207 } 1208 if (ret < 0 || pstr == NULL) { 1209 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1210 snmp_syserr ? snmp_syserr : ret, 1211 OID_sunPlatBinarySensorInterpretFalse, 1212 vol_props[ndx].row); 1213 (void) strlcpy(buf, STR_ST_FALSE, 1214 MAX_TRUTHVAL_LEN); 1215 } else { 1216 (void) strlcpy(buf, pstr, MAX_TRUTHVAL_LEN); 1217 } 1218 if (pstr) 1219 free(pstr); 1220 } else { 1221 (void) rw_unlock(&stale_tree_rwlp); 1222 log_msg(LOG_ERR, SNMPP_INV_PLAT_BINSNSR_CURRENT, 1223 propval, vol_props[ndx].row); 1224 return (PICL_FAILURE); 1225 } 1226 break; 1227 1228 case VPT_ALARMSTATE: 1229 if (propval == SSAS_OFF) { 1230 (void) strlcpy(buf, STR_SSAS_OFF, MAX_ALARMSTATE_LEN); 1231 } else if (propval == SSAS_STEADY) { 1232 (void) strlcpy(buf, STR_SSAS_STEADY, 1233 MAX_ALARMSTATE_LEN); 1234 } else if (propval == SSAS_ALTERNATING) { 1235 (void) strlcpy(buf, STR_SSAS_ALTERNATING, 1236 MAX_ALARMSTATE_LEN); 1237 } else { 1238 (void) strlcpy(buf, STR_SSAS_UNKNOWN, 1239 MAX_ALARMSTATE_LEN); 1240 } 1241 break; 1242 1243 case VPT_BATTERYSTATUS: 1244 switch (propval) { 1245 case SSBS_OTHER: 1246 (void) strlcpy(buf, STR_SSBS_OTHER, 1247 MAX_BATTERYSTATUS_LEN); 1248 break; 1249 case SSBS_FULLYCHARGED: 1250 (void) strlcpy(buf, STR_SSBS_FULLYCHARGED, 1251 MAX_BATTERYSTATUS_LEN); 1252 break; 1253 case SSBS_LOW: 1254 (void) strlcpy(buf, STR_SSBS_LOW, 1255 MAX_BATTERYSTATUS_LEN); 1256 break; 1257 case SSBS_CRITICAL: 1258 (void) strlcpy(buf, STR_SSBS_CRITICAL, 1259 MAX_BATTERYSTATUS_LEN); 1260 break; 1261 case SSBS_CHARGING: 1262 (void) strlcpy(buf, STR_SSBS_CHARGING, 1263 MAX_BATTERYSTATUS_LEN); 1264 break; 1265 case SSBS_CHARGING_AND_LOW: 1266 (void) strlcpy(buf, STR_SSBS_CHARGING_AND_LOW, 1267 MAX_BATTERYSTATUS_LEN); 1268 break; 1269 case SSBS_CHARGING_AND_HIGH: 1270 (void) strlcpy(buf, STR_SSBS_CHARGING_AND_HIGH, 1271 MAX_BATTERYSTATUS_LEN); 1272 break; 1273 case SSBS_CHARGING_AND_CRITICAL: 1274 (void) strlcpy(buf, STR_SSBS_CHARGING_AND_CRITICAL, 1275 MAX_BATTERYSTATUS_LEN); 1276 break; 1277 case SSBS_UNDEFINED: 1278 (void) strlcpy(buf, STR_SSBS_UNDEFINED, 1279 MAX_BATTERYSTATUS_LEN); 1280 break; 1281 case SSBS_PARTIALLY_CHARGED: 1282 (void) strlcpy(buf, STR_SSBS_PARTIALLY_CHARGED, 1283 MAX_BATTERYSTATUS_LEN); 1284 break; 1285 case SSBS_UNKNOWN: 1286 default: 1287 (void) strlcpy(buf, STR_SSBS_UNKNOWN, 1288 MAX_BATTERYSTATUS_LEN); 1289 break; 1290 } 1291 break; 1292 } 1293 1294 (void) rw_unlock(&stale_tree_rwlp); 1295 1296 return (PICL_SUCCESS); 1297 } 1298 1299 static void 1300 threshold(picl_nodehdl_t node, char *oidstr, int row, char *propname, 1301 int *snmp_syserr_p) 1302 { 1303 picl_prophdl_t prop; 1304 int err; 1305 int val; 1306 1307 if ((err = snmp_get_int(hdl, oidstr, row, &val, snmp_syserr_p)) != -1) { 1308 err = add_volatile_prop(node, propname, PICL_PTYPE_INT, 1309 PICL_READ, sizeof (int), read_volprop, NULL, &prop); 1310 if (err == PICL_SUCCESS) 1311 save_volprop(prop, oidstr, row, VPT_NUMSENSOR); 1312 } else 1313 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1314 *snmp_syserr_p ? *snmp_syserr_p : err, oidstr, row); 1315 } 1316 1317 static void 1318 add_thresholds(picl_nodehdl_t node, int row, int *snmp_syserr_p) 1319 { 1320 uchar_t *bitstr = NULL; 1321 uchar_t enabled; 1322 uint_t nbytes; 1323 int ret; 1324 1325 ret = snmp_get_str(hdl, 1326 OID_sunPlatNumericSensorEnabledThresholds, 1327 row, (char **)&bitstr, snmp_syserr_p); 1328 if (ret == -1) { 1329 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1330 *snmp_syserr_p ? *snmp_syserr_p : ret, 1331 OID_sunPlatNumericSensorEnabledThresholds, row); 1332 } else { 1333 nbytes = strlen((const char *)bitstr); 1334 } 1335 1336 CHECK_LINKRESET_VOID(snmp_syserr_p); 1337 1338 /* 1339 * No bit string of threshold masks was returned, so we can't 1340 * assume that any thresholds exist. 1341 * 1342 * This mask prevents us from attempting to fetch thresholds 1343 * which don't apply to the sensor or that aren't there anyway, 1344 * That speeds up the plug-in significantly since otherwise it 1345 * takes several seconds to time out. 1346 */ 1347 if (ret < 0 || bitstr == NULL || nbytes == 0 || 2 < nbytes) { 1348 if (bitstr) 1349 free(bitstr); 1350 return; 1351 } else if (nbytes == 1) { 1352 /* 1353 * The ALOM snmp agent doesn't adhere to the BER rules for 1354 * encoding bit strings. While the BER states that bitstrings 1355 * must begin from the second octet after length, and the 1356 * first octet after length must indicate the number of unused 1357 * bits in the last octet, the snmp agent simply sends the 1358 * bitstring data as if it were octet string -- that is, the 1359 * "unused bits" octet is missing. 1360 */ 1361 enabled = bitstr[0]; 1362 } else if (nbytes == 2) 1363 enabled = bitstr[1]; 1364 1365 if (bitstr) { 1366 free(bitstr); 1367 } 1368 1369 if (enabled & LOWER_FATAL) { 1370 threshold(node, 1371 OID_sunPlatNumericSensorLowerThresholdFatal, row, 1372 PICL_PROP_LOW_POWER_OFF, snmp_syserr_p); 1373 CHECK_LINKRESET_VOID(snmp_syserr_p) 1374 } 1375 if (enabled & LOWER_CRITICAL) { 1376 threshold(node, 1377 OID_sunPlatNumericSensorLowerThresholdCritical, row, 1378 PICL_PROP_LOW_SHUTDOWN, snmp_syserr_p); 1379 CHECK_LINKRESET_VOID(snmp_syserr_p) 1380 } 1381 if (enabled & LOWER_NON_CRITICAL) { 1382 threshold(node, 1383 OID_sunPlatNumericSensorLowerThresholdNonCritical, row, 1384 PICL_PROP_LOW_WARNING, snmp_syserr_p); 1385 CHECK_LINKRESET_VOID(snmp_syserr_p) 1386 } 1387 if (enabled & UPPER_NON_CRITICAL) { 1388 threshold(node, 1389 OID_sunPlatNumericSensorUpperThresholdNonCritical, row, 1390 PICL_PROP_HIGH_WARNING, snmp_syserr_p); 1391 CHECK_LINKRESET_VOID(snmp_syserr_p) 1392 } 1393 if (enabled & UPPER_CRITICAL) { 1394 threshold(node, 1395 OID_sunPlatNumericSensorUpperThresholdCritical, row, 1396 PICL_PROP_HIGH_SHUTDOWN, snmp_syserr_p); 1397 CHECK_LINKRESET_VOID(snmp_syserr_p) 1398 } 1399 if (enabled & UPPER_FATAL) { 1400 threshold(node, 1401 OID_sunPlatNumericSensorUpperThresholdFatal, row, 1402 PICL_PROP_HIGH_POWER_OFF, snmp_syserr_p); 1403 CHECK_LINKRESET_VOID(snmp_syserr_p) 1404 } 1405 } 1406 1407 static char * 1408 get_slot_type(int row, int *snmp_syserr_p) 1409 { 1410 char *p; 1411 char *slott = NULL; 1412 int ret; 1413 1414 ret = snmp_get_str(hdl, OID_sunPlatEquipmentHolderAcceptableTypes, 1415 row, &p, snmp_syserr_p); 1416 CHECK_LINKRESET(snmp_syserr_p, NULL) 1417 1418 if ((ret == 0) && p && *p) { 1419 slott = p; 1420 if ((p = strchr(slott, '\n')) != NULL) 1421 *p = 0; 1422 } else { 1423 log_msg(LOG_WARNING, SNMPP_NO_SLOT_TYPE, row); 1424 if (p) { 1425 free(p); 1426 } 1427 } 1428 1429 return (slott); 1430 } 1431 1432 /* 1433 * Create and add the specified volatile property 1434 */ 1435 static int 1436 add_volatile_prop(picl_nodehdl_t node, char *name, int type, int access, 1437 int size, int (*rdfunc)(ptree_rarg_t *, void *), 1438 int (*wrfunc)(ptree_warg_t *, const void *), picl_prophdl_t *propp) 1439 { 1440 ptree_propinfo_t propinfo; 1441 picl_prophdl_t prop; 1442 int err; 1443 1444 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1445 type, (access|PICL_VOLATILE), size, name, rdfunc, wrfunc); 1446 if (err != PICL_SUCCESS) { 1447 log_msg(LOG_ERR, SNMPP_CANT_INIT_PROPINFO, err); 1448 return (err); 1449 } 1450 1451 err = ptree_create_and_add_prop(node, &propinfo, NULL, &prop); 1452 if (err != PICL_SUCCESS) { 1453 log_msg(LOG_ERR, SNMPP_CANT_ADD_PROP, err, node); 1454 return (err); 1455 } 1456 1457 if (propp) 1458 *propp = prop; 1459 1460 return (PICL_SUCCESS); 1461 } 1462 1463 /* 1464 * Add the specified string property to the node 1465 */ 1466 static int 1467 add_string_prop(picl_nodehdl_t node, char *propname, char *propval) 1468 { 1469 ptree_propinfo_t propinfo; 1470 int err; 1471 1472 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1473 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(propval) + 1, 1474 propname, NULL, NULL); 1475 if (err != PICL_SUCCESS) { 1476 log_msg(LOG_ERR, SNMPP_CANT_INIT_STR_PROPINFO, err); 1477 return (err); 1478 } 1479 1480 err = ptree_create_and_add_prop(node, &propinfo, propval, NULL); 1481 if (err != PICL_SUCCESS) { 1482 log_msg(LOG_ERR, SNMPP_CANT_ADD_STR_PROP, err, node); 1483 return (err); 1484 } 1485 1486 return (PICL_SUCCESS); 1487 } 1488 1489 /* 1490 * Add the specified void property to the node 1491 */ 1492 static int 1493 add_void_prop(picl_nodehdl_t node, char *propname) 1494 { 1495 ptree_propinfo_t propinfo; 1496 int err; 1497 1498 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1499 PICL_PTYPE_VOID, PICL_READ, 0, propname, NULL, NULL); 1500 if (err != PICL_SUCCESS) { 1501 log_msg(LOG_ERR, SNMPP_CANT_INIT_VOID_PROPINFO, err); 1502 return (err); 1503 } 1504 1505 err = ptree_create_and_add_prop(node, &propinfo, NULL, NULL); 1506 if (err != PICL_SUCCESS) { 1507 log_msg(LOG_ERR, SNMPP_CANT_ADD_VOID_PROP, err, node); 1508 return (err); 1509 } 1510 1511 return (PICL_SUCCESS); 1512 } 1513 1514 static void 1515 add_prop(picl_nodehdl_t nodeh, picl_prophdl_t *php, char *label, 1516 int row, sp_propid_t pp, int *snmp_syserr_p) 1517 { 1518 char *serial_num; 1519 char *slot_type; 1520 char *fw_revision, *hw_revision; 1521 char *mfg_name, *model_name; 1522 char *phys_descr; 1523 int val; 1524 int ret; 1525 1526 switch (pp) { 1527 case PP_SERIAL_NUM: 1528 ret = snmp_get_str(hdl, OID_entPhysicalSerialNum, 1529 row, &serial_num, snmp_syserr_p); 1530 CHECK_LINKRESET_VOID(snmp_syserr_p) 1531 if ((ret == 0) && serial_num && *serial_num) { 1532 (void) add_string_prop(nodeh, 1533 PICL_PROP_SERIAL_NUMBER, serial_num); 1534 free((void *) serial_num); 1535 } 1536 if (ret == -1) 1537 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1538 *snmp_syserr_p ? *snmp_syserr_p : ret, 1539 OID_entPhysicalSerialNum, row); 1540 break; 1541 1542 case PP_SLOT_TYPE: 1543 if ((slot_type = get_slot_type(row, snmp_syserr_p)) == NULL) { 1544 CHECK_LINKRESET_VOID(snmp_syserr_p) 1545 (void) add_string_prop(nodeh, 1546 PICL_PROP_SLOT_TYPE, DEFAULT_SLOT_TYPE); 1547 } else { 1548 (void) add_string_prop(nodeh, 1549 PICL_PROP_SLOT_TYPE, slot_type); 1550 free((void *) slot_type); 1551 } 1552 break; 1553 1554 case PP_STATE: 1555 ret = add_volatile_prop(nodeh, PICL_PROP_STATE, 1556 PICL_PTYPE_CHARSTRING, PICL_READ, MAX_ALARMSTATE_LEN, 1557 read_volprop, NULL, php); 1558 if (ret == PICL_SUCCESS) { 1559 save_volprop(*php, OID_sunPlatAlarmState, row, 1560 VPT_ALARMSTATE); 1561 } 1562 break; 1563 1564 case PP_OPSTATUS: 1565 ret = add_volatile_prop(nodeh, PICL_PROP_OPERATIONAL_STATUS, 1566 PICL_PTYPE_CHARSTRING, PICL_READ, MAX_OPSTATE_LEN, 1567 read_volprop, NULL, php); 1568 if (ret == PICL_SUCCESS) { 1569 save_volprop(*php, 1570 OID_sunPlatEquipmentOperationalState, row, 1571 VPT_PLATOPSTATE); 1572 } 1573 break; 1574 1575 case PP_BATT_STATUS: 1576 ret = add_volatile_prop(nodeh, PICL_PROP_BATTERY_STATUS, 1577 PICL_PTYPE_CHARSTRING, PICL_READ, MAX_BATTERYSTATUS_LEN, 1578 read_volprop, NULL, php); 1579 if (ret == PICL_SUCCESS) { 1580 save_volprop(*php, OID_sunPlatBatteryStatus, row, 1581 VPT_BATTERYSTATUS); 1582 } 1583 break; 1584 1585 case PP_TEMPERATURE: 1586 ret = add_volatile_prop(nodeh, PICL_PROP_TEMPERATURE, 1587 PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 1588 NULL, php); 1589 if (ret == PICL_SUCCESS) { 1590 save_volprop(*php, OID_sunPlatNumericSensorCurrent, 1591 row, VPT_NUMSENSOR); 1592 } 1593 break; 1594 1595 case PP_VOLTAGE: 1596 ret = add_volatile_prop(nodeh, PICL_PROP_VOLTAGE, 1597 PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 1598 NULL, php); 1599 if (ret == PICL_SUCCESS) { 1600 save_volprop(*php, OID_sunPlatNumericSensorCurrent, 1601 row, VPT_NUMSENSOR); 1602 } 1603 break; 1604 1605 case PP_CURRENT: 1606 ret = add_volatile_prop(nodeh, PICL_PROP_CURRENT, 1607 PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 1608 NULL, php); 1609 if (ret == PICL_SUCCESS) { 1610 save_volprop(*php, OID_sunPlatNumericSensorCurrent, 1611 row, VPT_NUMSENSOR); 1612 } 1613 break; 1614 1615 case PP_SPEED: 1616 ret = add_volatile_prop(nodeh, PICL_PROP_SPEED, PICL_PTYPE_INT, 1617 PICL_READ, sizeof (int), read_volprop, NULL, php); 1618 if (ret == PICL_SUCCESS) { 1619 save_volprop(*php, OID_sunPlatNumericSensorCurrent, 1620 row, VPT_NUMSENSOR); 1621 } 1622 break; 1623 1624 case PP_SENSOR_VALUE: 1625 ret = add_volatile_prop(nodeh, PICL_PROP_SENSOR_VALUE, 1626 PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 1627 NULL, php); 1628 if (ret == PICL_SUCCESS) { 1629 save_volprop(*php, OID_sunPlatNumericSensorCurrent, 1630 row, VPT_NUMSENSOR); 1631 } 1632 break; 1633 1634 case PP_CONDITION: 1635 ret = add_volatile_prop(nodeh, PICL_PROP_CONDITION, 1636 PICL_PTYPE_CHARSTRING, PICL_READ, MAX_TRUTHVAL_LEN, 1637 read_volprop, NULL, php); 1638 if (ret == PICL_SUCCESS) { 1639 save_volprop(*php, OID_sunPlatBinarySensorCurrent, 1640 row, VPT_BINSENSOR); 1641 } 1642 break; 1643 1644 case PP_EXPECTED: 1645 ret = add_volatile_prop(nodeh, PICL_PROP_EXPECTED, 1646 PICL_PTYPE_CHARSTRING, PICL_READ, MAX_TRUTHVAL_LEN, 1647 read_volprop, NULL, php); 1648 if (ret == PICL_SUCCESS) { 1649 save_volprop(*php, OID_sunPlatBinarySensorExpected, 1650 row, VPT_BINSENSOR); 1651 } 1652 break; 1653 1654 case PP_EXPONENT: 1655 ret = add_volatile_prop(nodeh, PICL_PROP_EXPONENT, 1656 PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 1657 NULL, php); 1658 if (ret == PICL_SUCCESS) { 1659 save_volprop(*php, OID_sunPlatNumericSensorExponent, 1660 row, VPT_NUMSENSOR); 1661 } 1662 break; 1663 1664 case PP_REPLACEABLE: 1665 ret = snmp_get_int(hdl, OID_sunPlatCircuitPackReplaceable, 1666 row, &val, snmp_syserr_p); 1667 CHECK_LINKRESET_VOID(snmp_syserr_p) 1668 if ((ret == 0) && (val == ST_TRUE)) 1669 (void) add_void_prop(nodeh, PICL_PROP_IS_REPLACEABLE); 1670 if (ret == -1) 1671 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1672 *snmp_syserr_p ? *snmp_syserr_p : ret, 1673 OID_sunPlatCircuitPackReplaceable, row); 1674 break; 1675 1676 case PP_HOTSWAPPABLE: 1677 ret = snmp_get_int(hdl, OID_sunPlatCircuitPackHotSwappable, 1678 row, &val, snmp_syserr_p); 1679 CHECK_LINKRESET_VOID(snmp_syserr_p) 1680 if ((ret == 0) && (val == ST_TRUE)) 1681 (void) add_void_prop(nodeh, PICL_PROP_IS_HOT_SWAPPABLE); 1682 if (ret == -1) 1683 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1684 *snmp_syserr_p ? *snmp_syserr_p : ret, 1685 OID_sunPlatCircuitPackHotSwappable, row); 1686 break; 1687 1688 case PP_IS_FRU: 1689 ret = snmp_get_int(hdl, OID_entPhysicalIsFRU, row, 1690 &val, snmp_syserr_p); 1691 CHECK_LINKRESET_VOID(snmp_syserr_p) 1692 if ((ret == 0) && (val == ST_TRUE)) 1693 (void) add_void_prop(nodeh, PICL_PROP_IS_FRU); 1694 if (ret == -1) 1695 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1696 *snmp_syserr_p ? *snmp_syserr_p : ret, 1697 OID_entPhysicalIsFRU, row); 1698 break; 1699 1700 case PP_HW_REVISION: 1701 ret = snmp_get_str(hdl, OID_entPhysicalHardwareRev, 1702 row, &hw_revision, snmp_syserr_p); 1703 CHECK_LINKRESET_VOID(snmp_syserr_p) 1704 if ((ret == 0) && hw_revision && *hw_revision) { 1705 (void) add_string_prop(nodeh, 1706 PICL_PROP_HW_REVISION, hw_revision); 1707 free((void *) hw_revision); 1708 } 1709 if (ret == -1) 1710 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1711 *snmp_syserr_p ? *snmp_syserr_p : ret, 1712 OID_entPhysicalHardwareRev, row); 1713 break; 1714 1715 case PP_FW_REVISION: 1716 ret = snmp_get_str(hdl, OID_entPhysicalFirmwareRev, 1717 row, &fw_revision, snmp_syserr_p); 1718 CHECK_LINKRESET_VOID(snmp_syserr_p) 1719 if ((ret == 0) && fw_revision && *fw_revision) { 1720 (void) add_string_prop(nodeh, 1721 PICL_PROP_FW_REVISION, fw_revision); 1722 free((void *) fw_revision); 1723 } 1724 if (ret == -1) 1725 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1726 *snmp_syserr_p ? *snmp_syserr_p : ret, 1727 OID_entPhysicalFirmwareRev, row); 1728 break; 1729 1730 case PP_MFG_NAME: 1731 ret = snmp_get_str(hdl, OID_entPhysicalMfgName, 1732 row, &mfg_name, snmp_syserr_p); 1733 CHECK_LINKRESET_VOID(snmp_syserr_p) 1734 if ((ret == 0) && mfg_name && *mfg_name) { 1735 (void) add_string_prop(nodeh, 1736 PICL_PROP_MFG_NAME, mfg_name); 1737 free((void *) mfg_name); 1738 } 1739 if (ret == -1) 1740 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1741 *snmp_syserr_p ? *snmp_syserr_p : ret, 1742 OID_entPhysicalMfgName, row); 1743 break; 1744 1745 case PP_MODEL_NAME: 1746 ret = snmp_get_str(hdl, OID_entPhysicalModelName, 1747 row, &model_name, snmp_syserr_p); 1748 CHECK_LINKRESET_VOID(snmp_syserr_p) 1749 if ((ret == 0) && model_name && *model_name) { 1750 (void) add_string_prop(nodeh, 1751 PICL_PROP_MODEL_NAME, model_name); 1752 free((void *) model_name); 1753 } 1754 if (ret == -1) 1755 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1756 *snmp_syserr_p ? *snmp_syserr_p : ret, 1757 OID_entPhysicalModelName, row); 1758 break; 1759 1760 case PP_DESCRIPTION: 1761 ret = snmp_get_str(hdl, OID_entPhysicalDescr, 1762 row, &phys_descr, snmp_syserr_p); 1763 CHECK_LINKRESET_VOID(snmp_syserr_p) 1764 if ((ret == 0) && phys_descr && *phys_descr) { 1765 (void) add_string_prop(nodeh, 1766 PICL_PROP_PHYS_DESCRIPTION, phys_descr); 1767 free((void *) phys_descr); 1768 } 1769 if (ret == -1) 1770 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1771 *snmp_syserr_p ? *snmp_syserr_p : ret, 1772 OID_entPhysicalDescr, row); 1773 break; 1774 1775 case PP_LABEL: 1776 if (label && *label) 1777 (void) add_string_prop(nodeh, PICL_PROP_LABEL, label); 1778 break; 1779 1780 case PP_BASE_UNITS: 1781 ret = snmp_get_int(hdl, OID_sunPlatNumericSensorBaseUnits, 1782 row, &val, snmp_syserr_p); 1783 CHECK_LINKRESET_VOID(snmp_syserr_p) 1784 if ((ret == 0) && (val > 0) && (val < n_baseunits)) { 1785 (void) add_string_prop(nodeh, 1786 PICL_PROP_BASE_UNITS, sensor_baseunits[val]); 1787 } 1788 if (ret == -1) 1789 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1790 *snmp_syserr_p ? *snmp_syserr_p : ret, 1791 OID_sunPlatNumericSensorBaseUnits, row); 1792 break; 1793 1794 case PP_RATE_UNITS: 1795 ret = snmp_get_int(hdl, OID_sunPlatNumericSensorRateUnits, 1796 row, &val, snmp_syserr_p); 1797 CHECK_LINKRESET_VOID(snmp_syserr_p) 1798 if ((ret == 0) && (val > 0) && (val < n_rateunits)) { 1799 (void) add_string_prop(nodeh, 1800 PICL_PROP_RATE_UNITS, sensor_rateunits[val]); 1801 } 1802 if (ret == -1) 1803 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1804 *snmp_syserr_p ? *snmp_syserr_p : ret, 1805 OID_sunPlatNumericSensorRateUnits, row); 1806 break; 1807 } 1808 } 1809 1810 /*VARARGS2*/ 1811 static void 1812 log_msg(int pri, const char *fmt, ...) 1813 { 1814 va_list ap; 1815 1816 va_start(ap, fmt); 1817 vsyslog(pri, fmt, ap); 1818 va_end(ap); 1819 } 1820 1821 #ifdef SNMPPLUGIN_DEBUG 1822 1823 static void 1824 snmpplugin_log_init(void) 1825 { 1826 (void) mutex_init(&snmpplugin_dbuf_lock, USYNC_THREAD, NULL); 1827 } 1828 1829 static void 1830 snmpplugin_log(const char *fmt, ...) 1831 { 1832 va_list ap; 1833 1834 (void) mutex_lock(&snmpplugin_dbuf_lock); 1835 1836 va_start(ap, fmt); 1837 (void) vsnprintf(snmpplugin_lbuf, SNMPPLUGIN_DMAX_LINE, fmt, ap); 1838 snmpplugin_log_append(); 1839 va_end(ap); 1840 1841 (void) mutex_unlock(&snmpplugin_dbuf_lock); 1842 } 1843 1844 static void 1845 snmpplugin_log_append(void) 1846 { 1847 int len; 1848 1849 len = strlen(snmpplugin_lbuf); 1850 1851 if ((snmpplugin_dbuf_curp + len) >= 1852 (snmpplugin_dbuf + snmpplugin_dbuf_sz)) { 1853 snmpplugin_dbuf_realloc(); 1854 if (snmpplugin_dbuf == NULL) { 1855 return; 1856 } 1857 } 1858 1859 (void) strcpy(snmpplugin_dbuf_curp, snmpplugin_lbuf); 1860 snmpplugin_dbuf_curp += len; 1861 } 1862 1863 static void 1864 snmpplugin_dbuf_realloc(void) 1865 { 1866 char *p; 1867 size_t offset = 0; 1868 size_t count; 1869 1870 count = snmpplugin_dbuf_sz + SNMPPLUGIN_DBLOCK_SZ; 1871 if ((p = (char *)calloc(count, 1)) == NULL) { 1872 snmpplugin_dbuf_overflow++; 1873 snmpplugin_dbuf_curp = snmpplugin_dbuf; 1874 return; 1875 } 1876 1877 if (snmpplugin_dbuf) { 1878 offset = snmpplugin_dbuf_curp - snmpplugin_dbuf; 1879 (void) memcpy(p, snmpplugin_dbuf, snmpplugin_dbuf_sz); 1880 free(snmpplugin_dbuf); 1881 } 1882 1883 snmpplugin_dbuf = p; 1884 snmpplugin_dbuf_sz += SNMPPLUGIN_DBLOCK_SZ; 1885 1886 snmpplugin_dbuf_curp = snmpplugin_dbuf + offset; 1887 } 1888 #endif 1889