Print this page
NEX-17829 libfmd_snmp and snmp-notify should provide FMRIs for all fault types
Reviewed by: Cynthia Eastham <cynthia.eastham@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-16536 SUN-IREPORT-MIB is broken
NEX-16537 enhance FM traps
NEX-16545 SMF dict should have obsolete entries removed
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Cynthia Eastham <cynthia.eastham@nexenta.com>
Reviewed by: Alexander Eremin <alexander.eremin@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>

@@ -20,10 +20,17 @@
  */
 
 /*
  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
+
+/*
+ * Copyright 2018 Nexenta Systems, Inc.
+ */
+
+#include <fm/libtopo.h>
+
 #include <alloca.h>
 
 #include "libfmnotify.h"
 
 /*ARGSUSED*/

@@ -256,24 +263,59 @@
 }
 
 char *
 nd_get_event_fmri(nd_hdl_t *nhdl, fmev_t ev)
 {
-        nvlist_t *ev_nvl, *attr_nvl;
+        nvlist_t *ev_nvl, *snvl;
+        nvlist_t **fnvl;
+        uint_t nnvl;
         char *svcname;
 
         if ((ev_nvl = fmev_attr_list(ev)) == NULL) {
-                nd_error(nhdl, "Failed to lookup event attr nvlist");
+                nd_error(nhdl, "failed to lookup event nvlist");
                 return (NULL);
         }
-        if (nvlist_lookup_nvlist(ev_nvl, "attr", &attr_nvl) ||
-            nvlist_lookup_string(attr_nvl, "svc-string", &svcname)) {
-                nd_error(nhdl, "Malformed event 0x%p", (void *)ev_nvl);
+
+        /* If this is an ireport, simply lookup svc-string */
+        if (nvlist_lookup_nvlist(ev_nvl, "attr", &snvl) == 0 &&
+            nvlist_lookup_string(snvl, "svc-string", &svcname) == 0)
+                return (strdup((const char *)svcname));
+
+        /* Otherwise extract the fault-list and use the first element */
+        if (nvlist_lookup_nvlist_array(ev_nvl, FM_SUSPECT_FAULT_LIST,
+            &fnvl, &nnvl) != 0 || nnvl != 1)
                 return (NULL);
+
+        /*
+         * NOTE: this should match the logic in libfmd_snmp.
+         *
+         * Use the following order of nested nvlists to make up FMRI:
+         * - FRU
+         * - ASRU
+         * - resource
+         */
+        if (nvlist_lookup_nvlist(fnvl[0], FM_FAULT_FRU, &snvl) == 0 ||
+            nvlist_lookup_nvlist(fnvl[0], FM_FAULT_ASRU, &snvl) == 0 ||
+            nvlist_lookup_nvlist(fnvl[0], FM_FAULT_RESOURCE, &snvl) == 0) {
+                topo_hdl_t *thp;
+                int topoerr;
+                char *fmri, *ret = NULL;
+
+                thp = topo_open(TOPO_VERSION, NULL, &topoerr);
+                if (thp == NULL)
+                        return (NULL);
+
+                if (topo_fmri_nvl2str(thp, snvl, &fmri, &topoerr) == 0) {
+                        ret = strdup(fmri);
+                        topo_hdl_strfree(thp, fmri);
         }
 
-        return (strdup((const char *)svcname));
+                topo_close(thp);
+                return (ret);
+        }
+
+        return (NULL);
 }
 
 int
 nd_get_notify_prefs(nd_hdl_t *nhdl, const char *mech, fmev_t ev,
     nvlist_t ***pref_nvl, uint_t *nprefs)

@@ -509,13 +551,13 @@
  */
 int
 nd_get_event_info(nd_hdl_t *nhdl, const char *class, fmev_t ev,
     nd_ev_info_t **ev_info)
 {
-        nvlist_t *ev_nvl, *attr_nvl;
+        nvlist_t *attr_nvl;
         nd_ev_info_t *evi;
-        char *code, *uuid, *fmri, *from_state, *to_state, *reason;
+        char *code, *uuid, *from_state, *to_state, *reason;
 
         if ((evi = calloc(1, sizeof (nd_ev_info_t))) == NULL) {
                 nd_error(nhdl, "Failed to allocate memory");
                 return (-1);
         }

@@ -523,69 +565,73 @@
         /*
          * Hold event; class and payload will be valid for as long as
          * we hold the event.
          */
         fmev_hold(ev);
+
         evi->ei_ev = ev;
-        ev_nvl = fmev_attr_list(ev);
+        evi->ei_class = fmev_class(ev);
+        evi->ei_payload = fmev_attr_list(ev);
 
+        if (nvlist_lookup_string(evi->ei_payload, FM_SUSPECT_UUID,
+            &uuid) == 0) {
+                evi->ei_uuid = strdup(uuid);
+        } else {
+                nd_error(nhdl, "Malformed event");
+                nd_dump_nvlist(nhdl, evi->ei_payload);
+                nd_free_event_info(evi);
+                return (-1);
+        }
+
         /*
-         * Lookup the MSGID, event description and severity and KA URL
+         * Lookup the MSGID, type, severity, description, and KA URL.
          *
          * For FMA list.* events we just pull it out of the the event nvlist.
          * For all other events we call a utility function that computes the
          * diagcode using the dict name and class.
          */
         evi->ei_diagcode = calloc(32, sizeof (char));
-        if ((nvlist_lookup_string(ev_nvl, FM_SUSPECT_DIAG_CODE, &code) == 0 &&
-            strcpy(evi->ei_diagcode, code)) ||
-            nd_get_diagcode(nhdl, "SMF", class, evi->ei_diagcode, 32)
-            == 0) {
+        if ((nvlist_lookup_string(evi->ei_payload, FM_SUSPECT_DIAG_CODE,
+            &code) == 0 && strcpy(evi->ei_diagcode, code) != NULL) ||
+            nd_get_diagcode(nhdl, "SMF", class, evi->ei_diagcode, 32) == 0) {
+                evi->ei_type = fmd_msg_getitem_id(nhdl->nh_msghdl,
+                    NULL, evi->ei_diagcode, FMD_MSG_ITEM_TYPE);
                 evi->ei_severity = fmd_msg_getitem_id(nhdl->nh_msghdl,
                     NULL, evi->ei_diagcode, FMD_MSG_ITEM_SEVERITY);
                 evi->ei_descr = fmd_msg_getitem_id(nhdl->nh_msghdl,
                     NULL, evi->ei_diagcode, FMD_MSG_ITEM_DESC);
                 evi->ei_url = fmd_msg_getitem_id(nhdl->nh_msghdl,
                     NULL, evi->ei_diagcode, FMD_MSG_ITEM_URL);
         } else
                 (void) strcpy(evi->ei_diagcode, ND_UNKNOWN);
 
-        if (!evi->ei_severity)
+        if (evi->ei_type == NULL)
+                evi->ei_type = strdup(ND_UNKNOWN);
+        if (evi->ei_severity == NULL)
                 evi->ei_severity = strdup(ND_UNKNOWN);
-        if (!evi->ei_descr)
+        if (evi->ei_descr == NULL)
                 evi->ei_descr = strdup(ND_UNKNOWN);
-        if (!evi->ei_url)
+        if (evi->ei_url == NULL)
                 evi->ei_url = strdup(ND_UNKNOWN);
 
-        evi->ei_payload = ev_nvl;
-        evi->ei_class = fmev_class(ev);
-        if (nvlist_lookup_string(ev_nvl, FM_SUSPECT_UUID, &uuid) == 0)
-                evi->ei_uuid = strdup(uuid);
-        else {
-                nd_error(nhdl, "Malformed event");
-                nd_dump_nvlist(nhdl, evi->ei_payload);
-                nd_free_event_info(evi);
-                return (-1);
-        }
+        if ((evi->ei_fmri = nd_get_event_fmri(nhdl, ev)) == NULL)
+                evi->ei_fmri = strdup(ND_UNKNOWN);
 
         if (strncmp(class, "ireport.os.smf", 14) == 0) {
-                if ((fmri = nd_get_event_fmri(nhdl, ev)) == NULL) {
-                        nd_error(nhdl, "Failed to get fmri from event payload");
-                        nd_free_event_info(evi);
-                        return (-1);
-                }
-                if (nvlist_lookup_nvlist(evi->ei_payload, "attr", &attr_nvl) ||
-                    nvlist_lookup_string(attr_nvl, "from-state", &from_state) ||
-                    nvlist_lookup_string(attr_nvl, "to-state", &to_state) ||
-                    nvlist_lookup_string(attr_nvl, "reason-long", &reason)) {
+                if (nvlist_lookup_nvlist(evi->ei_payload, "attr",
+                    &attr_nvl) != 0 ||
+                    nvlist_lookup_string(attr_nvl, "from-state",
+                    &from_state) != 0 ||
+                    nvlist_lookup_string(attr_nvl, "to-state",
+                    &to_state) != 0 ||
+                    nvlist_lookup_string(attr_nvl, "reason-long",
+                    &reason) != 0) {
                         nd_error(nhdl, "Malformed event");
                         nd_dump_nvlist(nhdl, evi->ei_payload);
                         nd_free_event_info(evi);
-                        free(fmri);
                         return (-1);
                 }
-                evi->ei_fmri = fmri;
                 evi->ei_to_state = strdup(to_state);
                 evi->ei_from_state = strdup(from_state);
                 evi->ei_reason = strdup(reason);
         }
         *ev_info = evi;