1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #include <sys/fm/protocol.h> 31 #include <strings.h> 32 #include <alloca.h> 33 #include <stdio.h> 34 35 #include <fmd_protocol.h> 36 #include <fmd_module.h> 37 #include <fmd_conf.h> 38 #include <fmd_subr.h> 39 #include <fmd_error.h> 40 #include <fmd_time.h> 41 #include <fmd.h> 42 43 /* 44 * Create an FMRI authority element for the environment in which this instance 45 * of fmd is deployed. This function is called once and the result is cached. 46 */ 47 nvlist_t * 48 fmd_protocol_authority(void) 49 { 50 const char *str; 51 nvlist_t *nvl; 52 int err = 0; 53 54 if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0) 55 fmd_panic("failed to xalloc authority nvlist"); 56 57 err |= nvlist_add_uint8(nvl, FM_VERSION, FM_FMRI_AUTH_VERSION); 58 59 if ((str = fmd_conf_getnzstr(fmd.d_conf, "product")) == NULL) 60 str = fmd_conf_getnzstr(fmd.d_conf, "platform"); 61 62 if (str != NULL) 63 err |= nvlist_add_string(nvl, FM_FMRI_AUTH_PRODUCT, str); 64 65 if ((str = fmd_conf_getnzstr(fmd.d_conf, "chassis")) != NULL) 66 err |= nvlist_add_string(nvl, FM_FMRI_AUTH_CHASSIS, str); 67 68 if ((str = fmd_conf_getnzstr(fmd.d_conf, "domain")) != NULL) 69 err |= nvlist_add_string(nvl, FM_FMRI_AUTH_DOMAIN, str); 70 71 if ((str = fmd_conf_getnzstr(fmd.d_conf, "server")) != NULL) 72 err |= nvlist_add_string(nvl, FM_FMRI_AUTH_SERVER, str); 73 74 if (err != 0) 75 fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err)); 76 77 return (nvl); 78 } 79 80 /* 81 * Create an FMRI for the specified module. We use the cached authority 82 * nvlist saved in fmd.d_auth to fill in the authority member. 83 */ 84 nvlist_t * 85 fmd_protocol_fmri_module(fmd_module_t *mp) 86 { 87 nvlist_t *nvl; 88 int err = 0; 89 90 if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0) 91 fmd_panic("failed to xalloc diag-engine fmri nvlist"); 92 93 err |= nvlist_add_uint8(nvl, FM_VERSION, FM_FMD_SCHEME_VERSION); 94 err |= nvlist_add_string(nvl, FM_FMRI_SCHEME, FM_FMRI_SCHEME_FMD); 95 err |= nvlist_add_nvlist(nvl, FM_FMRI_AUTHORITY, fmd.d_auth); 96 err |= nvlist_add_string(nvl, FM_FMRI_FMD_NAME, mp->mod_name); 97 98 if (mp->mod_info != NULL) { 99 err |= nvlist_add_string(nvl, 100 FM_FMRI_FMD_VERSION, mp->mod_info->fmdi_vers); 101 } else if (mp == fmd.d_rmod) { 102 err |= nvlist_add_string(nvl, 103 FM_FMRI_FMD_VERSION, fmd.d_version); 104 } 105 106 if (err != 0) 107 fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err)); 108 109 return (nvl); 110 } 111 112 nvlist_t * 113 fmd_protocol_fault(const char *class, uint8_t certainty, 114 nvlist_t *asru, nvlist_t *fru, nvlist_t *resource) 115 { 116 nvlist_t *nvl; 117 int err = 0; 118 119 if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0) 120 fmd_panic("failed to xalloc fault nvlist"); 121 122 err |= nvlist_add_uint8(nvl, FM_VERSION, FM_FAULT_VERSION); 123 err |= nvlist_add_string(nvl, FM_CLASS, class); 124 err |= nvlist_add_uint8(nvl, FM_FAULT_CERTAINTY, certainty); 125 126 if (asru != NULL) 127 err |= nvlist_add_nvlist(nvl, FM_FAULT_ASRU, asru); 128 if (fru != NULL) 129 err |= nvlist_add_nvlist(nvl, FM_FAULT_FRU, fru); 130 if (resource != NULL) 131 err |= nvlist_add_nvlist(nvl, FM_FAULT_RESOURCE, resource); 132 133 if (err != 0) 134 fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err)); 135 136 return (nvl); 137 } 138 139 nvlist_t * 140 fmd_protocol_list(const char *class, nvlist_t *de_fmri, const char *uuid, 141 const char *code, uint_t argc, nvlist_t **argv, uint8_t *flagv, int domsg) 142 { 143 struct timeval tv; 144 int64_t tod[2]; 145 nvlist_t *nvl; 146 int err = 0; 147 148 fmd_time_gettimeofday(&tv); 149 tod[0] = tv.tv_sec; 150 tod[1] = tv.tv_usec; 151 152 if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0) 153 fmd_panic("failed to xalloc suspect list nvlist"); 154 155 err |= nvlist_add_uint8(nvl, FM_VERSION, FM_SUSPECT_VERSION); 156 err |= nvlist_add_string(nvl, FM_CLASS, class); 157 err |= nvlist_add_string(nvl, FM_SUSPECT_UUID, uuid); 158 err |= nvlist_add_string(nvl, FM_SUSPECT_DIAG_CODE, code); 159 err |= nvlist_add_int64_array(nvl, FM_SUSPECT_DIAG_TIME, tod, 2); 160 err |= nvlist_add_nvlist(nvl, FM_SUSPECT_DE, de_fmri); 161 err |= nvlist_add_uint32(nvl, FM_SUSPECT_FAULT_SZ, argc); 162 163 if (!domsg) { 164 err |= nvlist_add_boolean_value(nvl, 165 FM_SUSPECT_MESSAGE, B_FALSE); 166 } 167 168 if (argc != 0) { 169 err |= nvlist_add_nvlist_array(nvl, 170 FM_SUSPECT_FAULT_LIST, argv, argc); 171 err |= nvlist_add_uint8_array(nvl, 172 FM_SUSPECT_FAULT_STATUS, flagv, argc); 173 } 174 175 if (err != 0) 176 fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err)); 177 178 return (nvl); 179 } 180 181 nvlist_t * 182 fmd_protocol_rsrc_asru(const char *class, 183 nvlist_t *fmri, const char *uuid, const char *code, 184 boolean_t faulty, boolean_t unusable, boolean_t message, nvlist_t *event) 185 { 186 nvlist_t *nvl; 187 int err = 0; 188 189 if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0) 190 fmd_panic("failed to xalloc resource nvlist"); 191 192 err |= nvlist_add_uint8(nvl, FM_VERSION, FM_RSRC_VERSION); 193 err |= nvlist_add_string(nvl, FM_CLASS, class); 194 err |= nvlist_add_nvlist(nvl, FM_RSRC_RESOURCE, fmri); 195 196 if (uuid != NULL) 197 err |= nvlist_add_string(nvl, FM_RSRC_ASRU_UUID, uuid); 198 199 if (code != NULL) 200 err |= nvlist_add_string(nvl, FM_RSRC_ASRU_CODE, code); 201 202 err |= nvlist_add_boolean_value(nvl, FM_RSRC_ASRU_FAULTY, faulty); 203 err |= nvlist_add_boolean_value(nvl, FM_RSRC_ASRU_UNUSABLE, unusable); 204 err |= nvlist_add_boolean_value(nvl, FM_SUSPECT_MESSAGE, message); 205 206 if (event != NULL) 207 err |= nvlist_add_nvlist(nvl, FM_RSRC_ASRU_EVENT, event); 208 209 if (err != 0) 210 fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err)); 211 212 return (nvl); 213 } 214 215 nvlist_t * 216 fmd_protocol_fmderror(int errnum, const char *format, va_list ap) 217 { 218 uint64_t ena = fmd_ena(); 219 nvlist_t *nvl; 220 int err = 0; 221 char c, *msg; 222 size_t len; 223 224 if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0) 225 return (NULL); 226 227 len = vsnprintf(&c, 1, format, ap); 228 msg = alloca(len + 1); 229 (void) vsnprintf(msg, len + 1, format, ap); 230 231 if (msg[len] == '\n') 232 msg[len] = '\0'; 233 234 err |= nvlist_add_uint8(nvl, FM_VERSION, FM_EREPORT_VERSION); 235 err |= nvlist_add_string(nvl, FM_CLASS, fmd_errclass(errnum)); 236 err |= nvlist_add_uint64(nvl, FM_EREPORT_ENA, ena); 237 err |= nvlist_add_string(nvl, FMD_ERR_MOD_MSG, msg); 238 239 if (err != 0) { 240 nvlist_free(nvl); 241 return (NULL); 242 } 243 244 return (nvl); 245 } 246 247 nvlist_t * 248 fmd_protocol_moderror(fmd_module_t *mp, int oserr, const char *msg) 249 { 250 uint64_t ena = fmd_ena(); 251 nvlist_t *nvl, *fmri; 252 int err = 0; 253 254 if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0) 255 fmd_panic("failed to xalloc module error nvlist"); 256 257 if (mp->mod_fmri == NULL) 258 fmri = fmd_protocol_fmri_module(mp); 259 else 260 fmri = mp->mod_fmri; 261 262 err |= nvlist_add_uint8(nvl, FM_VERSION, FM_EREPORT_VERSION); 263 err |= nvlist_add_string(nvl, FM_CLASS, fmd_errclass(EFMD_MODULE)); 264 err |= nvlist_add_nvlist(nvl, FM_EREPORT_DETECTOR, fmri); 265 err |= nvlist_add_uint64(nvl, FM_EREPORT_ENA, ena); 266 err |= nvlist_add_string(nvl, FMD_ERR_MOD_MSG, msg); 267 268 if (mp->mod_fmri == NULL) 269 nvlist_free(fmri); 270 271 if (oserr != 0) { 272 err |= nvlist_add_int32(nvl, FMD_ERR_MOD_ERRNO, oserr); 273 err |= nvlist_add_string(nvl, FMD_ERR_MOD_ERRCLASS, 274 fmd_errclass(oserr)); 275 } 276 277 if (err != 0) 278 fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err)); 279 280 return (nvl); 281 } 282 283 nvlist_t * 284 fmd_protocol_xprt_ctl(fmd_module_t *mp, const char *class, uint8_t version) 285 { 286 nvlist_t *nvl; 287 int err = 0; 288 289 if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0) 290 fmd_panic("failed to xalloc rsrc xprt nvlist"); 291 292 err |= nvlist_add_uint8(nvl, FM_VERSION, version); 293 err |= nvlist_add_string(nvl, FM_CLASS, class); 294 err |= nvlist_add_nvlist(nvl, FM_RSRC_RESOURCE, mp->mod_fmri); 295 296 if (err != 0) 297 fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err)); 298 299 return (nvl); 300 } 301 302 nvlist_t * 303 fmd_protocol_xprt_sub(fmd_module_t *mp, 304 const char *class, uint8_t version, const char *subclass) 305 { 306 nvlist_t *nvl = fmd_protocol_xprt_ctl(mp, class, version); 307 int err = nvlist_add_string(nvl, FM_RSRC_XPRT_SUBCLASS, subclass); 308 309 if (err != 0) 310 fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err)); 311 312 return (nvl); 313 } 314 315 nvlist_t * 316 fmd_protocol_xprt_uuclose(fmd_module_t *mp, const char *class, uint8_t version, 317 const char *uuid) 318 { 319 nvlist_t *nvl = fmd_protocol_xprt_ctl(mp, class, version); 320 int err = nvlist_add_string(nvl, FM_RSRC_XPRT_UUID, uuid); 321 322 if (err != 0) 323 fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err)); 324 325 return (nvl); 326 } 327