xref: /titanic_52/usr/src/cmd/fm/fmd/common/fmd_protocol.c (revision d58fda4376e4bf67072ce2e69f6f47036f9dbb68)
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  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/fm/protocol.h>
30 #include <strings.h>
31 #include <alloca.h>
32 #include <stdio.h>
33 
34 #include <fmd_protocol.h>
35 #include <fmd_module.h>
36 #include <fmd_conf.h>
37 #include <fmd_subr.h>
38 #include <fmd_error.h>
39 #include <fmd_time.h>
40 #include <fmd.h>
41 
42 /*
43  * Create an FMRI authority element for the environment in which this instance
44  * of fmd is deployed.  This function is called once and the result is cached.
45  */
46 nvlist_t *
47 fmd_protocol_authority(void)
48 {
49 	const char *str;
50 	nvlist_t *nvl;
51 	int err = 0;
52 
53 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
54 		fmd_panic("failed to xalloc authority nvlist");
55 
56 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_FMRI_AUTH_VERSION);
57 	(void) fmd_conf_getprop(fmd.d_conf, "platform", &str);
58 	err |= nvlist_add_string(nvl, FM_FMRI_AUTH_PRODUCT, str);
59 
60 	if (fmd_conf_getprop(fmd.d_conf, "chassis", &str) == 0 && str != NULL)
61 		err |= nvlist_add_string(nvl, FM_FMRI_AUTH_CHASSIS, str);
62 
63 	if (fmd_conf_getprop(fmd.d_conf, "domain", &str) == 0 && str != NULL)
64 		err |= nvlist_add_string(nvl, FM_FMRI_AUTH_DOMAIN, str);
65 
66 	if (fmd_conf_getprop(fmd.d_conf, "server", &str) == 0 && str != NULL)
67 		err |= nvlist_add_string(nvl, FM_FMRI_AUTH_SERVER, str);
68 
69 	if (err != 0)
70 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
71 
72 	return (nvl);
73 }
74 
75 /*
76  * Create an FMRI for the specified module.  We use the cached authority
77  * nvlist saved in fmd.d_auth to fill in the authority member.
78  */
79 nvlist_t *
80 fmd_protocol_fmri_module(fmd_module_t *mp)
81 {
82 	nvlist_t *nvl;
83 	int err = 0;
84 
85 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
86 		fmd_panic("failed to xalloc diag-engine fmri nvlist");
87 
88 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_FMD_SCHEME_VERSION);
89 	err |= nvlist_add_string(nvl, FM_FMRI_SCHEME, FM_FMRI_SCHEME_FMD);
90 	err |= nvlist_add_nvlist(nvl, FM_FMRI_AUTHORITY, fmd.d_auth);
91 	err |= nvlist_add_string(nvl, FM_FMRI_FMD_NAME, mp->mod_name);
92 
93 	if (mp->mod_info != NULL) {
94 		err |= nvlist_add_string(nvl,
95 		    FM_FMRI_FMD_VERSION, mp->mod_info->fmdi_vers);
96 	}
97 
98 	if (err != 0)
99 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
100 
101 	return (nvl);
102 }
103 
104 nvlist_t *
105 fmd_protocol_fault(const char *class, uint8_t certainty,
106     nvlist_t *asru, nvlist_t *fru, nvlist_t *resource)
107 {
108 	nvlist_t *nvl;
109 	int err = 0;
110 
111 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
112 		fmd_panic("failed to xalloc fault nvlist");
113 
114 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_FAULT_VERSION);
115 	err |= nvlist_add_string(nvl, FM_CLASS, class);
116 	err |= nvlist_add_uint8(nvl, FM_FAULT_CERTAINTY, certainty);
117 
118 	if (asru != NULL)
119 		err |= nvlist_add_nvlist(nvl, FM_FAULT_ASRU, asru);
120 	if (fru != NULL)
121 		err |= nvlist_add_nvlist(nvl, FM_FAULT_FRU, fru);
122 	if (resource != NULL)
123 		err |= nvlist_add_nvlist(nvl, FM_FAULT_RESOURCE, resource);
124 
125 	if (err != 0)
126 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
127 
128 	return (nvl);
129 }
130 
131 nvlist_t *
132 fmd_protocol_suspects(nvlist_t *de_fmri,
133     const char *uuid, const char *code, uint_t argc, nvlist_t **argv, int domsg)
134 {
135 	struct timeval tv;
136 	int64_t tod[2];
137 	nvlist_t *nvl;
138 	int err = 0;
139 
140 	fmd_time_gettimeofday(&tv);
141 	tod[0] = tv.tv_sec;
142 	tod[1] = tv.tv_usec;
143 
144 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
145 		fmd_panic("failed to xalloc suspect list nvlist");
146 
147 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_SUSPECT_VERSION);
148 	err |= nvlist_add_string(nvl, FM_CLASS, FM_LIST_SUSPECT_CLASS);
149 	err |= nvlist_add_string(nvl, FM_SUSPECT_UUID, uuid);
150 	err |= nvlist_add_string(nvl, FM_SUSPECT_DIAG_CODE, code);
151 	err |= nvlist_add_int64_array(nvl, FM_SUSPECT_DIAG_TIME, tod, 2);
152 	err |= nvlist_add_nvlist(nvl, FM_SUSPECT_DE, de_fmri);
153 	err |= nvlist_add_uint32(nvl, FM_SUSPECT_FAULT_SZ, argc);
154 
155 	if (!domsg) {
156 		err |= nvlist_add_boolean_value(nvl, FM_SUSPECT_MESSAGE,
157 		    B_FALSE);
158 	}
159 
160 	if (argc != 0) {
161 		err |= nvlist_add_nvlist_array(nvl,
162 		    FM_SUSPECT_FAULT_LIST, argv, argc);
163 	}
164 
165 	if (err != 0)
166 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
167 
168 	return (nvl);
169 }
170 
171 nvlist_t *
172 fmd_protocol_resource(const char *class, nvlist_t *fmri, const char *uuid,
173     boolean_t faulty, boolean_t unusable, boolean_t message, nvlist_t *event)
174 {
175 	nvlist_t *nvl;
176 	int err = 0;
177 
178 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
179 		fmd_panic("failed to xalloc resource nvlist");
180 
181 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_RSRC_VERSION);
182 	err |= nvlist_add_string(nvl, FM_CLASS, class);
183 	err |= nvlist_add_nvlist(nvl, FM_RSRC_RESOURCE, fmri);
184 	err |= nvlist_add_string(nvl, FM_RSRC_ASRU_UUID, uuid);
185 	err |= nvlist_add_boolean_value(nvl, FM_RSRC_ASRU_FAULTY, faulty);
186 	err |= nvlist_add_boolean_value(nvl, FM_RSRC_ASRU_UNUSABLE, unusable);
187 	err |= nvlist_add_boolean_value(nvl, FM_SUSPECT_MESSAGE, message);
188 
189 	if (event != NULL)
190 		err |= nvlist_add_nvlist(nvl, FM_RSRC_ASRU_EVENT, event);
191 
192 	if (err != 0)
193 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
194 
195 	return (nvl);
196 }
197 
198 nvlist_t *
199 fmd_protocol_fmderror(int errnum, const char *format, va_list ap)
200 {
201 	uint64_t ena = fmd_ena();
202 	nvlist_t *nvl;
203 	int err = 0;
204 	char c, *msg;
205 	size_t len;
206 
207 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
208 		return (NULL);
209 
210 	len = vsnprintf(&c, 1, format, ap);
211 	msg = alloca(len + 1);
212 	(void) vsnprintf(msg, len + 1, format, ap);
213 
214 	if (msg[len] == '\n')
215 		msg[len] = '\0';
216 
217 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_EREPORT_VERSION);
218 	err |= nvlist_add_string(nvl, FM_CLASS, fmd_errclass(errnum));
219 	err |= nvlist_add_uint64(nvl, FM_EREPORT_ENA, ena);
220 	err |= nvlist_add_string(nvl, FMD_ERR_MOD_MSG, msg);
221 
222 	if (err != 0) {
223 		nvlist_free(nvl);
224 		return (NULL);
225 	}
226 
227 	return (nvl);
228 }
229 
230 nvlist_t *
231 fmd_protocol_moderror(fmd_module_t *mp, int oserr, const char *msg)
232 {
233 	uint64_t ena = fmd_ena();
234 	nvlist_t *nvl, *fmri;
235 	int err = 0;
236 
237 	if (nvlist_xalloc(&nvl, NV_UNIQUE_NAME, &fmd.d_nva) != 0)
238 		fmd_panic("failed to xalloc module error nvlist");
239 
240 	if (mp->mod_fmri == NULL)
241 		fmri = fmd_protocol_fmri_module(mp);
242 	else
243 		fmri = mp->mod_fmri;
244 
245 	err |= nvlist_add_uint8(nvl, FM_VERSION, FM_EREPORT_VERSION);
246 	err |= nvlist_add_string(nvl, FM_CLASS, fmd_errclass(EFMD_MODULE));
247 	err |= nvlist_add_nvlist(nvl, FM_EREPORT_DETECTOR, fmri);
248 	err |= nvlist_add_uint64(nvl, FM_EREPORT_ENA, ena);
249 	err |= nvlist_add_string(nvl, FMD_ERR_MOD_MSG, msg);
250 
251 	if (mp->mod_fmri == NULL)
252 		nvlist_free(fmri);
253 
254 	if (oserr != 0) {
255 		err |= nvlist_add_int32(nvl, FMD_ERR_MOD_ERRNO, oserr);
256 		err |= nvlist_add_string(nvl, FMD_ERR_MOD_ERRCLASS,
257 		    fmd_errclass(oserr));
258 	}
259 
260 	if (err != 0)
261 		fmd_panic("failed to populate nvlist: %s\n", fmd_strerror(err));
262 
263 	return (nvl);
264 }
265