xref: /illumos-gate/usr/src/lib/fm/libfmd_adm/common/fmd_adm.c (revision 516fc7f3e48e25d0375ea3f93ead33ec38bc597b)
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 <strings.h>
30 #include <stdlib.h>
31 #include <netdir.h>
32 #include <errno.h>
33 
34 #include <fmd_adm_impl.h>
35 #include <fmd_rpc_adm.h>
36 
37 static const uint_t _fmd_adm_bufsize = 128 * 1024;
38 
39 fmd_adm_t *
40 fmd_adm_open(const char *host, uint32_t prog, int version)
41 {
42 	fmd_adm_t *ap;
43 	CLIENT *c;
44 	int err;
45 	rpcvers_t v;
46 
47 	if (version != FMD_ADM_VERSION) {
48 		errno = ENOTSUP;
49 		return (NULL);
50 	}
51 
52 	if (host == NULL)
53 		host = HOST_SELF;
54 
55 	if (prog == FMD_ADM_PROGRAM)
56 		prog = FMD_ADM;
57 
58 	/*
59 	 * If we are connecting to the local host, attempt a door connection
60 	 * first.  If that fails or we need another host, fall through to
61 	 * using the standard clnt_create that iterates over all transports.
62 	 */
63 	if (strcmp(host, HOST_SELF) == 0)
64 		c = clnt_door_create(prog, FMD_ADM_VERSION_1, _fmd_adm_bufsize);
65 	else
66 		c = NULL;
67 
68 	if (c == NULL) {
69 		c = clnt_create_vers(host, prog, &v,
70 		    FMD_ADM_VERSION_1, FMD_ADM_VERSION_1, NULL);
71 	}
72 
73 	if (c == NULL) {
74 		errno = EPROTO;
75 		return (NULL);
76 	}
77 
78 	if ((ap = malloc(sizeof (fmd_adm_t))) == NULL) {
79 		err = errno;
80 		clnt_destroy(c);
81 		errno = err;
82 		return (NULL);
83 	}
84 
85 	ap->adm_clnt = c;
86 	ap->adm_version = version;
87 	ap->adm_svcerr = 0;
88 	ap->adm_errno = 0;
89 
90 	return (ap);
91 }
92 
93 void
94 fmd_adm_close(fmd_adm_t *ap)
95 {
96 	if (ap == NULL)
97 		return; /* permit NULL to simply caller code */
98 
99 	clnt_destroy(ap->adm_clnt);
100 	free(ap);
101 }
102 
103 static const char *
104 fmd_adm_svc_errmsg(enum fmd_adm_error err)
105 {
106 	switch (err) {
107 	case FMD_ADM_ERR_NOMEM:
108 		return ("unable to perform request due to allocation failure");
109 	case FMD_ADM_ERR_PERM:
110 		return ("operation requires additional privilege");
111 	case FMD_ADM_ERR_MODSRCH:
112 		return ("specified module is not loaded in fault manager");
113 	case FMD_ADM_ERR_MODBUSY:
114 		return ("module is in use and cannot be unloaded");
115 	case FMD_ADM_ERR_MODFAIL:
116 		return ("module failed and can no longer export statistics");
117 	case FMD_ADM_ERR_MODNOENT:
118 		return ("file missing or cannot be accessed by fault manager");
119 	case FMD_ADM_ERR_MODEXIST:
120 		return ("module using same name is already loaded");
121 	case FMD_ADM_ERR_MODINIT:
122 		return ("module failed to initialize (consult fmd(1M) log)");
123 	case FMD_ADM_ERR_MODLOAD:
124 		return ("module failed to load (consult fmd(1M) log)");
125 	case FMD_ADM_ERR_RSRCSRCH:
126 		return ("specified resource is not cached by fault manager");
127 	case FMD_ADM_ERR_RSRCNOTF:
128 		return ("specified resource is not known to be faulty");
129 	case FMD_ADM_ERR_SERDSRCH:
130 		return ("specified serd engine not present in module");
131 	case FMD_ADM_ERR_SERDFIRED:
132 		return ("specified serd engine has already fired");
133 	case FMD_ADM_ERR_ROTSRCH:
134 		return ("invalid log file name");
135 	case FMD_ADM_ERR_ROTFAIL:
136 		return ("failed to rotate log file (consult fmd(1M) log)");
137 	case FMD_ADM_ERR_ROTBUSY:
138 		return ("log file is too busy to rotate (try again later)");
139 	case FMD_ADM_ERR_CASESRCH:
140 		return ("specified UUID is invalid or has been repaired");
141 	case FMD_ADM_ERR_CASEOPEN:
142 		return ("specified UUID is still being diagnosed");
143 	default:
144 		return ("unknown fault manager error");
145 	}
146 }
147 
148 const char *
149 fmd_adm_errmsg(fmd_adm_t *ap)
150 {
151 	if (ap == NULL) {
152 		switch (errno) {
153 		case ENOTSUP:
154 			return ("client requires newer libfmd_adm version");
155 		case EPROTO:
156 			return (clnt_spcreateerror("failed to connect to fmd"));
157 		}
158 	}
159 
160 	switch (ap ? ap->adm_errno : errno) {
161 	case EPROTO:
162 		return (clnt_sperror(ap->adm_clnt, "rpc call failed"));
163 	case EREMOTE:
164 		return (fmd_adm_svc_errmsg(ap->adm_svcerr));
165 	default:
166 		return (strerror(ap->adm_errno));
167 	}
168 }
169 
170 static int
171 fmd_adm_set_svcerr(fmd_adm_t *ap, enum fmd_adm_error err)
172 {
173 	if (err != 0) {
174 		ap->adm_svcerr = err;
175 		ap->adm_errno = EREMOTE;
176 		return (-1);
177 	} else {
178 		ap->adm_svcerr = err;
179 		ap->adm_errno = 0;
180 		return (0);
181 	}
182 }
183 
184 static int
185 fmd_adm_set_errno(fmd_adm_t *ap, int err)
186 {
187 	ap->adm_errno = err;
188 	errno = err;
189 	return (-1);
190 }
191 
192 static int
193 fmd_adm_stats_cmp(const void *lp, const void *rp)
194 {
195 	return (strcmp(((fmd_stat_t *)lp)->fmds_name,
196 	    ((fmd_stat_t *)rp)->fmds_name));
197 }
198 
199 int
200 fmd_adm_stats_read(fmd_adm_t *ap, const char *name, fmd_adm_stats_t *sp)
201 {
202 	struct fmd_rpc_modstat rms;
203 	enum clnt_stat cs;
204 
205 	if (sp == NULL)
206 		return (fmd_adm_set_errno(ap, EINVAL));
207 
208 	bzero(&rms, sizeof (rms)); /* tell xdr to allocate memory for us */
209 
210 	if (name != NULL)
211 		cs = fmd_adm_modcstat_1((char *)name, &rms, ap->adm_clnt);
212 	else
213 		cs = fmd_adm_modgstat_1(&rms, ap->adm_clnt);
214 
215 	if (cs != RPC_SUCCESS)
216 		return (fmd_adm_set_errno(ap, EPROTO));
217 
218 	if (rms.rms_err != 0) {
219 		xdr_free(xdr_fmd_rpc_modstat, (char *)&rms);
220 		return (fmd_adm_set_svcerr(ap, rms.rms_err));
221 	}
222 
223 	sp->ams_buf = rms.rms_buf.rms_buf_val;
224 	sp->ams_len = rms.rms_buf.rms_buf_len;
225 
226 	if (sp->ams_len != 0) {
227 		qsort(sp->ams_buf, sp->ams_len,
228 		    sizeof (fmd_stat_t), fmd_adm_stats_cmp);
229 	}
230 
231 	return (0);
232 }
233 
234 int
235 fmd_adm_stats_free(fmd_adm_t *ap, fmd_adm_stats_t *sp)
236 {
237 	struct fmd_rpc_modstat rms;
238 
239 	if (sp == NULL)
240 		return (fmd_adm_set_errno(ap, EINVAL));
241 
242 	rms.rms_buf.rms_buf_val = sp->ams_buf;
243 	rms.rms_buf.rms_buf_len = sp->ams_len;
244 	rms.rms_err = 0;
245 
246 	xdr_free(xdr_fmd_rpc_modstat, (char *)&rms);
247 	bzero(sp, sizeof (fmd_adm_stats_t));
248 
249 	return (0);
250 }
251 
252 static int
253 fmd_adm_module_cmp(const void *lp, const void *rp)
254 {
255 	return (strcmp((*(struct fmd_rpc_modinfo **)lp)->rmi_name,
256 	    (*(struct fmd_rpc_modinfo **)rp)->rmi_name));
257 }
258 
259 int
260 fmd_adm_module_iter(fmd_adm_t *ap, fmd_adm_module_f *func, void *arg)
261 {
262 	struct fmd_rpc_modinfo *rmi, **rms, **rmp;
263 	struct fmd_rpc_modlist rml;
264 	fmd_adm_modinfo_t ami;
265 
266 	bzero(&rml, sizeof (rml)); /* tell xdr to allocate memory for us */
267 
268 	if (fmd_adm_modinfo_1(&rml, ap->adm_clnt) != RPC_SUCCESS)
269 		return (fmd_adm_set_errno(ap, EPROTO));
270 
271 	if (rml.rml_err != 0 || rml.rml_len == 0) {
272 		xdr_free(xdr_fmd_rpc_modlist, (char *)&rml);
273 		return (fmd_adm_set_svcerr(ap, rml.rml_err));
274 	}
275 
276 	if ((rms = rmp = malloc(sizeof (void *) * rml.rml_len)) == NULL) {
277 		xdr_free(xdr_fmd_rpc_modlist, (char *)&rml);
278 		return (fmd_adm_set_errno(ap, EAGAIN));
279 	}
280 
281 	for (rmi = rml.rml_list; rmi != NULL; rmi = rmi->rmi_next)
282 		*rmp++ = rmi; /* store copy of pointer in array for sorting */
283 
284 	qsort(rms, rml.rml_len, sizeof (void *), fmd_adm_module_cmp);
285 
286 	for (rmp = rms; rmp < rms + rml.rml_len; rmp++) {
287 		rmi = *rmp;
288 
289 		ami.ami_name = rmi->rmi_name;
290 		ami.ami_desc = rmi->rmi_desc;
291 		ami.ami_vers = rmi->rmi_vers;
292 		ami.ami_flags = 0;
293 
294 		if (rmi->rmi_faulty)
295 			ami.ami_flags |= FMD_ADM_MOD_FAILED;
296 
297 		if (func(&ami, arg) != 0)
298 			break;
299 	}
300 
301 	free(rms);
302 	xdr_free(xdr_fmd_rpc_modlist, (char *)&rml);
303 	return (0);
304 }
305 
306 int
307 fmd_adm_module_load(fmd_adm_t *ap, const char *path)
308 {
309 	char *str = (char *)path;
310 	int err;
311 
312 	if (path == NULL || path[0] != '/')
313 		return (fmd_adm_set_errno(ap, EINVAL));
314 
315 	if (fmd_adm_modload_1(str, &err, ap->adm_clnt) != RPC_SUCCESS)
316 		return (fmd_adm_set_errno(ap, EPROTO));
317 
318 	return (fmd_adm_set_svcerr(ap, err));
319 }
320 
321 int
322 fmd_adm_module_unload(fmd_adm_t *ap, const char *name)
323 {
324 	char *str = (char *)name;
325 	int err;
326 
327 	if (name == NULL || strchr(name, '/') != NULL)
328 		return (fmd_adm_set_errno(ap, EINVAL));
329 
330 	if (fmd_adm_modunload_1(str, &err, ap->adm_clnt) != RPC_SUCCESS)
331 		return (fmd_adm_set_errno(ap, EPROTO));
332 
333 	return (fmd_adm_set_svcerr(ap, err));
334 }
335 
336 int
337 fmd_adm_module_reset(fmd_adm_t *ap, const char *name)
338 {
339 	char *str = (char *)name;
340 	int err;
341 
342 	if (name == NULL || strchr(name, '/') != NULL)
343 		return (fmd_adm_set_errno(ap, EINVAL));
344 
345 	if (fmd_adm_modreset_1(str, &err, ap->adm_clnt) != RPC_SUCCESS)
346 		return (fmd_adm_set_errno(ap, EPROTO));
347 
348 	return (fmd_adm_set_svcerr(ap, err));
349 }
350 
351 int
352 fmd_adm_module_gc(fmd_adm_t *ap, const char *name)
353 {
354 	char *str = (char *)name;
355 	int err;
356 
357 	if (name == NULL || strchr(name, '/') != NULL)
358 		return (fmd_adm_set_errno(ap, EINVAL));
359 
360 	if (fmd_adm_modgc_1(str, &err, ap->adm_clnt) != RPC_SUCCESS)
361 		return (fmd_adm_set_errno(ap, EPROTO));
362 
363 	return (fmd_adm_set_svcerr(ap, err));
364 }
365 
366 int
367 fmd_adm_module_stats(fmd_adm_t *ap, const char *name, fmd_adm_stats_t *sp)
368 {
369 	struct fmd_rpc_modstat rms;
370 
371 	if (name == NULL || sp == NULL)
372 		return (fmd_adm_set_errno(ap, EINVAL));
373 
374 	bzero(&rms, sizeof (rms)); /* tell xdr to allocate memory for us */
375 
376 	if (fmd_adm_moddstat_1((char *)name, &rms, ap->adm_clnt) != RPC_SUCCESS)
377 		return (fmd_adm_set_errno(ap, EPROTO));
378 
379 	if (rms.rms_err != 0) {
380 		xdr_free(xdr_fmd_rpc_modstat, (char *)&rms);
381 		return (fmd_adm_set_svcerr(ap, rms.rms_err));
382 	}
383 
384 	sp->ams_buf = rms.rms_buf.rms_buf_val;
385 	sp->ams_len = rms.rms_buf.rms_buf_len;
386 
387 	return (0);
388 }
389 
390 static int
391 fmd_adm_rsrc_cmp(const void *lp, const void *rp)
392 {
393 	return (strcmp(*(char **)lp, *(char **)rp));
394 }
395 
396 int
397 fmd_adm_rsrc_iter(fmd_adm_t *ap, int all, fmd_adm_rsrc_f *func, void *arg)
398 {
399 	struct fmd_rpc_rsrclist rrl;
400 	struct fmd_rpc_rsrcinfo rri;
401 	fmd_adm_rsrcinfo_t ari;
402 	char **fmris, *p;
403 	int i, rv;
404 
405 	bzero(&rrl, sizeof (rrl)); /* tell xdr to allocate memory for us */
406 
407 	if (fmd_adm_rsrclist_1(all, &rrl, ap->adm_clnt) != RPC_SUCCESS)
408 		return (fmd_adm_set_errno(ap, EPROTO));
409 
410 	if (rrl.rrl_err != 0) {
411 		xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
412 		return (fmd_adm_set_svcerr(ap, rrl.rrl_err));
413 	}
414 
415 	if ((fmris = malloc(sizeof (char *) * rrl.rrl_cnt)) == NULL) {
416 		xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
417 		return (fmd_adm_set_errno(ap, EAGAIN));
418 	}
419 
420 	/*
421 	 * The fmd_adm_rsrclist_1 request returns an opaque XDR buffer that is
422 	 * a string table of FMRIs (e.g. "fmriA\0fmriB\0...") where rrl_cnt is
423 	 * the number of strings in the table and rrl_buf_val is its address.
424 	 * We construct an array of pointers into the string table and sort it.
425 	 */
426 	p = rrl.rrl_buf.rrl_buf_val;
427 
428 	for (i = 0; i < rrl.rrl_cnt; i++, p += strlen(p) + 1)
429 		fmris[i] = p; /* store fmri pointer in array for sorting */
430 
431 	qsort(fmris, rrl.rrl_cnt, sizeof (char *), fmd_adm_rsrc_cmp);
432 
433 	/*
434 	 * For each FMRI in the resource cache snapshot, use fmd_adm_rsrcinfo_1
435 	 * to get more information and the invoke the callback function.  If
436 	 * FMD_ADM_ERR_RSRCSRCH is returned, the FMRI has been purged from the
437 	 * cache since our snapshot: this error is therefore silently ignored.
438 	 */
439 	for (i = 0; i < rrl.rrl_cnt; i++) {
440 		bzero(&rri, sizeof (rri));
441 
442 		if (fmd_adm_rsrcinfo_1(fmris[i], &rri,
443 		    ap->adm_clnt) != RPC_SUCCESS) {
444 			free(fmris);
445 			xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
446 			return (fmd_adm_set_errno(ap, EPROTO));
447 		}
448 
449 		if (rri.rri_err != 0 && rri.rri_err != FMD_ADM_ERR_RSRCSRCH) {
450 			xdr_free(xdr_fmd_rpc_rsrcinfo, (char *)&rri);
451 			free(fmris);
452 			xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
453 			return (fmd_adm_set_svcerr(ap, rri.rri_err));
454 		}
455 
456 		if (rri.rri_err == FMD_ADM_ERR_RSRCSRCH) {
457 			xdr_free(xdr_fmd_rpc_rsrcinfo, (char *)&rri);
458 			continue;
459 		}
460 
461 		ari.ari_fmri = rri.rri_fmri;
462 		ari.ari_uuid = rri.rri_uuid;
463 		ari.ari_case = rri.rri_case;
464 		ari.ari_flags = 0;
465 
466 		if (rri.rri_faulty)
467 			ari.ari_flags |= FMD_ADM_RSRC_FAULTY;
468 		if (rri.rri_unusable)
469 			ari.ari_flags |= FMD_ADM_RSRC_UNUSABLE;
470 		if (rri.rri_invisible)
471 			ari.ari_flags |= FMD_ADM_RSRC_INVISIBLE;
472 
473 		rv = func(&ari, arg);
474 		xdr_free(xdr_fmd_rpc_rsrcinfo, (char *)&rri);
475 
476 		if (rv != 0)
477 			break;
478 	}
479 
480 	free(fmris);
481 	xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
482 	return (0);
483 }
484 
485 int
486 fmd_adm_rsrc_flush(fmd_adm_t *ap, const char *fmri)
487 {
488 	char *str = (char *)fmri;
489 	int err;
490 
491 	if (fmri == NULL)
492 		return (fmd_adm_set_errno(ap, EINVAL));
493 
494 	if (fmd_adm_rsrcflush_1(str, &err, ap->adm_clnt) != RPC_SUCCESS)
495 		return (fmd_adm_set_errno(ap, EPROTO));
496 
497 	return (fmd_adm_set_svcerr(ap, err));
498 }
499 
500 int
501 fmd_adm_rsrc_repair(fmd_adm_t *ap, const char *fmri)
502 {
503 	char *str = (char *)fmri;
504 	int err;
505 
506 	if (fmri == NULL)
507 		return (fmd_adm_set_errno(ap, EINVAL));
508 
509 	if (fmd_adm_rsrcrepair_1(str, &err, ap->adm_clnt) != RPC_SUCCESS)
510 		return (fmd_adm_set_errno(ap, EPROTO));
511 
512 	return (fmd_adm_set_svcerr(ap, err));
513 }
514 
515 int
516 fmd_adm_case_repair(fmd_adm_t *ap, const char *uuid)
517 {
518 	char *str = (char *)uuid;
519 	int err;
520 
521 	if (uuid == NULL)
522 		return (fmd_adm_set_errno(ap, EINVAL));
523 
524 	if (fmd_adm_caserepair_1(str, &err, ap->adm_clnt) != RPC_SUCCESS)
525 		return (fmd_adm_set_errno(ap, EPROTO));
526 
527 	return (fmd_adm_set_svcerr(ap, err));
528 }
529 
530 static int
531 fmd_adm_serd_cmp(const void *lp, const void *rp)
532 {
533 	return (strcmp((*(struct fmd_rpc_serdinfo **)lp)->rsi_name,
534 	    (*(struct fmd_rpc_serdinfo **)rp)->rsi_name));
535 }
536 
537 int
538 fmd_adm_serd_iter(fmd_adm_t *ap, const char *name,
539     fmd_adm_serd_f *func, void *arg)
540 {
541 	struct fmd_rpc_serdinfo *rsi, **ris, **rip;
542 	struct fmd_rpc_serdlist rsl;
543 	fmd_adm_serdinfo_t asi;
544 
545 	bzero(&rsl, sizeof (rsl)); /* tell xdr to allocate memory for us */
546 
547 	if (fmd_adm_serdinfo_1((char *)name, &rsl, ap->adm_clnt) != RPC_SUCCESS)
548 		return (fmd_adm_set_errno(ap, EPROTO));
549 
550 	if (rsl.rsl_err != 0 || rsl.rsl_len == 0) {
551 		xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl);
552 		return (fmd_adm_set_svcerr(ap, rsl.rsl_err));
553 	}
554 
555 	if ((ris = rip = malloc(sizeof (void *) * rsl.rsl_len)) == NULL) {
556 		xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl);
557 		return (fmd_adm_set_errno(ap, EAGAIN));
558 	}
559 
560 	for (rsi = rsl.rsl_list; rsi != NULL; rsi = rsi->rsi_next)
561 		*rip++ = rsi; /* store copy of pointer in array for sorting */
562 
563 	qsort(ris, rsl.rsl_len, sizeof (void *), fmd_adm_serd_cmp);
564 
565 	for (rip = ris; rip < ris + rsl.rsl_len; rip++) {
566 		rsi = *rip;
567 
568 		asi.asi_name = rsi->rsi_name;
569 		asi.asi_delta = rsi->rsi_delta;
570 		asi.asi_n = rsi->rsi_n;
571 		asi.asi_t = rsi->rsi_t;
572 		asi.asi_count = rsi->rsi_count;
573 		asi.asi_flags = 0;
574 
575 		if (rsi->rsi_fired)
576 			asi.asi_flags |= FMD_ADM_SERD_FIRED;
577 
578 		if (func(&asi, arg) != 0)
579 			break;
580 	}
581 
582 	free(ris);
583 	xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl);
584 	return (0);
585 }
586 
587 int
588 fmd_adm_serd_reset(fmd_adm_t *ap, const char *mod, const char *name)
589 {
590 	char *s1 = (char *)mod, *s2 = (char *)name;
591 	int err;
592 
593 	if (mod == NULL || name == NULL || strchr(mod, '/') != NULL)
594 		return (fmd_adm_set_errno(ap, EINVAL));
595 
596 	if (fmd_adm_serdreset_1(s1, s2, &err, ap->adm_clnt) != RPC_SUCCESS)
597 		return (fmd_adm_set_errno(ap, EPROTO));
598 
599 	return (fmd_adm_set_svcerr(ap, err));
600 }
601 
602 int
603 fmd_adm_log_rotate(fmd_adm_t *ap, const char *log)
604 {
605 	int err;
606 
607 	if (log == NULL)
608 		return (fmd_adm_set_errno(ap, EINVAL));
609 
610 	if (fmd_adm_logrotate_1((char *)log, &err, ap->adm_clnt) != RPC_SUCCESS)
611 		return (fmd_adm_set_errno(ap, EPROTO));
612 
613 	return (fmd_adm_set_svcerr(ap, err));
614 }
615 
616 /*
617  * Custom XDR routine for our API structure fmd_stat_t.  This function must
618  * match the definition of fmd_stat_t in <fm/fmd_api.h> and must also match
619  * the corresponding routine in usr/src/cmd/fm/fmd/common/fmd_rpc_adm.c.
620  */
621 bool_t
622 xdr_fmd_stat(XDR *xp, fmd_stat_t *sp)
623 {
624 	bool_t rv = TRUE;
625 
626 	rv &= xdr_opaque(xp, sp->fmds_name, sizeof (sp->fmds_name));
627 	rv &= xdr_u_int(xp, &sp->fmds_type);
628 	rv &= xdr_opaque(xp, sp->fmds_desc, sizeof (sp->fmds_desc));
629 
630 	switch (sp->fmds_type) {
631 	case FMD_TYPE_BOOL:
632 		rv &= xdr_int(xp, &sp->fmds_value.bool);
633 		break;
634 	case FMD_TYPE_INT32:
635 		rv &= xdr_int32_t(xp, &sp->fmds_value.i32);
636 		break;
637 	case FMD_TYPE_UINT32:
638 		rv &= xdr_uint32_t(xp, &sp->fmds_value.ui32);
639 		break;
640 	case FMD_TYPE_INT64:
641 		rv &= xdr_int64_t(xp, &sp->fmds_value.i64);
642 		break;
643 	case FMD_TYPE_UINT64:
644 	case FMD_TYPE_TIME:
645 	case FMD_TYPE_SIZE:
646 		rv &= xdr_uint64_t(xp, &sp->fmds_value.ui64);
647 		break;
648 	case FMD_TYPE_STRING:
649 		rv &= xdr_string(xp, &sp->fmds_value.str, ~0);
650 		break;
651 	}
652 
653 	return (rv);
654 }
655