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