xref: /illumos-gate/usr/src/cmd/fm/fmd/common/fmd_protocol.c (revision 7f7322febbcfe774b7270abc3b191c094bfcc517)
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 2005 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 	(void) fmd_conf_getprop(fmd.d_conf, "platform", &str);
59 	err |= nvlist_add_string(nvl, FM_FMRI_AUTH_PRODUCT, str);
60 
61 	if (fmd_conf_getprop(fmd.d_conf, "chassis", &str) == 0 && str != NULL)
62 		err |= nvlist_add_string(nvl, FM_FMRI_AUTH_CHASSIS, str);
63 
64 	if (fmd_conf_getprop(fmd.d_conf, "domain", &str) == 0 && str != NULL)
65 		err |= nvlist_add_string(nvl, FM_FMRI_AUTH_DOMAIN, str);
66 
67 	if (fmd_conf_getprop(fmd.d_conf, "server", &str) == 0 && str != NULL)
68 		err |= nvlist_add_string(nvl, FM_FMRI_AUTH_SERVER, str);
69 
70 	if (err != 0)
71 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
72 
73 	return (nvl);
74 }
75 
76 /*
77  * Create an FMRI for the specified module.  We use the cached authority
78  * nvlist saved in fmd.d_auth to fill in the authority member.
79  */
80 nvlist_t *
81 fmd_protocol_fmri_module(fmd_module_t *mp)
82 {
83 	nvlist_t *nvl;
84 	int err = 0;
85 
86 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
87 		fmd_panic("failed to xalloc diag-engine fmri nvlist");
88 
89 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_FMD_SCHEME_VERSION);
90 	err |= nvlist_add_string(nvl, FM_FMRI_SCHEME, FM_FMRI_SCHEME_FMD);
91 	err |= nvlist_add_nvlist(nvl, FM_FMRI_AUTHORITY, fmd.d_auth);
92 	err |= nvlist_add_string(nvl, FM_FMRI_FMD_NAME, mp->mod_name);
93 
94 	if (mp->mod_info != NULL) {
95 		err |= nvlist_add_string(nvl,
96 		    FM_FMRI_FMD_VERSION, mp->mod_info->fmdi_vers);
97 	} else if (mp == fmd.d_rmod) {
98 		err |= nvlist_add_string(nvl,
99 		    FM_FMRI_FMD_VERSION, fmd.d_version);
100 	}
101 
102 	if (err != 0)
103 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
104 
105 	return (nvl);
106 }
107 
108 nvlist_t *
109 fmd_protocol_fault(const char *class, uint8_t certainty,
110     nvlist_t *asru, nvlist_t *fru, nvlist_t *resource)
111 {
112 	nvlist_t *nvl;
113 	int err = 0;
114 
115 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
116 		fmd_panic("failed to xalloc fault nvlist");
117 
118 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_FAULT_VERSION);
119 	err |= nvlist_add_string(nvl, FM_CLASS, class);
120 	err |= nvlist_add_uint8(nvl, FM_FAULT_CERTAINTY, certainty);
121 
122 	if (asru != NULL)
123 		err |= nvlist_add_nvlist(nvl, FM_FAULT_ASRU, asru);
124 	if (fru != NULL)
125 		err |= nvlist_add_nvlist(nvl, FM_FAULT_FRU, fru);
126 	if (resource != NULL)
127 		err |= nvlist_add_nvlist(nvl, FM_FAULT_RESOURCE, resource);
128 
129 	if (err != 0)
130 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
131 
132 	return (nvl);
133 }
134 
135 nvlist_t *
136 fmd_protocol_list(const char *class, nvlist_t *de_fmri, const char *uuid,
137     const char *code, uint_t argc, nvlist_t **argv, uint8_t *flagv, int domsg)
138 {
139 	struct timeval tv;
140 	int64_t tod[2];
141 	nvlist_t *nvl;
142 	int err = 0;
143 
144 	fmd_time_gettimeofday(&tv);
145 	tod[0] = tv.tv_sec;
146 	tod[1] = tv.tv_usec;
147 
148 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
149 		fmd_panic("failed to xalloc suspect list nvlist");
150 
151 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_SUSPECT_VERSION);
152 	err |= nvlist_add_string(nvl, FM_CLASS, class);
153 	err |= nvlist_add_string(nvl, FM_SUSPECT_UUID, uuid);
154 	err |= nvlist_add_string(nvl, FM_SUSPECT_DIAG_CODE, code);
155 	err |= nvlist_add_int64_array(nvl, FM_SUSPECT_DIAG_TIME, tod, 2);
156 	err |= nvlist_add_nvlist(nvl, FM_SUSPECT_DE, de_fmri);
157 	err |= nvlist_add_uint32(nvl, FM_SUSPECT_FAULT_SZ, argc);
158 
159 	if (!domsg) {
160 		err |= nvlist_add_boolean_value(nvl,
161 		    FM_SUSPECT_MESSAGE, B_FALSE);
162 	}
163 
164 	if (argc != 0) {
165 		err |= nvlist_add_nvlist_array(nvl,
166 		    FM_SUSPECT_FAULT_LIST, argv, argc);
167 		err |= nvlist_add_uint8_array(nvl,
168 		    FM_SUSPECT_FAULT_STATUS, flagv, argc);
169 	}
170 
171 	if (err != 0)
172 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
173 
174 	return (nvl);
175 }
176 
177 nvlist_t *
178 fmd_protocol_rsrc_asru(const char *class,
179     nvlist_t *fmri, const char *uuid, const char *code,
180     boolean_t faulty, boolean_t unusable, boolean_t message, nvlist_t *event)
181 {
182 	nvlist_t *nvl;
183 	int err = 0;
184 
185 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
186 		fmd_panic("failed to xalloc resource nvlist");
187 
188 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_RSRC_VERSION);
189 	err |= nvlist_add_string(nvl, FM_CLASS, class);
190 	err |= nvlist_add_nvlist(nvl, FM_RSRC_RESOURCE, fmri);
191 	err |= nvlist_add_string(nvl, FM_RSRC_ASRU_UUID, uuid);
192 	err |= nvlist_add_string(nvl, FM_RSRC_ASRU_CODE, code);
193 	err |= nvlist_add_boolean_value(nvl, FM_RSRC_ASRU_FAULTY, faulty);
194 	err |= nvlist_add_boolean_value(nvl, FM_RSRC_ASRU_UNUSABLE, unusable);
195 	err |= nvlist_add_boolean_value(nvl, FM_SUSPECT_MESSAGE, message);
196 
197 	if (event != NULL)
198 		err |= nvlist_add_nvlist(nvl, FM_RSRC_ASRU_EVENT, event);
199 
200 	if (err != 0)
201 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
202 
203 	return (nvl);
204 }
205 
206 nvlist_t *
207 fmd_protocol_fmderror(int errnum, const char *format, va_list ap)
208 {
209 	uint64_t ena = fmd_ena();
210 	nvlist_t *nvl;
211 	int err = 0;
212 	char c, *msg;
213 	size_t len;
214 
215 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
216 		return (NULL);
217 
218 	len = vsnprintf(&c, 1, format, ap);
219 	msg = alloca(len + 1);
220 	(void) vsnprintf(msg, len + 1, format, ap);
221 
222 	if (msg[len] == '\n')
223 		msg[len] = '\0';
224 
225 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_EREPORT_VERSION);
226 	err |= nvlist_add_string(nvl, FM_CLASS, fmd_errclass(errnum));
227 	err |= nvlist_add_uint64(nvl, FM_EREPORT_ENA, ena);
228 	err |= nvlist_add_string(nvl, FMD_ERR_MOD_MSG, msg);
229 
230 	if (err != 0) {
231 		nvlist_free(nvl);
232 		return (NULL);
233 	}
234 
235 	return (nvl);
236 }
237 
238 nvlist_t *
239 fmd_protocol_moderror(fmd_module_t *mp, int oserr, const char *msg)
240 {
241 	uint64_t ena = fmd_ena();
242 	nvlist_t *nvl, *fmri;
243 	int err = 0;
244 
245 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
246 		fmd_panic("failed to xalloc module error nvlist");
247 
248 	if (mp->mod_fmri == NULL)
249 		fmri = fmd_protocol_fmri_module(mp);
250 	else
251 		fmri = mp->mod_fmri;
252 
253 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_EREPORT_VERSION);
254 	err |= nvlist_add_string(nvl, FM_CLASS, fmd_errclass(EFMD_MODULE));
255 	err |= nvlist_add_nvlist(nvl, FM_EREPORT_DETECTOR, fmri);
256 	err |= nvlist_add_uint64(nvl, FM_EREPORT_ENA, ena);
257 	err |= nvlist_add_string(nvl, FMD_ERR_MOD_MSG, msg);
258 
259 	if (mp->mod_fmri == NULL)
260 		nvlist_free(fmri);
261 
262 	if (oserr != 0) {
263 		err |= nvlist_add_int32(nvl, FMD_ERR_MOD_ERRNO, oserr);
264 		err |= nvlist_add_string(nvl, FMD_ERR_MOD_ERRCLASS,
265 		    fmd_errclass(oserr));
266 	}
267 
268 	if (err != 0)
269 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
270 
271 	return (nvl);
272 }
273 
274 nvlist_t *
275 fmd_protocol_xprt_ctl(fmd_module_t *mp, const char *class, uint8_t version)
276 {
277 	nvlist_t *nvl;
278 	int err = 0;
279 
280 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
281 		fmd_panic("failed to xalloc rsrc xprt nvlist");
282 
283 	err |= nvlist_add_uint8(nvl, FM_VERSION, version);
284 	err |= nvlist_add_string(nvl, FM_CLASS, class);
285 	err |= nvlist_add_nvlist(nvl, FM_RSRC_RESOURCE, mp->mod_fmri);
286 
287 	if (err != 0)
288 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
289 
290 	return (nvl);
291 }
292 
293 nvlist_t *
294 fmd_protocol_xprt_sub(fmd_module_t *mp,
295     const char *class, uint8_t version, const char *subclass)
296 {
297 	nvlist_t *nvl = fmd_protocol_xprt_ctl(mp, class, version);
298 	int err = nvlist_add_string(nvl, FM_RSRC_XPRT_SUBCLASS, subclass);
299 
300 	if (err != 0)
301 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
302 
303 	return (nvl);
304 }
305 
306 nvlist_t *
307 fmd_protocol_xprt_uuclose(fmd_module_t *mp, const char *class, uint8_t version,
308     const char *uuid)
309 {
310 	nvlist_t *nvl = fmd_protocol_xprt_ctl(mp, class, version);
311 	int err = nvlist_add_string(nvl, FM_RSRC_XPRT_UUID, uuid);
312 
313 	if (err != 0)
314 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
315 
316 	return (nvl);
317 }
318