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