11303Swesolows /* 21303Swesolows * CDDL HEADER START 31303Swesolows * 41303Swesolows * The contents of this file are subject to the terms of the 51303Swesolows * Common Development and Distribution License (the "License"). 61303Swesolows * You may not use this file except in compliance with the License. 71303Swesolows * 81303Swesolows * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91303Swesolows * or http://www.opensolaris.org/os/licensing. 101303Swesolows * See the License for the specific language governing permissions 111303Swesolows * and limitations under the License. 121303Swesolows * 131303Swesolows * When distributing Covered Code, include this CDDL HEADER in each 141303Swesolows * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151303Swesolows * If applicable, add the following below this CDDL HEADER, with the 161303Swesolows * fields enclosed by brackets "[]" replaced with your own identifying 171303Swesolows * information: Portions Copyright [yyyy] [name of copyright owner] 181303Swesolows * 191303Swesolows * CDDL HEADER END 201303Swesolows */ 211303Swesolows 221303Swesolows /* 231303Swesolows * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 241303Swesolows * Use is subject to license terms. 251303Swesolows */ 261303Swesolows 271303Swesolows #pragma ident "%Z%%M% %I% %E% SMI" 281303Swesolows 291303Swesolows #include <sys/fm/protocol.h> 301303Swesolows #include <fm/fmd_adm.h> 311303Swesolows #include <fm/fmd_snmp.h> 321303Swesolows #include <net-snmp/net-snmp-config.h> 331303Swesolows #include <net-snmp/net-snmp-includes.h> 341303Swesolows #include <net-snmp/agent/net-snmp-agent-includes.h> 351303Swesolows #include <pthread.h> 361303Swesolows #include <stddef.h> 371303Swesolows #include <errno.h> 381303Swesolows #include <alloca.h> 391303Swesolows #include <locale.h> 401303Swesolows #include <libuutil.h> 411303Swesolows #include <libnvpair.h> 421303Swesolows #include "sunFM_impl.h" 431303Swesolows #include "problem.h" 441303Swesolows 451303Swesolows /* 461303Swesolows * We assume that the number of suspect fault events associated with a 471303Swesolows * particular case will generally be sufficiently small that the overhead 481303Swesolows * associated with indexing them in a tree would exceed the gain from 491303Swesolows * not traversing the fault list for each request. 501303Swesolows */ 511303Swesolows static uu_avl_pool_t *problem_uuid_avl_pool; 521303Swesolows static uu_avl_t *problem_uuid_avl; 531303Swesolows 541303Swesolows #define VALID_AVL_STATE (problem_uuid_avl_pool != NULL && \ 551303Swesolows problem_uuid_avl != NULL) 561303Swesolows 571303Swesolows #define UPDATE_WAIT_MILLIS 10 /* poll interval in milliseconds */ 581303Swesolows 591303Swesolows /* 601303Swesolows * Update types. Single-index and all are mutually exclusive. 611303Swesolows */ 621303Swesolows #define UCT_INDEX 0x1 631303Swesolows #define UCT_ALL 0x2 641303Swesolows #define UCT_FLAGS 0x3 651303Swesolows 661303Swesolows #define MODULE_DATA_VALID(d) ((d)->d_valid == valid_stamp) 671303Swesolows 681303Swesolows /* 691303Swesolows * Locking strategy is described in module.c. 701303Swesolows */ 711303Swesolows static int valid_stamp; 721303Swesolows static pthread_mutex_t update_lock; 731303Swesolows static pthread_cond_t update_cv; 741303Swesolows static volatile enum { US_QUIET, US_NEEDED, US_INPROGRESS } update_status; 751303Swesolows 761303Swesolows static Netsnmp_Node_Handler sunFmProblemTable_handler; 771303Swesolows static Netsnmp_Node_Handler sunFmFaultEventTable_handler; 781303Swesolows 791303Swesolows static sunFmProblem_data_t * 801303Swesolows problem_key_build(const char *uuid) 811303Swesolows { 821303Swesolows static sunFmProblem_data_t key; 831303Swesolows 841303Swesolows key.d_aci_uuid = uuid; 851303Swesolows 861303Swesolows return (&key); 871303Swesolows } 881303Swesolows 891303Swesolows static sunFmProblem_data_t * 901303Swesolows problem_lookup_uuid_exact(const char *uuid) 911303Swesolows { 921303Swesolows sunFmProblem_data_t *key, *data; 931303Swesolows 941303Swesolows key = problem_key_build(uuid); 951303Swesolows 961303Swesolows DEBUGMSGTL((MODNAME_STR, "lookup_exact for uuid %s\n", uuid)); 971303Swesolows data = uu_avl_find(problem_uuid_avl, key, NULL, NULL); 981303Swesolows 991303Swesolows return (data); 1001303Swesolows } 1011303Swesolows 1021303Swesolows static sunFmProblem_data_t * 1031303Swesolows problem_lookup_uuid_next(const char *uuid) 1041303Swesolows { 1051303Swesolows sunFmProblem_data_t *key, *data; 1061303Swesolows uu_avl_index_t idx; 1071303Swesolows 1081303Swesolows key = problem_key_build(uuid); 1091303Swesolows 1101303Swesolows DEBUGMSGTL((MODNAME_STR, "lookup_next for uuid %s\n", uuid)); 1111303Swesolows (void) uu_avl_find(problem_uuid_avl, key, NULL, &idx); 1121303Swesolows 1131303Swesolows data = uu_avl_nearest_next(problem_uuid_avl, idx); 1141303Swesolows 1151303Swesolows DEBUGMSGTL((MODNAME_STR, "lookup_next: entry is %p\n", data)); 1161303Swesolows 1171303Swesolows return (data); 1181303Swesolows } 1191303Swesolows 1201303Swesolows static sunFmFaultEvent_data_t * 1211303Swesolows faultevent_lookup_index_exact(sunFmProblem_data_t *data, ulong_t index) 1221303Swesolows { 1231303Swesolows if (index > data->d_nsuspects) 1241303Swesolows return (NULL); 1251303Swesolows 1261303Swesolows if (data->d_suspects == NULL) 1271303Swesolows return (NULL); 1281303Swesolows 1291303Swesolows return (data->d_suspects[index - 1]); 1301303Swesolows } 1311303Swesolows 132*2134Swesolows /*ARGSUSED*/ 1331303Swesolows static int 1341303Swesolows problem_update_one(const fmd_adm_caseinfo_t *acp, void *arg) 1351303Swesolows { 1361303Swesolows sunFmProblem_data_t *data; 1371303Swesolows nvlist_t *nvl; 1381303Swesolows int64_t *diag_time; 1391303Swesolows uint_t nelem; 1401303Swesolows uint32_t nsusp; 1411303Swesolows int err; 1421303Swesolows 1431303Swesolows DEBUGMSGTL((MODNAME_STR, "update_one\n")); 1441303Swesolows 1451303Swesolows ASSERT(acp->aci_uuid != NULL); 1461303Swesolows 1471303Swesolows if ((data = problem_lookup_uuid_exact(acp->aci_uuid)) == NULL) { 1481303Swesolows uu_avl_index_t idx; 1491303Swesolows 1501303Swesolows DEBUGMSGTL((MODNAME_STR, "found new problem %s\n", 1511303Swesolows acp->aci_uuid)); 1521303Swesolows if ((data = SNMP_MALLOC_TYPEDEF(sunFmProblem_data_t)) == NULL) { 1531303Swesolows snmp_log(LOG_ERR, MODNAME_STR ": Out of memory for " 1541303Swesolows "new problem data at %s:%d\n", __FILE__, __LINE__); 1551303Swesolows return (0); 1561303Swesolows } 1571303Swesolows if ((err = nvlist_dup(acp->aci_event, &data->d_aci_event, 0)) 1581303Swesolows != 0) { 1591303Swesolows snmp_log(LOG_ERR, MODNAME_STR ": Problem data setup " 1601303Swesolows "failed: %s\n", strerror(err)); 1611303Swesolows SNMP_FREE(data); 1621303Swesolows return (0); 1631303Swesolows } 1641303Swesolows 1651303Swesolows data->d_aci_uuid = data->d_aci_code = data->d_aci_url = "-"; 1661303Swesolows (void) nvlist_lookup_string(data->d_aci_event, FM_SUSPECT_UUID, 1671303Swesolows (char **)&data->d_aci_uuid); 1681303Swesolows (void) nvlist_lookup_string(data->d_aci_event, 1691303Swesolows FM_SUSPECT_DIAG_CODE, (char **)&data->d_aci_code); 1701303Swesolows data->d_aci_url = strdup(acp->aci_url); 1711303Swesolows 1721303Swesolows if (nvlist_lookup_nvlist(data->d_aci_event, FM_SUSPECT_DE, 1731303Swesolows &nvl) == 0) 1741303Swesolows if ((data->d_diag_engine = sunFm_nvl2str(nvl)) == NULL) 1751303Swesolows data->d_diag_engine = "-"; 1761303Swesolows 1771303Swesolows if (nvlist_lookup_int64_array(data->d_aci_event, 1781303Swesolows FM_SUSPECT_DIAG_TIME, &diag_time, &nelem) == 0 && 1791303Swesolows nelem >= 2) { 1801303Swesolows data->d_diag_time.tv_sec = (long)diag_time[0]; 1811303Swesolows data->d_diag_time.tv_usec = (long)diag_time[1]; 1821303Swesolows } 1831303Swesolows 1841303Swesolows (void) nvlist_lookup_uint32(data->d_aci_event, 1851303Swesolows FM_SUSPECT_FAULT_SZ, &nsusp); 1861303Swesolows data->d_nsuspects = (ulong_t)nsusp; 1871303Swesolows 1881303Swesolows (void) nvlist_lookup_nvlist_array(data->d_aci_event, 1891303Swesolows FM_SUSPECT_FAULT_LIST, &data->d_suspects, &nelem); 1901303Swesolows 1911303Swesolows ASSERT(nelem == data->d_nsuspects); 1921303Swesolows 1931303Swesolows uu_avl_node_init(data, &data->d_uuid_avl, 1941303Swesolows problem_uuid_avl_pool); 1951303Swesolows (void) uu_avl_find(problem_uuid_avl, data, NULL, &idx); 1961303Swesolows uu_avl_insert(problem_uuid_avl, data, idx); 1971303Swesolows 1981303Swesolows data->d_valid = valid_stamp; 1991303Swesolows 2001303Swesolows DEBUGMSGTL((MODNAME_STR, "completed new problem %s@%p\n", 2011303Swesolows data->d_aci_uuid, data)); 2021303Swesolows } 2031303Swesolows 2041303Swesolows /* 2051303Swesolows * We don't touch problems we've seen before; they shouldn't change 2061303Swesolows * in any way we care about, since they've already been solved. The 2071303Swesolows * state, however, could change, and if we later expose that to the 2081303Swesolows * client we need to update it here. 2091303Swesolows */ 2101303Swesolows 2111303Swesolows return (0); 2121303Swesolows } 2131303Swesolows 2141303Swesolows static int 2151303Swesolows problem_update(sunFmProblem_update_ctx_t *update_ctx) 2161303Swesolows { 2171303Swesolows fmd_adm_t *adm; 2181303Swesolows 2191303Swesolows ASSERT(update_ctx != NULL); 2201303Swesolows ASSERT((update_ctx->uc_type & (UCT_INDEX|UCT_ALL)) != 2211303Swesolows (UCT_INDEX|UCT_ALL)); 2221303Swesolows ASSERT((update_ctx->uc_type & ~UCT_FLAGS) == 0); 2231303Swesolows ASSERT(VALID_AVL_STATE); 2241303Swesolows 2251303Swesolows if ((adm = fmd_adm_open(update_ctx->uc_host, update_ctx->uc_prog, 2261303Swesolows update_ctx->uc_version)) == NULL) { 2271303Swesolows snmp_log(LOG_ERR, MODNAME_STR ": Communication with fmd " 2281303Swesolows "failed: %s\n", strerror(errno)); 2291303Swesolows return (SNMP_ERR_RESOURCEUNAVAILABLE); 2301303Swesolows } 2311303Swesolows 2321303Swesolows ++valid_stamp; 2331303Swesolows if (fmd_adm_case_iter(adm, SNMP_URL_MSG, problem_update_one, 2341303Swesolows update_ctx) != 0) { 2351303Swesolows snmp_log(LOG_ERR, MODNAME_STR ": fmd case information update " 2361303Swesolows "failed: %s\n", fmd_adm_errmsg(adm)); 2371303Swesolows fmd_adm_close(adm); 2381303Swesolows return (SNMP_ERR_RESOURCEUNAVAILABLE); 2391303Swesolows } 2401303Swesolows 2411303Swesolows DEBUGMSGTL((MODNAME_STR, "case iteration completed\n")); 2421303Swesolows 2431303Swesolows fmd_adm_close(adm); 2441303Swesolows return (SNMP_ERR_NOERROR); 2451303Swesolows } 2461303Swesolows 2471303Swesolows /*ARGSUSED*/ 2481303Swesolows static void 2491303Swesolows update_thread(void *arg) 2501303Swesolows { 2511303Swesolows /* 2521303Swesolows * The current problem_update implementation offers minimal savings 2531303Swesolows * for the use of index-only updates; therefore we always do a full 2541303Swesolows * update. If it becomes advantageous to limit updates to a single 2551303Swesolows * index, the contexts can be queued by the handler instead. 2561303Swesolows */ 2571303Swesolows sunFmProblem_update_ctx_t uc; 2581303Swesolows 2591303Swesolows uc.uc_host = NULL; 2601303Swesolows uc.uc_prog = FMD_ADM_PROGRAM; 2611303Swesolows uc.uc_version = FMD_ADM_VERSION; 2621303Swesolows 2631303Swesolows uc.uc_index = NULL; 2641303Swesolows uc.uc_type = UCT_ALL; 2651303Swesolows 2661303Swesolows for (;;) { 2671303Swesolows (void) pthread_mutex_lock(&update_lock); 2681303Swesolows update_status = US_QUIET; 2691303Swesolows while (update_status == US_QUIET) 2701303Swesolows (void) pthread_cond_wait(&update_cv, &update_lock); 2711303Swesolows update_status = US_INPROGRESS; 2721303Swesolows (void) pthread_mutex_unlock(&update_lock); 2731303Swesolows (void) problem_update(&uc); 2741303Swesolows } 2751303Swesolows } 2761303Swesolows 2771303Swesolows static void 2781303Swesolows request_update(void) 2791303Swesolows { 2801303Swesolows (void) pthread_mutex_lock(&update_lock); 2811303Swesolows if (update_status != US_QUIET) { 2821303Swesolows (void) pthread_mutex_unlock(&update_lock); 2831303Swesolows return; 2841303Swesolows } 2851303Swesolows update_status = US_NEEDED; 2861303Swesolows (void) pthread_cond_signal(&update_cv); 2871303Swesolows (void) pthread_mutex_unlock(&update_lock); 2881303Swesolows } 2891303Swesolows 2901303Swesolows /*ARGSUSED*/ 2911303Swesolows static int 2921303Swesolows problem_compare_uuid(const void *l, const void *r, void *private) 2931303Swesolows { 2941303Swesolows sunFmProblem_data_t *l_data = (sunFmProblem_data_t *)l; 2951303Swesolows sunFmProblem_data_t *r_data = (sunFmProblem_data_t *)r; 2961303Swesolows 2971303Swesolows ASSERT(l_data != NULL && r_data != NULL); 2981303Swesolows 2991303Swesolows return (strcmp(l_data->d_aci_uuid, r_data->d_aci_uuid)); 3001303Swesolows } 3011303Swesolows 3021303Swesolows int 3031303Swesolows sunFmProblemTable_init(void) 3041303Swesolows { 3051303Swesolows static oid sunFmProblemTable_oid[] = { SUNFMPROBLEMTABLE_OID }; 3061303Swesolows netsnmp_table_registration_info *table_info; 3071303Swesolows netsnmp_handler_registration *handler; 3081303Swesolows int err; 3091303Swesolows 3101303Swesolows if ((err = pthread_mutex_init(&update_lock, NULL)) != 0) { 3111303Swesolows snmp_log(LOG_ERR, MODNAME_STR ": mutex_init failure: %s\n", 3121303Swesolows strerror(err)); 3131303Swesolows return (MIB_REGISTRATION_FAILED); 3141303Swesolows } 3151303Swesolows if ((err = pthread_cond_init(&update_cv, NULL)) != 0) { 3161303Swesolows snmp_log(LOG_ERR, MODNAME_STR ": cond_init failure: %s\n", 3171303Swesolows strerror(err)); 3181303Swesolows return (MIB_REGISTRATION_FAILED); 3191303Swesolows } 3201303Swesolows 3211303Swesolows if ((err = pthread_create(NULL, NULL, (void *(*)(void *))update_thread, 3221303Swesolows NULL)) != 0) { 3231303Swesolows snmp_log(LOG_ERR, MODNAME_STR ": error creating update " 3241303Swesolows "thread: %s\n", strerror(err)); 3251303Swesolows return (MIB_REGISTRATION_FAILED); 3261303Swesolows } 3271303Swesolows 3281303Swesolows if ((table_info = 3291303Swesolows SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info)) == NULL) 3301303Swesolows return (MIB_REGISTRATION_FAILED); 3311303Swesolows 3321303Swesolows if ((handler = netsnmp_create_handler_registration("sunFmProblemTable", 3331303Swesolows sunFmProblemTable_handler, sunFmProblemTable_oid, 3341303Swesolows OID_LENGTH(sunFmProblemTable_oid), HANDLER_CAN_RONLY)) == NULL) { 3351303Swesolows SNMP_FREE(table_info); 3361303Swesolows return (MIB_REGISTRATION_FAILED); 3371303Swesolows } 3381303Swesolows 3391303Swesolows /* 3401303Swesolows * The Net-SNMP template uses add_indexes here, but that 3411303Swesolows * function is unsafe because it does not check for failure. 3421303Swesolows */ 3431303Swesolows if (netsnmp_table_helper_add_index(table_info, ASN_OCTET_STR) == NULL) { 3441303Swesolows SNMP_FREE(table_info); 3451303Swesolows SNMP_FREE(handler); 3461303Swesolows return (MIB_REGISTRATION_FAILED); 3471303Swesolows } 3481303Swesolows 3491303Swesolows table_info->min_column = SUNFMPROBLEM_COLMIN; 3501303Swesolows table_info->max_column = SUNFMPROBLEM_COLMAX; 3511303Swesolows 3521303Swesolows if ((problem_uuid_avl_pool = uu_avl_pool_create("problem_uuid", 3531303Swesolows sizeof (sunFmProblem_data_t), 3541303Swesolows offsetof(sunFmProblem_data_t, d_uuid_avl), problem_compare_uuid, 3551303Swesolows UU_AVL_DEBUG)) == NULL) { 3561303Swesolows snmp_log(LOG_ERR, MODNAME_STR ": problem_uuid avl pool " 3571303Swesolows "creation failed: %s\n", uu_strerror(uu_error())); 3581303Swesolows snmp_free_varbind(table_info->indexes); 3591303Swesolows SNMP_FREE(table_info); 3601303Swesolows SNMP_FREE(handler); 3611303Swesolows return (MIB_REGISTRATION_FAILED); 3621303Swesolows } 3631303Swesolows 3641303Swesolows if ((problem_uuid_avl = uu_avl_create(problem_uuid_avl_pool, NULL, 3651303Swesolows UU_AVL_DEBUG)) == NULL) { 3661303Swesolows snmp_log(LOG_ERR, MODNAME_STR ": problem_uuid avl creation " 3671303Swesolows "failed: %s\n", uu_strerror(uu_error())); 3681303Swesolows snmp_free_varbind(table_info->indexes); 3691303Swesolows SNMP_FREE(table_info); 3701303Swesolows SNMP_FREE(handler); 3711303Swesolows uu_avl_pool_destroy(problem_uuid_avl_pool); 3721303Swesolows return (MIB_REGISTRATION_FAILED); 3731303Swesolows } 3741303Swesolows 3751303Swesolows if ((err = netsnmp_register_table(handler, table_info)) != 3761303Swesolows MIB_REGISTERED_OK) { 3771303Swesolows snmp_free_varbind(table_info->indexes); 3781303Swesolows SNMP_FREE(table_info); 3791303Swesolows SNMP_FREE(handler); 3801303Swesolows uu_avl_destroy(problem_uuid_avl); 3811303Swesolows uu_avl_pool_destroy(problem_uuid_avl_pool); 3821303Swesolows return (err); 3831303Swesolows } 3841303Swesolows 3851303Swesolows return (MIB_REGISTERED_OK); 3861303Swesolows } 3871303Swesolows 3881303Swesolows int 3891303Swesolows sunFmFaultEventTable_init(void) 3901303Swesolows { 3911303Swesolows static oid sunFmFaultEventTable_oid[] = { SUNFMFAULTEVENTTABLE_OID }; 3921303Swesolows netsnmp_table_registration_info *table_info; 3931303Swesolows netsnmp_handler_registration *handler; 3941303Swesolows int err; 3951303Swesolows 3961303Swesolows if ((table_info = 3971303Swesolows SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info)) == NULL) 3981303Swesolows return (MIB_REGISTRATION_FAILED); 3991303Swesolows 4001303Swesolows if ((handler = 4011303Swesolows netsnmp_create_handler_registration("sunFmFaultEventTable", 4021303Swesolows sunFmFaultEventTable_handler, sunFmFaultEventTable_oid, 4031303Swesolows OID_LENGTH(sunFmFaultEventTable_oid), HANDLER_CAN_RONLY)) == NULL) { 4041303Swesolows SNMP_FREE(table_info); 4051303Swesolows return (MIB_REGISTRATION_FAILED); 4061303Swesolows } 4071303Swesolows 4081303Swesolows /* 4091303Swesolows * The Net-SNMP template uses add_indexes here, but that 4101303Swesolows * function is unsafe because it does not check for failure. 4111303Swesolows */ 4121303Swesolows if (netsnmp_table_helper_add_index(table_info, ASN_OCTET_STR) == NULL) { 4131303Swesolows SNMP_FREE(table_info); 4141303Swesolows SNMP_FREE(handler); 4151303Swesolows return (MIB_REGISTRATION_FAILED); 4161303Swesolows } 4171303Swesolows if (netsnmp_table_helper_add_index(table_info, ASN_UNSIGNED) == NULL) { 4181303Swesolows snmp_free_varbind(table_info->indexes); 4191303Swesolows SNMP_FREE(table_info); 4201303Swesolows SNMP_FREE(handler); 4211303Swesolows return (MIB_REGISTRATION_FAILED); 4221303Swesolows } 4231303Swesolows 4241303Swesolows table_info->min_column = SUNFMFAULTEVENT_COLMIN; 4251303Swesolows table_info->max_column = SUNFMFAULTEVENT_COLMAX; 4261303Swesolows 4271303Swesolows if ((err = netsnmp_register_table(handler, table_info)) != 4281303Swesolows MIB_REGISTERED_OK) { 4291303Swesolows snmp_free_varbind(table_info->indexes); 4301303Swesolows SNMP_FREE(table_info); 4311303Swesolows SNMP_FREE(handler); 4321303Swesolows return (err); 4331303Swesolows } 4341303Swesolows 4351303Swesolows return (MIB_REGISTERED_OK); 4361303Swesolows } 4371303Swesolows 4381303Swesolows /* 4391303Swesolows * Returns the problem data for the problem whose uuid is next according 4401303Swesolows * to ASN.1 lexical ordering after the request in table_info. Indexes are 4411303Swesolows * updated to reflect the OID of the value being returned. This allows 4421303Swesolows * us to implement GETNEXT. 4431303Swesolows */ 4441303Swesolows static sunFmProblem_data_t * 4451303Swesolows sunFmProblemTable_nextpr(netsnmp_handler_registration *reginfo, 4461303Swesolows netsnmp_table_request_info *table_info) 4471303Swesolows { 4481303Swesolows sunFmProblem_data_t *data; 4491303Swesolows char *uuid = ""; 4501303Swesolows 4511303Swesolows if (table_info->number_indexes < 1) { 4521303Swesolows oid tmpoid[MAX_OID_LEN]; 4531303Swesolows 4541303Swesolows DEBUGMSGTL((MODNAME_STR, "nextpr: no indexes given\n")); 4551303Swesolows 456*2134Swesolows snmp_free_varbind(table_info->indexes); 4571303Swesolows table_info->indexes = 4581303Swesolows SNMP_MALLOC_TYPEDEF(netsnmp_variable_list); 4591303Swesolows snmp_set_var_typed_value(table_info->indexes, ASN_OCTET_STR, 4601303Swesolows (const uchar_t *)uuid, 0); 461*2134Swesolows (void) memcpy(tmpoid, reginfo->rootoid, 4621303Swesolows reginfo->rootoid_len * sizeof (oid)); 4631303Swesolows tmpoid[reginfo->rootoid_len] = 1; 4641303Swesolows tmpoid[reginfo->rootoid_len + 1] = table_info->colnum; 4651303Swesolows if (build_oid_segment(table_info->indexes) != SNMPERR_SUCCESS) { 4661303Swesolows snmp_free_varbind(table_info->indexes); 4671303Swesolows return (NULL); 4681303Swesolows } 4691303Swesolows table_info->number_indexes = 1; 4701303Swesolows table_info->index_oid_len = table_info->indexes->name_length; 471*2134Swesolows (void) memcpy(table_info->index_oid, table_info->indexes->name, 4721303Swesolows table_info->indexes->name_length); 4731303Swesolows 4741303Swesolows DEBUGMSGTL((MODNAME_STR, "nextpr: built fake index:\n")); 4751303Swesolows DEBUGMSGVAR((MODNAME_STR, table_info->indexes)); 4761303Swesolows DEBUGMSG((MODNAME_STR, "\n")); 4771303Swesolows } else { 4781303Swesolows /* 4791303Swesolows * Construct the next possible UUID to look for. We can 4801303Swesolows * simply increment the least significant byte of the last 4811303Swesolows * UUID because (a) that preserves SNMP lex order and (b) 4821303Swesolows * the characters that may appear in a UUID do not include 4831303Swesolows * 127 nor 255. 4841303Swesolows */ 4851303Swesolows uuid = alloca(table_info->indexes->val_len + 1); 4861303Swesolows (void) strlcpy(uuid, 4871303Swesolows (const char *)table_info->indexes->val.string, 4881303Swesolows table_info->indexes->val_len + 1); 4891303Swesolows ++uuid[table_info->indexes->val_len - 1]; 4901303Swesolows 4911303Swesolows DEBUGMSGTL((MODNAME_STR, "nextpr: received index:\n")); 4921303Swesolows DEBUGMSGVAR((MODNAME_STR, table_info->indexes)); 4931303Swesolows DEBUGMSG((MODNAME_STR, "\n")); 4941303Swesolows } 4951303Swesolows 4961303Swesolows if ((data = problem_lookup_uuid_next(uuid)) == NULL) { 4971303Swesolows DEBUGMSGTL((MODNAME_STR, "nextpr: next match not found for " 4981303Swesolows "%s; trying next column\n", uuid)); 499*2134Swesolows if (table_info->colnum >= 500*2134Swesolows netsnmp_find_table_registration_info(reginfo)->max_column) { 5011303Swesolows snmp_free_varbind(table_info->indexes); 5021303Swesolows table_info->indexes = NULL; 5031303Swesolows table_info->number_indexes = 0; 5041303Swesolows DEBUGMSGTL((MODNAME_STR, "nextpr: out of columns\n")); 5051303Swesolows return (NULL); 5061303Swesolows } 5071303Swesolows table_info->colnum++; 5081303Swesolows DEBUGMSGTL((MODNAME_STR, "nextpr: search for col %u empty " 5091303Swesolows "uuid\n", table_info->colnum, uuid)); 5101303Swesolows 5111303Swesolows if ((data = problem_lookup_uuid_next("")) == NULL) { 5121303Swesolows DEBUGMSGTL((MODNAME_STR, "nextpr: next match not found " 5131303Swesolows "for empty uuid; stopping\n")); 5141303Swesolows snmp_free_varbind(table_info->indexes); 5151303Swesolows table_info->indexes = NULL; 5161303Swesolows table_info->number_indexes = 0; 5171303Swesolows return (NULL); 5181303Swesolows } 5191303Swesolows } 5201303Swesolows 5211303Swesolows snmp_set_var_typed_value(table_info->indexes, ASN_OCTET_STR, 5221303Swesolows (uchar_t *)data->d_aci_uuid, strlen(data->d_aci_uuid)); 5231303Swesolows table_info->number_indexes = 1; 5241303Swesolows 5251303Swesolows DEBUGMSGTL((MODNAME_STR, "matching data is %s@%p\n", data->d_aci_uuid, 5261303Swesolows data)); 5271303Swesolows 5281303Swesolows return (data); 5291303Swesolows } 5301303Swesolows 5311303Swesolows /* 5321303Swesolows * Returns the problem data corresponding to the request in table_info. 5331303Swesolows * All request parameters are unmodified. 5341303Swesolows */ 535*2134Swesolows /*ARGSUSED*/ 5361303Swesolows static sunFmProblem_data_t * 5371303Swesolows sunFmProblemTable_pr(netsnmp_handler_registration *reginfo, 5381303Swesolows netsnmp_table_request_info *table_info) 5391303Swesolows { 5401303Swesolows char *uuid; 5411303Swesolows 5421303Swesolows ASSERT(table_info->number_indexes >= 1); 5431303Swesolows 5441303Swesolows uuid = alloca(table_info->indexes->val_len + 1); 5451303Swesolows (void) strlcpy(uuid, (const char *)table_info->indexes->val.string, 5461303Swesolows table_info->indexes->val_len + 1); 5471303Swesolows 5481303Swesolows return (problem_lookup_uuid_exact(uuid)); 5491303Swesolows } 5501303Swesolows 5511303Swesolows /* 5521303Swesolows * Returns the ASN.1 lexicographically first fault event after the one 5531303Swesolows * identified by table_info. Indexes are updated to reflect the OID 5541303Swesolows * of the data returned. This allows us to implement GETNEXT. 5551303Swesolows */ 5561303Swesolows static sunFmFaultEvent_data_t * 5571303Swesolows sunFmFaultEventTable_nextfe(netsnmp_handler_registration *reginfo, 5581303Swesolows netsnmp_table_request_info *table_info) 5591303Swesolows { 5601303Swesolows sunFmProblem_data_t *data; 5611303Swesolows sunFmFaultEvent_data_t *rv; 5621303Swesolows netsnmp_variable_list *var; 5631303Swesolows ulong_t index; 5641303Swesolows 5651303Swesolows for (;;) { 5661303Swesolows switch (table_info->number_indexes) { 5671303Swesolows case 2: 5681303Swesolows default: 5691303Swesolows DEBUGMSGTL((MODNAME_STR, "nextfe: 2 indices:\n")); 5701303Swesolows DEBUGMSGVAR((MODNAME_STR, table_info->indexes)); 5711303Swesolows DEBUGMSG((MODNAME_STR, "\n")); 5721303Swesolows DEBUGMSGVAR((MODNAME_STR, 5731303Swesolows table_info->indexes->next_variable)); 5741303Swesolows DEBUGMSG((MODNAME_STR, "\n")); 5751303Swesolows index = *(ulong_t *) 5761303Swesolows table_info->indexes->next_variable->val.integer + 1; 5771303Swesolows 5781303Swesolows if ((data = sunFmProblemTable_pr(reginfo, 5791303Swesolows table_info)) != NULL && 5801303Swesolows (rv = faultevent_lookup_index_exact(data, index)) != 5811303Swesolows NULL) { 5821303Swesolows snmp_set_var_typed_value( 5831303Swesolows table_info->indexes->next_variable, 5841303Swesolows ASN_UNSIGNED, (uchar_t *)&index, 5851303Swesolows sizeof (index)); 5861303Swesolows return (rv); 5871303Swesolows } 5881303Swesolows 5891303Swesolows if (sunFmProblemTable_nextpr(reginfo, table_info) == 5901303Swesolows NULL) 5911303Swesolows return (NULL); 5921303Swesolows break; 5931303Swesolows case 1: 5941303Swesolows if ((data = sunFmProblemTable_pr(reginfo, 5951303Swesolows table_info)) != NULL) { 5961303Swesolows oid tmpoid[MAX_OID_LEN]; 5971303Swesolows index = 0; 5981303Swesolows 5991303Swesolows DEBUGMSGTL((MODNAME_STR, "nextfe: 1 index:\n")); 6001303Swesolows DEBUGMSGVAR((MODNAME_STR, table_info->indexes)); 6011303Swesolows DEBUGMSG((MODNAME_STR, "\n")); 6021303Swesolows var = 6031303Swesolows SNMP_MALLOC_TYPEDEF(netsnmp_variable_list); 6041303Swesolows snmp_set_var_typed_value(var, ASN_UNSIGNED, 6051303Swesolows (uchar_t *)&index, sizeof (index)); 606*2134Swesolows (void) memcpy(tmpoid, reginfo->rootoid, 6071303Swesolows reginfo->rootoid_len * sizeof (oid)); 6081303Swesolows tmpoid[reginfo->rootoid_len] = 1; 6091303Swesolows tmpoid[reginfo->rootoid_len + 1] = 6101303Swesolows table_info->colnum; 6111303Swesolows if (build_oid_segment(var) != SNMPERR_SUCCESS) { 6121303Swesolows snmp_free_varbind(var); 6131303Swesolows return (NULL); 6141303Swesolows } 615*2134Swesolows snmp_free_varbind( 616*2134Swesolows table_info->indexes->next_variable); 6171303Swesolows table_info->indexes->next_variable = var; 6181303Swesolows table_info->number_indexes = 2; 6191303Swesolows DEBUGMSGTL((MODNAME_STR, "nextfe: built fake " 6201303Swesolows "index:\n")); 6211303Swesolows DEBUGMSGVAR((MODNAME_STR, table_info->indexes)); 6221303Swesolows DEBUGMSG((MODNAME_STR, "\n")); 6231303Swesolows DEBUGMSGVAR((MODNAME_STR, 6241303Swesolows table_info->indexes->next_variable)); 6251303Swesolows DEBUGMSG((MODNAME_STR, "\n")); 6261303Swesolows } else { 6271303Swesolows if (sunFmProblemTable_nextpr(reginfo, 6281303Swesolows table_info) == NULL) 6291303Swesolows return (NULL); 6301303Swesolows } 6311303Swesolows break; 6321303Swesolows case 0: 6331303Swesolows if (sunFmProblemTable_nextpr(reginfo, table_info) == 6341303Swesolows NULL) 6351303Swesolows return (NULL); 6361303Swesolows break; 6371303Swesolows } 6381303Swesolows } 6391303Swesolows } 6401303Swesolows 6411303Swesolows static sunFmFaultEvent_data_t * 6421303Swesolows sunFmFaultEventTable_fe(netsnmp_handler_registration *reginfo, 6431303Swesolows netsnmp_table_request_info *table_info) 6441303Swesolows { 6451303Swesolows sunFmProblem_data_t *data; 6461303Swesolows 6471303Swesolows ASSERT(table_info->number_indexes == 2); 6481303Swesolows 6491303Swesolows if ((data = sunFmProblemTable_pr(reginfo, table_info)) == NULL) 6501303Swesolows return (NULL); 6511303Swesolows 6521303Swesolows return (faultevent_lookup_index_exact(data, 6531303Swesolows *(ulong_t *)table_info->indexes->next_variable->val.integer)); 6541303Swesolows } 6551303Swesolows 656*2134Swesolows /*ARGSUSED*/ 6571303Swesolows static void 6581303Swesolows sunFmProblemTable_return(unsigned int reg, void *arg) 6591303Swesolows { 6601303Swesolows netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *)arg; 6611303Swesolows netsnmp_request_info *request; 6621303Swesolows netsnmp_agent_request_info *reqinfo; 6631303Swesolows netsnmp_handler_registration *reginfo; 6641303Swesolows netsnmp_table_request_info *table_info; 6651303Swesolows sunFmProblem_data_t *data; 6661303Swesolows 6671303Swesolows ASSERT(netsnmp_handler_check_cache(cache) != NULL); 6681303Swesolows 6691303Swesolows (void) pthread_mutex_lock(&update_lock); 6701303Swesolows if (update_status != US_QUIET) { 6711303Swesolows struct timeval tv; 6721303Swesolows 6731303Swesolows tv.tv_sec = UPDATE_WAIT_MILLIS / 1000; 6741303Swesolows tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000; 6751303Swesolows 6761303Swesolows (void) snmp_alarm_register_hr(tv, 0, sunFmProblemTable_return, 6771303Swesolows cache); 6781303Swesolows (void) pthread_mutex_unlock(&update_lock); 6791303Swesolows return; 6801303Swesolows } 6811303Swesolows 6821303Swesolows request = cache->requests; 6831303Swesolows reqinfo = cache->reqinfo; 6841303Swesolows reginfo = cache->reginfo; 6851303Swesolows 6861303Swesolows table_info = netsnmp_extract_table_info(request); 6871303Swesolows request->delegated = 0; 6881303Swesolows 6891303Swesolows ASSERT(table_info->colnum >= SUNFMPROBLEM_COLMIN); 6901303Swesolows ASSERT(table_info->colnum <= SUNFMPROBLEM_COLMAX); 6911303Swesolows 6921303Swesolows /* 6931303Swesolows * table_info->colnum contains the column number requested. 6941303Swesolows * table_info->indexes contains a linked list of snmp variable 6951303Swesolows * bindings for the indexes of the table. Values in the list 6961303Swesolows * have been set corresponding to the indexes of the 6971303Swesolows * request. We have other guarantees as well: 6981303Swesolows * 6991303Swesolows * - The column number is always within range. 7001303Swesolows * - If we have no index data, table_info->index_oid_len is 0. 7011303Swesolows * - We will never receive requests outside our table nor 7021303Swesolows * those with the first subid anything other than 1 (Entry) 7031303Swesolows * nor those without a column number. This is true even 7041303Swesolows * for GETNEXT requests. 7051303Swesolows */ 7061303Swesolows 7071303Swesolows switch (reqinfo->mode) { 7081303Swesolows case MODE_GET: 7091303Swesolows if ((data = sunFmProblemTable_pr(reginfo, table_info)) == 7101303Swesolows NULL) { 7111303Swesolows netsnmp_free_delegated_cache(cache); 7121303Swesolows (void) pthread_mutex_unlock(&update_lock); 7131303Swesolows return; 7141303Swesolows } 7151303Swesolows break; 7161303Swesolows case MODE_GETNEXT: 7171303Swesolows case MODE_GETBULK: 7181303Swesolows if ((data = sunFmProblemTable_nextpr(reginfo, table_info)) == 7191303Swesolows NULL) { 7201303Swesolows netsnmp_free_delegated_cache(cache); 7211303Swesolows (void) pthread_mutex_unlock(&update_lock); 7221303Swesolows return; 7231303Swesolows } 7241303Swesolows break; 7251303Swesolows default: 7261303Swesolows snmp_log(LOG_ERR, MODNAME_STR ": Unsupported request mode %d\n", 7271303Swesolows reqinfo->mode); 7281303Swesolows netsnmp_free_delegated_cache(cache); 7291303Swesolows (void) pthread_mutex_unlock(&update_lock); 7301303Swesolows return; 7311303Swesolows } 7321303Swesolows 7331303Swesolows switch (table_info->colnum) { 7341303Swesolows case SUNFMPROBLEM_COL_UUID: 7351303Swesolows { 7361303Swesolows netsnmp_table_build_result(reginfo, request, table_info, 7371303Swesolows ASN_OCTET_STR, (uchar_t *)data->d_aci_uuid, 7381303Swesolows strlen(data->d_aci_uuid)); 7391303Swesolows break; 7401303Swesolows } 7411303Swesolows case SUNFMPROBLEM_COL_CODE: 7421303Swesolows { 7431303Swesolows netsnmp_table_build_result(reginfo, request, table_info, 7441303Swesolows ASN_OCTET_STR, (uchar_t *)data->d_aci_code, 7451303Swesolows strlen(data->d_aci_code)); 7461303Swesolows break; 7471303Swesolows } 7481303Swesolows case SUNFMPROBLEM_COL_URL: 7491303Swesolows { 7501303Swesolows netsnmp_table_build_result(reginfo, request, table_info, 7511303Swesolows ASN_OCTET_STR, (uchar_t *)data->d_aci_url, 7521303Swesolows strlen(data->d_aci_url)); 7531303Swesolows break; 7541303Swesolows } 7551303Swesolows case SUNFMPROBLEM_COL_DIAGENGINE: 7561303Swesolows { 7571303Swesolows netsnmp_table_build_result(reginfo, request, table_info, 7581303Swesolows ASN_OCTET_STR, (uchar_t *)data->d_diag_engine, 7591303Swesolows strlen(data->d_diag_engine)); 7601303Swesolows break; 7611303Swesolows } 7621303Swesolows case SUNFMPROBLEM_COL_DIAGTIME: 7631303Swesolows { 7641303Swesolows /* 7651303Swesolows * The date_n_time function is not Y2038-safe; this may 7661303Swesolows * need to be updated when a suitable Y2038-safe Net-SNMP 7671303Swesolows * API is available. 7681303Swesolows */ 7691303Swesolows size_t dt_size; 7701303Swesolows time_t dt_time = (time_t)data->d_diag_time.tv_sec; 7711303Swesolows uchar_t *dt = date_n_time(&dt_time, &dt_size); 7721303Swesolows 7731303Swesolows netsnmp_table_build_result(reginfo, request, table_info, 7741303Swesolows ASN_OCTET_STR, dt, dt_size); 7751303Swesolows break; 7761303Swesolows } 7771303Swesolows case SUNFMPROBLEM_COL_SUSPECTCOUNT: 7781303Swesolows { 7791303Swesolows netsnmp_table_build_result(reginfo, request, table_info, 7801303Swesolows ASN_UNSIGNED, (uchar_t *)&data->d_nsuspects, 7811303Swesolows sizeof (data->d_nsuspects)); 7821303Swesolows break; 7831303Swesolows } 7841303Swesolows default: 7851303Swesolows break; 7861303Swesolows } 7871303Swesolows 7881303Swesolows netsnmp_free_delegated_cache(cache); 7891303Swesolows (void) pthread_mutex_unlock(&update_lock); 7901303Swesolows } 7911303Swesolows 7921303Swesolows static int 7931303Swesolows sunFmProblemTable_handler(netsnmp_mib_handler *handler, 7941303Swesolows netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, 7951303Swesolows netsnmp_request_info *requests) 7961303Swesolows { 7971303Swesolows netsnmp_request_info *request; 7981303Swesolows struct timeval tv; 7991303Swesolows 8001303Swesolows tv.tv_sec = UPDATE_WAIT_MILLIS / 1000; 8011303Swesolows tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000; 8021303Swesolows 8031303Swesolows request_update(); 8041303Swesolows 8051303Swesolows for (request = requests; request; request = request->next) { 8061303Swesolows if (request->processed != 0) 8071303Swesolows continue; 8081303Swesolows 8091303Swesolows if (netsnmp_extract_table_info(request) == NULL) 8101303Swesolows continue; 8111303Swesolows 8121303Swesolows request->delegated = 1; 8131303Swesolows (void) snmp_alarm_register_hr(tv, 0, 8141303Swesolows sunFmProblemTable_return, 8151303Swesolows (void *) netsnmp_create_delegated_cache(handler, reginfo, 8161303Swesolows reqinfo, request, NULL)); 8171303Swesolows } 8181303Swesolows 8191303Swesolows return (SNMP_ERR_NOERROR); 8201303Swesolows } 8211303Swesolows 822*2134Swesolows /*ARGSUSED*/ 8231303Swesolows static void 8241303Swesolows sunFmFaultEventTable_return(unsigned int reg, void *arg) 8251303Swesolows { 8261303Swesolows netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *)arg; 8271303Swesolows netsnmp_request_info *request; 8281303Swesolows netsnmp_agent_request_info *reqinfo; 8291303Swesolows netsnmp_handler_registration *reginfo; 8301303Swesolows netsnmp_table_request_info *table_info; 8311303Swesolows sunFmProblem_data_t *pdata; 8321303Swesolows sunFmFaultEvent_data_t *data; 8331303Swesolows 8341303Swesolows ASSERT(netsnmp_handler_check_cache(cache) != NULL); 8351303Swesolows 8361303Swesolows (void) pthread_mutex_lock(&update_lock); 8371303Swesolows if (update_status != US_QUIET) { 8381303Swesolows struct timeval tv; 8391303Swesolows 8401303Swesolows tv.tv_sec = UPDATE_WAIT_MILLIS / 1000; 8411303Swesolows tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000; 8421303Swesolows 8431303Swesolows (void) snmp_alarm_register_hr(tv, 0, 8441303Swesolows sunFmFaultEventTable_return, cache); 8451303Swesolows (void) pthread_mutex_unlock(&update_lock); 8461303Swesolows return; 8471303Swesolows } 8481303Swesolows 8491303Swesolows request = cache->requests; 8501303Swesolows reqinfo = cache->reqinfo; 8511303Swesolows reginfo = cache->reginfo; 8521303Swesolows 8531303Swesolows table_info = netsnmp_extract_table_info(request); 8541303Swesolows request->delegated = 0; 8551303Swesolows 8561303Swesolows ASSERT(table_info->colnum >= SUNFMFAULTEVENT_COLMIN); 8571303Swesolows ASSERT(table_info->colnum <= SUNFMFAULTEVENT_COLMAX); 8581303Swesolows 8591303Swesolows /* 8601303Swesolows * table_info->colnum contains the column number requested. 8611303Swesolows * table_info->indexes contains a linked list of snmp variable 8621303Swesolows * bindings for the indexes of the table. Values in the list 8631303Swesolows * have been set corresponding to the indexes of the 8641303Swesolows * request. We have other guarantees as well: 8651303Swesolows * 8661303Swesolows * - The column number is always within range. 8671303Swesolows * - If we have no index data, table_info->index_oid_len is 0. 8681303Swesolows * - We will never receive requests outside our table nor 8691303Swesolows * those with the first subid anything other than 1 (Entry) 8701303Swesolows * nor those without a column number. This is true even 8711303Swesolows * for GETNEXT requests. 8721303Swesolows */ 8731303Swesolows 8741303Swesolows switch (reqinfo->mode) { 8751303Swesolows case MODE_GET: 8761303Swesolows if ((data = sunFmFaultEventTable_fe(reginfo, table_info)) == 8771303Swesolows NULL) { 8781303Swesolows netsnmp_free_delegated_cache(cache); 8791303Swesolows (void) pthread_mutex_unlock(&update_lock); 8801303Swesolows return; 8811303Swesolows } 8821303Swesolows break; 8831303Swesolows case MODE_GETNEXT: 8841303Swesolows case MODE_GETBULK: 8851303Swesolows if ((data = sunFmFaultEventTable_nextfe(reginfo, table_info)) == 8861303Swesolows NULL) { 8871303Swesolows netsnmp_free_delegated_cache(cache); 8881303Swesolows (void) pthread_mutex_unlock(&update_lock); 8891303Swesolows return; 8901303Swesolows } 8911303Swesolows break; 8921303Swesolows default: 8931303Swesolows snmp_log(LOG_ERR, MODNAME_STR ": Unsupported request mode %d\n", 8941303Swesolows reqinfo->mode); 8951303Swesolows netsnmp_free_delegated_cache(cache); 8961303Swesolows (void) pthread_mutex_unlock(&update_lock); 8971303Swesolows return; 8981303Swesolows } 8991303Swesolows 9001303Swesolows switch (table_info->colnum) { 9011303Swesolows case SUNFMFAULTEVENT_COL_PROBLEMUUID: 9021303Swesolows { 9031303Swesolows if ((pdata = sunFmProblemTable_pr(reginfo, table_info)) 9041303Swesolows == NULL) { 9051303Swesolows netsnmp_table_build_result(reginfo, request, table_info, 9061303Swesolows ASN_OCTET_STR, NULL, 0); 9071303Swesolows break; 9081303Swesolows } 9091303Swesolows netsnmp_table_build_result(reginfo, request, table_info, 9101303Swesolows ASN_OCTET_STR, (uchar_t *)pdata->d_aci_uuid, 9111303Swesolows strlen(pdata->d_aci_uuid)); 9121303Swesolows break; 9131303Swesolows } 9141303Swesolows case SUNFMFAULTEVENT_COL_CLASS: 9151303Swesolows { 9161303Swesolows char *class = "-"; 9171303Swesolows 9181303Swesolows (void) nvlist_lookup_string(data, FM_CLASS, &class); 9191303Swesolows netsnmp_table_build_result(reginfo, request, table_info, 9201303Swesolows ASN_OCTET_STR, (uchar_t *)class, strlen(class)); 9211303Swesolows break; 9221303Swesolows } 9231303Swesolows case SUNFMFAULTEVENT_COL_CERTAINTY: 9241303Swesolows { 9251303Swesolows uint8_t pct = 0; 9261303Swesolows ulong_t pl; 9271303Swesolows 9281303Swesolows (void) nvlist_lookup_uint8(data, FM_FAULT_CERTAINTY, 9291303Swesolows &pct); 9301303Swesolows pl = (ulong_t)pct; 9311303Swesolows netsnmp_table_build_result(reginfo, request, table_info, 9321303Swesolows ASN_UNSIGNED, (uchar_t *)&pl, sizeof (pl)); 9331303Swesolows break; 9341303Swesolows } 9351303Swesolows case SUNFMFAULTEVENT_COL_ASRU: 9361303Swesolows { 9371303Swesolows nvlist_t *asru = NULL; 938*2134Swesolows char *fmri, *str; 9391303Swesolows 9401303Swesolows (void) nvlist_lookup_nvlist(data, FM_FAULT_ASRU, &asru); 941*2134Swesolows if ((str = sunFm_nvl2str(asru)) == NULL) 9421303Swesolows fmri = "-"; 943*2134Swesolows else 944*2134Swesolows fmri = str; 945*2134Swesolows 9461303Swesolows netsnmp_table_build_result(reginfo, request, table_info, 9471303Swesolows ASN_OCTET_STR, (uchar_t *)fmri, strlen(fmri)); 948*2134Swesolows free(str); 9491303Swesolows break; 9501303Swesolows } 9511303Swesolows case SUNFMFAULTEVENT_COL_FRU: 9521303Swesolows { 9531303Swesolows nvlist_t *fru = NULL; 954*2134Swesolows char *fmri, *str; 9551303Swesolows 9561303Swesolows (void) nvlist_lookup_nvlist(data, FM_FAULT_FRU, &fru); 957*2134Swesolows if ((str = sunFm_nvl2str(fru)) == NULL) 9581303Swesolows fmri = "-"; 959*2134Swesolows else 960*2134Swesolows fmri = str; 961*2134Swesolows 9621303Swesolows netsnmp_table_build_result(reginfo, request, table_info, 9631303Swesolows ASN_OCTET_STR, (uchar_t *)fmri, strlen(fmri)); 964*2134Swesolows free(str); 9651303Swesolows break; 9661303Swesolows } 9671303Swesolows case SUNFMFAULTEVENT_COL_RESOURCE: 9681303Swesolows { 9691303Swesolows nvlist_t *rsrc = NULL; 970*2134Swesolows char *fmri, *str; 9711303Swesolows 972*2134Swesolows (void) nvlist_lookup_nvlist(data, FM_FAULT_RESOURCE, &rsrc); 973*2134Swesolows if ((str = sunFm_nvl2str(rsrc)) == NULL) 9741303Swesolows fmri = "-"; 975*2134Swesolows else 976*2134Swesolows fmri = str; 977*2134Swesolows 9781303Swesolows netsnmp_table_build_result(reginfo, request, table_info, 9791303Swesolows ASN_OCTET_STR, (uchar_t *)fmri, strlen(fmri)); 980*2134Swesolows free(str); 9811303Swesolows break; 9821303Swesolows } 9831303Swesolows default: 9841303Swesolows break; 9851303Swesolows } 9861303Swesolows 9871303Swesolows netsnmp_free_delegated_cache(cache); 9881303Swesolows (void) pthread_mutex_unlock(&update_lock); 9891303Swesolows } 9901303Swesolows 9911303Swesolows static int 9921303Swesolows sunFmFaultEventTable_handler(netsnmp_mib_handler *handler, 9931303Swesolows netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, 9941303Swesolows netsnmp_request_info *requests) 9951303Swesolows { 9961303Swesolows netsnmp_request_info *request; 9971303Swesolows struct timeval tv; 9981303Swesolows 9991303Swesolows tv.tv_sec = UPDATE_WAIT_MILLIS / 1000; 10001303Swesolows tv.tv_usec = (UPDATE_WAIT_MILLIS % 1000) * 1000; 10011303Swesolows 10021303Swesolows request_update(); 10031303Swesolows 10041303Swesolows for (request = requests; request; request = request->next) { 10051303Swesolows if (request->processed != 0) 10061303Swesolows continue; 10071303Swesolows 10081303Swesolows if (netsnmp_extract_table_info(request) == NULL) 10091303Swesolows continue; 10101303Swesolows 10111303Swesolows request->delegated = 1; 10121303Swesolows (void) snmp_alarm_register_hr(tv, 0, 10131303Swesolows sunFmFaultEventTable_return, 10141303Swesolows (void *) netsnmp_create_delegated_cache(handler, reginfo, 10151303Swesolows reqinfo, request, NULL)); 10161303Swesolows } 10171303Swesolows 10181303Swesolows return (SNMP_ERR_NOERROR); 10191303Swesolows } 1020