xref: /illumos-gate/usr/src/cmd/fm/fmdump/common/fault.c (revision b1f62671)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
59dd0f810Scindi  * Common Development and Distribution License (the "License").
69dd0f810Scindi  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22f6e214c7SGavin Maltby  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
23*b1f62671SJohn Levon  * Copyright (c) 2018, Joyent, Inc.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <fmdump.h>
277c478bd9Sstevel@tonic-gate #include <stdio.h>
289dd0f810Scindi #include <strings.h>
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*ARGSUSED*/
317c478bd9Sstevel@tonic-gate static int
flt_short(fmd_log_t * lp,const fmd_log_record_t * rp,FILE * fp)327c478bd9Sstevel@tonic-gate flt_short(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp)
337c478bd9Sstevel@tonic-gate {
34627351e3Scy 	char buf[32], str[32];
35627351e3Scy 	char *class = NULL, *uuid = "-", *code = "-";
367c478bd9Sstevel@tonic-gate 
37f6e214c7SGavin Maltby 	static const struct {
38f6e214c7SGavin Maltby 		const char *class;
39f6e214c7SGavin Maltby 		const char *tag;
40f6e214c7SGavin Maltby 	} tags[] = {
41f6e214c7SGavin Maltby 		{ FM_LIST_SUSPECT_CLASS,	"Diagnosed" },
42f6e214c7SGavin Maltby 		{ FM_LIST_REPAIRED_CLASS,	"Repaired" },
43f6e214c7SGavin Maltby 		{ FM_LIST_RESOLVED_CLASS,	"Resolved" },
44f6e214c7SGavin Maltby 		{ FM_LIST_UPDATED_CLASS,	"Updated" },
45f6e214c7SGavin Maltby 		{ FM_LIST_ISOLATED_CLASS,	"Isolated" },
46f6e214c7SGavin Maltby 	};
47f6e214c7SGavin Maltby 
487c478bd9Sstevel@tonic-gate 	(void) nvlist_lookup_string(rp->rec_nvl, FM_SUSPECT_UUID, &uuid);
497c478bd9Sstevel@tonic-gate 	(void) nvlist_lookup_string(rp->rec_nvl, FM_SUSPECT_DIAG_CODE, &code);
507c478bd9Sstevel@tonic-gate 
51627351e3Scy 	(void) nvlist_lookup_string(rp->rec_nvl, FM_CLASS, &class);
52f6e214c7SGavin Maltby 	if (class != NULL) {
53f6e214c7SGavin Maltby 		int i;
54f6e214c7SGavin Maltby 
55f6e214c7SGavin Maltby 		for (i = 0; i < sizeof (tags) / sizeof (tags[0]); i++) {
56f6e214c7SGavin Maltby 			if (strcmp(class, tags[i].class) == 0) {
57f6e214c7SGavin Maltby 				(void) snprintf(str, sizeof (str), "%s %s",
58f6e214c7SGavin Maltby 				    code, tags[i].tag);
59f6e214c7SGavin Maltby 				code = str;
60f6e214c7SGavin Maltby 				break;
61f6e214c7SGavin Maltby 			}
62f6e214c7SGavin Maltby 		}
6325c6ff4bSstephh 	}
64627351e3Scy 
6547911a7dScy 	fmdump_printf(fp, "%-20s %-32s %s\n",
6647911a7dScy 	    fmdump_date(buf, sizeof (buf), rp), uuid, code);
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	return (0);
697c478bd9Sstevel@tonic-gate }
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate static int
flt_verb1(fmd_log_t * lp,const fmd_log_record_t * rp,FILE * fp)727c478bd9Sstevel@tonic-gate flt_verb1(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp)
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate 	uint_t i, size = 0;
757c478bd9Sstevel@tonic-gate 	nvlist_t **nva;
7625c6ff4bSstephh 	uint8_t *ba;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 	(void) flt_short(lp, rp, fp);
797c478bd9Sstevel@tonic-gate 	(void) nvlist_lookup_uint32(rp->rec_nvl, FM_SUSPECT_FAULT_SZ, &size);
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	if (size != 0) {
827c478bd9Sstevel@tonic-gate 		(void) nvlist_lookup_nvlist_array(rp->rec_nvl,
837c478bd9Sstevel@tonic-gate 		    FM_SUSPECT_FAULT_LIST, &nva, &size);
8425c6ff4bSstephh 		(void) nvlist_lookup_uint8_array(rp->rec_nvl,
8525c6ff4bSstephh 		    FM_SUSPECT_FAULT_STATUS, &ba, &size);
867c478bd9Sstevel@tonic-gate 	}
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 	for (i = 0; i < size; i++) {
897aec1d6eScindi 		char *class = NULL, *rname = NULL, *aname = NULL, *fname = NULL;
909dd0f810Scindi 		char *loc = NULL;
917aec1d6eScindi 		nvlist_t *fru, *asru, *rsrc;
927c478bd9Sstevel@tonic-gate 		uint8_t pct = 0;
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 		(void) nvlist_lookup_uint8(nva[i], FM_FAULT_CERTAINTY, &pct);
957c478bd9Sstevel@tonic-gate 		(void) nvlist_lookup_string(nva[i], FM_CLASS, &class);
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 		if (nvlist_lookup_nvlist(nva[i], FM_FAULT_FRU, &fru) == 0)
987c478bd9Sstevel@tonic-gate 			fname = fmdump_nvl2str(fru);
997c478bd9Sstevel@tonic-gate 
1007aec1d6eScindi 		if (nvlist_lookup_nvlist(nva[i], FM_FAULT_ASRU, &asru) == 0)
1017aec1d6eScindi 			aname = fmdump_nvl2str(asru);
1027aec1d6eScindi 
1037aec1d6eScindi 		if (nvlist_lookup_nvlist(nva[i], FM_FAULT_RESOURCE, &rsrc) == 0)
1047aec1d6eScindi 			rname = fmdump_nvl2str(rsrc);
1057aec1d6eScindi 
1069dd0f810Scindi 		if (nvlist_lookup_string(nva[i], FM_FAULT_LOCATION, &loc)
1079dd0f810Scindi 		    == 0) {
108ef884685Srb 			if (fname && strncmp(fname, FM_FMRI_LEGACY_HC_PREFIX,
1099dd0f810Scindi 			    sizeof (FM_FMRI_LEGACY_HC_PREFIX)) == 0)
1109dd0f810Scindi 				loc = fname + sizeof (FM_FMRI_LEGACY_HC_PREFIX);
1119dd0f810Scindi 		}
1129dd0f810Scindi 
1139dd0f810Scindi 
11425c6ff4bSstephh 		fmdump_printf(fp, "  %3u%%  %s",
1157aec1d6eScindi 		    pct, class ? class : "-");
1167aec1d6eScindi 
11725c6ff4bSstephh 		if (ba[i] & FM_SUSPECT_FAULTY)
11825c6ff4bSstephh 			fmdump_printf(fp, "\n\n");
11925c6ff4bSstephh 		else if (ba[i] & FM_SUSPECT_NOT_PRESENT)
12025c6ff4bSstephh 			fmdump_printf(fp, "\tRemoved\n\n");
12125c6ff4bSstephh 		else if (ba[i] & FM_SUSPECT_REPLACED)
12225c6ff4bSstephh 			fmdump_printf(fp, "\tReplaced\n\n");
12325c6ff4bSstephh 		else if (ba[i] & FM_SUSPECT_REPAIRED)
12425c6ff4bSstephh 			fmdump_printf(fp, "\tRepair Attempted\n\n");
12525c6ff4bSstephh 		else if (ba[i] & FM_SUSPECT_ACQUITTED)
12625c6ff4bSstephh 			fmdump_printf(fp, "\tAcquitted\n\n");
12725c6ff4bSstephh 		else
12825c6ff4bSstephh 			fmdump_printf(fp, "\n\n");
12925c6ff4bSstephh 
1307aec1d6eScindi 		fmdump_printf(fp, "        Problem in: %s\n",
13125c6ff4bSstephh 		    rname ? rname : "-");
1327aec1d6eScindi 
1337aec1d6eScindi 		fmdump_printf(fp, "           Affects: %s\n",
1347aec1d6eScindi 		    aname ? aname : "-");
1357c478bd9Sstevel@tonic-gate 
1369dd0f810Scindi 		fmdump_printf(fp, "               FRU: %s\n",
1377aec1d6eScindi 		    fname ? fname : "-");
1387c478bd9Sstevel@tonic-gate 
1399dd0f810Scindi 		fmdump_printf(fp, "          Location: %s\n\n",
1409dd0f810Scindi 		    loc ? loc : "-");
1419dd0f810Scindi 
1427c478bd9Sstevel@tonic-gate 		free(fname);
1437aec1d6eScindi 		free(aname);
1447c478bd9Sstevel@tonic-gate 		free(rname);
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	return (0);
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate static int
flt_verb23_cmn(fmd_log_t * lp,const fmd_log_record_t * rp,FILE * fp,nvlist_prtctl_t pctl)151f6e214c7SGavin Maltby flt_verb23_cmn(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp,
152f6e214c7SGavin Maltby     nvlist_prtctl_t pctl)
1537c478bd9Sstevel@tonic-gate {
1547c478bd9Sstevel@tonic-gate 	const struct fmdump_fmt *efp = &fmdump_err_ops.do_formats[FMDUMP_VERB1];
155540db9a9SStephen Hanson 	const struct fmdump_fmt *ffp = &fmdump_flt_ops.do_formats[FMDUMP_VERB2];
1567c478bd9Sstevel@tonic-gate 	uint_t i;
157540db9a9SStephen Hanson 	char buf[32], str[32];
158540db9a9SStephen Hanson 	char *class = NULL, *uuid = "-", *code = "-";
159540db9a9SStephen Hanson 
160540db9a9SStephen Hanson 	(void) nvlist_lookup_string(rp->rec_nvl, FM_SUSPECT_UUID, &uuid);
161540db9a9SStephen Hanson 	(void) nvlist_lookup_string(rp->rec_nvl, FM_SUSPECT_DIAG_CODE, &code);
162540db9a9SStephen Hanson 
163540db9a9SStephen Hanson 	(void) nvlist_lookup_string(rp->rec_nvl, FM_CLASS, &class);
164540db9a9SStephen Hanson 	if (class != NULL && strcmp(class, FM_LIST_REPAIRED_CLASS) == 0) {
165540db9a9SStephen Hanson 		(void) snprintf(str, sizeof (str), "%s %s", code, "Repaired");
166540db9a9SStephen Hanson 		code = str;
167540db9a9SStephen Hanson 	}
168540db9a9SStephen Hanson 	if (class != NULL && strcmp(class, FM_LIST_RESOLVED_CLASS) == 0) {
169540db9a9SStephen Hanson 		(void) snprintf(str, sizeof (str), "%s %s", code, "Resolved");
170540db9a9SStephen Hanson 		code = str;
171540db9a9SStephen Hanson 	}
172540db9a9SStephen Hanson 	if (class != NULL && strcmp(class, FM_LIST_UPDATED_CLASS) == 0) {
173540db9a9SStephen Hanson 		(void) snprintf(str, sizeof (str), "%s %s", code, "Updated");
174540db9a9SStephen Hanson 		code = str;
175540db9a9SStephen Hanson 	}
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	fmdump_printf(fp, "%s\n", ffp->do_hdr);
178540db9a9SStephen Hanson 	fmdump_printf(fp, "%-20s.%9.9llu %-32s %s\n",
179540db9a9SStephen Hanson 	    fmdump_year(buf, sizeof (buf), rp), rp->rec_nsec, uuid, code);
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	if (rp->rec_nrefs != 0)
1827c478bd9Sstevel@tonic-gate 		fmdump_printf(fp, "\n  %s\n", efp->do_hdr);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	for (i = 0; i < rp->rec_nrefs; i++) {
1857c478bd9Sstevel@tonic-gate 		fmdump_printf(fp, "  ");
186*b1f62671SJohn Levon 		(void) efp->do_func(lp, &rp->rec_xrefs[i], fp);
1877c478bd9Sstevel@tonic-gate 	}
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	fmdump_printf(fp, "\n");
190f6e214c7SGavin Maltby 	if (pctl)
191f6e214c7SGavin Maltby 		nvlist_prt(rp->rec_nvl, pctl);
192f6e214c7SGavin Maltby 	else
193f6e214c7SGavin Maltby 		nvlist_print(fp, rp->rec_nvl);
1947c478bd9Sstevel@tonic-gate 	fmdump_printf(fp, "\n");
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	return (0);
1977c478bd9Sstevel@tonic-gate }
1987c478bd9Sstevel@tonic-gate 
199f6e214c7SGavin Maltby static int
flt_verb2(fmd_log_t * lp,const fmd_log_record_t * rp,FILE * fp)200f6e214c7SGavin Maltby flt_verb2(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp)
201f6e214c7SGavin Maltby {
202f6e214c7SGavin Maltby 	return (flt_verb23_cmn(lp, rp, fp, NULL));
203f6e214c7SGavin Maltby }
204f6e214c7SGavin Maltby 
205f6e214c7SGavin Maltby 
206f6e214c7SGavin Maltby static int
flt_pretty(fmd_log_t * lp,const fmd_log_record_t * rp,FILE * fp)207f6e214c7SGavin Maltby flt_pretty(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp)
208f6e214c7SGavin Maltby {
209f6e214c7SGavin Maltby 	nvlist_prtctl_t pctl;
210f6e214c7SGavin Maltby 	int rc;
211f6e214c7SGavin Maltby 
212f6e214c7SGavin Maltby 	if ((pctl = nvlist_prtctl_alloc()) != NULL) {
213f6e214c7SGavin Maltby 		nvlist_prtctl_setdest(pctl, fp);
214f6e214c7SGavin Maltby 		nvlist_prtctlop_nvlist(pctl, fmdump_render_nvlist, NULL);
215f6e214c7SGavin Maltby 	}
216f6e214c7SGavin Maltby 
217f6e214c7SGavin Maltby 	rc = flt_verb23_cmn(lp, rp, fp, pctl);
218f6e214c7SGavin Maltby 
219f6e214c7SGavin Maltby 	nvlist_prtctl_free(pctl);
220f6e214c7SGavin Maltby 	return (rc);
221f6e214c7SGavin Maltby }
222f6e214c7SGavin Maltby 
223b6955755SRobert Johnston /*
224b6955755SRobert Johnston  * There is a lack of uniformity in how the various entries in our diagnosis
225b6955755SRobert Johnston  * are terminated.  Some end with one newline, others with two.  This makes the
226b6955755SRobert Johnston  * output of fmdump -m look a bit ugly.  Therefore we postprocess the message
227b6955755SRobert Johnston  * before printing it, removing consecutive occurences of newlines.
228b6955755SRobert Johnston  */
229b6955755SRobert Johnston static void
postprocess_msg(char * msg)230b6955755SRobert Johnston postprocess_msg(char *msg)
231b6955755SRobert Johnston {
232b6955755SRobert Johnston 	int i = 0, j = 0;
233b6955755SRobert Johnston 	char *buf;
234b6955755SRobert Johnston 
235b6955755SRobert Johnston 	if ((buf = malloc(strlen(msg) + 1)) == NULL)
236b6955755SRobert Johnston 		return;
237b6955755SRobert Johnston 
238b6955755SRobert Johnston 	buf[j++] = msg[i++];
239b6955755SRobert Johnston 	for (i = 1; i < strlen(msg); i++) {
240b6955755SRobert Johnston 		if (!(msg[i] == '\n' && msg[i - 1] == '\n'))
241b6955755SRobert Johnston 			buf[j++] = msg[i];
242b6955755SRobert Johnston 	}
243b6955755SRobert Johnston 	buf[j] = '\0';
244b6955755SRobert Johnston 	(void) strncpy(msg, buf, j+1);
245b6955755SRobert Johnston 	free(buf);
246b6955755SRobert Johnston }
247b6955755SRobert Johnston 
248b6955755SRobert Johnston /*ARGSUSED*/
249b6955755SRobert Johnston static int
flt_msg(fmd_log_t * lp,const fmd_log_record_t * rp,FILE * fp)250b6955755SRobert Johnston flt_msg(fmd_log_t *lp, const fmd_log_record_t *rp, FILE *fp)
251b6955755SRobert Johnston {
2528c331166SRob Johnston 	char *msg, *uuid = "-", *code = "-";
253b6955755SRobert Johnston 
254b6955755SRobert Johnston 	if ((msg = fmd_msg_gettext_nv(g_msg, NULL, rp->rec_nvl)) == NULL) {
2558c331166SRob Johnston 		(void) nvlist_lookup_string(rp->rec_nvl, FM_SUSPECT_UUID,
2568c331166SRob Johnston 		    &uuid);
2578c331166SRob Johnston 		(void) nvlist_lookup_string(rp->rec_nvl, FM_SUSPECT_DIAG_CODE,
2588c331166SRob Johnston 		    &code);
2598c331166SRob Johnston 		(void) fprintf(stderr, "%s: failed to format message for "
2608c331166SRob Johnston 		    "diagcode %s, event %s: %s\n\n", g_pname, code, uuid,
2618c331166SRob Johnston 		    strerror(errno));
262b6955755SRobert Johnston 		g_errs++;
263b6955755SRobert Johnston 	} else {
264b6955755SRobert Johnston 		postprocess_msg(msg);
265b6955755SRobert Johnston 		fmdump_printf(fp, "%s\n", msg);
266b6955755SRobert Johnston 		free(msg);
267b6955755SRobert Johnston 	}
268b6955755SRobert Johnston 
269b6955755SRobert Johnston 	return (0);
270b6955755SRobert Johnston }
271b6955755SRobert Johnston 
2727c478bd9Sstevel@tonic-gate const fmdump_ops_t fmdump_flt_ops = {
2737c478bd9Sstevel@tonic-gate "fault", {
2747c478bd9Sstevel@tonic-gate {
275f6e214c7SGavin Maltby "TIME                 UUID                                 SUNW-MSG-ID "
276f6e214c7SGavin Maltby 								"EVENT",
2777c478bd9Sstevel@tonic-gate (fmd_log_rec_f *)flt_short
2787c478bd9Sstevel@tonic-gate }, {
279f6e214c7SGavin Maltby "TIME                 UUID                                 SUNW-MSG-ID "
280f6e214c7SGavin Maltby 								"EVENT",
2817c478bd9Sstevel@tonic-gate (fmd_log_rec_f *)flt_verb1
2827c478bd9Sstevel@tonic-gate }, {
283540db9a9SStephen Hanson "TIME                           UUID"
284540db9a9SStephen Hanson "                                 SUNW-MSG-ID",
2857c478bd9Sstevel@tonic-gate (fmd_log_rec_f *)flt_verb2
286b6955755SRobert Johnston }, {
287f6e214c7SGavin Maltby "TIME                           UUID"
288f6e214c7SGavin Maltby "                                 SUNW-MSG-ID",
289f6e214c7SGavin Maltby (fmd_log_rec_f *)flt_pretty
290f6e214c7SGavin Maltby }, {
291b6955755SRobert Johnston NULL,
292b6955755SRobert Johnston (fmd_log_rec_f *)flt_msg
2932db6d663SJoshua M. Clulow }, {
2942db6d663SJoshua M. Clulow NULL,
2952db6d663SJoshua M. Clulow (fmd_log_rec_f *)fmdump_print_json
2967c478bd9Sstevel@tonic-gate } }
2977c478bd9Sstevel@tonic-gate };
298