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 2007 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 log_msg(LOG_WARNING, 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 } 509 510 if (snmp_syserr == ECANCELED) { 511 /* 512 * If we get this error, a link reset must've 513 * happened and we need to throw away everything 514 * we have now and rebuild the tree again. 515 */ 516 log_msg(LOG_WARNING, SNMPP_LINK_RESET); 517 free_resources(*subtree_rootp); 518 clr_linkreset = 1; 519 goto retry; 520 } 521 if (ret == -1) 522 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 523 snmp_syserr ? snmp_syserr : ret, 524 OID_entPhysicalDescr, row); 525 } 526 527 /* 528 * Record LastChangeTime after we're done building the tree 529 */ 530 ret = snmp_get_int(hdl, OID_entLastChangeTime, 0, 531 &change_time, &snmp_syserr); 532 if (ret < 0) { 533 if (snmp_syserr == ECANCELED) { 534 log_msg(LOG_WARNING, SNMPP_LINK_RESET); 535 free_resources(*subtree_rootp); 536 clr_linkreset = 1; 537 goto retry; 538 } else 539 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 540 snmp_syserr ? snmp_syserr : ret, 541 OID_entLastChangeTime, row); 542 } 543 544 /* 545 * If they don't match, some hotplugging must've happened, 546 * free resources we've created and still holding, then go 547 * back and retry 548 */ 549 if (change_time != change_time1) { 550 LOGPRINTF("build_physplat: entLastChangeTime has changed!\n"); 551 free_resources(*subtree_rootp); 552 change_time1 = change_time; 553 goto retry; 554 } 555 556 /* 557 * The physplat_nodes table is no longer needed, free it 558 */ 559 if (physplat_nodes) { 560 free(physplat_nodes); 561 physplat_nodes = NULL; 562 n_physplat_nodes = 0; 563 } 564 565 return (0); 566 } 567 568 /* 569 * Destroy all resources that were created during the building 570 * of the subtree 571 */ 572 static void 573 free_resources(picl_nodehdl_t subtree_root) 574 { 575 if (physplat_nodes) { 576 free(physplat_nodes); 577 physplat_nodes = NULL; 578 n_physplat_nodes = 0; 579 } 580 581 if (subtree_root) { 582 (void) ptree_delete_node(subtree_root); 583 (void) ptree_destroy_node(subtree_root); 584 } 585 586 if (vol_props) { 587 free(vol_props); 588 n_vol_props = 0; 589 volprop_ndx = 0; 590 } 591 } 592 593 static picl_nodehdl_t 594 make_node(picl_nodehdl_t subtree_root, int row, int *snmp_syserr_p) 595 { 596 picl_nodehdl_t nodeh, parenth; 597 picl_prophdl_t proph; 598 char *phys_name, *node_name; 599 int parent_row; 600 int ent_physclass, sunplat_physclass; 601 int sensor_class, sensor_type; 602 int alarm_type; 603 int ps_class; 604 int ret; 605 606 /* 607 * If we've already created this picl node, just return it 608 */ 609 if ((nodeh = lookup_nodeh(row)) != NULL) 610 return (nodeh); 611 612 /* 613 * If we are creating it only now, make sure we have the parent 614 * created first; if there's no parent, then parent it to the 615 * subtree's root node 616 */ 617 ret = snmp_get_int(hdl, OID_entPhysicalContainedIn, row, 618 &parent_row, snmp_syserr_p); 619 CHECK_LINKRESET(snmp_syserr_p, NULL) 620 if (ret < 0 || parent_row <= 0) 621 parenth = subtree_root; 622 else { 623 parenth = make_node(subtree_root, parent_row, snmp_syserr_p); 624 CHECK_LINKRESET(snmp_syserr_p, NULL) 625 if (parenth == NULL) 626 parenth = subtree_root; 627 } 628 629 /* 630 * Figure out the physical-platform node name from entPhysicalName; 631 * all rows in the MIB that have a valid entPhysicalIndex should 632 * have a physical name. 633 */ 634 ret = snmp_get_str(hdl, OID_entPhysicalName, row, 635 &phys_name, snmp_syserr_p); 636 CHECK_LINKRESET(snmp_syserr_p, NULL) 637 if (ret < 0 || phys_name == NULL) { 638 log_msg(LOG_WARNING, SNMPP_NO_ENTPHYSNAME, row); 639 return (NULL); 640 } 641 642 node_name = basename(phys_name); 643 644 ret = snmp_get_int(hdl, OID_entPhysicalClass, row, 645 &ent_physclass, snmp_syserr_p); 646 CHECK_LINKRESET(snmp_syserr_p, NULL) 647 if (ret < 0) { 648 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 649 *snmp_syserr_p ? *snmp_syserr_p : ret, 650 OID_entPhysicalClass, row); 651 free(phys_name); 652 return (NULL); 653 } 654 655 switch (ent_physclass) { 656 case SPC_OTHER: 657 ret = snmp_get_int(hdl, OID_sunPlatPhysicalClass, row, 658 &sunplat_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_sunPlatPhysicalClass, row); 664 free(phys_name); 665 return (NULL); 666 } 667 668 if (sunplat_physclass == SSPC_ALARM) { 669 ret = snmp_get_int(hdl, OID_sunPlatAlarmType, 670 row, &alarm_type, snmp_syserr_p); 671 CHECK_LINKRESET(snmp_syserr_p, NULL) 672 if (ret < 0) { 673 log_msg(LOG_WARNING, 674 SNMPP_CANT_FETCH_OBJECT_VAL, 675 *snmp_syserr_p ? *snmp_syserr_p : ret, 676 OID_sunPlatAlarmType, row); 677 free(phys_name); 678 return (NULL); 679 } 680 681 if (alarm_type == SSAT_VISIBLE) { 682 ADD_NODE(PICL_CLASS_LED) 683 } else { 684 ADD_NODE(PICL_CLASS_ALARM) 685 } 686 687 add_prop(nodeh, &proph, node_name, row, PP_STATE, 688 snmp_syserr_p); 689 CHECK_LINKRESET(snmp_syserr_p, NULL) 690 } else { 691 ADD_NODE(PICL_CLASS_OTHER) 692 } 693 694 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 695 snmp_syserr_p); 696 CHECK_LINKRESET(snmp_syserr_p, NULL) 697 break; 698 699 case SPC_UNKNOWN: 700 ADD_NODE(PICL_CLASS_UNKNOWN) 701 break; 702 703 case SPC_CHASSIS: 704 ADD_NODE(PICL_CLASS_CHASSIS) 705 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 706 snmp_syserr_p); 707 CHECK_LINKRESET(snmp_syserr_p, NULL) 708 break; 709 710 case SPC_BACKPLANE: 711 ADD_NODE(PICL_CLASS_BACKPLANE) 712 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 713 snmp_syserr_p); 714 CHECK_LINKRESET(snmp_syserr_p, NULL) 715 break; 716 717 case SPC_CONTAINER: 718 ADD_NODE(PICL_CLASS_CONTAINER) 719 720 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 721 snmp_syserr_p); 722 CHECK_LINKRESET(snmp_syserr_p, NULL) 723 724 add_prop(nodeh, &proph, node_name, row, PP_SLOT_TYPE, 725 snmp_syserr_p); 726 CHECK_LINKRESET(snmp_syserr_p, NULL) 727 break; 728 729 case SPC_POWERSUPPLY: 730 ret = snmp_get_int(hdl, OID_sunPlatPowerSupplyClass, 731 row, &ps_class, snmp_syserr_p); 732 CHECK_LINKRESET(snmp_syserr_p, NULL) 733 if (ret < 0) { 734 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 735 *snmp_syserr_p ? *snmp_syserr_p : ret, 736 OID_sunPlatPowerSupplyClass, row); 737 free(phys_name); 738 return (NULL); 739 } 740 741 if (ps_class == SSPSC_BATTERY) { 742 ADD_NODE(PICL_CLASS_BATTERY) 743 add_prop(nodeh, &proph, node_name, row, 744 PP_BATT_STATUS, snmp_syserr_p); 745 CHECK_LINKRESET(snmp_syserr_p, NULL) 746 } else { 747 ADD_NODE(PICL_CLASS_POWERSUPPLY) 748 } 749 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 750 snmp_syserr_p); 751 CHECK_LINKRESET(snmp_syserr_p, NULL) 752 break; 753 754 case SPC_FAN: 755 ADD_NODE(PICL_CLASS_FAN) 756 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 757 snmp_syserr_p); 758 CHECK_LINKRESET(snmp_syserr_p, NULL) 759 break; 760 761 case SPC_SENSOR: 762 ret = snmp_get_int(hdl, OID_sunPlatSensorClass, 763 row, &sensor_class, snmp_syserr_p); 764 CHECK_LINKRESET(snmp_syserr_p, NULL) 765 if (ret < 0) { 766 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 767 *snmp_syserr_p ? *snmp_syserr_p : ret, 768 OID_sunPlatSensorClass, row); 769 free(phys_name); 770 return (NULL); 771 } 772 773 ret = snmp_get_int(hdl, OID_sunPlatSensorType, 774 row, &sensor_type, snmp_syserr_p); 775 CHECK_LINKRESET(snmp_syserr_p, NULL) 776 if (ret < 0) { 777 log_msg(LOG_WARNING, SNMPP_CANT_FETCH_OBJECT_VAL, 778 *snmp_syserr_p ? *snmp_syserr_p : ret, 779 OID_sunPlatSensorType, row); 780 free(phys_name); 781 return (NULL); 782 } 783 784 if (sensor_class == SSSC_NUMERIC) { 785 if (sensor_type == SSST_TEMPERATURE) { 786 ADD_NODE(PICL_CLASS_TEMPERATURE_SENSOR) 787 add_prop(nodeh, &proph, node_name, row, 788 PP_TEMPERATURE, snmp_syserr_p); 789 } else if (sensor_type == SSST_VOLTAGE) { 790 ADD_NODE(PICL_CLASS_VOLTAGE_SENSOR) 791 add_prop(nodeh, &proph, node_name, row, 792 PP_VOLTAGE, snmp_syserr_p); 793 } else if (sensor_type == SSST_CURRENT) { 794 ADD_NODE(PICL_CLASS_CURRENT_SENSOR) 795 add_prop(nodeh, &proph, node_name, row, 796 PP_CURRENT, snmp_syserr_p); 797 } else if (sensor_type == SSST_TACHOMETER) { 798 ADD_NODE(PICL_CLASS_RPM_SENSOR) 799 add_prop(nodeh, &proph, node_name, row, 800 PP_SPEED, snmp_syserr_p); 801 } else { 802 ADD_NODE(PICL_CLASS_SENSOR) 803 add_prop(nodeh, &proph, node_name, row, 804 PP_SENSOR_VALUE, snmp_syserr_p); 805 } 806 CHECK_LINKRESET(snmp_syserr_p, NULL) 807 808 add_prop(nodeh, &proph, node_name, row, 809 PP_OPSTATUS, snmp_syserr_p); 810 CHECK_LINKRESET(snmp_syserr_p, NULL) 811 812 add_prop(nodeh, &proph, node_name, row, 813 PP_BASE_UNITS, snmp_syserr_p); 814 CHECK_LINKRESET(snmp_syserr_p, NULL) 815 816 add_prop(nodeh, &proph, node_name, row, 817 PP_EXPONENT, snmp_syserr_p); 818 CHECK_LINKRESET(snmp_syserr_p, NULL) 819 820 add_prop(nodeh, &proph, node_name, row, 821 PP_RATE_UNITS, snmp_syserr_p); 822 CHECK_LINKRESET(snmp_syserr_p, NULL) 823 824 add_thresholds(nodeh, row, snmp_syserr_p); 825 CHECK_LINKRESET(snmp_syserr_p, NULL) 826 827 } else if (sensor_class == SSSC_BINARY) { 828 if (sensor_type == SSST_TEMPERATURE) { 829 ADD_NODE(PICL_CLASS_TEMPERATURE_INDICATOR) 830 } else if (sensor_type == SSST_VOLTAGE) { 831 ADD_NODE(PICL_CLASS_VOLTAGE_INDICATOR) 832 } else if (sensor_type == SSST_CURRENT) { 833 ADD_NODE(PICL_CLASS_CURRENT_INDICATOR) 834 } else if (sensor_type == SSST_TACHOMETER) { 835 ADD_NODE(PICL_CLASS_RPM_INDICATOR) 836 } else if (sensor_type == SSST_PRESENCE) { 837 ADD_NODE(PICL_CLASS_PRESENCE_INDICATOR) 838 } else { 839 ADD_NODE(PICL_CLASS_INDICATOR) 840 } 841 842 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 843 snmp_syserr_p); 844 CHECK_LINKRESET(snmp_syserr_p, NULL) 845 846 add_prop(nodeh, &proph, node_name, row, PP_CONDITION, 847 snmp_syserr_p); 848 CHECK_LINKRESET(snmp_syserr_p, NULL) 849 850 add_prop(nodeh, &proph, node_name, row, PP_EXPECTED, 851 snmp_syserr_p); 852 CHECK_LINKRESET(snmp_syserr_p, NULL) 853 } else { 854 log_msg(LOG_ERR, 855 SNMPP_UNSUPP_SENSOR_CLASS, sensor_class, row); 856 return (NULL); 857 } 858 break; 859 860 case SPC_MODULE: 861 ADD_NODE(PICL_CLASS_MODULE) 862 863 add_prop(nodeh, &proph, node_name, row, PP_OPSTATUS, 864 snmp_syserr_p); 865 CHECK_LINKRESET(snmp_syserr_p, NULL) 866 867 add_prop(nodeh, &proph, node_name, row, PP_REPLACEABLE, 868 snmp_syserr_p); 869 CHECK_LINKRESET(snmp_syserr_p, NULL) 870 871 add_prop(nodeh, &proph, node_name, row, PP_HOTSWAPPABLE, 872 snmp_syserr_p); 873 CHECK_LINKRESET(snmp_syserr_p, NULL) 874 break; 875 876 case SPC_PORT: 877 ADD_NODE(PICL_CLASS_PORT) 878 break; 879 880 case SPC_STACK: 881 ADD_NODE(PICL_CLASS_STACK) 882 break; 883 884 default: 885 log_msg(LOG_WARNING, 886 SNMPP_UNKNOWN_ENTPHYSCLASS, ent_physclass, row); 887 free(phys_name); 888 return (NULL); 889 } 890 891 add_prop(nodeh, &proph, node_name, row, PP_DESCRIPTION, snmp_syserr_p); 892 CHECK_LINKRESET(snmp_syserr_p, NULL) 893 894 add_prop(nodeh, &proph, node_name, row, PP_LABEL, snmp_syserr_p); 895 CHECK_LINKRESET(snmp_syserr_p, NULL) 896 897 add_prop(nodeh, &proph, node_name, row, PP_HW_REVISION, snmp_syserr_p); 898 CHECK_LINKRESET(snmp_syserr_p, NULL) 899 900 add_prop(nodeh, &proph, node_name, row, PP_FW_REVISION, snmp_syserr_p); 901 CHECK_LINKRESET(snmp_syserr_p, NULL) 902 903 add_prop(nodeh, &proph, node_name, row, PP_SERIAL_NUM, snmp_syserr_p); 904 CHECK_LINKRESET(snmp_syserr_p, NULL) 905 906 add_prop(nodeh, &proph, node_name, row, PP_MFG_NAME, snmp_syserr_p); 907 CHECK_LINKRESET(snmp_syserr_p, NULL) 908 909 add_prop(nodeh, &proph, node_name, row, PP_MODEL_NAME, snmp_syserr_p); 910 CHECK_LINKRESET(snmp_syserr_p, NULL) 911 912 add_prop(nodeh, &proph, node_name, row, PP_IS_FRU, snmp_syserr_p); 913 CHECK_LINKRESET(snmp_syserr_p, NULL) 914 915 free(phys_name); 916 save_nodeh(nodeh, row); 917 918 return (nodeh); 919 } 920 921 /* 922 * Saves the node handle and the row id into physplat_nodes[]. If we're 923 * doing this in response to a hotplug event, we should've freed the 924 * old physplat_nodes before entering here to save the first node of the 925 * new physplat subtree. 926 */ 927 static void 928 save_nodeh(picl_nodehdl_t nodeh, int row) 929 { 930 size_t sz, count; 931 picl_nodehdl_t *p; 932 933 if (row >= n_physplat_nodes) { 934 count = (((size_t)row >> NODE_BLOCK_SHIFT) + 1) * 935 N_ELEMS_IN_NODE_BLOCK; 936 sz = count * sizeof (picl_nodehdl_t); 937 938 p = (picl_nodehdl_t *)calloc(count, sizeof (picl_nodehdl_t)); 939 if (p == NULL) { 940 log_msg(LOG_ERR, SNMPP_NO_MEM, sz); 941 return; 942 } 943 944 if (physplat_nodes) { 945 (void) memcpy((void *) p, (void *) physplat_nodes, 946 n_physplat_nodes * sizeof (picl_nodehdl_t)); 947 free((void *) physplat_nodes); 948 } 949 950 physplat_nodes = p; 951 n_physplat_nodes = count; 952 } 953 954 physplat_nodes[row] = nodeh; 955 } 956 957 static picl_nodehdl_t 958 lookup_nodeh(int row) 959 { 960 if (row >= n_physplat_nodes) 961 return (NULL); 962 963 return (physplat_nodes[row]); 964 } 965 966 /* 967 * We enter this routine only when we are building the physical-platform 968 * subtree, whether for the first time or in response to a hotplug event. 969 * If we're here for rebuilding the tree, we have already set stale_tree 970 * to be B_TRUE, so no one else would be accessing vol_props, n_vol_props 971 * or volprop_ndx. If we're here to build the tree for the first time, 972 * picld hasn't yet created doors and is running single-threaded, so no 973 * one else would be accessing them anyway. 974 */ 975 static void 976 save_volprop(picl_prophdl_t prop, char *oidstr, int row, int proptype) 977 { 978 vol_prophdl_t *p; 979 int count; 980 981 if (volprop_ndx == n_vol_props) { 982 count = n_vol_props + N_ELEMS_IN_VOLPROP_BLOCK; 983 p = (vol_prophdl_t *)calloc(count, sizeof (vol_prophdl_t)); 984 if (p == NULL) { 985 log_msg(LOG_ERR, SNMPP_NO_MEM, 986 count * sizeof (vol_prophdl_t)); 987 return; 988 } 989 990 if (vol_props) { 991 (void) memcpy((void *) p, (void *) vol_props, 992 n_vol_props * sizeof (vol_prophdl_t)); 993 free((void *) vol_props); 994 } 995 996 vol_props = p; 997 n_vol_props += N_ELEMS_IN_VOLPROP_BLOCK; 998 } 999 1000 vol_props[volprop_ndx].prop = prop; 1001 vol_props[volprop_ndx].oidstr = oidstr; 1002 vol_props[volprop_ndx].row = row; 1003 vol_props[volprop_ndx].proptype = proptype; 1004 1005 volprop_ndx++; 1006 } 1007 1008 static void 1009 check_for_stale_data(boolean_t nocache) 1010 { 1011 int cur_change_time; 1012 int ret; 1013 int snmp_syserr; 1014 1015 (void) rw_wrlock(&stale_tree_rwlp); 1016 1017 /* 1018 * Check if some other thread beat us to it 1019 */ 1020 if (stale_tree == B_TRUE) { 1021 (void) rw_unlock(&stale_tree_rwlp); 1022 return; 1023 } 1024 1025 /* 1026 * Cache OID_entLastChangeTime for up to 10 seconds before 1027 * fetching it from ILOM again. This prevents us from fetching 1028 * this value from ILOM when the we're filling or refreshing a 1029 * whole bunch of items in the cache around the same time. 1030 */ 1031 if (nocache == B_FALSE && time(NULL) - change_time_check <= 10) { 1032 (void) rw_unlock(&stale_tree_rwlp); 1033 return; 1034 } 1035 1036 /* 1037 * Check if mib data has changed (hotplug? link-reset?) 1038 */ 1039 ret = snmp_get_int(hdl, OID_entLastChangeTime, 0, &cur_change_time, 1040 &snmp_syserr); 1041 (void) time(&change_time_check); 1042 if ((ret == 0) && (cur_change_time == change_time)) { 1043 (void) rw_unlock(&stale_tree_rwlp); 1044 return; 1045 } 1046 1047 /* 1048 * If we can't read entLastChangeTime we assume we need to rebuild 1049 * the tree. This will also cover the case when we need to rebuild 1050 * the tree because a link reset had happened. 1051 */ 1052 LOGPRINTF2("check_for_stale_data: LastChange times have changed, " 1053 "(%#x != %#x)\n", change_time, cur_change_time); 1054 1055 /* 1056 * If the mib data has changed, we need to rebuild the physical-platform 1057 * subtree. To do this, we set a flag to mark the tree stale, 1058 * so that any future reads to get value of volatile properties will 1059 * return PICL_PROPVALUNAVAILABLE, until the stale_tree flag 1060 * is reset by the tree builder thread. 1061 */ 1062 stale_tree = B_TRUE; 1063 if (vol_props) { 1064 free(vol_props); 1065 } 1066 vol_props = NULL; 1067 volprop_ndx = 0; 1068 n_vol_props = 0; 1069 1070 (void) rw_unlock(&stale_tree_rwlp); 1071 1072 (void) mutex_lock(&rebuild_tree_lock); 1073 rebuild_tree = B_TRUE; 1074 (void) cond_signal(&rebuild_tree_cv); 1075 LOGPRINTF("check_for_stale_data: signalled tree builder\n"); 1076 (void) mutex_unlock(&rebuild_tree_lock); 1077 } 1078 1079 /* 1080 * This is the critical routine. This callback is invoked by picl whenever 1081 * it needs to fetch the value of a volatile property. The first thing we 1082 * must do, however, is to see if there has been a hotplug or a link-reset 1083 * event since the last time we built the tree and whether we need to 1084 * rebuild the tree. If so, we do whatever is necessary to make that happen, 1085 * but return PICL_PROPVALUNAVAILABLE for now, without making any further 1086 * snmp requests or accessing any globals. 1087 */ 1088 static int 1089 read_volprop(ptree_rarg_t *parg, void *buf) 1090 { 1091 char *pstr; 1092 int propval; 1093 int i, ndx; 1094 int ret; 1095 int snmp_syserr = 0; 1096 1097 /* 1098 * First check for any event that would make us throw away 1099 * the existing /physical-platform subtree and rebuild 1100 * another one. If we are rebuilding the subtree, we just 1101 * return the stale value until the tree is fully built. 1102 */ 1103 check_for_stale_data(B_FALSE); 1104 1105 (void) rw_rdlock(&stale_tree_rwlp); 1106 1107 if (stale_tree == B_TRUE) { 1108 (void) rw_unlock(&stale_tree_rwlp); 1109 return (PICL_PROPVALUNAVAILABLE); 1110 } 1111 1112 for (i = 0; i < volprop_ndx; i++) { 1113 if (vol_props[i].prop == parg->proph) { 1114 ndx = i; 1115 break; 1116 } 1117 } 1118 if (i == volprop_ndx) { 1119 (void) rw_unlock(&stale_tree_rwlp); 1120 log_msg(LOG_ERR, SNMPP_CANT_FIND_VOLPROP, parg->proph); 1121 return (PICL_FAILURE); 1122 } 1123 1124 /* 1125 * If we can't read the value, return failure. Even if this was 1126 * due to a link reset, between the check for stale data and now, 1127 * the next volatile callback by picl will initiate a tree-rebuild. 1128 */ 1129 ret = snmp_get_int(hdl, vol_props[ndx].oidstr, vol_props[ndx].row, 1130 &propval, &snmp_syserr); 1131 if (ret < 0) { 1132 (void) rw_unlock(&stale_tree_rwlp); 1133 check_for_stale_data(B_TRUE); 1134 if (stale_tree == B_TRUE) { 1135 return (PICL_PROPVALUNAVAILABLE); 1136 } 1137 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1138 snmp_syserr ? snmp_syserr : ret, 1139 vol_props[ndx].oidstr, vol_props[ndx].row); 1140 return (PICL_FAILURE); 1141 } 1142 1143 switch (vol_props[ndx].proptype) { 1144 case VPT_PLATOPSTATE: 1145 if (propval == SSOS_DISABLED) { 1146 (void) strlcpy(buf, STR_SSOS_DISABLED, MAX_OPSTATE_LEN); 1147 } else if (propval == SSOS_ENABLED) { 1148 (void) strlcpy(buf, STR_SSOS_ENABLED, MAX_OPSTATE_LEN); 1149 } else { 1150 (void) rw_unlock(&stale_tree_rwlp); 1151 log_msg(LOG_ERR, SNMPP_INV_PLAT_EQUIP_OPSTATE, 1152 propval, vol_props[ndx].row); 1153 return (PICL_FAILURE); 1154 } 1155 break; 1156 1157 case VPT_NUMSENSOR: 1158 (void) memcpy(buf, &propval, sizeof (propval)); 1159 break; 1160 1161 case VPT_BINSENSOR: 1162 if (propval == ST_TRUE) { 1163 ret = snmp_get_str(hdl, 1164 OID_sunPlatBinarySensorInterpretTrue, 1165 vol_props[ndx].row, &pstr, &snmp_syserr); 1166 if (snmp_syserr == ECANCELED) { 1167 (void) rw_unlock(&stale_tree_rwlp); 1168 if (pstr) 1169 free(pstr); 1170 return (PICL_FAILURE); 1171 } 1172 if (ret < 0 || pstr == NULL) { 1173 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1174 snmp_syserr ? snmp_syserr : ret, 1175 OID_sunPlatBinarySensorInterpretTrue, 1176 vol_props[ndx].row); 1177 (void) strlcpy(buf, STR_ST_TRUE, 1178 MAX_TRUTHVAL_LEN); 1179 } else { 1180 (void) strlcpy(buf, pstr, MAX_TRUTHVAL_LEN); 1181 } 1182 if (pstr) 1183 free(pstr); 1184 } else if (propval == ST_FALSE) { 1185 ret = snmp_get_str(hdl, 1186 OID_sunPlatBinarySensorInterpretFalse, 1187 vol_props[ndx].row, &pstr, &snmp_syserr); 1188 if (snmp_syserr == ECANCELED) { 1189 (void) rw_unlock(&stale_tree_rwlp); 1190 if (pstr) 1191 free(pstr); 1192 return (PICL_FAILURE); 1193 } 1194 if (ret < 0 || pstr == NULL) { 1195 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1196 snmp_syserr ? snmp_syserr : ret, 1197 OID_sunPlatBinarySensorInterpretFalse, 1198 vol_props[ndx].row); 1199 (void) strlcpy(buf, STR_ST_FALSE, 1200 MAX_TRUTHVAL_LEN); 1201 } else { 1202 (void) strlcpy(buf, pstr, MAX_TRUTHVAL_LEN); 1203 } 1204 if (pstr) 1205 free(pstr); 1206 } else { 1207 (void) rw_unlock(&stale_tree_rwlp); 1208 log_msg(LOG_ERR, SNMPP_INV_PLAT_BINSNSR_CURRENT, 1209 propval, vol_props[ndx].row); 1210 return (PICL_FAILURE); 1211 } 1212 break; 1213 1214 case VPT_ALARMSTATE: 1215 if (propval == SSAS_OFF) { 1216 (void) strlcpy(buf, STR_SSAS_OFF, MAX_ALARMSTATE_LEN); 1217 } else if (propval == SSAS_STEADY) { 1218 (void) strlcpy(buf, STR_SSAS_STEADY, 1219 MAX_ALARMSTATE_LEN); 1220 } else if (propval == SSAS_ALTERNATING) { 1221 (void) strlcpy(buf, STR_SSAS_ALTERNATING, 1222 MAX_ALARMSTATE_LEN); 1223 } else { 1224 (void) strlcpy(buf, STR_SSAS_UNKNOWN, 1225 MAX_ALARMSTATE_LEN); 1226 } 1227 break; 1228 1229 case VPT_BATTERYSTATUS: 1230 switch (propval) { 1231 case SSBS_OTHER: 1232 (void) strlcpy(buf, STR_SSBS_OTHER, 1233 MAX_BATTERYSTATUS_LEN); 1234 break; 1235 case SSBS_FULLYCHARGED: 1236 (void) strlcpy(buf, STR_SSBS_FULLYCHARGED, 1237 MAX_BATTERYSTATUS_LEN); 1238 break; 1239 case SSBS_LOW: 1240 (void) strlcpy(buf, STR_SSBS_LOW, 1241 MAX_BATTERYSTATUS_LEN); 1242 break; 1243 case SSBS_CRITICAL: 1244 (void) strlcpy(buf, STR_SSBS_CRITICAL, 1245 MAX_BATTERYSTATUS_LEN); 1246 break; 1247 case SSBS_CHARGING: 1248 (void) strlcpy(buf, STR_SSBS_CHARGING, 1249 MAX_BATTERYSTATUS_LEN); 1250 break; 1251 case SSBS_CHARGING_AND_LOW: 1252 (void) strlcpy(buf, STR_SSBS_CHARGING_AND_LOW, 1253 MAX_BATTERYSTATUS_LEN); 1254 break; 1255 case SSBS_CHARGING_AND_HIGH: 1256 (void) strlcpy(buf, STR_SSBS_CHARGING_AND_HIGH, 1257 MAX_BATTERYSTATUS_LEN); 1258 break; 1259 case SSBS_CHARGING_AND_CRITICAL: 1260 (void) strlcpy(buf, STR_SSBS_CHARGING_AND_CRITICAL, 1261 MAX_BATTERYSTATUS_LEN); 1262 break; 1263 case SSBS_UNDEFINED: 1264 (void) strlcpy(buf, STR_SSBS_UNDEFINED, 1265 MAX_BATTERYSTATUS_LEN); 1266 break; 1267 case SSBS_PARTIALLY_CHARGED: 1268 (void) strlcpy(buf, STR_SSBS_PARTIALLY_CHARGED, 1269 MAX_BATTERYSTATUS_LEN); 1270 break; 1271 case SSBS_UNKNOWN: 1272 default: 1273 (void) strlcpy(buf, STR_SSBS_UNKNOWN, 1274 MAX_BATTERYSTATUS_LEN); 1275 break; 1276 } 1277 break; 1278 } 1279 1280 (void) rw_unlock(&stale_tree_rwlp); 1281 1282 return (PICL_SUCCESS); 1283 } 1284 1285 static void 1286 threshold(picl_nodehdl_t node, char *oidstr, int row, char *propname, 1287 int *snmp_syserr_p) 1288 { 1289 picl_prophdl_t prop; 1290 int err; 1291 int val; 1292 1293 if ((err = snmp_get_int(hdl, oidstr, row, &val, snmp_syserr_p)) != -1) { 1294 err = add_volatile_prop(node, propname, PICL_PTYPE_INT, 1295 PICL_READ, sizeof (int), read_volprop, NULL, &prop); 1296 if (err == PICL_SUCCESS) 1297 save_volprop(prop, oidstr, row, VPT_NUMSENSOR); 1298 } else 1299 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1300 *snmp_syserr_p ? *snmp_syserr_p : err, oidstr, row); 1301 } 1302 1303 static void 1304 add_thresholds(picl_nodehdl_t node, int row, int *snmp_syserr_p) 1305 { 1306 uchar_t *bitstr = NULL; 1307 uchar_t enabled; 1308 uint_t nbytes; 1309 int ret; 1310 1311 ret = snmp_get_str(hdl, 1312 OID_sunPlatNumericSensorEnabledThresholds, 1313 row, (char **)&bitstr, snmp_syserr_p); 1314 if (ret == -1) { 1315 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1316 *snmp_syserr_p ? *snmp_syserr_p : ret, 1317 OID_sunPlatNumericSensorEnabledThresholds, row); 1318 } else { 1319 nbytes = strlen((const char *)bitstr); 1320 } 1321 1322 CHECK_LINKRESET_VOID(snmp_syserr_p); 1323 1324 /* 1325 * No bit string of threshold masks was returned, so we can't 1326 * assume that any thresholds exist. 1327 * 1328 * This mask prevents us from attempting to fetch thresholds 1329 * which don't apply to the sensor or that aren't there anyway, 1330 * That speeds up the plug-in significantly since otherwise it 1331 * takes several seconds to time out. 1332 */ 1333 if (ret < 0 || bitstr == NULL || nbytes == 0 || 2 < nbytes) { 1334 if (bitstr) 1335 free(bitstr); 1336 return; 1337 } else if (nbytes == 1) { 1338 /* 1339 * The ALOM snmp agent doesn't adhere to the BER rules for 1340 * encoding bit strings. While the BER states that bitstrings 1341 * must begin from the second octet after length, and the 1342 * first octet after length must indicate the number of unused 1343 * bits in the last octet, the snmp agent simply sends the 1344 * bitstring data as if it were octet string -- that is, the 1345 * "unused bits" octet is missing. 1346 */ 1347 enabled = bitstr[0]; 1348 } else if (nbytes == 2) 1349 enabled = bitstr[1]; 1350 1351 if (bitstr) { 1352 free(bitstr); 1353 } 1354 1355 if (enabled & LOWER_FATAL) { 1356 threshold(node, 1357 OID_sunPlatNumericSensorLowerThresholdFatal, row, 1358 PICL_PROP_LOW_POWER_OFF, snmp_syserr_p); 1359 CHECK_LINKRESET_VOID(snmp_syserr_p) 1360 } 1361 if (enabled & LOWER_CRITICAL) { 1362 threshold(node, 1363 OID_sunPlatNumericSensorLowerThresholdCritical, row, 1364 PICL_PROP_LOW_SHUTDOWN, snmp_syserr_p); 1365 CHECK_LINKRESET_VOID(snmp_syserr_p) 1366 } 1367 if (enabled & LOWER_NON_CRITICAL) { 1368 threshold(node, 1369 OID_sunPlatNumericSensorLowerThresholdNonCritical, row, 1370 PICL_PROP_LOW_WARNING, snmp_syserr_p); 1371 CHECK_LINKRESET_VOID(snmp_syserr_p) 1372 } 1373 if (enabled & UPPER_NON_CRITICAL) { 1374 threshold(node, 1375 OID_sunPlatNumericSensorUpperThresholdNonCritical, row, 1376 PICL_PROP_HIGH_WARNING, snmp_syserr_p); 1377 CHECK_LINKRESET_VOID(snmp_syserr_p) 1378 } 1379 if (enabled & UPPER_CRITICAL) { 1380 threshold(node, 1381 OID_sunPlatNumericSensorUpperThresholdCritical, row, 1382 PICL_PROP_HIGH_SHUTDOWN, snmp_syserr_p); 1383 CHECK_LINKRESET_VOID(snmp_syserr_p) 1384 } 1385 if (enabled & UPPER_FATAL) { 1386 threshold(node, 1387 OID_sunPlatNumericSensorUpperThresholdFatal, row, 1388 PICL_PROP_HIGH_POWER_OFF, snmp_syserr_p); 1389 CHECK_LINKRESET_VOID(snmp_syserr_p) 1390 } 1391 } 1392 1393 static char * 1394 get_slot_type(int row, int *snmp_syserr_p) 1395 { 1396 char *p; 1397 char *slott = NULL; 1398 int ret; 1399 1400 ret = snmp_get_str(hdl, OID_sunPlatEquipmentHolderAcceptableTypes, 1401 row, &p, snmp_syserr_p); 1402 CHECK_LINKRESET(snmp_syserr_p, NULL) 1403 1404 if ((ret == 0) && p && *p) { 1405 slott = p; 1406 if ((p = strchr(slott, '\n')) != NULL) 1407 *p = 0; 1408 } else { 1409 log_msg(LOG_WARNING, SNMPP_NO_SLOT_TYPE, row); 1410 if (p) { 1411 free(p); 1412 } 1413 } 1414 1415 return (slott); 1416 } 1417 1418 /* 1419 * Create and add the specified volatile property 1420 */ 1421 static int 1422 add_volatile_prop(picl_nodehdl_t node, char *name, int type, int access, 1423 int size, int (*rdfunc)(ptree_rarg_t *, void *), 1424 int (*wrfunc)(ptree_warg_t *, const void *), picl_prophdl_t *propp) 1425 { 1426 ptree_propinfo_t propinfo; 1427 picl_prophdl_t prop; 1428 int err; 1429 1430 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1431 type, (access|PICL_VOLATILE), size, name, rdfunc, wrfunc); 1432 if (err != PICL_SUCCESS) { 1433 log_msg(LOG_ERR, SNMPP_CANT_INIT_PROPINFO, err); 1434 return (err); 1435 } 1436 1437 err = ptree_create_and_add_prop(node, &propinfo, NULL, &prop); 1438 if (err != PICL_SUCCESS) { 1439 log_msg(LOG_ERR, SNMPP_CANT_ADD_PROP, err, node); 1440 return (err); 1441 } 1442 1443 if (propp) 1444 *propp = prop; 1445 1446 return (PICL_SUCCESS); 1447 } 1448 1449 /* 1450 * Add the specified string property to the node 1451 */ 1452 static int 1453 add_string_prop(picl_nodehdl_t node, char *propname, char *propval) 1454 { 1455 ptree_propinfo_t propinfo; 1456 int err; 1457 1458 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1459 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(propval) + 1, 1460 propname, NULL, NULL); 1461 if (err != PICL_SUCCESS) { 1462 log_msg(LOG_ERR, SNMPP_CANT_INIT_STR_PROPINFO, err); 1463 return (err); 1464 } 1465 1466 err = ptree_create_and_add_prop(node, &propinfo, propval, NULL); 1467 if (err != PICL_SUCCESS) { 1468 log_msg(LOG_ERR, SNMPP_CANT_ADD_STR_PROP, err, node); 1469 return (err); 1470 } 1471 1472 return (PICL_SUCCESS); 1473 } 1474 1475 /* 1476 * Add the specified void property to the node 1477 */ 1478 static int 1479 add_void_prop(picl_nodehdl_t node, char *propname) 1480 { 1481 ptree_propinfo_t propinfo; 1482 int err; 1483 1484 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1485 PICL_PTYPE_VOID, PICL_READ, 0, propname, NULL, NULL); 1486 if (err != PICL_SUCCESS) { 1487 log_msg(LOG_ERR, SNMPP_CANT_INIT_VOID_PROPINFO, err); 1488 return (err); 1489 } 1490 1491 err = ptree_create_and_add_prop(node, &propinfo, NULL, NULL); 1492 if (err != PICL_SUCCESS) { 1493 log_msg(LOG_ERR, SNMPP_CANT_ADD_VOID_PROP, err, node); 1494 return (err); 1495 } 1496 1497 return (PICL_SUCCESS); 1498 } 1499 1500 static void 1501 add_prop(picl_nodehdl_t nodeh, picl_prophdl_t *php, char *label, 1502 int row, sp_propid_t pp, int *snmp_syserr_p) 1503 { 1504 char *serial_num; 1505 char *slot_type; 1506 char *fw_revision, *hw_revision; 1507 char *mfg_name, *model_name; 1508 char *phys_descr; 1509 int val; 1510 int ret; 1511 1512 switch (pp) { 1513 case PP_SERIAL_NUM: 1514 ret = snmp_get_str(hdl, OID_entPhysicalSerialNum, 1515 row, &serial_num, snmp_syserr_p); 1516 CHECK_LINKRESET_VOID(snmp_syserr_p) 1517 if ((ret == 0) && serial_num && *serial_num) { 1518 (void) add_string_prop(nodeh, 1519 PICL_PROP_SERIAL_NUMBER, serial_num); 1520 free((void *) serial_num); 1521 } 1522 if (ret == -1) 1523 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1524 *snmp_syserr_p ? *snmp_syserr_p : ret, 1525 OID_entPhysicalSerialNum, row); 1526 break; 1527 1528 case PP_SLOT_TYPE: 1529 if ((slot_type = get_slot_type(row, snmp_syserr_p)) == NULL) { 1530 CHECK_LINKRESET_VOID(snmp_syserr_p) 1531 (void) add_string_prop(nodeh, 1532 PICL_PROP_SLOT_TYPE, DEFAULT_SLOT_TYPE); 1533 } else { 1534 (void) add_string_prop(nodeh, 1535 PICL_PROP_SLOT_TYPE, slot_type); 1536 free((void *) slot_type); 1537 } 1538 break; 1539 1540 case PP_STATE: 1541 ret = add_volatile_prop(nodeh, PICL_PROP_STATE, 1542 PICL_PTYPE_CHARSTRING, PICL_READ, MAX_ALARMSTATE_LEN, 1543 read_volprop, NULL, php); 1544 if (ret == PICL_SUCCESS) { 1545 save_volprop(*php, OID_sunPlatAlarmState, row, 1546 VPT_ALARMSTATE); 1547 } 1548 break; 1549 1550 case PP_OPSTATUS: 1551 ret = add_volatile_prop(nodeh, PICL_PROP_OPERATIONAL_STATUS, 1552 PICL_PTYPE_CHARSTRING, PICL_READ, MAX_OPSTATE_LEN, 1553 read_volprop, NULL, php); 1554 if (ret == PICL_SUCCESS) { 1555 save_volprop(*php, 1556 OID_sunPlatEquipmentOperationalState, row, 1557 VPT_PLATOPSTATE); 1558 } 1559 break; 1560 1561 case PP_BATT_STATUS: 1562 ret = add_volatile_prop(nodeh, PICL_PROP_BATTERY_STATUS, 1563 PICL_PTYPE_CHARSTRING, PICL_READ, MAX_BATTERYSTATUS_LEN, 1564 read_volprop, NULL, php); 1565 if (ret == PICL_SUCCESS) { 1566 save_volprop(*php, OID_sunPlatBatteryStatus, row, 1567 VPT_BATTERYSTATUS); 1568 } 1569 break; 1570 1571 case PP_TEMPERATURE: 1572 ret = add_volatile_prop(nodeh, PICL_PROP_TEMPERATURE, 1573 PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 1574 NULL, php); 1575 if (ret == PICL_SUCCESS) { 1576 save_volprop(*php, OID_sunPlatNumericSensorCurrent, 1577 row, VPT_NUMSENSOR); 1578 } 1579 break; 1580 1581 case PP_VOLTAGE: 1582 ret = add_volatile_prop(nodeh, PICL_PROP_VOLTAGE, 1583 PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 1584 NULL, php); 1585 if (ret == PICL_SUCCESS) { 1586 save_volprop(*php, OID_sunPlatNumericSensorCurrent, 1587 row, VPT_NUMSENSOR); 1588 } 1589 break; 1590 1591 case PP_CURRENT: 1592 ret = add_volatile_prop(nodeh, PICL_PROP_CURRENT, 1593 PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 1594 NULL, php); 1595 if (ret == PICL_SUCCESS) { 1596 save_volprop(*php, OID_sunPlatNumericSensorCurrent, 1597 row, VPT_NUMSENSOR); 1598 } 1599 break; 1600 1601 case PP_SPEED: 1602 ret = add_volatile_prop(nodeh, PICL_PROP_SPEED, PICL_PTYPE_INT, 1603 PICL_READ, sizeof (int), read_volprop, NULL, php); 1604 if (ret == PICL_SUCCESS) { 1605 save_volprop(*php, OID_sunPlatNumericSensorCurrent, 1606 row, VPT_NUMSENSOR); 1607 } 1608 break; 1609 1610 case PP_SENSOR_VALUE: 1611 ret = add_volatile_prop(nodeh, PICL_PROP_SENSOR_VALUE, 1612 PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 1613 NULL, php); 1614 if (ret == PICL_SUCCESS) { 1615 save_volprop(*php, OID_sunPlatNumericSensorCurrent, 1616 row, VPT_NUMSENSOR); 1617 } 1618 break; 1619 1620 case PP_CONDITION: 1621 ret = add_volatile_prop(nodeh, PICL_PROP_CONDITION, 1622 PICL_PTYPE_CHARSTRING, PICL_READ, MAX_TRUTHVAL_LEN, 1623 read_volprop, NULL, php); 1624 if (ret == PICL_SUCCESS) { 1625 save_volprop(*php, OID_sunPlatBinarySensorCurrent, 1626 row, VPT_BINSENSOR); 1627 } 1628 break; 1629 1630 case PP_EXPECTED: 1631 ret = add_volatile_prop(nodeh, PICL_PROP_EXPECTED, 1632 PICL_PTYPE_CHARSTRING, PICL_READ, MAX_TRUTHVAL_LEN, 1633 read_volprop, NULL, php); 1634 if (ret == PICL_SUCCESS) { 1635 save_volprop(*php, OID_sunPlatBinarySensorExpected, 1636 row, VPT_BINSENSOR); 1637 } 1638 break; 1639 1640 case PP_EXPONENT: 1641 ret = add_volatile_prop(nodeh, PICL_PROP_EXPONENT, 1642 PICL_PTYPE_INT, PICL_READ, sizeof (int), read_volprop, 1643 NULL, php); 1644 if (ret == PICL_SUCCESS) { 1645 save_volprop(*php, OID_sunPlatNumericSensorExponent, 1646 row, VPT_NUMSENSOR); 1647 } 1648 break; 1649 1650 case PP_REPLACEABLE: 1651 ret = snmp_get_int(hdl, OID_sunPlatCircuitPackReplaceable, 1652 row, &val, snmp_syserr_p); 1653 CHECK_LINKRESET_VOID(snmp_syserr_p) 1654 if ((ret == 0) && (val == ST_TRUE)) 1655 (void) add_void_prop(nodeh, PICL_PROP_IS_REPLACEABLE); 1656 if (ret == -1) 1657 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1658 *snmp_syserr_p ? *snmp_syserr_p : ret, 1659 OID_sunPlatCircuitPackReplaceable, row); 1660 break; 1661 1662 case PP_HOTSWAPPABLE: 1663 ret = snmp_get_int(hdl, OID_sunPlatCircuitPackHotSwappable, 1664 row, &val, snmp_syserr_p); 1665 CHECK_LINKRESET_VOID(snmp_syserr_p) 1666 if ((ret == 0) && (val == ST_TRUE)) 1667 (void) add_void_prop(nodeh, PICL_PROP_IS_HOT_SWAPPABLE); 1668 if (ret == -1) 1669 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1670 *snmp_syserr_p ? *snmp_syserr_p : ret, 1671 OID_sunPlatCircuitPackHotSwappable, row); 1672 break; 1673 1674 case PP_IS_FRU: 1675 ret = snmp_get_int(hdl, OID_entPhysicalIsFRU, row, 1676 &val, snmp_syserr_p); 1677 CHECK_LINKRESET_VOID(snmp_syserr_p) 1678 if ((ret == 0) && (val == ST_TRUE)) 1679 (void) add_void_prop(nodeh, PICL_PROP_IS_FRU); 1680 if (ret == -1) 1681 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1682 *snmp_syserr_p ? *snmp_syserr_p : ret, 1683 OID_entPhysicalIsFRU, row); 1684 break; 1685 1686 case PP_HW_REVISION: 1687 ret = snmp_get_str(hdl, OID_entPhysicalHardwareRev, 1688 row, &hw_revision, snmp_syserr_p); 1689 CHECK_LINKRESET_VOID(snmp_syserr_p) 1690 if ((ret == 0) && hw_revision && *hw_revision) { 1691 (void) add_string_prop(nodeh, 1692 PICL_PROP_HW_REVISION, hw_revision); 1693 free((void *) hw_revision); 1694 } 1695 if (ret == -1) 1696 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1697 *snmp_syserr_p ? *snmp_syserr_p : ret, 1698 OID_entPhysicalHardwareRev, row); 1699 break; 1700 1701 case PP_FW_REVISION: 1702 ret = snmp_get_str(hdl, OID_entPhysicalFirmwareRev, 1703 row, &fw_revision, snmp_syserr_p); 1704 CHECK_LINKRESET_VOID(snmp_syserr_p) 1705 if ((ret == 0) && fw_revision && *fw_revision) { 1706 (void) add_string_prop(nodeh, 1707 PICL_PROP_FW_REVISION, fw_revision); 1708 free((void *) fw_revision); 1709 } 1710 if (ret == -1) 1711 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1712 *snmp_syserr_p ? *snmp_syserr_p : ret, 1713 OID_entPhysicalFirmwareRev, row); 1714 break; 1715 1716 case PP_MFG_NAME: 1717 ret = snmp_get_str(hdl, OID_entPhysicalMfgName, 1718 row, &mfg_name, snmp_syserr_p); 1719 CHECK_LINKRESET_VOID(snmp_syserr_p) 1720 if ((ret == 0) && mfg_name && *mfg_name) { 1721 (void) add_string_prop(nodeh, 1722 PICL_PROP_MFG_NAME, mfg_name); 1723 free((void *) mfg_name); 1724 } 1725 if (ret == -1) 1726 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1727 *snmp_syserr_p ? *snmp_syserr_p : ret, 1728 OID_entPhysicalMfgName, row); 1729 break; 1730 1731 case PP_MODEL_NAME: 1732 ret = snmp_get_str(hdl, OID_entPhysicalModelName, 1733 row, &model_name, snmp_syserr_p); 1734 CHECK_LINKRESET_VOID(snmp_syserr_p) 1735 if ((ret == 0) && model_name && *model_name) { 1736 (void) add_string_prop(nodeh, 1737 PICL_PROP_MODEL_NAME, model_name); 1738 free((void *) model_name); 1739 } 1740 if (ret == -1) 1741 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1742 *snmp_syserr_p ? *snmp_syserr_p : ret, 1743 OID_entPhysicalModelName, row); 1744 break; 1745 1746 case PP_DESCRIPTION: 1747 ret = snmp_get_str(hdl, OID_entPhysicalDescr, 1748 row, &phys_descr, snmp_syserr_p); 1749 CHECK_LINKRESET_VOID(snmp_syserr_p) 1750 if ((ret == 0) && phys_descr && *phys_descr) { 1751 (void) add_string_prop(nodeh, 1752 PICL_PROP_PHYS_DESCRIPTION, phys_descr); 1753 free((void *) phys_descr); 1754 } 1755 if (ret == -1) 1756 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1757 *snmp_syserr_p ? *snmp_syserr_p : ret, 1758 OID_entPhysicalDescr, row); 1759 break; 1760 1761 case PP_LABEL: 1762 if (label && *label) 1763 (void) add_string_prop(nodeh, PICL_PROP_LABEL, label); 1764 break; 1765 1766 case PP_BASE_UNITS: 1767 ret = snmp_get_int(hdl, OID_sunPlatNumericSensorBaseUnits, 1768 row, &val, snmp_syserr_p); 1769 CHECK_LINKRESET_VOID(snmp_syserr_p) 1770 if ((ret == 0) && (val > 0) && (val < n_baseunits)) { 1771 (void) add_string_prop(nodeh, 1772 PICL_PROP_BASE_UNITS, sensor_baseunits[val]); 1773 } 1774 if (ret == -1) 1775 log_msg(LOG_ERR, SNMPP_CANT_FETCH_OBJECT_VAL, 1776 *snmp_syserr_p ? *snmp_syserr_p : ret, 1777 OID_sunPlatNumericSensorBaseUnits, row); 1778 break; 1779 1780 case PP_RATE_UNITS: 1781 ret = snmp_get_int(hdl, OID_sunPlatNumericSensorRateUnits, 1782 row, &val, snmp_syserr_p); 1783 CHECK_LINKRESET_VOID(snmp_syserr_p) 1784 if ((ret == 0) && (val > 0) && (val < n_rateunits)) { 1785 (void) add_string_prop(nodeh, 1786 PICL_PROP_RATE_UNITS, sensor_rateunits[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_sunPlatNumericSensorRateUnits, row); 1792 break; 1793 } 1794 } 1795 1796 /*VARARGS2*/ 1797 static void 1798 log_msg(int pri, const char *fmt, ...) 1799 { 1800 va_list ap; 1801 1802 va_start(ap, fmt); 1803 vsyslog(pri, fmt, ap); 1804 va_end(ap); 1805 } 1806 1807 #ifdef SNMPPLUGIN_DEBUG 1808 1809 static void 1810 snmpplugin_log_init(void) 1811 { 1812 (void) mutex_init(&snmpplugin_dbuf_lock, USYNC_THREAD, NULL); 1813 } 1814 1815 static void 1816 snmpplugin_log(const char *fmt, ...) 1817 { 1818 va_list ap; 1819 1820 (void) mutex_lock(&snmpplugin_dbuf_lock); 1821 1822 va_start(ap, fmt); 1823 (void) vsnprintf(snmpplugin_lbuf, SNMPPLUGIN_DMAX_LINE, fmt, ap); 1824 snmpplugin_log_append(); 1825 va_end(ap); 1826 1827 (void) mutex_unlock(&snmpplugin_dbuf_lock); 1828 } 1829 1830 static void 1831 snmpplugin_log_append(void) 1832 { 1833 int len; 1834 1835 len = strlen(snmpplugin_lbuf); 1836 1837 if ((snmpplugin_dbuf_curp + len) >= 1838 (snmpplugin_dbuf + snmpplugin_dbuf_sz)) { 1839 snmpplugin_dbuf_realloc(); 1840 if (snmpplugin_dbuf == NULL) { 1841 return; 1842 } 1843 } 1844 1845 (void) strcpy(snmpplugin_dbuf_curp, snmpplugin_lbuf); 1846 snmpplugin_dbuf_curp += len; 1847 } 1848 1849 static void 1850 snmpplugin_dbuf_realloc(void) 1851 { 1852 char *p; 1853 size_t offset = 0; 1854 size_t count; 1855 1856 count = snmpplugin_dbuf_sz + SNMPPLUGIN_DBLOCK_SZ; 1857 if ((p = (char *)calloc(count, 1)) == NULL) { 1858 snmpplugin_dbuf_overflow++; 1859 snmpplugin_dbuf_curp = snmpplugin_dbuf; 1860 return; 1861 } 1862 1863 if (snmpplugin_dbuf) { 1864 offset = snmpplugin_dbuf_curp - snmpplugin_dbuf; 1865 (void) memcpy(p, snmpplugin_dbuf, snmpplugin_dbuf_sz); 1866 free(snmpplugin_dbuf); 1867 } 1868 1869 snmpplugin_dbuf = p; 1870 snmpplugin_dbuf_sz += SNMPPLUGIN_DBLOCK_SZ; 1871 1872 snmpplugin_dbuf_curp = snmpplugin_dbuf + offset; 1873 } 1874 #endif 1875