xref: /onnv-gate/usr/src/cmd/fm/fmd/common/fmd_protocol.c (revision 5255:8dc347a9bd70)
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 /*
23*5255Sstephh  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <sys/fm/protocol.h>
300Sstevel@tonic-gate #include <strings.h>
310Sstevel@tonic-gate #include <alloca.h>
320Sstevel@tonic-gate #include <stdio.h>
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include <fmd_protocol.h>
350Sstevel@tonic-gate #include <fmd_module.h>
360Sstevel@tonic-gate #include <fmd_conf.h>
370Sstevel@tonic-gate #include <fmd_subr.h>
380Sstevel@tonic-gate #include <fmd_error.h>
390Sstevel@tonic-gate #include <fmd_time.h>
400Sstevel@tonic-gate #include <fmd.h>
410Sstevel@tonic-gate 
420Sstevel@tonic-gate /*
430Sstevel@tonic-gate  * Create an FMRI authority element for the environment in which this instance
440Sstevel@tonic-gate  * of fmd is deployed.  This function is called once and the result is cached.
450Sstevel@tonic-gate  */
460Sstevel@tonic-gate nvlist_t *
470Sstevel@tonic-gate fmd_protocol_authority(void)
480Sstevel@tonic-gate {
490Sstevel@tonic-gate 	const char *str;
500Sstevel@tonic-gate 	nvlist_t *nvl;
510Sstevel@tonic-gate 	int err = 0;
520Sstevel@tonic-gate 
530Sstevel@tonic-gate 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
540Sstevel@tonic-gate 		fmd_panic("failed to xalloc authority nvlist");
550Sstevel@tonic-gate 
560Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_FMRI_AUTH_VERSION);
571414Scindi 
581414Scindi 	if ((str = fmd_conf_getnzstr(fmd.d_conf, "product")) == NULL)
591414Scindi 		str = fmd_conf_getnzstr(fmd.d_conf, "platform");
600Sstevel@tonic-gate 
611414Scindi 	if (str != NULL)
621414Scindi 		err |= nvlist_add_string(nvl, FM_FMRI_AUTH_PRODUCT, str);
631414Scindi 
641414Scindi 	if ((str = fmd_conf_getnzstr(fmd.d_conf, "chassis")) != NULL)
650Sstevel@tonic-gate 		err |= nvlist_add_string(nvl, FM_FMRI_AUTH_CHASSIS, str);
660Sstevel@tonic-gate 
671414Scindi 	if ((str = fmd_conf_getnzstr(fmd.d_conf, "domain")) != NULL)
680Sstevel@tonic-gate 		err |= nvlist_add_string(nvl, FM_FMRI_AUTH_DOMAIN, str);
690Sstevel@tonic-gate 
701414Scindi 	if ((str = fmd_conf_getnzstr(fmd.d_conf, "server")) != NULL)
710Sstevel@tonic-gate 		err |= nvlist_add_string(nvl, FM_FMRI_AUTH_SERVER, str);
720Sstevel@tonic-gate 
730Sstevel@tonic-gate 	if (err != 0)
740Sstevel@tonic-gate 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 	return (nvl);
770Sstevel@tonic-gate }
780Sstevel@tonic-gate 
790Sstevel@tonic-gate /*
800Sstevel@tonic-gate  * Create an FMRI for the specified module.  We use the cached authority
810Sstevel@tonic-gate  * nvlist saved in fmd.d_auth to fill in the authority member.
820Sstevel@tonic-gate  */
830Sstevel@tonic-gate nvlist_t *
840Sstevel@tonic-gate fmd_protocol_fmri_module(fmd_module_t *mp)
850Sstevel@tonic-gate {
860Sstevel@tonic-gate 	nvlist_t *nvl;
870Sstevel@tonic-gate 	int err = 0;
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
900Sstevel@tonic-gate 		fmd_panic("failed to xalloc diag-engine fmri nvlist");
910Sstevel@tonic-gate 
920Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_FMD_SCHEME_VERSION);
930Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_FMRI_SCHEME, FM_FMRI_SCHEME_FMD);
940Sstevel@tonic-gate 	err |= nvlist_add_nvlist(nvl, FM_FMRI_AUTHORITY, fmd.d_auth);
950Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_FMRI_FMD_NAME, mp->mod_name);
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 	if (mp->mod_info != NULL) {
980Sstevel@tonic-gate 		err |= nvlist_add_string(nvl,
990Sstevel@tonic-gate 		    FM_FMRI_FMD_VERSION, mp->mod_info->fmdi_vers);
1001193Smws 	} else if (mp == fmd.d_rmod) {
1011193Smws 		err |= nvlist_add_string(nvl,
1021193Smws 		    FM_FMRI_FMD_VERSION, fmd.d_version);
1030Sstevel@tonic-gate 	}
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate 	if (err != 0)
1060Sstevel@tonic-gate 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 	return (nvl);
1090Sstevel@tonic-gate }
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate nvlist_t *
1120Sstevel@tonic-gate fmd_protocol_fault(const char *class, uint8_t certainty,
1133323Scindi     nvlist_t *asru, nvlist_t *fru, nvlist_t *resource, const char *location)
1140Sstevel@tonic-gate {
1150Sstevel@tonic-gate 	nvlist_t *nvl;
1160Sstevel@tonic-gate 	int err = 0;
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
1190Sstevel@tonic-gate 		fmd_panic("failed to xalloc fault nvlist");
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_FAULT_VERSION);
1220Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_CLASS, class);
1230Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_FAULT_CERTAINTY, certainty);
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 	if (asru != NULL)
1260Sstevel@tonic-gate 		err |= nvlist_add_nvlist(nvl, FM_FAULT_ASRU, asru);
1270Sstevel@tonic-gate 	if (fru != NULL)
1280Sstevel@tonic-gate 		err |= nvlist_add_nvlist(nvl, FM_FAULT_FRU, fru);
1290Sstevel@tonic-gate 	if (resource != NULL)
1300Sstevel@tonic-gate 		err |= nvlist_add_nvlist(nvl, FM_FAULT_RESOURCE, resource);
1313323Scindi 	if (location != NULL)
1323323Scindi 		err |= nvlist_add_string(nvl, FM_FAULT_LOCATION, location);
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	if (err != 0)
1350Sstevel@tonic-gate 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 	return (nvl);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate nvlist_t *
1411193Smws fmd_protocol_list(const char *class, nvlist_t *de_fmri, const char *uuid,
142*5255Sstephh     const char *code, uint_t argc, nvlist_t **argv, uint8_t *flagv, int domsg,
143*5255Sstephh     struct timeval *tvp)
1440Sstevel@tonic-gate {
1450Sstevel@tonic-gate 	int64_t tod[2];
1460Sstevel@tonic-gate 	nvlist_t *nvl;
1470Sstevel@tonic-gate 	int err = 0;
1480Sstevel@tonic-gate 
149*5255Sstephh 	tod[0] = tvp->tv_sec;
150*5255Sstephh 	tod[1] = tvp->tv_usec;
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
1530Sstevel@tonic-gate 		fmd_panic("failed to xalloc suspect list nvlist");
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_SUSPECT_VERSION);
1561193Smws 	err |= nvlist_add_string(nvl, FM_CLASS, class);
1570Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_SUSPECT_UUID, uuid);
1580Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_SUSPECT_DIAG_CODE, code);
1590Sstevel@tonic-gate 	err |= nvlist_add_int64_array(nvl, FM_SUSPECT_DIAG_TIME, tod, 2);
1600Sstevel@tonic-gate 	err |= nvlist_add_nvlist(nvl, FM_SUSPECT_DE, de_fmri);
1610Sstevel@tonic-gate 	err |= nvlist_add_uint32(nvl, FM_SUSPECT_FAULT_SZ, argc);
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate 	if (!domsg) {
1641193Smws 		err |= nvlist_add_boolean_value(nvl,
1651193Smws 		    FM_SUSPECT_MESSAGE, B_FALSE);
1660Sstevel@tonic-gate 	}
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	if (argc != 0) {
1690Sstevel@tonic-gate 		err |= nvlist_add_nvlist_array(nvl,
1700Sstevel@tonic-gate 		    FM_SUSPECT_FAULT_LIST, argv, argc);
1711193Smws 		err |= nvlist_add_uint8_array(nvl,
1721193Smws 		    FM_SUSPECT_FAULT_STATUS, flagv, argc);
1730Sstevel@tonic-gate 	}
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	if (err != 0)
1760Sstevel@tonic-gate 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 	return (nvl);
1790Sstevel@tonic-gate }
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate nvlist_t *
1821193Smws fmd_protocol_rsrc_asru(const char *class,
1831193Smws     nvlist_t *fmri, const char *uuid, const char *code,
184*5255Sstephh     boolean_t faulty, boolean_t unusable, boolean_t message, nvlist_t *event,
185*5255Sstephh     struct timeval *tvp)
1860Sstevel@tonic-gate {
1870Sstevel@tonic-gate 	nvlist_t *nvl;
188*5255Sstephh 	int64_t tod[2];
1890Sstevel@tonic-gate 	int err = 0;
1900Sstevel@tonic-gate 
191*5255Sstephh 	tod[0] = tvp->tv_sec;
192*5255Sstephh 	tod[1] = tvp->tv_usec;
193*5255Sstephh 
1940Sstevel@tonic-gate 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
1950Sstevel@tonic-gate 		fmd_panic("failed to xalloc resource nvlist");
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_RSRC_VERSION);
1980Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_CLASS, class);
1990Sstevel@tonic-gate 	err |= nvlist_add_nvlist(nvl, FM_RSRC_RESOURCE, fmri);
2001414Scindi 
2011414Scindi 	if (uuid != NULL)
2021414Scindi 		err |= nvlist_add_string(nvl, FM_RSRC_ASRU_UUID, uuid);
2031414Scindi 
2041414Scindi 	if (code != NULL)
2051414Scindi 		err |= nvlist_add_string(nvl, FM_RSRC_ASRU_CODE, code);
2061414Scindi 
2070Sstevel@tonic-gate 	err |= nvlist_add_boolean_value(nvl, FM_RSRC_ASRU_FAULTY, faulty);
2080Sstevel@tonic-gate 	err |= nvlist_add_boolean_value(nvl, FM_RSRC_ASRU_UNUSABLE, unusable);
2090Sstevel@tonic-gate 	err |= nvlist_add_boolean_value(nvl, FM_SUSPECT_MESSAGE, message);
210*5255Sstephh 	err |= nvlist_add_int64_array(nvl, FM_SUSPECT_DIAG_TIME, tod, 2);
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 	if (event != NULL)
2130Sstevel@tonic-gate 		err |= nvlist_add_nvlist(nvl, FM_RSRC_ASRU_EVENT, event);
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	if (err != 0)
2160Sstevel@tonic-gate 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	return (nvl);
2190Sstevel@tonic-gate }
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate nvlist_t *
2220Sstevel@tonic-gate fmd_protocol_fmderror(int errnum, const char *format, va_list ap)
2230Sstevel@tonic-gate {
2240Sstevel@tonic-gate 	uint64_t ena = fmd_ena();
2250Sstevel@tonic-gate 	nvlist_t *nvl;
2260Sstevel@tonic-gate 	int err = 0;
2270Sstevel@tonic-gate 	char c, *msg;
2280Sstevel@tonic-gate 	size_t len;
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
2310Sstevel@tonic-gate 		return (NULL);
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 	len = vsnprintf(&c, 1, format, ap);
2340Sstevel@tonic-gate 	msg = alloca(len + 1);
2350Sstevel@tonic-gate 	(void) vsnprintf(msg, len + 1, format, ap);
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 	if (msg[len] == '\n')
2380Sstevel@tonic-gate 		msg[len] = '\0';
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_EREPORT_VERSION);
2410Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_CLASS, fmd_errclass(errnum));
2420Sstevel@tonic-gate 	err |= nvlist_add_uint64(nvl, FM_EREPORT_ENA, ena);
2430Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FMD_ERR_MOD_MSG, msg);
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	if (err != 0) {
2460Sstevel@tonic-gate 		nvlist_free(nvl);
2470Sstevel@tonic-gate 		return (NULL);
2480Sstevel@tonic-gate 	}
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	return (nvl);
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate nvlist_t *
2540Sstevel@tonic-gate fmd_protocol_moderror(fmd_module_t *mp, int oserr, const char *msg)
2550Sstevel@tonic-gate {
2560Sstevel@tonic-gate 	uint64_t ena = fmd_ena();
2570Sstevel@tonic-gate 	nvlist_t *nvl, *fmri;
2580Sstevel@tonic-gate 	int err = 0;
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
2610Sstevel@tonic-gate 		fmd_panic("failed to xalloc module error nvlist");
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	if (mp->mod_fmri == NULL)
2640Sstevel@tonic-gate 		fmri = fmd_protocol_fmri_module(mp);
2650Sstevel@tonic-gate 	else
2660Sstevel@tonic-gate 		fmri = mp->mod_fmri;
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_EREPORT_VERSION);
2690Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FM_CLASS, fmd_errclass(EFMD_MODULE));
2700Sstevel@tonic-gate 	err |= nvlist_add_nvlist(nvl, FM_EREPORT_DETECTOR, fmri);
2710Sstevel@tonic-gate 	err |= nvlist_add_uint64(nvl, FM_EREPORT_ENA, ena);
2720Sstevel@tonic-gate 	err |= nvlist_add_string(nvl, FMD_ERR_MOD_MSG, msg);
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	if (mp->mod_fmri == NULL)
2750Sstevel@tonic-gate 		nvlist_free(fmri);
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	if (oserr != 0) {
2780Sstevel@tonic-gate 		err |= nvlist_add_int32(nvl, FMD_ERR_MOD_ERRNO, oserr);
2790Sstevel@tonic-gate 		err |= nvlist_add_string(nvl, FMD_ERR_MOD_ERRCLASS,
2800Sstevel@tonic-gate 		    fmd_errclass(oserr));
2810Sstevel@tonic-gate 	}
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	if (err != 0)
2840Sstevel@tonic-gate 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	return (nvl);
2870Sstevel@tonic-gate }
2881193Smws 
2891193Smws nvlist_t *
2901193Smws fmd_protocol_xprt_ctl(fmd_module_t *mp, const char *class, uint8_t version)
2911193Smws {
2921193Smws 	nvlist_t *nvl;
2931193Smws 	int err = 0;
2941193Smws 
2951193Smws 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
2961193Smws 		fmd_panic("failed to xalloc rsrc xprt nvlist");
2971193Smws 
2981193Smws 	err |= nvlist_add_uint8(nvl, FM_VERSION, version);
2991193Smws 	err |= nvlist_add_string(nvl, FM_CLASS, class);
3001193Smws 	err |= nvlist_add_nvlist(nvl, FM_RSRC_RESOURCE, mp->mod_fmri);
3011193Smws 
3021193Smws 	if (err != 0)
3031193Smws 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
3041193Smws 
3051193Smws 	return (nvl);
3061193Smws }
3071193Smws 
3081193Smws nvlist_t *
3091193Smws fmd_protocol_xprt_sub(fmd_module_t *mp,
3101193Smws     const char *class, uint8_t version, const char *subclass)
3111193Smws {
3121193Smws 	nvlist_t *nvl = fmd_protocol_xprt_ctl(mp, class, version);
3131193Smws 	int err = nvlist_add_string(nvl, FM_RSRC_XPRT_SUBCLASS, subclass);
3141193Smws 
3151193Smws 	if (err != 0)
3161193Smws 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
3171193Smws 
3181193Smws 	return (nvl);
3191193Smws }
3201193Smws 
3211193Smws nvlist_t *
3221193Smws fmd_protocol_xprt_uuclose(fmd_module_t *mp, const char *class, uint8_t version,
3231193Smws     const char *uuid)
3241193Smws {
3251193Smws 	nvlist_t *nvl = fmd_protocol_xprt_ctl(mp, class, version);
3261193Smws 	int err = nvlist_add_string(nvl, FM_RSRC_XPRT_UUID, uuid);
3271193Smws 
3281193Smws 	if (err != 0)
3291193Smws 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
3301193Smws 
3311193Smws 	return (nvl);
3321193Smws }
333