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  */
21749f21d3Swesolows 
227c478bd9Sstevel@tonic-gate /*
23f6e214c7SGavin Maltby  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <strings.h>
277c478bd9Sstevel@tonic-gate #include <limits.h>
287c478bd9Sstevel@tonic-gate #include <unistd.h>
297c478bd9Sstevel@tonic-gate #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <alloca.h>
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <fmd_rpc_adm.h>
337c478bd9Sstevel@tonic-gate #include <fmd_rpc.h>
347c478bd9Sstevel@tonic-gate #include <fmd_module.h>
357c478bd9Sstevel@tonic-gate #include <fmd_ustat.h>
367c478bd9Sstevel@tonic-gate #include <fmd_error.h>
377c478bd9Sstevel@tonic-gate #include <fmd_asru.h>
387c478bd9Sstevel@tonic-gate #include <fmd_ckpt.h>
397c478bd9Sstevel@tonic-gate #include <fmd_case.h>
407c478bd9Sstevel@tonic-gate #include <fmd_fmri.h>
41d9638e54Smws #include <fmd_idspace.h>
42d9638e54Smws #include <fmd_xprt.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #include <fmd.h>
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate bool_t
fmd_adm_modinfo_1_svc(struct fmd_rpc_modlist * rvp,struct svc_req * req)477c478bd9Sstevel@tonic-gate fmd_adm_modinfo_1_svc(struct fmd_rpc_modlist *rvp, struct svc_req *req)
487c478bd9Sstevel@tonic-gate {
497c478bd9Sstevel@tonic-gate 	struct fmd_rpc_modinfo *rmi;
507c478bd9Sstevel@tonic-gate 	fmd_module_t *mp;
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate 	rvp->rml_list = NULL;
537c478bd9Sstevel@tonic-gate 	rvp->rml_err = 0;
547c478bd9Sstevel@tonic-gate 	rvp->rml_len = 0;
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
577c478bd9Sstevel@tonic-gate 		rvp->rml_err = FMD_ADM_ERR_PERM;
587c478bd9Sstevel@tonic-gate 		return (TRUE);
597c478bd9Sstevel@tonic-gate 	}
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&fmd.d_mod_lock);
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 	for (mp = fmd_list_next(&fmd.d_mod_list);
647c478bd9Sstevel@tonic-gate 	    mp != NULL; mp = fmd_list_next(mp)) {
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 		if ((rmi = malloc(sizeof (struct fmd_rpc_modinfo))) == NULL) {
677c478bd9Sstevel@tonic-gate 			rvp->rml_err = FMD_ADM_ERR_NOMEM;
687c478bd9Sstevel@tonic-gate 			break;
697c478bd9Sstevel@tonic-gate 		}
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate 		fmd_module_lock(mp);
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 		/*
747c478bd9Sstevel@tonic-gate 		 * If mod_info is NULL, the module is in the middle of loading:
757c478bd9Sstevel@tonic-gate 		 * do not report its presence to observability tools yet.
767c478bd9Sstevel@tonic-gate 		 */
777c478bd9Sstevel@tonic-gate 		if (mp->mod_info == NULL) {
787c478bd9Sstevel@tonic-gate 			fmd_module_unlock(mp);
797c478bd9Sstevel@tonic-gate 			free(rmi);
807c478bd9Sstevel@tonic-gate 			continue;
817c478bd9Sstevel@tonic-gate 		}
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 		rmi->rmi_name = strdup(mp->mod_name);
847c478bd9Sstevel@tonic-gate 		rmi->rmi_desc = strdup(mp->mod_info->fmdi_desc);
857c478bd9Sstevel@tonic-gate 		rmi->rmi_vers = strdup(mp->mod_info->fmdi_vers);
867c478bd9Sstevel@tonic-gate 		rmi->rmi_faulty = mp->mod_error != 0;
877c478bd9Sstevel@tonic-gate 		rmi->rmi_next = rvp->rml_list;
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 		fmd_module_unlock(mp);
907c478bd9Sstevel@tonic-gate 		rvp->rml_list = rmi;
917c478bd9Sstevel@tonic-gate 		rvp->rml_len++;
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 		if (rmi->rmi_desc == NULL || rmi->rmi_vers == NULL) {
947c478bd9Sstevel@tonic-gate 			rvp->rml_err = FMD_ADM_ERR_NOMEM;
957c478bd9Sstevel@tonic-gate 			break;
967c478bd9Sstevel@tonic-gate 		}
977c478bd9Sstevel@tonic-gate 	}
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&fmd.d_mod_lock);
1007c478bd9Sstevel@tonic-gate 	return (TRUE);
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate bool_t
fmd_adm_modcstat_1_svc(char * name,struct fmd_rpc_modstat * rms,struct svc_req * req)1047c478bd9Sstevel@tonic-gate fmd_adm_modcstat_1_svc(char *name,
1057c478bd9Sstevel@tonic-gate     struct fmd_rpc_modstat *rms, struct svc_req *req)
1067c478bd9Sstevel@tonic-gate {
1077c478bd9Sstevel@tonic-gate 	fmd_ustat_snap_t snap;
1087c478bd9Sstevel@tonic-gate 	fmd_module_t *mp;
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	rms->rms_buf.rms_buf_val = NULL;
1117c478bd9Sstevel@tonic-gate 	rms->rms_buf.rms_buf_len = 0;
1127c478bd9Sstevel@tonic-gate 	rms->rms_err = 0;
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
1157c478bd9Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_PERM;
1167c478bd9Sstevel@tonic-gate 		return (TRUE);
1177c478bd9Sstevel@tonic-gate 	}
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, name)) == NULL) {
1207c478bd9Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_MODSRCH;
1217c478bd9Sstevel@tonic-gate 		return (TRUE);
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	if (fmd_modstat_snapshot(mp, &snap) == 0) {
1257c478bd9Sstevel@tonic-gate 		rms->rms_buf.rms_buf_val = snap.uss_buf;
1267c478bd9Sstevel@tonic-gate 		rms->rms_buf.rms_buf_len = snap.uss_len;
1277c478bd9Sstevel@tonic-gate 	} else if (errno == EFMD_HDL_ABORT) {
1287c478bd9Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_MODFAIL;
1297c478bd9Sstevel@tonic-gate 	} else
1307c478bd9Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_NOMEM;
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	fmd_module_rele(mp);
1337c478bd9Sstevel@tonic-gate 	return (TRUE);
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate bool_t
fmd_adm_moddstat_1_svc(char * name,struct fmd_rpc_modstat * rms,struct svc_req * req)1377c478bd9Sstevel@tonic-gate fmd_adm_moddstat_1_svc(char *name,
1387c478bd9Sstevel@tonic-gate     struct fmd_rpc_modstat *rms, struct svc_req *req)
1397c478bd9Sstevel@tonic-gate {
1407c478bd9Sstevel@tonic-gate 	fmd_module_t *mp;
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	rms->rms_buf.rms_buf_val = NULL;
1437c478bd9Sstevel@tonic-gate 	rms->rms_buf.rms_buf_len = 0;
1447c478bd9Sstevel@tonic-gate 	rms->rms_err = 0;
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
1477c478bd9Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_PERM;
1487c478bd9Sstevel@tonic-gate 		return (TRUE);
1497c478bd9Sstevel@tonic-gate 	}
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, name)) == NULL) {
1527c478bd9Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_MODSRCH;
1537c478bd9Sstevel@tonic-gate 		return (TRUE);
1547c478bd9Sstevel@tonic-gate 	}
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	rms->rms_buf.rms_buf_val = malloc(sizeof (fmd_modstat_t));
1577c478bd9Sstevel@tonic-gate 	rms->rms_buf.rms_buf_len = sizeof (fmd_modstat_t) / sizeof (fmd_stat_t);
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	if (rms->rms_buf.rms_buf_val == NULL) {
1607c478bd9Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_NOMEM;
1617c478bd9Sstevel@tonic-gate 		rms->rms_buf.rms_buf_len = 0;
1627c478bd9Sstevel@tonic-gate 		fmd_module_rele(mp);
1637c478bd9Sstevel@tonic-gate 		return (TRUE);
1647c478bd9Sstevel@tonic-gate 	}
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	/*
1677c478bd9Sstevel@tonic-gate 	 * Note: the bcopy() here is valid only if no FMD_TYPE_STRING stats
1687c478bd9Sstevel@tonic-gate 	 * are present in mp->mod_stats.  We don't use any for the daemon-
1697c478bd9Sstevel@tonic-gate 	 * maintained stats and provide this function in order to reduce the
170*bbf21555SRichard Lowe 	 * overhead of the fmstat(8) default view, where these minimal stats
1717c478bd9Sstevel@tonic-gate 	 * must be retrieved for all of the active modules.
1727c478bd9Sstevel@tonic-gate 	 */
1737c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&mp->mod_stats_lock);
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	if (mp->mod_stats != NULL) {
1767c478bd9Sstevel@tonic-gate 		mp->mod_stats->ms_snaptime.fmds_value.ui64 = gethrtime();
1777c478bd9Sstevel@tonic-gate 		bcopy(mp->mod_stats, rms->rms_buf.rms_buf_val,
1787c478bd9Sstevel@tonic-gate 		    sizeof (fmd_modstat_t));
1797c478bd9Sstevel@tonic-gate 	} else {
1807c478bd9Sstevel@tonic-gate 		free(rms->rms_buf.rms_buf_val);
1817c478bd9Sstevel@tonic-gate 		rms->rms_buf.rms_buf_val = NULL;
1827c478bd9Sstevel@tonic-gate 		rms->rms_buf.rms_buf_len = 0;
1837c478bd9Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_MODFAIL;
1847c478bd9Sstevel@tonic-gate 	}
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&mp->mod_stats_lock);
1877c478bd9Sstevel@tonic-gate 	fmd_module_rele(mp);
1887c478bd9Sstevel@tonic-gate 	return (TRUE);
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate bool_t
fmd_adm_modgstat_1_svc(struct fmd_rpc_modstat * rms,struct svc_req * req)1927c478bd9Sstevel@tonic-gate fmd_adm_modgstat_1_svc(struct fmd_rpc_modstat *rms, struct svc_req *req)
1937c478bd9Sstevel@tonic-gate {
1947c478bd9Sstevel@tonic-gate 	const size_t size = sizeof (fmd_statistics_t);
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
1977c478bd9Sstevel@tonic-gate 		rms->rms_buf.rms_buf_val = NULL;
1987c478bd9Sstevel@tonic-gate 		rms->rms_buf.rms_buf_len = 0;
1997c478bd9Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_PERM;
2007c478bd9Sstevel@tonic-gate 	} else if ((rms->rms_buf.rms_buf_val = malloc(size)) != NULL) {
2017c478bd9Sstevel@tonic-gate 		/*
2027c478bd9Sstevel@tonic-gate 		 * Note: the bcopy() here is valid only if no FMD_TYPE_STRING
2037c478bd9Sstevel@tonic-gate 		 * stats are present in fmd.d_stats (see definition in fmd.c).
2047c478bd9Sstevel@tonic-gate 		 */
2057c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&fmd.d_stats_lock);
2067c478bd9Sstevel@tonic-gate 		bcopy(fmd.d_stats, rms->rms_buf.rms_buf_val, size);
2077c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&fmd.d_stats_lock);
2087c478bd9Sstevel@tonic-gate 		rms->rms_buf.rms_buf_len = size / sizeof (fmd_stat_t);
2097c478bd9Sstevel@tonic-gate 		rms->rms_err = 0;
2107c478bd9Sstevel@tonic-gate 	} else {
2117c478bd9Sstevel@tonic-gate 		rms->rms_buf.rms_buf_len = 0;
2127c478bd9Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_NOMEM;
2137c478bd9Sstevel@tonic-gate 	}
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	return (TRUE);
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate bool_t
fmd_adm_modload_1_svc(char * path,int * rvp,struct svc_req * req)2197c478bd9Sstevel@tonic-gate fmd_adm_modload_1_svc(char *path, int *rvp, struct svc_req *req)
2207c478bd9Sstevel@tonic-gate {
2217c478bd9Sstevel@tonic-gate 	fmd_module_t *mp;
2227c478bd9Sstevel@tonic-gate 	const char *p;
2237c478bd9Sstevel@tonic-gate 	int err = 0;
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
2267c478bd9Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_PERM;
2277c478bd9Sstevel@tonic-gate 		return (TRUE);
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	/*
2317c478bd9Sstevel@tonic-gate 	 * Before we endure the expense of constructing a module and attempting
2327c478bd9Sstevel@tonic-gate 	 * to load it, do a quick check to see if the pathname is valid.
2337c478bd9Sstevel@tonic-gate 	 */
2347c478bd9Sstevel@tonic-gate 	if (access(path, F_OK) != 0) {
2357c478bd9Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_MODNOENT;
2367c478bd9Sstevel@tonic-gate 		return (TRUE);
2377c478bd9Sstevel@tonic-gate 	}
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	if ((p = strrchr(path, '.')) != NULL && strcmp(p, ".so") == 0)
2407c478bd9Sstevel@tonic-gate 		mp = fmd_modhash_load(fmd.d_mod_hash, path, &fmd_rtld_ops);
2417c478bd9Sstevel@tonic-gate 	else
2427c478bd9Sstevel@tonic-gate 		mp = fmd_modhash_load(fmd.d_mod_hash, path, &fmd_proc_ops);
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	if (mp == NULL) {
2457c478bd9Sstevel@tonic-gate 		switch (errno) {
2467c478bd9Sstevel@tonic-gate 		case EFMD_MOD_LOADED:
2477c478bd9Sstevel@tonic-gate 			err = FMD_ADM_ERR_MODEXIST;
2487c478bd9Sstevel@tonic-gate 			break;
2497c478bd9Sstevel@tonic-gate 		case EFMD_MOD_INIT:
2507c478bd9Sstevel@tonic-gate 			err = FMD_ADM_ERR_MODINIT;
2517c478bd9Sstevel@tonic-gate 			break;
2527c478bd9Sstevel@tonic-gate 		default:
2537c478bd9Sstevel@tonic-gate 			err = FMD_ADM_ERR_MODLOAD;
2547c478bd9Sstevel@tonic-gate 			break;
2557c478bd9Sstevel@tonic-gate 		}
2567c478bd9Sstevel@tonic-gate 	}
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	*rvp = err;
2597c478bd9Sstevel@tonic-gate 	return (TRUE);
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate bool_t
fmd_adm_modunload_1_svc(char * name,int * rvp,struct svc_req * req)2637c478bd9Sstevel@tonic-gate fmd_adm_modunload_1_svc(char *name, int *rvp, struct svc_req *req)
2647c478bd9Sstevel@tonic-gate {
2657c478bd9Sstevel@tonic-gate 	fmd_module_t *mp = NULL;
2667c478bd9Sstevel@tonic-gate 	int err = 0;
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	if (fmd_rpc_deny(req))
2697c478bd9Sstevel@tonic-gate 		err = FMD_ADM_ERR_PERM;
2707c478bd9Sstevel@tonic-gate 	else if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, name)) == NULL)
2717c478bd9Sstevel@tonic-gate 		err = FMD_ADM_ERR_MODSRCH;
2727c478bd9Sstevel@tonic-gate 	else if (mp == fmd.d_self)
2737c478bd9Sstevel@tonic-gate 		err = FMD_ADM_ERR_MODBUSY;
2747c478bd9Sstevel@tonic-gate 	else if (fmd_modhash_unload(fmd.d_mod_hash, name) != 0)
2757c478bd9Sstevel@tonic-gate 		err = FMD_ADM_ERR_MODSRCH;
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	if (mp != NULL)
2787c478bd9Sstevel@tonic-gate 		fmd_module_rele(mp);
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	*rvp = err;
2817c478bd9Sstevel@tonic-gate 	return (TRUE);
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate bool_t
fmd_adm_modreset_1_svc(char * name,int * rvp,struct svc_req * req)2857c478bd9Sstevel@tonic-gate fmd_adm_modreset_1_svc(char *name, int *rvp, struct svc_req *req)
2867c478bd9Sstevel@tonic-gate {
2877c478bd9Sstevel@tonic-gate 	fmd_module_t *mp = NULL;
2887c478bd9Sstevel@tonic-gate 	int err = 0;
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	if (fmd_rpc_deny(req))
2917c478bd9Sstevel@tonic-gate 		err = FMD_ADM_ERR_PERM;
2927c478bd9Sstevel@tonic-gate 	else if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, name)) == NULL)
2937c478bd9Sstevel@tonic-gate 		err = FMD_ADM_ERR_MODSRCH;
2947c478bd9Sstevel@tonic-gate 	else if (mp == fmd.d_self)
2957c478bd9Sstevel@tonic-gate 		err = FMD_ADM_ERR_MODBUSY;
2967c478bd9Sstevel@tonic-gate 	else if (fmd_modhash_unload(fmd.d_mod_hash, name) != 0)
2977c478bd9Sstevel@tonic-gate 		err = FMD_ADM_ERR_MODSRCH;
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	if (err == 0)
3007c478bd9Sstevel@tonic-gate 		fmd_ckpt_delete(mp); /* erase any saved checkpoints */
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 	if (err == 0 && fmd_modhash_load(fmd.d_mod_hash,
3037c478bd9Sstevel@tonic-gate 	    mp->mod_path, mp->mod_ops) == NULL) {
3047c478bd9Sstevel@tonic-gate 		if (errno == EFMD_MOD_INIT)
3057c478bd9Sstevel@tonic-gate 			err = FMD_ADM_ERR_MODINIT;
3067c478bd9Sstevel@tonic-gate 		else
3077c478bd9Sstevel@tonic-gate 			err = FMD_ADM_ERR_MODLOAD;
3087c478bd9Sstevel@tonic-gate 	}
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	if (mp != NULL)
3117c478bd9Sstevel@tonic-gate 		fmd_module_rele(mp);
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 	*rvp = err;
3147c478bd9Sstevel@tonic-gate 	return (TRUE);
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate bool_t
fmd_adm_modgc_1_svc(char * name,int * rvp,struct svc_req * req)3187c478bd9Sstevel@tonic-gate fmd_adm_modgc_1_svc(char *name, int *rvp, struct svc_req *req)
3197c478bd9Sstevel@tonic-gate {
3207c478bd9Sstevel@tonic-gate 	fmd_module_t *mp;
3217c478bd9Sstevel@tonic-gate 	int err = 0;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	if (fmd_rpc_deny(req))
3247c478bd9Sstevel@tonic-gate 		err = FMD_ADM_ERR_PERM;
3257c478bd9Sstevel@tonic-gate 	else if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, name)) == NULL)
3267c478bd9Sstevel@tonic-gate 		err = FMD_ADM_ERR_MODSRCH;
3277c478bd9Sstevel@tonic-gate 	else {
3287c478bd9Sstevel@tonic-gate 		fmd_module_gc(mp);
3297c478bd9Sstevel@tonic-gate 		fmd_module_rele(mp);
3307c478bd9Sstevel@tonic-gate 	}
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	*rvp = err;
3337c478bd9Sstevel@tonic-gate 	return (TRUE);
3347c478bd9Sstevel@tonic-gate }
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate /*
3377c478bd9Sstevel@tonic-gate  * Unlike our other RPC callbacks, fmd_adm_rsrclist_1 can return large amounts
3387c478bd9Sstevel@tonic-gate  * of data that may exceed the underlying RPC transport buffer size if the
3397c478bd9Sstevel@tonic-gate  * resource cache is heavily populated and/or all resources are requested.
3407c478bd9Sstevel@tonic-gate  * To minimize the likelihood of running out of RPC buffer space and having to
3417c478bd9Sstevel@tonic-gate  * fail the client request, fmd_adm_rsrclist_1 returns a snapshot of the
3427c478bd9Sstevel@tonic-gate  * relevant FMRI strings only: the client can use fmd_adm_rsrcinfo_1 on an
3437c478bd9Sstevel@tonic-gate  * individual FMRI if more information is needed.  To further reduce the XDR
3447c478bd9Sstevel@tonic-gate  * overhead, the string list is represented as XDR-opaque data where the
3457c478bd9Sstevel@tonic-gate  * entire list is returned as a string table (e.g. "fmriA\0fmriB\0...").
3467c478bd9Sstevel@tonic-gate  */
3477c478bd9Sstevel@tonic-gate static void
fmd_adm_rsrclist_asru(fmd_asru_t * ap,void * arg)3487c478bd9Sstevel@tonic-gate fmd_adm_rsrclist_asru(fmd_asru_t *ap, void *arg)
3497c478bd9Sstevel@tonic-gate {
3507c478bd9Sstevel@tonic-gate 	struct fmd_rpc_rsrclist *rrl = arg;
3517c478bd9Sstevel@tonic-gate 	size_t name_len, buf_len;
3527c478bd9Sstevel@tonic-gate 	void *p;
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	/*
35544743693Sstephh 	 * Skip the ASRU if this fault is marked as invisible.
3567c478bd9Sstevel@tonic-gate 	 * If rrl_all is false, we take a quick look at asru_flags with no lock
35744743693Sstephh 	 * held to see if the ASRU is not faulty.  If so,
3587c478bd9Sstevel@tonic-gate 	 * we don't want to report it by default and can just skip this ASRU.
3597c478bd9Sstevel@tonic-gate 	 * This helps keep overhead low in the common case, as the call to
3607c478bd9Sstevel@tonic-gate 	 * fmd_asru_getstate() can be expensive depending on the scheme.
3617c478bd9Sstevel@tonic-gate 	 */
36244743693Sstephh 
36344743693Sstephh 	if (ap->asru_flags & FMD_ASRU_INVISIBLE)
36444743693Sstephh 		return;
36544743693Sstephh 	if (rrl->rrl_all == B_FALSE && !(ap->asru_flags & FMD_ASRU_FAULTY))
3667c478bd9Sstevel@tonic-gate 		return;
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	if (rrl->rrl_err != 0 || fmd_asru_getstate(ap) == 0)
3697c478bd9Sstevel@tonic-gate 		return; /* error has occurred or resource is in 'ok' state */
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	/*
3727c478bd9Sstevel@tonic-gate 	 * Lock the ASRU and reallocate rrl_buf[] to be large enough to hold
3737c478bd9Sstevel@tonic-gate 	 * another string, doubling it as needed.  Then copy the new string
3747c478bd9Sstevel@tonic-gate 	 * on to the end, and increment rrl_len to indicate the used space.
3757c478bd9Sstevel@tonic-gate 	 */
3767c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ap->asru_lock);
3777c478bd9Sstevel@tonic-gate 	name_len = strlen(ap->asru_name) + 1;
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	while (rrl->rrl_len + name_len > rrl->rrl_buf.rrl_buf_len) {
3807c478bd9Sstevel@tonic-gate 		if (rrl->rrl_buf.rrl_buf_len != 0)
3817c478bd9Sstevel@tonic-gate 			buf_len = rrl->rrl_buf.rrl_buf_len * 2;
3827c478bd9Sstevel@tonic-gate 		else
3837c478bd9Sstevel@tonic-gate 			buf_len = 1024; /* default buffer size */
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 		if ((p = realloc(rrl->rrl_buf.rrl_buf_val, buf_len)) != NULL) {
3867c478bd9Sstevel@tonic-gate 			bzero((char *)p + rrl->rrl_buf.rrl_buf_len,
3877c478bd9Sstevel@tonic-gate 			    buf_len - rrl->rrl_buf.rrl_buf_len);
3887c478bd9Sstevel@tonic-gate 			rrl->rrl_buf.rrl_buf_val = p;
3897c478bd9Sstevel@tonic-gate 			rrl->rrl_buf.rrl_buf_len = buf_len;
3907c478bd9Sstevel@tonic-gate 		} else {
3917c478bd9Sstevel@tonic-gate 			rrl->rrl_err = FMD_ADM_ERR_NOMEM;
3927c478bd9Sstevel@tonic-gate 			break;
3937c478bd9Sstevel@tonic-gate 		}
3947c478bd9Sstevel@tonic-gate 	}
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	if (rrl->rrl_err == 0) {
3977c478bd9Sstevel@tonic-gate 		bcopy(ap->asru_name, (char *)rrl->rrl_buf.rrl_buf_val +
3987c478bd9Sstevel@tonic-gate 		    rrl->rrl_len, name_len);
3997c478bd9Sstevel@tonic-gate 		rrl->rrl_len += name_len;
4007c478bd9Sstevel@tonic-gate 		rrl->rrl_cnt++;
4017c478bd9Sstevel@tonic-gate 	}
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ap->asru_lock);
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate bool_t
fmd_adm_rsrclist_1_svc(bool_t all,struct fmd_rpc_rsrclist * rvp,struct svc_req * req)4077c478bd9Sstevel@tonic-gate fmd_adm_rsrclist_1_svc(bool_t all,
4087c478bd9Sstevel@tonic-gate     struct fmd_rpc_rsrclist *rvp, struct svc_req *req)
4097c478bd9Sstevel@tonic-gate {
4107c478bd9Sstevel@tonic-gate 	rvp->rrl_buf.rrl_buf_len = 0;
4117c478bd9Sstevel@tonic-gate 	rvp->rrl_buf.rrl_buf_val = NULL;
4127c478bd9Sstevel@tonic-gate 	rvp->rrl_len = 0;
4137c478bd9Sstevel@tonic-gate 	rvp->rrl_cnt = 0;
4147c478bd9Sstevel@tonic-gate 	rvp->rrl_err = 0;
4157c478bd9Sstevel@tonic-gate 	rvp->rrl_all = all;
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	if (fmd_rpc_deny(req))
4187c478bd9Sstevel@tonic-gate 		rvp->rrl_err = FMD_ADM_ERR_PERM;
4197c478bd9Sstevel@tonic-gate 	else
4207c478bd9Sstevel@tonic-gate 		fmd_asru_hash_apply(fmd.d_asrus, fmd_adm_rsrclist_asru, rvp);
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 	return (TRUE);
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate bool_t
fmd_adm_rsrcinfo_1_svc(char * fmri,struct fmd_rpc_rsrcinfo * rvp,struct svc_req * req)4267c478bd9Sstevel@tonic-gate fmd_adm_rsrcinfo_1_svc(char *fmri,
4277c478bd9Sstevel@tonic-gate     struct fmd_rpc_rsrcinfo *rvp, struct svc_req *req)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate 	fmd_asru_t *ap;
430d9638e54Smws 	fmd_case_impl_t *cip;
4317c478bd9Sstevel@tonic-gate 	int state;
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	bzero(rvp, sizeof (struct fmd_rpc_rsrcinfo));
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
4367c478bd9Sstevel@tonic-gate 		rvp->rri_err = FMD_ADM_ERR_PERM;
4377c478bd9Sstevel@tonic-gate 		return (TRUE);
4387c478bd9Sstevel@tonic-gate 	}
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	if ((ap = fmd_asru_hash_lookup_name(fmd.d_asrus, fmri)) == NULL) {
4417c478bd9Sstevel@tonic-gate 		rvp->rri_err = FMD_ADM_ERR_RSRCSRCH;
4427c478bd9Sstevel@tonic-gate 		return (TRUE);
4437c478bd9Sstevel@tonic-gate 	}
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	state = fmd_asru_getstate(ap);
4467c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ap->asru_lock);
447d9638e54Smws 	cip = (fmd_case_impl_t *)ap->asru_case;
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	rvp->rri_fmri = strdup(ap->asru_name);
4507c478bd9Sstevel@tonic-gate 	rvp->rri_uuid = strdup(ap->asru_uuid);
451d9638e54Smws 	rvp->rri_case = cip ? strdup(cip->ci_uuid) : NULL;
4527c478bd9Sstevel@tonic-gate 	rvp->rri_faulty = (state & FMD_ASRU_FAULTY) != 0;
4537c478bd9Sstevel@tonic-gate 	rvp->rri_unusable = (state & FMD_ASRU_UNUSABLE) != 0;
4547c478bd9Sstevel@tonic-gate 	rvp->rri_invisible = (ap->asru_flags & FMD_ASRU_INVISIBLE) != 0;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ap->asru_lock);
4577c478bd9Sstevel@tonic-gate 	fmd_asru_hash_release(fmd.d_asrus, ap);
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 	if (rvp->rri_fmri == NULL || rvp->rri_uuid == NULL)
4607c478bd9Sstevel@tonic-gate 		rvp->rri_err = FMD_ADM_ERR_NOMEM;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	return (TRUE);
4637c478bd9Sstevel@tonic-gate }
4647c478bd9Sstevel@tonic-gate 
465cbf75e67SStephen Hanson static void
fmd_adm_do_repair(char * name,struct svc_req * req,int * errp,uint8_t reason,char * uuid)466cbf75e67SStephen Hanson fmd_adm_do_repair(char *name, struct svc_req *req, int *errp, uint8_t reason,
467cbf75e67SStephen Hanson     char *uuid)
4687c478bd9Sstevel@tonic-gate {
4697c478bd9Sstevel@tonic-gate 	if (fmd_rpc_deny(req))
470cbf75e67SStephen Hanson 		*errp = FMD_ADM_ERR_PERM;
471d9638e54Smws 	else {
472cbf75e67SStephen Hanson 		fmd_asru_rep_arg_t fara;
4736e1fa242SStephen Hanson 		int err = FARA_ERR_RSRCNOTF;
474cbf75e67SStephen Hanson 
475cbf75e67SStephen Hanson 		fara.fara_reason = reason;
4766e1fa242SStephen Hanson 		fara.fara_rval = &err;
477cbf75e67SStephen Hanson 		fara.fara_uuid = uuid;
478cbf75e67SStephen Hanson 		fara.fara_bywhat = FARA_BY_ASRU;
479567cc2e6Sstephh 		fmd_asru_hash_apply_by_asru(fmd.d_asrus, name,
480cbf75e67SStephen Hanson 		    fmd_asru_repaired, &fara);
481cbf75e67SStephen Hanson 		fara.fara_bywhat = FARA_BY_LABEL;
482567cc2e6Sstephh 		fmd_asru_hash_apply_by_label(fmd.d_asrus, name,
483cbf75e67SStephen Hanson 		    fmd_asru_repaired, &fara);
484cbf75e67SStephen Hanson 		fara.fara_bywhat = FARA_BY_FRU;
485567cc2e6Sstephh 		fmd_asru_hash_apply_by_fru(fmd.d_asrus, name,
486cbf75e67SStephen Hanson 		    fmd_asru_repaired, &fara);
487cbf75e67SStephen Hanson 		fara.fara_bywhat = FARA_BY_RSRC;
488567cc2e6Sstephh 		fmd_asru_hash_apply_by_rsrc(fmd.d_asrus, name,
489cbf75e67SStephen Hanson 		    fmd_asru_repaired, &fara);
4906e1fa242SStephen Hanson 		if (err == FARA_ERR_RSRCNOTR)
4916e1fa242SStephen Hanson 			*errp = FMD_ADM_ERR_RSRCNOTR;
4926e1fa242SStephen Hanson 		else if (err == FARA_OK)
4936e1fa242SStephen Hanson 			*errp = 0;
49425c6ff4bSstephh 	}
495cbf75e67SStephen Hanson }
496cbf75e67SStephen Hanson 
497cbf75e67SStephen Hanson bool_t
fmd_adm_rsrcflush_1_svc(char * name,int * rvp,struct svc_req * req)498cbf75e67SStephen Hanson fmd_adm_rsrcflush_1_svc(char *name, int *rvp, struct svc_req *req)
499cbf75e67SStephen Hanson {
500cbf75e67SStephen Hanson 	int err = FMD_ADM_ERR_RSRCNOTF;
501cbf75e67SStephen Hanson 
5025750ef5cSStephen Hanson 	/*
5035750ef5cSStephen Hanson 	 * If anyone does an fmadm flush command, discard any resolved
5045750ef5cSStephen Hanson 	 * cases that were being retained for historic diagnosis.
5055750ef5cSStephen Hanson 	 */
5065750ef5cSStephen Hanson 	if (fmd_rpc_deny(req))
5075750ef5cSStephen Hanson 		err = FMD_ADM_ERR_PERM;
5085750ef5cSStephen Hanson 	else {
5095750ef5cSStephen Hanson 		fmd_asru_hash_apply_by_asru(fmd.d_asrus, name,
5105750ef5cSStephen Hanson 		    fmd_asru_flush, &err);
5115750ef5cSStephen Hanson 		fmd_asru_hash_apply_by_label(fmd.d_asrus, name,
5125750ef5cSStephen Hanson 		    fmd_asru_flush, &err);
5135750ef5cSStephen Hanson 		fmd_asru_hash_apply_by_fru(fmd.d_asrus, name,
5145750ef5cSStephen Hanson 		    fmd_asru_flush, &err);
5155750ef5cSStephen Hanson 		fmd_asru_hash_apply_by_rsrc(fmd.d_asrus, name,
5165750ef5cSStephen Hanson 		    fmd_asru_flush, &err);
5175750ef5cSStephen Hanson 	}
51825c6ff4bSstephh 	*rvp = err;
51925c6ff4bSstephh 	return (TRUE);
52025c6ff4bSstephh }
52125c6ff4bSstephh 
52225c6ff4bSstephh bool_t
fmd_adm_rsrcrepaired_1_svc(char * name,int * rvp,struct svc_req * req)523cbf75e67SStephen Hanson fmd_adm_rsrcrepaired_1_svc(char *name, int *rvp, struct svc_req *req)
52425c6ff4bSstephh {
52525c6ff4bSstephh 	int err = FMD_ADM_ERR_RSRCNOTF;
52625c6ff4bSstephh 
527cbf75e67SStephen Hanson 	fmd_adm_do_repair(name, req, &err, FMD_ASRU_REPAIRED, NULL);
52825c6ff4bSstephh 	*rvp = err;
52925c6ff4bSstephh 	return (TRUE);
53025c6ff4bSstephh }
53125c6ff4bSstephh 
532cbf75e67SStephen Hanson bool_t
fmd_adm_rsrcreplaced_1_svc(char * name,int * rvp,struct svc_req * req)533cbf75e67SStephen Hanson fmd_adm_rsrcreplaced_1_svc(char *name, int *rvp, struct svc_req *req)
53425c6ff4bSstephh {
535cbf75e67SStephen Hanson 	int err = FMD_ADM_ERR_RSRCNOTF;
53625c6ff4bSstephh 
537cbf75e67SStephen Hanson 	fmd_adm_do_repair(name, req, &err, FMD_ASRU_REPLACED, NULL);
538cbf75e67SStephen Hanson 	*rvp = err;
539cbf75e67SStephen Hanson 	return (TRUE);
54025c6ff4bSstephh }
54125c6ff4bSstephh 
54225c6ff4bSstephh bool_t
fmd_adm_rsrcacquit_1_svc(char * name,char * uuid,int * rvp,struct svc_req * req)54325c6ff4bSstephh fmd_adm_rsrcacquit_1_svc(char *name, char *uuid, int *rvp, struct svc_req *req)
54425c6ff4bSstephh {
54525c6ff4bSstephh 	int err = FMD_ADM_ERR_RSRCNOTF;
54625c6ff4bSstephh 
547cbf75e67SStephen Hanson 	fmd_adm_do_repair(name, req, &err, FMD_ASRU_ACQUITTED, uuid);
5487c478bd9Sstevel@tonic-gate 	*rvp = err;
5497c478bd9Sstevel@tonic-gate 	return (TRUE);
5507c478bd9Sstevel@tonic-gate }
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate static void
fmd_adm_serdlist_measure(fmd_serd_eng_t * sgp,void * arg)5531e6f4912SJakub Jermar fmd_adm_serdlist_measure(fmd_serd_eng_t *sgp, void *arg)
5547c478bd9Sstevel@tonic-gate {
5557c478bd9Sstevel@tonic-gate 	struct fmd_rpc_serdlist *rsl = arg;
5567c478bd9Sstevel@tonic-gate 
5571e6f4912SJakub Jermar 	rsl->rsl_len += strlen(sgp->sg_name) + 1;
5581e6f4912SJakub Jermar 	rsl->rsl_cnt++;
5591e6f4912SJakub Jermar }
5601e6f4912SJakub Jermar 
5611e6f4912SJakub Jermar static void
fmd_adm_serdlist_record(fmd_serd_eng_t * sgp,void * arg)5621e6f4912SJakub Jermar fmd_adm_serdlist_record(fmd_serd_eng_t *sgp, void *arg)
5631e6f4912SJakub Jermar {
5641e6f4912SJakub Jermar 	struct fmd_rpc_serdlist *rsl = arg;
5651e6f4912SJakub Jermar 
5661e6f4912SJakub Jermar 	bcopy(sgp->sg_name, rsl->rsl_buf.rsl_buf_val + rsl->rsl_len,
5671e6f4912SJakub Jermar 	    strlen(sgp->sg_name));
5681e6f4912SJakub Jermar 	rsl->rsl_len += strlen(sgp->sg_name) + 1;
5691e6f4912SJakub Jermar }
5701e6f4912SJakub Jermar 
5711e6f4912SJakub Jermar bool_t
fmd_adm_serdlist_1_svc(char * name,struct fmd_rpc_serdlist * rvp,struct svc_req * req)5721e6f4912SJakub Jermar fmd_adm_serdlist_1_svc(char *name, struct fmd_rpc_serdlist *rvp,
5731e6f4912SJakub Jermar     struct svc_req *req)
5741e6f4912SJakub Jermar {
5751e6f4912SJakub Jermar 	fmd_module_t *mp;
5761e6f4912SJakub Jermar 	void *p;
5771e6f4912SJakub Jermar 
5781e6f4912SJakub Jermar 	rvp->rsl_buf.rsl_buf_len = 0;
5791e6f4912SJakub Jermar 	rvp->rsl_buf.rsl_buf_val = NULL;
5801e6f4912SJakub Jermar 	rvp->rsl_len = 0;
5811e6f4912SJakub Jermar 	rvp->rsl_cnt = 0;
5821e6f4912SJakub Jermar 	rvp->rsl_err = 0;
5831e6f4912SJakub Jermar 
5841e6f4912SJakub Jermar 	if (fmd_rpc_deny(req)) {
5851e6f4912SJakub Jermar 		rvp->rsl_err = FMD_ADM_ERR_PERM;
5861e6f4912SJakub Jermar 		return (TRUE);
5871e6f4912SJakub Jermar 	}
5881e6f4912SJakub Jermar 
5891e6f4912SJakub Jermar 	if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, name)) == NULL) {
5901e6f4912SJakub Jermar 		rvp->rsl_err = FMD_ADM_ERR_MODSRCH;
5911e6f4912SJakub Jermar 		return (TRUE);
5921e6f4912SJakub Jermar 	}
5931e6f4912SJakub Jermar 
5941e6f4912SJakub Jermar 	fmd_module_lock(mp);
5951e6f4912SJakub Jermar 	/* In the first pass, collect the overall length of the buffer. */
5961e6f4912SJakub Jermar 	fmd_serd_hash_apply(&mp->mod_serds, fmd_adm_serdlist_measure, rvp);
5971e6f4912SJakub Jermar 	if (rvp->rsl_len == 0) {
5981e6f4912SJakub Jermar 		fmd_module_unlock(mp);
5991e6f4912SJakub Jermar 		fmd_module_rele(mp);
6001e6f4912SJakub Jermar 		return (TRUE);
6011e6f4912SJakub Jermar 	}
6021e6f4912SJakub Jermar 	p = malloc(rvp->rsl_len);
6031e6f4912SJakub Jermar 	if (p) {
6041e6f4912SJakub Jermar 		rvp->rsl_buf.rsl_buf_val = p;
6051e6f4912SJakub Jermar 		rvp->rsl_buf.rsl_buf_len = rvp->rsl_len;
6061e6f4912SJakub Jermar 		bzero(rvp->rsl_buf.rsl_buf_val, rvp->rsl_buf.rsl_buf_len);
6071e6f4912SJakub Jermar 		rvp->rsl_len = 0;
6081e6f4912SJakub Jermar 		/* In the second pass, populate the buffer with data. */
6091e6f4912SJakub Jermar 		fmd_serd_hash_apply(&mp->mod_serds, fmd_adm_serdlist_record,
6101e6f4912SJakub Jermar 		    rvp);
6111e6f4912SJakub Jermar 	} else {
6121e6f4912SJakub Jermar 		rvp->rsl_err = FMD_ADM_ERR_NOMEM;
6131e6f4912SJakub Jermar 	}
6141e6f4912SJakub Jermar 	fmd_module_unlock(mp);
6151e6f4912SJakub Jermar 
6161e6f4912SJakub Jermar 	fmd_module_rele(mp);
6171e6f4912SJakub Jermar 	return (TRUE);
6181e6f4912SJakub Jermar }
6191e6f4912SJakub Jermar 
6201e6f4912SJakub Jermar static void
fmd_adm_serdinfo_record(fmd_serd_eng_t * sgp,struct fmd_rpc_serdinfo * rsi)6211e6f4912SJakub Jermar fmd_adm_serdinfo_record(fmd_serd_eng_t *sgp, struct fmd_rpc_serdinfo *rsi)
6221e6f4912SJakub Jermar {
6237c478bd9Sstevel@tonic-gate 	uint64_t old, now = fmd_time_gethrtime();
6247c478bd9Sstevel@tonic-gate 	const fmd_serd_elem_t *oep;
6257c478bd9Sstevel@tonic-gate 
6261e6f4912SJakub Jermar 	if ((rsi->rsi_name = strdup(sgp->sg_name)) == NULL) {
6271e6f4912SJakub Jermar 		rsi->rsi_err = FMD_ADM_ERR_NOMEM;
6287c478bd9Sstevel@tonic-gate 		return;
6297c478bd9Sstevel@tonic-gate 	}
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	if ((oep = fmd_list_next(&sgp->sg_list)) != NULL)
6327c478bd9Sstevel@tonic-gate 		old = fmd_event_hrtime(oep->se_event);
6337c478bd9Sstevel@tonic-gate 	else
6347c478bd9Sstevel@tonic-gate 		old = now;
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	rsi->rsi_delta = now >= old ? now - old : (UINT64_MAX - old) + now + 1;
6377c478bd9Sstevel@tonic-gate 	rsi->rsi_count = sgp->sg_count;
6387c478bd9Sstevel@tonic-gate 	rsi->rsi_fired = fmd_serd_eng_fired(sgp) != 0;
6397c478bd9Sstevel@tonic-gate 	rsi->rsi_n = sgp->sg_n;
6407c478bd9Sstevel@tonic-gate 	rsi->rsi_t = sgp->sg_t;
6417c478bd9Sstevel@tonic-gate }
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate bool_t
fmd_adm_serdinfo_1_svc(char * mname,char * sname,struct fmd_rpc_serdinfo * rvp,struct svc_req * req)6441e6f4912SJakub Jermar fmd_adm_serdinfo_1_svc(char *mname, char *sname, struct fmd_rpc_serdinfo *rvp,
6451e6f4912SJakub Jermar     struct svc_req *req)
6467c478bd9Sstevel@tonic-gate {
6477c478bd9Sstevel@tonic-gate 	fmd_module_t *mp;
6481e6f4912SJakub Jermar 	fmd_serd_eng_t *sgp;
6497c478bd9Sstevel@tonic-gate 
6501e6f4912SJakub Jermar 	bzero(rvp, sizeof (struct fmd_rpc_serdinfo));
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
6531e6f4912SJakub Jermar 		rvp->rsi_err = FMD_ADM_ERR_PERM;
6547c478bd9Sstevel@tonic-gate 		return (TRUE);
6557c478bd9Sstevel@tonic-gate 	}
6567c478bd9Sstevel@tonic-gate 
6571e6f4912SJakub Jermar 	if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, mname)) == NULL) {
6581e6f4912SJakub Jermar 		rvp->rsi_err = FMD_ADM_ERR_MODSRCH;
6597c478bd9Sstevel@tonic-gate 		return (TRUE);
6607c478bd9Sstevel@tonic-gate 	}
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 	fmd_module_lock(mp);
6637c478bd9Sstevel@tonic-gate 
6641e6f4912SJakub Jermar 	if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, sname)) != NULL) {
6651e6f4912SJakub Jermar 		fmd_adm_serdinfo_record(sgp, rvp);
6661e6f4912SJakub Jermar 	} else
6671e6f4912SJakub Jermar 		rvp->rsi_err = FMD_ADM_ERR_SERDSRCH;
6681e6f4912SJakub Jermar 
6691e6f4912SJakub Jermar 	fmd_module_unlock(mp);
6707c478bd9Sstevel@tonic-gate 	fmd_module_rele(mp);
6711e6f4912SJakub Jermar 
6727c478bd9Sstevel@tonic-gate 	return (TRUE);
6737c478bd9Sstevel@tonic-gate }
6747c478bd9Sstevel@tonic-gate 
6751e6f4912SJakub Jermar /*ARGSUSED*/
6761e6f4912SJakub Jermar bool_t
fmd_adm_serdinfo_old_1_svc(char * name,struct fmd_rpc_serdlist * rvp,struct svc_req * req)6771e6f4912SJakub Jermar fmd_adm_serdinfo_old_1_svc(char *name, struct fmd_rpc_serdlist *rvp,
6781e6f4912SJakub Jermar     struct svc_req *req)
6791e6f4912SJakub Jermar {
6801e6f4912SJakub Jermar 	return (FALSE);
6811e6f4912SJakub Jermar }
6821e6f4912SJakub Jermar 
6837c478bd9Sstevel@tonic-gate bool_t
fmd_adm_serdreset_1_svc(char * mname,char * sname,int * rvp,struct svc_req * req)6847c478bd9Sstevel@tonic-gate fmd_adm_serdreset_1_svc(char *mname, char *sname, int *rvp, struct svc_req *req)
6857c478bd9Sstevel@tonic-gate {
6867c478bd9Sstevel@tonic-gate 	fmd_module_t *mp;
6877c478bd9Sstevel@tonic-gate 	fmd_serd_eng_t *sgp;
6887c478bd9Sstevel@tonic-gate 	int err = 0;
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
6917c478bd9Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_PERM;
6927c478bd9Sstevel@tonic-gate 		return (TRUE);
6937c478bd9Sstevel@tonic-gate 	}
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, mname)) == NULL) {
6967c478bd9Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_MODSRCH;
6977c478bd9Sstevel@tonic-gate 		return (TRUE);
6987c478bd9Sstevel@tonic-gate 	}
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 	fmd_module_lock(mp);
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, sname)) != NULL) {
7037c478bd9Sstevel@tonic-gate 		if (fmd_serd_eng_fired(sgp)) {
7047c478bd9Sstevel@tonic-gate 			err = FMD_ADM_ERR_SERDFIRED;
7057c478bd9Sstevel@tonic-gate 		} else {
7067c478bd9Sstevel@tonic-gate 			fmd_serd_eng_reset(sgp);
7077c478bd9Sstevel@tonic-gate 			fmd_module_setdirty(mp);
7087c478bd9Sstevel@tonic-gate 		}
7097c478bd9Sstevel@tonic-gate 	} else
7107c478bd9Sstevel@tonic-gate 		err = FMD_ADM_ERR_SERDSRCH;
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	fmd_module_unlock(mp);
7137c478bd9Sstevel@tonic-gate 	fmd_module_rele(mp);
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 	*rvp = err;
7167c478bd9Sstevel@tonic-gate 	return (TRUE);
7177c478bd9Sstevel@tonic-gate }
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate bool_t
fmd_adm_logrotate_1_svc(char * name,int * rvp,struct svc_req * req)7207c478bd9Sstevel@tonic-gate fmd_adm_logrotate_1_svc(char *name, int *rvp, struct svc_req *req)
7217c478bd9Sstevel@tonic-gate {
7227c478bd9Sstevel@tonic-gate 	fmd_log_t **lpp, *old, *new;
7237c478bd9Sstevel@tonic-gate 	int try = 1, trylimit = 1;
724f6e214c7SGavin Maltby 	pthread_rwlock_t *lockp;
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 	hrtime_t nsec = 0;
7277c478bd9Sstevel@tonic-gate 	timespec_t tv;
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
7307c478bd9Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_PERM;
7317c478bd9Sstevel@tonic-gate 		return (TRUE);
7327c478bd9Sstevel@tonic-gate 	}
7337c478bd9Sstevel@tonic-gate 
734f6e214c7SGavin Maltby 	if (strcmp(name, "errlog") == 0) {
7357c478bd9Sstevel@tonic-gate 		lpp = &fmd.d_errlog;
736f6e214c7SGavin Maltby 		lockp = &fmd.d_log_lock;
737f6e214c7SGavin Maltby 	} else if (strcmp(name, "fltlog") == 0) {
7387c478bd9Sstevel@tonic-gate 		lpp = &fmd.d_fltlog;
739f6e214c7SGavin Maltby 		lockp = &fmd.d_log_lock;
740f6e214c7SGavin Maltby 	} else if (strcmp(name, "infolog") == 0) {
741f6e214c7SGavin Maltby 		lpp = &fmd.d_ilog;
742f6e214c7SGavin Maltby 		lockp = &fmd.d_ilog_lock;
743f6e214c7SGavin Maltby 	} else if (strcmp(name, "infolog_hival") == 0) {
744f6e214c7SGavin Maltby 		lpp = &fmd.d_hvilog;
745f6e214c7SGavin Maltby 		lockp = &fmd.d_hvilog_lock;
746f6e214c7SGavin Maltby 	} else {
7477c478bd9Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_ROTSRCH;
7487c478bd9Sstevel@tonic-gate 		return (TRUE);
7497c478bd9Sstevel@tonic-gate 	}
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 	(void) fmd_conf_getprop(fmd.d_conf, "log.tryrotate", &trylimit);
7527c478bd9Sstevel@tonic-gate 	(void) fmd_conf_getprop(fmd.d_conf, "log.waitrotate", &nsec);
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 	tv.tv_sec = nsec / NANOSEC;
7557c478bd9Sstevel@tonic-gate 	tv.tv_nsec = nsec % NANOSEC;
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate 	/*
7587c478bd9Sstevel@tonic-gate 	 * To rotate a log file, grab d_log_lock as writer to make sure no
7597c478bd9Sstevel@tonic-gate 	 * one else can discover the current log pointer.  Then try to rotate
7607c478bd9Sstevel@tonic-gate 	 * the log.  If we're successful, release the old log pointer.
7617c478bd9Sstevel@tonic-gate 	 */
7627c478bd9Sstevel@tonic-gate 	do {
7637c478bd9Sstevel@tonic-gate 		if (try > 1)
7647c478bd9Sstevel@tonic-gate 			(void) nanosleep(&tv, NULL); /* wait for checkpoints */
7657c478bd9Sstevel@tonic-gate 
766f6e214c7SGavin Maltby 		(void) pthread_rwlock_wrlock(lockp);
7677c478bd9Sstevel@tonic-gate 		old = *lpp;
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 		if ((new = fmd_log_rotate(old)) != NULL) {
7707c478bd9Sstevel@tonic-gate 			fmd_log_rele(old);
7717c478bd9Sstevel@tonic-gate 			*lpp = new;
7727c478bd9Sstevel@tonic-gate 		}
7737c478bd9Sstevel@tonic-gate 
774f6e214c7SGavin Maltby 		(void) pthread_rwlock_unlock(lockp);
7757c478bd9Sstevel@tonic-gate 
7767c478bd9Sstevel@tonic-gate 	} while (new == NULL && errno == EFMD_LOG_ROTBUSY && try++ < trylimit);
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	if (new != NULL)
7797c478bd9Sstevel@tonic-gate 		*rvp = 0;
7807c478bd9Sstevel@tonic-gate 	else if (errno == EFMD_LOG_ROTBUSY)
7817c478bd9Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_ROTBUSY;
7827c478bd9Sstevel@tonic-gate 	else
7837c478bd9Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_ROTFAIL;
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate 	return (TRUE);
7867c478bd9Sstevel@tonic-gate }
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate bool_t
fmd_adm_caserepair_1_svc(char * uuid,int * rvp,struct svc_req * req)7897c478bd9Sstevel@tonic-gate fmd_adm_caserepair_1_svc(char *uuid, int *rvp, struct svc_req *req)
7907c478bd9Sstevel@tonic-gate {
7917c478bd9Sstevel@tonic-gate 	fmd_case_t *cp = NULL;
7927c478bd9Sstevel@tonic-gate 	int err = 0;
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 	if (fmd_rpc_deny(req))
7957c478bd9Sstevel@tonic-gate 		err = FMD_ADM_ERR_PERM;
7967c478bd9Sstevel@tonic-gate 	else if ((cp = fmd_case_hash_lookup(fmd.d_cases, uuid)) == NULL)
7977c478bd9Sstevel@tonic-gate 		err = FMD_ADM_ERR_CASESRCH;
798162ba6eaSmws 	else if (fmd_case_repair(cp) != 0) {
799d9638e54Smws 		err = errno == EFMD_CASE_OWNER ?
800d9638e54Smws 		    FMD_ADM_ERR_CASEXPRT : FMD_ADM_ERR_CASEOPEN;
801d9638e54Smws 	}
802d9638e54Smws 
80325c6ff4bSstephh 	if (cp != NULL)
80425c6ff4bSstephh 		fmd_case_rele(cp);
80525c6ff4bSstephh 
80625c6ff4bSstephh 	*rvp = err;
80725c6ff4bSstephh 	return (TRUE);
80825c6ff4bSstephh }
80925c6ff4bSstephh 
81025c6ff4bSstephh bool_t
fmd_adm_caseacquit_1_svc(char * uuid,int * rvp,struct svc_req * req)81125c6ff4bSstephh fmd_adm_caseacquit_1_svc(char *uuid, int *rvp, struct svc_req *req)
81225c6ff4bSstephh {
81325c6ff4bSstephh 	fmd_case_t *cp = NULL;
81425c6ff4bSstephh 	int err = 0;
81525c6ff4bSstephh 
81625c6ff4bSstephh 	if (fmd_rpc_deny(req))
81725c6ff4bSstephh 		err = FMD_ADM_ERR_PERM;
81825c6ff4bSstephh 	else if ((cp = fmd_case_hash_lookup(fmd.d_cases, uuid)) == NULL)
81925c6ff4bSstephh 		err = FMD_ADM_ERR_CASESRCH;
82025c6ff4bSstephh 	else if (fmd_case_acquit(cp) != 0) {
82125c6ff4bSstephh 		err = errno == EFMD_CASE_OWNER ?
82225c6ff4bSstephh 		    FMD_ADM_ERR_CASEXPRT : FMD_ADM_ERR_CASEOPEN;
82325c6ff4bSstephh 	}
82425c6ff4bSstephh 
825d9638e54Smws 	if (cp != NULL)
826d9638e54Smws 		fmd_case_rele(cp);
827d9638e54Smws 
828d9638e54Smws 	*rvp = err;
829d9638e54Smws 	return (TRUE);
830d9638e54Smws }
831d9638e54Smws 
832749f21d3Swesolows void
fmd_adm_caselist_case(fmd_case_t * cp,void * arg)833749f21d3Swesolows fmd_adm_caselist_case(fmd_case_t *cp, void *arg)
834749f21d3Swesolows {
835749f21d3Swesolows 	fmd_case_impl_t *cip = (fmd_case_impl_t *)cp;
836749f21d3Swesolows 	struct fmd_rpc_caselist *rcl = arg;
837749f21d3Swesolows 	size_t uuid_len, buf_len;
838749f21d3Swesolows 	void *p;
839749f21d3Swesolows 
840749f21d3Swesolows 	if (rcl->rcl_err != 0)
841749f21d3Swesolows 		return;
842749f21d3Swesolows 
84344743693Sstephh 	/*
84444743693Sstephh 	 * skip invisible cases
84544743693Sstephh 	 */
84644743693Sstephh 	if (cip->ci_flags & FMD_CF_INVISIBLE)
84744743693Sstephh 		return;
84844743693Sstephh 
849749f21d3Swesolows 	/*
850749f21d3Swesolows 	 * Lock the case and reallocate rcl_buf[] to be large enough to hold
851749f21d3Swesolows 	 * another string, doubling it as needed.  Then copy the new string
852749f21d3Swesolows 	 * on to the end, and increment rcl_len to indicate the used space.
853749f21d3Swesolows 	 */
854749f21d3Swesolows 	if (!(cip->ci_flags & FMD_CF_SOLVED))
855749f21d3Swesolows 		return;
856749f21d3Swesolows 
857749f21d3Swesolows 	(void) pthread_mutex_lock(&cip->ci_lock);
858749f21d3Swesolows 
859749f21d3Swesolows 	uuid_len = cip->ci_uuidlen + 1;
860749f21d3Swesolows 
861749f21d3Swesolows 	while (rcl->rcl_len + uuid_len > rcl->rcl_buf.rcl_buf_len) {
862749f21d3Swesolows 		if (rcl->rcl_buf.rcl_buf_len != 0)
863749f21d3Swesolows 			buf_len = rcl->rcl_buf.rcl_buf_len * 2;
864749f21d3Swesolows 		else
865749f21d3Swesolows 			buf_len = 1024; /* default buffer size */
866749f21d3Swesolows 
867749f21d3Swesolows 		if ((p = realloc(rcl->rcl_buf.rcl_buf_val, buf_len)) != NULL) {
868749f21d3Swesolows 			bzero((char *)p + rcl->rcl_buf.rcl_buf_len,
869749f21d3Swesolows 			    buf_len - rcl->rcl_buf.rcl_buf_len);
870749f21d3Swesolows 			rcl->rcl_buf.rcl_buf_val = p;
871749f21d3Swesolows 			rcl->rcl_buf.rcl_buf_len = buf_len;
872749f21d3Swesolows 		} else {
873749f21d3Swesolows 			rcl->rcl_err = FMD_ADM_ERR_NOMEM;
874749f21d3Swesolows 			break;
875749f21d3Swesolows 		}
876749f21d3Swesolows 	}
877749f21d3Swesolows 
878749f21d3Swesolows 	if (rcl->rcl_err == 0) {
879749f21d3Swesolows 		bcopy(cip->ci_uuid, (char *)rcl->rcl_buf.rcl_buf_val +
880749f21d3Swesolows 		    rcl->rcl_len, uuid_len);
881749f21d3Swesolows 		rcl->rcl_len += uuid_len;
882749f21d3Swesolows 		rcl->rcl_cnt++;
883749f21d3Swesolows 	}
884749f21d3Swesolows 
885749f21d3Swesolows 	(void) pthread_mutex_unlock(&cip->ci_lock);
886749f21d3Swesolows }
887749f21d3Swesolows 
888749f21d3Swesolows bool_t
fmd_adm_caselist_1_svc(struct fmd_rpc_caselist * rvp,struct svc_req * req)889749f21d3Swesolows fmd_adm_caselist_1_svc(struct fmd_rpc_caselist *rvp, struct svc_req *req)
890749f21d3Swesolows {
891749f21d3Swesolows 	rvp->rcl_buf.rcl_buf_len = 0;
892749f21d3Swesolows 	rvp->rcl_buf.rcl_buf_val = NULL;
893749f21d3Swesolows 	rvp->rcl_len = 0;
894749f21d3Swesolows 	rvp->rcl_cnt = 0;
895749f21d3Swesolows 	rvp->rcl_err = 0;
896749f21d3Swesolows 
897749f21d3Swesolows 	if (fmd_rpc_deny(req))
898749f21d3Swesolows 		rvp->rcl_err = FMD_ADM_ERR_PERM;
899749f21d3Swesolows 	else
900749f21d3Swesolows 		fmd_case_hash_apply(fmd.d_cases, fmd_adm_caselist_case, rvp);
901749f21d3Swesolows 
902749f21d3Swesolows 	return (TRUE);
903749f21d3Swesolows }
904749f21d3Swesolows 
905749f21d3Swesolows bool_t
fmd_adm_caseinfo_1_svc(char * uuid,struct fmd_rpc_caseinfo * rvp,struct svc_req * req)906749f21d3Swesolows fmd_adm_caseinfo_1_svc(char *uuid, struct fmd_rpc_caseinfo *rvp,
907749f21d3Swesolows     struct svc_req *req)
908749f21d3Swesolows {
90944743693Sstephh 	fmd_case_t *cp;
910749f21d3Swesolows 	nvlist_t *nvl;
911749f21d3Swesolows 	int err = 0;
912749f21d3Swesolows 
913749f21d3Swesolows 	bzero(rvp, sizeof (struct fmd_rpc_caseinfo));
914749f21d3Swesolows 
915749f21d3Swesolows 	if (fmd_rpc_deny(req)) {
916749f21d3Swesolows 		rvp->rci_err = FMD_ADM_ERR_PERM;
917749f21d3Swesolows 		return (TRUE);
918749f21d3Swesolows 	}
919749f21d3Swesolows 
92044743693Sstephh 	if ((cp = fmd_case_hash_lookup(fmd.d_cases, uuid)) == NULL) {
921749f21d3Swesolows 		rvp->rci_err = FMD_ADM_ERR_CASESRCH;
922749f21d3Swesolows 		return (TRUE);
923749f21d3Swesolows 	}
924749f21d3Swesolows 
92544743693Sstephh 	if (!(((fmd_case_impl_t *)cp)->ci_flags & FMD_CF_SOLVED)) {
92644743693Sstephh 		fmd_case_rele(cp);
927749f21d3Swesolows 		rvp->rci_err = FMD_ADM_ERR_CASESRCH;
928749f21d3Swesolows 		return (TRUE);
929749f21d3Swesolows 	}
930749f21d3Swesolows 
93144743693Sstephh 	nvl = fmd_case_mkevent(cp, FM_LIST_SUSPECT_CLASS);
932749f21d3Swesolows 
933749f21d3Swesolows 	err = nvlist_pack(nvl, &rvp->rci_evbuf.rci_evbuf_val,
934749f21d3Swesolows 	    &rvp->rci_evbuf.rci_evbuf_len, NV_ENCODE_XDR, 0);
935749f21d3Swesolows 
93644743693Sstephh 	nvlist_free(nvl);
93744743693Sstephh 
938749f21d3Swesolows 	if (err != 0)
939749f21d3Swesolows 		rvp->rci_err = FMD_ADM_ERR_NOMEM;
940749f21d3Swesolows 
94144743693Sstephh 	fmd_case_rele(cp);
942749f21d3Swesolows 
943749f21d3Swesolows 	return (TRUE);
944749f21d3Swesolows }
945749f21d3Swesolows 
946d9638e54Smws /*ARGSUSED*/
947d9638e54Smws static void
fmd_adm_xprtlist_one(fmd_idspace_t * ids,id_t id,void * arg)948d9638e54Smws fmd_adm_xprtlist_one(fmd_idspace_t *ids, id_t id, void *arg)
949d9638e54Smws {
950d9638e54Smws 	struct fmd_rpc_xprtlist *rvp = arg;
951d9638e54Smws 
952d9638e54Smws 	if (rvp->rxl_len < rvp->rxl_buf.rxl_buf_len)
953d9638e54Smws 		rvp->rxl_buf.rxl_buf_val[rvp->rxl_len++] = id;
954d9638e54Smws }
955d9638e54Smws 
956d9638e54Smws bool_t
fmd_adm_xprtlist_1_svc(struct fmd_rpc_xprtlist * rvp,struct svc_req * req)957d9638e54Smws fmd_adm_xprtlist_1_svc(struct fmd_rpc_xprtlist *rvp, struct svc_req *req)
958d9638e54Smws {
959d9638e54Smws 	if (fmd_rpc_deny(req)) {
960d9638e54Smws 		rvp->rxl_buf.rxl_buf_len = 0;
961d9638e54Smws 		rvp->rxl_buf.rxl_buf_val = NULL;
962d9638e54Smws 		rvp->rxl_len = 0;
963d9638e54Smws 		rvp->rxl_err = FMD_ADM_ERR_PERM;
964d9638e54Smws 		return (TRUE);
965d9638e54Smws 	}
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 	/*
968d9638e54Smws 	 * Since we're taking a snapshot of the transports, and these could
969d9638e54Smws 	 * change after we return our result, there's no need to hold any kind
970d9638e54Smws 	 * of lock between retrieving ids_count and taking the snapshot.  We'll
971d9638e54Smws 	 * just capture up to a maximum of whatever ids_count value we sampled.
9727c478bd9Sstevel@tonic-gate 	 */
973d9638e54Smws 	rvp->rxl_buf.rxl_buf_len = fmd.d_xprt_ids->ids_count;
974d9638e54Smws 	rvp->rxl_buf.rxl_buf_val = malloc(sizeof (int32_t) *
975d9638e54Smws 	    rvp->rxl_buf.rxl_buf_len);
976d9638e54Smws 	rvp->rxl_len = 0;
977d9638e54Smws 	rvp->rxl_err = 0;
978d9638e54Smws 
979d9638e54Smws 	if (rvp->rxl_buf.rxl_buf_val == NULL) {
980d9638e54Smws 		rvp->rxl_err = FMD_ADM_ERR_NOMEM;
981d9638e54Smws 		return (TRUE);
982d9638e54Smws 	}
9837c478bd9Sstevel@tonic-gate 
984d9638e54Smws 	fmd_idspace_apply(fmd.d_xprt_ids, fmd_adm_xprtlist_one, rvp);
985d9638e54Smws 	return (TRUE);
986d9638e54Smws }
9877c478bd9Sstevel@tonic-gate 
988d9638e54Smws bool_t
fmd_adm_xprtstat_1_svc(int32_t id,struct fmd_rpc_modstat * rms,struct svc_req * req)989d9638e54Smws fmd_adm_xprtstat_1_svc(int32_t id,
990d9638e54Smws     struct fmd_rpc_modstat *rms, struct svc_req *req)
991d9638e54Smws {
992d9638e54Smws 	fmd_xprt_impl_t *xip;
993d9638e54Smws 	fmd_stat_t *sp, *ep, *cp;
9947c478bd9Sstevel@tonic-gate 
995d9638e54Smws 	if (fmd_rpc_deny(req)) {
996d9638e54Smws 		rms->rms_buf.rms_buf_val = NULL;
997d9638e54Smws 		rms->rms_buf.rms_buf_len = 0;
998d9638e54Smws 		rms->rms_err = FMD_ADM_ERR_PERM;
999d9638e54Smws 		return (TRUE);
10007c478bd9Sstevel@tonic-gate 	}
10017c478bd9Sstevel@tonic-gate 
1002d9638e54Smws 	rms->rms_buf.rms_buf_val = malloc(sizeof (fmd_xprt_stat_t));
1003d9638e54Smws 	rms->rms_buf.rms_buf_len = sizeof (fmd_xprt_stat_t) /
1004d9638e54Smws 	    sizeof (fmd_stat_t);
1005d9638e54Smws 	rms->rms_err = 0;
1006d9638e54Smws 
1007d9638e54Smws 	if (rms->rms_buf.rms_buf_val == NULL) {
1008d9638e54Smws 		rms->rms_err = FMD_ADM_ERR_NOMEM;
1009d9638e54Smws 		rms->rms_buf.rms_buf_len = 0;
1010d9638e54Smws 		return (TRUE);
1011d9638e54Smws 	}
1012d9638e54Smws 
1013d9638e54Smws 	if ((xip = fmd_idspace_hold(fmd.d_xprt_ids, id)) == NULL) {
1014d9638e54Smws 		rms->rms_err = FMD_ADM_ERR_XPRTSRCH;
1015d9638e54Smws 		return (TRUE);
1016d9638e54Smws 	}
1017d9638e54Smws 
1018d9638e54Smws 	/*
1019d9638e54Smws 	 * Grab the stats lock and bcopy the entire transport stats array in
1020d9638e54Smws 	 * one shot. Then go back through and duplicate any string values.
1021d9638e54Smws 	 */
1022d9638e54Smws 	(void) pthread_mutex_lock(&xip->xi_stats_lock);
1023d9638e54Smws 
1024d9638e54Smws 	sp = (fmd_stat_t *)xip->xi_stats;
1025d9638e54Smws 	ep = sp + rms->rms_buf.rms_buf_len;
1026d9638e54Smws 	cp = rms->rms_buf.rms_buf_val;
1027d9638e54Smws 
1028d9638e54Smws 	bcopy(sp, cp, sizeof (fmd_xprt_stat_t));
1029d9638e54Smws 
1030d9638e54Smws 	for (; sp < ep; sp++, cp++) {
1031d9638e54Smws 		if (sp->fmds_type == FMD_TYPE_STRING &&
1032d9638e54Smws 		    sp->fmds_value.str != NULL)
1033d9638e54Smws 			cp->fmds_value.str = strdup(sp->fmds_value.str);
1034d9638e54Smws 	}
1035d9638e54Smws 
1036d9638e54Smws 	(void) pthread_mutex_unlock(&xip->xi_stats_lock);
1037d9638e54Smws 	fmd_idspace_rele(fmd.d_xprt_ids, id);
10387c478bd9Sstevel@tonic-gate 
10397c478bd9Sstevel@tonic-gate 	return (TRUE);
10407c478bd9Sstevel@tonic-gate }
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate int
fmd_adm_1_freeresult(SVCXPRT * xprt,xdrproc_t proc,caddr_t data)10437c478bd9Sstevel@tonic-gate fmd_adm_1_freeresult(SVCXPRT *xprt, xdrproc_t proc, caddr_t data)
10447c478bd9Sstevel@tonic-gate {
10457c478bd9Sstevel@tonic-gate 	xdr_free(proc, data);
10467c478bd9Sstevel@tonic-gate 	svc_done(xprt);
10477c478bd9Sstevel@tonic-gate 	return (TRUE);
10487c478bd9Sstevel@tonic-gate }
10497c478bd9Sstevel@tonic-gate 
10507c478bd9Sstevel@tonic-gate /*
10517c478bd9Sstevel@tonic-gate  * Custom XDR routine for our API structure fmd_stat_t.  This function must
10527c478bd9Sstevel@tonic-gate  * match the definition of fmd_stat_t in <fmd_api.h> and must also match
10537c478bd9Sstevel@tonic-gate  * the corresponding routine in usr/src/lib/fm/libfmd_adm/common/fmd_adm.c.
10547c478bd9Sstevel@tonic-gate  */
10557c478bd9Sstevel@tonic-gate bool_t
xdr_fmd_stat(XDR * xp,fmd_stat_t * sp)10567c478bd9Sstevel@tonic-gate xdr_fmd_stat(XDR *xp, fmd_stat_t *sp)
10577c478bd9Sstevel@tonic-gate {
10587c478bd9Sstevel@tonic-gate 	bool_t rv = TRUE;
10597c478bd9Sstevel@tonic-gate 
10607c478bd9Sstevel@tonic-gate 	rv &= xdr_opaque(xp, sp->fmds_name, sizeof (sp->fmds_name));
10617c478bd9Sstevel@tonic-gate 	rv &= xdr_u_int(xp, &sp->fmds_type);
10627c478bd9Sstevel@tonic-gate 	rv &= xdr_opaque(xp, sp->fmds_desc, sizeof (sp->fmds_desc));
10637c478bd9Sstevel@tonic-gate 
10647c478bd9Sstevel@tonic-gate 	switch (sp->fmds_type) {
10657c478bd9Sstevel@tonic-gate 	case FMD_TYPE_BOOL:
10667c478bd9Sstevel@tonic-gate 		rv &= xdr_int(xp, &sp->fmds_value.bool);
10677c478bd9Sstevel@tonic-gate 		break;
10687c478bd9Sstevel@tonic-gate 	case FMD_TYPE_INT32:
10697c478bd9Sstevel@tonic-gate 		rv &= xdr_int32_t(xp, &sp->fmds_value.i32);
10707c478bd9Sstevel@tonic-gate 		break;
10717c478bd9Sstevel@tonic-gate 	case FMD_TYPE_UINT32:
10727c478bd9Sstevel@tonic-gate 		rv &= xdr_uint32_t(xp, &sp->fmds_value.ui32);
10737c478bd9Sstevel@tonic-gate 		break;
10747c478bd9Sstevel@tonic-gate 	case FMD_TYPE_INT64:
10757c478bd9Sstevel@tonic-gate 		rv &= xdr_int64_t(xp, &sp->fmds_value.i64);
10767c478bd9Sstevel@tonic-gate 		break;
10777c478bd9Sstevel@tonic-gate 	case FMD_TYPE_UINT64:
10787c478bd9Sstevel@tonic-gate 	case FMD_TYPE_TIME:
10797c478bd9Sstevel@tonic-gate 	case FMD_TYPE_SIZE:
10807c478bd9Sstevel@tonic-gate 		rv &= xdr_uint64_t(xp, &sp->fmds_value.ui64);
10817c478bd9Sstevel@tonic-gate 		break;
10827c478bd9Sstevel@tonic-gate 	case FMD_TYPE_STRING:
10837c478bd9Sstevel@tonic-gate 		rv &= xdr_string(xp, &sp->fmds_value.str, ~0);
10847c478bd9Sstevel@tonic-gate 		break;
10857c478bd9Sstevel@tonic-gate 	}
10867c478bd9Sstevel@tonic-gate 
10877c478bd9Sstevel@tonic-gate 	return (rv);
10887c478bd9Sstevel@tonic-gate }
1089