xref: /onnv-gate/usr/src/cmd/fm/fmd/common/fmd_rpc_adm.c (revision 12967:ab9ae749152f)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51303Swesolows  * Common Development and Distribution License (the "License").
61303Swesolows  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
211303Swesolows 
220Sstevel@tonic-gate /*
23*12967Sgavin.maltby@oracle.com  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <strings.h>
270Sstevel@tonic-gate #include <limits.h>
280Sstevel@tonic-gate #include <unistd.h>
290Sstevel@tonic-gate #include <stdlib.h>
300Sstevel@tonic-gate #include <alloca.h>
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <fmd_rpc_adm.h>
330Sstevel@tonic-gate #include <fmd_rpc.h>
340Sstevel@tonic-gate #include <fmd_module.h>
350Sstevel@tonic-gate #include <fmd_ustat.h>
360Sstevel@tonic-gate #include <fmd_error.h>
370Sstevel@tonic-gate #include <fmd_asru.h>
380Sstevel@tonic-gate #include <fmd_ckpt.h>
390Sstevel@tonic-gate #include <fmd_case.h>
400Sstevel@tonic-gate #include <fmd_fmri.h>
411193Smws #include <fmd_idspace.h>
421193Smws #include <fmd_xprt.h>
430Sstevel@tonic-gate 
440Sstevel@tonic-gate #include <fmd.h>
450Sstevel@tonic-gate 
460Sstevel@tonic-gate bool_t
fmd_adm_modinfo_1_svc(struct fmd_rpc_modlist * rvp,struct svc_req * req)470Sstevel@tonic-gate fmd_adm_modinfo_1_svc(struct fmd_rpc_modlist *rvp, struct svc_req *req)
480Sstevel@tonic-gate {
490Sstevel@tonic-gate 	struct fmd_rpc_modinfo *rmi;
500Sstevel@tonic-gate 	fmd_module_t *mp;
510Sstevel@tonic-gate 
520Sstevel@tonic-gate 	rvp->rml_list = NULL;
530Sstevel@tonic-gate 	rvp->rml_err = 0;
540Sstevel@tonic-gate 	rvp->rml_len = 0;
550Sstevel@tonic-gate 
560Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
570Sstevel@tonic-gate 		rvp->rml_err = FMD_ADM_ERR_PERM;
580Sstevel@tonic-gate 		return (TRUE);
590Sstevel@tonic-gate 	}
600Sstevel@tonic-gate 
610Sstevel@tonic-gate 	(void) pthread_mutex_lock(&fmd.d_mod_lock);
620Sstevel@tonic-gate 
630Sstevel@tonic-gate 	for (mp = fmd_list_next(&fmd.d_mod_list);
640Sstevel@tonic-gate 	    mp != NULL; mp = fmd_list_next(mp)) {
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 		if ((rmi = malloc(sizeof (struct fmd_rpc_modinfo))) == NULL) {
670Sstevel@tonic-gate 			rvp->rml_err = FMD_ADM_ERR_NOMEM;
680Sstevel@tonic-gate 			break;
690Sstevel@tonic-gate 		}
700Sstevel@tonic-gate 
710Sstevel@tonic-gate 		fmd_module_lock(mp);
720Sstevel@tonic-gate 
730Sstevel@tonic-gate 		/*
740Sstevel@tonic-gate 		 * If mod_info is NULL, the module is in the middle of loading:
750Sstevel@tonic-gate 		 * do not report its presence to observability tools yet.
760Sstevel@tonic-gate 		 */
770Sstevel@tonic-gate 		if (mp->mod_info == NULL) {
780Sstevel@tonic-gate 			fmd_module_unlock(mp);
790Sstevel@tonic-gate 			free(rmi);
800Sstevel@tonic-gate 			continue;
810Sstevel@tonic-gate 		}
820Sstevel@tonic-gate 
830Sstevel@tonic-gate 		rmi->rmi_name = strdup(mp->mod_name);
840Sstevel@tonic-gate 		rmi->rmi_desc = strdup(mp->mod_info->fmdi_desc);
850Sstevel@tonic-gate 		rmi->rmi_vers = strdup(mp->mod_info->fmdi_vers);
860Sstevel@tonic-gate 		rmi->rmi_faulty = mp->mod_error != 0;
870Sstevel@tonic-gate 		rmi->rmi_next = rvp->rml_list;
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 		fmd_module_unlock(mp);
900Sstevel@tonic-gate 		rvp->rml_list = rmi;
910Sstevel@tonic-gate 		rvp->rml_len++;
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 		if (rmi->rmi_desc == NULL || rmi->rmi_vers == NULL) {
940Sstevel@tonic-gate 			rvp->rml_err = FMD_ADM_ERR_NOMEM;
950Sstevel@tonic-gate 			break;
960Sstevel@tonic-gate 		}
970Sstevel@tonic-gate 	}
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&fmd.d_mod_lock);
1000Sstevel@tonic-gate 	return (TRUE);
1010Sstevel@tonic-gate }
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate bool_t
fmd_adm_modcstat_1_svc(char * name,struct fmd_rpc_modstat * rms,struct svc_req * req)1040Sstevel@tonic-gate fmd_adm_modcstat_1_svc(char *name,
1050Sstevel@tonic-gate     struct fmd_rpc_modstat *rms, struct svc_req *req)
1060Sstevel@tonic-gate {
1070Sstevel@tonic-gate 	fmd_ustat_snap_t snap;
1080Sstevel@tonic-gate 	fmd_module_t *mp;
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	rms->rms_buf.rms_buf_val = NULL;
1110Sstevel@tonic-gate 	rms->rms_buf.rms_buf_len = 0;
1120Sstevel@tonic-gate 	rms->rms_err = 0;
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
1150Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_PERM;
1160Sstevel@tonic-gate 		return (TRUE);
1170Sstevel@tonic-gate 	}
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, name)) == NULL) {
1200Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_MODSRCH;
1210Sstevel@tonic-gate 		return (TRUE);
1220Sstevel@tonic-gate 	}
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 	if (fmd_modstat_snapshot(mp, &snap) == 0) {
1250Sstevel@tonic-gate 		rms->rms_buf.rms_buf_val = snap.uss_buf;
1260Sstevel@tonic-gate 		rms->rms_buf.rms_buf_len = snap.uss_len;
1270Sstevel@tonic-gate 	} else if (errno == EFMD_HDL_ABORT) {
1280Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_MODFAIL;
1290Sstevel@tonic-gate 	} else
1300Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_NOMEM;
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	fmd_module_rele(mp);
1330Sstevel@tonic-gate 	return (TRUE);
1340Sstevel@tonic-gate }
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate bool_t
fmd_adm_moddstat_1_svc(char * name,struct fmd_rpc_modstat * rms,struct svc_req * req)1370Sstevel@tonic-gate fmd_adm_moddstat_1_svc(char *name,
1380Sstevel@tonic-gate     struct fmd_rpc_modstat *rms, struct svc_req *req)
1390Sstevel@tonic-gate {
1400Sstevel@tonic-gate 	fmd_module_t *mp;
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 	rms->rms_buf.rms_buf_val = NULL;
1430Sstevel@tonic-gate 	rms->rms_buf.rms_buf_len = 0;
1440Sstevel@tonic-gate 	rms->rms_err = 0;
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
1470Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_PERM;
1480Sstevel@tonic-gate 		return (TRUE);
1490Sstevel@tonic-gate 	}
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 	if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, name)) == NULL) {
1520Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_MODSRCH;
1530Sstevel@tonic-gate 		return (TRUE);
1540Sstevel@tonic-gate 	}
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	rms->rms_buf.rms_buf_val = malloc(sizeof (fmd_modstat_t));
1570Sstevel@tonic-gate 	rms->rms_buf.rms_buf_len = sizeof (fmd_modstat_t) / sizeof (fmd_stat_t);
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	if (rms->rms_buf.rms_buf_val == NULL) {
1600Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_NOMEM;
1610Sstevel@tonic-gate 		rms->rms_buf.rms_buf_len = 0;
1620Sstevel@tonic-gate 		fmd_module_rele(mp);
1630Sstevel@tonic-gate 		return (TRUE);
1640Sstevel@tonic-gate 	}
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	/*
1670Sstevel@tonic-gate 	 * Note: the bcopy() here is valid only if no FMD_TYPE_STRING stats
1680Sstevel@tonic-gate 	 * are present in mp->mod_stats.  We don't use any for the daemon-
1690Sstevel@tonic-gate 	 * maintained stats and provide this function in order to reduce the
1700Sstevel@tonic-gate 	 * overhead of the fmstat(1M) default view, where these minimal stats
1710Sstevel@tonic-gate 	 * must be retrieved for all of the active modules.
1720Sstevel@tonic-gate 	 */
1730Sstevel@tonic-gate 	(void) pthread_mutex_lock(&mp->mod_stats_lock);
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	if (mp->mod_stats != NULL) {
1760Sstevel@tonic-gate 		mp->mod_stats->ms_snaptime.fmds_value.ui64 = gethrtime();
1770Sstevel@tonic-gate 		bcopy(mp->mod_stats, rms->rms_buf.rms_buf_val,
1780Sstevel@tonic-gate 		    sizeof (fmd_modstat_t));
1790Sstevel@tonic-gate 	} else {
1800Sstevel@tonic-gate 		free(rms->rms_buf.rms_buf_val);
1810Sstevel@tonic-gate 		rms->rms_buf.rms_buf_val = NULL;
1820Sstevel@tonic-gate 		rms->rms_buf.rms_buf_len = 0;
1830Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_MODFAIL;
1840Sstevel@tonic-gate 	}
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&mp->mod_stats_lock);
1870Sstevel@tonic-gate 	fmd_module_rele(mp);
1880Sstevel@tonic-gate 	return (TRUE);
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate bool_t
fmd_adm_modgstat_1_svc(struct fmd_rpc_modstat * rms,struct svc_req * req)1920Sstevel@tonic-gate fmd_adm_modgstat_1_svc(struct fmd_rpc_modstat *rms, struct svc_req *req)
1930Sstevel@tonic-gate {
1940Sstevel@tonic-gate 	const size_t size = sizeof (fmd_statistics_t);
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
1970Sstevel@tonic-gate 		rms->rms_buf.rms_buf_val = NULL;
1980Sstevel@tonic-gate 		rms->rms_buf.rms_buf_len = 0;
1990Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_PERM;
2000Sstevel@tonic-gate 	} else if ((rms->rms_buf.rms_buf_val = malloc(size)) != NULL) {
2010Sstevel@tonic-gate 		/*
2020Sstevel@tonic-gate 		 * Note: the bcopy() here is valid only if no FMD_TYPE_STRING
2030Sstevel@tonic-gate 		 * stats are present in fmd.d_stats (see definition in fmd.c).
2040Sstevel@tonic-gate 		 */
2050Sstevel@tonic-gate 		(void) pthread_mutex_lock(&fmd.d_stats_lock);
2060Sstevel@tonic-gate 		bcopy(fmd.d_stats, rms->rms_buf.rms_buf_val, size);
2070Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&fmd.d_stats_lock);
2080Sstevel@tonic-gate 		rms->rms_buf.rms_buf_len = size / sizeof (fmd_stat_t);
2090Sstevel@tonic-gate 		rms->rms_err = 0;
2100Sstevel@tonic-gate 	} else {
2110Sstevel@tonic-gate 		rms->rms_buf.rms_buf_len = 0;
2120Sstevel@tonic-gate 		rms->rms_err = FMD_ADM_ERR_NOMEM;
2130Sstevel@tonic-gate 	}
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	return (TRUE);
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate bool_t
fmd_adm_modload_1_svc(char * path,int * rvp,struct svc_req * req)2190Sstevel@tonic-gate fmd_adm_modload_1_svc(char *path, int *rvp, struct svc_req *req)
2200Sstevel@tonic-gate {
2210Sstevel@tonic-gate 	fmd_module_t *mp;
2220Sstevel@tonic-gate 	const char *p;
2230Sstevel@tonic-gate 	int err = 0;
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
2260Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_PERM;
2270Sstevel@tonic-gate 		return (TRUE);
2280Sstevel@tonic-gate 	}
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	/*
2310Sstevel@tonic-gate 	 * Before we endure the expense of constructing a module and attempting
2320Sstevel@tonic-gate 	 * to load it, do a quick check to see if the pathname is valid.
2330Sstevel@tonic-gate 	 */
2340Sstevel@tonic-gate 	if (access(path, F_OK) != 0) {
2350Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_MODNOENT;
2360Sstevel@tonic-gate 		return (TRUE);
2370Sstevel@tonic-gate 	}
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 	if ((p = strrchr(path, '.')) != NULL && strcmp(p, ".so") == 0)
2400Sstevel@tonic-gate 		mp = fmd_modhash_load(fmd.d_mod_hash, path, &fmd_rtld_ops);
2410Sstevel@tonic-gate 	else
2420Sstevel@tonic-gate 		mp = fmd_modhash_load(fmd.d_mod_hash, path, &fmd_proc_ops);
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	if (mp == NULL) {
2450Sstevel@tonic-gate 		switch (errno) {
2460Sstevel@tonic-gate 		case EFMD_MOD_LOADED:
2470Sstevel@tonic-gate 			err = FMD_ADM_ERR_MODEXIST;
2480Sstevel@tonic-gate 			break;
2490Sstevel@tonic-gate 		case EFMD_MOD_INIT:
2500Sstevel@tonic-gate 			err = FMD_ADM_ERR_MODINIT;
2510Sstevel@tonic-gate 			break;
2520Sstevel@tonic-gate 		default:
2530Sstevel@tonic-gate 			err = FMD_ADM_ERR_MODLOAD;
2540Sstevel@tonic-gate 			break;
2550Sstevel@tonic-gate 		}
2560Sstevel@tonic-gate 	}
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	*rvp = err;
2590Sstevel@tonic-gate 	return (TRUE);
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate bool_t
fmd_adm_modunload_1_svc(char * name,int * rvp,struct svc_req * req)2630Sstevel@tonic-gate fmd_adm_modunload_1_svc(char *name, int *rvp, struct svc_req *req)
2640Sstevel@tonic-gate {
2650Sstevel@tonic-gate 	fmd_module_t *mp = NULL;
2660Sstevel@tonic-gate 	int err = 0;
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 	if (fmd_rpc_deny(req))
2690Sstevel@tonic-gate 		err = FMD_ADM_ERR_PERM;
2700Sstevel@tonic-gate 	else if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, name)) == NULL)
2710Sstevel@tonic-gate 		err = FMD_ADM_ERR_MODSRCH;
2720Sstevel@tonic-gate 	else if (mp == fmd.d_self)
2730Sstevel@tonic-gate 		err = FMD_ADM_ERR_MODBUSY;
2740Sstevel@tonic-gate 	else if (fmd_modhash_unload(fmd.d_mod_hash, name) != 0)
2750Sstevel@tonic-gate 		err = FMD_ADM_ERR_MODSRCH;
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	if (mp != NULL)
2780Sstevel@tonic-gate 		fmd_module_rele(mp);
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 	*rvp = err;
2810Sstevel@tonic-gate 	return (TRUE);
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate bool_t
fmd_adm_modreset_1_svc(char * name,int * rvp,struct svc_req * req)2850Sstevel@tonic-gate fmd_adm_modreset_1_svc(char *name, int *rvp, struct svc_req *req)
2860Sstevel@tonic-gate {
2870Sstevel@tonic-gate 	fmd_module_t *mp = NULL;
2880Sstevel@tonic-gate 	int err = 0;
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	if (fmd_rpc_deny(req))
2910Sstevel@tonic-gate 		err = FMD_ADM_ERR_PERM;
2920Sstevel@tonic-gate 	else if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, name)) == NULL)
2930Sstevel@tonic-gate 		err = FMD_ADM_ERR_MODSRCH;
2940Sstevel@tonic-gate 	else if (mp == fmd.d_self)
2950Sstevel@tonic-gate 		err = FMD_ADM_ERR_MODBUSY;
2960Sstevel@tonic-gate 	else if (fmd_modhash_unload(fmd.d_mod_hash, name) != 0)
2970Sstevel@tonic-gate 		err = FMD_ADM_ERR_MODSRCH;
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	if (err == 0)
3000Sstevel@tonic-gate 		fmd_ckpt_delete(mp); /* erase any saved checkpoints */
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 	if (err == 0 && fmd_modhash_load(fmd.d_mod_hash,
3030Sstevel@tonic-gate 	    mp->mod_path, mp->mod_ops) == NULL) {
3040Sstevel@tonic-gate 		if (errno == EFMD_MOD_INIT)
3050Sstevel@tonic-gate 			err = FMD_ADM_ERR_MODINIT;
3060Sstevel@tonic-gate 		else
3070Sstevel@tonic-gate 			err = FMD_ADM_ERR_MODLOAD;
3080Sstevel@tonic-gate 	}
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 	if (mp != NULL)
3110Sstevel@tonic-gate 		fmd_module_rele(mp);
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 	*rvp = err;
3140Sstevel@tonic-gate 	return (TRUE);
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate bool_t
fmd_adm_modgc_1_svc(char * name,int * rvp,struct svc_req * req)3180Sstevel@tonic-gate fmd_adm_modgc_1_svc(char *name, int *rvp, struct svc_req *req)
3190Sstevel@tonic-gate {
3200Sstevel@tonic-gate 	fmd_module_t *mp;
3210Sstevel@tonic-gate 	int err = 0;
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	if (fmd_rpc_deny(req))
3240Sstevel@tonic-gate 		err = FMD_ADM_ERR_PERM;
3250Sstevel@tonic-gate 	else if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, name)) == NULL)
3260Sstevel@tonic-gate 		err = FMD_ADM_ERR_MODSRCH;
3270Sstevel@tonic-gate 	else {
3280Sstevel@tonic-gate 		fmd_module_gc(mp);
3290Sstevel@tonic-gate 		fmd_module_rele(mp);
3300Sstevel@tonic-gate 	}
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	*rvp = err;
3330Sstevel@tonic-gate 	return (TRUE);
3340Sstevel@tonic-gate }
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate /*
3370Sstevel@tonic-gate  * Unlike our other RPC callbacks, fmd_adm_rsrclist_1 can return large amounts
3380Sstevel@tonic-gate  * of data that may exceed the underlying RPC transport buffer size if the
3390Sstevel@tonic-gate  * resource cache is heavily populated and/or all resources are requested.
3400Sstevel@tonic-gate  * To minimize the likelihood of running out of RPC buffer space and having to
3410Sstevel@tonic-gate  * fail the client request, fmd_adm_rsrclist_1 returns a snapshot of the
3420Sstevel@tonic-gate  * relevant FMRI strings only: the client can use fmd_adm_rsrcinfo_1 on an
3430Sstevel@tonic-gate  * individual FMRI if more information is needed.  To further reduce the XDR
3440Sstevel@tonic-gate  * overhead, the string list is represented as XDR-opaque data where the
3450Sstevel@tonic-gate  * entire list is returned as a string table (e.g. "fmriA\0fmriB\0...").
3460Sstevel@tonic-gate  */
3470Sstevel@tonic-gate static void
fmd_adm_rsrclist_asru(fmd_asru_t * ap,void * arg)3480Sstevel@tonic-gate fmd_adm_rsrclist_asru(fmd_asru_t *ap, void *arg)
3490Sstevel@tonic-gate {
3500Sstevel@tonic-gate 	struct fmd_rpc_rsrclist *rrl = arg;
3510Sstevel@tonic-gate 	size_t name_len, buf_len;
3520Sstevel@tonic-gate 	void *p;
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 	/*
3555255Sstephh 	 * Skip the ASRU if this fault is marked as invisible.
3560Sstevel@tonic-gate 	 * If rrl_all is false, we take a quick look at asru_flags with no lock
3575255Sstephh 	 * held to see if the ASRU is not faulty.  If so,
3580Sstevel@tonic-gate 	 * we don't want to report it by default and can just skip this ASRU.
3590Sstevel@tonic-gate 	 * This helps keep overhead low in the common case, as the call to
3600Sstevel@tonic-gate 	 * fmd_asru_getstate() can be expensive depending on the scheme.
3610Sstevel@tonic-gate 	 */
3625255Sstephh 
3635255Sstephh 	if (ap->asru_flags & FMD_ASRU_INVISIBLE)
3645255Sstephh 		return;
3655255Sstephh 	if (rrl->rrl_all == B_FALSE && !(ap->asru_flags & FMD_ASRU_FAULTY))
3660Sstevel@tonic-gate 		return;
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 	if (rrl->rrl_err != 0 || fmd_asru_getstate(ap) == 0)
3690Sstevel@tonic-gate 		return; /* error has occurred or resource is in 'ok' state */
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 	/*
3720Sstevel@tonic-gate 	 * Lock the ASRU and reallocate rrl_buf[] to be large enough to hold
3730Sstevel@tonic-gate 	 * another string, doubling it as needed.  Then copy the new string
3740Sstevel@tonic-gate 	 * on to the end, and increment rrl_len to indicate the used space.
3750Sstevel@tonic-gate 	 */
3760Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ap->asru_lock);
3770Sstevel@tonic-gate 	name_len = strlen(ap->asru_name) + 1;
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 	while (rrl->rrl_len + name_len > rrl->rrl_buf.rrl_buf_len) {
3800Sstevel@tonic-gate 		if (rrl->rrl_buf.rrl_buf_len != 0)
3810Sstevel@tonic-gate 			buf_len = rrl->rrl_buf.rrl_buf_len * 2;
3820Sstevel@tonic-gate 		else
3830Sstevel@tonic-gate 			buf_len = 1024; /* default buffer size */
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 		if ((p = realloc(rrl->rrl_buf.rrl_buf_val, buf_len)) != NULL) {
3860Sstevel@tonic-gate 			bzero((char *)p + rrl->rrl_buf.rrl_buf_len,
3870Sstevel@tonic-gate 			    buf_len - rrl->rrl_buf.rrl_buf_len);
3880Sstevel@tonic-gate 			rrl->rrl_buf.rrl_buf_val = p;
3890Sstevel@tonic-gate 			rrl->rrl_buf.rrl_buf_len = buf_len;
3900Sstevel@tonic-gate 		} else {
3910Sstevel@tonic-gate 			rrl->rrl_err = FMD_ADM_ERR_NOMEM;
3920Sstevel@tonic-gate 			break;
3930Sstevel@tonic-gate 		}
3940Sstevel@tonic-gate 	}
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 	if (rrl->rrl_err == 0) {
3970Sstevel@tonic-gate 		bcopy(ap->asru_name, (char *)rrl->rrl_buf.rrl_buf_val +
3980Sstevel@tonic-gate 		    rrl->rrl_len, name_len);
3990Sstevel@tonic-gate 		rrl->rrl_len += name_len;
4000Sstevel@tonic-gate 		rrl->rrl_cnt++;
4010Sstevel@tonic-gate 	}
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ap->asru_lock);
4040Sstevel@tonic-gate }
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate bool_t
fmd_adm_rsrclist_1_svc(bool_t all,struct fmd_rpc_rsrclist * rvp,struct svc_req * req)4070Sstevel@tonic-gate fmd_adm_rsrclist_1_svc(bool_t all,
4080Sstevel@tonic-gate     struct fmd_rpc_rsrclist *rvp, struct svc_req *req)
4090Sstevel@tonic-gate {
4100Sstevel@tonic-gate 	rvp->rrl_buf.rrl_buf_len = 0;
4110Sstevel@tonic-gate 	rvp->rrl_buf.rrl_buf_val = NULL;
4120Sstevel@tonic-gate 	rvp->rrl_len = 0;
4130Sstevel@tonic-gate 	rvp->rrl_cnt = 0;
4140Sstevel@tonic-gate 	rvp->rrl_err = 0;
4150Sstevel@tonic-gate 	rvp->rrl_all = all;
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 	if (fmd_rpc_deny(req))
4180Sstevel@tonic-gate 		rvp->rrl_err = FMD_ADM_ERR_PERM;
4190Sstevel@tonic-gate 	else
4200Sstevel@tonic-gate 		fmd_asru_hash_apply(fmd.d_asrus, fmd_adm_rsrclist_asru, rvp);
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate 	return (TRUE);
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate bool_t
fmd_adm_rsrcinfo_1_svc(char * fmri,struct fmd_rpc_rsrcinfo * rvp,struct svc_req * req)4260Sstevel@tonic-gate fmd_adm_rsrcinfo_1_svc(char *fmri,
4270Sstevel@tonic-gate     struct fmd_rpc_rsrcinfo *rvp, struct svc_req *req)
4280Sstevel@tonic-gate {
4290Sstevel@tonic-gate 	fmd_asru_t *ap;
4301193Smws 	fmd_case_impl_t *cip;
4310Sstevel@tonic-gate 	int state;
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate 	bzero(rvp, sizeof (struct fmd_rpc_rsrcinfo));
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
4360Sstevel@tonic-gate 		rvp->rri_err = FMD_ADM_ERR_PERM;
4370Sstevel@tonic-gate 		return (TRUE);
4380Sstevel@tonic-gate 	}
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 	if ((ap = fmd_asru_hash_lookup_name(fmd.d_asrus, fmri)) == NULL) {
4410Sstevel@tonic-gate 		rvp->rri_err = FMD_ADM_ERR_RSRCSRCH;
4420Sstevel@tonic-gate 		return (TRUE);
4430Sstevel@tonic-gate 	}
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 	state = fmd_asru_getstate(ap);
4460Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ap->asru_lock);
4471193Smws 	cip = (fmd_case_impl_t *)ap->asru_case;
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate 	rvp->rri_fmri = strdup(ap->asru_name);
4500Sstevel@tonic-gate 	rvp->rri_uuid = strdup(ap->asru_uuid);
4511193Smws 	rvp->rri_case = cip ? strdup(cip->ci_uuid) : NULL;
4520Sstevel@tonic-gate 	rvp->rri_faulty = (state & FMD_ASRU_FAULTY) != 0;
4530Sstevel@tonic-gate 	rvp->rri_unusable = (state & FMD_ASRU_UNUSABLE) != 0;
4540Sstevel@tonic-gate 	rvp->rri_invisible = (ap->asru_flags & FMD_ASRU_INVISIBLE) != 0;
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ap->asru_lock);
4570Sstevel@tonic-gate 	fmd_asru_hash_release(fmd.d_asrus, ap);
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 	if (rvp->rri_fmri == NULL || rvp->rri_uuid == NULL)
4600Sstevel@tonic-gate 		rvp->rri_err = FMD_ADM_ERR_NOMEM;
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 	return (TRUE);
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate 
4659120SStephen.Hanson@Sun.COM static void
fmd_adm_do_repair(char * name,struct svc_req * req,int * errp,uint8_t reason,char * uuid)4669120SStephen.Hanson@Sun.COM fmd_adm_do_repair(char *name, struct svc_req *req, int *errp, uint8_t reason,
4679120SStephen.Hanson@Sun.COM     char *uuid)
4689120SStephen.Hanson@Sun.COM {
4699120SStephen.Hanson@Sun.COM 	if (fmd_rpc_deny(req))
4709120SStephen.Hanson@Sun.COM 		*errp = FMD_ADM_ERR_PERM;
4719120SStephen.Hanson@Sun.COM 	else {
4729120SStephen.Hanson@Sun.COM 		fmd_asru_rep_arg_t fara;
4739874SStephen.Hanson@Sun.COM 		int err = FARA_ERR_RSRCNOTF;
4749120SStephen.Hanson@Sun.COM 
4759120SStephen.Hanson@Sun.COM 		fara.fara_reason = reason;
4769874SStephen.Hanson@Sun.COM 		fara.fara_rval = &err;
4779120SStephen.Hanson@Sun.COM 		fara.fara_uuid = uuid;
4789120SStephen.Hanson@Sun.COM 		fara.fara_bywhat = FARA_BY_ASRU;
4799120SStephen.Hanson@Sun.COM 		fmd_asru_hash_apply_by_asru(fmd.d_asrus, name,
4809120SStephen.Hanson@Sun.COM 		    fmd_asru_repaired, &fara);
4819120SStephen.Hanson@Sun.COM 		fara.fara_bywhat = FARA_BY_LABEL;
4829120SStephen.Hanson@Sun.COM 		fmd_asru_hash_apply_by_label(fmd.d_asrus, name,
4839120SStephen.Hanson@Sun.COM 		    fmd_asru_repaired, &fara);
4849120SStephen.Hanson@Sun.COM 		fara.fara_bywhat = FARA_BY_FRU;
4859120SStephen.Hanson@Sun.COM 		fmd_asru_hash_apply_by_fru(fmd.d_asrus, name,
4869120SStephen.Hanson@Sun.COM 		    fmd_asru_repaired, &fara);
4879120SStephen.Hanson@Sun.COM 		fara.fara_bywhat = FARA_BY_RSRC;
4889120SStephen.Hanson@Sun.COM 		fmd_asru_hash_apply_by_rsrc(fmd.d_asrus, name,
4899120SStephen.Hanson@Sun.COM 		    fmd_asru_repaired, &fara);
4909874SStephen.Hanson@Sun.COM 		if (err == FARA_ERR_RSRCNOTR)
4919874SStephen.Hanson@Sun.COM 			*errp = FMD_ADM_ERR_RSRCNOTR;
4929874SStephen.Hanson@Sun.COM 		else if (err == FARA_OK)
4939874SStephen.Hanson@Sun.COM 			*errp = 0;
4949120SStephen.Hanson@Sun.COM 	}
4959120SStephen.Hanson@Sun.COM }
4969120SStephen.Hanson@Sun.COM 
4970Sstevel@tonic-gate bool_t
fmd_adm_rsrcflush_1_svc(char * name,int * rvp,struct svc_req * req)4980Sstevel@tonic-gate fmd_adm_rsrcflush_1_svc(char *name, int *rvp, struct svc_req *req)
4990Sstevel@tonic-gate {
5009120SStephen.Hanson@Sun.COM 	int err = FMD_ADM_ERR_RSRCNOTF;
5019120SStephen.Hanson@Sun.COM 
50210656SStephen.Hanson@Sun.COM 	/*
50310656SStephen.Hanson@Sun.COM 	 * If anyone does an fmadm flush command, discard any resolved
50410656SStephen.Hanson@Sun.COM 	 * cases that were being retained for historic diagnosis.
50510656SStephen.Hanson@Sun.COM 	 */
50610656SStephen.Hanson@Sun.COM 	if (fmd_rpc_deny(req))
50710656SStephen.Hanson@Sun.COM 		err = FMD_ADM_ERR_PERM;
50810656SStephen.Hanson@Sun.COM 	else {
50910656SStephen.Hanson@Sun.COM 		fmd_asru_hash_apply_by_asru(fmd.d_asrus, name,
51010656SStephen.Hanson@Sun.COM 		    fmd_asru_flush, &err);
51110656SStephen.Hanson@Sun.COM 		fmd_asru_hash_apply_by_label(fmd.d_asrus, name,
51210656SStephen.Hanson@Sun.COM 		    fmd_asru_flush, &err);
51310656SStephen.Hanson@Sun.COM 		fmd_asru_hash_apply_by_fru(fmd.d_asrus, name,
51410656SStephen.Hanson@Sun.COM 		    fmd_asru_flush, &err);
51510656SStephen.Hanson@Sun.COM 		fmd_asru_hash_apply_by_rsrc(fmd.d_asrus, name,
51610656SStephen.Hanson@Sun.COM 		    fmd_asru_flush, &err);
51710656SStephen.Hanson@Sun.COM 	}
5189120SStephen.Hanson@Sun.COM 	*rvp = err;
5199120SStephen.Hanson@Sun.COM 	return (TRUE);
5200Sstevel@tonic-gate }
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate bool_t
fmd_adm_rsrcrepaired_1_svc(char * name,int * rvp,struct svc_req * req)5237275Sstephh fmd_adm_rsrcrepaired_1_svc(char *name, int *rvp, struct svc_req *req)
5247275Sstephh {
5257275Sstephh 	int err = FMD_ADM_ERR_RSRCNOTF;
5267275Sstephh 
5279120SStephen.Hanson@Sun.COM 	fmd_adm_do_repair(name, req, &err, FMD_ASRU_REPAIRED, NULL);
5287275Sstephh 	*rvp = err;
5297275Sstephh 	return (TRUE);
5307275Sstephh }
5317275Sstephh 
5327275Sstephh bool_t
fmd_adm_rsrcreplaced_1_svc(char * name,int * rvp,struct svc_req * req)5337275Sstephh fmd_adm_rsrcreplaced_1_svc(char *name, int *rvp, struct svc_req *req)
5340Sstevel@tonic-gate {
5356228Sstephh 	int err = FMD_ADM_ERR_RSRCNOTF;
5360Sstevel@tonic-gate 
5379120SStephen.Hanson@Sun.COM 	fmd_adm_do_repair(name, req, &err, FMD_ASRU_REPLACED, NULL);
5387275Sstephh 	*rvp = err;
5397275Sstephh 	return (TRUE);
5407275Sstephh }
5417275Sstephh 
5427275Sstephh bool_t
fmd_adm_rsrcacquit_1_svc(char * name,char * uuid,int * rvp,struct svc_req * req)5437275Sstephh fmd_adm_rsrcacquit_1_svc(char *name, char *uuid, int *rvp, struct svc_req *req)
5447275Sstephh {
5457275Sstephh 	int err = FMD_ADM_ERR_RSRCNOTF;
5467275Sstephh 
5479120SStephen.Hanson@Sun.COM 	fmd_adm_do_repair(name, req, &err, FMD_ASRU_ACQUITTED, uuid);
5480Sstevel@tonic-gate 	*rvp = err;
5490Sstevel@tonic-gate 	return (TRUE);
5500Sstevel@tonic-gate }
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate static void
fmd_adm_serdlist_measure(fmd_serd_eng_t * sgp,void * arg)55311400SJakub.Jermar@Sun.COM fmd_adm_serdlist_measure(fmd_serd_eng_t *sgp, void *arg)
55411400SJakub.Jermar@Sun.COM {
55511400SJakub.Jermar@Sun.COM 	struct fmd_rpc_serdlist *rsl = arg;
55611400SJakub.Jermar@Sun.COM 
55711400SJakub.Jermar@Sun.COM 	rsl->rsl_len += strlen(sgp->sg_name) + 1;
55811400SJakub.Jermar@Sun.COM 	rsl->rsl_cnt++;
55911400SJakub.Jermar@Sun.COM }
56011400SJakub.Jermar@Sun.COM 
56111400SJakub.Jermar@Sun.COM static void
fmd_adm_serdlist_record(fmd_serd_eng_t * sgp,void * arg)56211400SJakub.Jermar@Sun.COM fmd_adm_serdlist_record(fmd_serd_eng_t *sgp, void *arg)
5630Sstevel@tonic-gate {
5640Sstevel@tonic-gate 	struct fmd_rpc_serdlist *rsl = arg;
56511400SJakub.Jermar@Sun.COM 
56611400SJakub.Jermar@Sun.COM 	bcopy(sgp->sg_name, rsl->rsl_buf.rsl_buf_val + rsl->rsl_len,
56711400SJakub.Jermar@Sun.COM 	    strlen(sgp->sg_name));
56811400SJakub.Jermar@Sun.COM 	rsl->rsl_len += strlen(sgp->sg_name) + 1;
56911400SJakub.Jermar@Sun.COM }
57011400SJakub.Jermar@Sun.COM 
57111400SJakub.Jermar@Sun.COM bool_t
fmd_adm_serdlist_1_svc(char * name,struct fmd_rpc_serdlist * rvp,struct svc_req * req)57211400SJakub.Jermar@Sun.COM fmd_adm_serdlist_1_svc(char *name, struct fmd_rpc_serdlist *rvp,
57311400SJakub.Jermar@Sun.COM     struct svc_req *req)
57411400SJakub.Jermar@Sun.COM {
57511400SJakub.Jermar@Sun.COM 	fmd_module_t *mp;
57611400SJakub.Jermar@Sun.COM 	void *p;
57711400SJakub.Jermar@Sun.COM 
57811400SJakub.Jermar@Sun.COM 	rvp->rsl_buf.rsl_buf_len = 0;
57911400SJakub.Jermar@Sun.COM 	rvp->rsl_buf.rsl_buf_val = NULL;
58011400SJakub.Jermar@Sun.COM 	rvp->rsl_len = 0;
58111400SJakub.Jermar@Sun.COM 	rvp->rsl_cnt = 0;
58211400SJakub.Jermar@Sun.COM 	rvp->rsl_err = 0;
58311400SJakub.Jermar@Sun.COM 
58411400SJakub.Jermar@Sun.COM 	if (fmd_rpc_deny(req)) {
58511400SJakub.Jermar@Sun.COM 		rvp->rsl_err = FMD_ADM_ERR_PERM;
58611400SJakub.Jermar@Sun.COM 		return (TRUE);
58711400SJakub.Jermar@Sun.COM 	}
58811400SJakub.Jermar@Sun.COM 
58911400SJakub.Jermar@Sun.COM 	if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, name)) == NULL) {
59011400SJakub.Jermar@Sun.COM 		rvp->rsl_err = FMD_ADM_ERR_MODSRCH;
59111400SJakub.Jermar@Sun.COM 		return (TRUE);
59211400SJakub.Jermar@Sun.COM 	}
5930Sstevel@tonic-gate 
59411400SJakub.Jermar@Sun.COM 	fmd_module_lock(mp);
59511400SJakub.Jermar@Sun.COM 	/* In the first pass, collect the overall length of the buffer. */
59611400SJakub.Jermar@Sun.COM 	fmd_serd_hash_apply(&mp->mod_serds, fmd_adm_serdlist_measure, rvp);
59711400SJakub.Jermar@Sun.COM 	if (rvp->rsl_len == 0) {
59811400SJakub.Jermar@Sun.COM 		fmd_module_unlock(mp);
59911400SJakub.Jermar@Sun.COM 		fmd_module_rele(mp);
60011400SJakub.Jermar@Sun.COM 		return (TRUE);
60111400SJakub.Jermar@Sun.COM 	}
60211400SJakub.Jermar@Sun.COM 	p = malloc(rvp->rsl_len);
60311400SJakub.Jermar@Sun.COM 	if (p) {
60411400SJakub.Jermar@Sun.COM 		rvp->rsl_buf.rsl_buf_val = p;
60511400SJakub.Jermar@Sun.COM 		rvp->rsl_buf.rsl_buf_len = rvp->rsl_len;
60611400SJakub.Jermar@Sun.COM 		bzero(rvp->rsl_buf.rsl_buf_val, rvp->rsl_buf.rsl_buf_len);
60711400SJakub.Jermar@Sun.COM 		rvp->rsl_len = 0;
60811400SJakub.Jermar@Sun.COM 		/* In the second pass, populate the buffer with data. */
60911400SJakub.Jermar@Sun.COM 		fmd_serd_hash_apply(&mp->mod_serds, fmd_adm_serdlist_record,
61011400SJakub.Jermar@Sun.COM 		    rvp);
61111400SJakub.Jermar@Sun.COM 	} else {
61211400SJakub.Jermar@Sun.COM 		rvp->rsl_err = FMD_ADM_ERR_NOMEM;
61311400SJakub.Jermar@Sun.COM 	}
61411400SJakub.Jermar@Sun.COM 	fmd_module_unlock(mp);
61511400SJakub.Jermar@Sun.COM 
61611400SJakub.Jermar@Sun.COM 	fmd_module_rele(mp);
61711400SJakub.Jermar@Sun.COM 	return (TRUE);
61811400SJakub.Jermar@Sun.COM }
61911400SJakub.Jermar@Sun.COM 
62011400SJakub.Jermar@Sun.COM static void
fmd_adm_serdinfo_record(fmd_serd_eng_t * sgp,struct fmd_rpc_serdinfo * rsi)62111400SJakub.Jermar@Sun.COM fmd_adm_serdinfo_record(fmd_serd_eng_t *sgp, struct fmd_rpc_serdinfo *rsi)
62211400SJakub.Jermar@Sun.COM {
6230Sstevel@tonic-gate 	uint64_t old, now = fmd_time_gethrtime();
6240Sstevel@tonic-gate 	const fmd_serd_elem_t *oep;
6250Sstevel@tonic-gate 
62611400SJakub.Jermar@Sun.COM 	if ((rsi->rsi_name = strdup(sgp->sg_name)) == NULL) {
62711400SJakub.Jermar@Sun.COM 		rsi->rsi_err = FMD_ADM_ERR_NOMEM;
6280Sstevel@tonic-gate 		return;
6290Sstevel@tonic-gate 	}
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 	if ((oep = fmd_list_next(&sgp->sg_list)) != NULL)
6320Sstevel@tonic-gate 		old = fmd_event_hrtime(oep->se_event);
6330Sstevel@tonic-gate 	else
6340Sstevel@tonic-gate 		old = now;
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 	rsi->rsi_delta = now >= old ? now - old : (UINT64_MAX - old) + now + 1;
6370Sstevel@tonic-gate 	rsi->rsi_count = sgp->sg_count;
6380Sstevel@tonic-gate 	rsi->rsi_fired = fmd_serd_eng_fired(sgp) != 0;
6390Sstevel@tonic-gate 	rsi->rsi_n = sgp->sg_n;
6400Sstevel@tonic-gate 	rsi->rsi_t = sgp->sg_t;
6410Sstevel@tonic-gate }
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate bool_t
fmd_adm_serdinfo_1_svc(char * mname,char * sname,struct fmd_rpc_serdinfo * rvp,struct svc_req * req)64411400SJakub.Jermar@Sun.COM fmd_adm_serdinfo_1_svc(char *mname, char *sname, struct fmd_rpc_serdinfo *rvp,
64511400SJakub.Jermar@Sun.COM     struct svc_req *req)
6460Sstevel@tonic-gate {
6470Sstevel@tonic-gate 	fmd_module_t *mp;
64811400SJakub.Jermar@Sun.COM 	fmd_serd_eng_t *sgp;
6490Sstevel@tonic-gate 
65011400SJakub.Jermar@Sun.COM 	bzero(rvp, sizeof (struct fmd_rpc_serdinfo));
6510Sstevel@tonic-gate 
6520Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
65311400SJakub.Jermar@Sun.COM 		rvp->rsi_err = FMD_ADM_ERR_PERM;
6540Sstevel@tonic-gate 		return (TRUE);
6550Sstevel@tonic-gate 	}
6560Sstevel@tonic-gate 
65711400SJakub.Jermar@Sun.COM 	if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, mname)) == NULL) {
65811400SJakub.Jermar@Sun.COM 		rvp->rsi_err = FMD_ADM_ERR_MODSRCH;
6590Sstevel@tonic-gate 		return (TRUE);
6600Sstevel@tonic-gate 	}
6610Sstevel@tonic-gate 
6620Sstevel@tonic-gate 	fmd_module_lock(mp);
66311400SJakub.Jermar@Sun.COM 
66411400SJakub.Jermar@Sun.COM 	if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, sname)) != NULL) {
66511400SJakub.Jermar@Sun.COM 		fmd_adm_serdinfo_record(sgp, rvp);
66611400SJakub.Jermar@Sun.COM 	} else
66711400SJakub.Jermar@Sun.COM 		rvp->rsi_err = FMD_ADM_ERR_SERDSRCH;
66811400SJakub.Jermar@Sun.COM 
6690Sstevel@tonic-gate 	fmd_module_unlock(mp);
67011400SJakub.Jermar@Sun.COM 	fmd_module_rele(mp);
6710Sstevel@tonic-gate 
6720Sstevel@tonic-gate 	return (TRUE);
6730Sstevel@tonic-gate }
6740Sstevel@tonic-gate 
67511400SJakub.Jermar@Sun.COM /*ARGSUSED*/
67611400SJakub.Jermar@Sun.COM bool_t
fmd_adm_serdinfo_old_1_svc(char * name,struct fmd_rpc_serdlist * rvp,struct svc_req * req)67711400SJakub.Jermar@Sun.COM fmd_adm_serdinfo_old_1_svc(char *name, struct fmd_rpc_serdlist *rvp,
67811400SJakub.Jermar@Sun.COM     struct svc_req *req)
67911400SJakub.Jermar@Sun.COM {
68011400SJakub.Jermar@Sun.COM 	return (FALSE);
68111400SJakub.Jermar@Sun.COM }
68211400SJakub.Jermar@Sun.COM 
6830Sstevel@tonic-gate bool_t
fmd_adm_serdreset_1_svc(char * mname,char * sname,int * rvp,struct svc_req * req)6840Sstevel@tonic-gate fmd_adm_serdreset_1_svc(char *mname, char *sname, int *rvp, struct svc_req *req)
6850Sstevel@tonic-gate {
6860Sstevel@tonic-gate 	fmd_module_t *mp;
6870Sstevel@tonic-gate 	fmd_serd_eng_t *sgp;
6880Sstevel@tonic-gate 	int err = 0;
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
6910Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_PERM;
6920Sstevel@tonic-gate 		return (TRUE);
6930Sstevel@tonic-gate 	}
6940Sstevel@tonic-gate 
6950Sstevel@tonic-gate 	if ((mp = fmd_modhash_lookup(fmd.d_mod_hash, mname)) == NULL) {
6960Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_MODSRCH;
6970Sstevel@tonic-gate 		return (TRUE);
6980Sstevel@tonic-gate 	}
6990Sstevel@tonic-gate 
7000Sstevel@tonic-gate 	fmd_module_lock(mp);
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate 	if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, sname)) != NULL) {
7030Sstevel@tonic-gate 		if (fmd_serd_eng_fired(sgp)) {
7040Sstevel@tonic-gate 			err = FMD_ADM_ERR_SERDFIRED;
7050Sstevel@tonic-gate 		} else {
7060Sstevel@tonic-gate 			fmd_serd_eng_reset(sgp);
7070Sstevel@tonic-gate 			fmd_module_setdirty(mp);
7080Sstevel@tonic-gate 		}
7090Sstevel@tonic-gate 	} else
7100Sstevel@tonic-gate 		err = FMD_ADM_ERR_SERDSRCH;
7110Sstevel@tonic-gate 
7120Sstevel@tonic-gate 	fmd_module_unlock(mp);
7130Sstevel@tonic-gate 	fmd_module_rele(mp);
7140Sstevel@tonic-gate 
7150Sstevel@tonic-gate 	*rvp = err;
7160Sstevel@tonic-gate 	return (TRUE);
7170Sstevel@tonic-gate }
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate bool_t
fmd_adm_logrotate_1_svc(char * name,int * rvp,struct svc_req * req)7200Sstevel@tonic-gate fmd_adm_logrotate_1_svc(char *name, int *rvp, struct svc_req *req)
7210Sstevel@tonic-gate {
7220Sstevel@tonic-gate 	fmd_log_t **lpp, *old, *new;
7230Sstevel@tonic-gate 	int try = 1, trylimit = 1;
724*12967Sgavin.maltby@oracle.com 	pthread_rwlock_t *lockp;
7250Sstevel@tonic-gate 
7260Sstevel@tonic-gate 	hrtime_t nsec = 0;
7270Sstevel@tonic-gate 	timespec_t tv;
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate 	if (fmd_rpc_deny(req)) {
7300Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_PERM;
7310Sstevel@tonic-gate 		return (TRUE);
7320Sstevel@tonic-gate 	}
7330Sstevel@tonic-gate 
734*12967Sgavin.maltby@oracle.com 	if (strcmp(name, "errlog") == 0) {
7350Sstevel@tonic-gate 		lpp = &fmd.d_errlog;
736*12967Sgavin.maltby@oracle.com 		lockp = &fmd.d_log_lock;
737*12967Sgavin.maltby@oracle.com 	} else if (strcmp(name, "fltlog") == 0) {
7380Sstevel@tonic-gate 		lpp = &fmd.d_fltlog;
739*12967Sgavin.maltby@oracle.com 		lockp = &fmd.d_log_lock;
740*12967Sgavin.maltby@oracle.com 	} else if (strcmp(name, "infolog") == 0) {
741*12967Sgavin.maltby@oracle.com 		lpp = &fmd.d_ilog;
742*12967Sgavin.maltby@oracle.com 		lockp = &fmd.d_ilog_lock;
743*12967Sgavin.maltby@oracle.com 	} else if (strcmp(name, "infolog_hival") == 0) {
744*12967Sgavin.maltby@oracle.com 		lpp = &fmd.d_hvilog;
745*12967Sgavin.maltby@oracle.com 		lockp = &fmd.d_hvilog_lock;
746*12967Sgavin.maltby@oracle.com 	} else {
7470Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_ROTSRCH;
7480Sstevel@tonic-gate 		return (TRUE);
7490Sstevel@tonic-gate 	}
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate 	(void) fmd_conf_getprop(fmd.d_conf, "log.tryrotate", &trylimit);
7520Sstevel@tonic-gate 	(void) fmd_conf_getprop(fmd.d_conf, "log.waitrotate", &nsec);
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 	tv.tv_sec = nsec / NANOSEC;
7550Sstevel@tonic-gate 	tv.tv_nsec = nsec % NANOSEC;
7560Sstevel@tonic-gate 
7570Sstevel@tonic-gate 	/*
7580Sstevel@tonic-gate 	 * To rotate a log file, grab d_log_lock as writer to make sure no
7590Sstevel@tonic-gate 	 * one else can discover the current log pointer.  Then try to rotate
7600Sstevel@tonic-gate 	 * the log.  If we're successful, release the old log pointer.
7610Sstevel@tonic-gate 	 */
7620Sstevel@tonic-gate 	do {
7630Sstevel@tonic-gate 		if (try > 1)
7640Sstevel@tonic-gate 			(void) nanosleep(&tv, NULL); /* wait for checkpoints */
7650Sstevel@tonic-gate 
766*12967Sgavin.maltby@oracle.com 		(void) pthread_rwlock_wrlock(lockp);
7670Sstevel@tonic-gate 		old = *lpp;
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate 		if ((new = fmd_log_rotate(old)) != NULL) {
7700Sstevel@tonic-gate 			fmd_log_rele(old);
7710Sstevel@tonic-gate 			*lpp = new;
7720Sstevel@tonic-gate 		}
7730Sstevel@tonic-gate 
774*12967Sgavin.maltby@oracle.com 		(void) pthread_rwlock_unlock(lockp);
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate 	} while (new == NULL && errno == EFMD_LOG_ROTBUSY && try++ < trylimit);
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate 	if (new != NULL)
7790Sstevel@tonic-gate 		*rvp = 0;
7800Sstevel@tonic-gate 	else if (errno == EFMD_LOG_ROTBUSY)
7810Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_ROTBUSY;
7820Sstevel@tonic-gate 	else
7830Sstevel@tonic-gate 		*rvp = FMD_ADM_ERR_ROTFAIL;
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate 	return (TRUE);
7860Sstevel@tonic-gate }
7870Sstevel@tonic-gate 
7880Sstevel@tonic-gate bool_t
fmd_adm_caserepair_1_svc(char * uuid,int * rvp,struct svc_req * req)7890Sstevel@tonic-gate fmd_adm_caserepair_1_svc(char *uuid, int *rvp, struct svc_req *req)
7900Sstevel@tonic-gate {
7910Sstevel@tonic-gate 	fmd_case_t *cp = NULL;
7920Sstevel@tonic-gate 	int err = 0;
7930Sstevel@tonic-gate 
7940Sstevel@tonic-gate 	if (fmd_rpc_deny(req))
7950Sstevel@tonic-gate 		err = FMD_ADM_ERR_PERM;
7960Sstevel@tonic-gate 	else if ((cp = fmd_case_hash_lookup(fmd.d_cases, uuid)) == NULL)
7970Sstevel@tonic-gate 		err = FMD_ADM_ERR_CASESRCH;
7981552Smws 	else if (fmd_case_repair(cp) != 0) {
7991193Smws 		err = errno == EFMD_CASE_OWNER ?
8001193Smws 		    FMD_ADM_ERR_CASEXPRT : FMD_ADM_ERR_CASEOPEN;
8010Sstevel@tonic-gate 	}
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 	if (cp != NULL)
8040Sstevel@tonic-gate 		fmd_case_rele(cp);
8050Sstevel@tonic-gate 
8060Sstevel@tonic-gate 	*rvp = err;
8070Sstevel@tonic-gate 	return (TRUE);
8080Sstevel@tonic-gate }
8090Sstevel@tonic-gate 
8107275Sstephh bool_t
fmd_adm_caseacquit_1_svc(char * uuid,int * rvp,struct svc_req * req)8117275Sstephh fmd_adm_caseacquit_1_svc(char *uuid, int *rvp, struct svc_req *req)
8127275Sstephh {
8137275Sstephh 	fmd_case_t *cp = NULL;
8147275Sstephh 	int err = 0;
8157275Sstephh 
8167275Sstephh 	if (fmd_rpc_deny(req))
8177275Sstephh 		err = FMD_ADM_ERR_PERM;
8187275Sstephh 	else if ((cp = fmd_case_hash_lookup(fmd.d_cases, uuid)) == NULL)
8197275Sstephh 		err = FMD_ADM_ERR_CASESRCH;
8207275Sstephh 	else if (fmd_case_acquit(cp) != 0) {
8217275Sstephh 		err = errno == EFMD_CASE_OWNER ?
8227275Sstephh 		    FMD_ADM_ERR_CASEXPRT : FMD_ADM_ERR_CASEOPEN;
8237275Sstephh 	}
8247275Sstephh 
8257275Sstephh 	if (cp != NULL)
8267275Sstephh 		fmd_case_rele(cp);
8277275Sstephh 
8287275Sstephh 	*rvp = err;
8297275Sstephh 	return (TRUE);
8307275Sstephh }
8317275Sstephh 
8321303Swesolows void
fmd_adm_caselist_case(fmd_case_t * cp,void * arg)8331303Swesolows fmd_adm_caselist_case(fmd_case_t *cp, void *arg)
8341303Swesolows {
8351303Swesolows 	fmd_case_impl_t *cip = (fmd_case_impl_t *)cp;
8361303Swesolows 	struct fmd_rpc_caselist *rcl = arg;
8371303Swesolows 	size_t uuid_len, buf_len;
8381303Swesolows 	void *p;
8391303Swesolows 
8401303Swesolows 	if (rcl->rcl_err != 0)
8411303Swesolows 		return;
8421303Swesolows 
8431303Swesolows 	/*
8445255Sstephh 	 * skip invisible cases
8455255Sstephh 	 */
8465255Sstephh 	if (cip->ci_flags & FMD_CF_INVISIBLE)
8475255Sstephh 		return;
8485255Sstephh 
8495255Sstephh 	/*
8501303Swesolows 	 * Lock the case and reallocate rcl_buf[] to be large enough to hold
8511303Swesolows 	 * another string, doubling it as needed.  Then copy the new string
8521303Swesolows 	 * on to the end, and increment rcl_len to indicate the used space.
8531303Swesolows 	 */
8541303Swesolows 	if (!(cip->ci_flags & FMD_CF_SOLVED))
8551303Swesolows 		return;
8561303Swesolows 
8571303Swesolows 	(void) pthread_mutex_lock(&cip->ci_lock);
8581303Swesolows 
8591303Swesolows 	uuid_len = cip->ci_uuidlen + 1;
8601303Swesolows 
8611303Swesolows 	while (rcl->rcl_len + uuid_len > rcl->rcl_buf.rcl_buf_len) {
8621303Swesolows 		if (rcl->rcl_buf.rcl_buf_len != 0)
8631303Swesolows 			buf_len = rcl->rcl_buf.rcl_buf_len * 2;
8641303Swesolows 		else
8651303Swesolows 			buf_len = 1024; /* default buffer size */
8661303Swesolows 
8671303Swesolows 		if ((p = realloc(rcl->rcl_buf.rcl_buf_val, buf_len)) != NULL) {
8681303Swesolows 			bzero((char *)p + rcl->rcl_buf.rcl_buf_len,
8691303Swesolows 			    buf_len - rcl->rcl_buf.rcl_buf_len);
8701303Swesolows 			rcl->rcl_buf.rcl_buf_val = p;
8711303Swesolows 			rcl->rcl_buf.rcl_buf_len = buf_len;
8721303Swesolows 		} else {
8731303Swesolows 			rcl->rcl_err = FMD_ADM_ERR_NOMEM;
8741303Swesolows 			break;
8751303Swesolows 		}
8761303Swesolows 	}
8771303Swesolows 
8781303Swesolows 	if (rcl->rcl_err == 0) {
8791303Swesolows 		bcopy(cip->ci_uuid, (char *)rcl->rcl_buf.rcl_buf_val +
8801303Swesolows 		    rcl->rcl_len, uuid_len);
8811303Swesolows 		rcl->rcl_len += uuid_len;
8821303Swesolows 		rcl->rcl_cnt++;
8831303Swesolows 	}
8841303Swesolows 
8851303Swesolows 	(void) pthread_mutex_unlock(&cip->ci_lock);
8861303Swesolows }
8871303Swesolows 
8881303Swesolows bool_t
fmd_adm_caselist_1_svc(struct fmd_rpc_caselist * rvp,struct svc_req * req)8891303Swesolows fmd_adm_caselist_1_svc(struct fmd_rpc_caselist *rvp, struct svc_req *req)
8901303Swesolows {
8911303Swesolows 	rvp->rcl_buf.rcl_buf_len = 0;
8921303Swesolows 	rvp->rcl_buf.rcl_buf_val = NULL;
8931303Swesolows 	rvp->rcl_len = 0;
8941303Swesolows 	rvp->rcl_cnt = 0;
8951303Swesolows 	rvp->rcl_err = 0;
8961303Swesolows 
8971303Swesolows 	if (fmd_rpc_deny(req))
8981303Swesolows 		rvp->rcl_err = FMD_ADM_ERR_PERM;
8991303Swesolows 	else
9001303Swesolows 		fmd_case_hash_apply(fmd.d_cases, fmd_adm_caselist_case, rvp);
9011303Swesolows 
9021303Swesolows 	return (TRUE);
9031303Swesolows }
9041303Swesolows 
9051303Swesolows bool_t
fmd_adm_caseinfo_1_svc(char * uuid,struct fmd_rpc_caseinfo * rvp,struct svc_req * req)9061303Swesolows fmd_adm_caseinfo_1_svc(char *uuid, struct fmd_rpc_caseinfo *rvp,
9071303Swesolows     struct svc_req *req)
9081303Swesolows {
9095255Sstephh 	fmd_case_t *cp;
9101303Swesolows 	nvlist_t *nvl;
9111303Swesolows 	int err = 0;
9121303Swesolows 
9131303Swesolows 	bzero(rvp, sizeof (struct fmd_rpc_caseinfo));
9141303Swesolows 
9151303Swesolows 	if (fmd_rpc_deny(req)) {
9161303Swesolows 		rvp->rci_err = FMD_ADM_ERR_PERM;
9171303Swesolows 		return (TRUE);
9181303Swesolows 	}
9191303Swesolows 
9205255Sstephh 	if ((cp = fmd_case_hash_lookup(fmd.d_cases, uuid)) == NULL) {
9211303Swesolows 		rvp->rci_err = FMD_ADM_ERR_CASESRCH;
9221303Swesolows 		return (TRUE);
9231303Swesolows 	}
9241303Swesolows 
9255255Sstephh 	if (!(((fmd_case_impl_t *)cp)->ci_flags & FMD_CF_SOLVED)) {
9265255Sstephh 		fmd_case_rele(cp);
9271303Swesolows 		rvp->rci_err = FMD_ADM_ERR_CASESRCH;
9281303Swesolows 		return (TRUE);
9291303Swesolows 	}
9301303Swesolows 
9315255Sstephh 	nvl = fmd_case_mkevent(cp, FM_LIST_SUSPECT_CLASS);
9321303Swesolows 
9331303Swesolows 	err = nvlist_pack(nvl, &rvp->rci_evbuf.rci_evbuf_val,
9341303Swesolows 	    &rvp->rci_evbuf.rci_evbuf_len, NV_ENCODE_XDR, 0);
9351303Swesolows 
9365255Sstephh 	nvlist_free(nvl);
9375255Sstephh 
9381303Swesolows 	if (err != 0)
9391303Swesolows 		rvp->rci_err = FMD_ADM_ERR_NOMEM;
9401303Swesolows 
9415255Sstephh 	fmd_case_rele(cp);
9421303Swesolows 
9431303Swesolows 	return (TRUE);
9441303Swesolows }
9451303Swesolows 
9461193Smws /*ARGSUSED*/
9471193Smws static void
fmd_adm_xprtlist_one(fmd_idspace_t * ids,id_t id,void * arg)9481193Smws fmd_adm_xprtlist_one(fmd_idspace_t *ids, id_t id, void *arg)
9491193Smws {
9501193Smws 	struct fmd_rpc_xprtlist *rvp = arg;
9511193Smws 
9521193Smws 	if (rvp->rxl_len < rvp->rxl_buf.rxl_buf_len)
9531193Smws 		rvp->rxl_buf.rxl_buf_val[rvp->rxl_len++] = id;
9541193Smws }
9551193Smws 
9561193Smws bool_t
fmd_adm_xprtlist_1_svc(struct fmd_rpc_xprtlist * rvp,struct svc_req * req)9571193Smws fmd_adm_xprtlist_1_svc(struct fmd_rpc_xprtlist *rvp, struct svc_req *req)
9581193Smws {
9591193Smws 	if (fmd_rpc_deny(req)) {
9601193Smws 		rvp->rxl_buf.rxl_buf_len = 0;
9611193Smws 		rvp->rxl_buf.rxl_buf_val = NULL;
9621193Smws 		rvp->rxl_len = 0;
9631193Smws 		rvp->rxl_err = FMD_ADM_ERR_PERM;
9641193Smws 		return (TRUE);
9651193Smws 	}
9661193Smws 
9671193Smws 	/*
9681193Smws 	 * Since we're taking a snapshot of the transports, and these could
9691193Smws 	 * change after we return our result, there's no need to hold any kind
9701193Smws 	 * of lock between retrieving ids_count and taking the snapshot.  We'll
9711193Smws 	 * just capture up to a maximum of whatever ids_count value we sampled.
9721193Smws 	 */
9731193Smws 	rvp->rxl_buf.rxl_buf_len = fmd.d_xprt_ids->ids_count;
9741193Smws 	rvp->rxl_buf.rxl_buf_val = malloc(sizeof (int32_t) *
9751193Smws 	    rvp->rxl_buf.rxl_buf_len);
9761193Smws 	rvp->rxl_len = 0;
9771193Smws 	rvp->rxl_err = 0;
9781193Smws 
9791193Smws 	if (rvp->rxl_buf.rxl_buf_val == NULL) {
9801193Smws 		rvp->rxl_err = FMD_ADM_ERR_NOMEM;
9811193Smws 		return (TRUE);
9821193Smws 	}
9831193Smws 
9841193Smws 	fmd_idspace_apply(fmd.d_xprt_ids, fmd_adm_xprtlist_one, rvp);
9851193Smws 	return (TRUE);
9861193Smws }
9871193Smws 
9881193Smws bool_t
fmd_adm_xprtstat_1_svc(int32_t id,struct fmd_rpc_modstat * rms,struct svc_req * req)9891193Smws fmd_adm_xprtstat_1_svc(int32_t id,
9901193Smws     struct fmd_rpc_modstat *rms, struct svc_req *req)
9911193Smws {
9921193Smws 	fmd_xprt_impl_t *xip;
9931193Smws 	fmd_stat_t *sp, *ep, *cp;
9941193Smws 
9951193Smws 	if (fmd_rpc_deny(req)) {
9961193Smws 		rms->rms_buf.rms_buf_val = NULL;
9971193Smws 		rms->rms_buf.rms_buf_len = 0;
9981193Smws 		rms->rms_err = FMD_ADM_ERR_PERM;
9991193Smws 		return (TRUE);
10001193Smws 	}
10011193Smws 
10021193Smws 	rms->rms_buf.rms_buf_val = malloc(sizeof (fmd_xprt_stat_t));
10031193Smws 	rms->rms_buf.rms_buf_len = sizeof (fmd_xprt_stat_t) /
10041193Smws 	    sizeof (fmd_stat_t);
10051193Smws 	rms->rms_err = 0;
10061193Smws 
10071193Smws 	if (rms->rms_buf.rms_buf_val == NULL) {
10081193Smws 		rms->rms_err = FMD_ADM_ERR_NOMEM;
10091193Smws 		rms->rms_buf.rms_buf_len = 0;
10101193Smws 		return (TRUE);
10111193Smws 	}
10121193Smws 
10131193Smws 	if ((xip = fmd_idspace_hold(fmd.d_xprt_ids, id)) == NULL) {
10141193Smws 		rms->rms_err = FMD_ADM_ERR_XPRTSRCH;
10151193Smws 		return (TRUE);
10161193Smws 	}
10171193Smws 
10181193Smws 	/*
10191193Smws 	 * Grab the stats lock and bcopy the entire transport stats array in
10201193Smws 	 * one shot. Then go back through and duplicate any string values.
10211193Smws 	 */
10221193Smws 	(void) pthread_mutex_lock(&xip->xi_stats_lock);
10231193Smws 
10241193Smws 	sp = (fmd_stat_t *)xip->xi_stats;
10251193Smws 	ep = sp + rms->rms_buf.rms_buf_len;
10261193Smws 	cp = rms->rms_buf.rms_buf_val;
10271193Smws 
10281193Smws 	bcopy(sp, cp, sizeof (fmd_xprt_stat_t));
10291193Smws 
10301193Smws 	for (; sp < ep; sp++, cp++) {
10311193Smws 		if (sp->fmds_type == FMD_TYPE_STRING &&
10321193Smws 		    sp->fmds_value.str != NULL)
10331193Smws 			cp->fmds_value.str = strdup(sp->fmds_value.str);
10341193Smws 	}
10351193Smws 
10361193Smws 	(void) pthread_mutex_unlock(&xip->xi_stats_lock);
10371193Smws 	fmd_idspace_rele(fmd.d_xprt_ids, id);
10381193Smws 
10391193Smws 	return (TRUE);
10401193Smws }
10411193Smws 
10420Sstevel@tonic-gate int
fmd_adm_1_freeresult(SVCXPRT * xprt,xdrproc_t proc,caddr_t data)10430Sstevel@tonic-gate fmd_adm_1_freeresult(SVCXPRT *xprt, xdrproc_t proc, caddr_t data)
10440Sstevel@tonic-gate {
10450Sstevel@tonic-gate 	xdr_free(proc, data);
10460Sstevel@tonic-gate 	svc_done(xprt);
10470Sstevel@tonic-gate 	return (TRUE);
10480Sstevel@tonic-gate }
10490Sstevel@tonic-gate 
10500Sstevel@tonic-gate /*
10510Sstevel@tonic-gate  * Custom XDR routine for our API structure fmd_stat_t.  This function must
10520Sstevel@tonic-gate  * match the definition of fmd_stat_t in <fmd_api.h> and must also match
10530Sstevel@tonic-gate  * the corresponding routine in usr/src/lib/fm/libfmd_adm/common/fmd_adm.c.
10540Sstevel@tonic-gate  */
10550Sstevel@tonic-gate bool_t
xdr_fmd_stat(XDR * xp,fmd_stat_t * sp)10560Sstevel@tonic-gate xdr_fmd_stat(XDR *xp, fmd_stat_t *sp)
10570Sstevel@tonic-gate {
10580Sstevel@tonic-gate 	bool_t rv = TRUE;
10590Sstevel@tonic-gate 
10600Sstevel@tonic-gate 	rv &= xdr_opaque(xp, sp->fmds_name, sizeof (sp->fmds_name));
10610Sstevel@tonic-gate 	rv &= xdr_u_int(xp, &sp->fmds_type);
10620Sstevel@tonic-gate 	rv &= xdr_opaque(xp, sp->fmds_desc, sizeof (sp->fmds_desc));
10630Sstevel@tonic-gate 
10640Sstevel@tonic-gate 	switch (sp->fmds_type) {
10650Sstevel@tonic-gate 	case FMD_TYPE_BOOL:
10660Sstevel@tonic-gate 		rv &= xdr_int(xp, &sp->fmds_value.bool);
10670Sstevel@tonic-gate 		break;
10680Sstevel@tonic-gate 	case FMD_TYPE_INT32:
10690Sstevel@tonic-gate 		rv &= xdr_int32_t(xp, &sp->fmds_value.i32);
10700Sstevel@tonic-gate 		break;
10710Sstevel@tonic-gate 	case FMD_TYPE_UINT32:
10720Sstevel@tonic-gate 		rv &= xdr_uint32_t(xp, &sp->fmds_value.ui32);
10730Sstevel@tonic-gate 		break;
10740Sstevel@tonic-gate 	case FMD_TYPE_INT64:
10750Sstevel@tonic-gate 		rv &= xdr_int64_t(xp, &sp->fmds_value.i64);
10760Sstevel@tonic-gate 		break;
10770Sstevel@tonic-gate 	case FMD_TYPE_UINT64:
10780Sstevel@tonic-gate 	case FMD_TYPE_TIME:
10790Sstevel@tonic-gate 	case FMD_TYPE_SIZE:
10800Sstevel@tonic-gate 		rv &= xdr_uint64_t(xp, &sp->fmds_value.ui64);
10810Sstevel@tonic-gate 		break;
10820Sstevel@tonic-gate 	case FMD_TYPE_STRING:
10830Sstevel@tonic-gate 		rv &= xdr_string(xp, &sp->fmds_value.str, ~0);
10840Sstevel@tonic-gate 		break;
10850Sstevel@tonic-gate 	}
10860Sstevel@tonic-gate 
10870Sstevel@tonic-gate 	return (rv);
10880Sstevel@tonic-gate }
1089