17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5749f21d3Swesolows  * Common Development and Distribution License (the "License").
6749f21d3Swesolows  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21d9638e54Smws 
227c478bd9Sstevel@tonic-gate /*
236e1fa242SStephen Hanson  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <strings.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <netdir.h>
307c478bd9Sstevel@tonic-gate #include <errno.h>
31749f21d3Swesolows #include <alloca.h>
32749f21d3Swesolows #include <locale.h>
33749f21d3Swesolows #include <uuid/uuid.h>
347c478bd9Sstevel@tonic-gate 
35749f21d3Swesolows #include <sys/fm/protocol.h>
367c478bd9Sstevel@tonic-gate #include <fmd_adm_impl.h>
377c478bd9Sstevel@tonic-gate #include <fmd_rpc_adm.h>
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate static const uint_t _fmd_adm_bufsize = 128 * 1024;
40654b400cSJoshua M. Clulow static const char _url_fallback[] = "http://illumos.org/msg/";
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate fmd_adm_t *
fmd_adm_open(const char * host,uint32_t prog,int version)437c478bd9Sstevel@tonic-gate fmd_adm_open(const char *host, uint32_t prog, int version)
447c478bd9Sstevel@tonic-gate {
457c478bd9Sstevel@tonic-gate 	fmd_adm_t *ap;
467c478bd9Sstevel@tonic-gate 	CLIENT *c;
477c478bd9Sstevel@tonic-gate 	rpcvers_t v;
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate 	if (version != FMD_ADM_VERSION) {
507c478bd9Sstevel@tonic-gate 		errno = ENOTSUP;
517c478bd9Sstevel@tonic-gate 		return (NULL);
527c478bd9Sstevel@tonic-gate 	}
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate 	if (host == NULL)
557c478bd9Sstevel@tonic-gate 		host = HOST_SELF;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate 	if (prog == FMD_ADM_PROGRAM)
587c478bd9Sstevel@tonic-gate 		prog = FMD_ADM;
597c478bd9Sstevel@tonic-gate 
60d7448364Seschrock 	if ((ap = malloc(sizeof (fmd_adm_t))) == NULL)
61d7448364Seschrock 		return (NULL);
627c478bd9Sstevel@tonic-gate 
63d7448364Seschrock 	if (strcmp(host, HOST_SELF) == 0) {
64d7448364Seschrock 		c = clnt_door_create(prog, FMD_ADM_VERSION_1, _fmd_adm_bufsize);
65d7448364Seschrock 		ap->adm_maxretries = 1;
66d7448364Seschrock 	} else {
677c478bd9Sstevel@tonic-gate 		c = clnt_create_vers(host, prog, &v,
687c478bd9Sstevel@tonic-gate 		    FMD_ADM_VERSION_1, FMD_ADM_VERSION_1, NULL);
69d7448364Seschrock 		ap->adm_maxretries = 0;
707c478bd9Sstevel@tonic-gate 	}
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 	if (c == NULL) {
737c478bd9Sstevel@tonic-gate 		errno = EPROTO;
74d7448364Seschrock 		free(ap);
757c478bd9Sstevel@tonic-gate 		return (NULL);
767c478bd9Sstevel@tonic-gate 	}
777c478bd9Sstevel@tonic-gate 
78d7448364Seschrock 	ap->adm_prog = prog;
797c478bd9Sstevel@tonic-gate 	ap->adm_clnt = c;
807c478bd9Sstevel@tonic-gate 	ap->adm_version = version;
817c478bd9Sstevel@tonic-gate 	ap->adm_svcerr = 0;
827c478bd9Sstevel@tonic-gate 	ap->adm_errno = 0;
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	return (ap);
857c478bd9Sstevel@tonic-gate }
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate void
fmd_adm_close(fmd_adm_t * ap)887c478bd9Sstevel@tonic-gate fmd_adm_close(fmd_adm_t *ap)
897c478bd9Sstevel@tonic-gate {
907c478bd9Sstevel@tonic-gate 	if (ap == NULL)
917c478bd9Sstevel@tonic-gate 		return; /* permit NULL to simply caller code */
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	clnt_destroy(ap->adm_clnt);
947c478bd9Sstevel@tonic-gate 	free(ap);
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate static const char *
fmd_adm_svc_errmsg(enum fmd_adm_error err)987c478bd9Sstevel@tonic-gate fmd_adm_svc_errmsg(enum fmd_adm_error err)
997c478bd9Sstevel@tonic-gate {
1007c478bd9Sstevel@tonic-gate 	switch (err) {
1017c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_NOMEM:
1027c478bd9Sstevel@tonic-gate 		return ("unable to perform request due to allocation failure");
1037c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_PERM:
1047c478bd9Sstevel@tonic-gate 		return ("operation requires additional privilege");
1057c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_MODSRCH:
1067c478bd9Sstevel@tonic-gate 		return ("specified module is not loaded in fault manager");
1077c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_MODBUSY:
1087c478bd9Sstevel@tonic-gate 		return ("module is in use and cannot be unloaded");
1097c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_MODFAIL:
1107c478bd9Sstevel@tonic-gate 		return ("module failed and can no longer export statistics");
1117c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_MODNOENT:
1127c478bd9Sstevel@tonic-gate 		return ("file missing or cannot be accessed by fault manager");
1137c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_MODEXIST:
1147c478bd9Sstevel@tonic-gate 		return ("module using same name is already loaded");
1157c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_MODINIT:
116*bbf21555SRichard Lowe 		return ("module failed to initialize (consult fmd(8) log)");
1177c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_MODLOAD:
118*bbf21555SRichard Lowe 		return ("module failed to load (consult fmd(8) log)");
1197c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_RSRCSRCH:
1207c478bd9Sstevel@tonic-gate 		return ("specified resource is not cached by fault manager");
1217c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_RSRCNOTF:
1227c478bd9Sstevel@tonic-gate 		return ("specified resource is not known to be faulty");
1237c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_SERDSRCH:
1247c478bd9Sstevel@tonic-gate 		return ("specified serd engine not present in module");
1257c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_SERDFIRED:
1267c478bd9Sstevel@tonic-gate 		return ("specified serd engine has already fired");
1277c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_ROTSRCH:
1287c478bd9Sstevel@tonic-gate 		return ("invalid log file name");
1297c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_ROTFAIL:
130*bbf21555SRichard Lowe 		return ("failed to rotate log file (consult fmd(8) log)");
1317c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_ROTBUSY:
1327c478bd9Sstevel@tonic-gate 		return ("log file is too busy to rotate (try again later)");
1337c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_CASESRCH:
1347c478bd9Sstevel@tonic-gate 		return ("specified UUID is invalid or has been repaired");
1357c478bd9Sstevel@tonic-gate 	case FMD_ADM_ERR_CASEOPEN:
1367c478bd9Sstevel@tonic-gate 		return ("specified UUID is still being diagnosed");
137d9638e54Smws 	case FMD_ADM_ERR_XPRTSRCH:
138d9638e54Smws 		return ("specified transport ID is invalid or has been closed");
139d9638e54Smws 	case FMD_ADM_ERR_CASEXPRT:
140d9638e54Smws 		return ("specified UUID is owned by a different fault manager");
1416e1fa242SStephen Hanson 	case FMD_ADM_ERR_RSRCNOTR:
1426e1fa242SStephen Hanson 		return ("specified resource has not been replaced");
1437c478bd9Sstevel@tonic-gate 	default:
1447c478bd9Sstevel@tonic-gate 		return ("unknown fault manager error");
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate const char *
fmd_adm_errmsg(fmd_adm_t * ap)1497c478bd9Sstevel@tonic-gate fmd_adm_errmsg(fmd_adm_t *ap)
1507c478bd9Sstevel@tonic-gate {
1517c478bd9Sstevel@tonic-gate 	if (ap == NULL) {
1527c478bd9Sstevel@tonic-gate 		switch (errno) {
1537c478bd9Sstevel@tonic-gate 		case ENOTSUP:
1547c478bd9Sstevel@tonic-gate 			return ("client requires newer libfmd_adm version");
1557c478bd9Sstevel@tonic-gate 		case EPROTO:
1567c478bd9Sstevel@tonic-gate 			return (clnt_spcreateerror("failed to connect to fmd"));
1577c478bd9Sstevel@tonic-gate 		}
1587c478bd9Sstevel@tonic-gate 	}
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	switch (ap ? ap->adm_errno : errno) {
1617c478bd9Sstevel@tonic-gate 	case EPROTO:
1627c478bd9Sstevel@tonic-gate 		return (clnt_sperror(ap->adm_clnt, "rpc call failed"));
1637c478bd9Sstevel@tonic-gate 	case EREMOTE:
1647c478bd9Sstevel@tonic-gate 		return (fmd_adm_svc_errmsg(ap->adm_svcerr));
1657c478bd9Sstevel@tonic-gate 	default:
1667c478bd9Sstevel@tonic-gate 		return (strerror(ap->adm_errno));
1677c478bd9Sstevel@tonic-gate 	}
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate static int
fmd_adm_set_svcerr(fmd_adm_t * ap,enum fmd_adm_error err)1717c478bd9Sstevel@tonic-gate fmd_adm_set_svcerr(fmd_adm_t *ap, enum fmd_adm_error err)
1727c478bd9Sstevel@tonic-gate {
1737c478bd9Sstevel@tonic-gate 	if (err != 0) {
1747c478bd9Sstevel@tonic-gate 		ap->adm_svcerr = err;
1757c478bd9Sstevel@tonic-gate 		ap->adm_errno = EREMOTE;
1767c478bd9Sstevel@tonic-gate 		return (-1);
1777c478bd9Sstevel@tonic-gate 	} else {
1787c478bd9Sstevel@tonic-gate 		ap->adm_svcerr = err;
1797c478bd9Sstevel@tonic-gate 		ap->adm_errno = 0;
1807c478bd9Sstevel@tonic-gate 		return (0);
1817c478bd9Sstevel@tonic-gate 	}
1827c478bd9Sstevel@tonic-gate }
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate static int
fmd_adm_set_errno(fmd_adm_t * ap,int err)1857c478bd9Sstevel@tonic-gate fmd_adm_set_errno(fmd_adm_t *ap, int err)
1867c478bd9Sstevel@tonic-gate {
1877c478bd9Sstevel@tonic-gate 	ap->adm_errno = err;
1887c478bd9Sstevel@tonic-gate 	errno = err;
1897c478bd9Sstevel@tonic-gate 	return (-1);
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate static int
fmd_adm_stats_cmp(const void * lp,const void * rp)1937c478bd9Sstevel@tonic-gate fmd_adm_stats_cmp(const void *lp, const void *rp)
1947c478bd9Sstevel@tonic-gate {
1957c478bd9Sstevel@tonic-gate 	return (strcmp(((fmd_stat_t *)lp)->fmds_name,
1967c478bd9Sstevel@tonic-gate 	    ((fmd_stat_t *)rp)->fmds_name));
1977c478bd9Sstevel@tonic-gate }
1987c478bd9Sstevel@tonic-gate 
199d7448364Seschrock /*
200d7448364Seschrock  * If the server (fmd) is restarted, this will cause all future door calls to
201d7448364Seschrock  * fail.  Unfortunately, once the server comes back up, we have no way of
202d7448364Seschrock  * reestablishing the connection.  To get around this, if the error indicates
203d7448364Seschrock  * that the RPC call failed, we reopen the client handle and try again.  For
204d7448364Seschrock  * simplicity we only deal with the door case, as it's unclear whether the
205d7448364Seschrock  * remote case suffers from the same pathology.
206d7448364Seschrock  */
207d7448364Seschrock boolean_t
fmd_adm_retry(fmd_adm_t * ap,enum clnt_stat cs,uint_t * retries)208d7448364Seschrock fmd_adm_retry(fmd_adm_t *ap, enum clnt_stat cs, uint_t *retries)
209d7448364Seschrock {
210d7448364Seschrock 	CLIENT *c;
211d7448364Seschrock 	struct rpc_err err;
212d7448364Seschrock 
213d7448364Seschrock 	if (cs == RPC_SUCCESS || *retries == ap->adm_maxretries)
214d7448364Seschrock 		return (B_FALSE);
215d7448364Seschrock 
216d7448364Seschrock 	clnt_geterr(ap->adm_clnt, &err);
217d7448364Seschrock 	if (err.re_status != RPC_CANTSEND)
218d7448364Seschrock 		return (B_FALSE);
219d7448364Seschrock 
220d7448364Seschrock 	if ((c = clnt_door_create(ap->adm_prog, FMD_ADM_VERSION_1,
221d7448364Seschrock 	    _fmd_adm_bufsize)) == NULL)
222d7448364Seschrock 		return (B_FALSE);
223d7448364Seschrock 
224d7448364Seschrock 	(*retries)++;
225d7448364Seschrock 
226d7448364Seschrock 	clnt_destroy(ap->adm_clnt);
227d7448364Seschrock 	ap->adm_clnt = c;
228d7448364Seschrock 
229d7448364Seschrock 	return (B_TRUE);
230d7448364Seschrock }
231d7448364Seschrock 
2327c478bd9Sstevel@tonic-gate int
fmd_adm_stats_read(fmd_adm_t * ap,const char * name,fmd_adm_stats_t * sp)2337c478bd9Sstevel@tonic-gate fmd_adm_stats_read(fmd_adm_t *ap, const char *name, fmd_adm_stats_t *sp)
2347c478bd9Sstevel@tonic-gate {
2357c478bd9Sstevel@tonic-gate 	struct fmd_rpc_modstat rms;
2367c478bd9Sstevel@tonic-gate 	enum clnt_stat cs;
237d7448364Seschrock 	uint_t retries = 0;
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	if (sp == NULL)
2407c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EINVAL));
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	bzero(&rms, sizeof (rms)); /* tell xdr to allocate memory for us */
2437c478bd9Sstevel@tonic-gate 
244d7448364Seschrock 	do {
245d7448364Seschrock 		if (name != NULL)
246d7448364Seschrock 			cs = fmd_adm_modcstat_1((char *)name, &rms,
247d7448364Seschrock 			    ap->adm_clnt);
248d7448364Seschrock 		else
249d7448364Seschrock 			cs = fmd_adm_modgstat_1(&rms, ap->adm_clnt);
250d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	if (cs != RPC_SUCCESS)
2537c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EPROTO));
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	if (rms.rms_err != 0) {
2567c478bd9Sstevel@tonic-gate 		xdr_free(xdr_fmd_rpc_modstat, (char *)&rms);
2577c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_svcerr(ap, rms.rms_err));
2587c478bd9Sstevel@tonic-gate 	}
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 	sp->ams_buf = rms.rms_buf.rms_buf_val;
2617c478bd9Sstevel@tonic-gate 	sp->ams_len = rms.rms_buf.rms_buf_len;
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	if (sp->ams_len != 0) {
2647c478bd9Sstevel@tonic-gate 		qsort(sp->ams_buf, sp->ams_len,
2657c478bd9Sstevel@tonic-gate 		    sizeof (fmd_stat_t), fmd_adm_stats_cmp);
2667c478bd9Sstevel@tonic-gate 	}
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	return (0);
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate int
fmd_adm_stats_free(fmd_adm_t * ap,fmd_adm_stats_t * sp)2727c478bd9Sstevel@tonic-gate fmd_adm_stats_free(fmd_adm_t *ap, fmd_adm_stats_t *sp)
2737c478bd9Sstevel@tonic-gate {
2747c478bd9Sstevel@tonic-gate 	struct fmd_rpc_modstat rms;
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	if (sp == NULL)
2777c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EINVAL));
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	rms.rms_buf.rms_buf_val = sp->ams_buf;
2807c478bd9Sstevel@tonic-gate 	rms.rms_buf.rms_buf_len = sp->ams_len;
2817c478bd9Sstevel@tonic-gate 	rms.rms_err = 0;
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	xdr_free(xdr_fmd_rpc_modstat, (char *)&rms);
2847c478bd9Sstevel@tonic-gate 	bzero(sp, sizeof (fmd_adm_stats_t));
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	return (0);
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate static int
fmd_adm_module_cmp(const void * lp,const void * rp)2907c478bd9Sstevel@tonic-gate fmd_adm_module_cmp(const void *lp, const void *rp)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate 	return (strcmp((*(struct fmd_rpc_modinfo **)lp)->rmi_name,
2937c478bd9Sstevel@tonic-gate 	    (*(struct fmd_rpc_modinfo **)rp)->rmi_name));
2947c478bd9Sstevel@tonic-gate }
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate int
fmd_adm_module_iter(fmd_adm_t * ap,fmd_adm_module_f * func,void * arg)2977c478bd9Sstevel@tonic-gate fmd_adm_module_iter(fmd_adm_t *ap, fmd_adm_module_f *func, void *arg)
2987c478bd9Sstevel@tonic-gate {
2997c478bd9Sstevel@tonic-gate 	struct fmd_rpc_modinfo *rmi, **rms, **rmp;
3007c478bd9Sstevel@tonic-gate 	struct fmd_rpc_modlist rml;
3017c478bd9Sstevel@tonic-gate 	fmd_adm_modinfo_t ami;
302d7448364Seschrock 	enum clnt_stat cs;
303d7448364Seschrock 	uint_t retries = 0;
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	bzero(&rml, sizeof (rml)); /* tell xdr to allocate memory for us */
3067c478bd9Sstevel@tonic-gate 
307d7448364Seschrock 	do {
308d7448364Seschrock 		cs = fmd_adm_modinfo_1(&rml, ap->adm_clnt);
309d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
310d7448364Seschrock 
311d7448364Seschrock 	if (cs != RPC_SUCCESS)
3127c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EPROTO));
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	if (rml.rml_err != 0 || rml.rml_len == 0) {
3157c478bd9Sstevel@tonic-gate 		xdr_free(xdr_fmd_rpc_modlist, (char *)&rml);
3167c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_svcerr(ap, rml.rml_err));
3177c478bd9Sstevel@tonic-gate 	}
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	if ((rms = rmp = malloc(sizeof (void *) * rml.rml_len)) == NULL) {
3207c478bd9Sstevel@tonic-gate 		xdr_free(xdr_fmd_rpc_modlist, (char *)&rml);
3217c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EAGAIN));
3227c478bd9Sstevel@tonic-gate 	}
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	for (rmi = rml.rml_list; rmi != NULL; rmi = rmi->rmi_next)
3257c478bd9Sstevel@tonic-gate 		*rmp++ = rmi; /* store copy of pointer in array for sorting */
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	qsort(rms, rml.rml_len, sizeof (void *), fmd_adm_module_cmp);
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	for (rmp = rms; rmp < rms + rml.rml_len; rmp++) {
3307c478bd9Sstevel@tonic-gate 		rmi = *rmp;
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 		ami.ami_name = rmi->rmi_name;
3337c478bd9Sstevel@tonic-gate 		ami.ami_desc = rmi->rmi_desc;
3347c478bd9Sstevel@tonic-gate 		ami.ami_vers = rmi->rmi_vers;
3357c478bd9Sstevel@tonic-gate 		ami.ami_flags = 0;
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 		if (rmi->rmi_faulty)
3387c478bd9Sstevel@tonic-gate 			ami.ami_flags |= FMD_ADM_MOD_FAILED;
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 		if (func(&ami, arg) != 0)
3417c478bd9Sstevel@tonic-gate 			break;
3427c478bd9Sstevel@tonic-gate 	}
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	free(rms);
3457c478bd9Sstevel@tonic-gate 	xdr_free(xdr_fmd_rpc_modlist, (char *)&rml);
3467c478bd9Sstevel@tonic-gate 	return (0);
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate int
fmd_adm_module_load(fmd_adm_t * ap,const char * path)3507c478bd9Sstevel@tonic-gate fmd_adm_module_load(fmd_adm_t *ap, const char *path)
3517c478bd9Sstevel@tonic-gate {
3527c478bd9Sstevel@tonic-gate 	char *str = (char *)path;
3537c478bd9Sstevel@tonic-gate 	int err;
354d7448364Seschrock 	enum clnt_stat cs;
355d7448364Seschrock 	uint_t retries = 0;
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	if (path == NULL || path[0] != '/')
3587c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EINVAL));
3597c478bd9Sstevel@tonic-gate 
360d7448364Seschrock 	do {
361d7448364Seschrock 		cs = fmd_adm_modload_1(str, &err, ap->adm_clnt);
362d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
363d7448364Seschrock 
364d7448364Seschrock 	if (cs != RPC_SUCCESS)
3657c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EPROTO));
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	return (fmd_adm_set_svcerr(ap, err));
3687c478bd9Sstevel@tonic-gate }
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate int
fmd_adm_module_unload(fmd_adm_t * ap,const char * name)3717c478bd9Sstevel@tonic-gate fmd_adm_module_unload(fmd_adm_t *ap, const char *name)
3727c478bd9Sstevel@tonic-gate {
3737c478bd9Sstevel@tonic-gate 	char *str = (char *)name;
3747c478bd9Sstevel@tonic-gate 	int err;
375d7448364Seschrock 	enum clnt_stat cs;
376d7448364Seschrock 	uint_t retries = 0;
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	if (name == NULL || strchr(name, '/') != NULL)
3797c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EINVAL));
3807c478bd9Sstevel@tonic-gate 
381d7448364Seschrock 	do {
382d7448364Seschrock 		cs = fmd_adm_modunload_1(str, &err, ap->adm_clnt);
383d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
384d7448364Seschrock 
385d7448364Seschrock 	if (cs != RPC_SUCCESS)
3867c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EPROTO));
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	return (fmd_adm_set_svcerr(ap, err));
3897c478bd9Sstevel@tonic-gate }
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate int
fmd_adm_module_reset(fmd_adm_t * ap,const char * name)3927c478bd9Sstevel@tonic-gate fmd_adm_module_reset(fmd_adm_t *ap, const char *name)
3937c478bd9Sstevel@tonic-gate {
3947c478bd9Sstevel@tonic-gate 	char *str = (char *)name;
3957c478bd9Sstevel@tonic-gate 	int err;
396d7448364Seschrock 	enum clnt_stat cs;
397d7448364Seschrock 	uint_t retries = 0;
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	if (name == NULL || strchr(name, '/') != NULL)
4007c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EINVAL));
4017c478bd9Sstevel@tonic-gate 
402d7448364Seschrock 	do {
403d7448364Seschrock 		cs = fmd_adm_modreset_1(str, &err, ap->adm_clnt);
404d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
405d7448364Seschrock 
406d7448364Seschrock 	if (cs != RPC_SUCCESS)
4077c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EPROTO));
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	return (fmd_adm_set_svcerr(ap, err));
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate int
fmd_adm_module_gc(fmd_adm_t * ap,const char * name)4137c478bd9Sstevel@tonic-gate fmd_adm_module_gc(fmd_adm_t *ap, const char *name)
4147c478bd9Sstevel@tonic-gate {
4157c478bd9Sstevel@tonic-gate 	char *str = (char *)name;
4167c478bd9Sstevel@tonic-gate 	int err;
417d7448364Seschrock 	enum clnt_stat cs;
418d7448364Seschrock 	uint_t retries = 0;
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	if (name == NULL || strchr(name, '/') != NULL)
4217c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EINVAL));
4227c478bd9Sstevel@tonic-gate 
423d7448364Seschrock 	do {
424d7448364Seschrock 		cs = fmd_adm_modgc_1(str, &err, ap->adm_clnt);
425d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
426d7448364Seschrock 
427d7448364Seschrock 	if (cs != RPC_SUCCESS)
4287c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EPROTO));
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	return (fmd_adm_set_svcerr(ap, err));
4317c478bd9Sstevel@tonic-gate }
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate int
fmd_adm_module_stats(fmd_adm_t * ap,const char * name,fmd_adm_stats_t * sp)4347c478bd9Sstevel@tonic-gate fmd_adm_module_stats(fmd_adm_t *ap, const char *name, fmd_adm_stats_t *sp)
4357c478bd9Sstevel@tonic-gate {
4367c478bd9Sstevel@tonic-gate 	struct fmd_rpc_modstat rms;
437d7448364Seschrock 	enum clnt_stat cs;
438d7448364Seschrock 	uint_t retries = 0;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	if (name == NULL || sp == NULL)
4417c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EINVAL));
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	bzero(&rms, sizeof (rms)); /* tell xdr to allocate memory for us */
4447c478bd9Sstevel@tonic-gate 
445d7448364Seschrock 	do {
446d7448364Seschrock 		cs = fmd_adm_moddstat_1((char *)name, &rms, ap->adm_clnt);
447d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
448d7448364Seschrock 
449d7448364Seschrock 	if (cs != RPC_SUCCESS)
4507c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EPROTO));
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	if (rms.rms_err != 0) {
4537c478bd9Sstevel@tonic-gate 		xdr_free(xdr_fmd_rpc_modstat, (char *)&rms);
4547c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_svcerr(ap, rms.rms_err));
4557c478bd9Sstevel@tonic-gate 	}
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	sp->ams_buf = rms.rms_buf.rms_buf_val;
4587c478bd9Sstevel@tonic-gate 	sp->ams_len = rms.rms_buf.rms_buf_len;
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	return (0);
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate 
463749f21d3Swesolows int
fmd_adm_rsrc_count(fmd_adm_t * ap,int all,uint32_t * rcp)464749f21d3Swesolows fmd_adm_rsrc_count(fmd_adm_t *ap, int all, uint32_t *rcp)
465749f21d3Swesolows {
466749f21d3Swesolows 	struct fmd_rpc_rsrclist rrl;
467d7448364Seschrock 	enum clnt_stat cs;
468d7448364Seschrock 	uint_t retries = 0;
469749f21d3Swesolows 
470749f21d3Swesolows 	if (rcp == NULL)
471749f21d3Swesolows 		return (fmd_adm_set_errno(ap, EINVAL));
472749f21d3Swesolows 
473749f21d3Swesolows 	bzero(&rrl, sizeof (rrl)); /* tell xdr to allocate memory for us */
474749f21d3Swesolows 
475d7448364Seschrock 	do {
476d7448364Seschrock 		cs = fmd_adm_rsrclist_1(all, &rrl, ap->adm_clnt);
477d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
478d7448364Seschrock 
479d7448364Seschrock 	if (cs != RPC_SUCCESS)
480749f21d3Swesolows 		return (fmd_adm_set_errno(ap, EPROTO));
481749f21d3Swesolows 
482749f21d3Swesolows 	if (rrl.rrl_err != 0) {
483749f21d3Swesolows 		xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
484749f21d3Swesolows 		return (fmd_adm_set_svcerr(ap, rrl.rrl_err));
485749f21d3Swesolows 	}
486749f21d3Swesolows 
487749f21d3Swesolows 	*rcp = rrl.rrl_cnt;
488749f21d3Swesolows 	xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
489749f21d3Swesolows 	return (0);
490749f21d3Swesolows }
491749f21d3Swesolows 
4927c478bd9Sstevel@tonic-gate static int
fmd_adm_rsrc_cmp(const void * lp,const void * rp)4937c478bd9Sstevel@tonic-gate fmd_adm_rsrc_cmp(const void *lp, const void *rp)
4947c478bd9Sstevel@tonic-gate {
4957c478bd9Sstevel@tonic-gate 	return (strcmp(*(char **)lp, *(char **)rp));
4967c478bd9Sstevel@tonic-gate }
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate int
fmd_adm_rsrc_iter(fmd_adm_t * ap,int all,fmd_adm_rsrc_f * func,void * arg)4997c478bd9Sstevel@tonic-gate fmd_adm_rsrc_iter(fmd_adm_t *ap, int all, fmd_adm_rsrc_f *func, void *arg)
5007c478bd9Sstevel@tonic-gate {
5017c478bd9Sstevel@tonic-gate 	struct fmd_rpc_rsrclist rrl;
5027c478bd9Sstevel@tonic-gate 	struct fmd_rpc_rsrcinfo rri;
5037c478bd9Sstevel@tonic-gate 	fmd_adm_rsrcinfo_t ari;
5047c478bd9Sstevel@tonic-gate 	char **fmris, *p;
5057c478bd9Sstevel@tonic-gate 	int i, rv;
506d7448364Seschrock 	enum clnt_stat cs;
507d7448364Seschrock 	uint_t retries = 0;
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 	bzero(&rrl, sizeof (rrl)); /* tell xdr to allocate memory for us */
5107c478bd9Sstevel@tonic-gate 
511d7448364Seschrock 	do {
512d7448364Seschrock 		cs = fmd_adm_rsrclist_1(all, &rrl, ap->adm_clnt);
513d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
514d7448364Seschrock 
515d7448364Seschrock 	if (cs != RPC_SUCCESS)
5167c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EPROTO));
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	if (rrl.rrl_err != 0) {
5197c478bd9Sstevel@tonic-gate 		xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
5207c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_svcerr(ap, rrl.rrl_err));
5217c478bd9Sstevel@tonic-gate 	}
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 	if ((fmris = malloc(sizeof (char *) * rrl.rrl_cnt)) == NULL) {
5247c478bd9Sstevel@tonic-gate 		xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
5257c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EAGAIN));
5267c478bd9Sstevel@tonic-gate 	}
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 	/*
5297c478bd9Sstevel@tonic-gate 	 * The fmd_adm_rsrclist_1 request returns an opaque XDR buffer that is
5307c478bd9Sstevel@tonic-gate 	 * a string table of FMRIs (e.g. "fmriA\0fmriB\0...") where rrl_cnt is
5317c478bd9Sstevel@tonic-gate 	 * the number of strings in the table and rrl_buf_val is its address.
5327c478bd9Sstevel@tonic-gate 	 * We construct an array of pointers into the string table and sort it.
5337c478bd9Sstevel@tonic-gate 	 */
5347c478bd9Sstevel@tonic-gate 	p = rrl.rrl_buf.rrl_buf_val;
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 	for (i = 0; i < rrl.rrl_cnt; i++, p += strlen(p) + 1)
5377c478bd9Sstevel@tonic-gate 		fmris[i] = p; /* store fmri pointer in array for sorting */
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 	qsort(fmris, rrl.rrl_cnt, sizeof (char *), fmd_adm_rsrc_cmp);
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	/*
5427c478bd9Sstevel@tonic-gate 	 * For each FMRI in the resource cache snapshot, use fmd_adm_rsrcinfo_1
5437c478bd9Sstevel@tonic-gate 	 * to get more information and the invoke the callback function.  If
5447c478bd9Sstevel@tonic-gate 	 * FMD_ADM_ERR_RSRCSRCH is returned, the FMRI has been purged from the
5457c478bd9Sstevel@tonic-gate 	 * cache since our snapshot: this error is therefore silently ignored.
5467c478bd9Sstevel@tonic-gate 	 */
5477c478bd9Sstevel@tonic-gate 	for (i = 0; i < rrl.rrl_cnt; i++) {
5487c478bd9Sstevel@tonic-gate 		bzero(&rri, sizeof (rri));
5497c478bd9Sstevel@tonic-gate 
550d7448364Seschrock 		retries = 0;
551d7448364Seschrock 		do {
552d7448364Seschrock 			cs = fmd_adm_rsrcinfo_1(fmris[i], &rri, ap->adm_clnt);
553d7448364Seschrock 		} while (fmd_adm_retry(ap, cs, &retries));
554d7448364Seschrock 
555d7448364Seschrock 		if (cs != RPC_SUCCESS) {
5567c478bd9Sstevel@tonic-gate 			free(fmris);
5577c478bd9Sstevel@tonic-gate 			xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
5587c478bd9Sstevel@tonic-gate 			return (fmd_adm_set_errno(ap, EPROTO));
5597c478bd9Sstevel@tonic-gate 		}
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 		if (rri.rri_err != 0 && rri.rri_err != FMD_ADM_ERR_RSRCSRCH) {
5627c478bd9Sstevel@tonic-gate 			xdr_free(xdr_fmd_rpc_rsrcinfo, (char *)&rri);
5637c478bd9Sstevel@tonic-gate 			free(fmris);
5647c478bd9Sstevel@tonic-gate 			xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
5657c478bd9Sstevel@tonic-gate 			return (fmd_adm_set_svcerr(ap, rri.rri_err));
5667c478bd9Sstevel@tonic-gate 		}
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 		if (rri.rri_err == FMD_ADM_ERR_RSRCSRCH) {
5697c478bd9Sstevel@tonic-gate 			xdr_free(xdr_fmd_rpc_rsrcinfo, (char *)&rri);
5707c478bd9Sstevel@tonic-gate 			continue;
5717c478bd9Sstevel@tonic-gate 		}
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 		ari.ari_fmri = rri.rri_fmri;
5747c478bd9Sstevel@tonic-gate 		ari.ari_uuid = rri.rri_uuid;
5757c478bd9Sstevel@tonic-gate 		ari.ari_case = rri.rri_case;
5767c478bd9Sstevel@tonic-gate 		ari.ari_flags = 0;
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 		if (rri.rri_faulty)
5797c478bd9Sstevel@tonic-gate 			ari.ari_flags |= FMD_ADM_RSRC_FAULTY;
5807c478bd9Sstevel@tonic-gate 		if (rri.rri_unusable)
5817c478bd9Sstevel@tonic-gate 			ari.ari_flags |= FMD_ADM_RSRC_UNUSABLE;
5827c478bd9Sstevel@tonic-gate 		if (rri.rri_invisible)
5837c478bd9Sstevel@tonic-gate 			ari.ari_flags |= FMD_ADM_RSRC_INVISIBLE;
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 		rv = func(&ari, arg);
5867c478bd9Sstevel@tonic-gate 		xdr_free(xdr_fmd_rpc_rsrcinfo, (char *)&rri);
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 		if (rv != 0)
5897c478bd9Sstevel@tonic-gate 			break;
5907c478bd9Sstevel@tonic-gate 	}
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 	free(fmris);
5937c478bd9Sstevel@tonic-gate 	xdr_free(xdr_fmd_rpc_rsrclist, (char *)&rrl);
5947c478bd9Sstevel@tonic-gate 	return (0);
5957c478bd9Sstevel@tonic-gate }
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate int
fmd_adm_rsrc_flush(fmd_adm_t * ap,const char * fmri)5987c478bd9Sstevel@tonic-gate fmd_adm_rsrc_flush(fmd_adm_t *ap, const char *fmri)
5997c478bd9Sstevel@tonic-gate {
6007c478bd9Sstevel@tonic-gate 	char *str = (char *)fmri;
6017c478bd9Sstevel@tonic-gate 	int err;
602d7448364Seschrock 	enum clnt_stat cs;
603d7448364Seschrock 	uint_t retries = 0;
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate 	if (fmri == NULL)
6067c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EINVAL));
6077c478bd9Sstevel@tonic-gate 
608d7448364Seschrock 	do {
609d7448364Seschrock 		cs = fmd_adm_rsrcflush_1(str, &err, ap->adm_clnt);
610d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
611d7448364Seschrock 
612d7448364Seschrock 	if (cs != RPC_SUCCESS)
6137c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EPROTO));
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	return (fmd_adm_set_svcerr(ap, err));
6167c478bd9Sstevel@tonic-gate }
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate int
fmd_adm_rsrc_repaired(fmd_adm_t * ap,const char * fmri)61925c6ff4bSstephh fmd_adm_rsrc_repaired(fmd_adm_t *ap, const char *fmri)
6207c478bd9Sstevel@tonic-gate {
6217c478bd9Sstevel@tonic-gate 	char *str = (char *)fmri;
6227c478bd9Sstevel@tonic-gate 	int err;
623d7448364Seschrock 	enum clnt_stat cs;
624d7448364Seschrock 	uint_t retries = 0;
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 	if (fmri == NULL)
6277c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EINVAL));
6287c478bd9Sstevel@tonic-gate 
629d7448364Seschrock 	do {
63025c6ff4bSstephh 		cs = fmd_adm_rsrcrepaired_1(str, &err, ap->adm_clnt);
63125c6ff4bSstephh 	} while (fmd_adm_retry(ap, cs, &retries));
63225c6ff4bSstephh 
63325c6ff4bSstephh 	if (cs != RPC_SUCCESS)
63425c6ff4bSstephh 		return (fmd_adm_set_errno(ap, EPROTO));
63525c6ff4bSstephh 
63625c6ff4bSstephh 	return (fmd_adm_set_svcerr(ap, err));
63725c6ff4bSstephh }
63825c6ff4bSstephh 
63925c6ff4bSstephh int
fmd_adm_rsrc_replaced(fmd_adm_t * ap,const char * fmri)64025c6ff4bSstephh fmd_adm_rsrc_replaced(fmd_adm_t *ap, const char *fmri)
64125c6ff4bSstephh {
64225c6ff4bSstephh 	char *str = (char *)fmri;
64325c6ff4bSstephh 	int err;
64425c6ff4bSstephh 	enum clnt_stat cs;
64525c6ff4bSstephh 	uint_t retries = 0;
64625c6ff4bSstephh 
64725c6ff4bSstephh 	if (fmri == NULL)
64825c6ff4bSstephh 		return (fmd_adm_set_errno(ap, EINVAL));
64925c6ff4bSstephh 
65025c6ff4bSstephh 	do {
65125c6ff4bSstephh 		cs = fmd_adm_rsrcreplaced_1(str, &err, ap->adm_clnt);
65225c6ff4bSstephh 	} while (fmd_adm_retry(ap, cs, &retries));
65325c6ff4bSstephh 
65425c6ff4bSstephh 	if (cs != RPC_SUCCESS)
65525c6ff4bSstephh 		return (fmd_adm_set_errno(ap, EPROTO));
65625c6ff4bSstephh 
65725c6ff4bSstephh 	return (fmd_adm_set_svcerr(ap, err));
65825c6ff4bSstephh }
65925c6ff4bSstephh 
66025c6ff4bSstephh int
fmd_adm_rsrc_acquit(fmd_adm_t * ap,const char * fmri,const char * uuid)66125c6ff4bSstephh fmd_adm_rsrc_acquit(fmd_adm_t *ap, const char *fmri, const char *uuid)
66225c6ff4bSstephh {
66325c6ff4bSstephh 	char *str = (char *)fmri;
66425c6ff4bSstephh 	char *str2 = (char *)uuid;
66525c6ff4bSstephh 	int err;
66625c6ff4bSstephh 	enum clnt_stat cs;
66725c6ff4bSstephh 	uint_t retries = 0;
66825c6ff4bSstephh 
66925c6ff4bSstephh 	if (fmri == NULL)
67025c6ff4bSstephh 		return (fmd_adm_set_errno(ap, EINVAL));
67125c6ff4bSstephh 
67225c6ff4bSstephh 	do {
67325c6ff4bSstephh 		cs = fmd_adm_rsrcacquit_1(str, str2, &err, ap->adm_clnt);
674d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
675d7448364Seschrock 
676d7448364Seschrock 	if (cs != RPC_SUCCESS)
6777c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EPROTO));
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate 	return (fmd_adm_set_svcerr(ap, err));
6807c478bd9Sstevel@tonic-gate }
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate int
fmd_adm_case_repair(fmd_adm_t * ap,const char * uuid)6837c478bd9Sstevel@tonic-gate fmd_adm_case_repair(fmd_adm_t *ap, const char *uuid)
6847c478bd9Sstevel@tonic-gate {
6857c478bd9Sstevel@tonic-gate 	char *str = (char *)uuid;
6867c478bd9Sstevel@tonic-gate 	int err;
687d7448364Seschrock 	enum clnt_stat cs;
688d7448364Seschrock 	uint_t retries = 0;
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	if (uuid == NULL)
6917c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EINVAL));
6927c478bd9Sstevel@tonic-gate 
693d7448364Seschrock 	do {
694d7448364Seschrock 		cs = fmd_adm_caserepair_1(str, &err, ap->adm_clnt);
695d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
696d7448364Seschrock 
697d7448364Seschrock 	if (cs != RPC_SUCCESS)
6987c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EPROTO));
69925c6ff4bSstephh 
70025c6ff4bSstephh 	return (fmd_adm_set_svcerr(ap, err));
70125c6ff4bSstephh }
70225c6ff4bSstephh 
70325c6ff4bSstephh int
fmd_adm_case_acquit(fmd_adm_t * ap,const char * uuid)70425c6ff4bSstephh fmd_adm_case_acquit(fmd_adm_t *ap, const char *uuid)
70525c6ff4bSstephh {
70625c6ff4bSstephh 	char *str = (char *)uuid;
70725c6ff4bSstephh 	int err;
70825c6ff4bSstephh 	enum clnt_stat cs;
70925c6ff4bSstephh 	uint_t retries = 0;
71025c6ff4bSstephh 
71125c6ff4bSstephh 	if (uuid == NULL)
71225c6ff4bSstephh 		return (fmd_adm_set_errno(ap, EINVAL));
71325c6ff4bSstephh 
71425c6ff4bSstephh 	do {
71525c6ff4bSstephh 		cs = fmd_adm_caseacquit_1(str, &err, ap->adm_clnt);
71625c6ff4bSstephh 	} while (fmd_adm_retry(ap, cs, &retries));
71725c6ff4bSstephh 
71825c6ff4bSstephh 	if (cs != RPC_SUCCESS)
71925c6ff4bSstephh 		return (fmd_adm_set_errno(ap, EPROTO));
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 	return (fmd_adm_set_svcerr(ap, err));
7227c478bd9Sstevel@tonic-gate }
7237c478bd9Sstevel@tonic-gate 
724749f21d3Swesolows static int
fmd_adm_case_cmp(const void * lp,const void * rp)725749f21d3Swesolows fmd_adm_case_cmp(const void *lp, const void *rp)
726749f21d3Swesolows {
727749f21d3Swesolows 	return (strcmp(*(char **)lp, *(char **)rp));
728749f21d3Swesolows }
729749f21d3Swesolows 
730749f21d3Swesolows static int
fmd_adm_case_one(fmd_adm_caseinfo_t * acp,const char * url_token,fmd_adm_case_f * func,void * arg)731749f21d3Swesolows fmd_adm_case_one(fmd_adm_caseinfo_t *acp, const char *url_token,
732749f21d3Swesolows     fmd_adm_case_f *func, void *arg)
733749f21d3Swesolows {
734749f21d3Swesolows 	char *p, *urlcode, *dict, *olang;
735749f21d3Swesolows 	const char *url;
736749f21d3Swesolows 	size_t	len;
737749f21d3Swesolows 
738749f21d3Swesolows 	if ((p = strchr(acp->aci_code, '-')) == NULL ||
739749f21d3Swesolows 	    p == acp->aci_code) {
740749f21d3Swesolows 		acp->aci_url = NULL;
741749f21d3Swesolows 	} else {
742749f21d3Swesolows 		dict = alloca((size_t)(p - acp->aci_code) + 1);
743749f21d3Swesolows 		(void) strncpy(dict, acp->aci_code,
744749f21d3Swesolows 		    (size_t)(p - acp->aci_code));
745749f21d3Swesolows 		dict[(size_t)(p - acp->aci_code)] = '\0';
746749f21d3Swesolows 
747749f21d3Swesolows 		/*
748749f21d3Swesolows 		 * If we're given a token to use in looking up the URL, try
749749f21d3Swesolows 		 * to use it.  Otherwise, or if we don't find it that way,
750749f21d3Swesolows 		 * use the fallback.
751749f21d3Swesolows 		 */
752749f21d3Swesolows 		if (url_token == NULL) {
753749f21d3Swesolows 			url = _url_fallback;
754749f21d3Swesolows 		} else if ((url = dgettext(dict, url_token)) == url_token) {
755749f21d3Swesolows 			/*
756749f21d3Swesolows 			 * We didn't find a translation in the
757749f21d3Swesolows 			 * dictionary for the current language.  Fall
758749f21d3Swesolows 			 * back to C and try again.
759749f21d3Swesolows 			 */
760749f21d3Swesolows 			olang = setlocale(LC_MESSAGES, NULL);
761749f21d3Swesolows 			(void) setlocale(LC_MESSAGES, "C");
762749f21d3Swesolows 			if ((url = dgettext(dict, url_token)) == url_token)
763749f21d3Swesolows 				url = _url_fallback;
764749f21d3Swesolows 			(void) setlocale(LC_MESSAGES, olang);
765749f21d3Swesolows 		}
766749f21d3Swesolows 		len = strlen(url);
767749f21d3Swesolows 		if (url[len - 1] == '/') {
768749f21d3Swesolows 			len += strlen(acp->aci_code) + 1;
769749f21d3Swesolows 			urlcode = alloca(len);
770749f21d3Swesolows 			(void) snprintf(urlcode, len, "%s%s", url,
771749f21d3Swesolows 			    acp->aci_code);
772749f21d3Swesolows 		} else {
773749f21d3Swesolows 			urlcode = (char *)url;
774749f21d3Swesolows 		}
775749f21d3Swesolows 		acp->aci_url = urlcode;
776749f21d3Swesolows 	}
777749f21d3Swesolows 
778749f21d3Swesolows 	return (func(acp, arg));
779749f21d3Swesolows }
780749f21d3Swesolows 
781749f21d3Swesolows /*
782749f21d3Swesolows  * Our approach to cases is the same as for resources: we first obtain a
783749f21d3Swesolows  * list of UUIDs, sort them, then obtain the case information for each.
784749f21d3Swesolows  */
785749f21d3Swesolows int
fmd_adm_case_iter(fmd_adm_t * ap,const char * url_token,fmd_adm_case_f * func,void * arg)786749f21d3Swesolows fmd_adm_case_iter(fmd_adm_t *ap, const char *url_token, fmd_adm_case_f *func,
787749f21d3Swesolows     void *arg)
788749f21d3Swesolows {
789749f21d3Swesolows 	struct fmd_rpc_caselist rcl;
790749f21d3Swesolows 	struct fmd_rpc_caseinfo rci;
791749f21d3Swesolows 	fmd_adm_caseinfo_t aci;
792749f21d3Swesolows 	char **uuids, *p;
793749f21d3Swesolows 	int i, rv;
794d7448364Seschrock 	enum clnt_stat cs;
795d7448364Seschrock 	uint_t retries = 0;
796749f21d3Swesolows 
797749f21d3Swesolows 	bzero(&rcl, sizeof (rcl)); /* tell xdr to allocate memory for us */
798749f21d3Swesolows 
799d7448364Seschrock 	do {
800d7448364Seschrock 		cs = fmd_adm_caselist_1(&rcl, ap->adm_clnt);
801d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
802d7448364Seschrock 
803d7448364Seschrock 	if (cs != RPC_SUCCESS)
804749f21d3Swesolows 		return (fmd_adm_set_errno(ap, EPROTO));
805749f21d3Swesolows 
806749f21d3Swesolows 	if (rcl.rcl_err != 0) {
807749f21d3Swesolows 		xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
808749f21d3Swesolows 		return (fmd_adm_set_svcerr(ap, rcl.rcl_err));
809749f21d3Swesolows 	}
810749f21d3Swesolows 
811749f21d3Swesolows 	if ((uuids = malloc(sizeof (char *) * rcl.rcl_cnt)) == NULL) {
812749f21d3Swesolows 		xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
813749f21d3Swesolows 		return (fmd_adm_set_errno(ap, EAGAIN));
814749f21d3Swesolows 	}
815749f21d3Swesolows 
816749f21d3Swesolows 	p = rcl.rcl_buf.rcl_buf_val;
817749f21d3Swesolows 
818749f21d3Swesolows 	for (i = 0; i < rcl.rcl_cnt; i++, p += strlen(p) + 1)
819749f21d3Swesolows 		uuids[i] = p;
820749f21d3Swesolows 
821749f21d3Swesolows 	qsort(uuids, rcl.rcl_cnt, sizeof (char *), fmd_adm_case_cmp);
822749f21d3Swesolows 
823749f21d3Swesolows 	for (i = 0; i < rcl.rcl_cnt; i++) {
824749f21d3Swesolows 		bzero(&rci, sizeof (rci));
825749f21d3Swesolows 
826d7448364Seschrock 		retries = 0;
827d7448364Seschrock 		do {
828d7448364Seschrock 			cs = fmd_adm_caseinfo_1(uuids[i], &rci, ap->adm_clnt);
829d7448364Seschrock 		} while (fmd_adm_retry(ap, cs, &retries));
830d7448364Seschrock 
831d7448364Seschrock 		if (cs != RPC_SUCCESS) {
832749f21d3Swesolows 			free(uuids);
833749f21d3Swesolows 			xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
834749f21d3Swesolows 			return (fmd_adm_set_errno(ap, EPROTO));
835749f21d3Swesolows 		}
836749f21d3Swesolows 
837749f21d3Swesolows 		if (rci.rci_err != 0 && rci.rci_err != FMD_ADM_ERR_CASESRCH) {
838749f21d3Swesolows 			xdr_free(xdr_fmd_rpc_caseinfo, (char *)&rci);
839749f21d3Swesolows 			free(uuids);
840749f21d3Swesolows 			xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
841749f21d3Swesolows 			return (fmd_adm_set_svcerr(ap, rci.rci_err));
842749f21d3Swesolows 		}
843749f21d3Swesolows 
844749f21d3Swesolows 		if (rci.rci_err == FMD_ADM_ERR_CASESRCH) {
845749f21d3Swesolows 			xdr_free(xdr_fmd_rpc_caseinfo, (char *)&rci);
846749f21d3Swesolows 			continue;
847749f21d3Swesolows 		}
848749f21d3Swesolows 
849749f21d3Swesolows 		bzero(&aci, sizeof (aci));
850749f21d3Swesolows 
851749f21d3Swesolows 		if ((rv = nvlist_unpack(rci.rci_evbuf.rci_evbuf_val,
852749f21d3Swesolows 		    rci.rci_evbuf.rci_evbuf_len, &aci.aci_event, 0)) != 0) {
853749f21d3Swesolows 			xdr_free(xdr_fmd_rpc_caseinfo, (char *)&rci);
854749f21d3Swesolows 			free(uuids);
855749f21d3Swesolows 			xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
856749f21d3Swesolows 			return (fmd_adm_set_errno(ap, rv));
857749f21d3Swesolows 		}
858749f21d3Swesolows 
859749f21d3Swesolows 		if ((rv = nvlist_lookup_string(aci.aci_event, FM_SUSPECT_UUID,
860749f21d3Swesolows 		    (char **)&aci.aci_uuid)) != 0) {
861749f21d3Swesolows 			xdr_free(xdr_fmd_rpc_caseinfo, (char *)&rci);
862749f21d3Swesolows 			free(uuids);
863749f21d3Swesolows 			xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
864749f21d3Swesolows 			nvlist_free(aci.aci_event);
865749f21d3Swesolows 			return (fmd_adm_set_errno(ap, rv));
866749f21d3Swesolows 		}
867749f21d3Swesolows 		if ((rv = nvlist_lookup_string(aci.aci_event,
868749f21d3Swesolows 		    FM_SUSPECT_DIAG_CODE, (char **)&aci.aci_code)) != 0) {
869749f21d3Swesolows 			xdr_free(xdr_fmd_rpc_caseinfo, (char *)&rci);
870749f21d3Swesolows 			free(uuids);
871749f21d3Swesolows 			xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
872749f21d3Swesolows 			nvlist_free(aci.aci_event);
873749f21d3Swesolows 			return (fmd_adm_set_errno(ap, rv));
874749f21d3Swesolows 		}
875749f21d3Swesolows 
876749f21d3Swesolows 		rv = fmd_adm_case_one(&aci, url_token, func, arg);
877749f21d3Swesolows 
878749f21d3Swesolows 		xdr_free(xdr_fmd_rpc_caseinfo, (char *)&rci);
879749f21d3Swesolows 		nvlist_free(aci.aci_event);
880749f21d3Swesolows 
881749f21d3Swesolows 		if (rv != 0)
882749f21d3Swesolows 			break;
883749f21d3Swesolows 	}
884749f21d3Swesolows 
885749f21d3Swesolows 	free(uuids);
886749f21d3Swesolows 	xdr_free(xdr_fmd_rpc_caselist, (char *)&rcl);
887749f21d3Swesolows 	return (0);
888749f21d3Swesolows }
889749f21d3Swesolows 
8907c478bd9Sstevel@tonic-gate static int
fmd_adm_serd_cmp(const void * lp,const void * rp)8917c478bd9Sstevel@tonic-gate fmd_adm_serd_cmp(const void *lp, const void *rp)
8927c478bd9Sstevel@tonic-gate {
8931e6f4912SJakub Jermar 	return (strcmp(*(char **)lp, *(char **)rp));
8947c478bd9Sstevel@tonic-gate }
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate int
fmd_adm_serd_iter(fmd_adm_t * ap,const char * name,fmd_adm_serd_f * func,void * arg)8977c478bd9Sstevel@tonic-gate fmd_adm_serd_iter(fmd_adm_t *ap, const char *name,
8987c478bd9Sstevel@tonic-gate     fmd_adm_serd_f *func, void *arg)
8997c478bd9Sstevel@tonic-gate {
9007c478bd9Sstevel@tonic-gate 	struct fmd_rpc_serdlist rsl;
9011e6f4912SJakub Jermar 	struct fmd_rpc_serdinfo rsi;
9021e6f4912SJakub Jermar 	char **serds, *p;
9037c478bd9Sstevel@tonic-gate 	fmd_adm_serdinfo_t asi;
904d7448364Seschrock 	enum clnt_stat cs;
905d7448364Seschrock 	uint_t retries = 0;
9061e6f4912SJakub Jermar 	int i, rv;
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 	bzero(&rsl, sizeof (rsl)); /* tell xdr to allocate memory for us */
9097c478bd9Sstevel@tonic-gate 
910d7448364Seschrock 	do {
9111e6f4912SJakub Jermar 		cs = fmd_adm_serdlist_1((char *)name, &rsl, ap->adm_clnt);
912d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
913d7448364Seschrock 
914d7448364Seschrock 	if (cs != RPC_SUCCESS)
9157c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EPROTO));
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate 	if (rsl.rsl_err != 0 || rsl.rsl_len == 0) {
9187c478bd9Sstevel@tonic-gate 		xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl);
9197c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_svcerr(ap, rsl.rsl_err));
9207c478bd9Sstevel@tonic-gate 	}
9217c478bd9Sstevel@tonic-gate 
9221e6f4912SJakub Jermar 	if ((serds = malloc(sizeof (char *) * rsl.rsl_cnt)) == NULL) {
9237c478bd9Sstevel@tonic-gate 		xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl);
9247c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EAGAIN));
9257c478bd9Sstevel@tonic-gate 	}
9267c478bd9Sstevel@tonic-gate 
9271e6f4912SJakub Jermar 	p = rsl.rsl_buf.rsl_buf_val;
9281e6f4912SJakub Jermar 
9291e6f4912SJakub Jermar 	for (i = 0; i < rsl.rsl_cnt; i++, p += strlen(p) + 1)
9301e6f4912SJakub Jermar 		serds[i] = p;
9317c478bd9Sstevel@tonic-gate 
9321e6f4912SJakub Jermar 	qsort(serds, rsl.rsl_cnt, sizeof (char *), fmd_adm_serd_cmp);
9337c478bd9Sstevel@tonic-gate 
9341e6f4912SJakub Jermar 	for (i = 0; i < rsl.rsl_cnt; i++) {
9351e6f4912SJakub Jermar 		bzero(&rsi, sizeof (rsi));
9367c478bd9Sstevel@tonic-gate 
9371e6f4912SJakub Jermar 		retries = 0;
9381e6f4912SJakub Jermar 		do {
9391e6f4912SJakub Jermar 			cs = fmd_adm_serdinfo_1((char *)name, serds[i], &rsi,
9401e6f4912SJakub Jermar 			    ap->adm_clnt);
9411e6f4912SJakub Jermar 		} while (fmd_adm_retry(ap, cs, &retries));
9421e6f4912SJakub Jermar 
9431e6f4912SJakub Jermar 		if (cs != RPC_SUCCESS) {
9441e6f4912SJakub Jermar 			free(serds);
9451e6f4912SJakub Jermar 			xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl);
9461e6f4912SJakub Jermar 			return (fmd_adm_set_errno(ap, EPROTO));
9471e6f4912SJakub Jermar 		}
9481e6f4912SJakub Jermar 
9491e6f4912SJakub Jermar 		if (rsi.rsi_err != 0 && rsi.rsi_err != FMD_ADM_ERR_SERDSRCH) {
9501e6f4912SJakub Jermar 			free(serds);
9511e6f4912SJakub Jermar 			xdr_free(xdr_fmd_rpc_serdinfo, (char *)&rsi);
9521e6f4912SJakub Jermar 			xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl);
9531e6f4912SJakub Jermar 			return (fmd_adm_set_svcerr(ap, rsi.rsi_err));
9541e6f4912SJakub Jermar 		}
9551e6f4912SJakub Jermar 
9561e6f4912SJakub Jermar 		if (rsi.rsi_err == FMD_ADM_ERR_SERDSRCH) {
9571e6f4912SJakub Jermar 			xdr_free(xdr_fmd_rpc_serdinfo, (char *)&rsi);
9581e6f4912SJakub Jermar 			continue;
9591e6f4912SJakub Jermar 		}
9601e6f4912SJakub Jermar 
9611e6f4912SJakub Jermar 		bzero(&asi, sizeof (asi));
9621e6f4912SJakub Jermar 
9631e6f4912SJakub Jermar 		asi.asi_name = rsi.rsi_name;
9641e6f4912SJakub Jermar 		asi.asi_delta = rsi.rsi_delta;
9651e6f4912SJakub Jermar 		asi.asi_n = rsi.rsi_n;
9661e6f4912SJakub Jermar 		asi.asi_t = rsi.rsi_t;
9671e6f4912SJakub Jermar 		asi.asi_count = rsi.rsi_count;
9687c478bd9Sstevel@tonic-gate 		asi.asi_flags = 0;
9697c478bd9Sstevel@tonic-gate 
9701e6f4912SJakub Jermar 		if (rsi.rsi_fired)
9717c478bd9Sstevel@tonic-gate 			asi.asi_flags |= FMD_ADM_SERD_FIRED;
9727c478bd9Sstevel@tonic-gate 
9731e6f4912SJakub Jermar 		rv = func(&asi, arg);
9741e6f4912SJakub Jermar 
9751e6f4912SJakub Jermar 		xdr_free(xdr_fmd_rpc_serdinfo, (char *)&rsi);
9761e6f4912SJakub Jermar 
9771e6f4912SJakub Jermar 		if (rv != 0)
9787c478bd9Sstevel@tonic-gate 			break;
9797c478bd9Sstevel@tonic-gate 	}
9807c478bd9Sstevel@tonic-gate 
9811e6f4912SJakub Jermar 	free(serds);
9827c478bd9Sstevel@tonic-gate 	xdr_free(xdr_fmd_rpc_serdlist, (char *)&rsl);
9837c478bd9Sstevel@tonic-gate 	return (0);
9847c478bd9Sstevel@tonic-gate }
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate int
fmd_adm_serd_reset(fmd_adm_t * ap,const char * mod,const char * name)9877c478bd9Sstevel@tonic-gate fmd_adm_serd_reset(fmd_adm_t *ap, const char *mod, const char *name)
9887c478bd9Sstevel@tonic-gate {
9897c478bd9Sstevel@tonic-gate 	char *s1 = (char *)mod, *s2 = (char *)name;
9907c478bd9Sstevel@tonic-gate 	int err;
991d7448364Seschrock 	enum clnt_stat cs;
992d7448364Seschrock 	uint_t retries = 0;
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate 	if (mod == NULL || name == NULL || strchr(mod, '/') != NULL)
9957c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EINVAL));
9967c478bd9Sstevel@tonic-gate 
997d7448364Seschrock 	do {
998d7448364Seschrock 		cs = fmd_adm_serdreset_1(s1, s2, &err, ap->adm_clnt);
999d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
1000d7448364Seschrock 
1001d7448364Seschrock 	if (cs != RPC_SUCCESS)
10027c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EPROTO));
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate 	return (fmd_adm_set_svcerr(ap, err));
10057c478bd9Sstevel@tonic-gate }
10067c478bd9Sstevel@tonic-gate 
1007d9638e54Smws int
fmd_adm_xprt_iter(fmd_adm_t * ap,fmd_adm_xprt_f * func,void * arg)1008d9638e54Smws fmd_adm_xprt_iter(fmd_adm_t *ap, fmd_adm_xprt_f *func, void *arg)
1009d9638e54Smws {
1010d9638e54Smws 	struct fmd_rpc_xprtlist rxl;
1011d9638e54Smws 	uint_t i;
1012d7448364Seschrock 	enum clnt_stat cs;
1013d7448364Seschrock 	uint_t retries = 0;
1014d9638e54Smws 
1015d9638e54Smws 	bzero(&rxl, sizeof (rxl)); /* tell xdr to allocate memory for us */
1016d9638e54Smws 
1017d7448364Seschrock 	do {
1018d7448364Seschrock 		cs = fmd_adm_xprtlist_1(&rxl, ap->adm_clnt);
1019d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
1020d7448364Seschrock 
1021d7448364Seschrock 	if (cs != RPC_SUCCESS)
1022d9638e54Smws 		return (fmd_adm_set_errno(ap, EPROTO));
1023d9638e54Smws 
1024d9638e54Smws 	if (rxl.rxl_err != 0) {
1025d9638e54Smws 		xdr_free(xdr_fmd_rpc_xprtlist, (char *)&rxl);
1026d9638e54Smws 		return (fmd_adm_set_svcerr(ap, rxl.rxl_err));
1027d9638e54Smws 	}
1028d9638e54Smws 
1029d9638e54Smws 	for (i = 0; i < rxl.rxl_len; i++)
1030d9638e54Smws 		func(rxl.rxl_buf.rxl_buf_val[i], arg);
1031d9638e54Smws 
1032d9638e54Smws 	xdr_free(xdr_fmd_rpc_xprtlist, (char *)&rxl);
1033d9638e54Smws 	return (0);
1034d9638e54Smws }
1035d9638e54Smws 
1036d9638e54Smws int
fmd_adm_xprt_stats(fmd_adm_t * ap,id_t id,fmd_adm_stats_t * sp)1037d9638e54Smws fmd_adm_xprt_stats(fmd_adm_t *ap, id_t id, fmd_adm_stats_t *sp)
1038d9638e54Smws {
1039d9638e54Smws 	struct fmd_rpc_modstat rms;
1040d7448364Seschrock 	enum clnt_stat cs;
1041d7448364Seschrock 	uint_t retries = 0;
1042d9638e54Smws 
1043d9638e54Smws 	if (sp == NULL)
1044d9638e54Smws 		return (fmd_adm_set_errno(ap, EINVAL));
1045d9638e54Smws 
1046d9638e54Smws 	bzero(&rms, sizeof (rms)); /* tell xdr to allocate memory for us */
1047d9638e54Smws 
1048d7448364Seschrock 	do {
1049d7448364Seschrock 		cs = fmd_adm_xprtstat_1(id, &rms, ap->adm_clnt);
1050d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
1051d7448364Seschrock 
1052d7448364Seschrock 	if (cs != RPC_SUCCESS)
1053d9638e54Smws 		return (fmd_adm_set_errno(ap, EPROTO));
1054d9638e54Smws 
1055d9638e54Smws 	if (rms.rms_err != 0) {
1056d9638e54Smws 		xdr_free(xdr_fmd_rpc_modstat, (char *)&rms);
1057d9638e54Smws 		return (fmd_adm_set_svcerr(ap, rms.rms_err));
1058d9638e54Smws 	}
1059d9638e54Smws 
1060d9638e54Smws 	sp->ams_buf = rms.rms_buf.rms_buf_val;
1061d9638e54Smws 	sp->ams_len = rms.rms_buf.rms_buf_len;
1062d9638e54Smws 
1063d9638e54Smws 	return (0);
1064d9638e54Smws }
1065d9638e54Smws 
10667c478bd9Sstevel@tonic-gate int
fmd_adm_log_rotate(fmd_adm_t * ap,const char * log)10677c478bd9Sstevel@tonic-gate fmd_adm_log_rotate(fmd_adm_t *ap, const char *log)
10687c478bd9Sstevel@tonic-gate {
10697c478bd9Sstevel@tonic-gate 	int err;
1070d7448364Seschrock 	enum clnt_stat cs;
1071d7448364Seschrock 	uint_t retries = 0;
10727c478bd9Sstevel@tonic-gate 
10737c478bd9Sstevel@tonic-gate 	if (log == NULL)
10747c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EINVAL));
10757c478bd9Sstevel@tonic-gate 
1076d7448364Seschrock 	do {
1077d7448364Seschrock 		cs = fmd_adm_logrotate_1((char *)log, &err, ap->adm_clnt);
1078d7448364Seschrock 	} while (fmd_adm_retry(ap, cs, &retries));
1079d7448364Seschrock 
1080d7448364Seschrock 	if (cs != RPC_SUCCESS)
10817c478bd9Sstevel@tonic-gate 		return (fmd_adm_set_errno(ap, EPROTO));
10827c478bd9Sstevel@tonic-gate 
10837c478bd9Sstevel@tonic-gate 	return (fmd_adm_set_svcerr(ap, err));
10847c478bd9Sstevel@tonic-gate }
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate /*
10877c478bd9Sstevel@tonic-gate  * Custom XDR routine for our API structure fmd_stat_t.  This function must
10887c478bd9Sstevel@tonic-gate  * match the definition of fmd_stat_t in <fm/fmd_api.h> and must also match
10897c478bd9Sstevel@tonic-gate  * the corresponding routine in usr/src/cmd/fm/fmd/common/fmd_rpc_adm.c.
10907c478bd9Sstevel@tonic-gate  */
10917c478bd9Sstevel@tonic-gate bool_t
xdr_fmd_stat(XDR * xp,fmd_stat_t * sp)10927c478bd9Sstevel@tonic-gate xdr_fmd_stat(XDR *xp, fmd_stat_t *sp)
10937c478bd9Sstevel@tonic-gate {
10947c478bd9Sstevel@tonic-gate 	bool_t rv = TRUE;
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 	rv &= xdr_opaque(xp, sp->fmds_name, sizeof (sp->fmds_name));
10977c478bd9Sstevel@tonic-gate 	rv &= xdr_u_int(xp, &sp->fmds_type);
10987c478bd9Sstevel@tonic-gate 	rv &= xdr_opaque(xp, sp->fmds_desc, sizeof (sp->fmds_desc));
10997c478bd9Sstevel@tonic-gate 
11007c478bd9Sstevel@tonic-gate 	switch (sp->fmds_type) {
11017c478bd9Sstevel@tonic-gate 	case FMD_TYPE_BOOL:
11027c478bd9Sstevel@tonic-gate 		rv &= xdr_int(xp, &sp->fmds_value.bool);
11037c478bd9Sstevel@tonic-gate 		break;
11047c478bd9Sstevel@tonic-gate 	case FMD_TYPE_INT32:
11057c478bd9Sstevel@tonic-gate 		rv &= xdr_int32_t(xp, &sp->fmds_value.i32);
11067c478bd9Sstevel@tonic-gate 		break;
11077c478bd9Sstevel@tonic-gate 	case FMD_TYPE_UINT32:
11087c478bd9Sstevel@tonic-gate 		rv &= xdr_uint32_t(xp, &sp->fmds_value.ui32);
11097c478bd9Sstevel@tonic-gate 		break;
11107c478bd9Sstevel@tonic-gate 	case FMD_TYPE_INT64:
11117c478bd9Sstevel@tonic-gate 		rv &= xdr_int64_t(xp, &sp->fmds_value.i64);
11127c478bd9Sstevel@tonic-gate 		break;
11137c478bd9Sstevel@tonic-gate 	case FMD_TYPE_UINT64:
11147c478bd9Sstevel@tonic-gate 	case FMD_TYPE_TIME:
11157c478bd9Sstevel@tonic-gate 	case FMD_TYPE_SIZE:
11167c478bd9Sstevel@tonic-gate 		rv &= xdr_uint64_t(xp, &sp->fmds_value.ui64);
11177c478bd9Sstevel@tonic-gate 		break;
11187c478bd9Sstevel@tonic-gate 	case FMD_TYPE_STRING:
11197c478bd9Sstevel@tonic-gate 		rv &= xdr_string(xp, &sp->fmds_value.str, ~0);
11207c478bd9Sstevel@tonic-gate 		break;
11217c478bd9Sstevel@tonic-gate 	}
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 	return (rv);
11247c478bd9Sstevel@tonic-gate }
1125