xref: /onnv-gate/usr/src/cmd/fm/fmd/common/fmd_protocol.c (revision 10928:eb060666c73f)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53323Scindi  * Common Development and Distribution License (the "License").
63323Scindi  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
211193Smws 
220Sstevel@tonic-gate /*
239120SStephen.Hanson@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #include <sys/fm/protocol.h>
2810234SRobert.Johnston@Sun.COM #include <fm/fmd_msg.h>
290Sstevel@tonic-gate #include <strings.h>
300Sstevel@tonic-gate #include <alloca.h>
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <fmd_protocol.h>
340Sstevel@tonic-gate #include <fmd_module.h>
350Sstevel@tonic-gate #include <fmd_conf.h>
360Sstevel@tonic-gate #include <fmd_subr.h>
370Sstevel@tonic-gate #include <fmd_error.h>
380Sstevel@tonic-gate #include <fmd_time.h>
390Sstevel@tonic-gate #include <fmd.h>
400Sstevel@tonic-gate 
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate  * Create an FMRI authority element for the environment in which this instance
430Sstevel@tonic-gate  * of fmd is deployed.  This function is called once and the result is cached.
440Sstevel@tonic-gate  */
450Sstevel@tonic-gate nvlist_t *
fmd_protocol_authority(void)460Sstevel@tonic-gate fmd_protocol_authority(void)
470Sstevel@tonic-gate {
480Sstevel@tonic-gate 	const char *str;
490Sstevel@tonic-gate 	nvlist_t *nvl;
500Sstevel@tonic-gate 	int err = 0;
510Sstevel@tonic-gate 
520Sstevel@tonic-gate 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
530Sstevel@tonic-gate 		fmd_panic("failed to xalloc authority nvlist");
540Sstevel@tonic-gate 
550Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_FMRI_AUTH_VERSION);
561414Scindi 
571414Scindi 	if ((str = fmd_conf_getnzstr(fmd.d_conf, "product")) == NULL)
581414Scindi 		str = fmd_conf_getnzstr(fmd.d_conf, "platform");
590Sstevel@tonic-gate 
601414Scindi 	if (str != NULL)
611414Scindi 		err |= nvlist_add_string(nvl, FM_FMRI_AUTH_PRODUCT, str);
621414Scindi 
6310462SSean.Ye@Sun.COM 	if ((str = fmd_conf_getnzstr(fmd.d_conf, "product_sn")) != NULL)
6410462SSean.Ye@Sun.COM 		err |= nvlist_add_string(nvl, FM_FMRI_AUTH_PRODUCT_SN, str);
6510462SSean.Ye@Sun.COM 
661414Scindi 	if ((str = fmd_conf_getnzstr(fmd.d_conf, "chassis")) != NULL)
670Sstevel@tonic-gate 		err |= nvlist_add_string(nvl, FM_FMRI_AUTH_CHASSIS, str);
680Sstevel@tonic-gate 
691414Scindi 	if ((str = fmd_conf_getnzstr(fmd.d_conf, "domain")) != NULL)
700Sstevel@tonic-gate 		err |= nvlist_add_string(nvl, FM_FMRI_AUTH_DOMAIN, str);
710Sstevel@tonic-gate 
721414Scindi 	if ((str = fmd_conf_getnzstr(fmd.d_conf, "server")) != NULL)
730Sstevel@tonic-gate 		err |= nvlist_add_string(nvl, FM_FMRI_AUTH_SERVER, str);
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	if (err != 0)
760Sstevel@tonic-gate 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	return (nvl);
790Sstevel@tonic-gate }
800Sstevel@tonic-gate 
810Sstevel@tonic-gate /*
820Sstevel@tonic-gate  * Create an FMRI for the specified module.  We use the cached authority
830Sstevel@tonic-gate  * nvlist saved in fmd.d_auth to fill in the authority member.
840Sstevel@tonic-gate  */
850Sstevel@tonic-gate nvlist_t *
fmd_protocol_fmri_module(fmd_module_t * mp)860Sstevel@tonic-gate fmd_protocol_fmri_module(fmd_module_t *mp)
870Sstevel@tonic-gate {
880Sstevel@tonic-gate 	nvlist_t *nvl;
890Sstevel@tonic-gate 	int err = 0;
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
920Sstevel@tonic-gate 		fmd_panic("failed to xalloc diag-engine fmri nvlist");
930Sstevel@tonic-gate 
940Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_FMD_SCHEME_VERSION);
950Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_FMRI_SCHEME, FM_FMRI_SCHEME_FMD);
960Sstevel@tonic-gate 	err |= nvlist_add_nvlist(nvl, FM_FMRI_AUTHORITY, fmd.d_auth);
970Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_FMRI_FMD_NAME, mp->mod_name);
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	if (mp->mod_info != NULL) {
1000Sstevel@tonic-gate 		err |= nvlist_add_string(nvl,
1010Sstevel@tonic-gate 		    FM_FMRI_FMD_VERSION, mp->mod_info->fmdi_vers);
1021193Smws 	} else if (mp == fmd.d_rmod) {
1031193Smws 		err |= nvlist_add_string(nvl,
1041193Smws 		    FM_FMRI_FMD_VERSION, fmd.d_version);
1050Sstevel@tonic-gate 	}
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 	if (err != 0)
1080Sstevel@tonic-gate 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	return (nvl);
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate nvlist_t *
fmd_protocol_fault(const char * class,uint8_t certainty,nvlist_t * asru,nvlist_t * fru,nvlist_t * resource,const char * location)1140Sstevel@tonic-gate fmd_protocol_fault(const char *class, uint8_t certainty,
1153323Scindi     nvlist_t *asru, nvlist_t *fru, nvlist_t *resource, const char *location)
1160Sstevel@tonic-gate {
1170Sstevel@tonic-gate 	nvlist_t *nvl;
1180Sstevel@tonic-gate 	int err = 0;
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
1210Sstevel@tonic-gate 		fmd_panic("failed to xalloc fault nvlist");
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_FAULT_VERSION);
1240Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_CLASS, class);
1250Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_FAULT_CERTAINTY, certainty);
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 	if (asru != NULL)
1280Sstevel@tonic-gate 		err |= nvlist_add_nvlist(nvl, FM_FAULT_ASRU, asru);
1290Sstevel@tonic-gate 	if (fru != NULL)
1300Sstevel@tonic-gate 		err |= nvlist_add_nvlist(nvl, FM_FAULT_FRU, fru);
1310Sstevel@tonic-gate 	if (resource != NULL)
1320Sstevel@tonic-gate 		err |= nvlist_add_nvlist(nvl, FM_FAULT_RESOURCE, resource);
1333323Scindi 	if (location != NULL)
1343323Scindi 		err |= nvlist_add_string(nvl, FM_FAULT_LOCATION, location);
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	if (err != 0)
1370Sstevel@tonic-gate 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	return (nvl);
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate nvlist_t *
fmd_protocol_list(const char * class,nvlist_t * de_fmri,const char * uuid,const char * code,uint_t argc,nvlist_t ** argv,uint8_t * flagv,int domsg,struct timeval * tvp,int injected)1431193Smws fmd_protocol_list(const char *class, nvlist_t *de_fmri, const char *uuid,
1445255Sstephh     const char *code, uint_t argc, nvlist_t **argv, uint8_t *flagv, int domsg,
145*10928SStephen.Hanson@Sun.COM     struct timeval *tvp, int injected)
1460Sstevel@tonic-gate {
1470Sstevel@tonic-gate 	int64_t tod[2];
1480Sstevel@tonic-gate 	nvlist_t *nvl;
1490Sstevel@tonic-gate 	int err = 0;
15010234SRobert.Johnston@Sun.COM 	fmd_msg_hdl_t *msghdl;
15110234SRobert.Johnston@Sun.COM 	char *severity;
1520Sstevel@tonic-gate 
1535255Sstephh 	tod[0] = tvp->tv_sec;
1545255Sstephh 	tod[1] = tvp->tv_usec;
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
1570Sstevel@tonic-gate 		fmd_panic("failed to xalloc suspect list nvlist");
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_SUSPECT_VERSION);
1601193Smws 	err |= nvlist_add_string(nvl, FM_CLASS, class);
1610Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_SUSPECT_UUID, uuid);
1620Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_SUSPECT_DIAG_CODE, code);
1630Sstevel@tonic-gate 	err |= nvlist_add_int64_array(nvl, FM_SUSPECT_DIAG_TIME, tod, 2);
1640Sstevel@tonic-gate 	err |= nvlist_add_nvlist(nvl, FM_SUSPECT_DE, de_fmri);
1650Sstevel@tonic-gate 	err |= nvlist_add_uint32(nvl, FM_SUSPECT_FAULT_SZ, argc);
1660Sstevel@tonic-gate 
167*10928SStephen.Hanson@Sun.COM 	if (injected)
168*10928SStephen.Hanson@Sun.COM 		err |= nvlist_add_boolean_value(nvl, FM_SUSPECT_INJECTED,
169*10928SStephen.Hanson@Sun.COM 		    B_TRUE);
170*10928SStephen.Hanson@Sun.COM 
1710Sstevel@tonic-gate 	if (!domsg) {
1721193Smws 		err |= nvlist_add_boolean_value(nvl,
1731193Smws 		    FM_SUSPECT_MESSAGE, B_FALSE);
1740Sstevel@tonic-gate 	}
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	if (argc != 0) {
1770Sstevel@tonic-gate 		err |= nvlist_add_nvlist_array(nvl,
1780Sstevel@tonic-gate 		    FM_SUSPECT_FAULT_LIST, argv, argc);
1791193Smws 		err |= nvlist_add_uint8_array(nvl,
1801193Smws 		    FM_SUSPECT_FAULT_STATUS, flagv, argc);
1810Sstevel@tonic-gate 	}
1820Sstevel@tonic-gate 
18310234SRobert.Johnston@Sun.COM 	/*
18410234SRobert.Johnston@Sun.COM 	 * Attempt to lookup the severity associated with this diagnosis from
18510234SRobert.Johnston@Sun.COM 	 * the portable object file using the diag code.  Failure to init
18610234SRobert.Johnston@Sun.COM 	 * libfmd_msg or add to the nvlist will be treated as fatal.  However,
18710234SRobert.Johnston@Sun.COM 	 * we won't treat a fmd_msg_getitem_id failure as fatal since during
18810234SRobert.Johnston@Sun.COM 	 * development it's not uncommon to be working with po/dict files that
18910234SRobert.Johnston@Sun.COM 	 * haven't yet been updated with newly added diagnoses.
19010234SRobert.Johnston@Sun.COM 	 */
19110234SRobert.Johnston@Sun.COM 	msghdl = fmd_msg_init(fmd.d_rootdir, FMD_MSG_VERSION);
19210234SRobert.Johnston@Sun.COM 	if (msghdl == NULL)
19310234SRobert.Johnston@Sun.COM 		fmd_panic("failed to initialize libfmd_msg\n");
19410234SRobert.Johnston@Sun.COM 
19510234SRobert.Johnston@Sun.COM 	if ((severity = fmd_msg_getitem_id(msghdl, NULL, code,
19610234SRobert.Johnston@Sun.COM 	    FMD_MSG_ITEM_SEVERITY)) != NULL) {
19710234SRobert.Johnston@Sun.COM 		err |= nvlist_add_string(nvl, FM_SUSPECT_SEVERITY, severity);
19810234SRobert.Johnston@Sun.COM 		free(severity);
19910234SRobert.Johnston@Sun.COM 	}
20010234SRobert.Johnston@Sun.COM 	fmd_msg_fini(msghdl);
20110234SRobert.Johnston@Sun.COM 
2020Sstevel@tonic-gate 	if (err != 0)
2030Sstevel@tonic-gate 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	return (nvl);
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate nvlist_t *
fmd_protocol_rsrc_asru(const char * class,nvlist_t * fmri,const char * uuid,const char * code,boolean_t faulty,boolean_t unusable,boolean_t message,nvlist_t * event,struct timeval * tvp,boolean_t repaired,boolean_t replaced,boolean_t acquitted,boolean_t resolved,nvlist_t * diag_de,boolean_t injected)2091193Smws fmd_protocol_rsrc_asru(const char *class,
2101193Smws     nvlist_t *fmri, const char *uuid, const char *code,
2115255Sstephh     boolean_t faulty, boolean_t unusable, boolean_t message, nvlist_t *event,
2127275Sstephh     struct timeval *tvp, boolean_t repaired, boolean_t replaced,
213*10928SStephen.Hanson@Sun.COM     boolean_t acquitted, boolean_t resolved, nvlist_t *diag_de,
214*10928SStephen.Hanson@Sun.COM     boolean_t injected)
2150Sstevel@tonic-gate {
2160Sstevel@tonic-gate 	nvlist_t *nvl;
2175255Sstephh 	int64_t tod[2];
2180Sstevel@tonic-gate 	int err = 0;
2190Sstevel@tonic-gate 
2205255Sstephh 	tod[0] = tvp->tv_sec;
2215255Sstephh 	tod[1] = tvp->tv_usec;
2225255Sstephh 
2230Sstevel@tonic-gate 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
2240Sstevel@tonic-gate 		fmd_panic("failed to xalloc resource nvlist");
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_RSRC_VERSION);
2270Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_CLASS, class);
2286228Sstephh 	if (fmri != NULL)
2296228Sstephh 		err |= nvlist_add_nvlist(nvl, FM_RSRC_RESOURCE, fmri);
2301414Scindi 
2311414Scindi 	if (uuid != NULL)
2321414Scindi 		err |= nvlist_add_string(nvl, FM_RSRC_ASRU_UUID, uuid);
2331414Scindi 
2341414Scindi 	if (code != NULL)
2351414Scindi 		err |= nvlist_add_string(nvl, FM_RSRC_ASRU_CODE, code);
2361414Scindi 
2370Sstevel@tonic-gate 	err |= nvlist_add_boolean_value(nvl, FM_RSRC_ASRU_FAULTY, faulty);
2387275Sstephh 	err |= nvlist_add_boolean_value(nvl, FM_RSRC_ASRU_REPAIRED, repaired);
2397275Sstephh 	err |= nvlist_add_boolean_value(nvl, FM_RSRC_ASRU_REPLACED, replaced);
2407275Sstephh 	err |= nvlist_add_boolean_value(nvl, FM_RSRC_ASRU_ACQUITTED, acquitted);
24110656SStephen.Hanson@Sun.COM 	err |= nvlist_add_boolean_value(nvl, FM_RSRC_ASRU_RESOLVED, resolved);
2420Sstevel@tonic-gate 	err |= nvlist_add_boolean_value(nvl, FM_RSRC_ASRU_UNUSABLE, unusable);
2430Sstevel@tonic-gate 	err |= nvlist_add_boolean_value(nvl, FM_SUSPECT_MESSAGE, message);
2445255Sstephh 	err |= nvlist_add_int64_array(nvl, FM_SUSPECT_DIAG_TIME, tod, 2);
2450Sstevel@tonic-gate 
2469120SStephen.Hanson@Sun.COM 	if (diag_de != NULL)
2479120SStephen.Hanson@Sun.COM 		err |= nvlist_add_nvlist(nvl, FM_SUSPECT_DE, diag_de);
248*10928SStephen.Hanson@Sun.COM 	if (injected)
249*10928SStephen.Hanson@Sun.COM 		err |= nvlist_add_boolean_value(nvl, FM_SUSPECT_INJECTED,
250*10928SStephen.Hanson@Sun.COM 		    B_TRUE);
2519120SStephen.Hanson@Sun.COM 
2520Sstevel@tonic-gate 	if (event != NULL)
2530Sstevel@tonic-gate 		err |= nvlist_add_nvlist(nvl, FM_RSRC_ASRU_EVENT, event);
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	if (err != 0)
2560Sstevel@tonic-gate 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	return (nvl);
2590Sstevel@tonic-gate }
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate nvlist_t *
fmd_protocol_fmderror(int errnum,const char * format,va_list ap)2620Sstevel@tonic-gate fmd_protocol_fmderror(int errnum, const char *format, va_list ap)
2630Sstevel@tonic-gate {
2640Sstevel@tonic-gate 	uint64_t ena = fmd_ena();
2650Sstevel@tonic-gate 	nvlist_t *nvl;
2660Sstevel@tonic-gate 	int err = 0;
2670Sstevel@tonic-gate 	char c, *msg;
2680Sstevel@tonic-gate 	size_t len;
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
2710Sstevel@tonic-gate 		return (NULL);
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 	len = vsnprintf(&c, 1, format, ap);
2740Sstevel@tonic-gate 	msg = alloca(len + 1);
2750Sstevel@tonic-gate 	(void) vsnprintf(msg, len + 1, format, ap);
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	if (msg[len] == '\n')
2780Sstevel@tonic-gate 		msg[len] = '\0';
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_EREPORT_VERSION);
2810Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_CLASS, fmd_errclass(errnum));
2820Sstevel@tonic-gate 	err |= nvlist_add_uint64(nvl, FM_EREPORT_ENA, ena);
2830Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FMD_ERR_MOD_MSG, msg);
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	if (err != 0) {
2860Sstevel@tonic-gate 		nvlist_free(nvl);
2870Sstevel@tonic-gate 		return (NULL);
2880Sstevel@tonic-gate 	}
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	return (nvl);
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate nvlist_t *
fmd_protocol_moderror(fmd_module_t * mp,int oserr,const char * msg)2940Sstevel@tonic-gate fmd_protocol_moderror(fmd_module_t *mp, int oserr, const char *msg)
2950Sstevel@tonic-gate {
2960Sstevel@tonic-gate 	uint64_t ena = fmd_ena();
2970Sstevel@tonic-gate 	nvlist_t *nvl, *fmri;
2980Sstevel@tonic-gate 	int err = 0;
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
3010Sstevel@tonic-gate 		fmd_panic("failed to xalloc module error nvlist");
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	if (mp->mod_fmri == NULL)
3040Sstevel@tonic-gate 		fmri = fmd_protocol_fmri_module(mp);
3050Sstevel@tonic-gate 	else
3060Sstevel@tonic-gate 		fmri = mp->mod_fmri;
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_EREPORT_VERSION);
3090Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_CLASS, fmd_errclass(EFMD_MODULE));
3100Sstevel@tonic-gate 	err |= nvlist_add_nvlist(nvl, FM_EREPORT_DETECTOR, fmri);
3110Sstevel@tonic-gate 	err |= nvlist_add_uint64(nvl, FM_EREPORT_ENA, ena);
3120Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FMD_ERR_MOD_MSG, msg);
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	if (mp->mod_fmri == NULL)
3150Sstevel@tonic-gate 		nvlist_free(fmri);
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 	if (oserr != 0) {
3180Sstevel@tonic-gate 		err |= nvlist_add_int32(nvl, FMD_ERR_MOD_ERRNO, oserr);
3190Sstevel@tonic-gate 		err |= nvlist_add_string(nvl, FMD_ERR_MOD_ERRCLASS,
3200Sstevel@tonic-gate 		    fmd_errclass(oserr));
3210Sstevel@tonic-gate 	}
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	if (err != 0)
3240Sstevel@tonic-gate 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	return (nvl);
3270Sstevel@tonic-gate }
3281193Smws 
3291193Smws nvlist_t *
fmd_protocol_xprt_ctl(fmd_module_t * mp,const char * class,uint8_t version)3301193Smws fmd_protocol_xprt_ctl(fmd_module_t *mp, const char *class, uint8_t version)
3311193Smws {
3321193Smws 	nvlist_t *nvl;
3331193Smws 	int err = 0;
3341193Smws 
3351193Smws 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
3361193Smws 		fmd_panic("failed to xalloc rsrc xprt nvlist");
3371193Smws 
3381193Smws 	err |= nvlist_add_uint8(nvl, FM_VERSION, version);
3391193Smws 	err |= nvlist_add_string(nvl, FM_CLASS, class);
3401193Smws 	err |= nvlist_add_nvlist(nvl, FM_RSRC_RESOURCE, mp->mod_fmri);
3411193Smws 
3421193Smws 	if (err != 0)
3431193Smws 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
3441193Smws 
3451193Smws 	return (nvl);
3461193Smws }
3471193Smws 
3481193Smws nvlist_t *
fmd_protocol_xprt_sub(fmd_module_t * mp,const char * class,uint8_t version,const char * subclass)3491193Smws fmd_protocol_xprt_sub(fmd_module_t *mp,
3501193Smws     const char *class, uint8_t version, const char *subclass)
3511193Smws {
3521193Smws 	nvlist_t *nvl = fmd_protocol_xprt_ctl(mp, class, version);
3531193Smws 	int err = nvlist_add_string(nvl, FM_RSRC_XPRT_SUBCLASS, subclass);
3541193Smws 
3551193Smws 	if (err != 0)
3561193Smws 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
3571193Smws 
3581193Smws 	return (nvl);
3591193Smws }
3601193Smws 
3611193Smws nvlist_t *
fmd_protocol_xprt_uuclose(fmd_module_t * mp,const char * class,uint8_t version,const char * uuid)3621193Smws fmd_protocol_xprt_uuclose(fmd_module_t *mp, const char *class, uint8_t version,
3631193Smws     const char *uuid)
3641193Smws {
3651193Smws 	nvlist_t *nvl = fmd_protocol_xprt_ctl(mp, class, version);
3661193Smws 	int err = nvlist_add_string(nvl, FM_RSRC_XPRT_UUID, uuid);
3671193Smws 
3681193Smws 	if (err != 0)
3691193Smws 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
3701193Smws 
3711193Smws 	return (nvl);
3721193Smws }
3739120SStephen.Hanson@Sun.COM 
3749120SStephen.Hanson@Sun.COM nvlist_t *
fmd_protocol_xprt_uuresolved(fmd_module_t * mp,const char * class,uint8_t version,const char * uuid)3759120SStephen.Hanson@Sun.COM fmd_protocol_xprt_uuresolved(fmd_module_t *mp, const char *class,
3769120SStephen.Hanson@Sun.COM     uint8_t version, const char *uuid)
3779120SStephen.Hanson@Sun.COM {
3789120SStephen.Hanson@Sun.COM 	nvlist_t *nvl = fmd_protocol_xprt_ctl(mp, class, version);
3799120SStephen.Hanson@Sun.COM 	int err = nvlist_add_string(nvl, FM_RSRC_XPRT_UUID, uuid);
3809120SStephen.Hanson@Sun.COM 
3819120SStephen.Hanson@Sun.COM 	if (err != 0)
3829120SStephen.Hanson@Sun.COM 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
3839120SStephen.Hanson@Sun.COM 
3849120SStephen.Hanson@Sun.COM 	return (nvl);
3859120SStephen.Hanson@Sun.COM }
3869120SStephen.Hanson@Sun.COM 
3879120SStephen.Hanson@Sun.COM nvlist_t *
fmd_protocol_xprt_updated(fmd_module_t * mp,const char * class,uint8_t version,const char * uuid,uint8_t * statusp,uint8_t * has_asrup,uint_t nelem)3889120SStephen.Hanson@Sun.COM fmd_protocol_xprt_updated(fmd_module_t *mp, const char *class, uint8_t version,
3899120SStephen.Hanson@Sun.COM     const char *uuid, uint8_t *statusp, uint8_t *has_asrup, uint_t nelem)
3909120SStephen.Hanson@Sun.COM {
3919120SStephen.Hanson@Sun.COM 	nvlist_t *nvl = fmd_protocol_xprt_ctl(mp, class, version);
3929120SStephen.Hanson@Sun.COM 	int err = nvlist_add_string(nvl, FM_RSRC_XPRT_UUID, uuid);
3939120SStephen.Hanson@Sun.COM 
3949120SStephen.Hanson@Sun.COM 	err |= nvlist_add_uint8_array(nvl, FM_RSRC_XPRT_FAULT_STATUS, statusp,
3959120SStephen.Hanson@Sun.COM 	    nelem);
3969120SStephen.Hanson@Sun.COM 	if (has_asrup)
3979120SStephen.Hanson@Sun.COM 		err |= nvlist_add_uint8_array(nvl, FM_RSRC_XPRT_FAULT_HAS_ASRU,
3989120SStephen.Hanson@Sun.COM 		    has_asrup, nelem);
3999120SStephen.Hanson@Sun.COM 
4009120SStephen.Hanson@Sun.COM 	if (err != 0)
4019120SStephen.Hanson@Sun.COM 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
4029120SStephen.Hanson@Sun.COM 
4039120SStephen.Hanson@Sun.COM 	return (nvl);
4049120SStephen.Hanson@Sun.COM }
405