/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <fm/fmd_snmp.h>
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <pthread.h>
#include <stddef.h>
#include <errno.h>
#include <alloca.h>
#include <locale.h>
#include <libuutil.h>
#include <libnvpair.h>
#include "sunFM_impl.h"
#include "problem.h"
/*
* We assume that the number of suspect fault events associated with a
* particular case will generally be sufficiently small that the overhead
* associated with indexing them in a tree would exceed the gain from
* not traversing the fault list for each request.
*/
problem_uuid_avl != NULL)
/*
* Update types. Single-index and all are mutually exclusive.
*/
/*
* Locking strategy is described in module.c.
*/
static int valid_stamp;
static sunFmProblem_data_t *
{
return (&key);
}
static sunFmProblem_data_t *
{
return (data);
}
static sunFmProblem_data_t *
{
return (data);
}
static sunFmFaultEvent_data_t *
{
return (NULL);
return (NULL);
}
static sunFmFaultStatus_data_t
{
return (0);
return (0);
return (0);
}
/*ARGSUSED*/
static int
{
int err;
"for new problem data at %s:%d\n", __FILE__,
__LINE__);
return (0);
}
!= 0) {
return (0);
}
(char **)&data->d_aci_uuid);
&nvl) == 0)
nelem >= 2) {
}
} else {
int i;
for (i = 0; i < nelem; i++)
}
/*
* We don't touch problems we've seen before; they shouldn't change
* in any way we care about, since they've already been solved. The
* state, however, could change, and if we later expose that to the
* client we need to update it here.
*/
return (0);
}
static int
{
return (SNMP_ERR_RESOURCEUNAVAILABLE);
}
++valid_stamp;
update_ctx) != 0) {
return (SNMP_ERR_RESOURCEUNAVAILABLE);
}
return (SNMP_ERR_NOERROR);
}
/*ARGSUSED*/
static void
{
/*
* The current problem_update implementation offers minimal savings
* for the use of index-only updates; therefore we always do a full
* update. If it becomes advantageous to limit updates to a single
* index, the contexts can be queued by the handler instead.
*/
for (;;) {
(void) pthread_mutex_lock(&update_lock);
while (update_status == US_QUIET)
(void) pthread_mutex_unlock(&update_lock);
(void) problem_update(&uc);
}
}
static void
request_update(void)
{
(void) pthread_mutex_lock(&update_lock);
if (update_status != US_QUIET) {
(void) pthread_mutex_unlock(&update_lock);
return;
}
(void) pthread_cond_signal(&update_cv);
(void) pthread_mutex_unlock(&update_lock);
}
/*ARGSUSED*/
static int
{
}
int
sunFmProblemTable_init(void)
{
int err;
return (MIB_REGISTRATION_FAILED);
}
return (MIB_REGISTRATION_FAILED);
}
NULL)) != 0) {
return (MIB_REGISTRATION_FAILED);
}
if ((table_info =
return (MIB_REGISTRATION_FAILED);
return (MIB_REGISTRATION_FAILED);
}
/*
* The Net-SNMP template uses add_indexes here, but that
* function is unsafe because it does not check for failure.
*/
return (MIB_REGISTRATION_FAILED);
}
sizeof (sunFmProblem_data_t),
UU_AVL_DEBUG)) == NULL) {
return (MIB_REGISTRATION_FAILED);
}
UU_AVL_DEBUG)) == NULL) {
return (MIB_REGISTRATION_FAILED);
}
return (err);
}
return (MIB_REGISTERED_OK);
}
int
{
int err;
if ((table_info =
return (MIB_REGISTRATION_FAILED);
if ((handler =
netsnmp_create_handler_registration("sunFmFaultEventTable",
return (MIB_REGISTRATION_FAILED);
}
/*
* The Net-SNMP template uses add_indexes here, but that
* function is unsafe because it does not check for failure.
*/
return (MIB_REGISTRATION_FAILED);
}
return (MIB_REGISTRATION_FAILED);
}
return (err);
}
return (MIB_REGISTERED_OK);
}
/*
* Returns the problem data for the problem whose uuid is next according
* to ASN.1 lexical ordering after the request in table_info. Indexes are
* updated to reflect the OID of the value being returned. This allows
* us to implement GETNEXT.
*/
static sunFmProblem_data_t *
{
return (NULL);
}
} else {
/*
* Construct the next possible UUID to look for. We can
* simply increment the least significant byte of the last
* UUID because (a) that preserves SNMP lex order and (b)
* the characters that may appear in a UUID do not include
* 127 nor 255.
*/
}
"%s; trying next column\n", uuid));
if (table_info->colnum >=
table_info->number_indexes = 0;
return (NULL);
}
table_info->colnum++;
"for empty uuid; stopping\n"));
table_info->number_indexes = 0;
return (NULL);
}
}
data));
return (data);
}
/*
* Returns the problem data corresponding to the request in table_info.
* All request parameters are unmodified.
*/
/*ARGSUSED*/
static sunFmProblem_data_t *
{
char *uuid;
return (problem_lookup_uuid_exact(uuid));
}
/*
* Returns the ASN.1 lexicographically first fault event after the one
* identified by table_info. Indexes are updated to reflect the OID
* of the data returned. This allows us to implement GETNEXT.
*/
static sunFmFaultEvent_data_t *
{
for (;;) {
switch (table_info->number_indexes) {
case 2:
default:
table_info)) != NULL &&
index)) != 0 &&
NULL) {
(void) snmp_set_var_typed_value(
sizeof (index));
return (rv);
}
NULL)
return (NULL);
break;
case 1:
table_info)) != NULL) {
index = 0;
var =
(void) snmp_set_var_typed_value(var,
sizeof (index));
return (NULL);
}
"index:\n"));
} else {
table_info) == NULL)
return (NULL);
}
break;
case 0:
NULL)
return (NULL);
break;
}
}
}
static sunFmFaultEvent_data_t *
{
return (NULL);
if (*statusp == 0)
return (NULL);
return (faultevent_lookup_index_exact(data,
}
/*ARGSUSED*/
static void
{
(void) pthread_mutex_lock(&update_lock);
if (update_status != US_QUIET) {
cache);
(void) pthread_mutex_unlock(&update_lock);
return;
}
/*
* table_info->colnum contains the column number requested.
* table_info->indexes contains a linked list of snmp variable
* bindings for the indexes of the table. Values in the list
* have been set corresponding to the indexes of the
* request. We have other guarantees as well:
*
* - The column number is always within range.
* - If we have no index data, table_info->index_oid_len is 0.
* - We will never receive requests outside our table nor
* those with the first subid anything other than 1 (Entry)
* nor those without a column number. This is true even
* for GETNEXT requests.
*/
case MODE_GET:
NULL) {
(void) pthread_mutex_unlock(&update_lock);
return;
}
break;
case MODE_GETNEXT:
case MODE_GETBULK:
NULL) {
(void) pthread_mutex_unlock(&update_lock);
return;
}
break;
default:
(void) pthread_mutex_unlock(&update_lock);
return;
}
switch (table_info->colnum) {
case SUNFMPROBLEM_COL_UUID:
{
break;
}
case SUNFMPROBLEM_COL_CODE:
{
break;
}
case SUNFMPROBLEM_COL_URL:
{
break;
}
{
break;
}
{
/*
* The date_n_time function is not Y2038-safe; this may
* need to be updated when a suitable Y2038-safe Net-SNMP
* API is available.
*/
break;
}
{
sizeof (data->d_nsuspects));
break;
}
default:
break;
}
(void) pthread_mutex_unlock(&update_lock);
}
static int
{
continue;
continue;
(void) snmp_alarm_register_hr(tv, 0,
}
return (SNMP_ERR_NOERROR);
}
/*ARGSUSED*/
static void
{
(void) pthread_mutex_lock(&update_lock);
if (update_status != US_QUIET) {
(void) snmp_alarm_register_hr(tv, 0,
(void) pthread_mutex_unlock(&update_lock);
return;
}
/*
* table_info->colnum contains the column number requested.
* table_info->indexes contains a linked list of snmp variable
* bindings for the indexes of the table. Values in the list
* have been set corresponding to the indexes of the
* request. We have other guarantees as well:
*
* - The column number is always within range.
* - If we have no index data, table_info->index_oid_len is 0.
* - We will never receive requests outside our table nor
* those with the first subid anything other than 1 (Entry)
* nor those without a column number. This is true even
* for GETNEXT requests.
*/
case MODE_GET:
(void) pthread_mutex_unlock(&update_lock);
return;
}
break;
case MODE_GETNEXT:
case MODE_GETBULK:
(void) pthread_mutex_unlock(&update_lock);
return;
}
break;
default:
(void) pthread_mutex_unlock(&update_lock);
return;
}
switch (table_info->colnum) {
{
== NULL) {
break;
}
break;
}
{
break;
}
{
&pct);
break;
}
case SUNFMFAULTEVENT_COL_ASRU:
{
fmri = "-";
else
break;
}
case SUNFMFAULTEVENT_COL_FRU:
{
fmri = "-";
else
break;
}
{
fmri = "-";
else
break;
}
{
if (status & FM_SUSPECT_FAULTY)
else if (status & FM_SUSPECT_NOT_PRESENT)
else if (status & FM_SUSPECT_REPLACED)
else if (status & FM_SUSPECT_REPAIRED)
else if (status & FM_SUSPECT_ACQUITTED)
break;
}
{
break;
}
default:
break;
}
(void) pthread_mutex_unlock(&update_lock);
}
static int
{
continue;
continue;
(void) snmp_alarm_register_hr(tv, 0,
}
return (SNMP_ERR_NOERROR);
}