2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <sys/fm/protocol.h>
2N/A#include <fm/libtopo.h>
2N/A#include <fm/fmd_msg.h>
2N/A#include <fm/fmd_api.h>
2N/A#include <strings.h>
2N/A
2N/A#include "asr.h"
2N/A#include "asr_buf.h"
2N/A#include "asr_err.h"
2N/A#include "asr_nvl.h"
2N/A
2N/A#define ASR_FLT_CLASS "class"
2N/A#define ASR_FLT_CERTAINTY "certainty"
2N/A#define ASR_FLT_DESCRIPTION "description"
2N/A#define ASR_FLT_INJECTED "injected"
2N/A#define ASR_FLT_SEVERITY "severity"
2N/A#define ASR_FLT_REASON "reason"
2N/A#define ASR_FLT_FRU_NAME "fru.name"
2N/A#define ASR_FLT_FRU_ID "fru.id"
2N/A#define ASR_FLT_FRU_PART "fru.part"
2N/A#define ASR_FLT_FRU_SERIAL "fru.serial"
2N/A#define ASR_FLT_FRU_REVISION "fru.revision"
2N/A
2N/A#define ASR_FLT_SEVERITY_NA "NA"
2N/A#define ASR_FLT_SEVERITY_NONE "None"
2N/A#define ASR_FLT_SEVERITY_MAJOR "Major"
2N/A#define ASR_FLT_SEVERITY_MINOR "Minor"
2N/A#define ASR_FLT_SEVERITY_CRITICAL "Critical"
2N/A
2N/A/*
2N/A * Returns a supported ASR severity value from the FMA severity value.
2N/A * NA, None, Major, Minor, Critical
2N/A */
2N/Astatic char *
2N/Aasr_sev_from_fma_sev(char *fmasev)
2N/A{
2N/A if (fmasev == NULL)
2N/A return (ASR_FLT_SEVERITY_NA);
2N/A if (strcmp(fmasev, "none") == 0 ||
2N/A strcmp(fmasev, ASR_FLT_SEVERITY_NONE) == 0)
2N/A return (ASR_FLT_SEVERITY_NONE);
2N/A if (strcmp(fmasev, "minor") == 0 ||
2N/A strcmp(fmasev, ASR_FLT_SEVERITY_MINOR) == 0)
2N/A return (ASR_FLT_SEVERITY_MINOR);
2N/A if (strcmp(fmasev, "major") == 0 ||
2N/A strcmp(fmasev, ASR_FLT_SEVERITY_MAJOR) == 0)
2N/A return (ASR_FLT_SEVERITY_MAJOR);
2N/A if (strcmp(fmasev, "critical") == 0 ||
2N/A strcmp(fmasev, ASR_FLT_SEVERITY_CRITICAL) == 0)
2N/A return (ASR_FLT_SEVERITY_CRITICAL);
2N/A return (ASR_FLT_SEVERITY_NA);
2N/A}
2N/A
2N/A/*
2N/A * Adds the diagnosis engine FMRI as additional information.
2N/A */
2N/Astatic int
2N/Aasr_add_de(topo_hdl_t *thp, nvlist_t *fault, int pad, asr_buf_t *out)
2N/A{
2N/A nvlist_t *de;
2N/A char *fmristr = NULL;
2N/A int err;
2N/A
2N/A err = nvlist_lookup_nvlist(fault, FM_SUSPECT_DE, &de);
2N/A if (err != 0 || de == NULL)
2N/A goto finally;
2N/A
2N/A if ((fmristr = asr_topo_fmri2str(thp, de)) == NULL) {
2N/A err = ASR_FAILURE;
2N/A goto finally;
2N/A }
2N/A
2N/A err = asr_buf_append_xml_ai(out, pad, "de", fmristr);
2N/A
2N/Afinally:
2N/A if (fmristr != NULL)
2N/A free(fmristr);
2N/A
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Pulls out the ASR component name from an FMRI string.
2N/A */
2N/Astatic char *
2N/Aasr_fmri_name(char *fmri)
2N/A{
2N/A char *name = fmri;
2N/A char *cp;
2N/A char *rname;
2N/A for (cp = fmri; *cp != '\0'; cp++)
2N/A if (*cp == '/')
2N/A name = cp;
2N/A if (*name == '/')
2N/A name++;
2N/A
2N/A rname = strdup(name);
2N/A
2N/A for (cp = rname; *cp != '\0'; cp++)
2N/A if (*cp == '=')
2N/A *cp = ' ';
2N/A return (rname);
2N/A}
2N/A
2N/A/*
2N/A * Truncates the fmri name string so it just contains the fru type.
2N/A */
2N/Astatic void
2N/Aasr_fmri_type(char *name)
2N/A{
2N/A int i;
2N/A for (i = 0; name[i] != '\0'; i++) {
2N/A if (name[i] == ' ') {
2N/A name[i] = '\0';
2N/A break;
2N/A }
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * Create hardware component for a manual fault.
2N/A */
2N/Astatic int
2N/Aasr_fault_fru(asr_buf_t *bp, nvlist_t *event)
2N/A{
2N/A int err = 0;
2N/A int pad = 3;
2N/A char *fru_name = asr_nvl_str(event, ASR_FLT_FRU_NAME);
2N/A char *fru_id = asr_nvl_str(event, ASR_FLT_FRU_ID);
2N/A char *fru_serial = asr_nvl_str(event, ASR_FLT_FRU_SERIAL);
2N/A char *fru_part = asr_nvl_str(event, ASR_FLT_FRU_PART);
2N/A char *fru_revision = asr_nvl_str(event, ASR_FLT_FRU_REVISION);
2N/A
2N/A /* FRU name is required by ASR message schema */
2N/A if (fru_name == NULL)
2N/A return (asr_error(EASR_FM, "fault missing FRU name"));
2N/A
2N/A err |= asr_buf_append_xml_elem(
2N/A bp, pad - 1, "hardware-component");
2N/A
2N/A err |= asr_buf_append_xml_nv(bp, pad, "name", fru_name);
2N/A err |= asr_buf_append_xml_nvtoken(bp, pad, "id", fru_id);
2N/A err |= asr_buf_append_xml_nv(bp, pad, "serial", fru_serial);
2N/A err |= asr_buf_append_xml_nv(bp, pad, "part", fru_part);
2N/A err |= asr_buf_append_xml_nvtoken(bp, pad,
2N/A "revision", fru_revision);
2N/A err |= asr_buf_append_xml_end(
2N/A bp, pad - 1, "hardware-component");
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Adds and ASR <hardware-component> element for each FRU suspect
2N/A */
2N/Astatic int
2N/Aasr_fault_components(asr_handle_t *ah,
2N/A asr_buf_t *bp, nvlist_t **faults, uint_t nfaults, nvlist_t *event)
2N/A{
2N/A topo_hdl_t *thp;
2N/A uint_t ii;
2N/A int err = 0;
2N/A int pad = 3;
2N/A boolean_t use_schema_2_1 = asr_use_schema_2_1(ah);
2N/A
2N/A if (nfaults == 0)
2N/A return (asr_fault_fru(bp, event));
2N/A
2N/A if ((thp = topo_open(TOPO_VERSION, NULL, &err)) == NULL) {
2N/A (void) asr_error(EASR_TOPO,
2N/A "failed to alloc topo handle: %s", topo_strerror(err));
2N/A return (ASR_FAILURE);
2N/A }
2N/A
2N/A for (ii = 0; ii < nfaults; ++ii) {
2N/A nvlist_t *fault = faults[ii];
2N/A nvlist_t *frunvl, *authority = NULL;
2N/A nvlist_t *asru, *resource;
2N/A
2N/A char *fmristr, *scheme;
2N/A char *hc_id, *hc_name, *hc_part, *hc_revision, *hc_serial_id;
2N/A
2N/A char *class;
2N/A uint8_t certainty;
2N/A char certaintystr[8];
2N/A
2N/A if (nvlist_lookup_string(fault, ASR_FLT_CLASS, &class) != 0)
2N/A class = NULL;
2N/A if (nvlist_lookup_uint8(
2N/A fault, ASR_FLT_CERTAINTY, &certainty) != 0)
2N/A certaintystr[0] = '\0';
2N/A else
2N/A (void) snprintf(certaintystr, sizeof (certaintystr),
2N/A "%d", certainty);
2N/A
2N/A if (nvlist_lookup_nvlist(fault, FM_FAULT_ASRU, &asru) != 0)
2N/A asru = NULL;
2N/A if (nvlist_lookup_nvlist(
2N/A fault, FM_FAULT_RESOURCE, &resource) != 0)
2N/A resource = NULL;
2N/A
2N/A if (nvlist_lookup_nvlist(fault, FM_FAULT_FRU, &frunvl) != 0) {
2N/A /* This must be a service fault. */
2N/A nvlist_t *fmrinvl;
2N/A char *name;
2N/A char *desc;
2N/A
2N/A if (asru == NULL && resource == NULL) {
2N/A err = asr_error(EASR_SC, "fault contained "
2N/A "no fru, asru, or resource");
2N/A goto finally;
2N/A }
2N/A
2N/A fmrinvl = asru == NULL ? resource : asru;
2N/A if ((fmristr = asr_topo_fmri2str(
2N/A thp, fmrinvl)) == NULL) {
2N/A err = ASR_FAILURE;
2N/A goto finally;
2N/A }
2N/A name = asr_nvl_str(fmrinvl, "mod-name");
2N/A if (name == NULL)
2N/A name = asr_fmri_str_to_name(fmristr);
2N/A desc = asr_nvl_str(fmrinvl, "mod-desc");
2N/A if (desc == NULL)
2N/A desc = "-";
2N/A
2N/A err = asr_buf_append_xml_elem(
2N/A bp, pad, "software-module");
2N/A err |= asr_buf_append_xml_nvtoken(
2N/A bp, pad+1, "name", name);
2N/A err |= asr_buf_append_xml_nv(
2N/A bp, pad+1, "description", desc);
2N/A err |= asr_buf_append_xml_end(
2N/A bp, pad, "software-module");
2N/A
2N/A free(fmristr);
2N/A
2N/A if (err != 0)
2N/A goto finally;
2N/A
2N/A continue;
2N/A }
2N/A
2N/A if (nvlist_lookup_string(
2N/A frunvl, FM_FMRI_SCHEME, &scheme) != 0) {
2N/A err = asr_error(EASR_SC,
2N/A "expected fmri to have scheme");
2N/A goto finally;
2N/A }
2N/A
2N/A if (strcmp(scheme, FM_FMRI_SCHEME_HC) != 0) {
2N/A err = asr_error(EASR_SC, "expected '%s' scheme",
2N/A FM_FMRI_SCHEME_HC);
2N/A goto finally;
2N/A }
2N/A
2N/A if ((fmristr = asr_topo_fmri2str(thp, frunvl)) == NULL) {
2N/A err = ASR_FAILURE;
2N/A goto finally;
2N/A }
2N/A
2N/A hc_name = asr_fmri_name(fmristr);
2N/A hc_id = asr_fmri_str_to_name(fmristr);
2N/A
2N/A if (nvlist_lookup_string(frunvl, FM_FMRI_HC_V1_FRU_PN,
2N/A &hc_part) != 0 && nvlist_lookup_string(frunvl,
2N/A FM_FMRI_HC_V0_PART, &hc_part) != 0)
2N/A hc_part = "N/A";
2N/A if (nvlist_lookup_string(frunvl, FM_FMRI_HC_V1_FRU_REV,
2N/A &hc_revision) != 0 && nvlist_lookup_string(frunvl,
2N/A FM_FMRI_HC_V0_REVISION, &hc_revision) != 0)
2N/A hc_revision = "N/A";
2N/A if (nvlist_lookup_string(frunvl, FM_FMRI_HC_V1_FRU_SN,
2N/A &hc_serial_id) != 0 && nvlist_lookup_string(frunvl,
2N/A FM_FMRI_HC_V0_SERIAL, &hc_serial_id) != 0)
2N/A hc_serial_id = "N/A";
2N/A
2N/A err |= asr_buf_append_xml_elem(bp, pad++, "hardware-component");
2N/A err |= asr_buf_append_xml_nv(bp, pad, "name", hc_name);
2N/A err |= asr_buf_append_xml_nvtoken(bp, pad, "id", hc_id);
2N/A
2N/A if (use_schema_2_1 && frunvl != NULL) {
2N/A nvlist_t *authority;
2N/A if (nvlist_lookup_nvlist(
2N/A frunvl, FM_FAULT_RESOURCE, &authority) != 0) {
2N/A char *chassis_model = asr_nvl_str(
2N/A authority, FM_FMRI_AUTH_V1_CHASSIS_NM);
2N/A char *chassis_serial = asr_nvl_str(
2N/A authority, FM_FMRI_AUTH_V1_CHASSIS_SN);
2N/A err |= asr_buf_append_xml_nv(
2N/A bp, pad, "chassis-model", chassis_model);
2N/A err |= asr_buf_append_xml_nv(
2N/A bp, pad, "chassis-serial", chassis_serial);
2N/A }
2N/A }
2N/A
2N/A err |= asr_buf_append_xml_nv(bp, pad, "serial", hc_serial_id);
2N/A err |= asr_buf_append_xml_nv(bp, pad, "part", hc_part);
2N/A
2N/A if (use_schema_2_1) {
2N/A err |= asr_buf_append_xml_nvtoken(bp, pad,
2N/A "fru-revision", hc_revision);
2N/A } else {
2N/A err |= asr_buf_append_xml_nvtoken(bp, pad,
2N/A "revision", hc_revision);
2N/A }
2N/A
2N/A if (use_schema_2_1) {
2N/A char *hc_data;
2N/A /* fault class: fault.cpu.intel.IOcache */
2N/A err |= asr_buf_append_xml_nv(
2N/A bp, pad, "fault", asr_nvl_str(fault, FM_CLASS));
2N/A /* location /SYS/MB/P0 */
2N/A if (nvlist_lookup_string(
2N/A fault, FM_FAULT_LOCATION, &hc_data) != 0)
2N/A err |= asr_buf_append_xml_nv(
2N/A bp, pad, "location", hc_data);
2N/A
2N/A /* manufacturer */
2N/A if (nvlist_lookup_string(
2N/A frunvl, "manufacturer", &hc_data) != 0)
2N/A err |= asr_buf_append_xml_nv(
2N/A bp, pad, "manufacturer", hc_data);
2N/A /* model */
2N/A if (nvlist_lookup_string(
2N/A frunvl, "model", &hc_data) != 0)
2N/A err |= asr_buf_append_xml_nv(
2N/A bp, pad, "model", hc_data);
2N/A /* capacity */
2N/A if (nvlist_lookup_string(
2N/A frunvl, "capacity", &hc_data) != 0)
2N/A err |= asr_buf_append_xml_nv(
2N/A bp, pad, "capacity", hc_data);
2N/A
2N/A /* certainty */
2N/A err |= asr_buf_append_xml_nv(
2N/A bp, pad, "certainty", certaintystr);
2N/A }
2N/A
2N/A /* Add required FRU authority information */
2N/A if (nvlist_lookup_nvlist(frunvl, FM_FMRI_AUTHORITY,
2N/A &authority) == 0)
2N/A err |= asr_buf_append_xml_ainvl(bp, pad, authority);
2N/A
2N/A /* Add optional additional-information elements */
2N/A err |= asr_add_de(thp, event, pad, bp);
2N/A
2N/A asr_fmri_type(hc_name);
2N/A err |= asr_buf_append_xml_ai(bp, pad, "type", hc_name);
2N/A
2N/A err |= asr_buf_append_xml_ai(bp, pad, "class", class);
2N/A if (certaintystr[0] != '\0')
2N/A err |= asr_buf_append_xml_ai(bp, pad, "certainty",
2N/A certaintystr);
2N/A
2N/A err |= asr_buf_append_xml_ai(bp, pad, "fmri", fmristr);
2N/A
2N/A if (asru != NULL) {
2N/A char *asrustr = asr_topo_fmri2str(thp, asru);
2N/A if (asrustr != NULL) {
2N/A err |= asr_buf_append_xml_ai(
2N/A bp, pad, "asru", asrustr);
2N/A free(asrustr);
2N/A }
2N/A }
2N/A if (resource != NULL) {
2N/A char *rstr = asr_topo_fmri2str(thp, resource);
2N/A if (rstr != NULL) {
2N/A err |= asr_buf_append_xml_ai(
2N/A bp, pad, "resource", rstr);
2N/A free(rstr);
2N/A }
2N/A }
2N/A
2N/A err |= asr_buf_append_xml_end(bp, --pad, "hardware-component");
2N/A
2N/A free(fmristr);
2N/A free(hc_name);
2N/A }
2N/Afinally:
2N/A topo_close(thp);
2N/A return (err == 0 ? ASR_OK : ASR_FAILURE);
2N/A}
2N/A
2N/A/*
2N/A * Gets the description and severity from and FMA event by looking up
2N/A * the dictionary information for the fault code.
2N/A */
2N/Astatic nvlist_t *
2N/Aasr_get_fmsg_items(nvlist_t *event)
2N/A{
2N/A fmd_msg_hdl_t *msghdl;
2N/A nvlist_t *items;
2N/A
2N/A char *desc = asr_nvl_str(event, ASR_FLT_DESCRIPTION);
2N/A char *sev = asr_nvl_str(event, ASR_FLT_SEVERITY);
2N/A char *reason = asr_nvl_str(event, ASR_FLT_REASON);
2N/A
2N/A items = asr_nvl_alloc();
2N/A if (items == NULL) {
2N/A (void) ASR_ERROR(EASR_NOMEM);
2N/A return (items);
2N/A }
2N/A
2N/A if (desc != NULL || sev != NULL) {
2N/A (void) asr_nvl_add_str(items, ASR_FLT_DESCRIPTION, desc);
2N/A (void) asr_nvl_add_str(items, ASR_FLT_SEVERITY, sev);
2N/A (void) asr_nvl_add_str(items, ASR_FLT_REASON, reason);
2N/A } else {
2N/A if ((msghdl = fmd_msg_init(NULL, FMD_MSG_VERSION)) != NULL) {
2N/A char *desc, *sev;
2N/A
2N/A if ((desc = fmd_msg_getitem_nv(
2N/A msghdl, NULL, event, FMD_MSG_ITEM_DESC)) == NULL)
2N/A (void) nvlist_add_string(
2N/A items, ASR_FLT_DESCRIPTION, desc);
2N/A
2N/A if ((sev = fmd_msg_getitem_nv(msghdl,
2N/A NULL, event, FMD_MSG_ITEM_SEVERITY)) == NULL)
2N/A (void) nvlist_add_string(
2N/A items, ASR_FLT_SEVERITY, sev);
2N/A fmd_msg_fini(msghdl);
2N/A } else {
2N/A (void) ASR_ERROR(EASR_NOMEM);
2N/A }
2N/A }
2N/A
2N/A return (items);
2N/A}
2N/A
2N/Astatic int
2N/Aasr_fault_addtime(nvlist_t *fault, char *timebuf, int tlen)
2N/A{
2N/A struct tm *tm;
2N/A int64_t *tv;
2N/A uint_t tn;
2N/A
2N/A if (nvlist_lookup_int64_array(fault, FM_SUSPECT_DIAG_TIME, &tv, &tn)) {
2N/A time_t now = time(NULL);
2N/A if ((tm = gmtime(&now)) == NULL)
2N/A tm = localtime(&now);
2N/A } else {
2N/A time_t ftime = tv[0];
2N/A if ((tm = gmtime(&ftime)) == NULL)
2N/A tm = localtime(&ftime);
2N/A }
2N/A if (strftime(timebuf, tlen, "%FT%T", tm) == 0)
2N/A return (asr_error(EASR_FM, "fault has bad diag time"));
2N/A return (ASR_OK);
2N/A}
2N/A
2N/A/*
2N/A * Creates an ASR event message or updates an FMA fault event.
2N/A */
2N/Astatic int
2N/Ado_asr_fault_msg(asr_handle_t *ah, nvlist_t *fault,
2N/A char *parent, char *msg_name, char *event_name,
2N/A asr_message_t **out_msg)
2N/A{
2N/A int err;
2N/A int pad = 1;
2N/A int rollback;
2N/A char *msgid, *uuid;
2N/A char *description = NULL, *severity = NULL, *reason = NULL;
2N/A char timebuf[64];
2N/A nvlist_t *items = NULL;
2N/A asr_message_t *msg = NULL;
2N/A asr_buf_t *buf;
2N/A nvlist_t **faults;
2N/A uint_t nfaults;
2N/A boolean_t use_schema_2_1 = asr_use_schema_2_1(ah);
2N/A boolean_t injected;
2N/A
2N/A /* Pick out particular fields for inclusion directly in the XML. */
2N/A if (nvlist_lookup_string(fault, FM_SUSPECT_DIAG_CODE, &msgid) != 0)
2N/A return (asr_error(EASR_FM, "fault missing diag code"));
2N/A
2N/A if (nvlist_lookup_string(fault, FM_SUSPECT_UUID, &uuid))
2N/A return (asr_error(EASR_FM, "fault missing uuid"));
2N/A
2N/A asr_log_debug(ah, "Creating ASR fault message for UUID=%s", uuid);
2N/A
2N/A if (asr_fault_addtime(fault, timebuf, sizeof (timebuf))) {
2N/A return (asr_error(EASR_FM, "fault missing diag time"));
2N/A }
2N/A
2N/A /*
2N/A * Look up Severity and Descripiton values.
2N/A */
2N/A items = asr_get_fmsg_items(fault);
2N/A if (items != NULL) {
2N/A (void) nvlist_lookup_string(
2N/A items, ASR_FLT_SEVERITY, &severity);
2N/A (void) nvlist_lookup_string(
2N/A items, ASR_FLT_DESCRIPTION, &description);
2N/A (void) nvlist_lookup_string(
2N/A items, ASR_FLT_REASON, &reason);
2N/A }
2N/A severity = asr_sev_from_fma_sev(severity);
2N/A if (description == NULL)
2N/A description = "-";
2N/A if (reason == NULL)
2N/A reason = description;
2N/A
2N/A if ((buf = asr_buf_alloc(4096)) == NULL) {
2N/A err = asr_set_errno(EASR_NOMEM);
2N/A goto finally;
2N/A }
2N/A
2N/A err = asr_msg_start(ah, buf);
2N/A err |= asr_buf_append_xml_elem(buf, pad, msg_name);
2N/A pad++;
2N/A err |= asr_buf_append_xml_elem(buf, pad, event_name);
2N/A pad++;
2N/A err |= asr_buf_append_xml_nvtoken(buf, pad, "message-id", msgid);
2N/A err |= asr_buf_append_xml_nvtoken(buf, pad, "event-uuid", uuid);
2N/A err |= asr_buf_append_xml_anv(buf, pad,
2N/A "timezone", "UTC", "event-time", timebuf);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "severity", severity);
2N/A
2N/A if (nvlist_lookup_nvlist_array(
2N/A fault, FM_SUSPECT_FAULT_LIST, &faults, &nfaults) != 0)
2N/A nfaults = 0;
2N/A
2N/A if (use_schema_2_1) {
2N/A char count[32];
2N/A char *eventType = NULL;
2N/A uint32_t case_state = 0;
2N/A
2N/A if (nvlist_lookup_uint32(
2N/A fault, FM_SUSPECT_CASE_STATE, &case_state) == 0) {
2N/A switch (case_state) {
2N/A case FMD_SUSPECT_CASE_SOLVED:
2N/A eventType = "SOLVED";
2N/A break;
2N/A case FMD_SUSPECT_CASE_CLOSE_WAIT:
2N/A eventType = "CLOSE_WAIT";
2N/A break;
2N/A case FMD_SUSPECT_CASE_ISOLATED:
2N/A eventType = "ISOLATED";
2N/A break;
2N/A case FMD_SUSPECT_CASE_REPAIRED:
2N/A eventType = "REPAIRED";
2N/A break;
2N/A case FMD_SUSPECT_CASE_RESOLVED:
2N/A eventType = "RESOLVED";
2N/A break;
2N/A }
2N/A }
2N/A err |= asr_buf_append_xml_nv(buf, pad, "event-type", eventType);
2N/A
2N/A (void) snprintf(count, sizeof (count), "%d",
2N/A nfaults == 0 ? 1 : nfaults);
2N/A err |= asr_buf_append_xml_nv(
2N/A buf, pad, "component-count", count);
2N/A }
2N/A
2N/A /* Add info about faulted components. */
2N/A err |= asr_buf_append_xml_elem(buf, pad, "component");
2N/A rollback = buf->asrb_length;
2N/A if (asr_fault_components(ah, buf, faults, nfaults, fault)) {
2N/A if (asr_get_errno() != EASR_SC && asr_get_errno() != EASR_FM) {
2N/A err = ASR_FAILURE;
2N/A goto finally;
2N/A }
2N/A buf->asrb_length = rollback;
2N/A err |= asr_buf_terminate(buf);
2N/A pad++;
2N/A err |= asr_buf_append_xml_nv(buf, pad+1, "uncategorized", "");
2N/A pad--;
2N/A }
2N/A err |= asr_buf_append_xml_end(buf, pad, "component");
2N/A
2N/A err |= asr_buf_append_xml_nnv(buf, pad, "summary", reason, 80);
2N/A
2N/A if (use_schema_2_1) {
2N/A nvlist_t *de;
2N/A err |= asr_buf_append_xml_nv(
2N/A buf, pad, "description", description);
2N/A
2N/A if (nvlist_lookup_nvlist(
2N/A fault, FM_SUSPECT_DE, &de) == 0) {
2N/A err |= asr_buf_append_xml_nv(
2N/A buf, pad, "diagnostic-engine-name",
2N/A asr_nvl_strd(de, "mod-name", "fmd"));
2N/A err |= asr_buf_append_xml_nv(
2N/A buf, pad, "diagnostic-engine-version",
2N/A asr_nvl_strd(de, "mod-version", NULL));
2N/A }
2N/A } else {
2N/A err |= asr_buf_append_xml_nnv(
2N/A buf, pad, "description", description, 80);
2N/A }
2N/A
2N/A err |= asr_buf_append_xml_ai(buf, pad,
2N/A "telemetry_source", ASR_TELEMETRY_SOURCE);
2N/A
2N/A if (nvlist_lookup_boolean_value(fault, FM_SUSPECT_INJECTED,
2N/A &injected) == 0)
2N/A err |= asr_buf_append_xml_ai(buf, pad, ASR_FLT_INJECTED,
2N/A injected ? "true" : "false");
2N/A err |= asr_buf_append_pad(buf, pad);
2N/A err |= asr_buf_append_str(buf, "<payload><![CDATA[");
2N/A asr_nvl_tostringi(buf, fault, 1, '\'', " => ");
2N/A err |= asr_buf_append_str(buf, "]]>\n");
2N/A err |= asr_buf_append_xml_end(buf, pad, "payload");
2N/A err |= asr_buf_append_xml_nv(buf, pad, "parent-event-uuid", parent);
2N/A pad--;
2N/A err |= asr_buf_append_xml_end(buf, pad, event_name);
2N/A pad--;
2N/A err |= asr_buf_append_xml_end(buf, pad, msg_name);
2N/A err |= asr_msg_end(buf);
2N/A
2N/Afinally:
2N/A if (err == 0) {
2N/A if ((msg = asr_message_alloc(buf, ASR_MSG_FAULT)) == NULL)
2N/A err = EASR_NOMEM;
2N/A } else {
2N/A asr_buf_free(buf);
2N/A }
2N/A
2N/A asr_nvl_free(items);
2N/A *out_msg = msg;
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Creates an ASR event message from an FMA fault event.
2N/A */
2N/Aint
2N/Aasr_fault(asr_handle_t *ah, nvlist_t *fault, asr_message_t **msg)
2N/A{
2N/A return (do_asr_fault_msg(
2N/A ah, fault, NULL, "event", "primary-event-information", msg));
2N/A}
2N/A
2N/A/*
2N/A * Creates an ASR event message that updates an FMA fault event.
2N/A * This type of message is used to identify that there are updates to an
2N/A * already existing event.
2N/A * Event UUIDs are used to identify the parent events.
2N/A */
2N/Aint
2N/Aasr_fault_update(asr_handle_t *ah, nvlist_t *fault, char *parent,
2N/A asr_message_t **msg)
2N/A{
2N/A return (do_asr_fault_msg(
2N/A ah, fault, parent, "event-update", "child-event-information", msg));
2N/A}